;* ======================================================================== *;
;*  The routines and data in this file (sleep.asm) are dedicated to the     *;
;*  public domain via the Creative Commons CC0 v1.0 license by its author,  *;
;*  Joseph Zbiciak.                                                         *;
;*                                                                          *;
;*          https://creativecommons.org/publicdomain/zero/1.0/              *;
;* ======================================================================== *;

;;==========================================================================;;
;; Joe Zbiciak's Task Routines:  Timer-based Task SLEEP/SPAWN support       ;;
;; http://spatula-city.org/~im14u2c/intv/                                   ;;
;;==========================================================================;;

;; ======================================================================== ;;
;;  GLOBAL VARIABLES USED BY THESE ROUTINES                                 ;;
;;                                                                          ;;
;;  Note that some of these routines may use one or more global variables.  ;;
;;  If you use these routines, you will need to allocate the appropriate    ;;
;;  space in either 16-bit or 8-bit memory as appropriate.  Each global     ;;
;;  variable is listed with the routines which use it and the required      ;;
;;  memory width.                                                           ;;
;;                                                                          ;;
;;  Example declarations for these routines are shown below, commented out. ;;
;;  You should uncomment these and add them to your program to make use of  ;;
;;  the routine that needs them.  Make sure to assign these variables to    ;;
;;  locations that aren't used for anything else.                           ;;
;;                                                                          ;;
;;  NOTES                                                                   ;;
;;   -- TSKTBL is formatted as described in 'timer.asm'                     ;;
;;   -- SLEEP_REGSV needs room for 5 words.                                 ;;
;;                                                                          ;;
;; ======================================================================== ;;

                       ; Used by       Req'd Width  Description
                       ;------------------------------------------------------
;TSKTBL      EQU $310  ; DOTIMER/etc   16-bit       Timer-task table
;SLEEP_REGSV EQU $310  ; SLEEP/SPAWN   16-bit       Timer-task table


;; ======================================================================== ;;
;;  SLEEP                                                                   ;;
;;      Causes a one-shot process to sleep by scheduling a second one-shot  ;;
;;      process to reawake it.  This is VERY TRICKY TO USE, and can be      ;;
;;      used by ONE PROCESS ONLY at a time, because there is only one       ;;
;;      register save area (SLEEP_REGSV).                                   ;;
;;                                                                          ;;
;;  SPAWN                                                                   ;;
;;      Same as sleep, only the sleeping task isn't a one-shot.  It keeps   ;;
;;      retriggering automatically at the designated interval, or can be    ;;
;;      retriggered manually if the period is odd.                          ;;
;;                                                                          ;;
;;      (NOTE: SLEEP and SPAWN point to the same place.  The different      ;;
;;      names are provided to make your code easier to read.)               ;;
;;                                                                          ;;
;;  INPUTS:                                                                 ;;
;;      R5 -- Invocation record, in following format:                       ;;
;;            Period/sleep time  1 DECLE  (ODD for SLEEP, EVEN for SPAWN)   ;;
;;            Process # to use   1 DECLE                                    ;;
;;      Top of Stack -- Return addr from _this_ process back to scheduler.  ;;
;;      Task will wake at address after invocation record.                  ;;
;;                                                                          ;;
;;  OUTPUTS:                                                                ;;
;;      R0, R1, R2, R3, R4 restored                                         ;;
;;      R5 points to your return address                                    ;;
;;      Top of stack has return address for scheduler                       ;;
;; ======================================================================== ;;
SLEEP:      PROC
SPAWN:     
            MVO     R4,     SLEEP_REGSV+4 ; Save R4
            MVII    #SLEEP_REGSV, R4
            MVO@    R0,     R4      ; Save R0
            MVO@    R1,     R4      ; Save R1
            MVO@    R2,     R4      ; Save R2
            MVO@    R3,     R4      ; Save R3
           
            MVI@    R5,     R2      ; Get sleep time
            MVI@    R5,     R3      ; Get PID
           
            SLL     R3,     2       ; R3 = R3 * 4 (four words/entry)
            MVII    #TSKTBL,R4      ; R4 = &TSKTBL[0]
            ADDR    R3,     R4      ; R4 = &TSKTBL[n]
            MVII    #@@wake,R0
            MVO@    R0,     R4      ; Address to wake up at
            MVO@    R5,     R4      ; Instance data (R5 restore)
            MVO@    R2,     R4
            MVO@    R2,     R4
           
            PULR    PC
           
@@wake:     PSHR    R5              ; Remember return address
            MOVR    R2,     R5
            MVII    #SLEEP_REGSV,R4 ; Point to register save area
            MVI@    R4,     R0      ; Restore R0
            MVI@    R4,     R1      ; Restore R1
            MVI@    R4,     R2      ; Restore R2
            MVI@    R4,     R3      ; Restore R3
            MVI@    R4,     R4      ; Restore R4
           
            JR      R5              ; Go there
           
            ENDP

;; ======================================================================== ;;
;;  End of File:  sleep.asm                                                 ;;
;; ======================================================================== ;;
