simavr icon indicating copy to clipboard operation
simavr copied to clipboard

avr_timer.c: compare/overflow clear/set modes do not work right when hooked to an ioport

Open JarrettBillingsley opened this issue 5 years ago • 0 comments

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).

JarrettBillingsley avatar Mar 31 '19 04:03 JarrettBillingsley