;****************************************************************
;*  Name    : klokschool.asm                                    *
;*  Author  : Bert De Deckere                                   *
;*  Notice  : Copyright Bert (c) 2009                           *
;*          : All Rights Reserved                               *
;*  Date    : 29/10/2009                                        *
;*  Version : 1.0                                               *
;*  Notes   : Please make sure you use the appropriate µC       *
;*          :                                                   *
;****************************************************************

	#include P18F1320.inc

;           PIC18F1320:                 +------v------+ 
;                            signal in <[RA.0     RB.3]> segment d
;                            display 1 <[RA.1     RB.2]> segment e
;                            display 4 <[RA.4     RA.7]> kristal
;                    	          MCLR <[RA.5     RA.6]> kristal
;                            	   GND <[             ]> V+
;                            display 2 <[RA.2     RB.7]> dubbele punt
;                            display 3 <[RA.3     RB.6]> segment a
;                            segment b <[RB.0     RB.5]> segment f
;                            segment c <[RB.1     RB.4]> segment g
;                                       +-------------+

	CONFIG PWRT 	= 	ON				; Enable power up timer
	CONFIG FSCM 	= 	ON            	; Fail-Safe Clock Monitor enabled
	CONFIG WDT		= 	OFF				; disable watchdog timer
	CONFIG MCLRE	= 	OFF				; Master CLear Reset pin disabled, RA5 input pin enabled
	CONFIG DEBUG 	= 	OFF				; Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins
	CONFIG LVP 		= 	OFF				; Low-Voltage programming disabled (necessary for debugging)
	CONFIG OSC 		= 	INTIO2			; High speed oscillator	
   	CONFIG IESO 	= 	ON				; Oscillator Switchover mode disabled
	CONFIG BOR		= 	ON				; Brown-out reset enabled

	#define	signaal		PORTA, 0		; signaalingang

;het DCF-77 signaal wordt gezien als corrigeersignaal niet als kloksignaal
;vandaar dubbele variabelen voor tijd en datum

;variabele lengte wordt gecodeerd op volgende manier
;bit7 : signaal is weggevallen
;bit6 : deze onthoud dat "decodeer" net nog verhoogd is
;bit5 : onthoudt dat hij net naar "nul" geweest is
;bit4 : pariteitsbit voor datum


laag		equ	00h			; variabele die telt hoe lang het signaal laag is van het DCF-77 signaal
hoog		equ	01h			; variabele die telt hoe lang het signaal hoog is van het DCF-77 signaal
lengte		equ	02h			; variabele die de overgang bijhoudt van het signaal, waarna de signaallengte opgenomen wordt
decodeer	equ	03h			; variabele die onthoudt welke bit waar moet komen van het DCF-77 signaal
uur			equ	04h			; variabelen voor tijd en datum
min			equ	05h
sec			equ	06h
dag			equ	07h
maand		equ	08h
uur2		equ	09h			; rechter nibble van "uur"
min2		equ	0Ah			; rechter nibble van "min"
sec2		equ	0Bh
dag2		equ	0Ch			; rechter nibble van "dag"
maand2		equ	0Dh			; rechter nibble van "maand"
wvar		equ	0Eh			; hier wordt het werkregister in bewaard gedurende de timer interrupt
tempcmd		equ	10h			; deze zorgt ervoor dat er naar de juiste variabele geschreven wordt
pariteit	equ	11h			; hier worden de bits samengeteld voor de pariteitscontrole
weekdag		equ	12h
jaar		equ	13h
teller		equ	14h			; deze verzorgt de tijdbasis voor de seconde
tijddat		equ	15h			; onthoud de overgang tussen tijd naar datum
display		equ	16h			; omwille van de BCD-code wordt eerst de linker nibble op display gezet, daarna rechter nibble
teller2		equ	17h			; deze onthoud welk display aangestuurd moet worden
maand3		equ	18h			; linker nibble van "maand"
status_temp	equ	19h			; variabele om registers te herstellen
dag3		equ	1Ah			; linker nibble van "dag"
min3		equ	1Bh			; linker nibble van "min"
uur3		equ	1Ch			; linker nibble van "uur"
sec3		equ	1Dh			; linker nibble van "sec"
delay1		equ	1Eh			; teller om een delay te maken
tempreg		equ	1Fh
delay2		equ	20h
tijddat2	equ	21h
tell2		equ	22h			; variabele voor de schakelaar die bepaald of tijd of tijd/dat moet weergegeven worden
bsr_temp	equ	23h



       			ORG	00h    				; reset vector
				clrf	decodeer
				bsf		lengte, 7		; signaal is weggevallen, dus eerst wachten op nieuwe minuut
				goto	vector1

				ORG	18h					; low priority vector (timer interrupt)
				goto	vector2

