In the previous lesson I showed you how potentially blocking instructions like WaitOn and Pause will automatically cause a task switch, i.e. cause the task to yield so another task can run. But what if there are no such instructions being executed?
The YieldTask instruction lets you force a task switch anywhere you like in your program. This is something you have to think about, for two reasons:
To illustrate this, copy the following into SPLat/PC and run it:
(Click here for some tips for working around problems with copy and paste out of Internet Explorer and HTML-help (.chm) files)
LaunchTask TaskA
LaunchTask TaskB
RunTasksForever
TaskA: On 0
Pause 1
Off 0
Pause 1
GoTo TaskA
TaskB: IncM 0
GoTo TaskB
The program will "bomb out" after a short while. A YieldTask placed after the IncM instruction will allow it to run properly. Try it!
Here's an example of a task that uses YieldTask. This task will monitor inputs 2 and 3 simultaneously. If input 2 comes on it increments RAM location Count. If input 3 comes on it decrements Count. Having counted up or down it waits for both inputs to be off, then repeats.
CountFunc: GoIfInOn 2,CountUp
GoIfInOn 3,CountDn
YieldTask ;Give someone else a go
GoTo CountFunc ;Loop and repeat
CountUp: IncM Count
GoTo WaitForBothOff
CountDn: DecM Count
WaitForBothOff: YieldTask
GoIfInOn 2,WaitForBothOff
GoIfInOn 3,WaitForBothOff
GoTo CountFunc
Count: mEQU 10 ;Declare the RAM variable
Combine the above task with the dual flasher example in the earlier example and get it running. Take time to study what the YieldTask is doing.
Hint: You can monitor Count at location 10 in the Data Memory window in SPLat/PC (explore the Window menu if this is unfamiliar ground).
The first loop of CountFunc (the first 4 instructions) uses one instruction more than necessary. Rearrange it so it only use 3 instructions. Hint: Move the YieldTask to the start of the loop, eliminate the unconditional GoTo and modify the remaining two conditional GoTo's so it works. Note: In general you should not stress over minor inefficiencies like this one in your code. In fact, unless you are pushing the limits of available memory, some inefficiencies are a good investment if they make the code easier to read.
Consider the following rewritten snippet of code:
WaitForBothOff: WaitOff 2
WaitOff 3
GoTo CountFunc
This would seem to achieve the same result with a saving of 2 lines of code. However, the original will only "trip" when both inputs are off simultaneously. Work out why the the above snippet could "trip" with input 2 on and input 3 off.