; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ;
;                                                                                      ;
; Als basis voor dit programma heb ik gebruikt :                                       ;
; - http://www.piclist.com/techref/piclist/cheapic/therm.htm                           ;
; - http://www.eng.uwi.tt/depts/elec/staff/feisal/ee33a/resources/sony-ir-decoding.pdf ; 
;                                                                                      ;
; Voor de 1Sec timer heb ik gebruikt :                                                 ;
; - http://www.ezy.net.au/~fastvid/one_sec.asm                                         ;
;                                                                                      ;
;      -=- I like to thank everybody for making this information available -=-         ;
;                                                                                      ;
; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ;

; Start :
; -------

; Aanpassingen :
;	13/09/2003 : Datum aan digitale klok toegevoegd
;	15/09/2003 : Bug in 'ga naar lijn x' routine weggewerkt.
;       24/12/2003 : Klok enkel tonen als ze juist staat. Anders niets tonen.
;
         processor 16f84
         include p16f84.inc

	 __CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
	 ; config for 16F84; code protect OFF, watchdog OFF, powerup timer ON,
	 ; oscillator is XT ready for 4 MHz crystal or resonator.

         ERRORLEVEL -224	; supress annoying message from tris
         ERRORLEVEL -302        ; supress message from page change

         ;  Define Information
         #DEFINE RS PORTA, 1    ; RA1 is RS line of LCD
         #DEFINE E  PORTA, 0    ; RA0 is E line of LCD
                                ; RB0-RB3 are D4-D7 of LCD
	 ;  Macro
EStrobe  MACRO                  ; Strobe the "E" Bit
         bsf    E
         bcf    E
         ENDM

CBLOCK   0CH
         screensaver
         bin                    ; binary number to be converted to BCD
         hundreds               ; BCD hundreds result
         tens_and_ones          ; BCD tens and ones result
         Packet			; Bevat de overgezonden ASCII-karakters
	 Packet2		; Controle-packet om storingen te vermijden.
	 Temp			; a temporary variable
	 X			; X positie kursor
	 Y			; Y positie kursor
	 Bitcnt
	 Cntr
	 P_Val
         cntmsec		; used in counting milliseconds
         klok_sync              ; 0 = klok staat fout --> niet tonen
                                ; 1 = klok staat juist --> tonen
         sec                    ; Seconden klok
	 old_sec                ; om de klok enkel te updaten indien nodig.
         min                    ; Minuten  klok
         uur                    ; Uren     klok
	 dag
	 maand
	 jaar
	 eeuw

         ; Start variablen voor Seconden Interrupt
         bres_hi		; hi byte of our 24bit variable
	 bres_mid		; mid byte
	 bres_lo		; lo byte
				; (we only need 3 bytes for this system)

	 status_temp		; used for interrupt servicing
	 w_temp			; used for interrupt servicing
         ENDC
          
         org 0x000		; start at location 0
         goto main		; jump over to main routine
         org 0x004		; Interrupt vector, int handler code comes next.
         goto int_handler       ; jump over to interrupt routine

;----------------------------------------------------------------------;
;                    Data for message to be output                     ;
;----------------------------------------------------------------------;
shomsg:                         ;  Message to Output
         addwf     PCL, f       ;  Output the Characters
jan      dt        " - Jan Wagemakers - ", 0
naam     dt        " 16F84 IR Ontvanger ", 0
empty    dt        "                    ", 0



goto1:	
         clrf X			; X = 0
	 clrf Y			; Y = 0
	 
	 movlw H'80'            ; we gaan naar lijn 2
	 call SendINS
	 Return

goto2:	
         clrf X			; X = 0
	 clrf Y
	 incf Y,f		; Y = 1 ; we tellen vanaf 0
	 
	 movlw H'C0'            ; we gaan naar lijn 2
	 call SendINS
	 Return
	 
goto3:
	 clrf X			; X = 0
	 movlw 2
	 movwf Y		; Y = 2

	 movlw H'94'            ; we gaan naar lijn 3
	 call SendINS
	 Return

goto4:
	 clrf X			; X = 0
	 movlw 3
	 movwf Y		; Y = 3

	 movlw H'D4'            ; we gaan naar lijn 4
	 call SendINS
	 Return

