1 ;; vim: filetype=avr |
|
2 ;; |
|
3 ;; Timer unit control and use |
|
4 ;; |
|
5 |
|
6 .equ TIMER_FLAGS = GPIOR0 |
|
7 |
|
8 ;; Timer0 |
|
9 ; Compare output mode |
|
10 .set TIMER0_COMA = 0b00 ; null |
|
11 .set TIMER0_COMB = 0b00 ; null |
|
12 |
|
13 ; Waveform Generation Mode (triplet low/high) |
|
14 .set TIMER0_WGML = 0b10 ; CTC |
|
15 .set TIMER0_WGMH = 0b0 ; CTC |
|
16 |
|
17 ; Clock Source |
|
18 .set TIMER0_CS = 0b101 ; 1/1024 |
|
19 |
|
20 ;; Timer1 |
|
21 ; Waveform Generation Mode (nibble low/high) |
|
22 .set TIMER1_WGML = 0b00 ; CTC |
|
23 .set TIMER1_WGMH = 0b01 ; CTC |
|
24 |
|
25 ; Clock Source |
|
26 .set TIMER1_CS = 0b101 ; 1/1024 |
|
27 |
|
28 ; Flags |
|
29 .equ TIMER1_BUSY = 1 |
|
30 |
|
31 .set SLEEP_MODE = 0b000 ; Idle |
|
32 |
|
33 Timer_Init: |
|
34 Timer0_Init: |
|
35 ; OC0A/B disconnected from output |
|
36 ; No PWM mode |
|
37 ldi r16, (TIMER0_COMA << COM0A0) | (TIMER0_COMB << COM0B0) | (TIMER0_WGML << WGM00) |
|
38 out TCCR0A, r16 |
|
39 |
|
40 ; Clear |
|
41 ldi r16, 0 |
|
42 out OCR0A, r16 |
|
43 out OCR0B, r16 |
|
44 out TCCR0B, r16 |
|
45 |
|
46 ; Enable compare interrupt |
|
47 ldi r16, (1 << OCIE0A) |
|
48 sts TIMSK0, r16 |
|
49 |
|
50 Timer1_Init: |
|
51 ; OC1A/B disconnected from output |
|
52 ; No PWM mode |
|
53 poke [TCCR1A, r16, (0b00 << COM1A0) | (0b00 << COM1B0) | (TIMER1_WGML << WGM10)] |
|
54 |
|
55 ; Clear |
|
56 poke [TCCR1B, r16, 0] |
|
57 poke [TCCR1C, r16, 0] |
|
58 |
|
59 ; Enable compare interrupt |
|
60 poke [TIMSK1, r16, (1 << OCIE1A)] |
|
61 |
|
62 Sleep_init: |
|
63 ; Select sleep mode |
|
64 ; Enable `sleep` |
|
65 poke [SMCR, r16, (SLEEP_MODE << SM0) | (1 << SE)] |
|
66 |
|
67 ; Disable ADC |
|
68 poke [SMCR, r16, (1 << PRTWI) | (1 << PRUSART0) | (1 << PRADC)] |
|
69 |
|
70 ret |
|
71 |
|
72 ;; Timer0 is recurring; this starts it running, and it keeps hitting OC0A periodically |
|
73 ;; Input: r16 (period, in 1k-cycles) |
|
74 Timer0_Start: |
|
75 ; Initialize timer |
|
76 ; set CTC trigger from r16 |
|
77 out OCR0A, r16 |
|
78 |
|
79 ; clear counter |
|
80 ldi r16, 0 |
|
81 out TCNT0, r16 |
|
82 |
|
83 ; Start |
|
84 ; WGM |
|
85 ; Clock Source |
|
86 ldi r16, (TIMER0_WGMH << WGM02) | (TIMER0_CS << CS00) |
|
87 out TCCR0B, r16 |
|
88 |
|
89 ret |
|
90 |
|
91 Timer0_Read8: |
|
92 in r16, TCNT0 |
|
93 |
|
94 ret |
|
95 |
|
96 ;; Timer0 Compare A interrupt handler |
|
97 Timer_OC0A: |
|
98 in r0, SREG |
|
99 |
|
100 ; Run callback |
|
101 rcall TIMER0_CB_A |
|
102 |
|
103 out SREG, r0 |
|
104 reti |
|
105 |
|
106 ;; Timer1 is one-shot; this starts it running, and it is then stopped once it hits OC1A |
|
107 Timer1_Start: |
|
108 ; Initialize timer |
|
109 poke [TCNT1H, r16, high(0)] |
|
110 poke [TCNT1L, r16, low(0)] |
|
111 |
|
112 ; Set flag |
|
113 sbi TIMER_FLAGS, TIMER1_BUSY |
|
114 |
|
115 ; Start |
|
116 ; WGM |
|
117 ; Clock Source |
|
118 poke [TCCR1B, r16, (TIMER1_WGMH << WGM12) | (TIMER1_CS << CS10)] |
|
119 |
|
120 ret |
|
121 |
|
122 Timer1_Stop: |
|
123 ; WGM |
|
124 ; Clock off |
|
125 poke [TCCR1B, r16, (TIMER1_WGMH << WGM12) | (0b00 << CS10)] |
|
126 |
|
127 ; Clear flag |
|
128 cbi TIMER_FLAGS, TIMER1_BUSY |
|
129 |
|
130 ret |
|
131 |
|
132 ;; Timer1 Compare A interrupt handler |
|
133 Timer_OC1A: |
|
134 in r0, SREG |
|
135 |
|
136 ; Stop timer |
|
137 rcall Timer1_Stop |
|
138 |
|
139 out SREG, r0 |
|
140 reti |
|
141 |
|
142 ;; Prime the timer and sleep for 1s |
|
143 Timer_Sleep_1s: |
|
144 ; Initialize counter to 16k cycles |
|
145 ldi XH, high(16 * 1024) |
|
146 ldi XL, low(16 * 1024) |
|
147 |
|
148 ;; Continue |
|
149 |
|
150 ;; Count to X |
|
151 Timer_Sleep: |
|
152 ; Set TOP |
|
153 sts OCR1AH, XH |
|
154 sts OCR1AL, XL |
|
155 |
|
156 ; Start timer |
|
157 rcall Timer1_Start |
|
158 |
|
159 ; Wait for timer to complete |
|
160 _timer1_sleep: |
|
161 sleep |
|
162 |
|
163 sbic TIMER_FLAGS, TIMER1_BUSY |
|
164 rjmp _timer1_sleep |
|
165 |
|
166 ; Done |
|
167 ret |
|
168 |
|
169 ;; Update timer for given timeout |
|
170 Timer_Update: |
|
171 ; Set TOP |
|
172 sts OCR1AH, XH |
|
173 sts OCR1AL, XL |
|
174 |
|
175 ; Check timer |
|
176 lds YL, TCNT1L |
|
177 lds YH, TCNT1H |
|
178 |
|
179 cp YL, XL |
|
180 cpc YH, XH |
|
181 |
|
182 brlo timer_up_out |
|
183 |
|
184 ; Update |
|
185 ; XXX: figure out a better way to do this... |
|
186 ldi r16, 0 |
|
187 subi XL, 2 |
|
188 sbc XH, r16 |
|
189 |
|
190 sts TCNT1L, XL |
|
191 sts TCNT1H, XH |
|
192 |
|
193 timer_up_out: |
|
194 ; Done |
|
195 ret |
|
196 |
|