carrier@sdics.ucsd.EDU (Mark Carrier) (09/07/88)
I am trying to get accurate millisecond timing on a Mac II. I want to record subject reaction times where the responses are keypresses. Installing a task via the Time Manager seems the most promising approach, where the task simply increments a global counter every millisecond. The only problem is that there does not seem to be a convenient way of making the task be executed every millisecond. Calling the routine PrimeTime from within the task itself to reschedule its execution does not work (the Mac crashes). Does anybody know a convenient (or any) way of doing this? Is it possible? If not, is there some other (perhaps lower-level) way of achieving millisecond timing? Any and all suggestions are appreciated. This timing problem seems solvable on the Mac II, someone must have already done such timing for some application?!! Mark Carrier
beard@ux1.lbl.gov (Patrick C Beard) (09/07/88)
In article <626@sdics.ucsd.EDU> carrier@sdics.UUCP (Mark Carrier) writes: > >I am trying to get accurate millisecond timing on a Mac II. I >want to record subject reaction times where the responses are >keypresses. Installing a task via the Time Manager seems the >most promising approach, where the task simply increments a >global counter every millisecond. The only problem is that >there does not seem to be a convenient way of making the task >be executed every millisecond. Calling the routine PrimeTime >from within the task itself to reschedule its execution does >not work (the Mac crashes). > >Does anybody know a convenient (or any) way of doing this? Is >it possible? If not, is there some other (perhaps lower-level) >way of achieving millisecond timing? > > > Mark Carrier I am using the Time Manager to do exactly what you describe, namely, reinstalling myself to schedule some future event. Here is a code excerpt: pascal void StepperInt() { SetCurrentA5(); /* set up access to my globals */ CurrentDirection=GridStepper->CurrentDirection; currentTime=INTERRUPT_PERIOD; /* some constant time in milliseconds */ PrimeTime(&TMStepperTask, currentTime); /* code ... */ RestoreCurrentA5(); /* restore previous A5 */ } SetCurrentA5() and RestoreCurrentA5() are routines I wrote in assembly language that use PC relative storage to store and retrieve the current and my values of A5 to solve interrupt global access under multifinder. A third routine, RememberOurA5() is called at application startup to store A5 for later retrieval by the interrupt routine. If there is further interest I will post these routines, but they are easy enough to implement. The reason your calls to PrimeTime() at interrupt time were crashing is probably because you weren't setting up access to your globals properly. I hope this helps. Patrick Beard Lawrence Berkeley Laboratory beard@ux1.lbl.gov The reason you
beard@ux1.lbl.gov (Patrick C Beard) (09/07/88)
By the way, you can use SetUpA5() and RestoreA5() if you aren't worried about Multifinder compatibility. The reason these won't work under MF is that the low memory global, CurrentA5 (0x904), has a different value if a different application is frontmost. You have to keep your application's A5 in a safe place. Patrick Beard Lawrence Berkeley Laboratory beard@ux1.lbl.gov
lsr@Apple.COM (Larry Rosenstein) (09/07/88)
In article <947@helios.ee.lbl.gov> beard@ux1.lbl.gov (Patrick C Beard) writes: >By the way, you can use SetUpA5() and RestoreA5() if you aren't worried >about Multifinder compatibility. The reason these won't work under MF is Tech Note #208 warns about using these in some optimizing compilers. These routines push the old value of A5 on the stack, but some compilers (MPW 3.0 is sited) leave function parameters on the stack across multiple function calls, which breaks these routines. Instead they suggest using a couple of inline procedures that set A5 and return its old value. You simply save the old value in a local variable. FUNCTION SetCurrentA5: LONGINT; INLINE $2E8D, $2A78, $0904; { returns A5 and sets A5 from CurrentA5 } FUNCTION SetA5(newA5: LONGINT): LONGINT; INLINE $2F4F, $0004, $2A5F; { returns A5 and sets it based on the parameter } As you said you can't use th value of CurrentA5 under MultiFinder. Unfortunately, the TimeManager does not pass a poiner to your time request to the routine, so you must store your application's A5 value in with the code of your time manager routine. Then you can get the A5 value with a PC-relative reference and use SetA5 to set the register. Larry Rosenstein, Object Specialist Apple Computer, Inc. 20525 Mariani Ave, MS 46-B Cupertino, CA 95014 AppleLink:Rosenstein1 domain:lsr@Apple.COM UUCP:{sun,voder,nsc,decwrl}!apple!lsr
conybear@bruce.oz (Roland Conybeare) (09/08/88)
From article <626@sdics.ucsd.EDU>, by carrier@sdics.ucsd.EDU (Mark Carrier): > > I am trying to get accurate millisecond timing on a Mac II. I > Just a thought: LSC's profiler appears to do millisecond timing so you might get a look at how it does it. Roland Conybeare (conybear@moncsbruce.oz)