;----------------------------------------------------------------------;
; Measure the duration of a high to low pulse on PortA,2.
; And leave the result in P_VAL.
; An 11 microsecond resolution is achieved with a 4MHz crystal.
;----------------------------------------------------------------------;
Pulsin:
         Clrf      Cntr         ; Clear the variables used,
         Clrf      P_Val        ; prior to the subroutine
Trans:
         Btfss     PORTA,2      ; Wait for a 1 to 0 transition
         Goto      Edge         ; Edge found!
         Incfsz    P_Val,1      ; Else, increment P-VAL until >255
         Goto      Trans
         Incfsz    Cntr,1       ; Loop until 255
         Goto      Trans
         Return
Edge:     
         Clrf      P_Val        ; A 1 to 0 transition occurred
Edge_lp:  
         Btfsc     PORTA,2      ; Count how long it's logic 0
         Return
         Nop              
         Nop                    ; Timing loop
         Nop
         Nop
         Nop
         Nop
         Incfsz    P_Val,1      ; Increment P_VAL until >255
         Goto      Edge_lp
         Return

;----------------------------------------------------------------------;
; Ontvang 8 Bits van de IR-Zender.
;----------------------------------------------------------------------;
IRIN:
         decfsz screensaver,w   ; Is het reeds tijd om de klok te tonen?
         goto IRIN_             ; Nee? Stop dan!
         call DispClock         ; Toon de klok
IRIN_:
         Call     Pulsin        ; Measure the header

	 ; Ga na of de header lengte voldoet.

         Movlw    D'40'	
         Subwf    P_Val,W
         Btfsc    STATUS,C
         Goto     Next1
         goto IRIN	
Next1:
         Movlw    D'80'      
         Subwf    P_Val,W
         Btfss    STATUS,C
         Goto     PK_Strt
         goto IRIN	

	 ; Hier worden de 8 bits binnen gehaald

PK_Strt: 
         Movlw    D'8'             
         Movwf    Bitcnt
S_again:  
         Rlf      Packet,F	; Roteer de vorige bit naar links 
         Call     Pulsin        ; Hoe lang duurde de ontvangen bit?
         Movlw    D'200'      
         Subwf    P_Val,w
         Btfsc    STATUS,C
         Goto     One
Zero:	 
	 ; Ok, de puls was korter dan 200. Dus het is waarschijnlijk een 0
	 ; en zeker geen 1. Echter om storingen te vermijden van bv. de
	 ; afstandsbediening van de TV doen we nog wat ekstra kontroles.
	 ; Indien hier niet aan voldaan wordt, gaan we terug naar IRIN.
	 
 	 Movlw    D'80'
	 Subwf    P_Val,w
	 Btfss    STATUS,C
	 Goto     IRIN		; Puls < 80 --> Ongeldig signaal
         Bcf      Packet,0      ; Clear bit (0)
         Goto     Cont
One:
         ; Ok, de puls was langer dan 200. Dus het is waarschijnlijk een 1
	 ; en zeker geen 0. Echter om storingen te vermijden van bv. de
	 ; afstandsbediening van de TV doen we nog wat ekstra kontroles.
	 ; Indien hier niet aan voldaan wordt, gaan we terug naar IRIN.
	 
	 Movlw    D'250'
	 Subwf    P_Val,w
	 Btfsc    STATUS,C
	 Goto     IRIN		; Puls > 250 --> Ongeldig signaal
         Bsf      Packet,0      ; Set bit   (1)
Cont:
         Decfsz Bitcnt,1        ; Hebben we alle bits ontvangen?
         Goto     S_again       ; Nee?, doe dan verder!
	 Return