delay			movlw	0FFh
				movwf	delay1
				movlw	03h
				movwf	delay2
verminder		decfsz	delay1
				goto	verminder
				decfsz	delay2
				goto	verminder
				return

decoder			incf	decodeer		; "decodeer" enkel verhogen indien het signaal net nog laag geweest is
				clrf	hoog
				return

overzetten		clrf	pariteit
				btfsc	min, 0			; pariteitscontrole
				incf	pariteit		; bits samentellen en daarna kijken of het resultaat even is
				btfsc	min, 1
				incf	pariteit
				btfsc	min, 2
				incf	pariteit
				btfsc	min, 3
				incf	pariteit
				btfsc	min, 4
				incf	pariteit
				btfsc	min, 5
				incf	pariteit
				btfsc	min, 6
				incf	pariteit
				btfsc	min, 7
				incf	pariteit

				btfsc	pariteit, 0		; als laatste bit = 0 dan is het resultaat even, dus antwoord klopt
				goto	uren

				clrf	min3
				btfsc	min, 0
				bsf		min3, 0
				btfsc	min, 1
				bsf		min3, 1
				btfsc	min, 2
				bsf		min3, 2
				btfsc	min, 3
				bsf		min3, 3

				clrf	min2
				btfsc	min, 4
				bsf		min2, 0
				btfsc	min, 5
				bsf		min2, 1
				btfsc	min, 6
				bsf		min2, 2

uren			clrf	pariteit
				btfsc	uur, 0			; pariteitscontrole
				incf	pariteit		; bits samentellen en daarna kijken of het resultaat even is
				btfsc	uur, 1
				incf	pariteit
				btfsc	uur, 2
				incf	pariteit
				btfsc	uur, 3
				incf	pariteit
				btfsc	uur, 4
				incf	pariteit
				btfsc	uur, 5
				incf	pariteit
				btfsc	uur, 6
				incf	pariteit

				btfsc	pariteit, 0		; als laatste bit = 0 dan is het resultaat even, dus antwoord klopt
				goto	datum

				clrf	uur3
				btfsc	uur, 0
				bsf		uur3, 0
				btfsc	uur, 1
				bsf		uur3, 1
				btfsc	uur, 2
				bsf		uur3, 2
				btfsc	uur, 3
				bsf		uur3, 3

				clrf	uur2
				btfsc	uur, 4
				bsf		uur2, 0
				btfsc	uur, 5
				bsf		uur2, 1

