BBC BASIC for Windows
Programming >> BBC BASIC language >> Switching a TIMEr OFF and ON?
http://bb4w.conforums.com/index.cgi?board=language&action=display&num=1257112987

Switching a TIMEr OFF and ON?
Post by 19Grumpah42 on Nov 1st, 2009, 9:03pm

I wonder is there a clean way to let a user temporarily pause the operation of an ON TIME xxx RETURN interrupt, by disabling the timer pro tem. I can do 'ON TIME OFF" to pause it, but there is no 'ON TIME ON' command to restart the timer. I could put the definition of the TIMEr IRQ into a separate PROC (is this appreciated?) for re-use. I have also left the TIMEr ON and issued a ...

SYS "SetTimer", @hwnd%, 101, &FFFFFFFF, 0 :REM ca. infinite timer!

.. command, which does work, then reissue the original timer setting to "continue".

What's the best way to do this?
--Grahame
Re: Switching a TIMEr OFF and ON?
Post by admin on Nov 1st, 2009, 10:09pm

Quote:
What's the best way to do this?

I don't know that there's a "best" way. The way I usually do it is as follows:

Code:
      REM. Temporarily disable timer interrupt:
      ON TIME RETURN
      REM. Enable timer interrupt again:
      ON TIME PROCtime : RETURN 

I will leave as an exercise for the reader why one might prefer to use ON TIME RETURN rather than ON TIME OFF (it could make the difference between a program working and occasionally crashing).

If I don't receive the correct answer in a couple of days I will reveal all*, but that would be disappointing!

Richard.

*not in the nudity sense

Re: Switching a TIMEr OFF and ON?
Post by 19Grumpah42 on Nov 2nd, 2009, 02:52am

Thanks for the advise Richard. ON TIME RETURN it is.
My mug's speculation on your question might be that the empty RETURN leaves the timer IRQ untroubled, ticking away "silently" in the background; this sounds clean to me. However, perhaps it also serves as a way to flush the IRQ queue, if you were a naughty boy and had over-run your period performing your last procedure? I don't give much for that idea. MSDN say (I think) that you can issue a repeat SYS "SetTimer", @hwnd%, 101 ...... at any time, and it will just re-initialise that existing timer (here #101), so I don't see a problem there. By the way, is '101' a magic number for the BB4W TIMEr?

I have not used two simultaneous SYS timers on one @hwnd%, but I probably will, and I would then need to know how to hear them, since ON TIME does not have a timer handle. (anyone?)

It could be that some other foreground thread (e.g. a REPEAT .... UNTIL loop) might get coswobulated if you suddenly re-initialised the timer IRQ at some inappropriate stage in it? I use my IRQs just for setting a global flag -- which is never used LOCALly or as a passed parameter -- wherever I can figure that; in fact, I find the ability of an IRQ to modify a parameter used by another thread is quintessential to the way I 'design' things.

So, I think I give up Richard, quite gracefully I hope. You might choose to just expose a bit of the answer?
--Grahame
Re: Switching a TIMEr OFF and ON?
Post by obby on Nov 2nd, 2009, 07:40am

Maybe a ONTIME OFF at the 'wrong' moment e.g. when the ONTIME interrupt itself is triggered, could miss this resulting in crashing due to a corrupted return value?

Manuel
Re: Switching a TIMEr OFF and ON?
Post by admin on Nov 2nd, 2009, 08:10am

Quote:
By the way, is '101' a magic number for the BB4W TIMEr?

Yes, it's a 'magic number'.

Quote:
However, perhaps it also serves as a way to flush the IRQ queue

You're close, but not quite there.

Quote:
I have not used two simultaneous SYS timers on one @hwnd%, but I probably will, and I would then need to know how to hear them, since ON TIME does not have a timer handle.

Actually it does: the timer ID is in @wparam%. But really this sounds like the kind of thing TIMERLIB is intended for. Have you investigated that?

Richard.
Re: Switching a TIMEr OFF and ON?
Post by admin on Nov 2nd, 2009, 08:13am

Quote:
Maybe a ONTIME OFF at the 'wrong' moment e.g. when the ONTIME interrupt itself is triggered, could miss this resulting in crashing due to a corrupted return value?

Nice try, but it's not that. As Grahame guessed, it's got something to do with the event 'queue', but he hasn't worked out quite what.

Richard.
Re: Switching a TIMEr OFF and ON?
Post by Michael Hutton on Nov 2nd, 2009, 1:12pm

A timer will send a WM_TIMER message to the wndproc (the default message handling procedure). If you kill the timer with ON TIME OFF. You will cancel the TimerProc callback procedure address.

When you want to kill the timer you *may still have* a WM_TIMER message in the message queue waiting to be processed, but you have killed the TimerProc address so it will (probably) crash. So ON TIME RETURN will ensure that any messages left over will be exited gracefully, without a crash.

Michael
Re: Switching a TIMEr OFF and ON?
Post by admin on Nov 2nd, 2009, 2:16pm

Quote:
If you kill the timer with ON TIME OFF. You will cancel the TimerProc callback procedure address

ON TIME OFF doesn't kill the timer (the timer runs all the time, unless you stop it, because it's used for the flashing characters in MODE 7) and you can't "cancel the callback address" because it's queued as part of the event.