;----------------------------------------------------------------------;
;                       Initialize the ports                           ;
;----------------------------------------------------------------------;
Init:
         clrf   PORTA
         clrf   PORTB

         movlw B'00011100'      ; RA2,3,4   input, others outputs
         tris PORTA
         movlw B'11110000'      ; RB4,5,6,7 input, others outputs
         tris PORTB

         movlw b'00001000'	;
              ;  x-------	; 7, 0=enable, 1=disable, portb pullups
	      ;  -x------	; 6, 1=/, int edge select bit
	      ;  --x-----	; 5, timer0 source, 0=internal clock, 1=ext pin.
	      ;  ---x----	; 4, timer0 ext edge, 1=\
	      ;  ----x---	; 3, prescaler assign, 1=wdt, 0=timer0
	      ;  -----x--	; 2,1,0, timer0 prescaler rate select
	      ;  ------x-	;   000=2, 001=4, 010=8, 011=16, etc.
	      ;  -------x	;
				; Note! We set the prescaler to the wdt, so timer0
				; has NO prescaler and will overflow every 256
				; instructions and make an interrupt.
				;
         option

				; INTCON setup
				;
				; for this code example, we enable the timer0
				; overflow interrupt.
				;
				; enable interrupts last
				; interrupt setup
	 movlw b'10100000'	; GIE=on TOIE=on (timer0 overflow int)
	 movwf INTCON		; set up.

	 ;-------------------------------------------------
	 ; Note! Now the hardware is set up we need to load the
	 ; first count for one second into our 24bit bres variable.
	 ;-------------------------------------------------
				; Note! This example uses 4 MHz clock, which is
				; 1,000,000 counts per second.
				;
				; We require a 1 second period, so we must load
				; 1,000,000 counts each time.
				; 1,000,000 = 0F 42 40 (in hex)
				;
				; We also need to add 256 counts for the first time,
				; so we just add 1 to the mid byte.
				; Check mid overflow if needed.

				; here we load the 24bit variable.
	 movlw 0x0F		; get msb value
	 movwf bres_hi		; put in hi

	 movlw 0x42 +1		; get mid value (note we added 1 to it)
	 movwf bres_mid		; put in mid

	 movlw 0x40		; get lsb value
	 movwf bres_lo		; put in mid
         return

;----------------------------------------------------------------------;
;                 Initialize the LCD                                   ;
;----------------------------------------------------------------------;
initlcd:
         movlw D'40'
         call   nmsec           ; Wait 40 msecs before Reset
         bcf    RS              ; send an 8 bit instruction
         movlw  0x03            ; Reset Command
         call   NybbleOut       ; Send the Nybble
         call   Dlay5           ; Wait 5 msecs before Sending Again
         EStrobe
         call Dlay160           ; Wait 160 usecs before Sending 2nd Time
         EStrobe
         call Dlay160           ; Wait 160 usecs before Sending 3rd Time
         bcf    RS              ; send an 8 bit instruction
         movlw  0x02            ; Set 4 Bit Mode
         call   NybbleOut              
         call Dlay160
         movlw  0x028           ; 4 bit, 2 Line, 5x7 font
         call   SendINS
         movlw  0x010           ; display shift off
         call   SendINS
         movlw  0x006           ; increment cursor
         call   SendINS
         movlw  0x00C           ; display on cursor off
         call   SendINS
cls:
         movlw  0x001           ; Clear the Display RAM
         call   SendINS  
         call   Dlay5           ; Note, Can take up to 4.1 msecs
         return

;----------------------------------------------------------------------;
;              Send the character in W out to the LCD                  ;
;----------------------------------------------------------------------;
SendASCII
         addlw '0'              ; Send nbr as ASCII character
SendCHAR                        ; Send the Character to the LCD
         movwf  Temp            ; Save the Temporary Value
         swapf  Temp, w         ; Send the High Nybble
         bsf    RS              ; RS = 1
         call   NybbleOut
         movf   Temp, w         ; Send the Low Nybble
         bsf    RS
         call   NybbleOut
         return

;----------------------------------------------------------------------;
;              Send an instruction in W out to the LCD                 ;
;----------------------------------------------------------------------;
SendINS                         ; Send the Instruction to the LCD
         movwf  Temp            ; Save the Temporary Value
         swapf  Temp, w         ; Send the High Nybble
         bcf    RS              ; RS = 0
         call   NybbleOut
         movf   Temp, w         ; Send the Low Nybble
         bcf    RS
         call   NybbleOut
         return

;----------------------------------------------------------------------;
;              Send the nibble in W out to the LCD                     ;
;----------------------------------------------------------------------;
NybbleOut                       ; Send a Nybble to the LCD
         movwf  PORTB                            
         EStrobe                ; Strobe out the LCD Data
         call Dlay160           ; delay for 160 usec
         return

;----------------------------------------------------------------------;
;                   Output the message on the LCD                      ;
;----------------------------------------------------------------------;
OutMessage:
         movwf  FSR             ; Point at first letter
OutLoop:
         movf   FSR, w          ; Get pointer into W
         incf   FSR, f          ; Set up for next letter
         call   shomsg          ; Get character to output
         iorlw  0               ; At the End of the Message?
         btfsc  STATUS, Z       ; Skip if not at end
         return                 ; Yes - Equal to Zero
         call   SendCHAR        ; Output the ASCII Character
         goto   OutLoop         ; Get the next character

