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
tick.c@18:207dd1474cd9, 2018-01-16 (annotated)
- 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?
| User | Revision | Line number | New 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 | } |