/* ClockTime.c */ /* h:mm:ss.uu mm:ss.uu ss.uu @uuuuu */ #include #include #include #include "ClockTime.h" #include enum { nTicks = 10 // number of samples for ISR averaging }; struct TMInfo { TMTask task; // task record for Time Manager UInt16 avgTicks; // average timer ISRs per second UInt16 curTicks; // number of timer ISRs during current second UInt16 curMS; // number of milliseconds since start of current second UInt32 curSecs; // real time clock seconds change comparator SInt32 curTime; // milliseconds timer for application SInt32 baseTime; // milliseconds as of start of current RTC second UInt16 curTick; // sample number for ticks[] Boolean run; // application timer run flag Boolean firstPass; // set during first second of ISR task UInt16 ticks[nTicks]; // samples of ticks per second for averaging }; // TMInfo typedef struct TMInfo TMInfo, *TMInfoPtr; TMInfo tmBlock; // working storage for clock ISR UInt16 timeres; // clock units for ASCII conversions // conversion to and from separated time units SInt32 HMSUToTime( UInt16 h, UInt16 m, UInt16 s, UInt16 u ); SInt32 HMSUToTime( UInt16 h, UInt16 m, UInt16 s, UInt16 u ) { return ((h * 60L + m) * 60L + s) * 1000L + (u * 1000L / timeres); } void TimeToHMSU( SInt32 t, UInt16 *h, UInt16 *m, UInt16 *s, UInt16 *u ); void TimeToHMSU( SInt32 t, UInt16 *h, UInt16 *m, UInt16 *s, UInt16 *u ) { *u = timeres * (t % 1000) / 1000; t = t / 1000; *s = t % 60; t = t / 60; *m = t % 60; *h = t / 60; } // ASCII to time SInt32 ParseTime( char *p, char *e, SInt32 *t ) { Boolean neg; UInt16 h,m,s,u; char c; char *p0 = p; UInt32 units; /* h:mm:ss.uu mm:ss.uu ss.uu ss @uuuuu */ neg = false; h = 0; m = 0; s = 0; u = 0; *t = 0; switch (*p) { case '-': neg = true; case '+': p++; } if (*p == '@') { units = 0; c = *++p; while( '0' <= c && c <= '9' && p2) err = true; break; case '.': if (colons>2) err = true; colons = 3; break; default: --p; done = true; break; } if (!err && !isdigit(c)) { if (!digit) err = true; else if (colons == 3 && done) u = n; else { h = m; m = s; s = n; } n = 0; digit = false; } if (err) done = true; } if (m >= 60 || s >= 60 || u >= timeres) err = true; if (err) return 0; } *t = HMSUToTime( h, m, s, u ); if (neg) *t = -*t; return p - p0; } void ClockToStr( SInt32 t, Str255 *str ) { UInt16 h,m,s,u; char *s0 = (char *) str; char *p = s0 + 1; if (t<0) { *p++ = '-'; t = -t; } TimeToHMSU( t, &h, &m, &s, &u ); *p++ = '0' + h / 10; *p++ = '0' + h % 10; *p++ = ':'; *p++ = '0' + m / 10; *p++ = '0' + m % 10; *p++ = ':'; *p++ = '0' + s / 10; *p++ = '0' + s % 10; *p++ = '.'; if (timeres > 100) { *p++ = '0' + u / 100; *p++ = '0' + u / 10 % 10; *p++ = '0' + u % 10; } else { *p++ = '0' + u / 10; *p++ = '0' + u % 10; } *s0 = p - s0 - 1; } // Setting clock time void SetClock( SInt32 t ) { Boolean temp = ClockRunning( ); if (temp) StopClock( ); tmBlock.curTime = t; if (temp) StartClock( ); } void ResetClock( void ) { SetClock( 0 ); } SInt32 GetClockTime( void ) { return tmBlock.curTime; } // Starting and stopping clock void StartClock( void ) { SInt32 t; UInt16 ms; if (!tmBlock.run) { t = tmBlock.curTime; tmBlock.run = true; do { ms = tmBlock.curMS; tmBlock.baseTime = t - ms; tmBlock.curTime = t; } while (ms != tmBlock.curMS); } } void StopClock( void ) { tmBlock.run = false; } Boolean ClockRunning( void ) { return tmBlock.run; } // timer interrupt service routine //#if GENERATINGPOWERPC #if GENERATINGCFM static pascal void ClockTimeTask( TMTaskPtr tmTaskPtr ); static pascal void ClockTimeTask( TMTaskPtr tmTaskPtr ) { UInt32 secs; UInt16 i; UInt32 n; TMInfoPtr tmBlock = (TMInfoPtr) tmTaskPtr; #else pascal TMInfoPtr GetTMInfo( void ) = 0x2E89; // move.l a1,(sp) static pascal void ClockTimeTask( void ); static pascal void ClockTimeTask( void ) { UInt32 secs; UInt16 i; UInt32 n; TMInfoPtr tmBlock; tmBlock = GetTMInfo( ); #endif GetDateTime( & secs ); if (secs == tmBlock->curSecs) { tmBlock->curTicks++; tmBlock->curMS = tmBlock->curTicks * 1000L / tmBlock->avgTicks; if (tmBlock->curMS > 999) tmBlock->curMS = 999; // don't allow overflow to happen! if (tmBlock->run) tmBlock->curTime = tmBlock->baseTime + tmBlock->curMS; } else { if (tmBlock->firstPass) tmBlock->firstPass = false; else { tmBlock->ticks[tmBlock->curTick++] = tmBlock->curTicks; tmBlock->curTick %= nTicks; n = 0; for (i=0; iticks[i]; tmBlock->avgTicks = n / nTicks; } tmBlock->curTicks = 0; tmBlock->curSecs = secs; tmBlock->curMS = 0; if (tmBlock->run) { tmBlock->baseTime += 1000L; tmBlock->curTime = tmBlock->baseTime; } } // re-install the timer task PrimeTime( (QElemPtr) & (tmBlock->task), 1L ); } // Module initialization void ClockTimeInit( void ) { UInt32 i; timeres = 30; // Install the Time Manager task //#if GENERATINGPOWERPC #if GENERATINGCFM tmBlock.task.tmAddr = NewTimerProc( ClockTimeTask ); #else tmBlock.task.tmAddr = &ClockTimeTask; #endif tmBlock.task.tmWakeUp = 0; tmBlock.task.tmReserved = 0; tmBlock.avgTicks = 1000; // average timer ISRs per second tmBlock.curTicks = 0; // number of timer ISRs during current second tmBlock.curMS = 0; // number of milliseconds since start of current second GetDateTime( & tmBlock.curSecs ); // real time clock seconds change comparator tmBlock.curTime = 0; // milliseconds timer for application tmBlock.baseTime = 0; // milliseconds as of start of current RTC second tmBlock.curTick = 0; // sample number for ticks[] tmBlock.run = false;// application timer run flag tmBlock.firstPass = true; // set during first second of ISR task for (i=0; i