Mbed Clock application using an NTP connection to get internet time and a terminal interface to send commands

Dependencies:   4DGL-uLCD-SE EthernetInterface NTPClient mbed-rtos mbed SDFileSystem wavfile

Revision:
0:4e6ae21cbd31
Child:
1:c47a2f0816bb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Dec 02 17:22:43 2014 +0000
@@ -0,0 +1,176 @@
+#include "mbed.h"
+#include "rtos.h"
+#include "EthernetInterface.h"
+#include "uLCD_4DGL.h"
+#include "Clock.h"
+#include <string>
+#include <sstream>
+#include <vector>
+
+uLCD_4DGL uLCD(p28,p27,p30);
+Serial pc(USBTX, USBRX);
+Mutex cMutex;
+Mutex sMutex;
+Clock clk;
+EthernetInterface eth;
+
+/**
+ * Function to get a command from the virtual serial connection.
+ * Will prompt the serial port for a command and read a command
+ * into a buffer and convert that buffer to a string object. This
+ * function should only be used while testing without a connection.
+ */
+string getCommand() {
+    char buffer[100];
+    char next = 0;
+    int i = 0;
+    sMutex.lock();
+    pc.printf("Enter a command: \n\r");
+    sMutex.unlock();
+    do {
+        sMutex.lock();
+        if (pc.readable()) {
+            next = pc.getc();
+            buffer[i++] = next;
+        }
+        sMutex.unlock();
+        Thread::wait(0.1);
+    } while (next != '\r');
+    
+    buffer[i] = '\0';
+    sMutex.lock();
+    pc.printf("Command entered: %s\n\r", buffer);
+    sMutex.unlock();
+    return string(buffer);
+}
+
+/**
+ * Function to take a string command and break it into tokens of words/numbers.
+ * These tokens will be added to the vector given as an argument and can then be 
+ * parsed to execute a command.
+ */
+vector<string>& splitCommand(const string &command, vector<string> &tokens) {
+    string buf;
+    stringstream ss(command);
+
+    while (ss >> buf)
+        tokens.push_back(buf);
+
+    return tokens;
+}
+
+/**
+ * Function to actually parse and execute a given command. If the command is not
+ * supported, an error function will be called to give feedback.
+ */
+void parseCommand(const vector<string> &tokens) {
+    sMutex.lock();
+    pc.printf("number of tokens: %d\n\r", tokens.size());
+    sMutex.unlock();
+
+    if (tokens.size() < 2) {
+        // error message
+        return;
+    }
+    
+    string operation = tokens[0];
+    string destination = tokens[1];
+    
+    if (operation == "set") {
+        if (destination == "time") {
+            int hour = atoi(tokens[2].c_str());
+            int minute = atoi(tokens[3].c_str());
+            int period = tokens.at(4) == "am" ? AM : PM;
+            cMutex.lock();
+            clk.setTime(hour, minute, period);
+            cMutex.unlock();
+        } else if (destination == "alarm") {
+            int hours = atoi(tokens[2].c_str());
+            int minutes = atoi(tokens[3].c_str());
+        } else if (destination == "timezone") {
+            int timezone = atoi(tokens[2].c_str());
+            cMutex.lock();
+            clk.setTimezone(timezone);
+            cMutex.unlock();
+        } else {
+            //return error message
+        }
+    } else if (operation == "sync") {
+        if (destination == "time") {
+
+            cMutex.lock();            
+            if (clk.syncTime() == 0) {
+                sMutex.lock();
+                pc.printf("Set time successfully\r\n");
+            } else {
+                sMutex.lock();
+                pc.printf("Error\r\n");
+            }
+            sMutex.unlock();
+            cMutex.unlock();
+        }
+        // return error message
+    }
+}
+
+/**
+ * Thread which updates the clock on the lcd while the main thread is waiting for 
+ * or executing a command.
+ */
+void lcdUpdateThread(void const *args) {
+    time_t time;
+    struct tm *timeinfo;
+    char buffer[20];
+    
+    // set initial time
+    cMutex.lock();
+    clk.syncTime();
+    clk.setTimezone(-5);
+    cMutex.unlock();
+    
+    // set lcd format
+    sMutex.lock();
+    uLCD.text_width(2);
+    uLCD.text_height(2);
+    uLCD.color(BLUE);
+    sMutex.unlock();
+    
+    while (1) {
+        cMutex.lock();
+        time = clk.getTime();
+        cMutex.unlock();
+        
+        timeinfo = localtime(&time);
+        strftime(buffer, 20, "%I:%M:%S        %p", timeinfo);
+        
+        sMutex.lock();
+        uLCD.locate(0,3);
+        uLCD.printf("%s", buffer);
+        sMutex.unlock();
+        Thread::wait(0.25);
+    }
+}
+
+/**
+ * main function which loops getting a command, parsing that command, and executing
+ * that command. It also starts a thread which updates the clock separate from the
+ * command execution.
+ */
+int main() {
+    vector<string> tokens;
+
+    eth.init();
+    eth.connect();
+    wait(5); // I don't know why you have to wait...
+
+    pc.printf("%s\n\r", eth.getIPAddress());
+    
+    Thread updateThread(lcdUpdateThread);
+
+    while (1) {
+        tokens.clear();
+        string command = getCommand();
+        splitCommand(command, tokens);
+        parseCommand(tokens);
+    }
+}