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.cpp@5:a3e37ce4975d, 2017-07-04 (annotated)
- Committer:
- andrewboyson
- Date:
- Tue Jul 04 15:04:26 2017 +0000
- Revision:
- 5:a3e37ce4975d
- Parent:
- 4:095dfd4a316b
- Child:
- 6:d8a6235486b7
Better saved the ppb state
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| andrewboyson | 4:095dfd4a316b | 1 | #include "mbed.h" |
| andrewboyson | 4:095dfd4a316b | 2 | #include "rtc.h" |
| andrewboyson | 4:095dfd4a316b | 3 | #include "time.h" |
| andrewboyson | 4:095dfd4a316b | 4 | #include "settings.h" |
| andrewboyson | 0:33686e88f09a | 5 | |
| andrewboyson | 0:33686e88f09a | 6 | #define ONE_BILLION 1000000000 |
| andrewboyson | 0:33686e88f09a | 7 | |
| andrewboyson | 0:33686e88f09a | 8 | #define COUNT_PER_TICK 96000000 |
| andrewboyson | 0:33686e88f09a | 9 | |
| andrewboyson | 0:33686e88f09a | 10 | static int64_t nsTickCount; |
| andrewboyson | 0:33686e88f09a | 11 | static int64_t nsFreqCount; |
| andrewboyson | 0:33686e88f09a | 12 | static int64_t nsTimeCount; |
| andrewboyson | 5:a3e37ce4975d | 13 | static bool nsCountIsSet = false; |
| andrewboyson | 5:a3e37ce4975d | 14 | bool TickIsSet() { return nsCountIsSet; } |
| andrewboyson | 5:a3e37ce4975d | 15 | void TickSet(int64_t extClock) |
| andrewboyson | 5:a3e37ce4975d | 16 | { |
| andrewboyson | 5:a3e37ce4975d | 17 | nsTickCount = 0; |
| andrewboyson | 5:a3e37ce4975d | 18 | nsFreqCount = 0; |
| andrewboyson | 5:a3e37ce4975d | 19 | nsTimeCount = extClock; |
| andrewboyson | 5:a3e37ce4975d | 20 | LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC. |
| andrewboyson | 5:a3e37ce4975d | 21 | LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC. |
| andrewboyson | 5:a3e37ce4975d | 22 | nsCountIsSet = true; |
| andrewboyson | 5:a3e37ce4975d | 23 | } |
| andrewboyson | 0:33686e88f09a | 24 | |
| andrewboyson | 5:a3e37ce4975d | 25 | int32_t slew = 0; //ns - up to +/- 2.147s of slew |
| andrewboyson | 5:a3e37ce4975d | 26 | int32_t TickGetSlew() { return slew; } |
| andrewboyson | 5:a3e37ce4975d | 27 | void TickSetSlew(int32_t value) { slew = value; } |
| andrewboyson | 5:a3e37ce4975d | 28 | |
| andrewboyson | 5:a3e37ce4975d | 29 | int32_t ppb = 0; |
| andrewboyson | 5:a3e37ce4975d | 30 | int32_t TickGetPpb () { return ppb; } |
| andrewboyson | 5:a3e37ce4975d | 31 | void TickSetPpb (int32_t value) { ppb = value; LPC_RTC->GPREG0 = ppb; } |
| andrewboyson | 5:a3e37ce4975d | 32 | void TickAddPpb (int32_t value) { ppb += value; LPC_RTC->GPREG0 = ppb; } |
| andrewboyson | 0:33686e88f09a | 33 | |
| andrewboyson | 0:33686e88f09a | 34 | #define CLOCK_TIC 0 |
| andrewboyson | 0:33686e88f09a | 35 | #define CLOCK_INT 1 |
| andrewboyson | 0:33686e88f09a | 36 | #define CLOCK_ABS 2 |
| andrewboyson | 0:33686e88f09a | 37 | |
| andrewboyson | 0:33686e88f09a | 38 | static void tick(void) //Called from main if the timer has overflowed |
| andrewboyson | 0:33686e88f09a | 39 | { |
| andrewboyson | 0:33686e88f09a | 40 | //Reset the timer interrupt |
| andrewboyson | 0:33686e88f09a | 41 | LPC_TIM1->IR |= 1; |
| andrewboyson | 0:33686e88f09a | 42 | |
| andrewboyson | 0:33686e88f09a | 43 | //reset the tick timer |
| andrewboyson | 0:33686e88f09a | 44 | LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC. |
| andrewboyson | 0:33686e88f09a | 45 | LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC |
| andrewboyson | 0:33686e88f09a | 46 | |
| andrewboyson | 0:33686e88f09a | 47 | //Calculate the new counts |
| andrewboyson | 0:33686e88f09a | 48 | nsTickCount += ONE_BILLION; |
| andrewboyson | 5:a3e37ce4975d | 49 | nsFreqCount += ppb; |
| andrewboyson | 5:a3e37ce4975d | 50 | nsTimeCount += slew; |
| andrewboyson | 0:33686e88f09a | 51 | |
| andrewboyson | 0:33686e88f09a | 52 | //Feedback the amount slewed |
| andrewboyson | 5:a3e37ce4975d | 53 | slew = 0; |
| andrewboyson | 0:33686e88f09a | 54 | } |
| andrewboyson | 0:33686e88f09a | 55 | static volatile int64_t nsTickSnapshot; |
| andrewboyson | 0:33686e88f09a | 56 | static volatile int64_t nsFreqSnapshot; |
| andrewboyson | 0:33686e88f09a | 57 | static volatile int64_t nsTimeSnapshot; |
| andrewboyson | 0:33686e88f09a | 58 | static volatile int32_t timerSnapshot; |
| andrewboyson | 0:33686e88f09a | 59 | |
| andrewboyson | 0:33686e88f09a | 60 | void TickSaveSnapshotI() |
| andrewboyson | 0:33686e88f09a | 61 | { |
| andrewboyson | 0:33686e88f09a | 62 | timerSnapshot = LPC_TIM1->TC; |
| andrewboyson | 0:33686e88f09a | 63 | nsTickSnapshot = nsTickCount; |
| andrewboyson | 0:33686e88f09a | 64 | nsFreqSnapshot = nsFreqCount; |
| andrewboyson | 0:33686e88f09a | 65 | nsTimeSnapshot = nsTimeCount; |
| andrewboyson | 0:33686e88f09a | 66 | } |
| andrewboyson | 0:33686e88f09a | 67 | void TickRetrieveSnapshot(int64_t* pNsInt, int64_t* pNsAbs) |
| andrewboyson | 0:33686e88f09a | 68 | { |
| andrewboyson | 0:33686e88f09a | 69 | int64_t fraction = ((int64_t)timerSnapshot << 32) / COUNT_PER_TICK; |
| andrewboyson | 0:33686e88f09a | 70 | int64_t nsFraction; |
| andrewboyson | 0:33686e88f09a | 71 | |
| andrewboyson | 0:33686e88f09a | 72 | int64_t nsBase = nsTickSnapshot; |
| andrewboyson | 0:33686e88f09a | 73 | int64_t nsPerTick = ONE_BILLION; |
| andrewboyson | 0:33686e88f09a | 74 | |
| andrewboyson | 0:33686e88f09a | 75 | nsBase += nsFreqSnapshot; |
| andrewboyson | 5:a3e37ce4975d | 76 | nsPerTick += ppb; |
| andrewboyson | 0:33686e88f09a | 77 | nsFraction = (nsPerTick * fraction) >> 32; |
| andrewboyson | 0:33686e88f09a | 78 | *pNsInt = nsBase + nsFraction; |
| andrewboyson | 0:33686e88f09a | 79 | |
| andrewboyson | 0:33686e88f09a | 80 | nsBase += nsTimeSnapshot; |
| andrewboyson | 5:a3e37ce4975d | 81 | nsPerTick += slew; |
| andrewboyson | 0:33686e88f09a | 82 | nsFraction = (nsPerTick * fraction) >> 32; |
| andrewboyson | 0:33686e88f09a | 83 | *pNsAbs = nsBase + nsFraction; |
| andrewboyson | 0:33686e88f09a | 84 | } |
| andrewboyson | 0:33686e88f09a | 85 | static int64_t getClock(char index) |
| andrewboyson | 0:33686e88f09a | 86 | { |
| andrewboyson | 0:33686e88f09a | 87 | //Get the base and fractional values while protected from a tick interrupt |
| andrewboyson | 0:33686e88f09a | 88 | __disable_irq(); |
| andrewboyson | 0:33686e88f09a | 89 | int64_t nsBase = nsTickCount; |
| andrewboyson | 0:33686e88f09a | 90 | int64_t nsPerTick = ONE_BILLION; |
| andrewboyson | 0:33686e88f09a | 91 | if (index >= CLOCK_INT) |
| andrewboyson | 0:33686e88f09a | 92 | { |
| andrewboyson | 0:33686e88f09a | 93 | nsBase += nsFreqCount; |
| andrewboyson | 5:a3e37ce4975d | 94 | nsPerTick += ppb; |
| andrewboyson | 0:33686e88f09a | 95 | } |
| andrewboyson | 0:33686e88f09a | 96 | if (index >= CLOCK_ABS) |
| andrewboyson | 0:33686e88f09a | 97 | { |
| andrewboyson | 0:33686e88f09a | 98 | nsBase += nsTimeCount; |
| andrewboyson | 5:a3e37ce4975d | 99 | nsPerTick += slew; |
| andrewboyson | 0:33686e88f09a | 100 | } |
| andrewboyson | 0:33686e88f09a | 101 | int32_t count = LPC_TIM1->TC; |
| andrewboyson | 0:33686e88f09a | 102 | __enable_irq(); |
| andrewboyson | 0:33686e88f09a | 103 | |
| andrewboyson | 0:33686e88f09a | 104 | //Now calculate everything |
| andrewboyson | 0:33686e88f09a | 105 | int64_t fraction = ((int64_t)count << 32) / COUNT_PER_TICK; |
| andrewboyson | 0:33686e88f09a | 106 | int64_t nsFraction = (nsPerTick * fraction) >> 32; |
| andrewboyson | 0:33686e88f09a | 107 | |
| andrewboyson | 0:33686e88f09a | 108 | //Return the base plus the fractional part |
| andrewboyson | 0:33686e88f09a | 109 | return nsBase + nsFraction; |
| andrewboyson | 0:33686e88f09a | 110 | |
| andrewboyson | 0:33686e88f09a | 111 | } |
| andrewboyson | 0:33686e88f09a | 112 | int64_t TickGetTic() {return getClock(CLOCK_TIC); } |
| andrewboyson | 0:33686e88f09a | 113 | int64_t TickGetInt() {return getClock(CLOCK_INT); } |
| andrewboyson | 0:33686e88f09a | 114 | int64_t TickGetAbs() {return getClock(CLOCK_ABS); } |
| andrewboyson | 0:33686e88f09a | 115 | |
| andrewboyson | 0:33686e88f09a | 116 | int TickInit(void) |
| andrewboyson | 0:33686e88f09a | 117 | { |
| andrewboyson | 0:33686e88f09a | 118 | nsTickCount = 0; |
| andrewboyson | 0:33686e88f09a | 119 | nsFreqCount = 0; |
| andrewboyson | 0:33686e88f09a | 120 | nsTimeCount = 0; |
| andrewboyson | 0:33686e88f09a | 121 | |
| andrewboyson | 5:a3e37ce4975d | 122 | ppb = LPC_RTC->GPREG0; //This is saved each time Tickppb is updated |
| andrewboyson | 5:a3e37ce4975d | 123 | slew = 0; |
| andrewboyson | 5:a3e37ce4975d | 124 | nsCountIsSet = false; |
| andrewboyson | 0:33686e88f09a | 125 | |
| andrewboyson | 0:33686e88f09a | 126 | LPC_SC->PCLKSEL0 &= ~0x20; // 4.7.3 Peripheral Clock Selection - PCLK_peripheral PCLK_TIMER1 01xxxx = CCLK - reset bit 5 |
| andrewboyson | 0:33686e88f09a | 127 | LPC_SC->PCLKSEL0 |= 0x10; // set bit 4 |
| andrewboyson | 0:33686e88f09a | 128 | LPC_SC->PCONP |= 4; // 4.8.9 Power Control for Peripherals register - Timer1 Power On |
| andrewboyson | 0:33686e88f09a | 129 | LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC. |
| andrewboyson | 0:33686e88f09a | 130 | LPC_TIM1->CTCR = 0; // 21.6.3 Count Control Register - Timer mode |
| andrewboyson | 0:33686e88f09a | 131 | LPC_TIM1->PR = 0; // 21.6.5 Prescale register - Don't prescale 96MHz clock (divide by PR+1). |
| andrewboyson | 0:33686e88f09a | 132 | LPC_TIM1->MR0 = COUNT_PER_TICK; // 21.6.7 Match Register 0 - Match count |
| andrewboyson | 0:33686e88f09a | 133 | LPC_TIM1->MCR = 1; // 21.6.8 Match Control Register - interrupt on match |
| andrewboyson | 0:33686e88f09a | 134 | LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC |
| andrewboyson | 0:33686e88f09a | 135 | |
| andrewboyson | 0:33686e88f09a | 136 | NVIC_SetVector(TIMER1_IRQn, (uint32_t)&tick); |
| andrewboyson | 0:33686e88f09a | 137 | NVIC_EnableIRQ(TIMER1_IRQn); |
| andrewboyson | 0:33686e88f09a | 138 | |
| andrewboyson | 0:33686e88f09a | 139 | return 0; |
| andrewboyson | 0:33686e88f09a | 140 | } |