timer: Added (non functional) C interrupt block
[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
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_ocra(avr_timer_t * p)
36 {
37         return p->io.avr->data[p->r_ocra] |
38                                 (p->r_ocrah ? (p->io.avr->data[p->r_ocrah] << 8) : 0);
39 }
40 static uint16_t _timer_get_ocrb(avr_timer_t * p)
41 {
42         return p->io.avr->data[p->r_ocrb] |
43                                 (p->r_ocrbh ? (p->io.avr->data[p->r_ocrbh] << 8) : 0);
44 }
45 static uint16_t _timer_get_tcnt(avr_timer_t * p)
46 {
47         return p->io.avr->data[p->r_tcnt] |
48                                 (p->r_tcnth ? (p->io.avr->data[p->r_tcnth] << 8) : 0);
49 }
50 static uint16_t _timer_get_icr(avr_timer_t * p)
51 {
52         return p->io.avr->data[p->r_icr] |
53                                 (p->r_tcnth ? (p->io.avr->data[p->r_icrh] << 8) : 0);
54 }
55
56 static avr_cycle_count_t avr_timer_compa(struct avr_t * avr, avr_cycle_count_t when, void * param)
57 {
58         avr_timer_t * p = (avr_timer_t *)param;
59         avr_raise_interrupt(avr, &p->compa);
60         return p->tov_cycles ? 0 : p->compa_cycles ? when + p->compa_cycles : 0;
61 }
62
63 static avr_cycle_count_t avr_timer_compb(struct avr_t * avr, avr_cycle_count_t when, void * param)
64 {
65         avr_timer_t * p = (avr_timer_t *)param;
66         avr_raise_interrupt(avr, &p->compb);
67         return p->tov_cycles ? 0 : p->compb_cycles ? when + p->compb_cycles : 0;
68 }
69
70 static avr_cycle_count_t avr_timer_tov(struct avr_t * avr, avr_cycle_count_t when, void * param)
71 {
72         avr_timer_t * p = (avr_timer_t *)param;
73         int start = p->tov_base == 0;
74         
75         if (!start)
76                 avr_raise_interrupt(avr, &p->overflow);
77         p->tov_base = when;
78
79         if (p->compa_cycles) {
80                 if (p->compa_cycles < p->tov_cycles)
81                         avr_cycle_timer_register(avr, 
82                                 p->compa_cycles - (avr->cycle - p->tov_base), 
83                                 avr_timer_compa, p);
84                 else if (p->tov_cycles == p->compa_cycles && !start)
85                         avr_timer_compa(avr, when, param);
86         }
87         
88         if (p->compb_cycles) {
89                 if (p->compb_cycles < p->tov_cycles)
90                         avr_cycle_timer_register(avr, 
91                                 p->compb_cycles - (avr->cycle - p->tov_base), 
92                                 avr_timer_compb, p);
93                 else if (p->tov_cycles == p->compb_cycles && !start)
94                         avr_timer_compb(avr, when, param);
95         }
96
97         return when + p->tov_cycles;
98 }
99
100
101 static uint8_t avr_timer_tcnt_read(struct avr_t * avr, avr_io_addr_t addr, void * param)
102 {
103         avr_timer_t * p = (avr_timer_t *)param;
104         // made to trigger potential watchpoints
105
106         if (p->tov_cycles) {
107                 uint64_t when = avr->cycle - p->tov_base;
108
109                 uint16_t tcnt = (when * p->tov_top) / p->tov_cycles;
110         //      printf("%s-%c when = %d tcnt = %d/%d\n", __FUNCTION__, p->name, (uint32_t)when, tcnt, p->tov_top);
111
112                 avr->data[p->r_tcnt] = tcnt;
113                 if (p->r_tcnth)
114                         avr->data[p->r_tcnth] = tcnt >> 8;
115         }
116         
117         return avr_core_watch_read(avr, addr);
118 }
119
120 static void avr_timer_tcnt_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
121 {
122         avr_timer_t * p = (avr_timer_t *)param;
123         avr_core_watch_write(avr, addr, v);
124         uint16_t tcnt = _timer_get_tcnt(p);
125
126         if (!p->tov_top)
127                 return;
128                 
129         if (tcnt >= p->tov_top)
130                 tcnt = 0;
131         
132         // this involves some magicking
133         // cancel the current timers, recalculate the "base" we should be at, reset the
134         // timer base as it should, and re-shedule the timers using that base.
135         
136         avr_cycle_timer_cancel(avr, avr_timer_tov, p);
137         avr_cycle_timer_cancel(avr, avr_timer_compa, p);
138         avr_cycle_timer_cancel(avr, avr_timer_compb, p);
139
140         uint64_t cycles = (tcnt * p->tov_cycles) / p->tov_top;
141
142 //      printf("%s-%c %d/%d -- cycles %d/%d\n", __FUNCTION__, p->name, tcnt, p->tov_top, (uint32_t)cycles, (uint32_t)p->tov_cycles);
143
144         // this reset the timers bases to the new base
145         p->tov_base = 0;
146         avr_cycle_timer_register(avr, p->tov_cycles - cycles, avr_timer_tov, p);
147         avr_timer_tov(avr, avr->cycle - cycles, p);
148
149 //      tcnt = ((avr->cycle - p->tov_base) * p->tov_top) / p->tov_cycles;
150 //      printf("%s-%c new tnt derive to %d\n", __FUNCTION__, p->name, tcnt);    
151 }
152
153 static void avr_timer_configure(avr_timer_t * p, uint32_t clock, uint32_t top)
154 {
155         uint32_t ocra = _timer_get_ocra(p);
156         uint32_t ocrb = _timer_get_ocrb(p);
157         float fa = clock / (float)(ocra+1), fb = clock / (float)(ocrb+1);
158         float t = clock / (float)(top+1);
159         float frequency = p->io.avr->frequency;
160
161         p->compa_cycles = p->compb_cycles = p->tov_cycles = 0;
162         p->tov_top = top;
163
164         printf("%s-%c clock %d top %d a %d b %d\n", __FUNCTION__, p->name, clock, top, ocra, ocrb);
165         p->tov_cycles = frequency / t; // avr_hz_to_cycles(frequency, t);
166         printf("%s-%c TOP %.2fHz = %d cycles\n", __FUNCTION__, p->name, t, (int)p->tov_cycles);
167
168         if (ocra && ocra <= top) {
169                 p->compa_cycles = frequency / fa; // avr_hz_to_cycles(p->io.avr, fa);
170                 printf("%s-%c A %.2fHz = %d cycles\n", __FUNCTION__, p->name, fa, (int)p->compa_cycles);
171         }
172         if (ocrb && ocrb <= top) {
173                 p->compb_cycles = frequency / fb; // avr_hz_to_cycles(p->io.avr, fb);
174                 printf("%s-%c B %.2fHz = %d cycles\n", __FUNCTION__, p->name, fb, (int)p->compb_cycles);
175         }
176
177         if (p->tov_cycles > 1) {
178                 avr_cycle_timer_register(p->io.avr, p->tov_cycles, avr_timer_tov, p);
179                 // calling it once, with when == 0 tells it to arm the A/B timers if needed
180                 p->tov_base = 0;
181                 avr_timer_tov(p->io.avr, p->io.avr->cycle, p);
182         }
183 }
184
185 static void avr_timer_reconfigure(avr_timer_t * p)
186 {
187         avr_t * avr = p->io.avr;
188
189         avr_timer_wgm_t zero={0};
190         p->mode = zero;
191         // cancel everything
192         p->compa_cycles = 0;
193         p->compb_cycles = 0;
194         p->tov_cycles = 0;
195         
196         avr_cycle_timer_cancel(avr, avr_timer_tov, p);
197         avr_cycle_timer_cancel(avr, avr_timer_compa, p);
198         avr_cycle_timer_cancel(avr, avr_timer_compb, p);
199
200         long clock = avr->frequency;
201
202         // only can exists on "asynchronous" 8 bits timers
203         if (avr_regbit_get(avr, p->as2))
204                 clock = 32768;
205
206         uint8_t cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs));
207         if (cs == 0) {
208                 printf("%s-%c clock turned off\n", __FUNCTION__, p->name);              
209                 return;
210         }
211
212         uint8_t mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm));
213         uint8_t cs_div = p->cs_div[cs];
214         uint32_t f = clock >> cs_div;
215
216         p->mode = p->wgm_op[mode];
217         //printf("%s-%c clock %d, div %d(/%d) = %d ; mode %d\n", __FUNCTION__, p->name, clock, cs, 1 << cs_div, f, mode);
218         switch (p->mode.kind) {
219                 case avr_timer_wgm_normal:
220                         avr_timer_configure(p, f, (1 << p->mode.size) - 1);
221                         break;
222                 case avr_timer_wgm_ctc: {
223                         avr_timer_configure(p, f, _timer_get_ocra(p));
224                 }       break;
225                 case avr_timer_wgm_pwm: {
226                         uint16_t top = p->mode.top == avr_timer_wgm_reg_ocra ? _timer_get_ocra(p) : _timer_get_icr(p);
227                         avr_timer_configure(p, f, top);
228                 }       break;
229                 case avr_timer_wgm_fast_pwm:
230                 //      avr_timer_configure(p, f, (1 << p->mode.size) - 1);
231                         break;
232                 default:
233                         printf("%s-%c unsupported timer mode wgm=%d (%d)\n", __FUNCTION__, p->name, mode, p->mode.kind);
234         }       
235 }
236
237 static void avr_timer_write_ocr(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
238 {
239         avr_timer_t * p = (avr_timer_t *)param;
240         avr_core_watch_write(avr, addr, v);
241         switch (p->mode.kind) {
242                 case avr_timer_wgm_pwm:
243                         if (p->mode.top != avr_timer_wgm_reg_ocra) {
244                                 avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocra(p));
245                                 avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocrb(p));
246                         }
247                         break;
248                 case avr_timer_wgm_fast_pwm:
249                         avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocra(p));
250                         avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocrb(p));
251                         break;
252                 default:
253                         printf("%s-%c mode %d\n", __FUNCTION__, p->name, p->mode.kind);
254                         avr_timer_reconfigure(p);
255                         break;
256         }
257 }
258
259 static void avr_timer_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
260 {
261         avr_timer_t * p = (avr_timer_t *)param;
262         avr_core_watch_write(avr, addr, v);
263         avr_timer_reconfigure(p);
264 }
265
266 static void avr_timer_reset(avr_io_t * port)
267 {
268         avr_timer_t * p = (avr_timer_t *)port;
269         avr_cycle_timer_cancel(p->io.avr, avr_timer_tov, p);
270         avr_cycle_timer_cancel(p->io.avr, avr_timer_compa, p);
271         avr_cycle_timer_cancel(p->io.avr, avr_timer_compb, p);
272         p->compa_cycles = 0;
273         p->compb_cycles = 0;
274 }
275
276 static  avr_io_t        _io = {
277         .kind = "timer",
278         .reset = avr_timer_reset,
279 };
280
281 void avr_timer_init(avr_t * avr, avr_timer_t * p)
282 {
283         p->io = _io;
284         //printf("%s timer%c created\n", __FUNCTION__, p->name);
285
286         // allocate this module's IRQ
287         p->io.irq_count = TIMER_IRQ_COUNT;
288         p->io.irq = avr_alloc_irq(0, p->io.irq_count);
289         p->io.irq_ioctl_get = AVR_IOCTL_TIMER_GETIRQ(p->name);
290         p->io.irq[TIMER_IRQ_OUT_PWM0].flags |= IRQ_FLAG_FILTERED;
291         p->io.irq[TIMER_IRQ_OUT_PWM1].flags |= IRQ_FLAG_FILTERED;
292
293         avr_register_io(avr, &p->io);
294         avr_register_vector(avr, &p->compa);
295         avr_register_vector(avr, &p->compb);
296         avr_register_vector(avr, &p->overflow);
297         avr_register_vector(avr, &p->icr);
298
299         avr_register_io_write(avr, p->cs[0].reg, avr_timer_write, p);
300
301         /*
302          * Even if the timer is 16 bits, we don't care to have watches on the
303          * high bytes because the datasheet says that the low address is always
304          * the trigger.
305          */
306         avr_register_io_write(avr, p->r_ocra, avr_timer_write_ocr, p);
307         if (p->r_ocrb) // not all timers have B register
308                 avr_register_io_write(avr, p->r_ocrb, avr_timer_write, p);
309         if(p->r_ocrc)   // but some have a C one
310                 avr_register_io_write(avr, p->r_ocrc, avr_timer_write, p);
311         avr_register_io_write(avr, p->r_tcnt, avr_timer_tcnt_write, p);
312
313         avr_register_io_read(avr, p->r_tcnt, avr_timer_tcnt_read, p);
314 }