pic18/task.ss
#lang planet zwizwa/staapl/pic18 \ -*- forth -*-
provide-all

\ This file contains bare bones task switching code, in the form of
\ the following words. It switches the 3 stacks and the a and f
\ registers.
\
\    suspend  \ -- task      | copy state to data stack, return task pointer
\    resume   \ task --      | ignore current context, resume old task
\    swaptask \ ta var -- tb | swap task ta with task stored in var
\
\ For example, using only two tasks, a single variable is used to
\ store the task pointer of the other state.
\
\    variable other
\
\ Which enables the definition of a simple yield word
\
\    : yield suspend other swaptask resume ;
\
\ In general, one would call a 'schedule' word which transforms one
\ task id into another one. For example by placing one task in a
\ queue, and reading the next one from the queue.
\
\    : yield suspend schedule resume ;
\
\
\ Booting a task is very simple. It requires the initialization of the
\ 3 stack pointers to an available location in memory. This depends on
\ the particual memory model an is left to the user.
\
\  : spawn
\	suspend other !   \ suspend current task
\	#x10 rp !         \ move return stack pointer to half of stack
\	#x50 xp !         \ similar for the other 2
\	#x60 dp !
\       init-task ;
\ 



\ IMPLEMENTATION

macro
: dp FSR0L ;
: xp FSR1L ;
: rp STKPTR ;   
forth

\ A task is represented by a data stack pointer. The tricky bits are
\ dp@ and dp! which must not interfere with the WREG = TOP
\ optimization we have going on. It turns out this is easy:
\
\ dp@ is just dp @, which is implemented as 'dup', followed by w <- FSR0L
\ dp! is also just dp !, implemented as 'w -> FSR0L' followed by 'drop'
\
\ Note that saving of a / f registers and TABLAT is only necessary if
\ you use them in all tasks. the first 2-task app i did indeed used
\ both a and f reg in both tasks, so here's the safest version.

\ Note: this saves only the low byte of the FSR address, so task
\ stacks need to be in the same bank.

macro
: dp@  dp @ ;
: dp!  dp ! ;   
forth


macro
: suspend  \ -- task
    TABLAT @ fl @ fh @ al @ ah @ rp @ xp @ dp@ ;
: resume   \ task --
    dp! xp ! rp ! ah ! al ! fh ! fl ! TABLAT ! ;
: swaptask \ task var --
    swap! ; 
forth



\ YIELD: M.W 3b: to surrender or relinquish to the physical control of another