simavr
simavr copied to clipboard
One-shot pulse generator doesn't work
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.
- 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.
- If I move the write to
ICR1before the write toTCCR1AI 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?