4 Handles the 8 bits and 16 bits AVR timer.
9 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
11 This file is part of simavr.
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.
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.
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/>.
28 #include "avr_timer.h"
32 * The timers are /always/ 16 bits here, if the higher byte register
33 * is specified it's just added.
35 static uint16_t _timer_get_ocra(avr_timer_t * p)
37 return p->io.avr->data[p->r_ocra] |
38 (p->r_ocrah ? (p->io.avr->data[p->r_ocrah] << 8) : 0);
40 static uint16_t _timer_get_ocrb(avr_timer_t * p)
42 return p->io.avr->data[p->r_ocrb] |
43 (p->r_ocrbh ? (p->io.avr->data[p->r_ocrbh] << 8) : 0);
45 static uint16_t _timer_get_tcnt(avr_timer_t * p)
47 return p->io.avr->data[p->r_tcnt] |
48 (p->r_tcnth ? (p->io.avr->data[p->r_tcnth] << 8) : 0);
51 static avr_cycle_count_t avr_timer_compa(struct avr_t * avr, avr_cycle_count_t when, void * param)
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;
58 static avr_cycle_count_t avr_timer_compb(struct avr_t * avr, avr_cycle_count_t when, void * param)
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;
65 static avr_cycle_count_t avr_timer_tov(struct avr_t * avr, avr_cycle_count_t when, void * param)
67 avr_timer_t * p = (avr_timer_t *)param;
68 int start = p->tov_base == 0;
71 avr_raise_interrupt(avr, &p->overflow);
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),
79 else if (p->tov_cycles == p->compa_cycles && !start)
80 avr_timer_compa(avr, when, param);
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),
88 else if (p->tov_cycles == p->compb_cycles && !start)
89 avr_timer_compb(avr, when, param);
92 return when + p->tov_cycles;
96 static uint8_t avr_timer_tcnt_read(struct avr_t * avr, avr_io_addr_t addr, void * param)
98 avr_timer_t * p = (avr_timer_t *)param;
99 // made to trigger potential watchpoints
101 uint64_t when = avr->cycle - p->tov_base;
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);
106 avr->data[p->r_tcnt] = tcnt;
108 avr->data[p->r_tcnth] = tcnt >> 8;
110 return avr_core_watch_read(avr, addr);
113 static void avr_timer_tcnt_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
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);
122 if (tcnt >= p->tov_top)
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.
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);
133 uint64_t cycles = (tcnt * p->tov_cycles) / p->tov_top;
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);
137 // this reset the timers bases to the new base
139 avr_cycle_timer_register(avr, p->tov_cycles - cycles, avr_timer_tov, p);
140 avr_timer_tov(avr, avr->cycle - cycles, p);
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);
146 static void avr_timer_configure(avr_timer_t * p, uint32_t clock, uint32_t top)
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;
154 p->compa_cycles = p->compb_cycles = p->tov_cycles = 0;
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);
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);
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);
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
174 avr_timer_tov(p->io.avr, p->io.avr->cycle, p);
178 static void avr_timer_reconfigure(avr_timer_t * p)
180 avr_t * avr = p->io.avr;
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);
191 long clock = avr->frequency;
193 // only can exists on "asynchronous" 8 bits timers
194 if (avr_regbit_get(avr, p->as2))
197 uint8_t cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs));
199 printf("%s-%c clock turned off\n", __FUNCTION__, p->name);
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;
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);
212 case avr_timer_wgm_ctc: {
213 avr_timer_configure(p, f, _timer_get_ocra(p));
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));
220 printf("%s-%c unsupported timer mode wgm=%d (%d)\n", __FUNCTION__, p->name, mode, p->wgm_op[mode].kind);
224 static void avr_timer_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
226 avr_timer_t * p = (avr_timer_t *)param;
227 avr_core_watch_write(avr, addr, v);
228 avr_timer_reconfigure(p);
231 static void avr_timer_reset(avr_io_t * port)
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);
241 static avr_io_t _io = {
243 .reset = avr_timer_reset,
246 void avr_timer_init(avr_t * avr, avr_timer_t * p)
249 printf("%s timer%c created OCRA %02x OCRAH %02x\n", __FUNCTION__, p->name, p->r_ocra, p->r_ocrah);
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;
258 avr_register_io(avr, &p->io);
259 avr_register_vector(avr, &p->compa);
260 avr_register_vector(avr, &p->compb);
262 avr_register_io_write(avr, p->cs[0].reg, avr_timer_write, p);
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
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);
273 avr_register_io_read(avr, p->r_tcnt, avr_timer_tcnt_read, p);