[comp.sys.mac.programmer] How to use Time Manager

menser@drexel.UUCP (Charles Menser) (12/09/88)

Could someone please explain how you can use Time Manager "in place of
cycle-counting timming loops."(IM4)

The text is very vague, at least to me, about actualy useing the manager
to pause a program's execution for a certain time. In my code, at present when Ineed a short delay, I use a for...do loop (MPW Pascal 2.0.2). How could I use
Time Manager instead?

Thanks.

-- 
================================================================
| Charles Menser        |USENET: ...!rutgers!bpa!drexel!menser |
| Drexel University     |--------------------------------------|
| Philadelphia, PA      |   This space for rent...             |

fry@brauer.harvard.edu (David Fry) (12/09/88)

Here's some code to measure a time interval accurate to 1 ms
from inside an XCMD.  It needs to use global variables, and
since it will be called from within an XCMD, you'll need to
perform some trick to use those globals.  This example use
Lightspeed C 3.0, which makes using globals referenced from A4
easy.

As I said, this example will be accurate to 1 ms.  But if you're
going to be measuring ADB keyboard and mouse events, they can
only be accurate to 5 ms at most, so you can save some processor
load by replacing the PrimeTime(&mytask,1L) calls with
PrimeTime(&mytask,5L) calls.  Then the interrupt will get called
1/5th as often.  Oh, and increment the variable by 5 each time.

I hope this helps...

----------------------------cut here---------------------------

#include "EventMgr.h"
#include "TimeMgr.h"
#include "setupa4.h"

/*
	to be used as part of an XCMD in LSC 3.0
*/

long		increment;
TMTask		mytask;

pascal void MyInc()
{
	SetUpA4();
	/* 
 		SetUpA4() is necessary because MyInc will be called
		as an interrupt and register A4 could point anywhere
	*/
	increment += 1;
	PrimeTime(&mytask,1L);
	RestoreA4();
}

time_something()
{

	increment = 0;
	mytask.tmAddr = MyInc;
	InsTime(&mytask);
	PrimeTime(&mytask,1L);
	RememberA4();
	do {
			/*
				do anything you want between the InsTime
				and RmvTime calls

				of course, you needn't stay in this
				function
			*/
	} while ( !Button() );  
	RmvTime(&mytask);

	/* 
		increment now contains the # of milliseconds
		elapsed time
	*/	
}

David Fry						fry@huma1.harvard.EDU
Department of Mathematics		fry@huma1.bitnet
Harvard University				...!harvard!huma1!fry
Cambridge, MA  02138		

beard@ux1.lbl.gov (Patrick C Beard) (12/10/88)

In article <829@drexel.UUCP> menser@drexel.UUCP (Charles Menser) writes:
>
>Could someone please explain how you can use Time Manager "in place of
>cycle-counting timming loops."(IM4)
>
>The text is very vague, at least to me, about actualy useing the manager
>to pause a program's execution for a certain time. In my code, at present when Ineed a short delay, I use a for...do loop (MPW Pascal 2.0.2). How could I use
>Time Manager instead?
>
>Thanks.
>

The answer:  DON'T!  If you just need a simple delay, then call:
	Delay(numTicks, finalTicks);
which is documented in Inside Macintosh II-384.  The Time Manager
is for more sophisticated things, where you need to be able to specify
that a routine get called after some number of milliseconds, at interrupt
time.

But, since you asked, here is how one could do a delay routine with the
time manager:

/*
	TMDelay.c - using the time manager to do a delay.
	by Patrick Beard
	beard@ux1.lbl.gov
 */

#include <TimeMgr.h>
#include <OSUtil.h>

pascal void TMDelayInterrupt();	/* routine that gets called at interrupt time */

static Boolean DelayComplete=false;
static TMTask DelayTask;

TMDelay(msToDelay)
long msToDelay;
{
	DelayComplete=false;
	InstallInterrupt(TMDelayInterrupt, &DelayTask, msToDelay);
	while(!DelayComplete);	/* could do something here like check for mouse */
	RemoveInterrupt(&DelayTask);
}

pascal void TMDelayInterrupt()
{
	SetUpA5();	/* so we can change a global */
				/* note this doesn't work under multifinder! */
	DelayComplete=true;

	RestoreA5();
}

InstallInterrupt(IntRoutine, IntTask, msToDelay)
ProcPtr IntRoutine;
TMTask *IntTask;
long msToDelay;
{
  
	(*IntTask).qType=vType;
	(*IntTask).tmAddr=IntRoutine;
	InsTime(IntTask);
	PrimeTime(IntTask, msToDelay);
}

RemoveInterrupt(IntTask)
TMTask *IntTask;
{
	RmvTime(IntTask);
}


/* ---------- */

Patrick Beard
Lawrence Berkeley Laboratory
beard@ux1.lbl.gov