MBED clock sync using NTP Server from from internet
Dependencies: EthernetInterface NTPClient mbed-rtos mbed
Fork of MbedClock by
main.cpp@0:4e6ae21cbd31, 2014-12-02 (annotated)
- Committer:
- dudanian
- Date:
- Tue Dec 02 17:22:43 2014 +0000
- Revision:
- 0:4e6ae21cbd31
- Child:
- 1:c47a2f0816bb
initial draft
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dudanian | 0:4e6ae21cbd31 | 1 | #include "mbed.h" |
dudanian | 0:4e6ae21cbd31 | 2 | #include "rtos.h" |
dudanian | 0:4e6ae21cbd31 | 3 | #include "EthernetInterface.h" |
dudanian | 0:4e6ae21cbd31 | 4 | #include "uLCD_4DGL.h" |
dudanian | 0:4e6ae21cbd31 | 5 | #include "Clock.h" |
dudanian | 0:4e6ae21cbd31 | 6 | #include <string> |
dudanian | 0:4e6ae21cbd31 | 7 | #include <sstream> |
dudanian | 0:4e6ae21cbd31 | 8 | #include <vector> |
dudanian | 0:4e6ae21cbd31 | 9 | |
dudanian | 0:4e6ae21cbd31 | 10 | uLCD_4DGL uLCD(p28,p27,p30); |
dudanian | 0:4e6ae21cbd31 | 11 | Serial pc(USBTX, USBRX); |
dudanian | 0:4e6ae21cbd31 | 12 | Mutex cMutex; |
dudanian | 0:4e6ae21cbd31 | 13 | Mutex sMutex; |
dudanian | 0:4e6ae21cbd31 | 14 | Clock clk; |
dudanian | 0:4e6ae21cbd31 | 15 | EthernetInterface eth; |
dudanian | 0:4e6ae21cbd31 | 16 | |
dudanian | 0:4e6ae21cbd31 | 17 | /** |
dudanian | 0:4e6ae21cbd31 | 18 | * Function to get a command from the virtual serial connection. |
dudanian | 0:4e6ae21cbd31 | 19 | * Will prompt the serial port for a command and read a command |
dudanian | 0:4e6ae21cbd31 | 20 | * into a buffer and convert that buffer to a string object. This |
dudanian | 0:4e6ae21cbd31 | 21 | * function should only be used while testing without a connection. |
dudanian | 0:4e6ae21cbd31 | 22 | */ |
dudanian | 0:4e6ae21cbd31 | 23 | string getCommand() { |
dudanian | 0:4e6ae21cbd31 | 24 | char buffer[100]; |
dudanian | 0:4e6ae21cbd31 | 25 | char next = 0; |
dudanian | 0:4e6ae21cbd31 | 26 | int i = 0; |
dudanian | 0:4e6ae21cbd31 | 27 | sMutex.lock(); |
dudanian | 0:4e6ae21cbd31 | 28 | pc.printf("Enter a command: \n\r"); |
dudanian | 0:4e6ae21cbd31 | 29 | sMutex.unlock(); |
dudanian | 0:4e6ae21cbd31 | 30 | do { |
dudanian | 0:4e6ae21cbd31 | 31 | sMutex.lock(); |
dudanian | 0:4e6ae21cbd31 | 32 | if (pc.readable()) { |
dudanian | 0:4e6ae21cbd31 | 33 | next = pc.getc(); |
dudanian | 0:4e6ae21cbd31 | 34 | buffer[i++] = next; |
dudanian | 0:4e6ae21cbd31 | 35 | } |
dudanian | 0:4e6ae21cbd31 | 36 | sMutex.unlock(); |
dudanian | 0:4e6ae21cbd31 | 37 | Thread::wait(0.1); |
dudanian | 0:4e6ae21cbd31 | 38 | } while (next != '\r'); |
dudanian | 0:4e6ae21cbd31 | 39 | |
dudanian | 0:4e6ae21cbd31 | 40 | buffer[i] = '\0'; |
dudanian | 0:4e6ae21cbd31 | 41 | sMutex.lock(); |
dudanian | 0:4e6ae21cbd31 | 42 | pc.printf("Command entered: %s\n\r", buffer); |
dudanian | 0:4e6ae21cbd31 | 43 | sMutex.unlock(); |
dudanian | 0:4e6ae21cbd31 | 44 | return string(buffer); |
dudanian | 0:4e6ae21cbd31 | 45 | } |
dudanian | 0:4e6ae21cbd31 | 46 | |
dudanian | 0:4e6ae21cbd31 | 47 | /** |
dudanian | 0:4e6ae21cbd31 | 48 | * Function to take a string command and break it into tokens of words/numbers. |
dudanian | 0:4e6ae21cbd31 | 49 | * These tokens will be added to the vector given as an argument and can then be |
dudanian | 0:4e6ae21cbd31 | 50 | * parsed to execute a command. |
dudanian | 0:4e6ae21cbd31 | 51 | */ |
dudanian | 0:4e6ae21cbd31 | 52 | vector<string>& splitCommand(const string &command, vector<string> &tokens) { |
dudanian | 0:4e6ae21cbd31 | 53 | string buf; |
dudanian | 0:4e6ae21cbd31 | 54 | stringstream ss(command); |
dudanian | 0:4e6ae21cbd31 | 55 | |
dudanian | 0:4e6ae21cbd31 | 56 | while (ss >> buf) |
dudanian | 0:4e6ae21cbd31 | 57 | tokens.push_back(buf); |
dudanian | 0:4e6ae21cbd31 | 58 | |
dudanian | 0:4e6ae21cbd31 | 59 | return tokens; |
dudanian | 0:4e6ae21cbd31 | 60 | } |
dudanian | 0:4e6ae21cbd31 | 61 | |
dudanian | 0:4e6ae21cbd31 | 62 | /** |
dudanian | 0:4e6ae21cbd31 | 63 | * Function to actually parse and execute a given command. If the command is not |
dudanian | 0:4e6ae21cbd31 | 64 | * supported, an error function will be called to give feedback. |
dudanian | 0:4e6ae21cbd31 | 65 | */ |
dudanian | 0:4e6ae21cbd31 | 66 | void parseCommand(const vector<string> &tokens) { |
dudanian | 0:4e6ae21cbd31 | 67 | sMutex.lock(); |
dudanian | 0:4e6ae21cbd31 | 68 | pc.printf("number of tokens: %d\n\r", tokens.size()); |
dudanian | 0:4e6ae21cbd31 | 69 | sMutex.unlock(); |
dudanian | 0:4e6ae21cbd31 | 70 | |
dudanian | 0:4e6ae21cbd31 | 71 | if (tokens.size() < 2) { |
dudanian | 0:4e6ae21cbd31 | 72 | // error message |
dudanian | 0:4e6ae21cbd31 | 73 | return; |
dudanian | 0:4e6ae21cbd31 | 74 | } |
dudanian | 0:4e6ae21cbd31 | 75 | |
dudanian | 0:4e6ae21cbd31 | 76 | string operation = tokens[0]; |
dudanian | 0:4e6ae21cbd31 | 77 | string destination = tokens[1]; |
dudanian | 0:4e6ae21cbd31 | 78 | |
dudanian | 0:4e6ae21cbd31 | 79 | if (operation == "set") { |
dudanian | 0:4e6ae21cbd31 | 80 | if (destination == "time") { |
dudanian | 0:4e6ae21cbd31 | 81 | int hour = atoi(tokens[2].c_str()); |
dudanian | 0:4e6ae21cbd31 | 82 | int minute = atoi(tokens[3].c_str()); |
dudanian | 0:4e6ae21cbd31 | 83 | int period = tokens.at(4) == "am" ? AM : PM; |
dudanian | 0:4e6ae21cbd31 | 84 | cMutex.lock(); |
dudanian | 0:4e6ae21cbd31 | 85 | clk.setTime(hour, minute, period); |
dudanian | 0:4e6ae21cbd31 | 86 | cMutex.unlock(); |
dudanian | 0:4e6ae21cbd31 | 87 | } else if (destination == "alarm") { |
dudanian | 0:4e6ae21cbd31 | 88 | int hours = atoi(tokens[2].c_str()); |
dudanian | 0:4e6ae21cbd31 | 89 | int minutes = atoi(tokens[3].c_str()); |
dudanian | 0:4e6ae21cbd31 | 90 | } else if (destination == "timezone") { |
dudanian | 0:4e6ae21cbd31 | 91 | int timezone = atoi(tokens[2].c_str()); |
dudanian | 0:4e6ae21cbd31 | 92 | cMutex.lock(); |
dudanian | 0:4e6ae21cbd31 | 93 | clk.setTimezone(timezone); |
dudanian | 0:4e6ae21cbd31 | 94 | cMutex.unlock(); |
dudanian | 0:4e6ae21cbd31 | 95 | } else { |
dudanian | 0:4e6ae21cbd31 | 96 | //return error message |
dudanian | 0:4e6ae21cbd31 | 97 | } |
dudanian | 0:4e6ae21cbd31 | 98 | } else if (operation == "sync") { |
dudanian | 0:4e6ae21cbd31 | 99 | if (destination == "time") { |
dudanian | 0:4e6ae21cbd31 | 100 | |
dudanian | 0:4e6ae21cbd31 | 101 | cMutex.lock(); |
dudanian | 0:4e6ae21cbd31 | 102 | if (clk.syncTime() == 0) { |
dudanian | 0:4e6ae21cbd31 | 103 | sMutex.lock(); |
dudanian | 0:4e6ae21cbd31 | 104 | pc.printf("Set time successfully\r\n"); |
dudanian | 0:4e6ae21cbd31 | 105 | } else { |
dudanian | 0:4e6ae21cbd31 | 106 | sMutex.lock(); |
dudanian | 0:4e6ae21cbd31 | 107 | pc.printf("Error\r\n"); |
dudanian | 0:4e6ae21cbd31 | 108 | } |
dudanian | 0:4e6ae21cbd31 | 109 | sMutex.unlock(); |
dudanian | 0:4e6ae21cbd31 | 110 | cMutex.unlock(); |
dudanian | 0:4e6ae21cbd31 | 111 | } |
dudanian | 0:4e6ae21cbd31 | 112 | // return error message |
dudanian | 0:4e6ae21cbd31 | 113 | } |
dudanian | 0:4e6ae21cbd31 | 114 | } |
dudanian | 0:4e6ae21cbd31 | 115 | |
dudanian | 0:4e6ae21cbd31 | 116 | /** |
dudanian | 0:4e6ae21cbd31 | 117 | * Thread which updates the clock on the lcd while the main thread is waiting for |
dudanian | 0:4e6ae21cbd31 | 118 | * or executing a command. |
dudanian | 0:4e6ae21cbd31 | 119 | */ |
dudanian | 0:4e6ae21cbd31 | 120 | void lcdUpdateThread(void const *args) { |
dudanian | 0:4e6ae21cbd31 | 121 | time_t time; |
dudanian | 0:4e6ae21cbd31 | 122 | struct tm *timeinfo; |
dudanian | 0:4e6ae21cbd31 | 123 | char buffer[20]; |
dudanian | 0:4e6ae21cbd31 | 124 | |
dudanian | 0:4e6ae21cbd31 | 125 | // set initial time |
dudanian | 0:4e6ae21cbd31 | 126 | cMutex.lock(); |
dudanian | 0:4e6ae21cbd31 | 127 | clk.syncTime(); |
dudanian | 0:4e6ae21cbd31 | 128 | clk.setTimezone(-5); |
dudanian | 0:4e6ae21cbd31 | 129 | cMutex.unlock(); |
dudanian | 0:4e6ae21cbd31 | 130 | |
dudanian | 0:4e6ae21cbd31 | 131 | // set lcd format |
dudanian | 0:4e6ae21cbd31 | 132 | sMutex.lock(); |
dudanian | 0:4e6ae21cbd31 | 133 | uLCD.text_width(2); |
dudanian | 0:4e6ae21cbd31 | 134 | uLCD.text_height(2); |
dudanian | 0:4e6ae21cbd31 | 135 | uLCD.color(BLUE); |
dudanian | 0:4e6ae21cbd31 | 136 | sMutex.unlock(); |
dudanian | 0:4e6ae21cbd31 | 137 | |
dudanian | 0:4e6ae21cbd31 | 138 | while (1) { |
dudanian | 0:4e6ae21cbd31 | 139 | cMutex.lock(); |
dudanian | 0:4e6ae21cbd31 | 140 | time = clk.getTime(); |
dudanian | 0:4e6ae21cbd31 | 141 | cMutex.unlock(); |
dudanian | 0:4e6ae21cbd31 | 142 | |
dudanian | 0:4e6ae21cbd31 | 143 | timeinfo = localtime(&time); |
dudanian | 0:4e6ae21cbd31 | 144 | strftime(buffer, 20, "%I:%M:%S %p", timeinfo); |
dudanian | 0:4e6ae21cbd31 | 145 | |
dudanian | 0:4e6ae21cbd31 | 146 | sMutex.lock(); |
dudanian | 0:4e6ae21cbd31 | 147 | uLCD.locate(0,3); |
dudanian | 0:4e6ae21cbd31 | 148 | uLCD.printf("%s", buffer); |
dudanian | 0:4e6ae21cbd31 | 149 | sMutex.unlock(); |
dudanian | 0:4e6ae21cbd31 | 150 | Thread::wait(0.25); |
dudanian | 0:4e6ae21cbd31 | 151 | } |
dudanian | 0:4e6ae21cbd31 | 152 | } |
dudanian | 0:4e6ae21cbd31 | 153 | |
dudanian | 0:4e6ae21cbd31 | 154 | /** |
dudanian | 0:4e6ae21cbd31 | 155 | * main function which loops getting a command, parsing that command, and executing |
dudanian | 0:4e6ae21cbd31 | 156 | * that command. It also starts a thread which updates the clock separate from the |
dudanian | 0:4e6ae21cbd31 | 157 | * command execution. |
dudanian | 0:4e6ae21cbd31 | 158 | */ |
dudanian | 0:4e6ae21cbd31 | 159 | int main() { |
dudanian | 0:4e6ae21cbd31 | 160 | vector<string> tokens; |
dudanian | 0:4e6ae21cbd31 | 161 | |
dudanian | 0:4e6ae21cbd31 | 162 | eth.init(); |
dudanian | 0:4e6ae21cbd31 | 163 | eth.connect(); |
dudanian | 0:4e6ae21cbd31 | 164 | wait(5); // I don't know why you have to wait... |
dudanian | 0:4e6ae21cbd31 | 165 | |
dudanian | 0:4e6ae21cbd31 | 166 | pc.printf("%s\n\r", eth.getIPAddress()); |
dudanian | 0:4e6ae21cbd31 | 167 | |
dudanian | 0:4e6ae21cbd31 | 168 | Thread updateThread(lcdUpdateThread); |
dudanian | 0:4e6ae21cbd31 | 169 | |
dudanian | 0:4e6ae21cbd31 | 170 | while (1) { |
dudanian | 0:4e6ae21cbd31 | 171 | tokens.clear(); |
dudanian | 0:4e6ae21cbd31 | 172 | string command = getCommand(); |
dudanian | 0:4e6ae21cbd31 | 173 | splitCommand(command, tokens); |
dudanian | 0:4e6ae21cbd31 | 174 | parseCommand(tokens); |
dudanian | 0:4e6ae21cbd31 | 175 | } |
dudanian | 0:4e6ae21cbd31 | 176 | } |