;*************************************************************************
;BCD clock kit from Jerry's Electronics
;Uses ATTINY261 clock runs at 1 mhz

;pin1 - pb0 - hours set
;pin2 - pb1 - minutes set
;pin3 - pb2 - sck/60 cycle input
;pin4 - pb3 - "1's"
;pin7 - pb4 - "2's"
;pin8 - pb5 - "4's"
;pin9 - pb6 - "8's" LED drive
;pin10 - pb7 - reset
;pin11 - pa7 - brightness
;pin12 - pa6 - 12/24 hour select input
;pin13 - pa5 - seconds ones digit
;pin14 - pa4 - seconds tens digit
;pin17 - pa3 - minutes ones digit
;pin18 - pa2 - minutes tens digit
;pin19 - pa1 - hours ones digit
;pin20 - pa0 - hours tens digit
;*************************************************************************

.def	detect_on		= r16
.def	hourstens		= r17
.def	hoursones		= r18
.def	minutestens		= r19
.def	minutesones		= r20
.def	secondstens		= r21
.def	secondsones 	= r22
.def	delay			= r23
.def	temp			= r24
.def	cycle_counter	= r25
.def	brightness		= r26

.cseg

;*************************************************************************
;							Setup I/O's
;*************************************************************************
reset:
	sbi		0x1a,0					;set pa0 as output
	sbi		0x1a,1					;set pa1 as output
	sbi		0x1a,2					;set pa2 as output
	sbi		0x1a,3					;set pa3 as output
	sbi		0x1a,4					;set pa4 as output
	sbi		0x1a,5					;set pa5 as output
	cbi		0x1a,6					;set pa6 as input
	cbi		0x1a,7					;set pa7 as input

	sbi		0x1b,6					;set pa6 pullup resistor

	cbi		0x17,0					;set pb0 as input
	cbi		0x17,1					;set pb1 as input
	cbi		0x17,2					;set pb2 as input
	sbi		0x17,3					;set pb3 as output
	sbi		0x17,4					;set pb4 as output
	sbi		0x17,5					;set pb5 as output
	sbi		0x17,6					;set pb6 as output
	cbi		0x17,7					;set pb7 as input
	
	sbi		0x18,0					;set pb0 pullup resistor
	sbi		0x18,1					;set pb1 pullup resistor
	sbi		0x18,7					;set pb7/reset pullup resistor

;*************************************************************************
;						Set I/O's initial state	
;*************************************************************************
	sbi		0x1b,0					;set pa0 high
	sbi		0x1b,1					;set pa1 high
	sbi		0x1b,2					;set pa2 high
	sbi		0x1b,3					;set pa3 high
	sbi		0x1b,4					;set pa4 high
	sbi		0x1b,5					;set pa5 high

	sbi		0x18,3					;set pb3 high
	sbi		0x18,4					;set pb4 high
	sbi		0x18,5					;set pb5 high
	sbi		0x18,6					;set pb6 high

;*************************************************************************
;						Set clock to 1 mhz
;*************************************************************************
	ldi		temp,128
	out		0x28,temp				;clock prescaler change enable
	ldi		temp,3
	out		0x28,temp				;set clock pre scaler to /8	

;*************************************************************************
;				Set up ADC for brightness control
;*************************************************************************
	sbi		0x06,7	 				;enable ADC
	sbi		0x07,5					;ADC left adjusted
	sbi		0x06,1					;prescaler division factor /4
	cbi		0x07,0					;use ADC6
	sbi		0x07,1					;use ADC6
	sbi		0x07,2					;use ADC6

;*************************************************************************
;						Clock start values
;*************************************************************************
	ldi		secondsones,0
	ldi		secondstens,0
	ldi		minutesones,0
	ldi		minutestens,0
	ldi		hoursones,1				;12 hour time
	sbis	0x19,6					;skip next if set to 12 hour time
	ldi		hoursones,0				;24 hour time
	ldi		hourstens,0
	ldi		detect_on,0
	ldi		cycle_counter,60

;*************************************************************************
;				Convert line frequency into 1 hz clock signal
;*************************************************************************
clock:
	cpi		detect_on,1
	breq	PC+5
	sbic	0x16,2					;60 hz signal input
	rjmp	scanleds
	ldi		detect_on,1				;clock bit cleared - load "1" into detect_on
	cbi		0x19,6					;turn test bit on
	sbis	0x16,2					;60 hz signal input
	rjmp	scanleds
	sbi		0x19,6					;turn test bit off
	ldi		detect_on,0				;clock bit set - load "0" into detect_on
	dec		cycle_counter
	brne	PC+2
	rjmp	hour12or24
	rjmp	scanleds

hour12or24:
	sbis	0x19,6					;skip next if set to 12 hour time
	rjmp	timeadjust24

