Backing up an unused program in case of future need

Dependencies:   mbed

Committer:
andrewboyson
Date:
Thu Dec 06 11:40:19 2018 +0000
Revision:
8:45a0205a298f
Parent:
4:e076884ef8bd
Backing up

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 0:09f915e6f9f6 1 #include <mbed.h>
andrewboyson 0:09f915e6f9f6 2 #include "log.h"
andrewboyson 0:09f915e6f9f6 3 #include "esp.h"
andrewboyson 0:09f915e6f9f6 4 #include "wifi.h"
andrewboyson 0:09f915e6f9f6 5 #include "time.h"
andrewboyson 0:09f915e6f9f6 6 #include "io.h"
andrewboyson 0:09f915e6f9f6 7 #include "at.h"
andrewboyson 2:06fa34661f19 8 #include "cfg.h"
andrewboyson 0:09f915e6f9f6 9
andrewboyson 0:09f915e6f9f6 10 #define GET_TIME_INTERVAL 600
andrewboyson 0:09f915e6f9f6 11 #define RETRY_INTERVAL 60
andrewboyson 0:09f915e6f9f6 12
andrewboyson 0:09f915e6f9f6 13 #define ID 0
andrewboyson 0:09f915e6f9f6 14
andrewboyson 0:09f915e6f9f6 15 #define SIXTEENTHS_TO_ADD 1
andrewboyson 0:09f915e6f9f6 16
andrewboyson 4:e076884ef8bd 17 static Timer timer;
andrewboyson 0:09f915e6f9f6 18
andrewboyson 0:09f915e6f9f6 19 struct Packet {
andrewboyson 0:09f915e6f9f6 20 /*
andrewboyson 0:09f915e6f9f6 21 LI: 00 no warning; 01 last minute has 61 seconds; 10 last minute has 59 seconds; 11 alarm condition (clock not synchronized)
andrewboyson 0:09f915e6f9f6 22 VN: 3 = 011
andrewboyson 0:09f915e6f9f6 23 Mode: 3 = 011 for client request; 4 = 100 for server reply
andrewboyson 0:09f915e6f9f6 24 0 1 2 3
andrewboyson 0:09f915e6f9f6 25 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
andrewboyson 0:09f915e6f9f6 26 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
andrewboyson 0:09f915e6f9f6 27 |LI | VN |Mode | Stratum | Poll | Precision |
andrewboyson 0:09f915e6f9f6 28 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
andrewboyson 0:09f915e6f9f6 29 |0 0 0 1|1 0 1 1|
andrewboyson 0:09f915e6f9f6 30
andrewboyson 0:09f915e6f9f6 31 Mode: If the Mode field of the request is 3 (client), the reply is set to 4 (server).
andrewboyson 0:09f915e6f9f6 32 If this field is set to 1 (symmetric active), the reply is set to 2 (symmetric passive).
andrewboyson 0:09f915e6f9f6 33 This allows clients configured in either client (NTP mode 3) or symmetric active (NTP mode 1) to
andrewboyson 0:09f915e6f9f6 34 interoperate successfully, even if configured in possibly suboptimal ways.
andrewboyson 0:09f915e6f9f6 35
andrewboyson 0:09f915e6f9f6 36 Poll: signed integer indicating the minimum interval between transmitted messages, in seconds as a power of two.
andrewboyson 0:09f915e6f9f6 37 For instance, a value of six indicates a minimum interval of 64 seconds.
andrewboyson 0:09f915e6f9f6 38
andrewboyson 0:09f915e6f9f6 39 Precision: signed integer indicating the precision of the various clocks, in seconds to the nearest power of two.
andrewboyson 0:09f915e6f9f6 40 The value must be rounded to the next larger power of two;
andrewboyson 0:09f915e6f9f6 41 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),
andrewboyson 0:09f915e6f9f6 42 while a 1000-Hz (1 ms) crystal-controlled clock would be assigned the value -9 (1.95 ms).
andrewboyson 0:09f915e6f9f6 43
andrewboyson 0:09f915e6f9f6 44 Root Delay (rootdelay): Total round-trip delay to the reference clock, in NTP short format (16bitseconds; 16bit fraction).
andrewboyson 0:09f915e6f9f6 45
andrewboyson 0:09f915e6f9f6 46 Root Dispersion (rootdisp): Total dispersion to the reference clock, in NTP short format (16bitseconds; 16bit fraction)..
andrewboyson 0:09f915e6f9f6 47 */
andrewboyson 0:09f915e6f9f6 48 union
andrewboyson 0:09f915e6f9f6 49 {
andrewboyson 0:09f915e6f9f6 50 uint32_t FirstLine;
andrewboyson 0:09f915e6f9f6 51 struct
andrewboyson 0:09f915e6f9f6 52 {
andrewboyson 0:09f915e6f9f6 53 unsigned Mode : 3;
andrewboyson 0:09f915e6f9f6 54 unsigned VN : 3;
andrewboyson 0:09f915e6f9f6 55 unsigned LI : 2;
andrewboyson 0:09f915e6f9f6 56 uint8_t Stratum;
andrewboyson 0:09f915e6f9f6 57 int8_t Poll;
andrewboyson 0:09f915e6f9f6 58 int8_t Precision;
andrewboyson 0:09f915e6f9f6 59 };
andrewboyson 0:09f915e6f9f6 60 };
andrewboyson 0:09f915e6f9f6 61 uint32_t RootDelay;
andrewboyson 0:09f915e6f9f6 62 uint32_t Dispersion;
andrewboyson 0:09f915e6f9f6 63 uint32_t RefIdentifier;
andrewboyson 0:09f915e6f9f6 64
andrewboyson 0:09f915e6f9f6 65 uint64_t RefTimeStamp;
andrewboyson 0:09f915e6f9f6 66 uint64_t OriTimeStamp;
andrewboyson 0:09f915e6f9f6 67 uint64_t RecTimeStamp;
andrewboyson 0:09f915e6f9f6 68 uint64_t TraTimeStamp;
andrewboyson 0:09f915e6f9f6 69 };
andrewboyson 0:09f915e6f9f6 70 static struct Packet packet;
andrewboyson 0:09f915e6f9f6 71
andrewboyson 0:09f915e6f9f6 72 static uint64_t ntohll(uint64_t n) {
andrewboyson 0:09f915e6f9f6 73 int testInt = 0x0001; //Big end contains 0x00; little end contains 0x01
andrewboyson 0:09f915e6f9f6 74 int *pTestInt = &testInt;
andrewboyson 0:09f915e6f9f6 75 char *pTestByte = (char*)pTestInt;
andrewboyson 0:09f915e6f9f6 76 char testByte = *pTestByte; //fetch the first byte
andrewboyson 0:09f915e6f9f6 77 if (testByte == 0x00) return n; //If the first byte is the big end then host and network have same endianess
andrewboyson 0:09f915e6f9f6 78
andrewboyson 0:09f915e6f9f6 79 union ull
andrewboyson 0:09f915e6f9f6 80 {
andrewboyson 0:09f915e6f9f6 81 uint64_t Whole;
andrewboyson 0:09f915e6f9f6 82 char Bytes[8];
andrewboyson 0:09f915e6f9f6 83 };
andrewboyson 0:09f915e6f9f6 84 union ull h;
andrewboyson 0:09f915e6f9f6 85 h.Whole = n;
andrewboyson 0:09f915e6f9f6 86
andrewboyson 0:09f915e6f9f6 87 char t;
andrewboyson 0:09f915e6f9f6 88 t = h.Bytes[7]; h.Bytes[7] = h.Bytes[0]; h.Bytes[0] = t;
andrewboyson 0:09f915e6f9f6 89 t = h.Bytes[6]; h.Bytes[6] = h.Bytes[1]; h.Bytes[1] = t;
andrewboyson 0:09f915e6f9f6 90 t = h.Bytes[5]; h.Bytes[5] = h.Bytes[2]; h.Bytes[2] = t;
andrewboyson 0:09f915e6f9f6 91 t = h.Bytes[4]; h.Bytes[4] = h.Bytes[3]; h.Bytes[3] = t;
andrewboyson 0:09f915e6f9f6 92
andrewboyson 0:09f915e6f9f6 93 return h.Whole;
andrewboyson 0:09f915e6f9f6 94 }
andrewboyson 0:09f915e6f9f6 95 uint64_t getTimeAsNtp()
andrewboyson 0:09f915e6f9f6 96 {
andrewboyson 0:09f915e6f9f6 97 uint64_t ntpTime = 2208988800ULL << 32;
andrewboyson 0:09f915e6f9f6 98 ntpTime += TimeGet16ths() << 28;
andrewboyson 0:09f915e6f9f6 99 return ntpTime;
andrewboyson 0:09f915e6f9f6 100 }
andrewboyson 0:09f915e6f9f6 101 void setTimeAsNtp(uint64_t ntpTime)
andrewboyson 0:09f915e6f9f6 102 {
andrewboyson 0:09f915e6f9f6 103 ntpTime -= 2208988800ULL << 32;
andrewboyson 0:09f915e6f9f6 104 uint64_t time16ths = (ntpTime >> 28) + SIXTEENTHS_TO_ADD;
andrewboyson 0:09f915e6f9f6 105 TimeSet16ths(time16ths);
andrewboyson 0:09f915e6f9f6 106 }
andrewboyson 0:09f915e6f9f6 107 void NtpInit()
andrewboyson 0:09f915e6f9f6 108 {
andrewboyson 0:09f915e6f9f6 109 EspIpdReserved[ID] = true;
andrewboyson 0:09f915e6f9f6 110 }
andrewboyson 0:09f915e6f9f6 111 int preparePacket()
andrewboyson 0:09f915e6f9f6 112 {
andrewboyson 0:09f915e6f9f6 113 memset(&packet, 0, sizeof(packet));
andrewboyson 0:09f915e6f9f6 114 packet.LI = 0;
andrewboyson 0:09f915e6f9f6 115 packet.VN = 1;
andrewboyson 0:09f915e6f9f6 116 packet.Mode = 3; //Client
andrewboyson 0:09f915e6f9f6 117 packet.TraTimeStamp = ntohll(getTimeAsNtp());
andrewboyson 0:09f915e6f9f6 118 return 0;
andrewboyson 0:09f915e6f9f6 119 }
andrewboyson 0:09f915e6f9f6 120 int handlePacket()
andrewboyson 0:09f915e6f9f6 121 {
andrewboyson 0:09f915e6f9f6 122
andrewboyson 0:09f915e6f9f6 123 //Handle the reply
andrewboyson 0:09f915e6f9f6 124 char leap = packet.LI;
andrewboyson 0:09f915e6f9f6 125 char version = packet.VN;
andrewboyson 0:09f915e6f9f6 126 char mode = packet.Mode;
andrewboyson 0:09f915e6f9f6 127 char stratum = packet.Stratum;
andrewboyson 0:09f915e6f9f6 128 if (leap == 3) { LogF("Remote clock has a fault\r\n"); return -1; }
andrewboyson 0:09f915e6f9f6 129 if (version < 1) { LogF("Version is %d\r\n", version); return -1; }
andrewboyson 0:09f915e6f9f6 130 if (mode != 4) { LogF("Mode is %d\r\n", mode); return -1; }
andrewboyson 0:09f915e6f9f6 131 if (stratum == 0) { LogF("Received Kiss of Death packet (stratum is 0)\r\n"); return -1; }
andrewboyson 0:09f915e6f9f6 132
andrewboyson 0:09f915e6f9f6 133 /*
andrewboyson 0:09f915e6f9f6 134 See http://www.eecis.udel.edu/~mills/time.html for timestamp calculations
andrewboyson 0:09f915e6f9f6 135 Ori
andrewboyson 0:09f915e6f9f6 136 ----t1---------t4---- RTC
andrewboyson 0:09f915e6f9f6 137 \ /
andrewboyson 0:09f915e6f9f6 138 -------t2---t3------- NTP
andrewboyson 0:09f915e6f9f6 139 Rec Tra
andrewboyson 0:09f915e6f9f6 140 offset (RTC - NTP) = (t1 + t4)/2 - (t2 + t3)/2 ==> [(t1 - t2) + (t4 - t3)] / 2
andrewboyson 0:09f915e6f9f6 141 delay = (t4 - t1) - (t3 - t2)
andrewboyson 0:09f915e6f9f6 142 */
andrewboyson 0:09f915e6f9f6 143
andrewboyson 0:09f915e6f9f6 144 //Set the RTC
andrewboyson 0:09f915e6f9f6 145 setTimeAsNtp(ntohll(packet.RecTimeStamp));
andrewboyson 0:09f915e6f9f6 146
andrewboyson 0:09f915e6f9f6 147 return 0;
andrewboyson 0:09f915e6f9f6 148 }
andrewboyson 0:09f915e6f9f6 149 int NtpIdConnectStatus = AT_NONE;
andrewboyson 0:09f915e6f9f6 150 static void outgoingMain()
andrewboyson 0:09f915e6f9f6 151 {
andrewboyson 0:09f915e6f9f6 152 if (AtBusy()) return;
andrewboyson 0:09f915e6f9f6 153 if (!WifiStarted()) return;
andrewboyson 0:09f915e6f9f6 154
andrewboyson 0:09f915e6f9f6 155 static int firstAttempt = true;
andrewboyson 0:09f915e6f9f6 156 static int result = AT_NONE;
andrewboyson 0:09f915e6f9f6 157
andrewboyson 0:09f915e6f9f6 158 if (NtpIdConnectStatus == AT_SUCCESS)
andrewboyson 0:09f915e6f9f6 159 {
andrewboyson 0:09f915e6f9f6 160 int retryAfterFailure = timer.read() > RETRY_INTERVAL && result != AT_SUCCESS;
andrewboyson 0:09f915e6f9f6 161 int repeat = timer.read() > GET_TIME_INTERVAL;
andrewboyson 0:09f915e6f9f6 162
andrewboyson 0:09f915e6f9f6 163 if (firstAttempt || retryAfterFailure || repeat)
andrewboyson 0:09f915e6f9f6 164 {
andrewboyson 0:09f915e6f9f6 165 preparePacket();
andrewboyson 0:09f915e6f9f6 166 AtSendData(ID, sizeof(packet), &packet, &result);
andrewboyson 0:09f915e6f9f6 167 firstAttempt = false;
andrewboyson 0:09f915e6f9f6 168 timer.reset();
andrewboyson 0:09f915e6f9f6 169 timer.start();
andrewboyson 0:09f915e6f9f6 170 }
andrewboyson 0:09f915e6f9f6 171 }
andrewboyson 0:09f915e6f9f6 172 else
andrewboyson 0:09f915e6f9f6 173 {
andrewboyson 2:06fa34661f19 174 AtConnectId(ID, "UDP", CfgNtpIp, 123, &packet, sizeof(packet), &NtpIdConnectStatus);
andrewboyson 0:09f915e6f9f6 175 }
andrewboyson 0:09f915e6f9f6 176 }
andrewboyson 0:09f915e6f9f6 177 static void incomingMain()
andrewboyson 0:09f915e6f9f6 178 {
andrewboyson 0:09f915e6f9f6 179 if (EspDataAvailable == ESP_AVAILABLE && EspIpdId == ID)
andrewboyson 0:09f915e6f9f6 180 {
andrewboyson 0:09f915e6f9f6 181 if (EspIpdLength == sizeof(packet)) handlePacket();
andrewboyson 0:09f915e6f9f6 182 else LogF("Incorrect NTP packet length of %d bytes", EspIpdLength);
andrewboyson 0:09f915e6f9f6 183 }
andrewboyson 0:09f915e6f9f6 184 }
andrewboyson 0:09f915e6f9f6 185 int NtpMain()
andrewboyson 0:09f915e6f9f6 186 {
andrewboyson 0:09f915e6f9f6 187 outgoingMain();
andrewboyson 0:09f915e6f9f6 188 incomingMain();
andrewboyson 0:09f915e6f9f6 189 return 0;
andrewboyson 0:09f915e6f9f6 190 }