;----------------------------------------------------------------------;
;                        time delay routines                           ;
;----------------------------------------------------------------------;

Dlay160: movlw D'40'            ; delay about 160 usec,(4/loop )
micro4:  addlw H'FF'            ; subtract 1 from 'W'
         btfss STATUS,Z         ; skip when you reach zero
         goto micro4            ; more loops
         return                     

Dlay5:   movlw 5                ;  delay for 5 milliseconds
         goto $ + 2
msec250: movlw D'250'           ;  delay for 250 milliseconds
         ;*** N millisecond delay routine ***
nmsec:   movwf cntmsec          ;  delay for N (in W) millisec
msecloop:
         movlw D'248'           ;  1 usec for load
         call micro4            ;  this instruction takes 995 usec
         nop                    ;  1 usec 
         decfsz cntmsec,f       ;  1 usec, (2 if skip taken)
         goto msecloop          ;  2 usec here makes 995+5=1 msec
         return
;----------------------------------------------------------------------;
;                  Change binary nbr in bin to BCD                     ;
;----------------------------------------------------------------------;
binary_to_bcd:                  ; by Scott Dattalo
         clrf hundreds
         swapf bin, W
         addwf bin, W
         andlw B'00001111'
         skpndc
         addlw 0x16
         skpndc
         addlw 0x06
         addlw 0x06
         skpdc
         addlw -0x06
         btfsc bin,4
         addlw 0x16 - 1 + 0x6
         skpdc
         addlw -0x06
         btfsc bin,5
         addlw 0x30
         btfsc bin, 6
         addlw 0x60
         btfsc bin,7
         addlw 0x20
         addlw 0x60
         rlf hundreds, f
         btfss hundreds, 0
         addlw -0x60
         movwf tens_and_ones
         btfsc bin,7
         incf hundreds, f
         return

;----------------------------------------------------------------------;
;                Display binary value in W in decimal                  ;
;                                                                      ;
;----------------------------------------------------------------------;
DispDec:
         movwf bin
         call binary_to_bcd
;         movf hundreds, W      ; Hondertallen zijn niet nodig in mijn projekt
;         call SendASCII
         swapf tens_and_ones, W
         andlw H'F'
         call SendASCII
         movf tens_and_ones, W
         andlw H'F'
         call SendASCII
         return

;----------------------------------------------------------------------;
;                Toon de digitale klok                                 ;
;                                                                      ;
;----------------------------------------------------------------------;
DispClock:
         decfsz klok_sync,w
         goto DispNoClock       ; klok enkel tonen als ze juist staat
         goto DispClockIfSync
DispNoClock:
         call cls               ; Scherm wissen als klok fout staat

         ; In tegenstelling tot de situatie waar we de klok tonen,
         ; hoeven we dit niet om de seconde te updaten. Dus mag
         ; screensaver terug uitgeschakeld worden.

         movlw D'255'            ; zet screensaver op MAX
         movwf screensaver

         return
DispClockIfSync:
	 ; klok wordt enkel om de seconde ge-update -----------------------
	 movf old_sec, W	; W = old_sec
	 subwf sec, W		; W = sec - old_sec
	 Btfsc STATUS, Z        
	 return			; Als old_sec = sec dan is de klok reeds OK
	 ;
	 movf sec, W            ; W = sec
	 movwf old_sec          ; old_sec = sec
	 ; ----------------------------------------------------------------
	 
	 movlw H'80'            ; Toon startbericht
         call SendINS
         movlw naam -6
         call OutMessage

         movlw H'C0'
         call SendINS
         movlw jan -6
         call OutMessage
	 
         movlw H'94'
         call SendINS
         movlw empty -6
         call OutMessage
	 
         movlw H'D4'
         call SendINS

         movf dag,w
	 call DispDec
	 
	 movlw '/'
	 call SendCHAR
	 
         movf maand,w
	 call DispDec
	 
	 movlw '/'
	 call SendCHAR
	 
	 movf eeuw,w
	 call DispDec
	 movf jaar,w
	 call DispDec
	 
 	 movlw ' '
	 call SendCHAR
	 movlw ' '
	 call SendCHAR
	 
         movf uur,w
         call DispDec

         movlw ':'
         call SendCHAR

         movf min,w
         call DispDec

         movlw ':'
         call SendCHAR

         movf sec,w
         call DispDec

         return
