Timer interupt / pause command confilict

martini

New Member
I have a problem with a very simple program which demonstrates a problem with the pause command when interrupts are being used.

The first 3 lines enable a timer interrupt to be generated every 10ms (100Hz)
The main loop flashes a LED on and off every two seconds
The interrupt handler pulses output 3 each time and then re-enables the interrupts.

With the interrupts disables the LED flashes on and off every 2 seconds, HOWEVER, when the interrupts are enabled, the interrupt routine does just what I expect (output 0 is pulsed on/off every 10ms) but the main program loop stops working correctly.
The pause command no longer waits the 1 second, but drops out after approximately 5-10ms and does not wait the defined time. Changing the rate of the interrupt does help either.

Changing the length of the pause does not help either pause 100, pause 1000, pause 10000 all result in the same short delay.

Q1. Am I doing something wrong in the handling of interrupts that may be causing the timing of the pause command to fail?
Or
Q2. Is there a known bug or “feature” that causes this problem?

Many thanks,
Martin

Code:
Timer=$ffff			'set timer to generate interrupt on next timer overflow
settimer 65385  		'set timer frequency to 100hz
setintflags $80,$80		‘enable timer interrupt

main:	
	high 0			'turn led on
	pause 1000		'wait 1 second
	low 0			'turn led off
	pause 1000		'wait 1 second
	goto main

	
Interrupt:	
	high 3				'set output3 high
	low 3				'set output3 low
	toflag = 0			'clear the timer overflow flag
	timer = $ffff			'initialise timer to interupt on next count
	setintflags $80,$80		'enable the timer interrupt
     	return 				‘return
 

boriz

Senior Member
Although I have never tried this, my guess would be that the PAUSE routine is being interrupted as you would expect, but when control is returned to the main program it resumes at the instruction following the PAUSE.

If this is the case, one workaround would be to dispense with PAUSE altogether and increment a variable every time the interrupt is triggered and test the variable inside the main loop for a value of approximately 200 (10mS * 200 = 2 seconds).

Or another possibility would be to use PWMOUT to generate your 100hz signal. This works in the background and should not significantly effect PAUSE commands. Some tweaking will be required to get such a low frequency from PWMOUT, but it is possible.
 

martini

New Member
Yes, I've already thought of your suggestion of incrementing a variable but in my real application, I will be changing the interupt rate dynamically thus making it very difficult to calculate delay.

What really puzzle me is that if I slow the interrupt down to 1 pulse in 20 seconds the main loop still fails.

I've also tried the pwm output but the minimum frequncy is 3.9Khz - far too fast.

I guess I'll have to waste another variable and build a new pause command based on a 10ms delay loop.
 

boriz

Senior Member
There is a POKE you can use to prescale the PWMOUT frequency. I'll see if i can find it.