;*************************************************************************
;				12 hour time count and time adjust routine
;*************************************************************************
timeadjust12:
	sbic	0x16,1					;set minutes
	rjmp	PC+3
	ldi		cycle_counter,30
	rjmp	minuteset12	
	sbic	0x16,0					;set hours
	rjmp	count12
	ldi		cycle_counter,30
	rjmp	hourset12
	
count12:
	ldi		cycle_counter,60
	inc		secondsones				;add 1 second
	cpi		secondsones,10			;compare to 10
	brlo	scanleds				;if not equal to 10 branch to scanleds
	ldi		secondsones,0			;if seconds equal to 10 - reset to 0
	inc		secondstens				;add 1 to tens seconds 
	cpi		secondstens,6			;compare to 6
	brlo	scanleds				;if not equal to 6 branch to scanleds
	ldi		secondstens,0			;if tens seconds equal to six - reset to 0

minuteset12:
	inc		minutesones				;add 1 to ones minutes
	cpi		minutesones,10			;compare to 10
	brlo	scanleds				;if lower than 10 branch to scanleds
	ldi		minutesones,0			;if ones minutes equal to 10 - reset to 0
	inc		minutestens				;add 1 to tens minutes 
	cpi		minutestens,6			;compare to 6
	brlo	scanleds				;if lower than 6 branch to scanleds
	ldi		minutestens,0			;load "0" to minutestens

hourset12:
	cpi		hourstens,1				;compare to 1
	breq	PC+7
	inc		hoursones				;add 1 to ones hours
	cpi		hoursones,10			;compare to 10
	brlo	scanleds				;if lower than 10 branch to scanleds
	ldi		hoursones,0				;if ones hour equal to 10 - reset to 0
	inc		hourstens				;add 1 to tens hours 
	rjmp	scanleds
	inc		hoursones				;add 1 to ones hours
	cpi		hoursones,3				;compare to 3
	brlo	scanleds				;if not equal to 3 branch to scanleds	
	ldi		hourstens,0
	ldi		hoursones,1				;12 hour time
	
scanleds:
	rjmp	ledscan

;*************************************************************************
;				24 hour time count and time adjust routine
;*************************************************************************
timeadjust24:
	sbic	0x16,1					;set minutes
	rjmp	PC+3
	ldi		cycle_counter,30
	rjmp	minuteset24	
	sbic	0x16,0					;set hours
	rjmp	count24
	ldi		cycle_counter,30
	rjmp	hourset24

count24:
	ldi		cycle_counter,60
	inc		secondsones				;add 1 second
	cpi		secondsones,10			;compare to 10
	brlo	scanleds				;if not equal to 10 branch to scanleds
	ldi		secondsones,0			;if seconds equal to 10 - reset to 0
	inc		secondstens				;add 1 to tens seconds 
	cpi		secondstens,6			;compare to 6
	brlo	scanleds				;if not equal to 6 branch to scanleds
	ldi		secondstens,0			;if tens seconds equal to six - reset to 0

minuteset24:
	inc		minutesones				;add 1 to ones minutes
	cpi		minutesones,10			;compare to 10
	brlo	scanleds				;if lower than 10 branch to scanleds
	ldi		minutesones,0			;if ones minutes equal to 10 - reset to 0
	inc		minutestens				;add 1 to tens minutes 
	cpi		minutestens,6			;compare to 6
	brlo	scanleds				;if lower than 6 branch to scanleds
	ldi		minutestens,0			;load "0" to minutestens

hourset24:
	cpi		hourstens,2				;compare to 2
	breq	PC+7
	inc		hoursones				;add 1 to ones hours
	cpi		hoursones,10			;compare to 10
	brlo	scanleds				;if lower than 10 branch to scanleds
	ldi		hoursones,0				;if ones hour equal to 10 - reset to 0
	inc		hourstens				;add 1 to tens hours 
	rjmp	scanleds
	inc		hoursones				;add 1 to ones hours
	cpi		hoursones,4				;compare to 4
	brlo	scanleds				;if lower than 4 branch to scanleds	
	ldi		hourstens,0
	ldi		hoursones,0				;24 hour time
	
;*************************************************************************
;		Scan LED routines, but first read ADC for brightness control
;*************************************************************************
ledscan:
	sbi  	0x06,6                	;start conversion
	sbis 	0x06,4        			;wait here till conv complete
	rjmp 	PC-1
	in   	temp,0x04				;ADCL
	in   	brightness,0x05			;ADCH
	sbi		0x06,4					;force ADIF off
	lsr		brightness
	
	cpi		brightness,0			;test if brightness is "0"
	brne	PC+2
	ldi		brightness,1			;make brightness "1"