;----------------------------------------------------------------------;
;                           The Main routine                           ;
;----------------------------------------------------------------------;
main:
	 call Init              ; initialize ports, set up timer
	 call initlcd           ; initialize the LCD
         ; Ik gebruik een display met 20 karakters op 4 lijnen.
	 ;
	 ; Cursor op 1ste lijn vooraan = 80h
	 ;           2de  lijn vooraan = C0h
	 ;           3de  lijn vooraan = 94h
	 ;           4de  lijn vooraan = D4h
	 ;
	 ; Bv.:
	 ; movlw H'D4'          ; plaats kursor op 4de lijn vooraan
         ; call SendINS
	 ;

         clrf klok_sync         ; klok staat niet juist

restart:
         decfsz klok_sync,w
         goto reklame
geen_reklame:                   ; als de klok juist staat, toon dan GEEN reklame
         clrf screensaver
         incf screensaver,f     ; screensaver = 1
         goto lustop
reklame:
         movlw D'5'
         movwf screensaver
      	 movlw H'80'            ; Een beetje reklame maken ;-)
         call SendINS
         movlw naam -6
         call OutMessage

         movlw H'94'
         call SendINS
         movlw jan -6
         call OutMessage
lustop:
	 call goto1		; Kursor op startpositie
lus:  
         ; Na aanroepen van IRIN bevat Packet het ascii-karakter.
         call IRIN

         ; ------------------------------------------------------------------------------------------
         decfsz screensaver,w
         goto nocls
         call cls               ; Wis scherm als screensaver aktief was.
         ; Wanneer IRIN geen geldig signaal ontvangt, blijft deze in een oneindige lus hangen.
         ; Dit gebruiken we om de screensaver te starten.
nocls:
         movlw D'15'            ; Toon screensaver, na +/- xx minuten geen IR-signaal ontvangen te hebben.
         movwf screensaver
         ; In de Interruptlus wordt er elke minuut "screensaver = screensaver -1" gedaan, zodat na +/- xx
         ; minuten de screensaver zal verschijnen. Behalve als we hier geraken waar screensaver weer
         ; gezet wordt
         ; ------------------------------------------------------------------------------------------

         movf Packet,W		; W = ASCII

	 ; ASCII 0 gebruiken we als kontrole karakter
	 btfss STATUS,Z		; Als W = 0 dan ...
	 goto ASCII
				; ... gaat het om een kontrole karakter
	 call IRIN		; haal 2de deel kontrole karakter op
	 movf Packet,W
	 btfss STATUS,Z		; 0 0 --> cls
	 goto geen_cls
	 call cls               ; ... clear screen
	 goto lustop
geen_cls:
         decfsz Packet,F	; 0 1 --> zet kursor op lijn 1 
         goto x1                ; (alsof we op lijn4 zaten)
         goto lustop
x1:
	 decfsz Packet,F	; 0 2 --> zet kursor op lijn 2
         goto x2
         goto lijn1
x2:
	 decfsz Packet,F	; 0 3 --> zet kursor op lijn 3
         goto x3
         goto lijn2
x3:
	 decfsz Packet,F	; 0 4 --> zet kursor op lijn 4
         goto x4
         goto lijn3
x4:
         decfsz Packet,F        ; 0 5 --> synchronize clock
         goto x5
	 call IRIN		; haal 2de deel kontrole karakter op
	 movf Packet,W
         movwf uur
	 call IRIN		; haal 2de deel kontrole karakter op
	 movf Packet,W
         movwf min
	 call IRIN		; haal 2de deel kontrole karakter op
	 movf Packet,W
         movwf sec
         clrf klok_sync
         incf klok_sync,f       ; klok_sync = 1
         goto restart
x5:
	 decfsz Packet,F	; 0 6 --> synchronize date
	 goto x6
	 call IRIN
	 movf Packet,W
	 movwf dag
	 call IRIN
	 movf Packet,W
	 movwf maand
	 call IRIN
	 movf Packet,W
	 movwf eeuw
	 call IRIN
	 movf Packet,W
	 movwf jaar
         clrf klok_sync
         incf klok_sync,f       ; klok_sync = 1
	 goto restart
x6:	 
	 goto lus               ; Ongeldig kontrole karakter
