return p->io.avr->data[p->comp[compi].r_ocr] |
(p->comp[compi].r_ocrh ? (p->io.avr->data[p->comp[compi].r_ocrh] << 8) : 0);
}
+static uint16_t _timer_get_comp_ocr(struct avr_t * avr, avr_timer_comp_p comp)
+{
+ int ocrh = comp->r_ocrh;
+ return avr->data[comp->r_ocr] |
+ (ocrh ? (avr->data[ocrh] << 8) : 0);
+}
static uint16_t _timer_get_tcnt(avr_timer_t * p)
{
return p->io.avr->data[p->r_tcnt] |
static void avr_timer_write_ocr(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
{
- avr_timer_t * p = (avr_timer_t *)param;
- uint16_t oldv[AVR_TIMER_COMP_COUNT];
- int target = -1;
+ avr_timer_comp_p comp = (avr_timer_comp_p)param;
+ avr_timer_t *timer = comp->timer;
+ uint16_t oldv;
/* check to see if the OCR values actually changed */
- for (int oi = 0; oi < AVR_TIMER_COMP_COUNT; oi++)
- oldv[oi] = _timer_get_ocr(p, oi);
+ oldv = _timer_get_comp_ocr(avr, comp);
avr_core_watch_write(avr, addr, v);
- for (int oi = 0; oi < AVR_TIMER_COMP_COUNT; oi++)
- if (oldv[oi] != _timer_get_ocr(p, oi)) {
- target = oi;
- break;
- }
- switch (p->mode.kind) {
+ switch (timer->mode.kind) {
case avr_timer_wgm_normal:
- avr_timer_reconfigure(p);
+ avr_timer_reconfigure(timer);
break;
case avr_timer_wgm_fc_pwm: // OCR is not used here
- avr_timer_reconfigure(p);
+ avr_timer_reconfigure(timer);
break;
case avr_timer_wgm_ctc:
- avr_timer_reconfigure(p);
+ avr_timer_reconfigure(timer);
break;
case avr_timer_wgm_pwm:
- if (p->mode.top != avr_timer_wgm_reg_ocra) {
- avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocr(p, AVR_TIMER_COMPA));
- avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocr(p, AVR_TIMER_COMPB));
+ if (timer->mode.top != avr_timer_wgm_reg_ocra) {
+ avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocr(timer, AVR_TIMER_COMPA));
+ avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocr(timer, AVR_TIMER_COMPB));
}
break;
case avr_timer_wgm_fast_pwm:
- if (target != -1)
- avr_timer_reconfigure(p);
- avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocr(p, AVR_TIMER_COMPA));
- avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocr(p, AVR_TIMER_COMPB));
+ if (oldv != _timer_get_comp_ocr(avr, comp))
+ avr_timer_reconfigure(timer);
+ avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocr(timer, AVR_TIMER_COMPA));
+ avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocr(timer, AVR_TIMER_COMPB));
break;
default:
- AVR_LOG(avr, LOG_WARNING, "TIMER: %s-%c mode %d UNSUPPORTED\n", __FUNCTION__, p->name, p->mode.kind);
- avr_timer_reconfigure(p);
+ AVR_LOG(avr, LOG_WARNING, "TIMER: %s-%c mode %d UNSUPPORTED\n", __FUNCTION__, timer->name, timer->mode.kind);
+ avr_timer_reconfigure(timer);
break;
}
}
* the trigger.
*/
for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) {
+ p->comp[compi].timer = p;
+
avr_register_vector(avr, &p->comp[compi].interrupt);
if (p->comp[compi].r_ocr) // not all timers have all comparators
- avr_register_io_write(avr, p->comp[compi].r_ocr, avr_timer_write_ocr, p);
+ avr_register_io_write(avr, p->comp[compi].r_ocr, avr_timer_write_ocr, &p->comp[compi]);
}
avr_register_io_write(avr, p->r_tcnt, avr_timer_tcnt_write, p);
avr_register_io_read(avr, p->r_tcnt, avr_timer_tcnt_read, p);
#define AVR_TIMER_WGM_OCPWM() { .kind = avr_timer_wgm_pwm, .top = avr_timer_wgm_reg_ocra }
#define AVR_TIMER_WGM_ICPWM() { .kind = avr_timer_wgm_pwm, .top = avr_timer_wgm_reg_icr }
+typedef struct avr_timer_comp_t {
+ avr_int_vector_t interrupt; // interrupt vector
+ struct avr_timer_t *timer; // parent timer
+ avr_io_addr_t r_ocr; // comparator register low byte
+ avr_io_addr_t r_ocrh; // comparator register hi byte
+ avr_regbit_t com; // comparator output mode registers
+ avr_regbit_t com_pin; // where comparator output is connected
+ uint64_t comp_cycles;
+} avr_timer_comp_t, *avr_timer_comp_p;
typedef struct avr_timer_t {
avr_io_t io;
avr_regbit_t icp; // input capture pin, to link IRQs
avr_regbit_t ices; // input capture edge select
- struct {
- avr_int_vector_t interrupt; // interrupt vector
- avr_io_addr_t r_ocr; // comparator register low byte
- avr_io_addr_t r_ocrh; // comparator register hi byte
- avr_regbit_t com; // comparator output mode registers
- avr_regbit_t com_pin; // where comparator output is connected
- uint64_t comp_cycles;
- } comp[AVR_TIMER_COMP_COUNT];
+ avr_timer_comp_t comp[AVR_TIMER_COMP_COUNT];
avr_int_vector_t overflow; // overflow
avr_int_vector_t icr; // input capture