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