timer: Added comparator modes for pins
[simavr] / simavr / sim / avr_timer.c
1 /*
2         avr_timer.c
3
4         Handles the 8 bits and 16 bits AVR timer.
5         Handles
6         + CDC
7         + Fast PWM
8
9         Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
10
11         This file is part of simavr.
12
13         simavr is free software: you can redistribute it and/or modify
14         it under the terms of the GNU General Public License as published by
15         the Free Software Foundation, either version 3 of the License, or
16         (at your option) any later version.
17
18         simavr is distributed in the hope that it will be useful,
19         but WITHOUT ANY WARRANTY; without even the implied warranty of
20         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21         GNU General Public License for more details.
22
23         You should have received a copy of the GNU General Public License
24         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
25  */
26
27 #include <stdio.h>
28 #include "avr_timer.h"
29 #include "avr_ioport.h"
30
31 /*
32  * The timers are /always/ 16 bits here, if the higher byte register
33  * is specified it's just added.
34  */
35 static uint16_t _timer_get_ocr(avr_timer_t * p, int compi)
36 {
37         return p->io.avr->data[p->comp[compi].r_ocr] |
38                       (p->comp[compi].r_ocrh ? (p->io.avr->data[p->comp[compi].r_ocrh] << 8) : 0);
39 }
40 static uint16_t _timer_get_tcnt(avr_timer_t * p)
41 {
42         return p->io.avr->data[p->r_tcnt] |
43                                 (p->r_tcnth ? (p->io.avr->data[p->r_tcnth] << 8) : 0);
44 }
45 static uint16_t _timer_get_icr(avr_timer_t * p)
46 {
47         return p->io.avr->data[p->r_icr] |
48                                 (p->r_tcnth ? (p->io.avr->data[p->r_icrh] << 8) : 0);
49 }
50 static avr_cycle_count_t avr_timer_comp(avr_timer_t *p, avr_cycle_count_t when, uint8_t comp)
51 {
52         avr_t * avr = p->io.avr;
53         avr_raise_interrupt(avr, &p->comp[comp].interrupt);
54
55         // check output compare mode and set/clear pins
56         uint8_t mode = avr_regbit_get_array(avr, p->comp[comp].com,
57                 ARRAY_SIZE(p->comp[comp].com));
58         avr_irq_t * irq = &p->io.irq[TIMER_IRQ_OUT_COMP + comp];
59
60         switch (mode) {
61                 case avr_timer_com_normal: // Normal mode OCnA disconnected
62                         break;
63                 case avr_timer_com_toggle: // Toggle OCnA on compare match
64                         if (p->comp[comp].com_pin.reg)  // we got a physical pin
65                                 avr_raise_irq(irq,
66                                                 0x100 + (avr_regbit_get(avr, p->comp[comp].com_pin) ? 0 : 1));
67                         else // no pin, toggle the IRQ anyway
68                                 avr_raise_irq(irq,
69                                                 p->io.irq[TIMER_IRQ_OUT_COMP + comp].value ? 0 : 1);
70                         break;
71                 case avr_timer_com_clear:
72                         avr_raise_irq(irq, 0);
73                         break;
74                 case avr_timer_com_set:
75                         avr_raise_irq(irq, 1);
76                         break;
77         }
78
79         return p->tov_cycles ? 0 : p->comp[comp].comp_cycles ? when
80                 + p->comp[comp].comp_cycles : 0;
81 }
82
83 static avr_cycle_count_t avr_timer_compa(struct avr_t * avr, avr_cycle_count_t when, void * param)
84 {
85         return avr_timer_comp((avr_timer_t*)param, when, AVR_TIMER_COMPA);
86 }
87
88 static avr_cycle_count_t avr_timer_compb(struct avr_t * avr, avr_cycle_count_t when, void * param)
89 {
90         return avr_timer_comp((avr_timer_t*)param, when, AVR_TIMER_COMPB);
91 }
92
93 static avr_cycle_count_t avr_timer_compc(struct avr_t * avr, avr_cycle_count_t when, void * param)
94 {
95         return avr_timer_comp((avr_timer_t*)param, when, AVR_TIMER_COMPC);
96 }
97
98 static avr_cycle_count_t avr_timer_tov(struct avr_t * avr, avr_cycle_count_t when, void * param)
99 {
100         avr_timer_t * p = (avr_timer_t *)param;
101         int start = p->tov_base == 0;
102
103         if (!start)
104                 avr_raise_interrupt(avr, &p->overflow);
105         p->tov_base = when;
106
107         static const avr_cycle_timer_t dispatch[AVR_TIMER_COMP_COUNT] =
108                 { avr_timer_compa, avr_timer_compb, avr_timer_compc };
109
110         for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) {
111                 if (p->comp[compi].comp_cycles) {
112                         if (p->comp[compi].comp_cycles < p->tov_cycles)
113                                 avr_cycle_timer_register(avr,
114                                         p->comp[compi].comp_cycles - (avr->cycle - p->tov_base),
115                                         dispatch[compi], p);
116                         else if (p->tov_cycles == p->comp[compi].comp_cycles && !start)
117                                 dispatch[compi](avr, when, param);
118                 }
119         }
120
121         return when + p->tov_cycles;
122 }
123
124
125 static uint8_t avr_timer_tcnt_read(struct avr_t * avr, avr_io_addr_t addr, void * param)
126 {
127         avr_timer_t * p = (avr_timer_t *)param;
128         // made to trigger potential watchpoints
129
130         if (p->tov_cycles) {
131                 uint64_t when = avr->cycle - p->tov_base;
132
133                 uint16_t tcnt = (when * p->tov_top) / p->tov_cycles;
134         //      printf("%s-%c when = %d tcnt = %d/%d\n", __FUNCTION__, p->name, (uint32_t)when, tcnt, p->tov_top);
135
136                 avr->data[p->r_tcnt] = tcnt;
137                 if (p->r_tcnth)
138                         avr->data[p->r_tcnth] = tcnt >> 8;
139         }
140         
141         return avr_core_watch_read(avr, addr);
142 }
143
144 static void avr_timer_tcnt_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
145 {
146         avr_timer_t * p = (avr_timer_t *)param;
147         avr_core_watch_write(avr, addr, v);
148         uint16_t tcnt = _timer_get_tcnt(p);
149
150         if (!p->tov_top)
151                 return;
152                 
153         if (tcnt >= p->tov_top)
154                 tcnt = 0;
155         
156         // this involves some magicking
157         // cancel the current timers, recalculate the "base" we should be at, reset the
158         // timer base as it should, and re-shedule the timers using that base.
159         
160         avr_cycle_timer_cancel(avr, avr_timer_tov, p);
161         avr_cycle_timer_cancel(avr, avr_timer_compa, p);
162         avr_cycle_timer_cancel(avr, avr_timer_compb, p);
163         avr_cycle_timer_cancel(avr, avr_timer_compc, p);
164
165         uint64_t cycles = (tcnt * p->tov_cycles) / p->tov_top;
166
167 //      printf("%s-%c %d/%d -- cycles %d/%d\n", __FUNCTION__, p->name, tcnt, p->tov_top, (uint32_t)cycles, (uint32_t)p->tov_cycles);
168
169         // this reset the timers bases to the new base
170         p->tov_base = 0;
171         avr_cycle_timer_register(avr, p->tov_cycles - cycles, avr_timer_tov, p);
172         avr_timer_tov(avr, avr->cycle - cycles, p);
173
174 //      tcnt = ((avr->cycle - p->tov_base) * p->tov_top) / p->tov_cycles;
175 //      printf("%s-%c new tnt derive to %d\n", __FUNCTION__, p->name, tcnt);    
176 }
177
178 static void avr_timer_configure(avr_timer_t * p, uint32_t clock, uint32_t top)
179 {
180         float t = clock / (float)(top+1);
181         float frequency = p->io.avr->frequency;
182
183         p->tov_cycles = 0;
184         p->tov_top = top;
185
186         p->tov_cycles = frequency / t; // avr_hz_to_cycles(frequency, t);
187         printf("%s-%c TOP %.2fHz = %d cycles\n", __FUNCTION__, p->name, t, (int)p->tov_cycles);
188
189         for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) {
190                 uint32_t ocr = _timer_get_ocr(p, compi);
191                 float fc = clock / (float)(ocr);
192
193                 p->comp[compi].comp_cycles = 0;
194 //              printf("%s-%c clock %d top %d OCR%c %d\n", __FUNCTION__, p->name, clock, top, 'A'+compi, ocr);
195
196                 if (ocr && ocr <= top) {
197                         p->comp[compi].comp_cycles = frequency / fc; // avr_hz_to_cycles(p->io.avr, fa);
198                         printf("%s-%c %c %.2fHz = %d cycles\n", __FUNCTION__, p->name,
199                                         'A'+compi, fc, (int)p->comp[compi].comp_cycles);
200                 }
201         }
202
203         if (p->tov_cycles > 1) {
204                 avr_cycle_timer_register(p->io.avr, p->tov_cycles, avr_timer_tov, p);
205                 // calling it once, with when == 0 tells it to arm the A/B/C timers if needed
206                 p->tov_base = 0;
207                 avr_timer_tov(p->io.avr, p->io.avr->cycle, p);
208         }
209 }
210
211 static void avr_timer_reconfigure(avr_timer_t * p)
212 {
213         avr_t * avr = p->io.avr;
214
215         avr_timer_wgm_t zero={0};
216         p->mode = zero;
217         // cancel everything
218         p->comp[AVR_TIMER_COMPA].comp_cycles = 0;
219         p->comp[AVR_TIMER_COMPB].comp_cycles = 0;
220         p->comp[AVR_TIMER_COMPC].comp_cycles = 0;
221         p->tov_cycles = 0;
222         
223         avr_cycle_timer_cancel(avr, avr_timer_tov, p);
224         avr_cycle_timer_cancel(avr, avr_timer_compa, p);
225         avr_cycle_timer_cancel(avr, avr_timer_compb, p);
226         avr_cycle_timer_cancel(avr, avr_timer_compc, p);
227
228         long clock = avr->frequency;
229
230         // only can exists on "asynchronous" 8 bits timers
231         if (avr_regbit_get(avr, p->as2))
232                 clock = 32768;
233
234         uint8_t cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs));
235         if (cs == 0) {
236                 printf("%s-%c clock turned off\n", __FUNCTION__, p->name);              
237                 return;
238         }
239
240         uint8_t mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm));
241         uint8_t cs_div = p->cs_div[cs];
242         uint32_t f = clock >> cs_div;
243
244         p->mode = p->wgm_op[mode];
245         //printf("%s-%c clock %d, div %d(/%d) = %d ; mode %d\n", __FUNCTION__, p->name, clock, cs, 1 << cs_div, f, mode);
246         switch (p->mode.kind) {
247                 case avr_timer_wgm_normal:
248                         avr_timer_configure(p, f, (1 << p->mode.size) - 1);
249                         break;
250                 case avr_timer_wgm_ctc: {
251                         avr_timer_configure(p, f, _timer_get_ocr(p, AVR_TIMER_COMPA));
252                 }       break;
253                 case avr_timer_wgm_pwm: {
254                         uint16_t top = p->mode.top == avr_timer_wgm_reg_ocra ? _timer_get_ocr(p, AVR_TIMER_COMPA) : _timer_get_icr(p);
255                         avr_timer_configure(p, f, top);
256                 }       break;
257                 case avr_timer_wgm_fast_pwm:
258                 //      avr_timer_configure(p, f, (1 << p->mode.size) - 1);
259                         break;
260                 default:
261                         printf("%s-%c unsupported timer mode wgm=%d (%d)\n", __FUNCTION__, p->name, mode, p->mode.kind);
262         }       
263 }
264
265 static void avr_timer_write_ocr(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
266 {
267         avr_timer_t * p = (avr_timer_t *)param;
268         avr_core_watch_write(avr, addr, v);
269
270         switch (p->mode.kind) {
271                 case avr_timer_wgm_pwm:
272                         if (p->mode.top != avr_timer_wgm_reg_ocra) {
273                                 avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocr(p, AVR_TIMER_COMPA));
274                                 avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocr(p, AVR_TIMER_COMPB));
275                         }
276                         break;
277                 case avr_timer_wgm_fast_pwm:
278                         avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocr(p, AVR_TIMER_COMPA));
279                         avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocr(p, AVR_TIMER_COMPB));
280                         break;
281                 default:
282                         printf("%s-%c mode %d\n", __FUNCTION__, p->name, p->mode.kind);
283                         avr_timer_reconfigure(p);
284                         break;
285         }
286 }
287
288 static void avr_timer_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
289 {
290         avr_timer_t * p = (avr_timer_t *)param;
291         avr_core_watch_write(avr, addr, v);
292         avr_timer_reconfigure(p);
293 }
294
295 static void avr_timer_reset(avr_io_t * port)
296 {
297         avr_timer_t * p = (avr_timer_t *)port;
298         avr_cycle_timer_cancel(p->io.avr, avr_timer_tov, p);
299         avr_cycle_timer_cancel(p->io.avr, avr_timer_compa, p);
300         avr_cycle_timer_cancel(p->io.avr, avr_timer_compb, p);
301         avr_cycle_timer_cancel(p->io.avr, avr_timer_compc, p);
302
303         // check to see if the comparators have a pin output. If they do,
304         // (try) to get the ioport corresponding IRQ and connect them
305         // they will automagically be triggered when the comparator raises
306         // it's own IRQ
307         for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) {
308                 p->comp[compi].comp_cycles = 0;
309
310                 avr_ioport_getirq_t req = {
311                         .bit = p->comp[compi].com_pin
312                 };
313                 if (avr_ioctl(port->avr, AVR_IOCTL_IOPORT_GETIRQ_REGBIT, &req) > 0) {
314                         // cool, got an IRQ
315 //                      printf("%s-%c COMP%c Connecting PIN IRQ %d\n", __FUNCTION__, p->name, 'A'+compi, req.irq[0]->irq);
316                         avr_connect_irq(&port->irq[TIMER_IRQ_OUT_COMP + compi], req.irq[0]);
317                 }
318         }
319 }
320
321 static  avr_io_t        _io = {
322         .kind = "timer",
323         .reset = avr_timer_reset,
324 };
325
326 void avr_timer_init(avr_t * avr, avr_timer_t * p)
327 {
328         p->io = _io;
329
330         // allocate this module's IRQ
331         p->io.irq_count = TIMER_IRQ_COUNT;
332         p->io.irq = avr_alloc_irq(0, p->io.irq_count);
333         p->io.irq_ioctl_get = AVR_IOCTL_TIMER_GETIRQ(p->name);
334         p->io.irq[TIMER_IRQ_OUT_PWM0].flags |= IRQ_FLAG_FILTERED;
335         p->io.irq[TIMER_IRQ_OUT_PWM1].flags |= IRQ_FLAG_FILTERED;
336
337         avr_register_io(avr, &p->io);
338         avr_register_vector(avr, &p->overflow);
339         avr_register_vector(avr, &p->icr);
340
341         avr_register_io_write(avr, p->cs[0].reg, avr_timer_write, p);
342
343         /*
344          * Even if the timer is 16 bits, we don't care to have watches on the
345          * high bytes because the datasheet says that the low address is always
346          * the trigger.
347          */
348         for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) {
349                 avr_register_vector(avr, &p->comp[compi].interrupt);
350
351                 if (p->comp[compi].r_ocr) // not all timers have all comparators
352                         avr_register_io_write(avr, p->comp[compi].r_ocr, avr_timer_write_ocr, p);
353         }
354         avr_register_io_write(avr, p->r_tcnt, avr_timer_tcnt_write, p);
355         avr_register_io_read(avr, p->r_tcnt, avr_timer_tcnt_read, p);
356 }