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:46:38 2014 +0000
Parent:
21:2fa676f214fe
Parent:
20:294eaeaf2ebb
Child:
23:80083138d609
Commit message:
Another merge;

Changed in this revision

RealtimeMath.lib Show annotated file Show diff for this revision Revisions of this file
RealtimeMath.lib.orig 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.cpp.orig 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
comms.h.orig 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.cpp.orig 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 diff for this revision Revisions of this file
main.h 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.cpp.orig 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
sync.h.orig Show annotated file Show diff for this revision Revisions of this file
--- a/RealtimeMath.lib	Sat Jun 07 07:12:25 2014 +0000
+++ b/RealtimeMath.lib	Sat Jun 07 07:46:38 2014 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/ellingjp/code/RealtimeMath/#e6c5780532d1
+http://mbed.org/users/ellingjp/code/RealtimeMath/#922b711e7a4b
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RealtimeMath.lib.orig	Sat Jun 07 07:46:38 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/ellingjp/code/RealtimeMath/#e6c5780532d1
--- a/comms.cpp	Sat Jun 07 07:12:25 2014 +0000
+++ b/comms.cpp	Sat Jun 07 07:46:38 2014 +0000
@@ -3,6 +3,7 @@
 
 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
@@ -21,17 +22,19 @@
     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;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/comms.cpp.orig	Sat Jun 07 07:46:38 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
--- a/comms.h	Sat Jun 07 07:12:25 2014 +0000
+++ b/comms.h	Sat Jun 07 07:46:38 2014 +0000
@@ -10,7 +10,7 @@
 class Comms {
     public:
         Comms() : bt(P0_19, P0_18) { bt.baud(115200); }
-        
+
         int receivePacket(Packet **p, int timeout);
         void sendPacket(Packet *p);
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/comms.h.orig	Sat Jun 07 07:46:38 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/log_data.cpp	Sat Jun 07 07:12:25 2014 +0000
+++ b/log_data.cpp	Sat Jun 07 07:46:38 2014 +0000
@@ -3,7 +3,10 @@
 #include "SDFileSystem.h"
 #include "helper_3dmath.h"
 #include "debug.h"
+<<<<<<< local
 #include "SystemTime.h"
+=======
+>>>>>>> other
 #include "pins.h"
 
 // SD Card
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/log_data.cpp.orig	Sat Jun 07 07:46:38 2014 +0000
@@ -0,0 +1,76 @@
+#include "mbed.h"
+#include "log_data.h"
+#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
+
+// DS3231 rtc(I2C_SDA, I2C_SCL);
+
+// Logging vars
+FILE *accelFile;
+FILE *peakFile;
+
+/* 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);
+        DIE(SD_ERROR_RATE);
+        return false;
+    }
+    
+    peakFile = fopen(PEAK_LOG, "a");
+    if (peakFile == NULL) {
+        PC_PRINTLNF("SD card initialization error: Failed to open %s", SPLIT_LOG);
+        DIE(SD_ERROR_RATE);
+        return false;
+    }
+
+//    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(int time_ms, VectorInt16 *data) {
+    if (accelFile != NULL) {
+//        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;
+    }
+    
+    return false;
+}
+
+/* Returns true if data was successfully logged, false otherwise 
+   Used for logging split times */
+bool log_data(int time_ms, int split) {
+    if (peakFile != NULL) {
+//        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;
+    }
+    
+    return false;
+}
+
+/* Returns true if logging was successfully closed, false otherwise */
+bool log_close() {
+//    if (accelFile != NULL && splitFile != NULL)
+//        return ( (fclose(accelFile) == 0) && (fclose(splitFile) == 0) );
+    
+    fclose(accelFile);
+    fclose(peakFile);
+    
+    return true;
+}
\ No newline at end of file
--- a/main.cpp.orig	Sat Jun 07 07:12:25 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-#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/sync.cpp	Sat Jun 07 07:12:25 2014 +0000
+++ b/sync.cpp	Sat Jun 07 07:46:38 2014 +0000
@@ -76,6 +76,12 @@
 {
     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;
+    }
+
+    uint8_t *d = new uint8_t[PACKET_MAX_DATA];
     
     if (fp == NULL) {
         PC_PRINTLNF("sendFile: Error opening file %s", filename.c_str());
@@ -115,9 +121,11 @@
     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);
+        PC_PRINTLNF("sendFile: sending packet of length %d", len);
 
         Packet *p = Packet::create(CMD_SYNCOLDEST, 0x00, len, d);
         PC_PRINTLNF("sendFile: packet checksum = %x", p->checkSum);
@@ -156,6 +164,7 @@
 
     PC_PRINTLNF("sendFile: done sending %s in ", filename.c_str());
     PC_PRINTLNF("%d packets.", numPackets);
+    PC_PRINTLNF("sendFile: done sending %s", filename.c_str());
     // 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());
@@ -250,6 +259,7 @@
     while(State == SYNC) {
         PC_PRINTLN("Waiting for packet...")
         Packet *p; 
+
         int ret = btComm.receivePacket(&p, TIMEOUT);
         if (ret == 0) {
             PC_PRINTLN("Timeout!");
@@ -267,6 +277,7 @@
             PC_PRINTLNF("%x", p->data[i]);
         }
         PC_PRINTLNF("check: %x", p->checkSum);
+
         switch(p->cmd) {
             case CMD_SYNCOLDEST:
                 if (!syncOldestSession())
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sync.cpp.orig	Sat Jun 07 07:46:38 2014 +0000
@@ -0,0 +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"
+
+enum state {IDLE, CAPTURE, SYNC};
+extern enum state State;
+extern DS3231 rtc;
+Timeout t;
+
+//MODSERIAL bt(P0_19, P0_18); // tx, rx
+Comms btComm;
+uint16_t packetSeq = 0;
+
+bool sync_init()
+{
+    return true;
+}
+
+
+
+//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;
+}
+
+/* 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;
+            }
+        }
+    }
+    
+    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	Sat Jun 07 07:12:25 2014 +0000
+++ b/sync.h	Sat Jun 07 07:46:38 2014 +0000
@@ -15,5 +15,4 @@
 #define PACKET_MAX_DATA 110
 
 #define TIMEOUT 5000
-
 #endif // _SYNC_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sync.h.orig	Sat Jun 07 07:46:38 2014 +0000
@@ -0,0 +1,19 @@
+#ifndef _SYNC_H
+#define _SYNC_H
+
+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