• Print

Author Topic: ON TIMER, STOP - remembered events [fixed* (refer to final replies)]  (Read 433 times)

MajorApollo

  • Newbie
  • *
  • Posts: 10
ON TIMER, STOP - remembered events [fixed* (refer to final replies)]
« on: March 16, 2013, 09:47:04 AM »
Hi,

This is my first post! After a brief period I am now a registered member! I hope that I may be able to contribute in the future, but now have a question regarding the TIMER system specifically regarding the below statement.

Quote from: qb64 wiki
TIMER STOP disables timer event trapping. When an event occurs while stopped, it is remembered. If timer events are turned back on later, any remembered events are immediately executed.

What what I can make of that is that you can use the TIMER STOP command and every call/gosub it was supposed to make during its suspension would be executed once it was resumed. Based on the code below in which a timer is invoked that ads 1 to the "a" variable every 2 seconds that can be paused by pressing "P" then after some time by resuming the counter by pressing "R" that each 2 seconds would be included in the "If timer events are turned back on later, any remembered events are immediately executed" then if you paused it for 10 second then resumed it a would have a=a+1 called 5 times if resumed after 10 seconds. At least this is how I seem to understand it, but I do not exactly know what I am doing wrong.

Code: [Select]
t1 = _FREETIMER
ON TIMER(t1, 2) GOSUB Counter ' add up gosub calls
TIMER(t1) ON
status$ = "ON" 'status of timer
dur$ = TIME$

DO

    LOCATE 1, 1: PRINT "Time Running:"; tcount; " / "; TIME$
    LOCATE 2, 1: PRINT "Total Timer/Gosub Calls:"; a
    LOCATE 3, 1: PRINT "Counter Status: "; status$
    PRINT
    PRINT "(P)ause / (R)esume / (Q)uit"

    IF dur$ = TIME$ THEN ELSE tcount = tcount + 1: dur$ = TIME$

    i$ = UCASE$(INKEY$)

    'pause the timer
    IF i$ = "P" THEN TIMER(t1) STOP: status$ = "PAUSED"

    'resume the timer
    IF i$ = "R" THEN TIMER(t1) ON: status$ = "ON    "

LOOP UNTIL i$ = "Q"
END

Counter:
a = a + 1
RETURN
« Last Edit: April 04, 2013, 05:15:25 AM by Galleon »

OlDosLover

  • Hero Member
  • *****
  • Posts: 3860
  • OlDosLover
    • Email
Re: ON TIMER, STOP - remembered events
« Reply #1 on: March 16, 2013, 07:42:32 PM »
Hi all,
    Welcome to the forum MajorApollo. Excellent question and presented very well also. Hmm some of your post i cannot explain. The only thing i do remember is that continual calling of the time may lag the computer out. From the wiki:
Quote
Returns the present computer time in following hh:mm:ss 24 hour format: "19:20:33"
Uses 2 colon (:) separators between hours, minutes and seconds
Hour values range from "00" to "23" starting from midnite.
Minutes and seconds range from "00" to "59"
Continuous TIME$ calls may lag if a QBasic program is minimized to the taskbar!

    You state that
Quote
What what I can make of that is that you can use the TIMER STOP command and every call/gosub it was supposed to make during its suspension would be executed once it was resumed
. I read that differently. Unless something else is "counting" and keeping a record , how would we know? It seems safe to assume that if the delay was greater than the value of the timer it would add one for the total time of the delay.
    What puzzled me the most was when we resumed your program the counter STOPPED counting! So i rewrote it to use a second timer to record the time and it seems to work better. In all of my experiments (10,20,20 sec delays) all i ever got was a max of 2 added to the counter.
Code: [Select]
REM
DEFLNG A-Z


t1 = _FREETIMER
ON TIMER(t1, 2) GOSUB Counter ' add up gosub calls
TIMER(t1) ON

t2 = _FREETIMER
ON TIMER(t2, 1) GOSUB GetTime ' update onscreen clock
TIMER(t2) ON

status$ = "ON" 'status of timer
dur$ = TIME$

DO
  _LIMIT 30
  LOCATE 1, 1: PRINT "Time Running:"; tcount; " / "; NowTime$
  LOCATE 2, 1: PRINT "Total Timer/Gosub Calls:"; a
  LOCATE 3, 1: PRINT "Counter Status: "; status$
  PRINT
  PRINT "(P)ause / (R)esume / (Q)uit"

  i$ = UCASE$(INKEY$)

  'pause the timer
  IF i$ = "P" THEN TIMER(t1) STOP: status$ = "PAUSED"

  'resume the timer
  IF i$ = "R" THEN TIMER(t1) ON: status$ = "ON    "
  _DISPLAY
