Page 147 - The Unofficial Guide to Lego Mindstorms Robots
P. 147
136
The CELLS word simply converts a number on the stack from cells, which are the fundamental units of Forth memory,
to bytes. The line above allocates no space for user variables and 32 cells each for the parameter stack and return stack.
The name of the new task is M OTOR_TASK. In tortast.txt, three other tasks are allocated in the same way:
0 32 CELLS 32 CELLS ALLOT_TASK TIMER_TASK
0 32 CELLS 32 CELLS ALLOT_TASK SENSOR_TASK
0 32 CELLS 32 CELLS ALLOT_TASK DISPLAY_TASK
Notice how the name o f the new task is specified after the ALLOT_TASK word, almost like a va riable definition.
2. Next, each task must be built into a list. When one task voluntarily gives up control (cooperates), the next task in the list will
get control. The BUILD word assembles tasks into a list:
MOTOR_TASK BUILD
TIMER_TASK BUILD
SENSOR_TASK BUILD
DISPLAY_TASK BUILD
3. Next, you need to actually define what each task does. This is done with the ACTIVATE word, which can be used only
inside a definition. Consider, for example, the MOTOR_TASK. Basically, we want it to look like this:
BEGIN UPDATE_MOTORS PAUSE AGAIN
The real work of th e task is in UPDATE_MOTORS, a word that examines some other values in the system and sets the
state of the moto rs. The PAUSE word is the key to cooperative multitasking-it passes control to the next task in the list.
To associate this loop with MOTOR_TASK, we need another special word, ACTIVATE:
:NONAME MOTOR_TASK ACTIVATE BEGIN UPDATE_MOTORS PAUSE AGAIN ; EXECUTE
The ACTIVATE word associates MOTOR_TASK with the rest of the NONAME definition, which is simply the endless
BEGIN AGAIN loop. To link the code into the task list, the NONAME definition is executed. (The combination of
NONAME and EXECUTE allows you to e xecute a defined word just one time. Because it doesn't have a name, you can't
execute the defined w ord again later.) The tortast.txt example sets up its other three tasks in the same way:
: NO NAME TIMER_TASK ACTIVATE BEGIN UPDATE_TIMERS PAUSE AGAIN ; EXECUTE
:NONAME S ENSOR_TASK ACTIVATE BEGIN UPDATE_SENSORS PAUSE AGAIN ; EXECUTE
:NONAME DISPLAY_T ASK ACTIVATE BEGIN UPDATE_DISPLAY PAUSE AGAIN ; EXECUTE
4. To actually start the tasks running, use AWAKE, like th is:
DIS PLAY_TASK AWAKE
SENSOR_TASK AWAKE
TIMER_TASK AWAKE
MOTOR_TASK AWAKE