Timer Overflow 1

The Uzebox now have a fully functional emulator! Download and discuss it here.
CunningFellow
Posts: 1488
Joined: Mon Feb 11, 2013 8:08 am
Location: Brisbane, Australia

Timer Overflow 1

Post by CunningFellow »

Howdy,

I am working on a new video mode for Tempest.

I am having a bit of a problem. When I run the code in the AVR simulator it runs OK. In the emulator it seems that the timer overflow interrupt is not happening.

Does the AVR core in UzeEm not implement interrupts apart from OC1A, OC1B ?
CunningFellow
Posts: 1488
Joined: Mon Feb 11, 2013 8:08 am
Location: Brisbane, Australia

Re: Timer Overflow 1

Post by CunningFellow »

Well - I think I have answered my own question by looking at David Ethertons source code.
uzem source snippet 1
uzem source snippet 1
uzemints01.png (1.21 KiB) Viewed 7165 times
uzem source snippet 2
uzem source snippet 2
uzemints02.png (2.57 KiB) Viewed 7168 times
Looks like the timer overflow int is not there.

I think even a c-challenged halfwit like myself could probably work out how to add the function. However I only have one computer and I can't install Visual Studio on it without breaking things.

I might see if my little 1.3ghz laptop can cope with it. Else I will just have to fly blind.
CunningFellow
Posts: 1488
Joined: Mon Feb 11, 2013 8:08 am
Location: Brisbane, Australia

Re: Timer Overflow 1

Post by CunningFellow »

And I see there is newer source code on the google code bit.

It still does not have the overflow interrupt but seems better layed out and easier to fix up.

I am just downloading VS2005-express to try install on the old laptop. On my internet connection it should have downloaded the ISO in just a day or two.
User avatar
uze6666
Site Admin
Posts: 4821
Joined: Tue Aug 12, 2008 9:13 pm
Location: Montreal, Canada
Contact:

Re: Timer Overflow 1

Post by uze6666 »

As you found out, the emulator implements just the bare minimum to emulate the Uzebox kernel requirements of the time. It's been cleaned up a few times, lately by myself to add timer1b interrupt. If you feel confortable to add the functionality, go for it! Btw, VC++ is not used anymore to maintain uzem but GCC.
CunningFellow
Posts: 1488
Joined: Mon Feb 11, 2013 8:08 am
Location: Brisbane, Australia

Re: Timer Overflow 1

Post by CunningFellow »

OK - did the GCC thing and can compile it now

I am just not smart enough to work it out :(

I added into avr8::updatehardware

Code: Select all

		if (TCNT1 > (0xFFFF - cycles))
		{
			if (TIMSK1 & TOIE1)
			TIFR1|=TOV1; //overflow
		}
and

Code: Select all

		}else if (TIFR1 & TOV1){

			TIFR1&= ~TOV1; //clear TOV1 flag
			trigger_interrupt(TIMER1_OVF);
		}
The #defines where already in place.

All that happens now is that I get a ticking sound when the code does not run.

I suspect it may be something to do with how the emulator works out video from the line not far below that says

Code: Select all

if (scanline_count >= 0 && current_cycle < 1440)
User avatar
uze6666
Site Admin
Posts: 4821
Joined: Tue Aug 12, 2008 9:13 pm
Location: Montreal, Canada
Contact:

Re: Timer Overflow 1

Post by uze6666 »

I'm looking into it...couple questions:

1)Sorry if I ask again, did you explain what's the trick with the overflow of timer1, could help me understand some things. Seeing the code could help too.
2)Do you have a HEX file that works that I can use to test?
3)Do you actually need to trigger the interrupt or just have the flag set?
4)Are you changing the operation mode of timer1 so it can count up to 0xffff?
CunningFellow
Posts: 1488
Joined: Mon Feb 11, 2013 8:08 am
Location: Brisbane, Australia

Re: Timer Overflow 1

Post by CunningFellow »

uze6666 wrote:1)Sorry if I ask again, did you explain what's the trick with the overflow of timer1, could help me understand some things. Seeing the code could help too.
I am using Timer1 to end the pixel loop. Because OC1A and OC1B interrupts are already in use I am using OVF1 as a pseudo timer interrupt.

This is the code just before "Render_Line" is called.

Code: Select all

	ldi	ZL, 0x01					; turn of CTC mode
	sts	_SFR_MEM_ADDR(TCCR1B),ZL

	ldi ZL, (1<<TOV1)				; clear any pending timer1_ovf int
	sts _SFR_MEM_ADDR(TIFR1),ZL

	ldi	r16, 0xE5					; load 0xFFFF - (32bytes * 8Pixels * 5clocks_per_pixel) - overhead
	ldi	r17, 0xFA
	sts _SFR_MEM_ADDR(TCNT1H), r17	; This will make TOVF1 trigger on the 3rd last instruction
	sts _SFR_MEM_ADDR(TCNT1L), r16	; of the render loop

	lds r3, _SFR_MEM_ADDR(TIMSK1)   ; save the state of the timer int mask register in R3

	ldi	ZL, (1<<TOIE1)				; enable the timer overflow interrupt
	sts _SFR_MEM_ADDR(TIMSK1),ZL

	sei								; global enable interrupts.

 	rjmp render_tile_line_hires 	; JUMP to render_tile_line