datum			clrf	pariteit
				btfsc	dag, 0			; pariteitscontrole
				incf	pariteit		; bits samentellen en daarna kijken of het resultaat even is
				btfsc	dag, 1
				incf	pariteit
				btfsc	dag, 2
				incf	pariteit
				btfsc	dag, 3
				incf	pariteit
				btfsc	dag, 4
				incf	pariteit
				btfsc	dag, 5
				incf	pariteit
				btfsc	weekdag, 0
				incf	pariteit
				btfsc	weekdag, 1
				incf	pariteit
				btfsc	weekdag, 2
				incf	pariteit
				btfsc	maand, 0
				incf	pariteit
				btfsc	maand, 1
				incf	pariteit
				btfsc	maand, 2
				incf	pariteit
				btfsc	maand, 3
				incf	pariteit
				btfsc	maand, 4
				incf	pariteit
				btfsc	jaar, 0
				incf	pariteit
				btfsc	jaar, 1
				incf	pariteit
				btfsc	jaar, 2
				incf	pariteit
				btfsc	jaar, 3
				incf	pariteit
				btfsc	jaar, 4
				incf	pariteit
				btfsc	jaar, 5
				incf	pariteit
				btfsc	jaar, 6
				incf	pariteit
				btfsc	jaar, 7
				incf	pariteit
				btfsc	lengte, 4
				incf	pariteit

				btfsc	pariteit, 0
				goto	terug

				clrf	dag3
				btfsc	dag, 0
				bsf		dag3, 0
				btfsc	dag, 1
				bsf		dag3, 1
				btfsc	dag, 2
				bsf		dag3, 2
				btfsc	dag, 3
				bsf		dag3, 3

				clrf	dag2
				btfsc	dag, 4
				bsf		dag2, 0
				btfsc	dag, 5
				bsf		dag2, 1

				clrf	maand3
				btfsc	maand, 0
				bsf		maand3, 0
				btfsc	maand, 1
				bsf		maand3, 1
				btfsc	maand, 2
				bsf		maand3, 2
				btfsc	maand, 3
				bsf		maand3, 3

				clrf	maand2
				btfsc	maand, 4
				bsf		maand2, 0
terug			return

een				movf	decodeer, w	    	; een systeempje om afhankelijk van de waarde van variabele
				movwf	tempreg	         
                movlw	HIGH  cmd_tab    
				movwf	PCLATH		 		
				movlw	LOW  cmd_tab
                movwf   tempcmd
                movf    tempreg,w
                addwf   tempcmd,f			
				btfsc	STATUS, 0			
				incf	PCLATH,f				
				btfsc	STATUS, 0			
				incf	PCLATU,f				
                addwf   tempcmd,f			
				btfsc	STATUS, 0			
				incf	PCLATH,f				
				btfsc	STATUS, 0			
				incf	PCLATU,f				
				movf    tempcmd,w

				movwf	PCL
cmd_tab			nop
				nop							; aankondigingsbits zijn niet belangrijk
				nop							; deze zijn enkel bedoelt voor analoge klokken
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				bsf		min, 0			; LSB wordt eerst uitgezonden
				bsf		min, 1			; minuten decoderen (7 bits)
				bsf		min, 2
				bsf		min, 3
				bsf		min, 4
				bsf		min, 5
				bsf		min, 6
				bsf		min, 7			; even pariteitsbit
				bsf		uur, 0			; uren decoderen (6 bits)
				bsf		uur, 1
				bsf		uur, 2
				bsf		uur, 3
				bsf		uur, 4
				bsf		uur, 5
				bsf		uur, 6			; even pariteit
				bsf		dag, 0			; dag v/d maand decoderen (6 bits)
				bsf		dag, 1
				bsf		dag, 2
				bsf		dag, 3
				bsf		dag, 4
				bsf		dag, 5
				bsf		weekdag, 0		; hier wordt de dag v/d week uitgezonden = irrelevant
				bsf		weekdag, 1		; maar wordt toch gedecodeerd omwille van de pariteit
				bsf		weekdag, 2		
				bsf		maand, 0		; maand decoderen (5 bits)
				bsf		maand, 1
				bsf		maand, 2
				bsf		maand, 3
				bsf		maand, 4
				bsf		jaar, 0			; jaren zijn ook irrelevant
				bsf		jaar, 1
				bsf		jaar, 2
				bsf		jaar, 3			; deze hele codering lijkt misschien raar
				bsf		jaar, 4			; maar het geheim zit er hem in dat al de gedecodeerde info
				bsf		jaar, 5			; pas op het einde van de minuut gebruikt wordt				
				bsf		jaar, 6
				bsf		jaar, 7
				bsf		lengte, 4		; pariteitsbit
				return

