Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

tick.c

Committer:
andrewboyson
Date:
2018-01-25
Revision:
26:0421132e6eaf
Parent:
25:81014a201736
Child:
28:b4aa41fdeb68

File content as of revision 26:0421132e6eaf:

#include <stdint.h>
#include <stdbool.h>

#include "peripherals.h"
#include "rtc.h"
#include "time.h"
#include "tick.h"
#include "timer.h"
#include "led.h"
#include "log.h"

static int64_t     tickCount = 0;
static int64_t     slewCount = 0;
static bool       countIsSet = false;
static bool           ticked = false;
static int64_t         ticks = 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    TickIsSet() { return countIsSet; }
bool    Ticked()    { return ticked; }
int64_t Ticks()     { return ticks; } //30th bit is one second

int32_t TickGetSlew() { return slew; }
void    TickSetSlew(int32_t value) { slew = value; }

int32_t TickGetPpb () { return ppb;  }
void    TickSetPpb (int32_t value) { ppb  = value; LPC_RTC->GPREG0 = ppb; }
void    TickAddPpb (int32_t value) { ppb += value; LPC_RTC->GPREG0 = ppb; }

void    TicksToTmUtc  (int64_t ticks, struct tm* ptm)
{
    time_t t = ticks >> TICK_ONE_SECOND_SHIFT;
    TimeToTmUtc(t, ptm);
}
int64_t TicksFromTmUtc(struct tm* ptm)
{
    time_t t = TimeFromTmUtc(ptm);
    return t << TICK_ONE_SECOND_SHIFT;
}


/*
+---------+---------------+
| Seconds |   Base count  |
+---------+---------------+
|    0    |             0 |
|    1    |    96,000,000 |
|   ...   |       ...     |
|   44    | 4,224,000,000 |
|   44.74 |          2^32 |
|   45    |    25,032,704 |
|   ...   |       ...     |
+---------+---------------+
*/

void TickSet(int64_t extClock)
{
     int64_t timerCountSinceLastSecond = TimerCountSinceLastSecond();
     int64_t fraction = (timerCountSinceLastSecond << TICK_ONE_SECOND_SHIFT) / TIMER_COUNT_PER_SECOND;
     int64_t    ticks = extClock - fraction;

    __disable_irq();
        tickCount = ticks;
        slewCount = 0;
    __enable_irq();
    
    ticks = extClock;
    
    countIsSet = true;
}
void TickMain()
{    
    //Update the times whenever there has been a system second
    if (TimerTicked)
    { 
        __disable_irq();
               tickCount += TICK_ONE_SECOND + ppb;
               slewCount += slew;
                    slew  = 0;
        __enable_irq();
    }
    
    //Update TickTime
    ticks = tickCount + slewCount + TimerMultiplyFractionalPart(TICK_ONE_SECOND + ppb + slew, TimerCountSinceLastSecond());
    
    //Update the ticked flag
    static bool lastTick = false;
    bool thisTick = ticks & TICK_ONE_SECOND;
    ticked = thisTick != lastTick;
    lastTick = thisTick;

}
static volatile  int64_t  tickSnapshot;
static volatile  int64_t  slewSnapshot;
static volatile uint32_t timerSnapshot;

void TickSaveSnapshot()
{
     timerSnapshot = TimerCountSinceLastSecond();
      tickSnapshot = tickCount;
      slewSnapshot = slewCount;
}
void TickGetTimesFromSnapshot(int64_t* pInt, int64_t* pAbs)
{
    *pInt = tickSnapshot                + TimerMultiplyFractionalPart(TICK_ONE_SECOND + ppb,        timerSnapshot);
    *pAbs = tickSnapshot + slewSnapshot + TimerMultiplyFractionalPart(TICK_ONE_SECOND + ppb + slew, timerSnapshot);
}
void TickGetTimes(int64_t* pInt, int64_t* pAbs)
{   
    uint32_t timerCount = TimerCountSinceLastSecond();
    *pInt = tickCount             + TimerMultiplyFractionalPart(TICK_ONE_SECOND + ppb,        timerCount);
    *pAbs = tickCount + slewCount + TimerMultiplyFractionalPart(TICK_ONE_SECOND + ppb + slew, timerCount);
}
void TickInit(void)
{
    ppb  = LPC_RTC->GPREG0; //This is saved each time Tickppb is updated
}