A GPS disciplined clock

Dependencies:   net lpc1768 crypto clock web log

Committer:
andrewboyson
Date:
Thu Oct 10 19:09:48 2019 +0000
Revision:
75:0ed9157d3bb3
Parent:
51:ae71fd4d03ca
Child:
77:4e3925cbb1d8
Updated libraries

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 34:d9586fc921dc 9 #include "gps.h"
andrewboyson 4:108157115360 10
andrewboyson 4:108157115360 11 #define IO0INTENR_ADDR 0x40028090
andrewboyson 4:108157115360 12 #define IO0INTCLR_ADDR 0x4002808C
andrewboyson 4:108157115360 13 #define ISER0_ADDR 0xE000E100
andrewboyson 4:108157115360 14
andrewboyson 4:108157115360 15 #define FIX_PIN FIO0PIN(23)
andrewboyson 4:108157115360 16 #define ENABLE_DIR FIO0DIR(24)
andrewboyson 4:108157115360 17 #define ENABLE_SET FIO0SET(24)
andrewboyson 4:108157115360 18 #define ENABLE_CLR FIO0CLR(24)
andrewboyson 4:108157115360 19 #define PPS_PIN FIO0PIN(17)
andrewboyson 4:108157115360 20 #define PPS_INT_ENR BIT_BAND4(IO0INTENR_ADDR, 17) = 1
andrewboyson 4:108157115360 21 #define PPS_INT_CLR BIT_BAND4(IO0INTCLR_ADDR, 17) = 1
andrewboyson 4:108157115360 22 #define ISER0 *((volatile unsigned *) ISER0_ADDR)
andrewboyson 4:108157115360 23
andrewboyson 35:a535b65203a9 24 static volatile uint32_t hrThisPulse = 0;
andrewboyson 35:a535b65203a9 25 static volatile int hadPulse = false;
andrewboyson 4:108157115360 26
andrewboyson 36:2983e45eeb49 27 #define CONFIDENCE_OK 10
andrewboyson 45:3b70941589af 28 #define TIMEOUT_MS 1000
andrewboyson 4:108157115360 29
andrewboyson 4:108157115360 30 static int confidence = 0;
andrewboyson 35:a535b65203a9 31 bool PpsIsStable() { return confidence == CONFIDENCE_OK; }
andrewboyson 34:d9586fc921dc 32
andrewboyson 34:d9586fc921dc 33 int PpsMsSinceLastPulse = 0;
andrewboyson 34:d9586fc921dc 34
andrewboyson 51:ae71fd4d03ca 35 void PpsHandler() //Called by an interrupt
andrewboyson 4:108157115360 36 {
andrewboyson 4:108157115360 37 PPS_INT_CLR;
andrewboyson 24:6f3e53833e62 38 ClkGovSyncPpsI();
andrewboyson 35:a535b65203a9 39 hrThisPulse = HrTimerCount();
andrewboyson 4:108157115360 40 hadPulse = true;
andrewboyson 4:108157115360 41 }
andrewboyson 36:2983e45eeb49 42 static bool pulseWasStopped = true;
andrewboyson 36:2983e45eeb49 43 static void checkForPulsesStoppingAndStarting()
andrewboyson 34:d9586fc921dc 44 {
andrewboyson 36:2983e45eeb49 45 if (PpsMsSinceLastPulse > TIMEOUT_MS)
andrewboyson 4:108157115360 46 {
andrewboyson 4:108157115360 47 confidence = 0;
andrewboyson 34:d9586fc921dc 48 if (!pulseWasStopped)
andrewboyson 34:d9586fc921dc 49 {
andrewboyson 35:a535b65203a9 50 GpsLog("PPS pulses have stopped - sync disabled\r\n");
andrewboyson 34:d9586fc921dc 51 pulseWasStopped = true;
andrewboyson 34:d9586fc921dc 52 }
andrewboyson 4:108157115360 53 }
andrewboyson 34:d9586fc921dc 54 if (hadPulse)
andrewboyson 34:d9586fc921dc 55 {
andrewboyson 34:d9586fc921dc 56 if (pulseWasStopped)
andrewboyson 34:d9586fc921dc 57 {
andrewboyson 35:a535b65203a9 58 GpsLog("PPS pulses have started\r\n");
andrewboyson 34:d9586fc921dc 59 pulseWasStopped = false;
andrewboyson 34:d9586fc921dc 60 }
andrewboyson 34:d9586fc921dc 61 }
andrewboyson 4:108157115360 62 }
andrewboyson 34:d9586fc921dc 63
andrewboyson 35:a535b65203a9 64 static void buildConfidence()
andrewboyson 34:d9586fc921dc 65 {
andrewboyson 35:a535b65203a9 66 static uint32_t hrPrevPulse = 0;
andrewboyson 35:a535b65203a9 67 if (hrPrevPulse)
andrewboyson 34:d9586fc921dc 68 {
andrewboyson 35:a535b65203a9 69 uint32_t hrSinceLastPulse = hrThisPulse - hrPrevPulse;
andrewboyson 35:a535b65203a9 70 uint32_t msSinceLastPulse = hrSinceLastPulse / (HR_TIMER_COUNT_PER_SECOND / 1000);
andrewboyson 35:a535b65203a9 71 uint32_t msSinceLastPulseMod1000 = msSinceLastPulse % 1000;
andrewboyson 35:a535b65203a9 72
andrewboyson 35:a535b65203a9 73 if (msSinceLastPulseMod1000 == 999 || msSinceLastPulseMod1000 == 000)
andrewboyson 34:d9586fc921dc 74 {
andrewboyson 34:d9586fc921dc 75 confidence++;
andrewboyson 34:d9586fc921dc 76 if (confidence > CONFIDENCE_OK) confidence = CONFIDENCE_OK;
andrewboyson 34:d9586fc921dc 77 }
andrewboyson 34:d9586fc921dc 78 else
andrewboyson 34:d9586fc921dc 79 {
andrewboyson 35:a535b65203a9 80 GpsLog("PPS interval %03d is not 999 or 1000 ms - sync disabled\r\n", msSinceLastPulse);
andrewboyson 34:d9586fc921dc 81 confidence = 0;
andrewboyson 34:d9586fc921dc 82 }
andrewboyson 35:a535b65203a9 83 }
andrewboyson 35:a535b65203a9 84 hrPrevPulse = hrThisPulse;
andrewboyson 36:2983e45eeb49 85 }
andrewboyson 36:2983e45eeb49 86 static void displayConfidence()
andrewboyson 36:2983e45eeb49 87 {
andrewboyson 35:a535b65203a9 88 static bool wasConfident = false;
andrewboyson 35:a535b65203a9 89 if (confidence == CONFIDENCE_OK)
andrewboyson 35:a535b65203a9 90 {
andrewboyson 35:a535b65203a9 91 if (!wasConfident) GpsLog("PPS is stable\r\n");
andrewboyson 35:a535b65203a9 92 wasConfident = true;
andrewboyson 35:a535b65203a9 93 }
andrewboyson 35:a535b65203a9 94 else
andrewboyson 35:a535b65203a9 95 {
andrewboyson 35:a535b65203a9 96 if (wasConfident) GpsLog("PPS is not stable\r\n");
andrewboyson 35:a535b65203a9 97 wasConfident = false;
andrewboyson 34:d9586fc921dc 98 }
andrewboyson 34:d9586fc921dc 99 }
andrewboyson 34:d9586fc921dc 100
andrewboyson 4:108157115360 101 void PpsMain()
andrewboyson 4:108157115360 102 {
andrewboyson 36:2983e45eeb49 103 //Wait for 100ms after the start up in order to ignore initial glitches on the PPS line
andrewboyson 36:2983e45eeb49 104 static bool afterStartup = false; //Need to store the timeout as hr timer rolls over every 44 seconds
andrewboyson 35:a535b65203a9 105 if (HrTimerCount() > HR_TIMER_COUNT_PER_SECOND / 10) afterStartup = true;
andrewboyson 36:2983e45eeb49 106 if (!afterStartup)
andrewboyson 35:a535b65203a9 107 {
andrewboyson 36:2983e45eeb49 108 hadPulse = false; //Cancel the pulse
andrewboyson 36:2983e45eeb49 109 return;
andrewboyson 35:a535b65203a9 110 }
andrewboyson 36:2983e45eeb49 111
andrewboyson 36:2983e45eeb49 112 checkForPulsesStoppingAndStarting(); //Do this before storing PPsMsSinceLastPulse to allow log to show when they started not zero
andrewboyson 36:2983e45eeb49 113
andrewboyson 36:2983e45eeb49 114 PpsMsSinceLastPulse = HrTimerSinceMs(hrThisPulse);
andrewboyson 36:2983e45eeb49 115
andrewboyson 36:2983e45eeb49 116 if (hadPulse)
andrewboyson 36:2983e45eeb49 117 {
andrewboyson 36:2983e45eeb49 118 buildConfidence();
andrewboyson 36:2983e45eeb49 119 GpsHadPps();
andrewboyson 36:2983e45eeb49 120 }
andrewboyson 36:2983e45eeb49 121 displayConfidence();
andrewboyson 36:2983e45eeb49 122
andrewboyson 35:a535b65203a9 123 hadPulse = false;
andrewboyson 4:108157115360 124 }
andrewboyson 4:108157115360 125
andrewboyson 4:108157115360 126 void PpsInit()
andrewboyson 4:108157115360 127 {
andrewboyson 36:2983e45eeb49 128 ENABLE_SET; //Set the enable to high
andrewboyson 4:108157115360 129 ENABLE_DIR = 1; //Set the enable pin direction to 1 == output
andrewboyson 4:108157115360 130 PPS_INT_ENR; //Set the PPS pin to be interrupt on rise
andrewboyson 4:108157115360 131 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 132 }