'' ***************************** '' * Timer * '' * (C) 2006 Parallax, Inc. * '' ***************************** CON TIX_DLY = 1_000_000 / 1_000 ' for 1 ms tix period MAX_STR = 16 ' maximum string length #0, TMR_TIX, TMR_SECS, TMR_MINS, TMR_HRS, TMR_DAYS VAR long cogon, cog ' cog status long tmrStack[12] ' local stack long tix, scs, mns, hrs, dys ' timer registers long running ' timer status long updating ' updating flag byte tmrStr[MAX_STR + 1] ' add one for zero terminator PUB start : okay '' Load background timer if cog available '' -- timer is on hold and registers cleared stop ' stop cog for this object if running reset okay := cogon := (cog := cognew(updateTimer, @tmrStack)) > 0 PUB stop '' Unload timer object - frees a cog if cogon~ ' if object running, mark stopped cogstop(cog) ' stop the cog PUB set(h, m, s) '' Put timer on hold and set hours, minutes, and seconds '' -- tix and days registers are cleared reset ' hold and clear regs wrReg(TMR_HRS, h) ' set time registers wrReg(TMR_MINS, m) wrReg(TMR_SECS, s) PUB reset '' Put timer on hold and clear registers hold ' stop timer longfill(@tix, 0, 5) ' clear registers PUB hold '' Put timer on hold without clearing registers running~ ' disable timer (set to false) PUB run '' Allow timer to run and update timer registers running~~ ' enable timer (set to true) PUB rdReg(reg) | t, s, m, h, d '' Read a timer register snapShot(@t) ' capture current values after update case reg ' return requested register TMR_TIX : result := t TMR_SECS : result := s TMR_MINS : result := m TMR_HRS : result := h TMR_DAYS : result := d PUB wrReg(reg, value) '' Write value to timer register '' -- value is forced positive and truncated if required for register if running ' live updates in progress? updating~~ ' yes set update flag repeat while updating ' wait for flag to clear case reg ' update reg with value TMR_TIX : tix := ||value // 1000 TMR_SECS : scs := ||value // 60 TMR_MINS : mns := ||value // 60 TMR_HRS : hrs := ||value // 24 TMR_DAYS : dys := ||value PUB snapShot(destAddr) '' Copies timer regs (5 longs) to destAddr '' -- makes transfer immediately after current update if running ' live updates in progress? updating~~ ' yes set update flag repeat while updating ' wait for flag to clear longmove(destAddr, @tix, 5) ' move timer registers to destination PUB showTimer | t, s, m, h, d '' Returns address of string in format HH:MM:SS.TTT snapShot(@t) ' capture registers after current update bytefill(@tmrStr, 0, MAX_STR + 1) ' clear string tmrStr[0] := (h / 10) + "0" ' convert 10's digit to ASCII char tmrStr[1] := (h // 10) + "0" ' convert 1's digit to ASCII char tmrStr[2] := ":" tmrStr[3] := (m / 10) + "0" tmrStr[4] := (m // 10) + "0" tmrStr[5] := ":" tmrStr[6] := (s / 10) + "0" tmrStr[7] := (s // 10) + "0" tmrStr[8] := "." tmrStr[9] := (t / 100) + "0" ' 1/10ths digit tmrStr[10] := (t // 100 / 10) + "0" ' 1/100ths digit tmrStr[11] := (t // 10) + "0" ' 1/1000ths digit return @tmrStr ' return address of string PRI updateTimer | t '' Updates timer registers '' -- timer.start method launches this into separate cog t := cnt ' sync with system counter repeat ' run until cog unloaded waitcnt(t += clkfreq / TIX_DLY) ' wait 1 ms if running ' if timer enabled tix := ++tix // 1000 ' update tix if (tix == 0) ' rollover? scs := ++scs // 60 ' yes, update seconds if (scs == 0) ' rollover? mns := ++mns // 60 ' yes, update minutes if (mns == 0) ' rollover? hrs := ++hrs // 24 ' yes, update hours if (hrs == 0) ' rollover? ++dys ' yes, increment days updating~ ' clear updating flag