Quote:
When you want to kill the timer you *may still have* a WM_TIMER message in the message queue waiting to be processed, but you have killed the TimerProc address so it will (probably) crash.

Not quite, but you're definitely getting warm. Another hint: BB4W has its own private event queue quite separate from Windows' message queue.

Richard.

Re: Switching a TIMEr OFF and ON?
Post by 19Grumpah42 on Nov 2nd, 2009, 3:43pm

Thank you Richard. So we have a TIMER.LIB do we? I am on my way!
--Grahame
Re: Switching a TIMEr OFF and ON?
Post by 19Grumpah42 on Nov 2nd, 2009, 3:52pm

Well, so perhaps if you issued ON TIMER OFF while your

ON TIME PROC_handler :RETURN

was processing its PROC_handler, the ON TIME IRQ would have been received, but the ON TIME OFF would have cancelled the response before the RETURN could implement. So the 'notion' of the received IRQ would be sitting on some stack somewhere, with no way to clear it. The PROC_handler would run quite nicely, thank you, but it would -- quite unfairly, since it is a nice handler -- have left behind this irremovable entry on my mythical stack (somewhere).

Is that a bit closer?
--Grahame
Re: Switching a TIMEr OFF and ON?
Post by admin on Nov 2nd, 2009, 4:51pm

Quote:
Is that a bit closer?

I had better put you all out of your misery! What I was thinking of is that ON TIME OFF stops timer events entering BB4W's event queue whereas ON TIME RETURN causes events still to enter the queue, but to be discarded as they leave it.

Only in very exceptional circumstances will this make a difference, but despite the rarety it's as well to be aware of the possibility.

In fact this issue is alluded to in the docs, under 'Notes on the use of interrupts':

Quote:
The LOCAL forms of event trapping available in BBC BASIC for Windows version 5.00a and later (ON CLOSE LOCAL, ON MOUSE LOCAL, ON MOVE LOCAL, ON SYS LOCAL and ON TIME LOCAL) need special care. Because of the way events are queued it is possible that an event has occurred but has not yet been processed when the ON <event> LOCAL statement is executed. In that case the event may be processed by the previous ON <event> statement, if any. Similarly, a queued event may be processed by the ON <event> LOCAL statement even after the function or procedure in which it is contained has been exited. You should write your interrupt service routines to be tolerant of these possibilities.

Somebody mentioned the possibility of 'flushing' the event queue; neither ON TIME OFF nor ON TIME RETURN do that. The only way you could simulate that would be to provide a global switch affecting how the ON TIME handler behaves, for example:

Code:
      ON TIME IF OnTimeFlush% RETURN ELSE PROCtime:RETURN 


Richard.
Re: Switching a TIMEr OFF and ON?
Post by admin on Nov 2nd, 2009, 5:14pm

Quote:
I wonder is there a clean way to let a user temporarily pause the operation of an ON TIME xxx RETURN interrupt, by disabling the timer pro tem. I can do 'ON TIME OFF" to pause it, but there is no 'ON TIME ON' command to restart the timer.

Returning to the original subject, after the diversion via ON TIME RETURN, I should probably have originally suggested ON TIME LOCAL as one way of achieving your "disabling the timer pro tem". If you can arrange that the period for which you need to disable the timer corresponds to being inside a specific procedure or function, then you can achieve what you asked for directly:

Code:
      ON TIME do something : RETURN
      REM. Timer interrupts are active here....
      PROC_timer_disabled
      REM. Timer interrupts are active here too....
      END

      DEF PROC_timer_disabled
      ON TIME LOCAL RETURN
      REM. Timer interrupts are disabled
      REM. (apart from any already queued)....
      ENDPROC 

You may consider this nicer than the alternative of repeating the original ON TIME statement.

Richard.
Re: Switching a TIMEr OFF and ON?
Post by 19Grumpah42 on Nov 3rd, 2009, 3:34pm

Yes, that's cool.
--Grahame