LOOP UNTIL i$ = "Q"
END

Counter:
a = a + 1
RETURN

GetTime:
NowTime$ = TIME$
tcount = tcount + 1
RETURN
OlDosLover.


OlDosLover

  • Hero Member
  • *****
  • Posts: 3860
  • OlDosLover
    • Email
Re: ON TIMER, STOP - remembered events
« Reply #2 on: March 16, 2013, 07:54:02 PM »
Hi all,
    I removed the ability of the user to pause and made the program do it automatically. The results are interesting!
Code: [Select]
REM
DEFLNG A-Z


t1 = _FREETIMER
ON TIMER(t1, 2) GOSUB Counter ' add up gosub calls
TIMER(t1) ON

t2 = _FREETIMER
ON TIMER(t2, 1) GOSUB GetTime ' update onscreen clock
TIMER(t2) ON

status$ = "ON" 'status of timer
dur$ = TIME$

DO
  _LIMIT 30
  SELECT CASE tcount
    CASE 10 TO 20
      TIMER(t1) STOP: status$ = "PAUSED"
    CASE 30 TO 50
      TIMER(t1) STOP: status$ = "PAUSED"
    CASE 60 TO 90
      TIMER(t1) STOP: status$ = "PAUSED"
    CASE 120
      END
    CASE ELSE
      TIMER(t1) ON: status$ = "ON    "
  END SELECT
  LOCATE 1, 1: PRINT "Time Running:"; tcount; " / "; NowTime$
  LOCATE 2, 1: PRINT "Total Timer/Gosub Calls:"; a
  LOCATE 3, 1: PRINT "Counter Status: "; status$
  PRINT
  PRINT " (Q)uit"

  i$ = UCASE$(INKEY$)

  _DISPLAY
LOOP UNTIL i$ = "Q"
END

Counter:
a = a + 1
RETURN

GetTime:
NowTime$ = TIME$
tcount = tcount + 1
RETURN
OlDosLover.

RhoSigma

  • Jr. Member
  • **
  • Posts: 75
  • 4 * 1.0079 = 4.0026
    • Email
Re: ON TIMER, STOP - remembered events
« Reply #3 on: March 17, 2013, 07:00:15 AM »
Hi all,

in my opinion the ON TIMER construct as implemented in QB64 is absolutly useless at all, as long timer events does not break a SLEEP, _DELAY or _LIMIT, as it's done by QBasic.

The timer event needs to be an interrupt like event, which needs to be processed immediately, and not when the program just have time to process it.

Try this, see comments in the code:
Code: [Select]
t1 = _FREETIMER
ON TIMER(t1, 0.2) GOSUB Counter 'should count 5x per second, hence program should end after 1 second

PRINT TIMER 'start timer
a% = 0
TIMER(t1) ON
DO
    '-----
    '-- uncommenting any of the below delay options will screw up the timer,
    '-- hence ON TIMER is absolutly useless in QB64
    '-----
    'SLEEP 'does never end at all (use the X to close the program)
    'SLEEP 1  'end after 5 seconds
    '_DELAY 1 'end after 5 seconds
    '_LIMIT 1 'end after 5 seconds
    '-----
LOOP UNTIL a% = 5 'end program, if this count is reached (should be 1 second)
TIMER(t1) OFF
PRINT TIMER 'end timer

TIMER(t1) FREE
END

Counter:
a% = a% + 1
RETURN

Regards, RhoSigma
Download archives of my QB64 stuff:
Polygon functions: http://rhosigma-cw.net/down/GfxDemos.zip
Screen savers: http://rhosigma-cw.net/down/ScrSavers.zip
Libraries collection: http://rhosigma-cw.net/down/QB64Library.zip (extract into the QB64 folder, a new sub-folder "QB64Library" is created)

OlDosLover

  • Hero Member
  • *****
  • Posts: 3860
  • OlDosLover
    • Email
Re: ON TIMER, STOP - remembered events
« Reply #4 on: March 17, 2013, 07:44:21 AM »
Hi all,
    Same results with SDL. Here's a version that takes 10 seconds!
Code: [Select]
t1 = _FREETIMER
ON TIMER(t1, 0.1) GOSUB Counter 'should count 5x per second, hence program should end after 1 second

PRINT "Start Timer ="; TIMER 'start timer
PRINT "Start Time ="; TIME$
a% = 0
TIMER(t1) ON
DO
  '-----
  '-- uncommenting any of the below delay options will screw up the timer,
  '-- hence ON TIMER is absolutly useless in QB64
  '-----
  'SLEEP 'does never end at all (use the X to close the program)
  SLEEP 1 'end after 5 seconds
  '_DELAY 1 'end after 5 seconds
  '_LIMIT 1 'end after 5 seconds
  '-----
