A GPS disciplined clock

Dependencies:   net lpc1768 crypto clock web log

Committer:
andrewboyson
Date:
Tue Jan 08 21:07:03 2019 +0000
Revision:
24:6f3e53833e62
Parent:
17:1dcc58dac445
Child:
34:d9586fc921dc
Updated clock library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 4:108157115360 1 #include <stdbool.h>
andrewboyson 4:108157115360 2 #include <time.h>
andrewboyson 4:108157115360 3
andrewboyson 4:108157115360 4 #include "log.h"
andrewboyson 24:6f3e53833e62 5 #include "clkgov.h"
andrewboyson 14:1bce51823be0 6 #include "hrtimer.h"
andrewboyson 4:108157115360 7 #include "gpio.h"
andrewboyson 4:108157115360 8 #include "bitband.h"
andrewboyson 4:108157115360 9
andrewboyson 4:108157115360 10 #define CONFIDENCE_OK 60
andrewboyson 4:108157115360 11
andrewboyson 4:108157115360 12 #define IO0INTENR_ADDR 0x40028090
andrewboyson 4:108157115360 13 #define IO0INTCLR_ADDR 0x4002808C
andrewboyson 4:108157115360 14 #define ISER0_ADDR 0xE000E100
andrewboyson 4:108157115360 15
andrewboyson 4:108157115360 16 #define FIX_PIN FIO0PIN(23)
andrewboyson 4:108157115360 17 #define ENABLE_DIR FIO0DIR(24)
andrewboyson 4:108157115360 18 #define ENABLE_SET FIO0SET(24)
andrewboyson 4:108157115360 19 #define ENABLE_CLR FIO0CLR(24)
andrewboyson 4:108157115360 20 #define PPS_PIN FIO0PIN(17)
andrewboyson 4:108157115360 21 #define PPS_INT_ENR BIT_BAND4(IO0INTENR_ADDR, 17) = 1
andrewboyson 4:108157115360 22 #define PPS_INT_CLR BIT_BAND4(IO0INTCLR_ADDR, 17) = 1
andrewboyson 4:108157115360 23 #define ISER0 *((volatile unsigned *) ISER0_ADDR)
andrewboyson 4:108157115360 24
andrewboyson 4:108157115360 25 static uint32_t msTimer;
andrewboyson 4:108157115360 26 static volatile bool hadPulse;
andrewboyson 4:108157115360 27
andrewboyson 4:108157115360 28 time_t PpsTime = 0;
andrewboyson 4:108157115360 29
andrewboyson 4:108157115360 30 int PpsMsSinceLastPulse = 0;
andrewboyson 4:108157115360 31
andrewboyson 4:108157115360 32 static int confidence = 0;
andrewboyson 15:e5bfa0cd1ff8 33 void PpsStabilityConfidenceReset()
andrewboyson 4:108157115360 34 {
andrewboyson 4:108157115360 35 confidence = 0;
andrewboyson 4:108157115360 36 }
andrewboyson 15:e5bfa0cd1ff8 37 void PpsStabilityConfidenceIncrease()
andrewboyson 4:108157115360 38 {
andrewboyson 4:108157115360 39 confidence++;
andrewboyson 4:108157115360 40 if (confidence > CONFIDENCE_OK) confidence = CONFIDENCE_OK;
andrewboyson 4:108157115360 41 }
andrewboyson 15:e5bfa0cd1ff8 42 bool PpsIsStable()
andrewboyson 15:e5bfa0cd1ff8 43 {
andrewboyson 15:e5bfa0cd1ff8 44 return confidence == CONFIDENCE_OK;
andrewboyson 15:e5bfa0cd1ff8 45 }
andrewboyson 4:108157115360 46 __irq void PpsHandler()
andrewboyson 4:108157115360 47 {
andrewboyson 4:108157115360 48 PPS_INT_CLR;
andrewboyson 24:6f3e53833e62 49 ClkGovSyncPpsI();
andrewboyson 4:108157115360 50 hadPulse = true;
andrewboyson 4:108157115360 51 }
andrewboyson 4:108157115360 52
andrewboyson 4:108157115360 53 static void pulseN()
andrewboyson 4:108157115360 54 {
andrewboyson 4:108157115360 55 PpsTime += (PpsMsSinceLastPulse + 500) / 1000;
andrewboyson 4:108157115360 56
andrewboyson 4:108157115360 57 int ppsOffset = PpsMsSinceLastPulse % 1000;
andrewboyson 4:108157115360 58
andrewboyson 4:108157115360 59 if (ppsOffset != 999 && ppsOffset != 0)
andrewboyson 4:108157115360 60 {
andrewboyson 4:108157115360 61 LogTimeF("GPS %4d ms PPS interval is not 999 or 000 ms - sync disabled\r\n", PpsMsSinceLastPulse);
andrewboyson 4:108157115360 62 confidence = 0;
andrewboyson 4:108157115360 63 }
andrewboyson 4:108157115360 64
andrewboyson 24:6f3e53833e62 65 if (confidence == CONFIDENCE_OK) ClkGovSyncPpsN(PpsTime);
andrewboyson 4:108157115360 66
andrewboyson 4:108157115360 67 }
andrewboyson 4:108157115360 68 void PpsMain()
andrewboyson 4:108157115360 69 {
andrewboyson 4:108157115360 70 //Handle time since last pulse
andrewboyson 14:1bce51823be0 71 PpsMsSinceLastPulse = HrTimerSinceMs(msTimer);
andrewboyson 4:108157115360 72 bool pulseHasStopped = PpsMsSinceLastPulse > 1000;
andrewboyson 4:108157115360 73 static bool pulseWasStopped = false;
andrewboyson 15:e5bfa0cd1ff8 74 if ( pulseHasStopped) PpsStabilityConfidenceReset();
andrewboyson 4:108157115360 75 if ( pulseHasStopped && !pulseWasStopped) LogTimeF("GPS %4d ms PPS pulses have stopped - sync disabled\r\n", PpsMsSinceLastPulse);
andrewboyson 4:108157115360 76 if (!pulseHasStopped && pulseWasStopped) LogTimeF("GPS %4d ms PPS pulses have started\r\n", PpsMsSinceLastPulse);
andrewboyson 4:108157115360 77 pulseWasStopped = pulseHasStopped;
andrewboyson 4:108157115360 78
andrewboyson 4:108157115360 79 //Handle the arrival of a pulse
andrewboyson 4:108157115360 80 if (hadPulse)
andrewboyson 4:108157115360 81 {
andrewboyson 14:1bce51823be0 82 msTimer = HrTimerCount();
andrewboyson 4:108157115360 83 pulseN();
andrewboyson 4:108157115360 84 hadPulse = false;
andrewboyson 4:108157115360 85 pulseHasStopped = false; //This gets the signal 1 scan before the ms is reset
andrewboyson 4:108157115360 86 }
andrewboyson 4:108157115360 87
andrewboyson 4:108157115360 88 //Settle time after disruption
andrewboyson 24:6f3e53833e62 89 ClkGovIsReceivingTime = confidence == CONFIDENCE_OK;
andrewboyson 4:108157115360 90 static bool lastStable = false;
andrewboyson 24:6f3e53833e62 91 if (ClkGovIsReceivingTime && !lastStable) LogTimeF("GPS %4d ms stable - sync enabled\r\n", PpsMsSinceLastPulse);
andrewboyson 24:6f3e53833e62 92 lastStable = ClkGovIsReceivingTime;
andrewboyson 4:108157115360 93 }
andrewboyson 4:108157115360 94
andrewboyson 4:108157115360 95 void PpsInit()
andrewboyson 4:108157115360 96 {
andrewboyson 14:1bce51823be0 97 msTimer = HrTimerCount();
andrewboyson 4:108157115360 98
andrewboyson 4:108157115360 99 ENABLE_CLR; //Set the enable to low to reset the GPS
andrewboyson 4:108157115360 100 ENABLE_DIR = 1; //Set the enable pin direction to 1 == output
andrewboyson 14:1bce51823be0 101 while (HrTimerSinceMs(msTimer) < 10) __nop();
andrewboyson 4:108157115360 102 ENABLE_SET; //Set the enable to high
andrewboyson 4:108157115360 103 PPS_INT_ENR; //Set the PPS pin to be interrupt on rise
andrewboyson 4:108157115360 104 ISER0 |= 1 << 21; //6.5.1 bit1 == Interrupt set enable for EINT3. It MUST be enabled even for GPIO interrupts - I checked.
andrewboyson 4:108157115360 105 }