A GPS disciplined clock
Dependencies: net lpc1768 crypto clock web log
gps/pps.c@13:dc986dce561b, 2018-12-03 (annotated)
- 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?
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 | 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 | } |