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
Diff: tick.c
- Revision:
- 17:927fc1eceb9d
- Parent:
- 16:933cbe190bb0
- Child:
- 18:207dd1474cd9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tick.c Thu Jan 11 17:39:36 2018 +0000
@@ -0,0 +1,152 @@
+#include "peripherals.h"
+#include "rtc.h"
+#include "time.h"
+#include "tick.h"
+
+#define TRUE 1
+#define FALSE 0
+
+#define ONE_BILLION 1000000000
+
+static volatile int64_t nsTickCount;
+static volatile int64_t nsFreqCount;
+static volatile int64_t nsTimeCount;
+
+static int nsCountIsSet = FALSE;
+int TickIsSet() { return nsCountIsSet; }
+void TickSet(int64_t extClock)
+{
+ nsTickCount = 0;
+ nsFreqCount = 0;
+ nsTimeCount = extClock;
+ LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
+ LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC.
+ nsCountIsSet = TRUE;
+}
+
+static volatile int32_t slew = 0; //ns - up to +/- 2.147s of slew
+int32_t TickGetSlew() { return slew; }
+void TickSetSlew(int32_t value) { slew = value; }
+
+static volatile int32_t ppb = 0;
+int32_t TickGetPpb () { return ppb; }
+void TickSetPpb (int32_t value) { ppb = value; LPC_RTC->GPREG0 = ppb; }
+void TickAddPpb (int32_t value) { ppb += value; LPC_RTC->GPREG0 = ppb; }
+
+#define CLOCK_TIC 0
+#define CLOCK_INT 1
+#define CLOCK_ABS 2
+
+__irq void TickHandler(void)
+{//Checked the number of counts and this routine takes 46 counts or about 0.5us
+
+ //Reset the timer interrupt
+ LPC_TIM1->IR |= 1;
+
+ //reset the tick timer
+ LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
+ LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC
+
+ //Calculate the new counts
+ nsTickCount += ONE_BILLION;
+ nsFreqCount += ppb;
+ nsTimeCount += slew;
+
+ //Feedback the amount slewed
+ slew = 0;
+}
+static volatile int64_t nsTickSnapshot;
+static volatile int64_t nsFreqSnapshot;
+static volatile int64_t nsTimeSnapshot;
+static volatile int32_t timerSnapshot;
+
+void TickSaveSnapshotI()
+{
+ timerSnapshot = LPC_TIM1->TC;
+ nsTickSnapshot = nsTickCount;
+ nsFreqSnapshot = nsFreqCount;
+ nsTimeSnapshot = nsTimeCount;
+}
+static void makeTimesFromCounts(int32_t timerCount, int64_t tickNs, int64_t freqNs, int64_t timeNs, int64_t* pNsInt, int64_t* pNsAbs)
+{
+ int64_t fraction = timerCount;
+ fraction <<= 32;
+ fraction /= TICK_COUNT_PER_SECOND;
+
+ int64_t nsFraction;
+
+ int64_t nsBase = tickNs;
+ int64_t nsPerTick = ONE_BILLION;
+
+ nsBase += freqNs;
+ nsPerTick += ppb;
+ nsFraction = (nsPerTick * fraction) >> 32;
+ *pNsInt = nsBase + nsFraction;
+
+ nsBase += timeNs;
+ nsPerTick += slew;
+ nsFraction = (nsPerTick * fraction) >> 32;
+ *pNsAbs = nsBase + nsFraction;
+}
+void TickRetrieveSnapshot(int64_t* pNsInt, int64_t* pNsAbs)
+{
+ makeTimesFromCounts(timerSnapshot, nsTickSnapshot, nsFreqSnapshot, nsTimeSnapshot, pNsInt, pNsAbs);
+}
+void TickGetTimes(int64_t* pNsInt, int64_t* pNsAbs)
+{
+ int32_t timerCount;
+ int64_t tickNs;
+ int64_t freqNs;
+ int64_t timeNs;
+
+ __disable_irq();
+ timerCount = LPC_TIM1->TC;
+ tickNs = nsTickCount;
+ freqNs = nsFreqCount;
+ timeNs = nsTimeCount;
+ __enable_irq();
+
+ makeTimesFromCounts(timerCount, tickNs, freqNs, timeNs, pNsInt, pNsAbs);
+}
+
+void TickInit(void)
+{
+ nsTickCount = 0;
+ nsFreqCount = 0;
+ nsTimeCount = 0;
+
+ ppb = LPC_RTC->GPREG0; //This is saved each time Tickppb is updated
+ slew = 0;
+ nsCountIsSet = FALSE;
+
+ LPC_SC->PCLKSEL0 &= ~0x20; // 4.7.3 Peripheral Clock Selection - PCLK_peripheral PCLK_TIMER1 01xxxx = CCLK - reset bit 5
+ LPC_SC->PCLKSEL0 |= 0x10; // set bit 4
+ LPC_SC->PCONP |= 4; // 4.8.9 Power Control for Peripherals register - Timer1 Power On
+ LPC_TIM1->TCR = 2; // 21.6.2 Timer Control Register - Reset TC and PC.
+ LPC_TIM1->CTCR = 0; // 21.6.3 Count Control Register - Timer mode
+ LPC_TIM1->PR = 0; // 21.6.5 Prescale register - Don't prescale 96MHz clock (divide by PR+1).
+ LPC_TIM1->MR0 = TICK_COUNT_PER_SECOND; // 21.6.7 Match Register 0 - Match count
+ LPC_TIM1->MCR = 1; // 21.6.8 Match Control Register - interrupt on match
+ LPC_TIM1->TCR = 1; // 21.6.2 Timer Control Register - Enable TC and PC
+
+ NVIC->ISER[0] |= 0x04; // 6.5.1 bit2 == Interrupt set enable for timer 1.
+}
+int32_t TickElapsed(int32_t* pLastTime)
+{
+ int32_t thisTime = LPC_TIM1->TC;
+
+ if (thisTime < *pLastTime) *pLastTime -= TICK_COUNT_PER_SECOND; //lastCount could be 96 000 002 and thisTime could be 00 000 100 which should give 98
+ int32_t elapsed = thisTime - *pLastTime;
+
+ *pLastTime = thisTime;
+ return elapsed;
+}
+int Ticked(int32_t* pLastTime)
+{
+ int thisTime = LPC_TIM1->TC;
+
+ int ticked = thisTime < *pLastTime;
+
+ *pLastTime = thisTime;
+ return ticked;
+}