[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Time Manager tasks and as foreign functions

At 10:38 AM 93.11.17 -0500, M. G. Slack wrote:
>Has anyone ever setup a periodic task using the time manager system from within
>a foreign function call?  I've made a couple of attempts but the system crashes
>instantly.  My test was trivial ... setting a periodic task up which increments
>a counter every n-milliseconds and then each time the ff is called it returns
>the  count.  I can get the code to run as a standalone c program but not as a
>ff.  I'm guessing that it has somthing to do with setting and restoring the A5
>environment.  Any leads?

Below is some LISP code I wrote to interrupt a Radius Rocket periodically;
it doesn't use foreign functions, just LISP and a machine code stub. You'd
need to replace the code
 24 8 #x13FC #x0001 #x????????  MOVE.B #1,rocket-control ; kick the rocket
to increment your counter instead. Also, I was interrupting every few
hundred microseconds (which severely taxes the Mac); perhaps you'd be
better off with:

(defun set-rocket-irq-period (msec)
  (when *rocket-timer-task*
    (%put-long *rocket-timer-task* msec 36))
  (setq *rocket-timer-time* msec))


;;; Timer interrupts

#| the timer task structure is laid out as follows...
  0 2   -- filler --
  2 4 QElemPtr     qLink            ; start of TMInfo
  6 2 short        qType
  8 4 TimerProcPtr tmAddr
 12 4 long         tmCount
 16 4 long         tmWakeup
 20 4 long         tmReserved
     -- the code --
 24 8 #x13FC #x0001 #x????????  MOVE.B #1,rocket-control ; kick the rocket
 32 2 #x2049                    MOVE.L A1, A0            ; ptr to TMInfo (above)
 34 6 #x203C #x????????         MOVE.L #delay, D0        ; new delay
 40 2 #x4EF9 #x????????         JMP ___PrimeTime         ; schedule next wakeup
 40 2 #xA05A                    _PrimeTime               ; schedule next wakeup
 42 2 #x4E75                    RTS

(defparameter *rocket-timer-task* nil)

(defparameter *rocket-timer-time* -666) ; delay -- negative => microseconds

(defun make-rocket-timer (rocket-slot)
  (when *rocket-timer-task*
    (stop-rocket-timer rocket-slot)
    (#_DisposPtr *rocket-timer-task*)
    (setq *rocket-timer-task* nil))
  (setq *rocket-timer-task* (#_NewPtr 48))
  (when (%null-ptr-p *rocket-timer-task*)
    (setq *rocket-timer-task* nil)
    (error "No memory!"))
  ; init the TMInfo
  (%put-long *rocket-timer-task* 0 0)
  (%put-long *rocket-timer-task* 0 4)
  (%put-ptr  *rocket-timer-task* (%inc-ptr *rocket-timer-task* 24) 8)
  (%put-long *rocket-timer-task* 0 12)
  (%put-long *rocket-timer-task* 0 16)
  (%put-long *rocket-timer-task* 0 20)
  ; init the code
  (%put-long *rocket-timer-task* #x13FC0001 24)
  (%put-ptr  *rocket-timer-task* (slot-to-rocket-control-addr rocket-slot) 28)
  (%put-long *rocket-timer-task* #x2049203C 32)
  (%put-long *rocket-timer-task* *rocket-timer-time* 36)
  ; was: (%put-long *rocket-timer-task* #xA05A4E75 40)
  (%put-word *rocket-timer-task* #x4EF9 40)
  (%put-ptr  *rocket-timer-task* (#_NGetTrapAddress #x05A) 42) ;
  ; flush the cache?
  (#_InsXTime (%inc-ptr *rocket-timer-task* 2)))

(defun start-rocket-timer (rocket-slot)
  (unless *rocket-timer-task*
    (make-rocket-timer rocket-slot))
  (when *rocket-timer-task*
    (#_PrimeTime (%inc-ptr *rocket-timer-task* 2) *rocket-timer-time*)))

(defun stop-rocket-timer (rocket-slot)
  (declare (ignore rocket-slot))
  (when *rocket-timer-task*
    (#_RmvTime (%inc-ptr *rocket-timer-task* 2))))

(defun set-rocket-irq-period (usec)
  (when *rocket-timer-task*
    (%put-long *rocket-timer-task* (- usec) 36))
; (setq *rocket-timer-time* (- usec))


;; EOF