Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: oldheating gps motorhome heating
time.c
- Committer:
- andrewboyson
- Date:
- 2018-11-29
- Revision:
- 32:f915ccb1ece3
File content as of revision 32:f915ccb1ece3:
#include <stdint.h>
#include <stdbool.h>
#include "rtc.h"
#include "tm.h"
#include "time.h"
#include "timer.h"
#include "led.h"
#include "log.h"
#define GPREG0 (*((volatile unsigned *) 0x40024044))
static int64_t tickCount = 0;
static int64_t slewCount = 0;
static bool countIsSet = false;
//static bool ticked = false;
static int64_t ticksThisScan = 0;
static volatile int32_t slew = 0; //ns - up to +/- 2.147s of slew
static volatile int32_t ppb = 0; //This gets set to the last recorded ppb in TickInit
bool TimeIsSet() { return countIsSet; }
//bool TimeTicked(){ return ticked; }
int64_t TimeNow() { return ticksThisScan; } //30th bit is one second
int32_t TimeGetSlew() { return slew; }
void TimeSetSlew(int32_t value) { slew = value; }
int32_t TimeGetPpb () { return ppb; }
void TimeSetPpb (int32_t value) { ppb = value; GPREG0 = ppb; }
void TimeAddPpb (int32_t value) { ppb += value; GPREG0 = ppb; }
void TimeToTmUtc (int64_t ticks, struct tm* ptm)
{
time_t t = ticks >> TIME_ONE_SECOND_SHIFT;
TmUtcFromTimeT(t, ptm);
}
int64_t TimeFromTmUtc(struct tm* ptm)
{
time_t t = TmUtcToTimeT(ptm);
return t << TIME_ONE_SECOND_SHIFT;
}
/* Timer counts like this:
+---------+---------------+
| Seconds | Base count |
+---------+---------------+
| 0 | 0 |
| 1 | 96,000,000 |
| ... | ... |
| 44 | 4,224,000,000 |
| 44.74 | 2^32 |
| 45 | 25,032,704 |
| ... | ... |
+---------+---------------+
Tick counts as a signed 64 bit integer
1 bit sign, 33 bits for seconds, 30 bits for fraction
giving +/- 272 years with a resolution of around approximately 1ns or 1 ppb per second (2^30 == 1024x1024x1024)
*/
void TimeSet(int64_t extClock)
{
int64_t timerCountSinceLastSecond = TimerCountSinceLastSecond();
int64_t fraction = (timerCountSinceLastSecond << TIME_ONE_SECOND_SHIFT) / TIMER_COUNT_PER_SECOND;
int64_t ticks = extClock - fraction;
__disable_irq();
tickCount = ticks;
slewCount = 0;
__enable_irq();
ticksThisScan = extClock;
countIsSet = true;
}
void TimeMain()
{
//Update the times whenever there has been a system second
if (TimerHadSecond)
{
__disable_irq();
tickCount += TIME_ONE_SECOND + ppb;
slewCount += slew;
slew = 0;
__enable_irq();
}
//Update TickTime
ticksThisScan = tickCount + slewCount + TimerMultiplyFractionalPart(TIME_ONE_SECOND + ppb + slew, TimerCountSinceLastSecond());
//Update the ticked flag
// static bool lastTick = false;
// bool thisTick = ticksThisScan & TIME_ONE_SECOND;
// ticked = thisTick != lastTick;
// lastTick = thisTick;
}
static volatile int64_t tickSnapshot;
static volatile int64_t slewSnapshot;
static volatile uint32_t timerSnapshot;
void TimeSaveSnapshot()
{
timerSnapshot = TimerCountSinceLastSecond();
tickSnapshot = tickCount;
slewSnapshot = slewCount;
}
void TimesGetFromSnapshot(int64_t* pInt, int64_t* pAbs)
{
*pInt = tickSnapshot + TimerMultiplyFractionalPart(TIME_ONE_SECOND + ppb, timerSnapshot);
*pAbs = tickSnapshot + slewSnapshot + TimerMultiplyFractionalPart(TIME_ONE_SECOND + ppb + slew, timerSnapshot);
}
void TimesGet(int64_t* pInt, int64_t* pAbs)
{
uint32_t timerCount = TimerCountSinceLastSecond();
*pInt = tickCount + TimerMultiplyFractionalPart(TIME_ONE_SECOND + ppb, timerCount);
*pAbs = tickCount + slewCount + TimerMultiplyFractionalPart(TIME_ONE_SECOND + ppb + slew, timerCount);
}
void TimeInit(void)
{
ppb = GPREG0; //This is saved each time Tickppb is updated
}