nul				bsf		lengte, 5

				movf	decodeer, w	    	; een systeempje om afhankelijk van de waarde van variabele
				movwf	tempreg	         
                movlw	HIGH  cmd_tab2    
				movwf	PCLATH		 		
				movlw	LOW  cmd_tab2
                movwf   tempcmd
                movf    tempreg,w
                addwf   tempcmd,f			
				btfsc	STATUS, 0			
				incf	PCLATH,f				
				btfsc	STATUS, 0			
				incf	PCLATU,f				
                addwf   tempcmd,f			
				btfsc	STATUS, 0			
				incf	PCLATH,f				
				btfsc	STATUS, 0			
				incf	PCLATU,f				
				movf    tempcmd,w

				movwf	PCL
cmd_tab2		nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				bcf		min, 0			; LSB wordt eerst uitgezonden
				bcf		min, 1			; minuten decoderen (7 bits)
				bcf		min, 2
				bcf		min, 3
				bcf		min, 4
				bcf		min, 5
				bcf		min, 6
				bcf		min, 7			; even pariteitsbit
				bcf		uur, 0			; uren decoderen (6 bits)
				bcf		uur, 1
				bcf		uur, 2
				bcf		uur, 3
				bcf		uur, 4
				bcf		uur, 5
				bcf		uur, 6			; even pariteit
				bcf		dag, 0			; dag v/d maand decoderen (6 bits)
				bcf		dag, 1
				bcf		dag, 2
				bcf		dag, 3
				bcf		dag, 4
				bcf		dag, 5
				bcf		weekdag, 0		; hier wordt de dag v/d week uitgezonden = irrelevant
				bcf		weekdag, 1		; maar wordt toch gedecodeerd omwille van de pariteit
				bcf		weekdag, 2		
				bcf		maand, 0		; maand decoderen (5 bits)
				bcf		maand, 1
				bcf		maand, 2
				bcf		maand, 3
				bcf		maand, 4
				bcf		jaar, 0			; jaren zijn ook irrelevant
				bcf		jaar, 1
				bcf		jaar, 2
				bcf		jaar, 3			; deze hele codering lijkt misschien raar
				bcf		jaar, 4			; maar het geheim zit er hem in dat al de gedecodeerde info
				bcf		jaar, 5			; pas op het einde van de minuut gebruikt wordt				
				bcf		jaar, 6
				bcf		jaar, 7
				bcf		lengte, 4		; pariteitsbit
				return		

afhandeling		movlw	02h
				cpfsgt	hoog
				goto	aa

				movlw	0E0h			; is het signaal langer laag dan 4 sec = signaal weggevallen
				cpfsgt	laag			; dus alle gedecodeerde info wissen
				goto	ab
aa				clrf	uur
				clrf	sec
				clrf	min
				clrf	dag
				clrf	maand
				clrf	laag
				clrf	decodeer		; terug vanaf 0 beginnen decoderen
				bsf		lengte, 7
				return

ab				movlw	58h				; is het signaal langer laag dan 1,5 sec dan nieuwe minuut beginnen
				cpfsgt	laag
				goto	ac
				clrf	decodeer
				bcf		lengte, 7

ac				btfsc	lengte, 7		; als het signaal weggevallen is stoppen met decoderen tot het terug is
				clrf	decodeer
				movlw	09h				; hier pollen op ,15s
				cpfsgt	hoog			; was het DCF-77 signaal langer hoog dan ,15s dan is er een 1 verstuurd
				call	nul
				btfss	lengte, 5
				call	een
				bcf		lengte, 5
				return