(I bet i have to log in again when i come back. It's starting to piss me off.)
 

boriz

Senior Member
Ok. Found it.

POKE $12, $05 'provides a pre-scale of 1:4
POKE $12, $06 'provides a pre-scale of 1:16

REF

This can get PWMOUT down to around 250Hz. For lower frequencies there is another POKE that will slow the whole processor down. Can’t find it at the moment.
 

RBruceM

New Member
Thanks, Martini, for this post. I found it today when writing a polled interupt routine for the hardware serial inputs on the 40x after finding in the notes section of the setint command section of the Picaxe Basic manual, page 147, it says:

"In the case of interupted pause, wait, play or tune command, any remaining time delay is ignored and the program continues with the next program line"

I then searched the forum in hopes that this was a mistake- left over from an earlier version and perhaps not true for the 40X1

This sure makes for a lot of work to repair timing in my main program, and I hope this will be fixed someday. Having the pause extended slightly by a short interupt routine would be big improvement.

So I guess like Martini I will be replacing all my pause's with subroutine calls to a for- next loop with a bunch of short pauses. Bummer, but so glad I learned about it now before testing it.

Best Wishes,
Bruce
 

martini

New Member
Thanks for finding the reference about the pause command and interrupts in the manual - It seems a bit odd to do this.

A question to Technical
Are there any plans to change the way that pause functions when an interrupt occurs? It wouild be really usefull if it continued with the remaining part of the pause after the return from interrupt.
 

hippy

Technical Support
Staff member
"In the case of interupted pause, wait, play or tune command, any remaining time delay is ignored and the program continues with the next program line"

I then searched the forum in hopes that this was a mistake- left over from an earlier version and perhaps not true for the 40X1

This sure makes for a lot of work to repair timing in my main program, and I hope this will be fixed someday. Having the pause extended slightly by a short interupt routine would be big improvement.
That it's 'broken and needs fixing' is a tough call to make. The pragmatic outcome will probably be that operation remains as it is to ensure execution compatibility across the entire PICAXE range. There are also technical reasons; an interrupt would have to know which command it were in and store the runtime state ready for when the interrupt finished, then come back to it. This would add a lot of firmware overhead. The 'abort current command on interrupt then allow the main interpreter loop to handle the interrupt' is far simpler but does have the consequences you've discovered.

For some programs extending the Pause time would be just as catastrophic to operation as truncating it is so there's no easy answer. The For-Pause-Next loop minimises the amount of time lost whereas there's no easy way to tell the pause had been extended.

For the X1 and X2 parts, an alternative is for a pause routine to start a timer and then only return when the timer's value exceeds some particular value. It should be possible to configure so the 'timer' variable goes from 0 to 1 when the time is up.
 

boriz

Senior Member
When I used to write games, I would often time everything something like this:

Code:
(pseudocode) 
Player_timer=player_rate
Alien_timer=alien_rate
Screen_timer=screen_rate
DO
	Decrement player_timer
	Decrement alien_timer
	Decrement screen_timer
	IF  player_timer=0 THEN
		player_timer=player_rate
		Gosub update_player

	IF alien_timer=0 THEN
		Alien_timer=alien_rate
		Gosub update_alien

	IF screen_timer=0 THEN
		Screen_timer=screen_rate
		Gosub update_screen
LOOP
This kind of approach lends itself nicely to operating several independently timed routines that all operate at a multiple of the main loop time. No interrupt required. A variation of this sort of thing might work for you.
 

RBruceM

New Member
I don't like this implementation (pause discontinued on interrupt); no experienced programmer of any sort would expect that of an interrupt routine. To have pause timing slightly affected by a short polled interrupt routine would be more useful (and what is expected) in the majority of cases...then if someone needed more precise timing, they could resort to timer tricks.

I think it limits applications for the Picaxe; in the future I'd go with something else (compiler and the same PIC chip) when I need fairy good timing and interupts. Which is a shame because I think the Picaxe chips are such a great product, and I'd use them where ever I could. But having an interupt driven routine of some sort while needing reasonably stable timing in the main program is awfully common.

For example, I selected the 40x1 picaxe for a "public" project (group of us nasty Yanks) to add an engine controller to Listeroid copies of the venerable 1929 British Lister CS diesel engine, just because of the addition of the hardware serial input with interupts capability.

Anyway, as the picaxe chips continue to become more sophisticated, and take on more sophisicated tasks (which is surely going to be true) that would be my suggestion.

The only other thing that really needs enhancement is the symbol statement needs to include the additional ports. This is not as serious as the interrupt ruins pause situation.

Thanks very much for the timer-pause suggestion, Hippy. That might work for my present application as an alternate p_ause subroutine.

Bruce M
retired EE (Computer Science)
 
Last edited:

RBruceM

New Member
I found that I had no conflict using the timer as a pause subroutine. Thanks again Hippy for the suggestion.

Not such a great solution if the timer routine is the interupt routine, and you still need some sort or reasonably accurate delays in your main program. In that case a for next loop of smaller pauses might do the trick if the interupts weren't coming too fast and frequently.

For someone who might need it, here's my alternate pause routine. At 4MHz it can delay up to 4.19 seconds. Easy to also make larger time increments by testing the timer value (major ticks) in the loop instead.

'subroutine alt_pause - put timer preload in w0
alt_pause:
timer=65535
settimer w0
time_loop:
if toflag=0 then time_loop
return
 
Last edited:
Top