Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Sat Jan 20 17:10:55 2018 +0000
Revision:
23:07b19cd5f6d0
Parent:
22:df0b906bda26
Child:
24:6c9833e2a049
Combined the freq and ticks per second count

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 18:207dd1474cd9 1 #include <stdint.h>
andrewboyson 18:207dd1474cd9 2 #include <stdbool.h>
andrewboyson 18:207dd1474cd9 3
andrewboyson 17:927fc1eceb9d 4 #include "peripherals.h"
andrewboyson 14:7ef557918bb1 5 #include "rtc.h"
andrewboyson 14:7ef557918bb1 6 #include "time.h"
andrewboyson 14:7ef557918bb1 7 #include "tick.h"
andrewboyson 18:207dd1474cd9 8 #include "led.h"
andrewboyson 18:207dd1474cd9 9 #include "log.h"
andrewboyson 0:33686e88f09a 10
andrewboyson 0:33686e88f09a 11 #define ONE_BILLION 1000000000
andrewboyson 0:33686e88f09a 12
andrewboyson 16:933cbe190bb0 13 static volatile int64_t nsTickCount;
andrewboyson 23:07b19cd5f6d0 14 static volatile int64_t nsSlewCount;
andrewboyson 18:207dd1474cd9 15 static bool nsCountIsSet = false;
andrewboyson 18:207dd1474cd9 16 bool TickIsSet() { return nsCountIsSet; }
andrewboyson 0:33686e88f09a 17
andrewboyson 16:933cbe190bb0 18 static volatile int32_t slew = 0; //ns - up to +/- 2.147s of slew
andrewboyson 5:a3e37ce4975d 19 int32_t TickGetSlew() { return slew; }
andrewboyson 5:a3e37ce4975d 20 void TickSetSlew(int32_t value) { slew = value; }
andrewboyson 5:a3e37ce4975d 21
andrewboyson 16:933cbe190bb0 22 static volatile int32_t ppb = 0;
andrewboyson 5:a3e37ce4975d 23 int32_t TickGetPpb () { return ppb; }
andrewboyson 5:a3e37ce4975d 24 void TickSetPpb (int32_t value) { ppb = value; LPC_RTC->GPREG0 = ppb; }
andrewboyson 5:a3e37ce4975d 25 void TickAddPpb (int32_t value) { ppb += value; LPC_RTC->GPREG0 = ppb; }
andrewboyson 0:33686e88f09a 26
andrewboyson 20:62e0760cae13 27 bool TickTicked = false;
andrewboyson 20:62e0760cae13 28
andrewboyson 20:62e0760cae13 29 /*
andrewboyson 20:62e0760cae13 30 +---------+---------------+
andrewboyson 20:62e0760cae13 31 | Seconds | Base count |
andrewboyson 20:62e0760cae13 32 +---------+---------------+
andrewboyson 20:62e0760cae13 33 | 0 | 0 |
andrewboyson 20:62e0760cae13 34 | 1 | 96,000,000 |
andrewboyson 20:62e0760cae13 35 | ... | ... |
andrewboyson 20:62e0760cae13 36 | 44 | 4,224,000,000 |
andrewboyson 20:62e0760cae13 37 | 44.74 | 2^32 |
andrewboyson 20:62e0760cae13 38 | 45 | 25,032,704 |
andrewboyson 20:62e0760cae13 39 | ... | ... |
andrewboyson 20:62e0760cae13 40 +---------+---------------+
andrewboyson 20:62e0760cae13 41 */
andrewboyson 20:62e0760cae13 42 static uint32_t secondsBaseCount = 0;
andrewboyson 20:62e0760cae13 43
andrewboyson 20:62e0760cae13 44 void TickSet(int64_t extClock)
andrewboyson 20:62e0760cae13 45 {
andrewboyson 21:48fe75bcde84 46 uint32_t tc = LPC_TIM0->TC;
andrewboyson 20:62e0760cae13 47 uint32_t seconds = tc / TICK_COUNT_PER_SECOND; //0 to 44
andrewboyson 20:62e0760cae13 48 uint32_t base = seconds * TICK_COUNT_PER_SECOND; //0 to 2^32
andrewboyson 20:62e0760cae13 49 uint32_t fraction = tc % TICK_COUNT_PER_SECOND; //0 to 96,000,000
andrewboyson 20:62e0760cae13 50 uint32_t fractionNs = fraction / 96 * 1000; //0 to 1,000,000,000 which fits into 32 bits
andrewboyson 20:62e0760cae13 51 int64_t ns = extClock - fractionNs;
andrewboyson 20:62e0760cae13 52
andrewboyson 20:62e0760cae13 53 __disable_irq();
andrewboyson 20:62e0760cae13 54 nsTickCount = ns;
andrewboyson 23:07b19cd5f6d0 55 nsSlewCount = 0;
andrewboyson 20:62e0760cae13 56 secondsBaseCount = base;
andrewboyson 20:62e0760cae13 57 __enable_irq();
andrewboyson 20:62e0760cae13 58
andrewboyson 20:62e0760cae13 59 nsCountIsSet = true;
andrewboyson 20:62e0760cae13 60 }
andrewboyson 18:207dd1474cd9 61 void TickMain()
andrewboyson 18:207dd1474cd9 62 {
andrewboyson 21:48fe75bcde84 63 uint32_t sincesecondsBaseCount = LPC_TIM0->TC - secondsBaseCount;
andrewboyson 20:62e0760cae13 64 if (sincesecondsBaseCount > TICK_COUNT_PER_SECOND)
andrewboyson 18:207dd1474cd9 65 {
andrewboyson 18:207dd1474cd9 66 __disable_irq();
andrewboyson 20:62e0760cae13 67 secondsBaseCount += TICK_COUNT_PER_SECOND;
andrewboyson 23:07b19cd5f6d0 68 nsTickCount += ONE_BILLION + ppb;
andrewboyson 23:07b19cd5f6d0 69 nsSlewCount += slew;
andrewboyson 18:207dd1474cd9 70 __enable_irq();
andrewboyson 20:62e0760cae13 71 slew = 0;
andrewboyson 18:207dd1474cd9 72 }
andrewboyson 0:33686e88f09a 73 }
andrewboyson 18:207dd1474cd9 74 static volatile int64_t nsTickSnapshot;
andrewboyson 23:07b19cd5f6d0 75 static volatile int64_t nsSlewSnapshot;
andrewboyson 18:207dd1474cd9 76 static volatile uint32_t timerSnapshot;
andrewboyson 0:33686e88f09a 77
andrewboyson 22:df0b906bda26 78 void TickSaveSnapshot()
andrewboyson 0:33686e88f09a 79 {
andrewboyson 21:48fe75bcde84 80 timerSnapshot = LPC_TIM0->TC - secondsBaseCount;
andrewboyson 0:33686e88f09a 81 nsTickSnapshot = nsTickCount;
andrewboyson 23:07b19cd5f6d0 82 nsSlewSnapshot = nsSlewCount;
andrewboyson 0:33686e88f09a 83 }
andrewboyson 23:07b19cd5f6d0 84 static void makeTimesFromCounts(uint32_t timerCount, int64_t tickNs, int64_t slewNs, int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 16:933cbe190bb0 85 {
andrewboyson 16:933cbe190bb0 86 int64_t fraction = timerCount;
andrewboyson 16:933cbe190bb0 87 fraction <<= 32;
andrewboyson 16:933cbe190bb0 88 fraction /= TICK_COUNT_PER_SECOND;
andrewboyson 16:933cbe190bb0 89
andrewboyson 0:33686e88f09a 90 int64_t nsFraction;
andrewboyson 0:33686e88f09a 91
andrewboyson 14:7ef557918bb1 92 int64_t nsBase = tickNs;
andrewboyson 23:07b19cd5f6d0 93 int64_t nsPerTick = ONE_BILLION + ppb;
andrewboyson 0:33686e88f09a 94 nsFraction = (nsPerTick * fraction) >> 32;
andrewboyson 0:33686e88f09a 95 *pNsInt = nsBase + nsFraction;
andrewboyson 0:33686e88f09a 96
andrewboyson 23:07b19cd5f6d0 97 nsBase += slewNs;
andrewboyson 5:a3e37ce4975d 98 nsPerTick += slew;
andrewboyson 0:33686e88f09a 99 nsFraction = (nsPerTick * fraction) >> 32;
andrewboyson 0:33686e88f09a 100 *pNsAbs = nsBase + nsFraction;
andrewboyson 0:33686e88f09a 101 }
andrewboyson 22:df0b906bda26 102 void TickGetTimesFromSnapshot(int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 14:7ef557918bb1 103 {
andrewboyson 23:07b19cd5f6d0 104 makeTimesFromCounts(timerSnapshot, nsTickSnapshot, nsSlewSnapshot, pNsInt, pNsAbs);
andrewboyson 14:7ef557918bb1 105 }
andrewboyson 6:d8a6235486b7 106 void TickGetTimes(int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 23:07b19cd5f6d0 107 {
andrewboyson 23:07b19cd5f6d0 108 makeTimesFromCounts(LPC_TIM0->TC - secondsBaseCount, nsTickCount, nsSlewCount, pNsInt, pNsAbs);
andrewboyson 0:33686e88f09a 109 }
andrewboyson 0:33686e88f09a 110
andrewboyson 17:927fc1eceb9d 111 void TickInit(void)
andrewboyson 0:33686e88f09a 112 {
andrewboyson 0:33686e88f09a 113 nsTickCount = 0;
andrewboyson 23:07b19cd5f6d0 114 nsSlewCount = 0;
andrewboyson 0:33686e88f09a 115
andrewboyson 5:a3e37ce4975d 116 ppb = LPC_RTC->GPREG0; //This is saved each time Tickppb is updated
andrewboyson 5:a3e37ce4975d 117 slew = 0;
andrewboyson 18:207dd1474cd9 118 nsCountIsSet = false;
andrewboyson 0:33686e88f09a 119
andrewboyson 21:48fe75bcde84 120 LPC_TIM0->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
andrewboyson 21:48fe75bcde84 121 LPC_TIM0->CTCR = 0; // 21.6.3 Count Control Register - Timer mode
andrewboyson 21:48fe75bcde84 122 LPC_TIM0->PR = 0; // 21.6.5 Prescale register - Don't prescale 96MHz clock (divide by PR+1).
andrewboyson 21:48fe75bcde84 123 LPC_TIM0->MCR = 0; // 21.6.8 Match Control Register - no interrupt or reset
andrewboyson 21:48fe75bcde84 124 LPC_TIM0->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC
andrewboyson 0:33686e88f09a 125 }
andrewboyson 18:207dd1474cd9 126 uint32_t TickElapsed(uint32_t* pLastTime)
andrewboyson 14:7ef557918bb1 127 {
andrewboyson 21:48fe75bcde84 128 uint32_t thisTime = LPC_TIM0->TC;
andrewboyson 18:207dd1474cd9 129 uint32_t elapsed = thisTime - *pLastTime;
andrewboyson 14:7ef557918bb1 130 *pLastTime = thisTime;
andrewboyson 14:7ef557918bb1 131 return elapsed;
andrewboyson 14:7ef557918bb1 132 }
andrewboyson 19:e537bacd1478 133 uint32_t TickTimerStart()
andrewboyson 19:e537bacd1478 134 {
andrewboyson 21:48fe75bcde84 135 return LPC_TIM0->TC;
andrewboyson 19:e537bacd1478 136 }
andrewboyson 19:e537bacd1478 137 uint32_t TickTimerCount(uint32_t startCount)
andrewboyson 19:e537bacd1478 138 {
andrewboyson 21:48fe75bcde84 139 uint32_t thisCount = LPC_TIM0->TC;
andrewboyson 19:e537bacd1478 140 return thisCount - startCount;
andrewboyson 19:e537bacd1478 141 }
andrewboyson 19:e537bacd1478 142 uint32_t TickTimerMs(uint32_t startCount)
andrewboyson 19:e537bacd1478 143 {
andrewboyson 19:e537bacd1478 144 uint32_t count = TickTimerCount(startCount);
andrewboyson 19:e537bacd1478 145 return count / 96000;
andrewboyson 19:e537bacd1478 146 }