vector2			movwf	wvar			; werkregister in variabele "wvar" zetten, om op het einde terug te zetten
				movff	STATUS, status_temp
				movff	BSR, bsr_temp

				incf	tijddat2
				btfsc	tijddat2, 2
				incf	tijddat			; tijd of datum weergeven?
				movlw	0FFh
				cpfslt	tijddat
				clrf	tijddat
				movlw	0FFh
				cpfslt	tijddat2
				clrf	tijddat2

				incf	teller
				movlw	3Dh				; als "teller" = 61 (3D HEX) dan seconden verhogen
				cpfsgt	teller			; alsook minuten en uren verder aanpassen
				goto	volgende
				clrf	teller
				incf	sec3

				movlw	09h				; als sec3 > 9 dan sec3 clearen en sec2 verhogen
				cpfsgt	sec3
				goto	volgende
				incf	sec2
				clrf	sec3

				movlw	05h
				cpfsgt	sec2
				goto	volgende
				incf	min3
				clrf	sec2

				movlw	09h
				cpfsgt	min3
				goto	volgende
				incf	min2
				clrf	min3		

				movlw	05h
				cpfsgt	min2
				goto	volgende
				incf	uur3
				clrf	min2

				movlw	09h
				cpfsgt	uur3
				goto	volgende
				incf	uur2
				clrf	uur3

				movlw	01h
				cpfsgt	uur2
				goto	volgende
				movlw	03h
				cpfsgt	uur3
				goto	volgende			
				clrf	uur2
				clrf	uur3
				clrf	min2
				clrf	min3
				clrf	teller	

volgende		movlw	3Ah				; als het decoderen op z'n einde loopt de variabelen op z'n plaats zetten
				cpfslt	decodeer
				call	overzetten

				btfss	signaal			; timer interrupt routine
				goto	lag				; als DCF77-signaal laag is naar lag gaan
				goto	hog				; en vice versa

lag				movlw	3Ah				; op de 59e bit seconden resetten
				cpfslt	decodeer
				clrf	sec2
				cpfslt	decodeer
				clrf	sec3
				cpfslt	decodeer		; terug in de pas laten lopen
				clrf	teller

				movlw	3Ch
				cpfslt	decodeer
				clrf	decodeer

				bcf		lengte, 6
				incf	laag
				call	afhandeling
				goto	einde

hog				btfss	lengte, 6		; bij stijgende flank van het signaal
				call	decoder			; variabele "decodeer" verhogen en "hoog" wissen
				bsf		lengte, 6
				clrf	laag
				incf	hoog
				movlw	50h
				cpfsgt	hoog
				goto	einde
				clrf	decodeer
				clrf	hoog

einde			movf	wvar, 0			; werkregister terug zetten
				movff	bsr_temp, BSR
				movff	status_temp, STATUS
				bcf		INTCON, 2		; flag bit terug op 0 zetten
				retfie					

vector1			movlb	b'1111'

				movlw	b'01110000'		; intosc op 8MHz
				movwf	OSCCON

				movlw	b'00010111'
				movwf	OSCTUNE

				movlw	b'11111111'
				movwf	ADCON1

				movlw 	b'00100001'		; poortconfiguratie (enkel bij opstarten)
				movwf	TRISA
		
				movlw	b'00000000'
				movwf	TRISB
		
				movlw	b'11100000'
				movwf	INTCON

				movlw	b'10000100'		; interrupt on change is low priority
				movwf	INTCON2			; timer interrupt is high priority

				movlw	b'11000110'		; prescaler op 128
				movwf	T0CON			; om de 0.016384s een overflow
		
				bsf		RCON, 7			; priority enable

				movlb	b'0000'

				movlw	01h
				movwf	dag3			; data wissen en datum op 01/01 zetten
				movwf	maand3

				clrf	dag2
				clrf	maand2
				clrf	sec3
				clrf	sec2
				clrf	sec
				clrf	uur3
				clrf	uur2
				clrf	uur
				clrf	min3
				clrf	min2
				clrf	min
				clrf	maand
				clrf	dag
				clrf	jaar
				clrf	decodeer
				clrf	laag
				clrf	hoog
				bsf		tell2, 6		; standaard tijd tonen geen tijd/datum

main			btfsc	PORTA, 5		; tijd/datum of tijd?
				goto	schak2
				btfsc	tell2, 7
				goto	schak1
				bsf		tell2, 7
				goto	schak3