LOOP UNTIL a% = 10 'end program, if this count is reached (should be 1 second)
TIMER(t1) OFF
PRINT "End Timer ="; TIMER 'end timer
PRINT a%
PRINT "End Time ="; TIME$
TIMER(t1) FREE
END

Counter:
a% = a% + 1
RETURN
Perhaps somehow the one second is being multiplied by the one tenth of a second!
OlDosLover
« Last Edit: March 17, 2013, 08:30:17 AM by OlDosLover »

OlDosLover

  • Hero Member
  • *****
  • Posts: 3860
  • OlDosLover
    • Email
Re: ON TIMER, STOP - remembered events
« Reply #5 on: March 17, 2013, 07:48:51 AM »
Hi all,
    Another version that takes 100 seconds.
Code: [Select]
t1 = _FREETIMER
ON TIMER(t1, 0.01) GOSUB Counter 'should count 5x per second, hence program should end after 1 second

PRINT "Start Timer ="; TIMER 'start timer
PRINT "Start Time ="; TIME$
a% = 0
TIMER(t1) ON
DO
  '-----
  '-- uncommenting any of the below delay options will screw up the timer,
  '-- hence ON TIMER is absolutly useless in QB64
  '-----
  'SLEEP 'does never end at all (use the X to close the program)
  SLEEP 1 'end after 5 seconds
  '_DELAY 1 'end after 5 seconds
  '_LIMIT 1 'end after 5 seconds
  '-----
LOOP UNTIL a% = 100 'end program, if this count is reached (should be 1 second)
TIMER(t1) OFF
PRINT "End Timer ="; TIMER 'end timer
PRINT a%
PRINT "End Time ="; TIME$
TIMER(t1) FREE
END

Counter:
a% = a% + 1
RETURN
OlDosLover.

RhoSigma

  • Jr. Member
  • **
  • Posts: 75
  • 4 * 1.0079 = 4.0026
    • Email
Re: ON TIMER, STOP - remembered events
« Reply #6 on: March 17, 2013, 08:14:52 AM »
Hi,

Quote from: OlDosLover on March 17, 2013, 07:44:21 AM
...Perhaps somehow the one second is being multiplied by the one tenth of a second!...

no, for me it seems the timer event simply isn't checked until the delay has elapsed, hence the timer threshold is always >= current delay. Probably its because of the way it is checked in the produced C++ source code, if I look on it, it seems events (doesn't matter if timer or other events) are checked after every QB64 instruction, which means, that even regular (not only SLEEP, DELAY, LIMIT) will screw up with the timer, as every instruction needs time to be executed, hence delay the program flow.

That's why I say events have to be processed in an interrupt like manner, hence in realtime, not waiting until the next time the program is ready to check for any events that may have happened in the meantime.
Download archives of my QB64 stuff:
Polygon functions: http://rhosigma-cw.net/down/GfxDemos.zip
Screen savers: http://rhosigma-cw.net/down/ScrSavers.zip
Libraries collection: http://rhosigma-cw.net/down/QB64Library.zip (extract into the QB64 folder, a new sub-folder "QB64Library" is created)

OlDosLover

  • Hero Member
  • *****
  • Posts: 3860
  • OlDosLover
    • Email
Re: ON TIMER, STOP - remembered events
« Reply #7 on: March 17, 2013, 08:27:30 AM »
Hi all,
    I'm not disagreeing with you. From the wiki:
Quote
QBasic Information
In Qbasic the INTEGER seconds' parameter can be from 1 to 86400 seconds(one day).
A TIMER ON statement must be made before an ON TIMER event is enabled in QB or QB64.
TIMER STOP remembers previous events when enabled by a TIMER ON statement and the ON TIMER statement(s) may be executed immediately if a timer event has occurred.
TIMER OFF disables timer event trapping. Events will not be remembered in a subsequent ON TIMER statement.
ON TIMER events will interrupt a SLEEP call and RETURN to running program procedures.
Qbasic can only use one TIMER event at a time and all TIMER code MUST be in the main code.