ASCII:	
	 call SendCHAR		; Zet ASCII op display
	 incf X,1		; X = X + 1
	
	 ; als X => 20 then ....
         Movlw    D'20'	
         Subwf    X,W
         Btfss    STATUS,C
         Goto     lus
	 ; .... voer hetgene hieronder staat uit :
	 BTFSS Y,0		; Als bit 0 van Y = 1 dan skip next...
	 goto Y0is0	
	 BTFSS Y,1		; Als bit 1 van Y = 1 dan skip next...
	 goto lijn2		; Als Y = 01 ==> we stonden op lijn 2

	 goto lustop		; Scherm stond helemaal vol -> reset kursor
Y0is0:
	 BTFSC Y,1		; Als bit 1 van Y = 0 dan skip next...
	 goto lijn3
lijn1:	
         call goto2		; we stonden op lijn 1, dus ...
	 goto lus		; we gaan naar lijn 2
lijn2:
	 call goto3		; we stonden op lijn 2, dus ...
	 goto lus		; we gaan naar lijn 3
lijn3:	
	 call goto4		; we stonden op lijn 3, dus ...
	 goto lus		; we gaan naar lijn 4

;******************************************************************************
;  INTERRUPT HANDLER     (runs this code each timer0 interrupt)
;******************************************************************************
;
;------------------
int_handler:      ;
;------------------

	 ;-------------------------------------------------
	 ; first we preserve w and status register

	 movwf w_temp           ; save off current W register contents
	 movf  STATUS,w         ; move status register into W register
	 movwf status_temp      ; save off contents of STATUS register

	 ;-------------------------------------------------
	 ; Note! we get here every 256 instructions, we
	 ; can now do our special one second timing system.

	 ; This consists of three main steps;
	 ; * subtract 256 counts from our 24bit variable
	 ; * test if we reached the setpoint
	 ; * if so, add 1,000,000 counts to 24bit variable and generate event.
	 ;-------------------------------------------------
	 ; * optimised 24 bit subtract here
	 ; This is done with the minimum instructions.
	 ; We subtract 256 from the 24bit variable
	 ; by just decrementing the mid byte.

	 tstf bres_mid		; first test for mid==0
	 skpnz			; nz = no underflow needed
	 decf bres_hi,f		; z, so is underflow, so dec the msb

	 decfsz bres_mid,f	; dec the mid byte (subtract 256)

	 ; now the full 24bit optimised subtract is done!
	 ; this is about 4 times faster than a "proper"
	 ; 24bit subtract.

	 goto int_exit		; nz, so definitely not one second yet.
				; in most cases the entire 'fake" int takes
				; only 9 instructions.
	 ;------------------------
	 ; * test if we have reached one second.
	 ; only gets here when mid==0, it MAY be one second.
	 ; only gets to here 1 in every 256 times.
	 ; (this is our best optimised test)
	 ; it gets here when bres_mid ==0.

	tstf bres_hi		; test hi for zero too
	skpz			; z = both hi and mid are zero, is one second!
	goto int_exit		; nz, so not one second yet.

	 ;-------------------------------------------------
	 ; Only gets to here if we have reached one second.

	 ; now we can generate our one second event, like add
	 ; one second to our clock or whatever.
	 ; (in this example we toggle a led)

	 ; The other thing we need to do is add 1,000,000 counts
	 ; to our 24bit variable and start all over again.
	 ;-------------------------------------------------
	 ; Add the 1,000,000 counts first.
	 ; One second = 1,000,000 = 0F 42 40 (in hex)

	 ; As we know hi==0 and mid==0 this makes it very fast.
	 ; This is an optimised 24bit add, because we can
	 ; just load the top two bytes and only need to do
	 ; a real add on the bottom byte. This is much quicker
	 ; than a "proper" 24bit add.

	 movlw 0x0F		; get msb value
	 movwf bres_hi		; load in msb

	 movlw 0x42		; get mid value
	 movwf bres_mid		; load in mid

	 movlw 0x40		; lsb value to add
	 addwf bres_lo,f	; add it to the remainder already in lsb
	 skpnc			; nc = no overflow, so mid is still ok

	 incf bres_mid,f	; c, so lsb overflowed, so inc mid
				; this is optimised and relies on mid being known
				; and that mid won't overflow from one inc.

	 ; that's it! Our optimised 24bit add is done,
	 ; this is roughly twice as quick as a "proper"
	 ; 24bit add.
	 ;-------------------------

         ; Elke seconden komen we dus hier, ideaal om de klok up te daten...

         incf sec,f             ; sec = sec + 1
         Movlw D'60'
         Subwf sec,W
         Btfss STATUS,C
         goto klok              ; Als sec < 60 dan stop
         clrf sec

         decfsz screensaver,w   ; Trek van screensaver 1 af, behalve als het resultaat nul zou zijn.
         decf screensaver,f
         incf min,f             ; min = min + 1
         Movlw D'60'
         Subwf min,W
         Btfss STATUS,C
         goto klok              ; Als min < 60 dan stop
         clrf min

         incf uur,f
         Movlw D'24'
         Subwf uur,W
         Btfss STATUS,C
         goto klok              ; Als uur < 24 dan stop
         clrf uur
	 incf sec,f             ; Kompenseren van afwijking van de klok, door er 
	                        ; elke dag stiekem 1sec bij te tellen.
	 
         incf dag,f             ; dag = dag + 1
	 
	 movlw D'2'
	 subwf maand,W
	 btfss STATUS,Z		; Is het februarie?
	 goto Geen_feb
	 movf jaar,W
	 andlw D'3'             ; W = jaar and 0x00000011
	 btfss STATUS,Z
	 goto niet_schrikkel
	 ; Jaren die deelbaar zijn door 4 zijn schrikkeljaren.
	 ; behalve als :

	 ; Het een nieuwe eeuw is EN eeuw niet deelbaar door 4 is.

	 movf jaar,W		; W = jaar
	 btfsc STATUS,Z
	 goto nieuwe_eeuw
	 goto wel_schrikkel
	 
