Commit a8c5b5a9e3b3461e04c793c56359c358e8efd607
authorKyrylo Yatsenko <kyrylo.yatsenko@hedrok.org>
Tue, 14 Oct 2014 13:49:12 +0000 (16:49 +0300)
committerKyrylo Yatsenko <kyrylo.yatsenko@hedrok.org>
Tue, 14 Oct 2014 16:43:59 +0000 (19:43 +0300)
- 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

index 7d4d715da30dfb715558ee970cdd22cfafb3ba6b..6e0b17e0917730a0a582c8e7a697f0945d90b91e 100644 (file)
@@ -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))