Andrew Boyson / clock

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Tue Jan 16 17:38:12 2018 +0000
Revision:
18:207dd1474cd9
Parent:
17:927fc1eceb9d
Child:
19:e537bacd1478
Made counter work continuously without the need for interrupts

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 16:933cbe190bb0 14 static volatile int64_t nsFreqCount;
andrewboyson 16:933cbe190bb0 15 static volatile int64_t nsTimeCount;
andrewboyson 16:933cbe190bb0 16
andrewboyson 18:207dd1474cd9 17 static bool nsCountIsSet = false;
andrewboyson 18:207dd1474cd9 18 bool TickIsSet() { return nsCountIsSet; }
andrewboyson 5:a3e37ce4975d 19 void TickSet(int64_t extClock)
andrewboyson 5:a3e37ce4975d 20 {
andrewboyson 18:207dd1474cd9 21 nsTickCount = 0;
andrewboyson 18:207dd1474cd9 22 nsFreqCount = 0;
andrewboyson 18:207dd1474cd9 23 nsTimeCount = extClock - LPC_TIM1->TC;
andrewboyson 18:207dd1474cd9 24 nsCountIsSet = true;
andrewboyson 5:a3e37ce4975d 25 }
andrewboyson 0:33686e88f09a 26
andrewboyson 16:933cbe190bb0 27 static volatile int32_t slew = 0; //ns - up to +/- 2.147s of slew
andrewboyson 5:a3e37ce4975d 28 int32_t TickGetSlew() { return slew; }
andrewboyson 5:a3e37ce4975d 29 void TickSetSlew(int32_t value) { slew = value; }
andrewboyson 5:a3e37ce4975d 30
andrewboyson 16:933cbe190bb0 31 static volatile int32_t ppb = 0;
andrewboyson 5:a3e37ce4975d 32 int32_t TickGetPpb () { return ppb; }
andrewboyson 5:a3e37ce4975d 33 void TickSetPpb (int32_t value) { ppb = value; LPC_RTC->GPREG0 = ppb; }
andrewboyson 5:a3e37ce4975d 34 void TickAddPpb (int32_t value) { ppb += value; LPC_RTC->GPREG0 = ppb; }
andrewboyson 0:33686e88f09a 35
andrewboyson 18:207dd1474cd9 36 static uint32_t lastCall = 0;
andrewboyson 18:207dd1474cd9 37 void TickMain()
andrewboyson 18:207dd1474cd9 38 {
andrewboyson 18:207dd1474cd9 39 uint32_t sinceLastCall = LPC_TIM1->TC - lastCall;
andrewboyson 18:207dd1474cd9 40 if (sinceLastCall > TICK_COUNT_PER_SECOND)
andrewboyson 18:207dd1474cd9 41 {
andrewboyson 18:207dd1474cd9 42 __disable_irq();
andrewboyson 18:207dd1474cd9 43 lastCall += TICK_COUNT_PER_SECOND;
andrewboyson 18:207dd1474cd9 44 nsTickCount += ONE_BILLION;
andrewboyson 18:207dd1474cd9 45 nsFreqCount += ppb;
andrewboyson 18:207dd1474cd9 46 nsTimeCount += slew;
andrewboyson 18:207dd1474cd9 47 slew = 0;
andrewboyson 18:207dd1474cd9 48 __enable_irq();
andrewboyson 18:207dd1474cd9 49 }
andrewboyson 0:33686e88f09a 50 }
andrewboyson 18:207dd1474cd9 51 static volatile int64_t nsTickSnapshot;
andrewboyson 18:207dd1474cd9 52 static volatile int64_t nsFreqSnapshot;
andrewboyson 18:207dd1474cd9 53 static volatile int64_t nsTimeSnapshot;
andrewboyson 18:207dd1474cd9 54 static volatile uint32_t timerSnapshot;
andrewboyson 0:33686e88f09a 55
andrewboyson 0:33686e88f09a 56 void TickSaveSnapshotI()
andrewboyson 0:33686e88f09a 57 {
andrewboyson 18:207dd1474cd9 58 timerSnapshot = LPC_TIM1->TC - lastCall;
andrewboyson 0:33686e88f09a 59 nsTickSnapshot = nsTickCount;
andrewboyson 0:33686e88f09a 60 nsFreqSnapshot = nsFreqCount;
andrewboyson 0:33686e88f09a 61 nsTimeSnapshot = nsTimeCount;
andrewboyson 0:33686e88f09a 62 }
andrewboyson 18:207dd1474cd9 63 static void makeTimesFromCounts(uint32_t timerCount, int64_t tickNs, int64_t freqNs, int64_t timeNs, int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 16:933cbe190bb0 64 {
andrewboyson 16:933cbe190bb0 65 int64_t fraction = timerCount;
andrewboyson 16:933cbe190bb0 66 fraction <<= 32;
andrewboyson 16:933cbe190bb0 67 fraction /= TICK_COUNT_PER_SECOND;
andrewboyson 16:933cbe190bb0 68
andrewboyson 0:33686e88f09a 69 int64_t nsFraction;
andrewboyson 0:33686e88f09a 70
andrewboyson 14:7ef557918bb1 71 int64_t nsBase = tickNs;
andrewboyson 0:33686e88f09a 72 int64_t nsPerTick = ONE_BILLION;
andrewboyson 16:933cbe190bb0 73
andrewboyson 14:7ef557918bb1 74 nsBase += freqNs;
andrewboyson 5:a3e37ce4975d 75 nsPerTick += ppb;
andrewboyson 0:33686e88f09a 76 nsFraction = (nsPerTick * fraction) >> 32;
andrewboyson 0:33686e88f09a 77 *pNsInt = nsBase + nsFraction;
andrewboyson 0:33686e88f09a 78
andrewboyson 14:7ef557918bb1 79 nsBase += timeNs;
andrewboyson 5:a3e37ce4975d 80 nsPerTick += slew;
andrewboyson 0:33686e88f09a 81 nsFraction = (nsPerTick * fraction) >> 32;
andrewboyson 0:33686e88f09a 82 *pNsAbs = nsBase + nsFraction;
andrewboyson 0:33686e88f09a 83 }
andrewboyson 14:7ef557918bb1 84 void TickRetrieveSnapshot(int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 14:7ef557918bb1 85 {
andrewboyson 14:7ef557918bb1 86 makeTimesFromCounts(timerSnapshot, nsTickSnapshot, nsFreqSnapshot, nsTimeSnapshot, pNsInt, pNsAbs);
andrewboyson 14:7ef557918bb1 87 }
andrewboyson 6:d8a6235486b7 88 void TickGetTimes(int64_t* pNsInt, int64_t* pNsAbs)
andrewboyson 0:33686e88f09a 89 {
andrewboyson 18:207dd1474cd9 90 uint32_t timerCount;
andrewboyson 18:207dd1474cd9 91 int64_t tickNs;
andrewboyson 18:207dd1474cd9 92 int64_t freqNs;
andrewboyson 18:207dd1474cd9 93 int64_t timeNs;
andrewboyson 14:7ef557918bb1 94
andrewboyson 0:33686e88f09a 95 __disable_irq();
andrewboyson 18:207dd1474cd9 96 timerCount = LPC_TIM1->TC - lastCall;
andrewboyson 14:7ef557918bb1 97 tickNs = nsTickCount;
andrewboyson 14:7ef557918bb1 98 freqNs = nsFreqCount;
andrewboyson 14:7ef557918bb1 99 timeNs = nsTimeCount;
andrewboyson 0:33686e88f09a 100 __enable_irq();
andrewboyson 6:d8a6235486b7 101
andrewboyson 14:7ef557918bb1 102 makeTimesFromCounts(timerCount, tickNs, freqNs, timeNs, pNsInt, pNsAbs);
andrewboyson 0:33686e88f09a 103 }
andrewboyson 0:33686e88f09a 104
andrewboyson 17:927fc1eceb9d 105 void TickInit(void)
andrewboyson 0:33686e88f09a 106 {
andrewboyson 0:33686e88f09a 107 nsTickCount = 0;
andrewboyson 0:33686e88f09a 108 nsFreqCount = 0;
andrewboyson 0:33686e88f09a 109 nsTimeCount = 0;
andrewboyson 0:33686e88f09a 110
andrewboyson 5:a3e37ce4975d 111 ppb = LPC_RTC->GPREG0; //This is saved each time Tickppb is updated
andrewboyson 5:a3e37ce4975d 112 slew = 0;
andrewboyson 18:207dd1474cd9 113 nsCountIsSet = false;
andrewboyson 0:33686e88f09a 114
andrewboyson 14:7ef557918bb1 115 LPC_SC->PCONP |= 4; // 4.8.9 Power Control for Peripherals register - Timer1 Power On
andrewboyson 14:7ef557918bb1 116 LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
andrewboyson 14:7ef557918bb1 117 LPC_TIM1->CTCR = 0; // 21.6.3 Count Control Register - Timer mode
andrewboyson 14:7ef557918bb1 118 LPC_TIM1->PR = 0; // 21.6.5 Prescale register - Don't prescale 96MHz clock (divide by PR+1).
andrewboyson 18:207dd1474cd9 119 LPC_TIM1->MCR = 0; // 21.6.8 Match Control Register - no interrupt or reset
andrewboyson 14:7ef557918bb1 120 LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC
andrewboyson 0:33686e88f09a 121 }
andrewboyson 18:207dd1474cd9 122 uint32_t TickElapsed(uint32_t* pLastTime)
andrewboyson 14:7ef557918bb1 123 {
andrewboyson 18:207dd1474cd9 124 uint32_t thisTime = LPC_TIM1->TC;
andrewboyson 18:207dd1474cd9 125 uint32_t elapsed = thisTime - *pLastTime;
andrewboyson 14:7ef557918bb1 126 *pLastTime = thisTime;
andrewboyson 14:7ef557918bb1 127 return elapsed;
andrewboyson 14:7ef557918bb1 128 }