nieuwe_eeuw:	 
	 movf eeuw,W
	 andlw D'3'             ; W = eeuw and 0x00000011
	 btfss STATUS,Z
	 goto niet_schrikkel

wel_schrikkel:
         movlw D'30'		; schrikkeljaar --> feb = 29 dagen
         goto D	 
	 
niet_schrikkel:	 
         movlw D'29'		; geen schrikkeljaar --> feb = 28 dagen.
	 goto D
	 
Geen_feb:	 
	 movlw D'8'
	 subwf maand,W           
	 btfss STATUS,C         
	 goto m8		; Als maand < 8 dan ga naar m8
	 ; Ok maand is dus > 7
	 btfss maand,0
	 goto D31		; Als maand > 7 en oneven, dan heeft ze 30 dagen
	 goto D30
m8:	 
 	 btfsc maand,0
	 goto D31		; Als maand < 8 en even, dan heeft ze 30 dagen
D30:
	 movlw D'31'
	 goto D
D31:
	 movlw D'32'
D:	 
	 subwf dag,W
	 btfss STATUS,C
	 goto klok              ; Als dag < W dan stop
	 clrf dag
	 incf dag,f             ; dag = 1
	 
	 incf maand,f           ; maand = maand + 1
	 movlw D'13'
	 subwf maand,W
	 btfss STATUS,C
	 goto klok		; Als maand < 13 dan stop
	 
	 clrf maand
	 incf maand,f           ; maand = januarie
	 
	 incf jaar,f		; jaar = jaar + 1
	 movlw D'100'
	 subwf jaar,W
	 btfss STATUS,C
	 goto klok		; Als jaar < 100 dan stop
	 
	 incf eeuw,f		; eeuw = eeuw + 1

klok:
         ;
	 ; Opmerking. Ik had eerst de routine die de klok op het scherm toonde
	 ; hier opgenomen. Maar dit had tot gevolg dat de klok niet nauwkeurig
	 ; liep als ze getoond werd. Blijkbaar mag je dus in deze interrupt-routine
	 ; niets opnemen dat te veel tijd in beslag neemt.
	 ;
	 ; call DispClock wordt nu aangeroepen vanuit IRIN.
	 ;

	 ;-------------------------------------------------
	 ; now our one second event is all done, we can exit the
	 ; interrupt handler.
	 ;-------------------------------------------------
	 ; finally we restore w and status registers.
	 ; also clears TMRO int flag now we are finished.
int_exit:
	 BCF INTCON,T0IF	; reset the tmr0 interrupt flag

	 movf status_temp,w     ; retrieve copy of STATUS register
	 movwf STATUS           ; restore pre-isr STATUS register contents
	 swapf w_temp,f
	 swapf w_temp,w         ; restore pre-isr W register contents
	 retfie				; return from interrupt
;------------------------------------------------------------------------------

         end			; The End ;-)