schak3			btg		tell2, 6
				movlw	00B0h
				btfss	tell2, 6
				movwf	tijddat
				goto	schak1
 
schak2			bcf		tell2, 7

schak1   		btfsc	tell2, 6
				clrf	tijddat
				btfsc	tell2, 6
				goto	tijd

				movlw	00B0h			; 16 keer datum tonen (255-16) 239 keer tijd tonen
				cpfslt	tijddat
				goto	dat
				goto	tijd

tijd			incf	teller2
				movlw	04h
				cpfslt	teller2
				clrf	teller2

				movlw	00h
				cpfseq	teller2
				goto	ea
				movff	min3, display
ea				movlw	01h
				cpfseq	teller2
				goto	eb
				movff	min2, display
eb				movlw	02h
				cpfseq	teller2
				goto	ec
				movff	uur3, display
ec				movlw	03h
				cpfseq	teller2
				goto	nulde
				movff	uur2, display
				goto	nulde

dat				incf	teller2
				movlw	04h
				cpfslt	teller2
				clrf	teller2

				movlw	00h
				cpfseq	teller2
				goto	ca
				movff	maand3, display
ca				movlw	01h
				cpfseq	teller2
				goto	cb
				movff	maand2, display
cb				movlw	02h
				cpfseq	teller2
				goto	cc
				movff	dag3, display
cc				movlw	03h
				cpfseq	teller2
				goto	nulde
				movff	dag2, display

nulde			movlw	00h
				cpfseq	display
				goto	eerste
				movlw	b'01101111'				; is min2 gelijk aan 0 dan 0 tonen enz..
				movwf	LATB
				goto	aansturing

eerste			movlw	01h
				cpfseq	display
				goto	tweede
				movlw	b'00000011'
				movwf	LATB
				goto	aansturing

tweede			movlw	02h
				cpfseq	display
				goto	derde
				movlw	b'01011101'
				movwf	LATB
				goto	aansturing

derde			movlw	03h
				cpfseq	display
				goto	vierde
				movlw	b'01011011'
				movwf	LATB
				goto	aansturing

vierde			movlw	04h
				cpfseq	display
				goto	vijfde
				movlw	b'00110011'
				movwf	LATB
				goto	aansturing

vijfde			movlw	05h
				cpfseq	display
				goto	zesde
				movlw	b'01111010'
				movwf	LATB
				goto	aansturing

zesde			movlw	06h
				cpfseq	display
				goto	zevende
				movlw	b'01111110'
				movwf	LATB
				goto	aansturing

zevende			movlw	07h
				cpfseq	display
				goto	achtste
				movlw	b'01000011'
				movwf	LATB
				goto	aansturing

achtste			movlw	08h
				cpfseq	display
				goto	negende
				movlw	b'01111111'
				movwf	LATB
				goto	aansturing

negende			movlw	b'01111011'
				movwf	LATB


aansturing		movlw	00B0h				; als datum weergegeven wordt niet knipperen
				cpfslt	tijddat
				goto	knipper

				movlw	1Eh					; deze blok verzorgt de dubbele punt
				cpfslt	teller
				goto	knipper
				bsf		LATB, 7
				goto	display1
knipper			bcf		LATB, 7

display1		movlw	00h					; afhankelijk van de data een ander display
				cpfseq	teller2				; onder spanning zetten
				goto	display2
				bcf		LATB, 7
				bcf		LATA, 1
				bsf		LATA, 3
				call	delay
				goto	main
display2		movlw	01h
				cpfseq	teller2
				goto	display3
				bcf		LATA, 3
				bsf		LATA, 4
				call	delay
				goto	main
display3		movlw	02h
				cpfseq	teller2
				goto	display4
				bcf		LATA, 4
				bsf		LATA, 2
				call	delay
				goto	main
display4		bcf		LATA, 2
				bsf		LATA, 1
				bcf		LATB, 7
				call	delay
				goto	main

				end