;*************************************************************************
;							Scan seconds
;*************************************************************************
	sbrc	secondsones,0
	rjmp	PC+3
	sbi		0x18,3					;turn bit 1 off
	rjmp	PC+2
	cbi		0x18,3					;turn bit 1 on

	sbrc	secondsones,1
	rjmp	PC+3
	sbi		0x18,4					;turn bit 2 off
	rjmp	PC+2
	cbi		0x18,4					;turn bit 2 on
	
	sbrc	secondsones,2
	rjmp	PC+3
	sbi		0x18,5					;turn bit 4 off
	rjmp	PC+2
	cbi		0x18,5					;turn bit 4 on
		
	sbrc	secondsones,3
	rjmp	PC+3
	sbi		0x18,6					;turn bit 8 off
	rjmp	PC+2
	cbi		0x18,6					;turn bit 8 on

	cbi		0x1b,5					;turn on seconds ones column
	mov		delay,brightness
	dec		delay
	brne	PC-1
	sbi		0x1b,5					;turn off seconds ones column

	sbrc	secondstens,0
	rjmp	PC+3
	sbi		0x18,3					;turn bit 1 off
	rjmp	PC+2
	cbi		0x18,3					;turn bit 1 on

	sbrc	secondstens,1
	rjmp	PC+3
	sbi		0x18,4					;turn bit 2 off
	rjmp	PC+2
	cbi		0x18,4					;turn bit 2 on
	
	sbrc	secondstens,2
	rjmp	PC+3
	sbi		0x18,5					;turn bit 4 off
	rjmp	PC+2
	cbi		0x18,5					;turn bit 4 on

	cbi		0x1b,4					;turn on seconds tens column
	mov		delay,brightness
	dec		delay
	brne	PC-1
	sbi		0x1b,4					;turn off seconds tens column

;*************************************************************************
;							Scan minutes
;*************************************************************************
	sbrc	minutesones,0
	rjmp	PC+3
	sbi		0x18,3					;turn bit 1 off
	rjmp	PC+2
	cbi		0x18,3					;turn bit 1 on

	sbrc	minutesones,1
	rjmp	PC+3
	sbi		0x18,4					;turn bit 2 off
	rjmp	PC+2
	cbi		0x18,4					;turn bit 2 on
	
	sbrc	minutesones,2
	rjmp	PC+3
	sbi		0x18,5					;turn bit 4 off
	rjmp	PC+2
	cbi		0x18,5					;turn bit 4 on
		
	sbrc	minutesones,3
	rjmp	PC+3
	sbi		0x18,6					;turn bit 8 off
	rjmp	PC+2
	cbi		0x18,6					;turn bit 8 on

	cbi		0x1b,3					;turn on minutes ones column
	mov		delay,brightness
	dec		delay
	brne	PC-1
	sbi		0x1b,3					;turn off minutes ones column

	sbrc	minutestens,0
	rjmp	PC+3
	sbi		0x18,3					;turn bit 1 off
	rjmp	PC+2
	cbi		0x18,3					;turn bit 1 on

	sbrc	minutestens,1
	rjmp	PC+3
	sbi		0x18,4					;turn bit 2 off
	rjmp	PC+2
	cbi		0x18,4					;turn bit 2 on
	
	sbrc	minutestens,2
	rjmp	PC+3
	sbi		0x18,5					;turn bit 4 off
	rjmp	PC+2
	cbi		0x18,5					;turn bit 4 on

	cbi		0x1b,2					;turn on seconds tens column
	mov		delay,brightness
	dec		delay
	brne	PC-1
	sbi		0x1b,2					;turn off seconds tens column

;*************************************************************************
;							Scan hours
;*************************************************************************
	sbrc	hoursones,0
	rjmp	PC+3
	sbi		0x18,3					;turn bit 1 off
	rjmp	PC+2
	cbi		0x18,3					;turn bit 1 on

	sbrc	hoursones,1
	rjmp	PC+3
	sbi		0x18,4					;turn bit 2 off
	rjmp	PC+2
	cbi		0x18,4					;turn bit 2 on
	
	sbrc	hoursones,2
	rjmp	PC+3
	sbi		0x18,5					;turn bit 4 off
	rjmp	PC+2
	cbi		0x18,5					;turn bit 4 on
		
	sbrc	hoursones,3
	rjmp	PC+3
	sbi		0x18,6					;turn bit 8 off
	rjmp	PC+2
	cbi		0x18,6					;turn bit 8 on

	cbi		0x1b,1					;turn on hour ones column
	mov		delay,brightness
	dec		delay
	brne	PC-1
	sbi		0x1b,1					;turn off hour ones column

	sbrc	hourstens,0
	rjmp	PC+3
	sbi		0x18,3					;turn bit 1 off
	rjmp	PC+2
	cbi		0x18,3					;turn bit 1 on

	sbrc	hourstens,1
	rjmp	PC+3
	sbi		0x18,4					;turn bit 2 off
	rjmp	PC+2
	cbi		0x18,4					;turn bit 2 on
	
	cbi		0x1b,0					;turn on hour tens column
	mov		delay,brightness
	dec		delay
	brne	PC-1
	sbi		0x1b,0					;turn off hour tens column

	rjmp	clock
