A GPS disciplined clock

Dependencies:   net lpc1768 crypto clock web log

Committer:
andrewboyson
Date:
Mon Dec 03 16:28:14 2018 +0000
Revision:
13:dc986dce561b
Parent:
12:9bd8f04df514
Child:
14:1bce51823be0
Changes to 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 12:9bd8f04df514 5 #include "clksync.h"
andrewboyson 4:108157115360 6 #include "timer.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 bool PpsStable = false;
andrewboyson 4:108157115360 33 static int confidence = 0;
andrewboyson 4:108157115360 34 void PpsConfidenceNone()
andrewboyson 4:108157115360 35 {
andrewboyson 4:108157115360 36 confidence = 0;
andrewboyson 4:108157115360 37 }
andrewboyson 4:108157115360 38 void PpsConfidenceIncrease()
andrewboyson 4:108157115360 39 {
andrewboyson 4:108157115360 40 confidence++;
andrewboyson 4:108157115360 41 if (confidence > CONFIDENCE_OK) confidence = CONFIDENCE_OK;
andrewboyson 4:108157115360 42 }
andrewboyson 4:108157115360 43
andrewboyson 4:108157115360 44 __irq void PpsHandler()
andrewboyson 4:108157115360 45 {
andrewboyson 4:108157115360 46 PPS_INT_CLR;
andrewboyson 4:108157115360 47 SyncPpsI();
andrewboyson 4:108157115360 48 hadPulse = true;
andrewboyson 4:108157115360 49 }
andrewboyson 4:108157115360 50
andrewboyson 4:108157115360 51 static void pulseN()
andrewboyson 4:108157115360 52 {
andrewboyson 4:108157115360 53 PpsTime += (PpsMsSinceLastPulse + 500) / 1000;
andrewboyson 4:108157115360 54
andrewboyson 4:108157115360 55 int ppsOffset = PpsMsSinceLastPulse % 1000;
andrewboyson 4:108157115360 56
andrewboyson 4:108157115360 57 if (ppsOffset != 999 && ppsOffset != 0)
andrewboyson 4:108157115360 58 {
andrewboyson 4:108157115360 59 LogTimeF("GPS %4d ms PPS interval is not 999 or 000 ms - sync disabled\r\n", PpsMsSinceLastPulse);
andrewboyson 4:108157115360 60 confidence = 0;
andrewboyson 4:108157115360 61 }
andrewboyson 4:108157115360 62
andrewboyson 4:108157115360 63 if (confidence == CONFIDENCE_OK) SyncPpsN(PpsTime);
andrewboyson 4:108157115360 64
andrewboyson 4:108157115360 65 }
andrewboyson 4:108157115360 66 void PpsMain()
andrewboyson 4:108157115360 67 {
andrewboyson 4:108157115360 68 //Handle time since last pulse
andrewboyson 4:108157115360 69 PpsMsSinceLastPulse = TimerSinceMs(msTimer);
andrewboyson 4:108157115360 70 bool pulseHasStopped = PpsMsSinceLastPulse > 1000;
andrewboyson 4:108157115360 71 static bool pulseWasStopped = false;
andrewboyson 4:108157115360 72 if ( pulseHasStopped) PpsConfidenceNone();
andrewboyson 4:108157115360 73 if ( pulseHasStopped && !pulseWasStopped) LogTimeF("GPS %4d ms PPS pulses have stopped - sync disabled\r\n", PpsMsSinceLastPulse);
andrewboyson 4:108157115360 74 if (!pulseHasStopped && pulseWasStopped) LogTimeF("GPS %4d ms PPS pulses have started\r\n", PpsMsSinceLastPulse);
andrewboyson 4:108157115360 75 pulseWasStopped = pulseHasStopped;
andrewboyson 4:108157115360 76
andrewboyson 4:108157115360 77 //Handle the arrival of a pulse
andrewboyson 4:108157115360 78 if (hadPulse)
andrewboyson 4:108157115360 79 {
andrewboyson 13:dc986dce561b 80 msTimer = TimerCount();
andrewboyson 4:108157115360 81 pulseN();
andrewboyson 4:108157115360 82 hadPulse = false;
andrewboyson 4:108157115360 83 pulseHasStopped = false; //This gets the signal 1 scan before the ms is reset
andrewboyson 4:108157115360 84 }
andrewboyson 4:108157115360 85
andrewboyson 4:108157115360 86 //Settle time after disruption
andrewboyson 4:108157115360 87 bool isStable = confidence == CONFIDENCE_OK;
andrewboyson 4:108157115360 88 static bool lastStable = false;
andrewboyson 4:108157115360 89 if (isStable && !lastStable) LogTimeF("GPS %4d ms stable - sync enabled\r\n", PpsMsSinceLastPulse);
andrewboyson 4:108157115360 90 lastStable = isStable;
andrewboyson 4:108157115360 91 }
andrewboyson 4:108157115360 92
andrewboyson 4:108157115360 93 void PpsInit()
andrewboyson 4:108157115360 94 {
andrewboyson 13:dc986dce561b 95 msTimer = TimerCount();
andrewboyson 4:108157115360 96
andrewboyson 4:108157115360 97 ENABLE_CLR; //Set the enable to low to reset the GPS
andrewboyson 4:108157115360 98 ENABLE_DIR = 1; //Set the enable pin direction to 1 == output
andrewboyson 4:108157115360 99 while (TimerSinceMs(msTimer) < 10) __nop();
andrewboyson 4:108157115360 100 ENABLE_SET; //Set the enable to high
andrewboyson 4:108157115360 101 PPS_INT_ENR; //Set the PPS pin to be interrupt on rise
andrewboyson 4:108157115360 102 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 103 }