Then the pixel_loop does not need the counter or compare/branch_back. Here is my dumb test pixel_loop that should just draw white stripes.

Code: Select all

1:
	ldi r17, 0x00			; Pixel 0
	mov r2,r17						
	out _SFR_IO_ADDR(DATA_PORT),r2	
	nop
	nop

	ldi r17, 0xFF			; Pixel 1
	mov r2,r17						
	out _SFR_IO_ADDR(DATA_PORT),r2
	nop
	nop

	ldi r17, 0x00			; Pixel 2
	mov r2,r17						
	out _SFR_IO_ADDR(DATA_PORT),r2
	nop
	nop

	ldi r17, 0xFF			; Pixel 3
	mov r2,r17						
	out _SFR_IO_ADDR(DATA_PORT),r2
	nop
	nop

	ldi r17, 0x00			; Pixel 4
	mov r2,r17						
	out _SFR_IO_ADDR(DATA_PORT),r2
	nop
	nop

	ldi r17, 0xFF			; Pixel 5
	mov r2,r17						
	out _SFR_IO_ADDR(DATA_PORT),r2
	nop
	nop

	ldi r17, 0x00			; Pixel 6
	mov r2,r17						
	out _SFR_IO_ADDR(DATA_PORT),r2
	nop
	nop

	ldi r17, 0xFF			; Pixel 7
	mov r2,r17						
	out _SFR_IO_ADDR(DATA_PORT),r2
	rjmp 1b				; Go back always - Timer OVF will end the loop when needed

herez1:
	rjmp	herez1
And after the interrupt ends I am restoring TCNT1 back to what it should have been after so many clocks

Code: Select all

TIMER1_OVF_vect:

	clr r0
	out _SFR_IO_ADDR(DATA_PORT),r0		; output black colour after visable area

	ldi	r16, 0xEB 						; restore TCNT to 0x06EB which is what
	ldi r17, 0x06						; it would have been at this spot if we
	sts _SFR_MEM_ADDR(TCNT1H), r17		; where a vanilla pixel loop
	sts _SFR_MEM_ADDR(TCNT1L), r16

	sts _SFR_MEM_ADDR(TIMSK1),r3		; Restore TimerMask to what it was
	ldi	ZL, 0x09
	sts	_SFR_MEM_ADDR(TCCR1B),ZL		; Set Timer1 back to CTC_A mode

	pop		r19							; Take the RETI return address of the
	pop		r19							; stack (we dont want to return to there)

	; cli

	WAIT 	r19,129						; Extra Cycles becuase 256 pixels	

 	dec 	r10							; Check to see if all lines rendered
	breq 	text_frame_end
uze6666 wrote:2)Do you have a HEX file that works that I can use to test?
Not one I know works. I only have UzEm and the AVR simulator. No real hardware to test on.
uze6666 wrote:3)Do you actually need to trigger the interrupt or just have the flag set?
As shown above I actually trigger interrupt to end the pixel_loop. During the pixel loop TCNT is nothing like it would be on a normal pixel render loop and I think that might be what is breaking things.
uze6666 wrote:4)Are you changing the operation mode of timer1 so it can count up to 0xffff?
Yes. And then changing it back to CTC mode afterwards.

I have included my project directory in the zip file. It seems to do what I expect it to in the AVR-Simulator in AVR-Studio. In UzEm it only produced the white stripes I expect if I put in the DEC/BRNE to end the loop.
Attachments
VectorDemo.zip
(154.61 KiB) Downloaded 409 times
CunningFellow
Posts: 1488
Joined: Mon Feb 11, 2013 8:08 am
Location: Brisbane, Australia

Re: Timer Overflow 1

Post by CunningFellow »

Found my problem.

I have now updated the emulator to support Timer1_OVF

Full steam ahead now.
User avatar
uze6666
Site Admin
Posts: 4821
Joined: Tue Aug 12, 2008 9:13 pm
Location: Montreal, Canada
Contact:

Re: Timer Overflow 1

Post by uze6666 »

Now I understand and its a very clever trick! :ugeek: Never thought about using interrupts to get out of loops. I can see a couple place were this could come in handy. :D

Btw, I commited the changes to SVN. New version of uzem is V1.16. I improved the logic to account for the fact that CTC and normal doesn't work the same and wont triggers interrupts under the same conditions. Should still be compatible with your code. Let me know if not.
CunningFellow
Posts: 1488
Joined: Mon Feb 11, 2013 8:08 am
Location: Brisbane, Australia

Re: Timer Overflow 1

Post by CunningFellow »

As long as you are already counting clock cycles and know if the interrupt is going to fall on a 1,2 or 3 clock instruction you don't need to "realign" for latency afterwards.

If you look in the tempest thread you will see the render loop there. You save a clock cycle or two by not having to keep count. When I have to get 8 x 5 colour pixels out in 40 clock cycles, every clock cycle counts.
Post Reply