From a8c5b5a9e3b3461e04c793c56359c358e8efd607 Mon Sep 17 00:00:00 2001 From: Kyrylo Yatsenko Date: Tue, 14 Oct 2014 16:49:12 +0300 Subject: [PATCH] Enhance emulation of PWM mode - Clear/set output pin on TOP when OCRnX is in clear/set mode, previously it was changed only on TCNT=OCRnX - Call PWM irq for OCRnB even when TOP is OCRnA --- simavr/sim/avr_timer.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/simavr/sim/avr_timer.c b/simavr/sim/avr_timer.c index 7d4d715..6e0b17e 100644 --- a/simavr/sim/avr_timer.c +++ b/simavr/sim/avr_timer.c @@ -86,6 +86,27 @@ static avr_cycle_count_t avr_timer_comp(avr_timer_t *p, avr_cycle_count_t when, p->comp[comp].comp_cycles ? when + p->comp[comp].comp_cycles : 0; } +static void avr_timer_comp_on_tov(avr_timer_t *p, avr_cycle_count_t when, uint8_t comp) +{ + avr_t * avr = p->io.avr; + + // check output compare mode and set/clear pins + uint8_t mode = avr_regbit_get(avr, p->comp[comp].com); + avr_irq_t * irq = &p->io.irq[TIMER_IRQ_OUT_COMP + comp]; + + switch (mode) { + case avr_timer_com_normal: // Normal mode + break; + case avr_timer_com_toggle: // toggle on compare match => on tov do nothing + break; + case avr_timer_com_clear: // clear on compare match => set on tov + avr_raise_irq(irq, 1); + break; + case avr_timer_com_set: //set on compare match => clear on tov + avr_raise_irq(irq, 0); + break; + } +} static avr_cycle_count_t avr_timer_compa(struct avr_t * avr, avr_cycle_count_t when, void * param) { @@ -117,11 +138,12 @@ static avr_cycle_count_t avr_timer_tov(struct avr_t * avr, avr_cycle_count_t whe for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) { if (p->comp[compi].comp_cycles) { - if (p->comp[compi].comp_cycles < p->tov_cycles) + if (p->comp[compi].comp_cycles < p->tov_cycles) { + avr_timer_comp_on_tov(p, when, compi); avr_cycle_timer_register(avr, p->comp[compi].comp_cycles, dispatch[compi], p); - else if (p->tov_cycles == p->comp[compi].comp_cycles && !start) + } else if (p->tov_cycles == p->comp[compi].comp_cycles && !start) dispatch[compi](avr, when, param); } } @@ -294,8 +316,8 @@ static void avr_timer_write_ocr(struct avr_t * avr, avr_io_addr_t addr, uint8_t case avr_timer_wgm_pwm: 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)); } + 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 (oldv != _timer_get_comp_ocr(avr, comp)) -- 2.39.5