simavr
simavr copied to clipboard
avr_timer.c: compare/overflow clear/set modes do not work right when hooked to an ioport
I have some ATTiny85 code which sets up TIM1 in PWM mode such that it sets PB4 on overflow and clears it on COMPB:
; Output on PB4 (sound) and PB1 (debugging!)
ldi temp, _BV(DDB4) | _BV(DDB1)
out IO(DDRB), temp
; Set compare unit values
ldi temp, 0
out IO(OCR1B), temp
ldi temp, 255
out IO(OCR1A), temp
out IO(OCR1C), temp
; Enable PWM mode on timer 1
ldi temp, _BV(PWM1B) | _BV(COM1B1)
out IO(GTCCR), temp
; Enable timer overflow interrupt
in temp, IO(TIMSK)
ori temp, _BV(TOIE1)
out IO(TIMSK), temp
; Hardware bug requires COM1A0 to be enabled as well.
; "2" means clock timer with CK/2 (32KHz sample rate)
ldi temp, _BV(PWM1A) | _BV(COM1A1) | _BV(COM1A0) | 2
out IO(TCCR1), temp
I then change OCR1B
in the timer overflow ISR to change the width of the pulse being output. Pretty tutorial-standard stuff. It works in hardware, but not in simavr. I think I figured out why:
In avr_timer.c
, in the functions avr_timer_comp
and avr_timer_comp_on_tov
, the cases for avr_timer_com_clear
and avr_timer_com_set
never attach the AVR_IOPORT_OUTPUT
flag to the values being raised. I hacked AVR_IOPORT_OUTPUT |
into those four function calls, and now it works fine.
That's probably not the right way to do it, but I'm not sure what is (I notice the avr_timer_com_toggle
case does something more complex).