.include "tn85def.inc" ; One LED clock V1.0 ; Mike Ingle ; Atmel ATTINY25/45/85 ; PORTB0 - LED out Red, 470 ohm resistor in series with LED ; PORTB1 - LED out Green ; PORTB2 - switch common ; Hours button PORTB2 - PORTB0 with 470 ohm resistor ; Minutes button PORTB2 - PORTB1 with 470 ohm resistor ; Timing set for 4MHz crystal and CKDIV8 (500 KHz) ; This is open source software. ; Uncomment to blink 15-minute intervals instead of 5-minute intervals #define OPTION_FIFTEEN_MIN = 0 .def REG_SUBSECONDS = r0 ; sub-second counting register .def REG_SECONDS = r1 ; seconds counting register .def REG_MINUTES = r2 ; minutes counting register, 0-4 .def REG_MINUTES_COPY = r3 ; copy for displaying .def REG_FIVEMIN = r4 ; five-minute counting register, 0-11 .def REG_FIVEMIN_COPY = r5 ; copy for displaying .def REG_HOURS = r6 ; hours counting register, 1-12 .def REG_HOURS_COPY = r7 ; copy for displaying .def REG_BLINK_DELAY = r8 ; countdown for pausing .def REG_SHOW_MINUTES = r9 ; nonzero = show minutes, 0xff = latch show minutes .def REG_DEBOUNCE = r10 ; key debounce .def SCRATCH0 = r16 .def SCRATCH1 = r17 ;.def SCRATCH2 = r18 .equ PORT_LED = PORTB .equ PIN_LED = PINB .equ PORT_LED_RED = PORTB0 .equ PORT_LED_GREEN = PORTB1 .equ PORT_SWITCH_COMMON = PORTB2 ; Note these are defined in order such that a shift left handles most state transitions. ; Change the order at your own risk. .def FLAGS1 = r19 .equ FLAG1_PAUSE_HOURS = 0 .equ FLAG1_BLINK_HOURS = 1 .equ FLAG1_PAUSE_FIVEMIN = 2 .equ FLAG1_BLINK_FIVEMIN = 3 .equ FLAG1_PAUSE_MINUTES = 4 .equ FLAG1_BLINK_MINUTES = 5 .def FLAGS2 = r20 .equ FLAG2_SWH_DOWN = 0 .equ FLAG2_SWM_DOWN = 1 .equ FLAG2_SW_DEBOUNCED = 2 .equ FLAG2_SW_DEBOUNCE = 3 .equ FLAG2_LED_YELLOW = 4 .org 0x0 rjmp V_RESET rjmp V_INT0 rjmp V_PCINT0 rjmp V_TIMER1_COMPA rjmp V_TIMER1_OVF rjmp V_TIMER0_OVF rjmp V_EE_RDY rjmp V_ANA_COMP rjmp V_ADC rjmp V_TIMER1_COMPB rjmp V_TIMER0_COMPA rjmp V_TIMER0_COMPB rjmp V_WDT rjmp V_USI_START rjmp V_USI_OVF V_RESET: V_ADC: V_INT0: V_PCINT0: V_TIMER1_COMPA: V_TIMER1_OVF: V_TIMER0_OVF: V_EE_RDY: V_ANA_COMP: V_TIMER1_COMPB: V_TIMER0_COMPB: V_WDT: V_USI_START: V_USI_OVF: ; Stack pointer ldi SCRATCH0,high(RAMEND) ldi SCRATCH1,low(RAMEND) out SPH,SCRATCH0 ; comment this out for ATTINY25 out SPL,SCRATCH1 ; Init registers clr REG_SUBSECONDS clr REG_SECONDS clr REG_MINUTES clr REG_FIVEMIN clr REG_HOURS inc REG_HOURS clr REG_DEBOUNCE clr REG_SHOW_MINUTES clr FLAGS1 clr FLAGS2 ; Setup I/O sbi ACSR,ACD ; save power ldi SCRATCH0,1< BLINK_HOURS mov REG_HOURS_COPY,REG_HOURS mov REG_FIVEMIN_COPY,REG_FIVEMIN mov REG_MINUTES_COPY,REG_MINUTES BLINK_OUT_1: rjmp BLINK_OUT ; BLINK_HOURS: tst REG_HOURS_COPY brne BHRS_NOTDONE ; done blinking hours, transition to pause minutes lsl FLAGS1 ; BLINK_HOURS -> PAUSE_FIVEMIN ldi SCRATCH0,250 mov REG_BLINK_DELAY,SCRATCH0 rjmp BLINK_OUT BHRS_NOTDONE: mov SCRATCH0,REG_SUBSECONDS tst SCRATCH0 ; is it zero? brne BHRS_NZ sbi PORT_LED,PORT_LED_RED ; light it red at zero cbi PORT_LED,PORT_LED_GREEN BHRS_NZ: cpi SCRATCH0,125 ; is it half? brne BHRS_NH cbi PORT_LED,PORT_LED_RED ; light off at half cbi PORT_LED,PORT_LED_GREEN dec REG_HOURS_COPY BHRS_NH: rjmp BLINK_OUT BLINK_PAUSE_FIVEMIN: dec REG_BLINK_DELAY brne BLINK_OUT ; done with pause fivemin, transition to blink fivemin lsl FLAGS1 ; PAUSE_FIVEMIN -> BLINK_FIVEMIN mov REG_BLINK_DELAY,REG_FIVEMIN rjmp BLINK_OUT ; BLINK_FIVEMIN: tst REG_FIVEMIN_COPY brne BFMN_NOTDONE ; done blinking fivemin, transition to pause minutes or next cycle cbr FLAGS1,1< BLINK_MINUTES mov SCRATCH0,REG_SHOW_MINUTES cpi SCRATCH0,0xff ; means latched breq BPM_SKIP1 dec REG_SHOW_MINUTES BPM_SKIP1: rjmp BLINK_OUT ; BLINK_MINUTES: tst REG_MINUTES_COPY brne BMIN_NOTDONE ; done blinking minutes, transition to next cycle ldi FLAGS1,1<