Backing up an unused program in case of future need

Dependencies:   mbed

Revision:
0:09f915e6f9f6
Child:
2:06fa34661f19
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ntp.cpp	Wed Apr 13 09:21:02 2016 +0000
@@ -0,0 +1,189 @@
+#include <mbed.h>
+#include  "log.h"
+#include  "esp.h"
+#include "wifi.h"
+#include "time.h"
+#include   "io.h"
+#include   "at.h"
+
+#define GET_TIME_INTERVAL  600
+#define    RETRY_INTERVAL   60
+
+#define ID 0
+
+#define SIXTEENTHS_TO_ADD 1
+
+Timer timer;
+
+struct Packet {
+/*
+    LI:  00 no warning; 01 last minute has 61 seconds; 10 last minute has 59 seconds; 11 alarm condition (clock not synchronized)
+    VN:   3 = 011
+    Mode: 3 = 011 for client request; 4 = 100 for server reply
+       0                   1                   2                   3
+       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |LI | VN  |Mode |    Stratum    |     Poll      |   Precision   |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |0 0 0 1|1 0 1 1|
+    
+    Mode: If the Mode field of the request is 3 (client), the reply is set to 4 (server).
+          If this field is set to 1 (symmetric active), the reply is   set to 2 (symmetric passive).
+          This allows clients configured in either client (NTP mode 3) or symmetric active (NTP mode 1) to
+          interoperate successfully, even if configured in possibly suboptimal ways.
+          
+    Poll: signed integer indicating the minimum interval between transmitted messages, in seconds as a power of two.
+    For instance, a value of six indicates a minimum interval of 64 seconds.
+    
+    Precision: signed integer indicating the precision of the various clocks, in seconds to the nearest power of two.
+    The value must be rounded to the next larger power of two;
+    for instance, a 50-Hz (20 ms) or 60-Hz (16.67 ms) power-frequency clock would be assigned the value -5 (31.25 ms),
+    while a 1000-Hz (1 ms) crystal-controlled clock would be assigned the value -9 (1.95 ms).
+    
+    Root Delay (rootdelay): Total round-trip delay to the reference clock, in NTP short format (16bitseconds; 16bit fraction).
+
+    Root Dispersion (rootdisp): Total dispersion to the reference clock, in NTP short format (16bitseconds; 16bit fraction)..
+*/
+    union
+    {
+        uint32_t FirstLine;
+        struct
+        {
+            unsigned Mode : 3;
+            unsigned VN   : 3;
+            unsigned LI   : 2;
+            uint8_t  Stratum; 
+             int8_t  Poll;
+             int8_t  Precision;
+        };
+    };
+    uint32_t RootDelay;
+    uint32_t Dispersion;
+    uint32_t RefIdentifier;
+    
+    uint64_t RefTimeStamp;
+    uint64_t OriTimeStamp;
+    uint64_t RecTimeStamp;
+    uint64_t TraTimeStamp;
+};
+static struct Packet packet;
+
+static uint64_t ntohll(uint64_t n) {
+    int testInt = 0x0001; //Big end contains 0x00; little end contains 0x01
+    int *pTestInt = &testInt;
+    char *pTestByte = (char*)pTestInt;
+    char testByte = *pTestByte; //fetch the first byte
+    if (testByte == 0x00) return n; //If the first byte is the big end then host and network have same endianess
+    
+    union ull
+    {
+        uint64_t Whole;
+        char Bytes[8];
+    };
+    union ull h;
+    h.Whole = n;
+    
+    char t;
+    t = h.Bytes[7]; h.Bytes[7] = h.Bytes[0]; h.Bytes[0] = t;
+    t = h.Bytes[6]; h.Bytes[6] = h.Bytes[1]; h.Bytes[1] = t;
+    t = h.Bytes[5]; h.Bytes[5] = h.Bytes[2]; h.Bytes[2] = t;
+    t = h.Bytes[4]; h.Bytes[4] = h.Bytes[3]; h.Bytes[3] = t;
+    
+    return h.Whole;
+}
+uint64_t getTimeAsNtp()
+{
+    uint64_t ntpTime = 2208988800ULL << 32;
+    ntpTime += TimeGet16ths() << 28;
+    return ntpTime;
+}
+void setTimeAsNtp(uint64_t ntpTime)
+{
+    ntpTime -= 2208988800ULL << 32;
+    uint64_t time16ths = (ntpTime >> 28) + SIXTEENTHS_TO_ADD;
+    TimeSet16ths(time16ths);
+}
+void NtpInit()
+{
+    EspIpdReserved[ID] = true;
+}
+int preparePacket()
+{        
+    memset(&packet, 0, sizeof(packet));
+    packet.LI   = 0;
+    packet.VN   = 1;
+    packet.Mode = 3; //Client
+    packet.TraTimeStamp = ntohll(getTimeAsNtp());    
+    return 0;
+}
+int handlePacket()
+{        
+    
+    //Handle the reply  
+    char leap    = packet.LI;
+    char version = packet.VN;
+    char mode    = packet.Mode;
+    char stratum = packet.Stratum;
+    if (leap    == 3) { LogF("Remote clock has a fault\r\n");                     return -1; }
+    if (version  < 1) { LogF("Version is %d\r\n", version);                       return -1; }
+    if (mode    != 4) { LogF("Mode is %d\r\n", mode);                             return -1; }
+    if (stratum == 0) { LogF("Received Kiss of Death packet (stratum is 0)\r\n"); return -1; }
+    
+/*
+    See http://www.eecis.udel.edu/~mills/time.html for timestamp calculations
+        Ori
+    ----t1---------t4---- RTC
+          \       /
+    -------t2---t3------- NTP
+           Rec  Tra
+    offset (RTC - NTP) = (t1 + t4)/2 - (t2 + t3)/2 ==> [(t1 - t2) + (t4 - t3)] / 2
+    delay              = (t4 - t1)   - (t3 - t2)
+*/
+
+    //Set the RTC
+    setTimeAsNtp(ntohll(packet.RecTimeStamp));
+    
+    return 0;
+}
+int NtpIdConnectStatus = AT_NONE;
+static void outgoingMain()
+{
+    if (AtBusy()) return;
+    if (!WifiStarted()) return;
+    
+    static int firstAttempt = true;
+    static int result = AT_NONE;
+         
+    if (NtpIdConnectStatus == AT_SUCCESS)
+    {
+        int retryAfterFailure =  timer.read() > RETRY_INTERVAL && result != AT_SUCCESS;
+        int repeat            =  timer.read() > GET_TIME_INTERVAL;
+        
+        if (firstAttempt || retryAfterFailure || repeat)
+        {
+            preparePacket();
+            AtSendData(ID, sizeof(packet), &packet, &result);
+            firstAttempt = false;
+            timer.reset();
+            timer.start();
+        }
+    }
+    else
+    {
+        AtConnectId(ID, "UDP", "192.168.1.3", 123, &packet, sizeof(packet), &NtpIdConnectStatus);
+    }
+}
+static void incomingMain()
+{
+    if (EspDataAvailable == ESP_AVAILABLE && EspIpdId == ID)
+    {
+        if (EspIpdLength == sizeof(packet)) handlePacket();
+        else LogF("Incorrect NTP packet length of %d bytes", EspIpdLength);
+    }
+}
+int NtpMain()
+{
+    outgoingMain();
+    incomingMain();
+    return 0;
+}
\ No newline at end of file