A GPS disciplined clock
Dependencies: net lpc1768 crypto clock web log
gps/pps.c@75:0ed9157d3bb3, 2019-10-10 (annotated)
- 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?
User | Revision | Line number | New 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 | } |