|
Post by turtleman on Jul 30, 2022 4:57:52 GMT -5
I apologize not including the code, but it would be impractical with the loop comprising thousands of lines. Nonetheless, I'll try to post something representative of what I'm trying to do. Most of the time, I can extract what I need from the examples you guys are kind enough to post. I just want to thank all of you for trying to help and I'll post back when I have something better defined.
|
|
|
Post by Rod on Jul 30, 2022 9:59:46 GMT -5
Yes but your loop starts with one line and end with another. In between we don't care unless you leave the loop. So you really only need to show us half a dozen lines of code. The loop start, any exit code, the loop end. Presumably one of the exit lines of code is to light the led. So how do you leave the loop, a button? and how do you rejoin the loop. So how does the led button handler get back into the loop?
You will leave the loop at a scan or wait if a button event is set. How does the button handler get back to the loop?
|
|
|
Post by Walt Decker on Jul 30, 2022 11:14:30 GMT -5
I think this is a little closer to what you describe. Notice that the app is doing stuff while waiting for the button to be pressed and continues doing stuff after the button is pressed and while the "LED" is RED.
' '########################################################## ' TIMED_001._BAS ' Another Method for flashing a LED in response to an ' external event '##########################################################
GLOBAL TimeEnd, _ DmoEnd
TimeEnd = 0 '<--- time to show LED DmoEnd = 0
STYLEBITS #DMO.GFX, 0, _WS_BORDER, 0, 0 GRAPHICBOX #DMO.GFX, 5, 5, 30, 30
BUTTON #DMO.BTN, "SET TIMER", PUSH.BTN, UL, 40, 5, 65, 25
OPEN "TIMED" FOR WINDOW AS #DMO PRINT #DMO, "TRAPCLOSE DMO.END"
CALL DO.STUFF '<--- infinit loop
'--------------------------------------------- '---------------------------------------------
SUB PUSH.BTN BtnHndl$ '<--- button handler
IF TimeEnd THEN EXIT SUB
CALL SET.TIMER TimeEnd
END SUB
'--------------------------------------------- '---------------------------------------------
SUB SET.TIMER TimeStrt '<--- change graphic color and enable timer
PRINT #DMO.GFX, "DOWN" PRINT #DMO.GFX, "FILL RED"
TimeStrt = 550 TIMER TimeStrt, STOP.TIMER END SUB
'--------------------------------------------- '---------------------------------------------
SUB STOP.TIMER '<--- change graphic color and disable timer
PRINT #DMO.GFX, "DOWN" PRINT #DMO.GFX, "FILL WHITE"
TIMER 0 TimeEnd = 0 END SUB
'--------------------------------------------- '---------------------------------------------
SUB DO.STUFF '<--- infinit loop; use window kill button 'to escape
LoopCntr = 0
I = 0 [START.LOOP] LoopCntr = 0 J = RND(0) * 1000 + 1 K = 0 '<--- loop counter for jumping to [START.LOOP] SCAN '<--- allow branching to external events
[DO.LOOP] IF DmoEnd THEN EXIT SUB FOR I = 1 TO J K = FN.AddK(K, 3) '<--- add a value NEXT I LoopCntr = LoopCntr + 1
IF LoopCntr > 9 THEN GOTO [START.LOOP]
SCAN '<--- allow branching to external events
GOTO [DO.LOOP]
END SUB
'--------------------------------------------- '---------------------------------------------
SUB DMO.END DmoHndl$ '<--- close app DmoEnd = 1 CLOSE #DmoHndl$ END SUB
'--------------------------------------------- '---------------------------------------------
FUNCTION FN.AddK(Value, Adder)
Value = Value + Adder
FN.AddK = Value END FUNCTION
'
|
|
|
Post by turtleman on Aug 3, 2022 7:19:41 GMT -5
Here's a very simplified example using the timer used to control an LED-type indicator. The intent is to turn on the indicator (the small rectangle directly below the SHUFFLE button) when the button is pressed, stay on for a short duration, and turn off while the cards are being dealt. As it is, the LED stays on until all cards have been dealt, regardless of timer duration or time it takes to deal. I definitely do not want to slow down anything while the timer is active.
All I want is the software equivalent of a one-shot – independent of whatever else the program is doing. Yeah, I know 100 ms is too short, but that's just to illustrate the problem. Why does it stay on? I'm probably doing something incredibly stupid, but don't know what. Thanks!
'Timer Demo Aug. 03, 2022 nomainwin WindowWidth=1160:WindowHeight=480 UpperLeftX=1:UpperLeftY=1 button #main.start "SHUFFLE",[shuffle], UL, 15, 200, 70, 30 graphicbox #main.shuffleind, 15, 230, 70, 5 graphicbox #main.g, 0, 30, 1150, 440 open "Timer Demo" for window_nf as #main #main "trapclose [quit]"
'graphicbox handle hBox=hwnd(#main.g)
'open the cards dll open "qcard32.dll" for dll as #qc 'background #main.g "down; fill 15 190 225"
numcards = 52 dim num(numcards) dim cards (100) gosub [shuffle] wait [shuffleindclear] #main.shuffleind, "down; fill white" timer 0 wait [shuffle] #main.shuffleind, "down; fill red" 'turns on LED timer 100, [shuffleindclear] 'should turn off LED after 100 ms Call InitializeDeck hBox FOR j = 1 to 52 num(j) = j NEXT j
[randomize] FOR j = 1 to numcards r = int(rnd(1)* numcards + 1) temp = num(j) num(j) = num(r) num(r) = temp NEXT
'draw cards FOR j = 1 to numcards i = i + 1 cards(i) = num(j) print "Cards = ";i; " "; cards(i) nc = cards(i) face = 1 Call SetCardStatus nC,face Call DealCard hBox,nc,i * 20,50 call Pause 10 'normally zero delay NEXT i = 0 wait
[quit] close #qc:close #main:end
'subs and functions:
Sub Pause ms 'pause ms number of milliseconds calldll #kernel32,"Sleep",_ ms as long, re as void End Sub
Sub InitializeDeck hndle calldll #qc, "InitializeDeck",_ hndle as long,r as long End Sub
Sub DealCard hndle,nC,x,y 'places card on window whose handle is hndle at x,y 'nC is number of card - 1-52 in first deck and calldll #qc, "DealCard",hndle as long,nC as long,_ x as long,y as long,r as void End Sub
Sub SetCardStatus nC,face 'nC is number of card: 1-52 'face: 0=facedown,1=faceup calldll #qc, "SetCardStatus",nC as long,_ face as long,r as void End Sub
|
|
|
Post by Walt Decker on Aug 3, 2022 9:49:32 GMT -5
If you want the "LED" to light at the beginning of the shuffle and off at the end of the shuffle, simply turn it on at the beginning and off at the end. Forget the timer.
|
|
|
Post by turtleman on Aug 3, 2022 9:58:48 GMT -5
I guess I didn't explain too well. I want the LED to turn on at the beginning, as it does now, but I want it switch off 100 ms (or whatever) afterwards. If I put a wait statement before the draw cards routine, the LED flashes like it should. But if drawing the cards, it stays on. Why?
|
|
|
Post by Rod on Aug 3, 2022 10:21:31 GMT -5
The reason the led does not get turned off is that you don’t set any code to react to the timer firing. The timer will fire at 100ms but your code is stuck in the loop shuffling and issuing the cards. Only when it reaches the wait statement at the end of that process will the timer event get handled.
What you need is a SCAN inside your card issuing loop. You also need the led off handler to be a sub. So in your card issuing loop it scans for events every loop. It will find the timer event after 100ms then it should branch off to the led off sub and return to the card issuing loop..
|
|
|
Post by Rod on Aug 3, 2022 10:26:02 GMT -5
Just to add, you generally cannot mix [branch] code and sub code. It is nearly always best to do all subs or all [branch] other than a high level initial loop.
Why? Well [branch] labels cannot be found when you are inside a sub.
|
|
|
Post by turtleman on Aug 3, 2022 10:30:54 GMT -5
I hate to ask, but how many "scans" can you have? In the complete program, once a long routine has been initiated, hitting the same button again (using SCAN) pauses the program. Another press causes the program to resume. This has nothing to do with the SHUFFLE code already mentioned.
|
|
|
Post by Walt Decker on Aug 3, 2022 10:40:39 GMT -5
I do not have qcard.dll so can not test the timing. You might try this:
' 'Timer Demo Aug. 03, 2022 nomainwin WindowWidth=1160:WindowHeight=480 UpperLeftX=1:UpperLeftY=1 button #main.start "SHUFFLE",[shuffle], UL, 15, 200, 70, 30 graphicbox #main.shuffleind, 15, 230, 70, 5 graphicbox #main.g, 0, 30, 1150, 440 open "Timer Demo" for window_nf as #main #main "trapclose [quit]"
'graphicbox handle hBox=hwnd(#main.g)
'open the cards dll open "qcard32.dll" for dll as #qc 'background #main.g "down; fill 15 190 225"
numcards = 52 dim num(numcards) dim cards (100) gosub [shuffle] wait '[shuffleindclear] ' #main.shuffleind, "down; fill white" ' timer 0 ' wait [shuffle] ' #main.shuffleind, "down; fill red" 'turns on LED ' timer 100, [shuffleindclear] 'should turn off LED after 100 ms
CALL BEGIN.SHUFFLE 100 Call InitializeDeck hBox FOR j = 1 to 52 num(j) = j NEXT j
[randomize] FOR j = 1 to numcards r = int(rnd(1)* numcards + 1) temp = num(j) num(j) = num(r) num(r) = temp NEXT
SCAN 'draw cards FOR j = 1 to numcards i = i + 1 cards(i) = num(j) print "Cards = ";i; " "; cards(i) nc = cards(i) face = 1 Call SetCardStatus nC,face Call DealCard hBox,nc,i * 20,50 call Pause 10 'normally zero delay NEXT i = 0 wait
[quit] close #qc:close #main:end
'subs and functions:
Sub Pause ms 'pause ms number of milliseconds calldll #kernel32,"Sleep",_ ms as long, re as void End Sub
Sub InitializeDeck hndle calldll #qc, "InitializeDeck",_ hndle as long,r as long End Sub
Sub DealCard hndle,nC,x,y 'places card on window whose handle is hndle at x,y 'nC is number of card - 1-52 in first deck and calldll #qc, "DealCard",hndle as long,nC as long,_ x as long,y as long,r as void End Sub
Sub SetCardStatus nC,face 'nC is number of card: 1-52 'face: 0=facedown,1=faceup calldll #qc, "SetCardStatus",nC as long,_ face as long,r as void End Sub
'------------------------------------------------------------ '------------------------------------------------------------
SUB BEGIN.SHUFFLE Ms
#main.shuffleind, "down; fill red" 'turns on LED timer Ms, CLEAR.LED 'should turn off LED after 100 ms
END SUB
'------------------------------------------------------------ '------------------------------------------------------------
SUB CLEAR.LED
#main.shuffleind, "down; fill white" timer 0
END SUB '
Unless the branch label is within the sub.
How many "WAIT" statement can you have? As many as you need.
|
|
|
Post by turtleman on Aug 3, 2022 10:59:57 GMT -5
Thanks, but it appears to do exactly the same thing!
Not to appear rude if I don't reply as quickly as I'd like, it's because but I'm currently in the process of selling my house and preparing for a long-distance move. It's almost as bewildering as the code!
|
|
|
Post by Rod on Aug 3, 2022 13:34:12 GMT -5
Yes, and the code is in the sub!
As many as is necessary.
Both WAIT and SCAN are commands that look at the event list and branch to code handlers. So if you have three loops that happen one after the other put a SCAN in each loop. Then if you have an event pending like a timer led switch or a button press to change state the program flow will see the event and branch off to the handler. For this to work in a mixed program of [branch] and subs the handler really has to be a sub.
If it is a sub it is called if the event has fired when the program reaches the SCAN. As it is a sub handler it will return to the SCAN statement and keep processing the loop.
It is all actually simpler than it sounds. Just think flow, sequential looping flow and diverting branches to do special things like switch off a led. You want to dive off and switch off the led but come back exactly where you are in the program flow. So Subs work and Gosub works if you are using [branch] code.
|
|
|
Post by Rod on Aug 3, 2022 13:44:35 GMT -5
Walt, the scan needs to be in the depth of the loop (all loops) not on the extremity. It needs to allow the code to branch immediately and not once the loop is ended.
|
|
|
Post by Walt Decker on Aug 3, 2022 14:16:32 GMT -5
This appears to conform to the specs. Bear in mind that I do not have qcard.
' 'Timer Demo Aug. 03, 2022 nomainwin
[DECLARE.GLOBALS] GLOBAL numcards, _ Milisecs
dim cards (numcards)
[INIT.GLOBALS] numcards = 51 Milisecs = 100
dim cards (numcards)
[INIT.CARDS] CALL INIT.CARDS numcards ' gosub [shuffle]
' nomainwin
WindowWidth= 800 WindowHeight=480 UpperLeftX=1 UpperLeftY=1
button #main.start "SHUFFLE", [SHUFFLE], UL, 15, 10, 70, 30 graphicbox #main.shuffleind, 15, 45, 70, 5
graphicbox #main.g, 0, 50, 750, 440 open "Timer Demo" for window_nf as #main #main "trapclose [quit]"
'graphicbox handle hBox=hwnd(#main.g)
'open the cards dll 'open "qcard32.dll" for dll as #qc Call InitializeDeck hBox
'background #main.g "down; fill 15 190 225"
[BEGIN.WAIT] wait
'--------------------------------------------- '---------------------------------------------
[SHUFFLE]
CALL SET.LED Milisecs CALL RANDOMIZE.CARDS numcards
[SCAN.ONCE] 'print Milisecs SCAN IF Milisecs THEN GOTO [SCAN.ONCE]
Milisecs = 100
CALL DRAW.CARDS numcards GOTO [BEGIN.WAIT] [SHUFFLE.END]
'--------------------------------------------- '---------------------------------------------
SUB SET.LED Ms
#main.shuffleind, "down; fill red" 'turns on LED timer Ms, TURN.OFF.LED 'should turn off LED after 100 ms
END SUB
'--------------------------------------------- '---------------------------------------------
SUB TURN.OFF.LED TRACE 2 #main.shuffleind, "down; fill WHITE" 'turns on LED timer 0 'should turn off LED after 100 ms Milisecs = 0
END SUB
'--------------------------------------------- '---------------------------------------------
SUB RANDOMIZE.CARDS CardCount
Rcard = 0 TmpCard = 0
FOR I = 0 TO CardCount [AGAIN] Rcard = INT(RND(0) * CardCount)
FOR J = I + 1 TO CardCount IF cards(J) = Rcard THEN GOTO [AGAIN] NEXT J
cards(I) = Rcard NEXT I
END SUB
'--------------------------------------------- '---------------------------------------------
SUB INIT.CARDS CardCount
FOR I = 0 TO CardCount cards(I) = I NEXT I END SUB
'--------------------------------------------- '---------------------------------------------
SUB DRAW.CARDS CardCount
FOR i = 0 TO numcards nc = cards(i) face = 1 Call SetCardStatus nc,face Call DealCard hBox,nc,i * 20,50 call Pause 10 'normally zero delay NEXT
END SUB
[quit]
'close #qc close #main end
'subs and functions:
Sub Pause ms 'pause ms number of milliseconds calldll #kernel32,"Sleep",_ ms as long, re as void End Sub
Sub InitializeDeck hndle ' calldll #qc, "InitializeDeck",_ ' hndle as long,r as long End Sub
Sub DealCard hndle,nC,x,y 'places card on window whose handle is hndle at x,y 'nC is number of card - 1-52 in first deck and
' calldll #qc, "DealCard",hndle as long,nC as long,_ ' x as long,y as long,r as void PRINT #main.g, "backcolor green" PRINT #main.g, "down" PRINT #main.g, "boxfilled ";x;" ";y End Sub
Sub SetCardStatus nC,face 'nC is number of card: 1-52
'face: 0=facedown,1=faceup ' calldll #qc, "SetCardStatus",nC as long,_ ' face as long,r as void End Sub '
|
|
|
Post by turtleman on Aug 3, 2022 15:29:13 GMT -5
Thanks Walt, I need to give this more attention than I can at the moment. But while the LED comes on immediately with the button press, the rest of the program doesn't get going until the LED turns off. I'm really starting to wonder if a software equivalent of a one-shot that turns the LED on and off independently from everything else is even possible.
|
|