simavr icon indicating copy to clipboard operation
simavr copied to clipboard

One-shot pulse generator doesn't work

Open MikePlayle opened this issue 7 years ago • 0 comments

I'm using a technique like this to generate pulses with controllable widths:

#define F_CPU 16000000UL

#include "avr_mcu_section.h"

AVR_MCU(F_CPU, "atmega32u4");
AVR_MCU_VCD_FILE("trace.vcd", 1);

#include <avr/io.h>

const struct avr_mmcu_vcd_trace_t _mytrace[] _MMCU_ = {
        { AVR_MCU_VCD_SYMBOL("DDRB"), .what = (void*)&DDRB, },
        { AVR_MCU_VCD_SYMBOL("PORTB"), .what = (void*)&PORTB, },
        { AVR_MCU_VCD_SYMBOL("TCNT1L"), .what = (void*)&TCNT1L, },
        { AVR_MCU_VCD_SYMBOL("TCNT1H"), .what = (void*)&TCNT1H, },
        { AVR_MCU_VCD_SYMBOL("OCR1AL"), .what = (void*)&OCR1AL, },
        { AVR_MCU_VCD_SYMBOL("OCR1AH"), .what = (void*)&OCR1AH, },
};

volatile int a = 0;

int main (void) {

        // Waveform mode = 14: count up from 0 to ICR1, then restart from 0

        TCCR1A = 0x82; // clear on compare match, set on top
        TCCR1B = 0x19; // run from CPU clock, no prescaler
        ICR1 = 0x3; // minimum the data sheet allows; doesn't really matter though
        TCCR1C = 0; // there isn't anything in this register anyway

        PORTB |= _BV(DDB5);
        DDRB |= _BV(DDB5);

        OCR1A = -1000;
        TCNT1 = -1001;

        for(;;) a = TCNT1;
}

The intention is that the timer will count up from -1000, wrap around to zero, and then count from 0 to 3 until the next pulse is triggered. This works on real hardware but I'm having trouble getting sensible results from it with simavr.

  1. With the code as written above, the timer appears to start counting upwards from zero more or less immediately, and it doesn't reset when it gets to 3 as it should.
  2. If I move the write to ICR1 before the write to TCCR1A I get slightly more sensible behaviour, but the timer still appears to 'jump' straight to zero rather than counting up to 0xFFFF first.

I took a look at the code and the failure to stop at 3 seems to be caused by p->tov_top not being updated when ICR1 is written, but the 'jumping' to zero looks more deeply rooted. Does simavr support operating the timers outside their 'usual' counting range like this?

MikePlayle avatar Jan 31 '18 21:01 MikePlayle