INTERRUPT MULTITASKING EXPLAINED
One pass around the loop of a background task is performed at regular precise intervals defined by the user. This scheme is particularly useful when there are a number of events occurring at preset intervals, the background task can handle all of them leaving the foreground task free for asynchronous work.
Using Interrupt Multitasking there is only one parameter stack and user variables, number formatting area and PAD are common to both tasks. However a second return stack is maintained (above the old one) for the background task.
PERIOD LESS THAN 53MS
A separate high level Forth task can be assigned to any or all of the three external and seven internal interrupts. The task-switching scheme shown in INTERRUPTS WRITTEN IN HIGH LEVEL FORTH executes immediately an event happens; this is often what is needed in real-time systems. Using the 16-bit Output Compare Interrupt 1 we can arrange for a regular interrupt to occur at whatever interval is desired up to a maximum of 53.3ms. Now the background program is running 'all' the time and can be considered to be in an infinite loop, just like the foreground program.
This is achieved with the word LATER which determines the interval between successive runs of the background task. LATER takes a number u from the stack which is added to the Output Compare Register 1. After a period of time u times 0.8138�s the 16-bit free running counter will again match the Output Compare Register 1 and we will get another 'loop' of the background program.
This example is one you can try and modify if you have any difficulty with the word LATER :
( _MT.TDS) DECIMAL
88 USER %CTR ( an 8-bit variable
: INTWORK ( one pass through a regularly
( occurring sequence
1 %CTR C+! ( increment a byte variable
%CTR C@ 0= ( true every 256 'loops' of the
( background task
IF ." I'm in the background " THEN ( type to
( serial port
10000 LATER RETURN; ( now do foreground program
( for 8.138ms
: TEST ( foreground program
EIS $8 C@ $8 OR $8 C! ( enable output compare
BEGIN ." THIS IS THE FOREGROUND PROGRAM" CR 200MS
?TERMINAL UNTIL ;
OCI ASSIGN INTWORK
Compile this then type TEST . The foreground program continuously prints a message on the screen. Every 256 'loops' of the background program (every 2 seconds or so) it puts up its own message at whatever point the foreground has reached. Now press ctrl+C to exit the foreground program back to Forth. You will see that the second program is still running and you'll have to type DIS to stop it.
You can pass data from one task to another by means of variables or arrays provided one task writes and the other reads. You might need to disable the interrupt or set a semaphore while this 'mailbox' is being written if an interrupt half way through the write would result in bad data being read by the other task.
LONG PERIOD MULTIPLE REGULAR INTERRUPTS
Execution of many background programs at defined time intervals can be achieved using the library program _EVERY.TDS. It is an extension to the above scheme. For example run routine AAAA every 100ms, BBBB every second and CCCC each minute. See the file for a working example but this shows how the multiple regular tasks are defined. Any time period up to 1638.2 secs. (27 minutes) can be used.
: INTWORK ( Interrupt. One pass every 1/20 second
( As many programs as needed can be added
( but total execution time should all be
( called must be less than 50ms
0.1 EVERY AAAA ( do AAAA every 0.1 sec
1.0 EVERY BBBB ( do BBBB every second
60.0 EVERY CCCC ( do CCCC every minute
50MS RETURN; ( return to foreground program
OCI ASSIGN INTWORK