Swimate V2 without RTOS code
Dependencies: Adafruit_GFX_128x64 DS3231 PinDetect SDFileSystem USBDevice mbed RealtimeMath MODSERIAL
Revision 21:2fa676f214fe, committed 2014-06-07
- 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
--- 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