QB64 Specific Information
Can use multiple numbered timer events and SINGLE floating point second values down to one millisecond(.001).
MUST use the _FREETIMER function to assign free timer numbers. Use specific variables or an array to store the TIMER values.
If the TIMER number is omitted or ON TIMER(0, seconds!) is used, the TIMER used is the base timer. The base TIMER cannot be freed! No number reference can also be used to keep QB64 compatible with older Qbasic code.
GOSUB or SUB procedures are allowed to be referenced, however CALL CANNOT be used.
SUB parameter values are passed by value and should be SHARED or literal values!
Specific TIMER events can be turned on, suspended, turned off or freed using TIMER(n) ON, STOP, OFF or FREE.
Use TIMER(n) FREE to release a timer event after it has been turned off or is no longer used.
QB64 allows TIMER statements to also be inside of SUB and FUNCTION procedures.
Quote
Does not currently interrupt SLEEP or _DELAY calls.
$CHECKING:OFF can disable QB64 event checking. Use it ONLY with errorless code that needs every CPU cycle!
    The behaviour is noted in the wiki.
OlDosLover.

RhoSigma

  • Jr. Member
  • **
  • Posts: 75
  • 4 * 1.0079 = 4.0026
    • Email
Re: ON TIMER, STOP - remembered events
« Reply #8 on: March 17, 2013, 09:55:22 AM »
Hi,

yes I know this is noted in the wiki, but that it is noted don't make it right...  ;D

As you will read for the QBasic part in the wiki, it says QBasic WILL break SLEEP...., and I can confirm this.
Also every other BASIC on other platforms do break SLEEP...., simply because that's the way it must behave to allow for any useful things. As QB64 is meant to be compatible with QBasic, it's a shame those general things never get solved, instead a new branch (GL) is launched, taking over the old issues from SDL and introducing a lot of new either.

The point I wanna make is, as I'm as programmer always watch out not to claim more performance for my programs than really required, hence I've a _DELAY or _LIMIT in almost every closed loop. As ON TIMER interferes with it, it becomes useless for me.

Eg. In one of my programs I was about to check for a user exit request (_EXIT) function. As I was not in the mood to place an individual _EXIT check in various places in my program, I've made it in a GOSUB routine, which should be called 5x per second (that's the reason for my example above), via an ON TIMER event, if an exit request was noted, the routine should return to the program's exit label, otherwise simply return to regular execution. Well, it simply didn't work out the way it was intended, because of the _LIMIT/_DELAY instructions scatterd throughout my program. So I had to decide removing all limits and claim all CPU power, or find another way for the exit check. Guess what I've decided....

Download archives of my QB64 stuff:
Polygon functions: http://rhosigma-cw.net/down/GfxDemos.zip
Screen savers: http://rhosigma-cw.net/down/ScrSavers.zip
Libraries collection: http://rhosigma-cw.net/down/QB64Library.zip (extract into the QB64 folder, a new sub-folder "QB64Library" is created)

OlDosLover

  • Hero Member
  • *****
  • Posts: 3860
  • OlDosLover
    • Email
Re: ON TIMER, STOP - remembered events
« Reply #9 on: March 17, 2013, 10:23:02 AM »
Hi all,
    I understand and to some degree agree with you.
Quote
The point I wanna make is, as I'm as programmer always watch out not to claim more performance for my programs than really required, hence I've a _DELAY or _LIMIT in almost every closed loop. As ON TIMER interferes with it, it becomes useless for me.
    This would make a great topic in the Developers Blog /Q&A. As its your point i'll refrain from posting the topic.
OlDosLover.

RhoSigma

  • Jr. Member
  • **
  • Posts: 75
  • 4 * 1.0079 = 4.0026
    • Email
Re: ON TIMER, STOP - remembered events
« Reply #10 on: March 17, 2013, 02:12:32 PM »
Quote from: OlDosLover on March 17, 2013, 10:23:02 AM
    This would make a great topic in the Developers Blog /Q&A. As its your point i'll refrain from posting the topic.
OlDosLover.

Don't worry, just go ahead...
I've eliminated the need for it in all my programs.
Download archives of my QB64 stuff:
Polygon functions: http://rhosigma-cw.net/down/GfxDemos.zip
Screen savers: http://rhosigma-cw.net/down/ScrSavers.zip
Libraries collection: http://rhosigma-cw.net/down/QB64Library.zip (extract into the QB64 folder, a new sub-folder "QB64Library" is created)

MajorApollo

  • Newbie
  • *
  • Posts: 10
Re: ON TIMER, STOP - remembered events
« Reply #11 on: March 17, 2013, 02:26:50 PM »
Thanks for answering.

I did notice that the time you input into the timer needs to be /2 , like if you want it to count for 10 seconds then set it to 5 seconds, which I am fine with.

I just wanted to be able to "pause" the timers and then when I unpause one or more they (1) resume (2) process all events while paused (like the wiki says it does).

So the ON TIMER is off by 1 second per second, doesn't allow resuming nor does it process the calls/gosubs as it claims to... 3 bugs?!?

