A GPS disciplined clock

Dependencies:   net lpc1768 crypto clock web log

gps/pps.c

Committer:
andrewboyson
Date:
2018-12-04
Revision:
14:1bce51823be0
Parent:
13:dc986dce561b
Child:
15:e5bfa0cd1ff8

File content as of revision 14:1bce51823be0:

#include <stdbool.h>
#include <time.h>

#include "log.h"
#include "clksync.h"
#include "hrtimer.h"
#include "gpio.h"
#include "bitband.h"

#define CONFIDENCE_OK  60

#define IO0INTENR_ADDR 0x40028090
#define IO0INTCLR_ADDR 0x4002808C
#define     ISER0_ADDR 0xE000E100

#define     FIX_PIN FIO0PIN(23)
#define  ENABLE_DIR FIO0DIR(24)
#define  ENABLE_SET FIO0SET(24)
#define  ENABLE_CLR FIO0CLR(24)
#define     PPS_PIN FIO0PIN(17)
#define PPS_INT_ENR BIT_BAND4(IO0INTENR_ADDR, 17) = 1
#define PPS_INT_CLR BIT_BAND4(IO0INTCLR_ADDR, 17) = 1
#define ISER0 *((volatile unsigned *) ISER0_ADDR)

static uint32_t msTimer;
static volatile bool hadPulse;

time_t PpsTime = 0;

int  PpsMsSinceLastPulse = 0;

bool PpsStable = false;
static int confidence = 0;
void PpsConfidenceNone()
{
    confidence = 0;
}
void PpsConfidenceIncrease()
{
    confidence++;
    if (confidence > CONFIDENCE_OK) confidence = CONFIDENCE_OK;
}

__irq void PpsHandler()
{
    PPS_INT_CLR;
    ClkSyncPpsI();
    hadPulse = true;
}

static void pulseN()
{    
    PpsTime += (PpsMsSinceLastPulse + 500) / 1000;

    int ppsOffset = PpsMsSinceLastPulse % 1000;
        
    if (ppsOffset != 999 && ppsOffset != 0)
    {
        LogTimeF("GPS %4d ms PPS interval is not 999 or 000 ms - sync disabled\r\n", PpsMsSinceLastPulse);
        confidence = 0;
    }
    
    if (confidence == CONFIDENCE_OK) ClkSyncPpsN(PpsTime);
    
}
void PpsMain()
{
    //Handle time since last pulse
    PpsMsSinceLastPulse = HrTimerSinceMs(msTimer);
    bool pulseHasStopped = PpsMsSinceLastPulse > 1000;
    static bool pulseWasStopped = false;
    if ( pulseHasStopped)  PpsConfidenceNone();
    if ( pulseHasStopped && !pulseWasStopped) LogTimeF("GPS %4d ms PPS pulses have stopped - sync disabled\r\n", PpsMsSinceLastPulse);
    if (!pulseHasStopped &&  pulseWasStopped) LogTimeF("GPS %4d ms PPS pulses have started\r\n", PpsMsSinceLastPulse);
    pulseWasStopped = pulseHasStopped;

    //Handle the arrival of a pulse
    if (hadPulse)
    {
        msTimer = HrTimerCount();
        pulseN();
        hadPulse = false;
        pulseHasStopped = false; //This gets the signal 1 scan before the ms is reset
    }
    
    //Settle time after disruption
    bool isStable = confidence == CONFIDENCE_OK;
    static bool lastStable = false;
    if (isStable && !lastStable) LogTimeF("GPS %4d ms stable - sync enabled\r\n", PpsMsSinceLastPulse);
    lastStable = isStable;
}

void PpsInit()
{
    msTimer = HrTimerCount();
    
    ENABLE_CLR;       //Set the enable to low to reset the GPS
    ENABLE_DIR = 1;   //Set the enable pin direction to 1 == output
    while (HrTimerSinceMs(msTimer) < 10) __nop();
    ENABLE_SET;       //Set the enable to high
    PPS_INT_ENR;      //Set the PPS pin to be interrupt on rise
    ISER0 |= 1 << 21; //6.5.1 bit1 == Interrupt set enable for EINT3. It MUST be enabled even for GPIO interrupts - I checked.
}