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@25:81014a201736, 2018-01-22 (annotated)
- Committer:
- andrewboyson
- Date:
- Mon Jan 22 18:54:23 2018 +0000
- Revision:
- 25:81014a201736
- Parent:
- 24:6c9833e2a049
- Child:
- 26:0421132e6eaf
Moved timer defines from tick to timer
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 | 24:6c9833e2a049 | 5 | #include "rtc.h" |
| andrewboyson | 14:7ef557918bb1 | 6 | #include "time.h" |
| andrewboyson | 14:7ef557918bb1 | 7 | #include "tick.h" |
| andrewboyson | 24:6c9833e2a049 | 8 | #include "timer.h" |
| andrewboyson | 18:207dd1474cd9 | 9 | #include "led.h" |
| andrewboyson | 18:207dd1474cd9 | 10 | #include "log.h" |
| andrewboyson | 0:33686e88f09a | 11 | |
| andrewboyson | 0:33686e88f09a | 12 | #define ONE_BILLION 1000000000 |
| andrewboyson | 0:33686e88f09a | 13 | |
| andrewboyson | 16:933cbe190bb0 | 14 | static volatile int64_t nsTickCount; |
| andrewboyson | 23:07b19cd5f6d0 | 15 | static volatile int64_t nsSlewCount; |
| andrewboyson | 18:207dd1474cd9 | 16 | static bool nsCountIsSet = false; |
| andrewboyson | 18:207dd1474cd9 | 17 | bool TickIsSet() { return nsCountIsSet; } |
| andrewboyson | 0:33686e88f09a | 18 | |
| andrewboyson | 16:933cbe190bb0 | 19 | static volatile int32_t slew = 0; //ns - up to +/- 2.147s of slew |
| andrewboyson | 5:a3e37ce4975d | 20 | int32_t TickGetSlew() { return slew; } |
| andrewboyson | 5:a3e37ce4975d | 21 | void TickSetSlew(int32_t value) { slew = value; } |
| andrewboyson | 5:a3e37ce4975d | 22 | |
| andrewboyson | 16:933cbe190bb0 | 23 | static volatile int32_t ppb = 0; |
| andrewboyson | 5:a3e37ce4975d | 24 | int32_t TickGetPpb () { return ppb; } |
| andrewboyson | 5:a3e37ce4975d | 25 | void TickSetPpb (int32_t value) { ppb = value; LPC_RTC->GPREG0 = ppb; } |
| andrewboyson | 5:a3e37ce4975d | 26 | void TickAddPpb (int32_t value) { ppb += value; LPC_RTC->GPREG0 = ppb; } |
| andrewboyson | 0:33686e88f09a | 27 | |
| andrewboyson | 20:62e0760cae13 | 28 | bool TickTicked = false; |
| andrewboyson | 20:62e0760cae13 | 29 | |
| andrewboyson | 20:62e0760cae13 | 30 | /* |
| andrewboyson | 20:62e0760cae13 | 31 | +---------+---------------+ |
| andrewboyson | 20:62e0760cae13 | 32 | | Seconds | Base count | |
| andrewboyson | 20:62e0760cae13 | 33 | +---------+---------------+ |
| andrewboyson | 20:62e0760cae13 | 34 | | 0 | 0 | |
| andrewboyson | 20:62e0760cae13 | 35 | | 1 | 96,000,000 | |
| andrewboyson | 20:62e0760cae13 | 36 | | ... | ... | |
| andrewboyson | 20:62e0760cae13 | 37 | | 44 | 4,224,000,000 | |
| andrewboyson | 20:62e0760cae13 | 38 | | 44.74 | 2^32 | |
| andrewboyson | 20:62e0760cae13 | 39 | | 45 | 25,032,704 | |
| andrewboyson | 20:62e0760cae13 | 40 | | ... | ... | |
| andrewboyson | 20:62e0760cae13 | 41 | +---------+---------------+ |
| andrewboyson | 20:62e0760cae13 | 42 | */ |
| andrewboyson | 20:62e0760cae13 | 43 | static uint32_t secondsBaseCount = 0; |
| andrewboyson | 20:62e0760cae13 | 44 | |
| andrewboyson | 24:6c9833e2a049 | 45 | int64_t TickTime = 0; //30th bit is one second |
| andrewboyson | 24:6c9833e2a049 | 46 | |
| andrewboyson | 20:62e0760cae13 | 47 | void TickSet(int64_t extClock) |
| andrewboyson | 20:62e0760cae13 | 48 | { |
| andrewboyson | 24:6c9833e2a049 | 49 | uint32_t tc = TimerNowCount(); |
| andrewboyson | 25:81014a201736 | 50 | uint32_t seconds = tc / TIMER_COUNT_PER_SECOND; //0 to 44 |
| andrewboyson | 25:81014a201736 | 51 | uint32_t base = seconds * TIMER_COUNT_PER_SECOND; //0 to 2^32 |
| andrewboyson | 25:81014a201736 | 52 | uint32_t fraction = tc % TIMER_COUNT_PER_SECOND; //0 to 96,000,000 |
| andrewboyson | 20:62e0760cae13 | 53 | uint32_t fractionNs = fraction / 96 * 1000; //0 to 1,000,000,000 which fits into 32 bits |
| andrewboyson | 20:62e0760cae13 | 54 | int64_t ns = extClock - fractionNs; |
| andrewboyson | 20:62e0760cae13 | 55 | |
| andrewboyson | 20:62e0760cae13 | 56 | __disable_irq(); |
| andrewboyson | 20:62e0760cae13 | 57 | nsTickCount = ns; |
| andrewboyson | 23:07b19cd5f6d0 | 58 | nsSlewCount = 0; |
| andrewboyson | 20:62e0760cae13 | 59 | secondsBaseCount = base; |
| andrewboyson | 20:62e0760cae13 | 60 | __enable_irq(); |
| andrewboyson | 20:62e0760cae13 | 61 | |
| andrewboyson | 20:62e0760cae13 | 62 | nsCountIsSet = true; |
| andrewboyson | 20:62e0760cae13 | 63 | } |
| andrewboyson | 18:207dd1474cd9 | 64 | void TickMain() |
| andrewboyson | 18:207dd1474cd9 | 65 | { |
| andrewboyson | 24:6c9833e2a049 | 66 | uint32_t sinceSecondsBaseCount = TimerSinceCount(secondsBaseCount); |
| andrewboyson | 24:6c9833e2a049 | 67 | |
| andrewboyson | 24:6c9833e2a049 | 68 | //Update the times whenever there has been a system second |
| andrewboyson | 25:81014a201736 | 69 | if (sinceSecondsBaseCount > TIMER_COUNT_PER_SECOND) |
| andrewboyson | 18:207dd1474cd9 | 70 | { |
| andrewboyson | 18:207dd1474cd9 | 71 | __disable_irq(); |
| andrewboyson | 25:81014a201736 | 72 | secondsBaseCount += TIMER_COUNT_PER_SECOND; |
| andrewboyson | 23:07b19cd5f6d0 | 73 | nsTickCount += ONE_BILLION + ppb; |
| andrewboyson | 23:07b19cd5f6d0 | 74 | nsSlewCount += slew; |
| andrewboyson | 24:6c9833e2a049 | 75 | slew = 0; |
| andrewboyson | 18:207dd1474cd9 | 76 | __enable_irq(); |
| andrewboyson | 25:81014a201736 | 77 | sinceSecondsBaseCount -= TIMER_COUNT_PER_SECOND; |
| andrewboyson | 18:207dd1474cd9 | 78 | } |
| andrewboyson | 24:6c9833e2a049 | 79 | |
| andrewboyson | 24:6c9833e2a049 | 80 | //Update TickTime |
| andrewboyson | 24:6c9833e2a049 | 81 | int64_t fraction = sinceSecondsBaseCount; |
| andrewboyson | 24:6c9833e2a049 | 82 | fraction <<= 32; |
| andrewboyson | 25:81014a201736 | 83 | fraction /= TIMER_COUNT_PER_SECOND; |
| andrewboyson | 24:6c9833e2a049 | 84 | |
| andrewboyson | 24:6c9833e2a049 | 85 | int64_t nsBase = nsTickCount + nsSlewCount; |
| andrewboyson | 24:6c9833e2a049 | 86 | int64_t nsPerTick = ONE_BILLION + ppb + slew; |
| andrewboyson | 24:6c9833e2a049 | 87 | int64_t nsFraction = (nsPerTick * fraction) >> 32; |
| andrewboyson | 24:6c9833e2a049 | 88 | TickTime = nsBase + nsFraction; |
| andrewboyson | 24:6c9833e2a049 | 89 | |
| andrewboyson | 24:6c9833e2a049 | 90 | //Update the ticked flag |
| andrewboyson | 24:6c9833e2a049 | 91 | static bool lastTick = false; |
| andrewboyson | 24:6c9833e2a049 | 92 | bool thisTick = TickTime & (1ULL << 30); |
| andrewboyson | 24:6c9833e2a049 | 93 | TickTicked = thisTick && !lastTick; |
| andrewboyson | 24:6c9833e2a049 | 94 | lastTick = TickTicked; |
| andrewboyson | 24:6c9833e2a049 | 95 | |
| andrewboyson | 0:33686e88f09a | 96 | } |
| andrewboyson | 18:207dd1474cd9 | 97 | static volatile int64_t nsTickSnapshot; |
| andrewboyson | 23:07b19cd5f6d0 | 98 | static volatile int64_t nsSlewSnapshot; |
| andrewboyson | 18:207dd1474cd9 | 99 | static volatile uint32_t timerSnapshot; |
| andrewboyson | 0:33686e88f09a | 100 | |
| andrewboyson | 22:df0b906bda26 | 101 | void TickSaveSnapshot() |
| andrewboyson | 0:33686e88f09a | 102 | { |
| andrewboyson | 24:6c9833e2a049 | 103 | timerSnapshot = TimerSinceCount(secondsBaseCount); |
| andrewboyson | 0:33686e88f09a | 104 | nsTickSnapshot = nsTickCount; |
| andrewboyson | 23:07b19cd5f6d0 | 105 | nsSlewSnapshot = nsSlewCount; |
| andrewboyson | 0:33686e88f09a | 106 | } |
| andrewboyson | 23:07b19cd5f6d0 | 107 | static void makeTimesFromCounts(uint32_t timerCount, int64_t tickNs, int64_t slewNs, int64_t* pNsInt, int64_t* pNsAbs) |
| andrewboyson | 16:933cbe190bb0 | 108 | { |
| andrewboyson | 16:933cbe190bb0 | 109 | int64_t fraction = timerCount; |
| andrewboyson | 16:933cbe190bb0 | 110 | fraction <<= 32; |
| andrewboyson | 25:81014a201736 | 111 | fraction /= TIMER_COUNT_PER_SECOND; |
| andrewboyson | 16:933cbe190bb0 | 112 | |
| andrewboyson | 0:33686e88f09a | 113 | int64_t nsFraction; |
| andrewboyson | 0:33686e88f09a | 114 | |
| andrewboyson | 14:7ef557918bb1 | 115 | int64_t nsBase = tickNs; |
| andrewboyson | 23:07b19cd5f6d0 | 116 | int64_t nsPerTick = ONE_BILLION + ppb; |
| andrewboyson | 0:33686e88f09a | 117 | nsFraction = (nsPerTick * fraction) >> 32; |
| andrewboyson | 0:33686e88f09a | 118 | *pNsInt = nsBase + nsFraction; |
| andrewboyson | 0:33686e88f09a | 119 | |
| andrewboyson | 23:07b19cd5f6d0 | 120 | nsBase += slewNs; |
| andrewboyson | 5:a3e37ce4975d | 121 | nsPerTick += slew; |
| andrewboyson | 0:33686e88f09a | 122 | nsFraction = (nsPerTick * fraction) >> 32; |
| andrewboyson | 0:33686e88f09a | 123 | *pNsAbs = nsBase + nsFraction; |
| andrewboyson | 0:33686e88f09a | 124 | } |
| andrewboyson | 22:df0b906bda26 | 125 | void TickGetTimesFromSnapshot(int64_t* pNsInt, int64_t* pNsAbs) |
| andrewboyson | 14:7ef557918bb1 | 126 | { |
| andrewboyson | 23:07b19cd5f6d0 | 127 | makeTimesFromCounts(timerSnapshot, nsTickSnapshot, nsSlewSnapshot, pNsInt, pNsAbs); |
| andrewboyson | 14:7ef557918bb1 | 128 | } |
| andrewboyson | 6:d8a6235486b7 | 129 | void TickGetTimes(int64_t* pNsInt, int64_t* pNsAbs) |
| andrewboyson | 23:07b19cd5f6d0 | 130 | { |
| andrewboyson | 24:6c9833e2a049 | 131 | makeTimesFromCounts(TimerSinceCount(secondsBaseCount), nsTickCount, nsSlewCount, pNsInt, pNsAbs); |
| andrewboyson | 0:33686e88f09a | 132 | } |
| andrewboyson | 17:927fc1eceb9d | 133 | void TickInit(void) |
| andrewboyson | 0:33686e88f09a | 134 | { |
| andrewboyson | 0:33686e88f09a | 135 | nsTickCount = 0; |
| andrewboyson | 23:07b19cd5f6d0 | 136 | nsSlewCount = 0; |
| andrewboyson | 0:33686e88f09a | 137 | |
| andrewboyson | 5:a3e37ce4975d | 138 | ppb = LPC_RTC->GPREG0; //This is saved each time Tickppb is updated |
| andrewboyson | 5:a3e37ce4975d | 139 | slew = 0; |
| andrewboyson | 18:207dd1474cd9 | 140 | nsCountIsSet = false; |
| andrewboyson | 24:6c9833e2a049 | 141 | } |