MULTITASKING Although Max-FORTH does not directly support multitasking, multi- tasking is possible. The user may add on a multitasking program with relative ease since Max-FORTH was written to be totally preemptable. When Max-FORTH was created, user variable were reserved to specify each task's priority, record the task's state and allow for a double linked list of tasks to be created. Using these variables and interrupts, the user can create round robin or priority multitaskers, or combinations thereof. Pos- sibly the simplest structured multitasker is the round robin time sliced scheme. The following example demonstarts such a system. For simplicity sake only one task is open to communicate with the terminal. (The other tasks' USER variables, KEY-BC-PTR and EMIT- BC-PTR, could have been modified to allow them to talk to their own terminal.) (In order to find the value of NEXT2 in your revision of Max- FORTH, tick the address of COLD and DUMP the following 100 hex bytes. The address of NEXT2 is held in the two bytes immediately following the first 7E op-code in the that listing, about 90 hex bytes down.) COLD HEX FORGET TASK ( MAKE NEW ) ( USER AREA ) ( FOR TASK #1 ) 0000 C000 100 CMOVE C000 C00E +! C000 C010 +! C100 C01C ! 50 C01E ! C160 C022 ! C180 C02C ! C000 C034 +! C000 C040 +! C000 C046 +! C000 C06A +! C000 C06C +! D006 C006 ! C806 C008 ! ( MAKE NEW ) ( USER AREA ) ( FOR TASK #2 ) 0000 C800 100 1 CMOVE C800 C80E +! C800 C810 +! C900 C81C ! 50 C81E ! C960 C822 ! C980 C82C ! C800 C834 +! C800 C840 +! C800 C846 +! C800 C86A +! C800 C86C +! C006 C806 ! D006 C808 ! ( MAKE NEW ) ( USER AREA ) ( FOR TASK #3 ) 0000 D000 100 CMOVE D000 D00E +! D000 D010 +! D100 D01C ! 50 D01E ! D160 D022 ! D180 D02C ! D000 D034 +! D000 D040 +! D000 D046 +! D000 D06A +! D000 D06C +! C806 D006 ! C006 D008 ! C006 04 ! ABORT ( Assumes three tasks and 8K of RAM at $C000 ) ( The first task at $C000 slowly counts up on PB ) ( The second task at $C800 acts as a thermostat: reads AN0 output PA6 ) ( The third task at $D000 runs the normal Max-FORTH outer interpreter ) ( the task will also be master task, starting & handling of others ) ( Begin with simple task first ) : TASK ; : WAIT 1000 0 DO LOOP ; : RUN-TASK-1 0 BEGIN 1+ DUP B004 C! DUP 2 C00A ! ( THIS LINE IS ONLY TO LEAVE A TRACE IN MEM ) WAIT AGAIN ; ' RUN-TASK-1 CFA C002 ! ( SAVE CFA TO RUN IN AUTOSTART POS FOR LATER ) ( Switch to define the second task ) C806 04 ! ABORT : TASK ; VARIABLE LO-SET-POINT VARIABLE HI-SET-POINT VARIABLE HEATER-STATE VARIABLE TEMP : READ-A/D 0 B030 C! ( Start conversion for PE0 ) BEGIN B030 C@ 80 AND UNTIL ( Wait for conversion complete ) B031 C@ TEMP ! ; : CHK-LO? TEMP C@ LO-SET-POINT C@ < ; : HEATER-ON 1 HEATER-STATE ! FF B000 ! ; : CHK-HI? TEMP C@ HI-SET-POINT C@ > ; : HEATER-OFF 0 HEATER-STATE ! BF B000 ! ; : RUN-TASK-2 70 LO-SET-POINT ! 74 HI-SET-POINT ! BEGIN READ-A/D HEATER-STATE @ C80A ! ( THIS LINE IS ONLY TO LEAVE A TRACE IN MEM ) CHK-LO? IF HEATER-ON THEN 3 CHK-HI? IF HEATER-OFF THEN AGAIN ; ' RUN-TASK-2 CFA C802 ! ( SAVE CFA TO RUN IN AUTOSTART POS FOR LATER ) ( Switch to define the third task ) D006 04 ! ABORT : TASK ; CODE IRQRTN 86 C, 40 C, ( LDAA # $40 CLEAR THE INTERRUPT SOURCE ) B7 C, B025 , ( STAA $B025 BY KNOCKING DOWN BIT TFLG2 ) DE C, 02 C, ( LDX IP SAVE IP ON CONTEXT'S STACK ) 3C C, ( PSHX ) DE C, 00 C, ( LDX W SAVE W ON CONTEXT'S STACK ) 3C C, ( PSHX ) DE C, 04 C, ( LDX UP GET THIS TASK PTR AT $0004 ) AF C, 06 C, ( STS RPSAVE,X SAVE OLD CONTEXT ) EE C, 02 C, ( LDX UPLINK,X FIND NEXT TASK ) DF C, 04 C, ( STX UP AND SAVE FOR NXT IRQ ) AE C, 06 C, ( LDS RPSAVE,X SWITCH CONTEXT ) 38 C, ( PULX ) DF C, 00 C, ( STX W RECOVER W CONTEXT'S STACK ) 38 C, ( PULX ) DF C, 02 C, ( STX IP RECOVER IP CONTEXT'S STACK ) 3B C, ( RTI ) END-CODE CODE-SUB CLEAR-CC-MASKS 86 C, 00 C, ( LDAA # 0 ) 06 C, ( TAP ) 39 C, ( RTS ) END-CODE : ENABLE-MULTITASKING ( INSTALL THE REAL-TIME-INTERRUPT JUMP TABLE ENTRY ) 7E B7E6 EEC! ( JMP OP-CODE ) [ ' IRQRTN @ >< FF AND ] LITERAL B7E7 EEC! ( HI BYTE ) [ ' IRQRTN @ FF AND ] LITERAL B7E8 EEC! ( LO BYTE ) ( CREATE CONTEXTS FOR THE OTHER TASKS ON THEIR STACKS ) ( TASK 1 START UP CONTEXT ) FE54 C0FE ! ( PROGRAM COUNTER = NEXT2 ) C010 @ C0FC ! ( Y REGISTER = XXXX ) C002 @ C0FA ! ( X REGISTER = CFA TO RUN ) 0000 C0F8 ! ( B&A REGISTERS ) 00 C0F7 C! ( CC REGISTER ) 4 0000 C0F5 ! ( IP ) 0000 C0F3 ! ( W ) C0F2 C00C ! ( RPSAVE ) ( TASK 2 START UP CONTEXT ) FE54 C8FE ! ( PROGRAM COUNTER = NEXT2 ) C810 @ C8FC ! ( Y REGISTER = XXXX ) C802 @ C8FA ! ( X REGISTER = CFA TO RUN ) 0000 C8F8 ! ( B&A REGISTERS ) 00 C8F7 C! ( CC REGISTER ) 0000 C8F5 ! ( IP ) 0000 C8F3 ! ( W ) C8F2 C80C ! ( RPSAVE ) ( ENABLE THE HARDWARE TO GIVE REAL TIME IRQ'S ) 40 B024 C! ( RTII SET ) CLEAR-CC-MASKS ; : TASK1? BEGIN C00A @ U. ?TERMINAL UNTIL ; : TASK2? BEGIN C80A @ U. ?TERMINAL UNTIL ; 5