MajorApollo

  • Newbie
  • *
  • Posts: 10
Re: ON TIMER, STOP - remembered events
« Reply #12 on: March 17, 2013, 04:53:07 PM »
Quote from: RhoSigma on March 17, 2013, 09:55:22 AM
Hi,

yes I know this is noted in the wiki, but that it is noted don't make it right...  ;D

As you will read for the QBasic part in the wiki, it says QBasic WILL break SLEEP...., and I can confirm this.
Also every other BASIC on other platforms do break SLEEP...., simply because that's the way it must behave to allow for any useful things. As QB64 is meant to be compatible with QBasic, it's a shame those general things never get solved, instead a new branch (GL) is launched, taking over the old issues from SDL and introducing a lot of new either.

The point I wanna make is, as I'm as programmer always watch out not to claim more performance for my programs than really required, hence I've a _DELAY or _LIMIT in almost every closed loop. As ON TIMER interferes with it, it becomes useless for me.

Eg. In one of my programs I was about to check for a user exit request (_EXIT) function. As I was not in the mood to place an individual _EXIT check in various places in my program, I've made it in a GOSUB routine, which should be called 5x per second (that's the reason for my example above), via an ON TIMER event, if an exit request was noted, the routine should return to the program's exit label, otherwise simply return to regular execution. Well, it simply didn't work out the way it was intended, because of the _LIMIT/_DELAY instructions scatterd throughout my program. So I had to decide removing all limits and claim all CPU power, or find another way for the exit check. Guess what I've decided....

When using ON TIMER the timer event will trigger, process and return to the exact line it was called from; as long as you make sure where it gosub/calls returns it properly and doesn't branch all over and cause an eventual error. This is sufficient for what I'm doing, but can also see how it could not be useful in other situations. I just wish the event trapping while paused worked :/

OlDosLover

  • Hero Member
  • *****
  • Posts: 3860
  • OlDosLover
    • Email
Re: ON TIMER, STOP - remembered events
« Reply #13 on: March 17, 2013, 06:52:52 PM »
Hi all,
Quote
I did notice that the time you input into the timer needs to be /2 , like if you want it to count for 10 seconds then set it to 5 seconds, which I am fine with.

    .2 with 5 counts = 1 second
    .1 with 10 counts = 1 second etc
Quote
I just wanted to be able to "pause" the timers and then when I unpause one or more they (1) resume (2) process all events while paused (like the wiki says it does).
    Well have 2 timers. Only pause one , while the other does the real work. The pause one is the show pony. I dont know if we agree on the intrepretation of the wiki on that.

Quote
So the ON TIMER is off by 1 second per second, doesn't allow resuming nor does it process the calls/gosubs as it claims to... 3 bugs?!?
    Our program seems to simply add 1 for whatever the delay period is and resumes normal "scanning behaviour" after unpauseing. It doesn't keep a count of the total missed events and get called THAT amount to recover  them , it seems to only be called once to recover them then returns to normal or so it seems. Not sure if i'd describe  this behaviour as a bug.
OlDosLover.

MajorApollo

  • Newbie
  • *
  • Posts: 10
Re: ON TIMER, STOP - remembered events
« Reply #14 on: March 18, 2013, 09:36:41 AM »
Quote from: OlDosLover on March 17, 2013, 06:52:52 PM
Hi all,
Quote
I did notice that the time you input into the timer needs to be /2 , like if you want it to count for 10 seconds then set it to 5 seconds, which I am fine with.

    .2 with 5 counts = 1 second
    .1 with 10 counts = 1 second etc
Quote
I just wanted to be able to "pause" the timers and then when I unpause one or more they (1) resume (2) process all events while paused (like the wiki says it does).
    Well have 2 timers. Only pause one , while the other does the real work. The pause one is the show pony. I dont know if we agree on the intrepretation of the wiki on that.

Quote
So the ON TIMER is off by 1 second per second, doesn't allow resuming nor does it process the calls/gosubs as it claims to... 3 bugs?!?
    Our program seems to simply add 1 for whatever the delay period is and resumes normal "scanning behaviour" after unpauseing. It doesn't keep a count of the total missed events and get called THAT amount to recover  them , it seems to only be called once to recover them then returns to normal or so it seems. Not sure if i'd describe  this behaviour as a bug.
OlDosLover.

Well, if I set the timer to 10 seconds the event doesn't trigger until 20 seconds. So if I want an event to trigger at 8 seconds I have to set the TIMER to 4 seconds.

The wiki states that the timer when paused and resumed will carry out every event when unpaused, which in reality it doesn't even carry out a single one when unpaused and becomes totally useless.

  • Print