Swimate V2 without RTOS code

Dependencies:   Adafruit_GFX_128x64 DS3231 PinDetect SDFileSystem USBDevice mbed RealtimeMath MODSERIAL

Files at this revision

API Documentation at this revision

Comitter:
ellingjp
Date:
Sat Jun 07 07:12:25 2014 +0000
Parent:
15:002bac432234
Child:
22:9350752f5414
Commit message:
Working sync

Changed in this revision

DS3231.lib Show annotated file Show diff for this revision Revisions of this file
MODSERIAL.lib Show annotated file Show diff for this revision Revisions of this file
RealtimeMath.lib Show annotated file Show diff for this revision Revisions of this file
comms.cpp Show annotated file Show diff for this revision Revisions of this file
comms.h Show annotated file Show diff for this revision Revisions of this file
debug.h Show annotated file Show diff for this revision Revisions of this file
log_data.cpp Show annotated file Show diff for this revision Revisions of this file
log_data.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
main.cpp.orig Show annotated file Show diff for this revision Revisions of this file
main.h Show annotated file Show diff for this revision Revisions of this file
process_data.cpp Show annotated file Show diff for this revision Revisions of this file
process_data.h Show annotated file Show diff for this revision Revisions of this file
receive_data.cpp Show annotated file Show diff for this revision Revisions of this file
sync.cpp Show annotated file Show diff for this revision Revisions of this file
sync.h Show annotated file Show diff for this revision Revisions of this file
--- a/DS3231.lib	Thu Jun 05 19:03:42 2014 +0000
+++ b/DS3231.lib	Sat Jun 07 07:12:25 2014 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/teams/CSE477/code/DS3231/#b5736355af3a
+http://mbed.org/teams/CSE477/code/DS3231/#71aad49938bc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MODSERIAL.lib	Sat Jun 07 07:12:25 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/AjK/code/MODSERIAL/#ae0408ebdd68
--- a/RealtimeMath.lib	Thu Jun 05 19:03:42 2014 +0000
+++ b/RealtimeMath.lib	Sat Jun 07 07:12:25 2014 +0000
@@ -1,1 +1,1 @@
-RealtimeMath#922b711e7a4b
+http://mbed.org/users/ellingjp/code/RealtimeMath/#e6c5780532d1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/comms.cpp	Sat Jun 07 07:12:25 2014 +0000
@@ -0,0 +1,142 @@
+#include "comms.h"
+#include "debug.h"
+
+const int Packet::HEADER_SIZE = 5;
+
+/*  If successful, loads p with a new packet.  User is responsible for deleting.
+ *  Returns > 0 on success
+              0 on timeout
+            < 0 on error
+ */
+int Comms::receivePacket(Packet **p, int timeout) {
+//    PC_PRINTLN("receivePacket: getting header");
+    uint8_t headerBuf[Packet::HEADER_SIZE];
+    if (!getBytes(headerBuf, Packet::HEADER_SIZE, timeout))
+        return 0;
+    
+    uint8_t cmd = headerBuf[0];
+    uint16_t packetNumber = headerBuf[1];
+    uint16_t dataLength = headerBuf[3];
+    
+    PC_PRINTLNF("receivePacket: cmd = %d", cmd);
+    PC_PRINTLNF("receivePacket: packetNumber = %d", packetNumber);
+    PC_PRINTLNF("receivePacket: dataLength = %d", dataLength);
+    
+    uint8_t data[dataLength];
+    if (!getBytes(data, dataLength, timeout))
+        return 0;
+    
+    PC_PRINTLN("receivePacket: getting checksum");
+    uint16_t checkSum;
+    if (!getBytes((uint8_t *) &checkSum, sizeof(checkSum), timeout))
+        return 0;
+    
+    PC_PRINTLN("receivePacket: verifying checksum");
+    *p = Packet::createAndVerify(cmd, packetNumber, dataLength, data, checkSum);
+    if (*p == NULL)
+        return -1;
+    
+    return 1;
+}
+
+/* Sends packet p, and deletes it */
+void Comms::sendPacket(Packet *p) {
+    sendBytes((uint8_t *)&p->cmd, sizeof(p->cmd));
+    sendBytes((uint8_t *)&p->packetNumber, sizeof(p->packetNumber));
+    sendBytes((uint8_t *)&p->dataLength, sizeof(p->dataLength));
+    sendBytes((uint8_t *) p->data, p->dataLength);
+    sendBytes((uint8_t *)&p->checkSum, sizeof(p->checkSum));
+}
+
+void Comms::sendBytes(uint8_t *bytes, int nElms) {
+    for (int i = 0; i < nElms; i++)
+        bt.putc(bytes[i]);   
+}
+
+void Comms::sendByte(uint8_t byte) {
+    bt.putc(byte);
+}
+
+/* Loads buf with a byte from the bluetooth stream.
+ * Returns true if successful, false on timeout. */
+bool Comms::getBytes(uint8_t *buf, int n, int timeout) {
+    for (int i = 0; i < n; i++) {
+//        PC_PRINTLNF("getBytes: waiting for byte %d", i);
+        if (!getByte(buf+i, timeout)) {
+//            PC_PRINTLN("getBytes: failed to get byte");
+            return false;
+        }
+//        PC_PRINTLNF("getBytes: got byte %d", *(buf+i));
+    }
+    
+//    PC_PRINTLN("getBytes: got bytes");
+    return true;
+}
+
+/* Loads c with a byte from the bluetooth stream.
+ * Returns true if successful, false on timeout. */
+bool Comms::getByte(uint8_t *byte, int timeout) {
+//    PC_PRINTLN("getByte: getting byte");
+    if (timeout != INT_MAX)
+        timer.start();
+        
+//    PC_PRINTLN("getByte: waiting for bt readable");
+    // Spin until byte available or timeout
+    while ( !bt.readable() )
+        if (timer.read_ms() > timeout)
+            return false;
+    
+//    PC_PRINTLN("getByte: byte available");
+    timer.stop();
+    timer.reset();
+    *byte = bt.getc();
+    
+//    PC_PRINTLNF("getByte: byte read = %d", *byte);
+    return true;
+}
+
+/* Returns a new packet.  Copies dataLength bytes from data, and verifies the checkSum.
+ * If the given checkSum is incorrect, returns NULL.
+ * User is responsible for deleting the returned packet. */
+Packet *Packet::createAndVerify(uint8_t cmd, uint16_t packetNumber, uint16_t dataLength, uint8_t *data, uint16_t checkSum) {
+    if (dataLength > 0 && data == NULL)
+        return NULL;
+    
+    Packet *p = new Packet(cmd, packetNumber, dataLength, data);
+    if (p->checkSum != checkSum)
+        return NULL;
+    else
+        return p;
+}
+
+/* Returns a new packet.  Copies dataLength bytes from data, and generates the checksum.
+ * User is responsible for deleting the returned packet. */
+Packet *Packet::create(uint8_t cmd, uint16_t packetNumber, uint16_t dataLength, uint8_t *data) {
+    if (dataLength > 0 && data == NULL)
+        return NULL;
+        
+    return new Packet(cmd, packetNumber, dataLength, data);
+}
+
+/* Copies dataLength bytes from data */
+Packet::Packet(uint8_t cmd, uint16_t packetNumber, uint16_t dataLength, uint8_t *data) {
+    checkSum = 0;
+    
+    this->cmd = cmd;
+    this->packetNumber = packetNumber;
+    this->dataLength = dataLength;
+    
+    checkSum ^= cmd;
+    checkSum ^= packetNumber;
+    checkSum ^= dataLength;
+    
+    this->data = new uint8_t[dataLength];
+    for (int i = 0; i < dataLength; i++) {
+        this->data[i] = data[i];
+        checkSum ^= data[i];
+    }
+}
+
+Packet::~Packet() {
+    delete[] data;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/comms.h	Sat Jun 07 07:12:25 2014 +0000
@@ -0,0 +1,43 @@
+#ifndef _COMMS_H
+#define _COMMS_H
+
+#include "mbed.h"
+#include "MODSERIAL.h"
+#include <limits.h>
+
+class Packet;   // forward declaration
+
+class Comms {
+    public:
+        Comms() : bt(P0_19, P0_18) { bt.baud(115200); }
+        
+        int receivePacket(Packet **p, int timeout);
+        void sendPacket(Packet *p);
+    
+    private:
+        Timer timer;
+        void sendByte(uint8_t byte);
+        void sendBytes(uint8_t *bytes, int nElms);
+        bool getByte(uint8_t *c, int timeout = INT_MAX);
+        bool getBytes(uint8_t *buf, int nElms, int timeout = INT_MAX);
+        MODSERIAL bt; // tx, rx
+};
+
+class Packet {
+    public:
+        static Packet *create(uint8_t cmd, uint16_t packetNumber, uint16_t dataLength, uint8_t *data);
+        static Packet *createAndVerify(uint8_t cmd, uint16_t packetNumber, uint16_t dataLength, uint8_t *data, uint16_t checkSum);
+        ~Packet();
+        
+        uint8_t cmd;
+        uint16_t packetNumber;
+        uint16_t dataLength;
+        uint8_t *data;
+        uint16_t checkSum;
+        
+        static const int HEADER_SIZE;
+    private:
+        Packet(uint8_t cmd, uint16_t packetNumber, uint16_t dataLength, uint8_t *data);
+};
+
+#endif // _COMMS_H
\ No newline at end of file
--- a/debug.h	Thu Jun 05 19:03:42 2014 +0000
+++ b/debug.h	Sat Jun 07 07:12:25 2014 +0000
@@ -7,7 +7,7 @@
 #define DMP_ERROR_RATE 1
 #define SD_ERROR_RATE 2
 
-#define NDEBUG
+//#define NDEBUG
 #ifndef NDEBUG
     /************ On-board LED Access      ****************/
     extern DigitalOut led;
--- a/log_data.cpp	Thu Jun 05 19:03:42 2014 +0000
+++ b/log_data.cpp	Sat Jun 07 07:12:25 2014 +0000
@@ -3,6 +3,8 @@
 #include "SDFileSystem.h"
 #include "helper_3dmath.h"
 #include "debug.h"
+#include "SystemTime.h"
+#include "pins.h"
 
 // SD Card
 SDFileSystem sd(P0_21, P0_22, P1_15, P1_19, "sd"); // MOSI, MISO, SCLK, SSEL SPI1
@@ -15,6 +17,8 @@
 
 /* Returns true if logging was successfully initialized, false otherwise */
 bool log_init() {
+    PC_PRINTLN("Initializing logging...");
+
     accelFile = fopen(ACCEL_LOG, "a");
     if (accelFile == NULL) {
         PC_PRINTLNF("SD card initialization error: Failed to open %s", ACCEL_LOG);
@@ -28,16 +32,19 @@
         DIE(SD_ERROR_RATE);
         return false;
     }
-    fprintf(accelFile, "---- BEGIN NEW DATASET ----\n");
-    fprintf(peakFile, "---- BEGIN NEW DATASET ----\n");
+
+//    fprintf(accelFile, "---- BEGIN NEW DATASET ----\n");
+//    fprintf(peakFile, "---- BEGIN NEW DATASET ----\n");
     return true;
 }
 
 /* Returns true if data was successfully logged, false otherwise 
    Used for logging acceleration data */
-bool log_data(VectorInt16 *data) {
+bool log_data(int time_ms, VectorInt16 *data) {
     if (accelFile != NULL) {
-        fprintf(accelFile, "%d, %d, %d\n", data->x, data->y, data->z);
+//        fprintf(accelFile, "%d, %d, %d, %d\n", time_ms, data->x, data->y, data->z);
+        fwrite(&time_ms, sizeof(int), 1, accelFile);
+        fwrite(data, sizeof(VectorInt16), 1, accelFile);
         return true;
     }
     
@@ -46,9 +53,11 @@
 
 /* Returns true if data was successfully logged, false otherwise 
    Used for logging split times */
-bool log_data(int split) {
+bool log_data(int time_ms, int split) {
     if (peakFile != NULL) {
-        fprintf(peakFile, "%d\n", split);
+//        fprintf(peakFile, "%d, %d\n", time_ms, split);
+        fwrite( (void*) &time_ms, sizeof(int), 1, peakFile);
+        fwrite( (void*) &split, sizeof(int), 1, peakFile);
         return true;
     }
     
--- a/log_data.h	Thu Jun 05 19:03:42 2014 +0000
+++ b/log_data.h	Sat Jun 07 07:12:25 2014 +0000
@@ -7,8 +7,8 @@
 #define PEAK_LOG "/sd/peaks.log"
 
 bool log_init();
-bool log_data(VectorInt16 *data);
-bool log_data(int split);
+bool log_data(int time_ms, VectorInt16 *data);
+bool log_data(int time_ms, int split);
 bool log_close();
 
 #endif // _LOG_FILE_H
\ No newline at end of file
--- a/main.cpp	Thu Jun 05 19:03:42 2014 +0000
+++ b/main.cpp	Sat Jun 07 07:12:25 2014 +0000
@@ -10,17 +10,20 @@
 #include "debug.h"
 #include "SystemTime.h"
 #include "sync.h"
+#include "pins.h"
+//#include "DS3231.h"
 
 // Capture button stuff
 #define PIN_DETECT_SAMPLE_PERIOD_uS 20000   // 20 ms sample period
 #define SYNC_HELD_SAMPLES   (SYNC_HOLD_TIME_MS * 1000 / PIN_DETECT_SAMPLE_PERIOD_uS)
 
 #ifdef USE_OLED
-// Display
-SPI spi0(P0_9, NC, P0_10); // mosi, miso, sclk
-Adafruit_SSD1306 oled(spi0, P0_11, P0_12, P0_13); // DC, RST, CS
+    SPI spi0(P0_9, NC, P0_10); // mosi, miso, sclk
+    Adafruit_SSD1306 oled(spi0, P0_11, P0_12, P0_13); // DC, RST, CS
 #endif
 
+// DS3231 rtc(I2C_SDA, I2C_SCL);
+
 // Mode button
 PinDetect captureButton(P0_16, PullUp);
 
@@ -28,6 +31,8 @@
 enum state {IDLE, CAPTURE, SYNC};
 enum state State;
 
+Timer captureTimer;
+
 // This is used to ensure the rising edge after a hold is ignored
 bool ignore_edge = false;
 void buttonHeld() {
@@ -84,34 +89,35 @@
             OLED_CLEAR();
             OLED_PRINTP("Capturing data...", 0, 0);
             
-            
+            captureTimer.start();
             while (State == CAPTURE) {
                 data = receive_data();
-                log_data(data);
+                log_data(captureTimer.read_ms(), data);
+
                 int split;
-                if (process_data(data->y, &split)) {
-                    PC_PRINTLNF("Split time: %d", split);
+                if (process_data((int) (data->x), (int) (data->y), &split)) {
+                    PC_PRINTLNF("Peak time: %d", split);
                     
                     int min = split / 60000;
                     int sec = (split / 1000) % 60;
                     int hund = (split / 10) % 100;
                     
-                    OLED_PRINTPF("%1d", min, 0, 40);
-                    OLED_PRINTPF("%02d", sec, 5, 40);
-                    oled.drawPixel(14, 44, 0x1);
-                    OLED_PRINTPF("%02d", hund, 15, 40);
-                    log_data(split);
+//                    OLED_PRINTPF("%1d", min, 0, 40);
+//                    OLED_PRINTPF("%02d", sec, 5, 40);
+//                    OLED_DRAWPIXEL(14, 44, 0x1);
+//                    OLED_PRINTPF("%02d", hund, 15, 40);
+                    log_data(captureTimer.read_ms(), split);
                 }
             }
-            
+            captureTimer.stop();
+            captureTimer.reset();
             receive_close();
             process_close();
             log_close();
         } else if (State == SYNC) {
             OLED_PRINTP("Ready to sync...", 0, 0);
             sync_init();
-            while (State == SYNC)
-                sync();
+            sync();
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp.orig	Sat Jun 07 07:12:25 2014 +0000
@@ -0,0 +1,112 @@
+#include "main.h"
+#include "mbed.h"
+#include "PinDetect.h"
+#include "USBSerial.h"
+#include "Adafruit_SSD1306.h"
+#include "SDFileSystem.h"
+#include "receive_data.h"
+#include "log_data.h"
+#include "process_data.h"
+#include "debug.h"
+#include "SystemTime.h"
+#include "sync.h"
+#include "pins.h"
+#include "DS3231.h"
+
+// Capture button stuff
+#define PIN_DETECT_SAMPLE_PERIOD_uS 20000   // 20 ms sample period
+#define SYNC_HELD_SAMPLES   (SYNC_HOLD_TIME_MS * 1000 / PIN_DETECT_SAMPLE_PERIOD_uS)
+
+#ifdef USE_OLED
+// Display
+SPI spi0(P0_9, NC, P0_10); // mosi, miso, sclk
+Adafruit_SSD1306 oled(spi0, P0_11, P0_12, P0_13); // DC, RST, CS
+#endif
+
+DS3231 rtc(I2C_SDA, I2C_SCL);
+
+// Mode button
+PinDetect captureButton(P0_16, PullUp);
+
+// State
+enum state {IDLE, CAPTURE, SYNC};
+enum state State;
+
+// This is used to ensure the rising edge after a hold is ignored
+bool ignore_edge = false;
+void buttonHeld() {
+    if (State == IDLE)
+        State = SYNC;
+    else
+        State = IDLE;
+    
+    // Button was held down, so don't count the next assert
+    ignore_edge = true;
+}
+
+void buttonPressed() {
+    // Don't ignore subsequent edges
+    if (ignore_edge) {
+        ignore_edge = false;
+        return;
+    }
+    
+    if (State == IDLE)
+        State = CAPTURE;
+    else if (State == CAPTURE)
+        State = IDLE;
+}
+
+int main(void)
+{
+    SystemTime::start();
+
+    State = IDLE;
+    
+    // After button is held, the next rising edge will call buttonPressed.
+    //   Because of this, inside the callbacks need to ensure that edge
+    //   does not do anything unintended.
+    captureButton.attach_deasserted_held(buttonHeld);
+    captureButton.attach_asserted(buttonPressed);
+    captureButton.setSampleFrequency();
+    captureButton.setSamplesTillHeld(SYNC_HELD_SAMPLES);
+    
+    VectorInt16 *data;
+    while (true) {
+        if (State == IDLE){
+            OLED_CLEAR();
+            OLED_PRINTP("Idling...", 0, 0);
+            PC_PRINTLN("Idling...");
+        } else if (State == CAPTURE) {
+            OLED_PRINTP("Starting capture...", 0, 0);
+            OLED_PRINTP("Init SD card...", 0, 10);
+            log_init(rtc.getTimestamp());
+            OLED_PRINTP("Init peak detect...", 0, 10);
+            process_init();
+            OLED_PRINTP("Init data receipt...", 0, 10);
+            receive_init();           
+            OLED_CLEAR();
+            OLED_PRINTP("Capturing data...", 0, 0);
+            
+            
+            while (State == CAPTURE) {
+                data = receive_data();
+                log_data(data);
+//                int split = process_data(data->x);
+//                if (split != UINT16_MAX) {
+//                    PC_PRINTLNF("Split time: %d", split);
+//                    OLED_PRINTPF("Split: %d", split, 0, 40);
+//                    log_data(split);
+//                }
+            }
+            
+            receive_close();
+            process_close();
+            log_close();
+        } else if (State == SYNC) {
+            OLED_PRINTP("Ready to sync...", 0, 0);
+            sync_init();
+            sync();
+        }
+    }
+}
--- a/main.h	Thu Jun 05 19:03:42 2014 +0000
+++ b/main.h	Sat Jun 07 07:12:25 2014 +0000
@@ -1,11 +1,22 @@
+#ifndef _MAIN_H
+#define _MAIN_H
+
 #define SYNC_HOLD_TIME_MS 1000
 #define DEBOUNCE_TIME_MS 200
 
-#define USE_OLED
+#include "Adafruit_SSD1306.h"
+
+// #define USE_OLED
 #ifdef USE_OLED
+
+    extern SPI spi0; // mosi, miso, sclk
+    extern Adafruit_SSD1306 oled; // DC, RST, CS
+
     #define OLED_SETCURS(xpos,ypos) oled.setCursor(xpos,ypos);
     #define OLED_CLEAR() oled.clearDisplay();
     
+    #define OLED_DRAWPIXEL(x,y,color) oled.drawPixel(x, y, color);
+    
     #define OLED_PRINT(x) oled.printf("%s", x); oled.display();
     #define OLED_PRINTF(x,y) oled.printf(x, y); oled.display();
     #define OLED_PRINTLN(x) oled.printf("%s\r\n", x); oled.display();
@@ -22,7 +33,10 @@
     #define OLED_PRINTPFR(x,y,xpos,ypos) oled.setCursor(xpos,ypos); oled.printf(x,y); oled.printf("\r"); oled.display();
 #else
     #define OLED_SETCURS(xpos,ypos)
-
+    #define OLED_CLEAR()
+    
+    #define OLED_DRAWPIXEL(x, y, color)
+    
     #define OLED_PRINT(x)
     #define OLED_PRINTF(x,y)
     #define OLED_PRINTLN(x)
@@ -37,4 +51,6 @@
     #define OLED_PRINTPLNF(x,y,xpos,ypos)
     #define OLED_PRINTPR(x,xpos,ypos)
     #define OLED_PRINTPFR(x,y,xpos,ypos)
-#endif
\ No newline at end of file
+#endif
+
+#endif // _MAIN_H
\ No newline at end of file
--- a/process_data.cpp	Thu Jun 05 19:03:42 2014 +0000
+++ b/process_data.cpp	Sat Jun 07 07:12:25 2014 +0000
@@ -6,46 +6,44 @@
 #include "PeakDetector.h"
 #include "FloatingThresholdPeakDetector.h"
 #include "SimplePeakDetector.h"
+#include "main.h"
 
-PeakDetector::PeakDetector *detector;
+PeakDetector::PeakDetector *peakDetector;
+PeakDetector::PeakDetector *startDetector;
 Timer split_timer;
 
+enum SwimState {WAITING, TIMING};
+SwimState swimState;
+
 /* Creates a new peak detector */
 bool process_init()
 {
-    detector = new FloatingThresholdPeakDetector();
+    swimState = WAITING;
+    
+    peakDetector = new FloatingThresholdPeakDetector();
+    startDetector = new SimplePeakDetector(30, 4000);
 
-    split_timer.start();
+    split_timer.reset();
     return true;
 }
 
-enum length {ZERO, ONE, TWO};
-static enum length Length = ZERO;
-static int l_zero, l_two;
-
 /* If true, loads latest split time into split  */
-bool process_data(int data, int *split)
+bool process_data(int xdata, int ydata, int *split)
 {
-    if (detector->onPeak(data)) {//
-        *split = SystemTime::read_ms();
-        return true;
-//        PC_PRINTLNF("Peak detected @ %d", SystemTime::read_ms());
-//        if (Length == ZERO) {
-//            l_zero = split_timer.read_ms();
-//            Length = ONE;
-//            return false;
-//        } else if (Length == ONE) {
-////            l_one = SystemTime::read_ms();
-//            Length = TWO;
-//            return false;
-//        } else {
-//            l_two = split_timer.read_ms();
-//            Length = ZERO;
-//            split_timer.reset();
-//        
-//            *split = abs((l_two - l_zero));
-//            return true;
-//        }
+    static int start_time;
+    if (swimState == WAITING) {
+        if (startDetector->onPeak(xdata)) {
+            swimState = TIMING;
+            split_timer.start();
+            start_time = SystemTime::read_ms();
+            OLED_PRINTPF("xpeak - %d     ", start_time, 0, 30);
+        }
+    } else if (swimState == TIMING) {
+        if (peakDetector->onPeak(ydata) && SystemTime::read_ms() - start_time > 5000 ) {
+            *split = split_timer.read_ms();
+            OLED_PRINTPF("ypeak - %d     ", *split, 0, 40);
+            return true;
+        }
     }
     
     return false;
@@ -54,9 +52,9 @@
 bool process_close() {
     split_timer.reset();
     split_timer.stop();
-    Length = ZERO;
-    l_zero = l_two = 0;
     
-    delete detector;
+    delete peakDetector;
+    delete startDetector;
+    
     return true;
 }
\ No newline at end of file
--- a/process_data.h	Thu Jun 05 19:03:42 2014 +0000
+++ b/process_data.h	Sat Jun 07 07:12:25 2014 +0000
@@ -4,7 +4,7 @@
 #include "mbed.h"
 
 bool process_init();
-bool process_data(int data, int *split);
+bool process_data(int xdata, int ydata, int *split);
 bool process_close();
 
 #endif // _PROCESS_DATA_H
\ No newline at end of file
--- a/receive_data.cpp	Thu Jun 05 19:03:42 2014 +0000
+++ b/receive_data.cpp	Sat Jun 07 07:12:25 2014 +0000
@@ -95,4 +95,6 @@
         DIE(DMP_ERROR_RATE);
         return false;
     }
+    
+    PC_PRINTLN("Receive init success, capturing data...");
 }
\ No newline at end of file
--- a/sync.cpp	Thu Jun 05 19:03:42 2014 +0000
+++ b/sync.cpp	Sat Jun 07 07:12:25 2014 +0000
@@ -1,39 +1,303 @@
 #include "mbed.h"
 #include "sync.h"
+#include "DS3231.h"
+#include "Timeout.h"
+#include "SDFileSystem.h"
+#include "MODSERIAL.h"
+#include "debug.h"
+#include <string>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include "comms.h"
 
-/*
-    PACKET STRUCTURE:
-    
-    Command:
-        [ 1 CMD | 17 SESSION_ID (optional) ]
-    
-    Response:
-        [ 1 ACK/NACK | X Data (optional) ]
-        
-    Byte | Description
-    ------------------
-    0x0  | ACK        
-    0x1  | NACK         
-    0x2  | Delete All  
-    0x4  | Receive file 
-*/
+enum state {IDLE, CAPTURE, SYNC};
+extern enum state State;
+extern DS3231 rtc;
+Timeout t;
 
-Serial bt(P0_19, P0_18); // tx, rx
+//MODSERIAL bt(P0_19, P0_18); // tx, rx
+Comms btComm;
+uint16_t packetSeq = 0;
 
-bool sync_init() {
-    bt.baud(115200);
+bool sync_init()
+{
     return true;
 }
 
-unsigned char get_command() {
+
+
+//void setRtc(packet *p)
+//{
+//    int dayOfWeek=0, date, month, year, hours, minutes, seconds;
+//    uint16_t len;
+//    len = getLen();
+//    int i = 0;
+//    for(i = 0; i < len; i++)
+//    {
+//        buff[i] = bt.getc();
+//    }
+//    buff[i] = 0; // end the string with a zero
+//    sscanf(buff, "%04d-%02d-%02d %02d:%02d:%02d",&year,&month,&date,&hours,&minutes,&seconds);
+//    rtc.setDate(dayOfWeek, date, month, year);
+//    rtc.setTime(hours, minutes, seconds);
+//    //sendResponse(CMD_RTCSET, ACK);
+//}
+
+//void listSessions()
+//{   //todo buffer this with buff
+//    DIR *dp;
+//    struct dirent *dirp;
+//    dp = opendir("/sd/");
+//    while((dirp = readdir(dp)) != NULL) {
+//        bt.puts(dirp->d_name);
+//        bt.putc(',');
+//        //todo: put size here?
+//        bt.puts("\r\\n");
+//    }
+//    closedir(dp);
+//}
+
+//void syncSession()
+//{
+//    //sendResponse(buf[0], resp);
+//    //populate packet:
+//    //1 byte CMD_SYNCSESSION 0x03
+//    //2 bytes packet number
+//    //2 bytes current packet's data's length
+//    //2 bytes checksum
+//}
+//
+
+/* Sends a file over BT stream.  Returns
+ * true on success, false on failure. */
+bool sendFile(string filename)
+{
+    PC_PRINTLNF("sendFile: Trying to open file %s", filename.c_str());
+    FILE *fp = fopen(filename.c_str(), "r");
+    
+    if (fp == NULL) {
+        PC_PRINTLNF("sendFile: Error opening file %s", filename.c_str());
+        return false;
+    }
+    
+    fseek(fp, 0L, SEEK_END);
+    int file_size = ftell(fp);
+    fseek(fp, 0L, SEEK_SET);
+    
+    Packet *firstPacket = Packet::create(CMD_SYNCOLDEST, 0x00, sizeof(file_size), (uint8_t *) &file_size);
+    btComm.sendPacket(firstPacket);
+
+    PC_PRINTLNF("sendFile: first packet checksum = %x", firstPacket->checkSum);
+    
+    delete firstPacket;
     
+    Packet *res;
+    int n = btComm.receivePacket(&res, TIMEOUT);
+    if (n <= 0) {
+        PC_PRINTLN("sendFile: timeout waiting for ack!");
+        fclose(fp);
+        return false;
+    }
+
+    if (res->cmd != ACK) {
+        PC_PRINTLN("sendFile: packet received was not an ack!");
+        delete res;
+        fclose(fp);
+        return false;
+    }
+
+    delete res;
+
+    uint8_t *d = new uint8_t[PACKET_MAX_DATA];
+    
+    PC_PRINTLN("sendFile: created buffer");
+    int len;
+    int numPackets = 0;
+    while ( (len = fread(d, 1, PACKET_MAX_DATA, fp) ) > 0 ) {
+        PC_PRINTLNF("sendFile: packet number: %d ", numPackets);
+        PC_PRINTLNF("length: %d", len);
+
+        Packet *p = Packet::create(CMD_SYNCOLDEST, 0x00, len, d);
+        PC_PRINTLNF("sendFile: packet checksum = %x", p->checkSum);
+        btComm.sendPacket(p);
+        delete p;
+        
+        for (int i = 0; i < len; i++) {
+            PC_PRINTLNF("sendFile: packet[%d] = ", i);
+            PC_PRINTLNF("%x", d[i]);   
+        }
+        
+        PC_PRINTLNF("sendFile: sent packet of length %d", len);
+        PC_PRINTLN("sendFile: waiting for ack...");
+        
+        Packet *resp;
+        int n = btComm.receivePacket(&resp, TIMEOUT);
+        if (n <= 0) {
+            PC_PRINTLN("sendFile: timeout waiting for ack!");
+            fclose(fp);
+            return false;
+        }
+        
+        if (resp->cmd != ACK) {
+            PC_PRINTLN("sendFile: packet received was not an ack!");
+            delete resp;
+            fclose(fp);
+            return false;
+        }
+        
+        delete resp;
+        
+        PC_PRINTLN("sendFile: received ack!");
+        numPackets++;
+    }
+    delete[] d;
+
+    PC_PRINTLNF("sendFile: done sending %s in ", filename.c_str());
+    PC_PRINTLNF("%d packets.", numPackets);
+    // Appears to be a bug where feof isn't defined, so no error checking :(
+//    if (!feof(fp)) {
+//        PC_PRINTLNF("sendFile: Error reading file %s", absolute_filename.c_str());
+//        return false;
+//    }
+    
+    fclose(fp);
+    return true;
 }
 
-void sync() {
-    if(bt.readable()) {
-        bt.putc(bt.getc());
-        bt.putc('\n');
+/* Returns absolute filename of the oldest log file on the SD card */
+bool getOldestFile(string *oldest) 
+{
+    
+    PC_PRINTLN("Finding oldest file...");
+    
+    // Ensure all fields get set to zero
+    long long file_time = {0};
+    long long oldest_time = LLONG_MAX;  // ensures first file gets set to oldest
+    string oldest_file;
+
+    DIR *dp;
+    struct dirent *dirp;
+    dp = opendir("/sd/");
+
+    if (dp == NULL) {
+      PC_PRINTLN("syncOldestSession: Error opening directory");
+      return false;
+    }
+
+    while((dirp = readdir(dp)) != NULL) {
+        char *strp = dirp->d_name;
+
+        // Verify we are looking at a .log file
+        char ext[5];
+        memcpy(ext, strp+strlen(strp) - 4, 5);
+        if (strncmp(ext, ".log", 4) == 0) {
+            PC_PRINTLNF("syncOldestSession: reading file %s", dirp->d_name);
+
+            file_time = strtoll(strp, NULL, 10);
+
+            // If file time is older than oldest time, set the oldest file
+            //   to the current file
+            if (file_time < oldest_time) {
+                PC_PRINTLN("syncOldestSession: updating oldest file");
+                oldest_time = file_time;
+                oldest_file = strp;
+            }
+        }
     }
     
-    unsigned char cmd = get_command();
+    PC_PRINTLNF("getOldestFile: prepending /sd/ to %s", oldest_file.c_str());
+    *oldest = "/sd/";
+    *oldest += oldest_file;
+    
+    closedir(dp);
+    return true;    
+}
+
+bool syncOldestSession()
+{
+    string oldest;
+    
+    if (getOldestFile(&oldest))
+        return sendFile(oldest);
+    
+    return false;
+}
+
+bool deleteOldestSession()
+{
+    string oldest;
+    
+    if (getOldestFile(&oldest)) {
+        PC_PRINTLNF("deleteOldestSession: deleting %s", oldest.c_str());
+        
+        if (remove(oldest.c_str()) == 0) {
+           PC_PRINTLN("deleteOldestSession: delete success");
+           // send ack
+           return true;
+        }
+    }
+        
+    // send ack
+        
+    return false;
+}
+
+void sync()
+{
+    PC_PRINTLN("Entered sync mode...");
+    while(State == SYNC) {
+        PC_PRINTLN("Waiting for packet...")
+        Packet *p; 
+        int ret = btComm.receivePacket(&p, TIMEOUT);
+        if (ret == 0) {
+            PC_PRINTLN("Timeout!");
+            continue;
+        } else if (ret < 0) {
+            PC_PRINTLN("Received bad packet :(");
+            continue;
+        }
+
+        PC_PRINTLNF("cmd: %x", p->cmd);
+        PC_PRINTLNF("pnum: %x", p->packetNumber);
+        PC_PRINTLNF("len: %x", p->dataLength);
+        for (int i = 0; i < p->dataLength; i++) {
+            PC_PRINTF("data[%d]: ", i);
+            PC_PRINTLNF("%x", p->data[i]);
+        }
+        PC_PRINTLNF("check: %x", p->checkSum);
+        switch(p->cmd) {
+            case CMD_SYNCOLDEST:
+                if (!syncOldestSession())
+                    PC_PRINTLN("Sync oldest session failed!");
+                    break;
+            case CMD_DELETEOLDEST:
+                if (!deleteOldestSession())
+                    PC_PRINTLN("Delete oldest session failed!");
+                    break;
+//                case CMD_RTCSET:
+//                    //setRtc(p);
+//                    break;
+//                case CMD_LISTSESSIONS:
+//                    listSessions();
+//                    break;
+//                case CMD_SYNCSESSION:
+//                    syncSession();
+//                    break;
+//                case CMD_DELETESESSION:
+//                    deleteSession();
+//                    break;
+//                case CMD_DONE:
+//                    bt.putc(CMD_DONE);
+//                    //sendResponse(CMD_DONE, ACK);
+//                    State = IDLE;
+//                    break;
+//                default: break;
+        }
+
+        PC_PRINTLN("Deleting received packet...");
+        delete p;
+        PC_PRINTLN("Ready for new packet");
+    }
 }
\ No newline at end of file
--- a/sync.h	Thu Jun 05 19:03:42 2014 +0000
+++ b/sync.h	Sat Jun 07 07:12:25 2014 +0000
@@ -4,4 +4,16 @@
 bool sync_init();
 void sync();
 
+#define CMD_RTCSET 0x01
+#define CMD_LISTSESSIONS 0x02
+#define CMD_SYNCOLDEST 0x03
+#define CMD_DELETEOLDEST 0x04
+#define CMD_DONE 0x05
+#define ACK 0x06
+#define NACK 0x07
+
+#define PACKET_MAX_DATA 110
+
+#define TIMEOUT 5000
+
 #endif // _SYNC_H
\ No newline at end of file