Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

tick.c

Committer:
andrewboyson
Date:
2018-01-16
Revision:
18:207dd1474cd9
Parent:
17:927fc1eceb9d
Child:
19:e537bacd1478

File content as of revision 18:207dd1474cd9:

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

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

#define ONE_BILLION 1000000000

static volatile int64_t nsTickCount;
static volatile int64_t nsFreqCount;
static volatile int64_t nsTimeCount;

static bool nsCountIsSet = false;
bool  TickIsSet() { return nsCountIsSet; }
void TickSet(int64_t extClock)
{
    nsTickCount  = 0;
    nsFreqCount  = 0;
    nsTimeCount  = extClock - LPC_TIM1->TC;
    nsCountIsSet = true;
}

static volatile int32_t slew = 0; //ns     - up to +/- 2.147s of slew
int32_t TickGetSlew() { return slew; }
void    TickSetSlew(int32_t value) { slew = value; }

static volatile int32_t ppb  = 0;
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; }

static uint32_t lastCall = 0;
void TickMain()
{
    uint32_t sinceLastCall = LPC_TIM1->TC - lastCall;
    if (sinceLastCall > TICK_COUNT_PER_SECOND)
    { 
        __disable_irq();
           lastCall += TICK_COUNT_PER_SECOND;
        nsTickCount += ONE_BILLION;
        nsFreqCount += ppb;
        nsTimeCount += slew;
               slew  = 0;
        __enable_irq();
    }
}
static volatile  int64_t nsTickSnapshot;
static volatile  int64_t nsFreqSnapshot;
static volatile  int64_t nsTimeSnapshot;
static volatile uint32_t  timerSnapshot;

void TickSaveSnapshotI()
{
     timerSnapshot = LPC_TIM1->TC - lastCall;
    nsTickSnapshot = nsTickCount;
    nsFreqSnapshot = nsFreqCount;
    nsTimeSnapshot = nsTimeCount;
}
static void makeTimesFromCounts(uint32_t timerCount, int64_t tickNs, int64_t freqNs, int64_t timeNs, int64_t* pNsInt, int64_t* pNsAbs)
{
    int64_t   fraction = timerCount;
              fraction <<= 32;
              fraction /= TICK_COUNT_PER_SECOND;

    int64_t nsFraction;
    
    int64_t nsBase     = tickNs;
    int64_t nsPerTick  = ONE_BILLION;
     
    nsBase    += freqNs;
    nsPerTick += ppb;
    nsFraction = (nsPerTick * fraction) >> 32;
    *pNsInt = nsBase + nsFraction;

    nsBase    += timeNs;
    nsPerTick += slew;
    nsFraction = (nsPerTick * fraction) >> 32;
    *pNsAbs = nsBase + nsFraction;
}
void TickRetrieveSnapshot(int64_t* pNsInt, int64_t* pNsAbs)
{
    makeTimesFromCounts(timerSnapshot, nsTickSnapshot, nsFreqSnapshot, nsTimeSnapshot, pNsInt, pNsAbs);
}
void TickGetTimes(int64_t* pNsInt, int64_t* pNsAbs)
{
    uint32_t timerCount;
     int64_t tickNs;
     int64_t freqNs;
     int64_t timeNs;
    
    __disable_irq();
        timerCount = LPC_TIM1->TC - lastCall;
         tickNs    = nsTickCount;
         freqNs    = nsFreqCount;
         timeNs    = nsTimeCount;
    __enable_irq();
    
    makeTimesFromCounts(timerCount, tickNs, freqNs, timeNs, pNsInt, pNsAbs);
}

void TickInit(void)
{
    nsTickCount = 0;
    nsFreqCount = 0;
    nsTimeCount = 0;
    
    ppb  = LPC_RTC->GPREG0; //This is saved each time Tickppb is updated
    slew = 0;
    nsCountIsSet = false;
    
    LPC_SC->PCONP    |=     4; //  4.8.9 Power Control for Peripherals register - Timer1 Power On
    LPC_TIM1->TCR     =     2; // 21.6.2 Timer Control Register - Reset TC and PC.
    LPC_TIM1->CTCR    =     0; // 21.6.3 Count Control Register - Timer mode
    LPC_TIM1->PR      =     0; // 21.6.5 Prescale register      - Don't prescale 96MHz clock (divide by PR+1).
    LPC_TIM1->MCR     =     0; // 21.6.8 Match Control Register - no interrupt or reset
    LPC_TIM1->TCR     =     1; // 21.6.2 Timer Control Register - Enable TC and PC
}
uint32_t TickElapsed(uint32_t* pLastTime)
{
    uint32_t thisTime = LPC_TIM1->TC;
    uint32_t elapsed = thisTime - *pLastTime;    
    *pLastTime = thisTime;
    return elapsed;
}