posilani dat
Dependencies: FatFileSystemCpp mbed PowerControl USBHostLite
main.cpp
- Committer:
- PavelKumpan
- Date:
- 2017-03-13
- Revision:
- 23:bb76f8ad9557
- Parent:
- 22:69621e10dd26
- Child:
- 24:f9809529d3ce
File content as of revision 23:bb76f8ad9557:
/* BRIEF: * Connects to wifi and listen on ip given by dhcp on port 2000 * * Commands are send in for #X where X is from {S,E,T,B,R}, all commands are * confirmed by mbed by sending #A * * Use #S to start saving data, #E to stop saving. This can be done repeatedly, * mbed saves the data into separated files and generates new swimmer id * At the end, use #T to start data transfer, the format of transmitted data is: * * Header for each swimmer: * (int) -1 (int) -1 (int) swimmer_id * Data itself * (char) 0xAA (int) count 3*(short) acc 3*(float) gyro * End of swimmer block * (int) -1 (int) -1 * * where count is number starting on 0, incremented on every packet * 0xAA is a sync byte used to avoid confusion when some bytes are lost during * transmission (UART on faster reates seems to be unstable) * * CHANGELOG 22/10/2015 * - Refactored code * - Now using USB flash instead of SD card * - SIZE of packets to be saved at once changed to 32 (from 1000, saving took too much time, effectively loosing measurements) * - Using fwrite to write 32 packets at once (packet size = 16 bytes -> 32*16 = 512 bytes -> USB flash sector size is 512 bytes, thus maximizing fwrite effectivity * - Saving of 32 packets takes about 3,5 ms * KNOWN ISSUES: * - Opening USB disk takes some time, couple first measurements not valid (perhaps open next file right when saving stops ?) * * CHANGELOG 13/11/2015 * - Focused on data acquisition * - #T commands now requires one byte after ACK to pick which swimmer data to send * - When board resets, it deletes all files on root, to make sure old data won't get send * - Added new command #B which represents begining of unified scope of data and should be sent right after connecting (clears all files and resets swimmerid) * * CHANGELOG 7/1/2016 * - Integrated MPU6000 IMU library * - Rewritten data acquisition to support new IMU * - Edited usbhost library to support sandisk flash disk * * CHANGELOG 12/1/2016 * - Added delay after chipselect deselection between device bursts (solved gyro data inconsistency) * * CHANGELOG 6/5/2016 * - Moved to first real HW (rev 1.0) * - Added multipurpose button functionality * * CHANGELOG 19/10/2016 * - Added status message * - Changed button behaviour * - Added background battery monitoring * - Added background filesystem monitoring * * CHANGELOG 22/10/2016 * - Slightly adjusted wifly communication (added timeouts) * - Disabled TCP autoretransmission on wifly * - Added send log feature * * CHANGELOG 05/03/2017 * - Added define switch for new revision of hardware * - HW v1r2 only supports single MPU * * CHANGELOG 10/03/2017 * - Added swimmer index to the status message. * - Added record file for records, function appendRecord, sendRecords * - Added clear root command * * CHANGELOG 13/03/2017 * - Removed clearRoot() call from init. * - Change representation of the records file to binary. */ // Includes ==================================================================== #include "mbed.h" #include "EthernetPowerControl.h" #include "MSCFileSystem.h" #include "PowerControl.h" #include "DirHandle.h" #include "mpu6000.h" #include "stdint.h" #include "stdio.h" #include "utils.h" #include "wifi.h" #include "math.h" // Revision ==================================================================== // Revision define, it's important to select proper version! (pinmuxes differ) #define REVISION 1 // Defines ===================================================================== /* Data acquisition related stuff */ //#define SAMPLE_RATE 700000 // Sample rate for ADC conversion #define SAMPLE_RATE 10000 #define SAMPLE_PERIOD 0.01 // Setting the period of measuring, 0.01 means 100 times per second #define SIZE 32 // Setting number of instance in array - for saving to SD card #define BUFFER_SIZE (sizeof(int) + sizeof(short)*6) //size of one data block /* Battery related defines */ #define UVLO_THRESHOLD 140U // Battery low threshold #define BATTERY_PERIOD 30U // How often to measure voltage in seconds /* Button press defines */ #define PRESS_PERIOD_SHUTDOWN 2000U #define PRESS_PERIOD_LOW 250U #define PRESS_PERIOD_HIGH 450U /* Mass storage realted stuff */ #define FSNAME "usb" #define LOG_FILE "/usb/log.txt" #define RECORDS_FILE "/usb/records.txt" #define SPACE_LOW_THRESHOLD 100 // USB Flash disk free threshold #define SPACE_PERIOD 300U // How often to measure free space in seconds /* Commands swimfly understands */ #define SAVING_START 'S' #define SAVING_STOP 'E' #define TRANSFER_REQUEST 'T' #define SCOPE_BEGIN 'B' #define CHECK_READY 'R' #define SEND_LOG 'L' #define SEND_RECORDS 'D' #define HALT 'H' /* Comm stuff */ #define SOH 0x01 /* Test mode define (undefine to disable) */ //#define LOG_TEST_MODE /* Function like macros for leds (bleh) */ #define leds_off() { led_measuring = led_sending = led_working = led_saving = 0; } #define leds_error() { led_measuring = led_sending = led_working = led_saving = 1; } // Function to power down magic USB interface chip with new firmware #define USR_POWERDOWN (0x104) int semihost_powerdown() { uint32_t arg; return __semihost(USR_POWERDOWN, &arg); } // Function prototypes ========================================================= /* File handling */ void clearRoot(void); void appendLog(char textToAppend[]); void appendRecord(void); bool doesFileExist(const char *filename); void spaceMeas(void); void readSwimmerID(void); /* Button handlers */ void btnPressCallback(void); void btnReleaseCallback(void); /* Power management */ void pllInit(void); void battMeas(void); void shutdownHandler(void); /* Init */ void boardInit(void); /* Measurement */ void measure(void); void setMeasuringFlag(void); /* Command functions */ void startSaving(void); void stopSaving(void); void transfer(void); void sendLog(void); void halt(void); void beginScope(void); void sendStatus(void); /* Generic functions */ void blink(void); // Watchdog class ============================================================== class Watchdog { public: /* Kick the watchdog with time period setting */ void setKick(float s) { LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4 LPC_WDT->WDTC = s * (float)clk; LPC_WDT->WDMOD = 0x3; // Enabled and Reset kick(); } /* Kick the watchdog */ void kick() { LPC_WDT->WDFEED = 0xAA; LPC_WDT->WDFEED = 0x55; } }; // Objects & vars ============================================================== /* Objects */ Watchdog wdt; // Initialize watchdog Ticker Saving_Ticker; // Ticker for interrupts on measuring Ticker Battery_Ticker; // Ticker for voltage measurement Ticker Space_Ticker; // Ticker for free space measurement Wifi wifi(p13, p14, p12, p23); // Wifly module SPI spi(p5, p6, p7); // NEW MPU6000 SPI connection MPU6000 mpu(spi, p8); // NEW MPU6000 Timer button_timer; // Button press time counter Serial pc(USBTX, USBRX); // USB Serial port /* LED indicators */ #if REVISION == 1 DigitalOut led_system(p30); #elif REVISION == 2 DigitalOut led_system(p27); DigitalOut cs_2(p26); #endif DigitalOut led_measuring(LED1); DigitalOut led_sending(LED2); DigitalOut led_working(LED3); DigitalOut led_saving(LED4); /* System LED notification patterns */ //typedef enum {USER_BOOT, UVLO, DISK_FULL, AOK} blink_t; /* Power related stuff */ DigitalOut wifly_enable_n(p9); DigitalOut flash_enable_n(p10); DigitalOut btn_latch_n(p28); InterruptIn btn_input(p29); AnalogIn batt_vol(p15); volatile uint8_t systemRequest = 0; volatile bool userShutdownFlag = 0; volatile bool UVLOShutdownFlag = 0; volatile uint8_t battLevel = 150U; // Batt level between 136U/3.4816V and 165U/4.2240V (High byte of 16bit voltage measurement) volatile uint32_t curTime = 0; volatile uint32_t oldTime = 0; /* Added for test purposes */ #ifdef LOG_TEST_MODE DigitalOut flagSetNotify(p19); DigitalOut measureNotify(p20); #endif /* USB && saving related stuffs */ FILE *gfp; // Global file pointer MSCFileSystem logger(FSNAME); // Initialize USB flash disk char fname[40]; // Variable for name of Text file saved on USB flash disk uint8_t timestamp[8]; // Variable for name of Text file saved on USB flash disk static volatile uint64_t absolute = 0; // Variable for numbering saved data volatile int relative = 0; // Relative packtets saved number volatile uint8_t swimmer_id = 0; // Global swimmer ID volatile bool measuringFlag = 0; // Flag that is set with interrupt and indicates measurement is to be done volatile bool savingFlag = 0; // Flag that is set and indicates data is being saved periodically volatile bool lowSpaceFlag = 0; // Flag that is set when below SPACE_THRESHOLD MB's remain free volatile uint16_t mbFree = 0; // Variable to store remaining space on USB flash disk /* Accelerometer buffers */ short int acc_x[SIZE]; short int acc_y[SIZE]; short int acc_z[SIZE]; /* Gyroscope buffers */ short int gyro_x[SIZE]; short int gyro_y[SIZE]; short int gyro_z[SIZE]; // Functions -> File handling ================================================== /* Clear all files in root directory */ void clearRoot(void) { char buf[40]; // Buffer for string building /* Dir related structs & vars */ DIR *dir; // Prepare directory handle struct dirent *file; // Directory entry structure dir = opendir("/usb"); // Open root of usb flash disk /* Iterate all files beside log file in root directory and delete them */ while((file = readdir(dir)) != NULL) // Incrementally points to next files, until NULL is reached { if (strcmp(file->d_name, "log.txt") != 0) // Only dele non-log files { sprintf(buf, "/usb/"); sprintf(buf+5, file->d_name); remove(buf); // Remove file that is currently being pointed to } } /* If file is not present */ closedir(dir); // Close dir & return false } /* Append line to log file */ void appendLog(char textToAppend[]) { printf("Writing to log file...\r\n"); /* Append line to log file */ FILE *log; log = fopen(LOG_FILE, "a"); // Open file with log name fprintf(log, "%s\r\n", textToAppend); // Append line fclose(log); // Close file } /* Append record to records file */ void appendRecord(void) { printf("Writing to record file...\r\n"); /* Append line to records file */ FILE *records; records = fopen(RECORDS_FILE, "a"); // Open file with records name uint8_t recordbuffer[9]; recordbuffer[0] = swimmer_id; for(int i = 0; i < 8; i++) { recordbuffer[i+1] = timestamp[i]; } fwrite(recordbuffer, 1, 9, records); // Write 32 buffer lines (16 bytes) to file (512 bytes total -> one block) fflush(records); fclose(records); // Close file } /* Read last swimmer ID */ void readSwimmerID(void) { if(false == doesFileExist(RECORDS_FILE)) { swimmer_id = 0; printf("File with records does not exists, so ID set to 0...\r\n"); } else { printf("Reading last swimmer ID from records file...\r\n"); /* Append line to records file */ FILE *records; records = fopen(RECORDS_FILE, "r"); // Open file with records name fseek(records, -8, SEEK_END); if(ferror(records)) { swimmer_id = 0; } else { swimmer_id = (uint8_t)fgetc(records) + 1; } fclose(records); printf("Actual index is %d...\r\n", swimmer_id); } } /* Sees whether giver file exists on flash disk */ bool doesFileExist(const char *filename) { /* Dir related structs & vars */ DIR *dir; // Prepare directory handle struct dirent *file; // Directory entry structure dir = opendir("/usb"); // Open root of usb flash disk /* Iterate all available files in root directory */ while((file = readdir(dir)) != NULL) // Incrementally points to next files, until NULL is reached { /* Check if it's file we are looking for */ if(strcmp(filename+5, file->d_name) == 0) // +5 moves us beyond /usb/, not cool I know... { closedir(dir); // Close dir & return true return true; } } /* If file is not present */ closedir(dir); // Close dir & return false return false; // If not, return false } /* Measures space left and updates global variable value */ void spaceMeas(void) { FATFS* fs; DWORD fre_clust; f_getfree("0:",&fre_clust,&fs); mbFree = (uint16_t)((fs->csize * fs->free_clust) >> 11); } // Functions -> Power management =============================================== void pllInit(void) { LPC_SC->PLL0CON = 0x00; /* PLL0 Disable */ LPC_SC->PLL0FEED = 0xAA; LPC_SC->PLL0FEED = 0x55; LPC_SC->CCLKCFG = 0x00000005; /* Select Clock Divisor = 6 */ LPC_SC->PLL0CFG = 0x0000000B; /* configure PLL0 */ LPC_SC->PLL0FEED = 0xAA; /* divide by 1 then multiply by 12 */ LPC_SC->PLL0FEED = 0x55; /* PLL0 frequency = 288,000,000 */ LPC_SC->PLL0CON = 0x01; /* PLL0 Enable */ LPC_SC->PLL0FEED = 0xAA; LPC_SC->PLL0FEED = 0x55; while (!(LPC_SC->PLL0STAT & (1<<26)));/* Wait for PLOCK0 */ LPC_SC->PLL0CON = 0x03; /* PLL0 Enable & Connect */ LPC_SC->PLL0FEED = 0xAA; LPC_SC->PLL0FEED = 0x55; while (!(LPC_SC->PLL0STAT & ((1<<25) | (1<<24))));/* Wait for PLLC0_STAT & PLLE0_STAT */ SystemCoreClockUpdate(); /* Should now be at 48,000,000 */ SystemCoreClock = (12000000 * 2 / (((LPC_SC->PLL0STAT >> 16) & 0xFF) + 1) * ((LPC_SC->PLL0STAT & 0x7FFF) + 1) / ((LPC_SC->CCLKCFG & 0xFF)+ 1)); } /* Callback for button press */ void btnPressCallback(void) { /* Resets and starts timer */ button_timer.reset(); button_timer.start(); } /* Callback for button release */ void btnReleaseCallback(void) { /* Stop timer */ button_timer.stop(); /* See whether user is trying to shutdown */ uint32_t buf = button_timer.read_ms(); if((buf < PRESS_PERIOD_HIGH) && (buf > PRESS_PERIOD_LOW)) { systemRequest += 1; } else { led_system = !led_system; systemRequest = 0; } } /* Does single battery voltage measurement, and sets UVLO flag if voltage too low */ void battMeas(void) { battLevel = batt_vol.read_u16() >> 8; // Store High byte of voltage measurement to global variable if(battLevel < UVLO_THRESHOLD) // Determine whether we have enough juice { UVLOShutdownFlag = 1; // Raise Under Voltage Lock Out flag if necessary } } /* Checkes whether UVLO flag is set and halts board if necessary */ void shutdownHandler(void) { /* Button shutdown handler */ if(3 == systemRequest) { halt(); // Halt } /* UVLO shutdown handler */ if(1 == UVLOShutdownFlag) // Control of flag that is being set asynchronously if battLevel drops below threshold { if (1 == savingFlag) // If saving's in progress stop it, to make sure file system won't get corrupted { stopSaving(); } UVLOShutdownFlag = 0; blink(); blink(); appendLog("Battery low halting"); printf("Battery low, halting.\r\n"); btn_latch_n = 1; // Halt } } // Functions -> Init =========================================================== /* Prepares board for operation (adc's, gyroscope etc.) */ void boardInit (void) { //pllInit(); pc.baud(9600); pc.printf("\r\nBooting...\r\n"); // Notify user that board is booting pc.printf("SystemCoreClock = %d Hz\r\n", SystemCoreClock); /* Watchdog */ if ((LPC_WDT->WDMOD >> 2) & 1) { led_system = 1; wait(1); led_system = 0; } wdt.setKick(15.0); /* Power related stuff */ btn_latch_n = 0; // This latch holds power P-MOS opened in order to provide power to whole board wait_ms(20); flash_enable_n = 0; wait_ms(20); wifly_enable_n = 0; wifi.init(); // Initialize wifly led_measuring = 1; // Use incremental LED's to notify user about boot stages #if REVISION == 2 cs_2 = 1; #endif /* IMU init */ uint8_t name = mpu.init(); // Initializes both gyro and accelerometer printf("0x%02X MPUID\r\n", name); wait_ms(40); // Wait for settings to stabilize led_sending = 1; // Light up second LED to notify mpu init ok /* Power saving features */ PHY_PowerDown(); // Disable ETH PHY to conserve power (about 40mA) semihost_powerdown(); // Disable USB Host to conserve power (about 30mA) wait_ms(40); // Wait a bit led_working = 1; // Light up third LED /* Measure voltage */ battMeas(); printf("%d mV\r\n", (battLevel << 8) / 10); spaceMeas(); printf("%d MB\r\n", mbFree); shutdownHandler(); wait_ms(40); led_saving = 1; /* Timers & Tickers init */ Battery_Ticker.attach(&battMeas, BATTERY_PERIOD); Space_Ticker.attach(&spaceMeas, SPACE_PERIOD); button_timer.start(); // Start timer that counts lengths of button presses btn_input.fall(&btnPressCallback); // Attach button press callback btn_input.rise(&btnReleaseCallback); // Attach button release callback wait_ms(40); readSwimmerID(); /* End of init */ appendLog("Booted"); // Append line to log file leds_off(); // Turn all LEDs off blink(); // Blink system led to notify user wdt.setKick(5); pc.printf("Ready...\r\n"); // Notify user of end init } // Functions -> Measuring ====================================================== /* Main measuring function */ void measure(void) { /* Vars */ char buffer[SIZE][BUFFER_SIZE]; // Buffer int pos = 0; // Position /* Read IMU values */ mpu.valRead(ACCEL, acc_x[relative], acc_y[relative], acc_z[relative]); // Read Accelerometer values mpu.valRead(GYRO, gyro_x[relative], gyro_y[relative],gyro_z[relative]); // Read Gyroscope values /* Increment counters */ absolute++; // Increment absolute counter relative++; // Increment relative counter /* After our buffers are full save the data */ if ( absolute % SIZE == 0 ) { /* Flip led_saving state */ led_saving = !led_saving; /* Handle file error */ if (gfp == NULL) { printf("Unable to append data to file %s\r\n", fname); // Notify user return; // Return } /* Iterate all buffer elements */ for (int k = 0; k < SIZE; k++) { pos = absolute-SIZE+k; // Increment position toBytes(buffer[k], &pos, sizeof(int)); // Append data to buffer in byte form toBytes(buffer[k]+sizeof(int), &acc_x[k], sizeof(short)); toBytes(buffer[k]+sizeof(int) + sizeof(short), &acc_y[k], sizeof(short)); toBytes(buffer[k]+sizeof(int) + sizeof(short)*2, &acc_z[k], sizeof(short)); toBytes(buffer[k]+sizeof(int) + sizeof(short)*3, &gyro_x[k], sizeof(short)); toBytes(buffer[k]+sizeof(int) + sizeof(short)*4, &gyro_y[k], sizeof(short)); toBytes(buffer[k]+sizeof(int) + sizeof(short)*5, &gyro_z[k], sizeof(short)); } /* Write */ #ifdef LOG_TEST_MODE measureNotify = 1; // Used for saving debug #endif fwrite(buffer, SIZE, BUFFER_SIZE, gfp); // Write 32 buffer lines (16 bytes) to file (512 bytes total -> one block) fflush(gfp); // Flush to make sure nothing is left in buffer #ifdef LOG_TEST_MODE measureNotify = 0; // Used for saving debug #endif /* Reset relative counter */ relative = 0; } } /* Sets the measuring flag */ void setMeasuringFlag(void) { #ifdef LOG_TEST_MODE flagSetNotify = 1; // Used for saving debug #endif measuringFlag = 1; // Set measuring flag #ifdef LOG_TEST_MODE flagSetNotify = 0; // Used for saving debug #endif } // Functions -> Commands ======================================================= /* Starts to acquire data from sensors */ void startSaving(void) { for(int i = 0; i < 8; i++) { timestamp[i] = wifi.readByte(); // Get bytes containing timestamp for the current record } wifi.sendAck(); savingFlag = 1; // Set saving flag /* Open global file with current swimmer ID */ gfp = fopen(fname, "wb"); // Try to open that file if(gfp == NULL) { leds_error(); // Turn on all leds printf("Unable to open file %s for writing\r\n", fname); // Notify user return; // Exit function } /* Prepare file & vars for data acquisition */ fprintf(gfp, "%c%c%c", -1, -1, swimmer_id); // Append header to current swimmer output file fflush(gfp); /* Reset counters */ absolute = 0; // Reset absolute counter relative = 0; // Reset relative counter /* Set timer */ Saving_Ticker.attach(&setMeasuringFlag, SAMPLE_PERIOD); // Attach function that periodically sets the flag } /* Stops acquiring data, and save data left in buffers to USB */ void stopSaving(void) { savingFlag = 0; // Clear saving flag /* Stop saving */ Saving_Ticker.detach(); // Stop setting measuring flag /* Try to append data left in buffers */ if(gfp == NULL) { leds_error(); // Turn on all leds printf("Unable to open file %s before sending data\r\n", fname); // Notify user return; // Exit function } /* Append data left to buffer */ int base = ((absolute - (absolute%SIZE)) < 0) ? 0 : absolute - (absolute%SIZE); char buffer[relative][BUFFER_SIZE]; // packet array /* Iterate all array elements */ for (int k = 0; k < relative; k++) { int pos = base+k; toBytes(buffer[k], &pos, sizeof(int)); toBytes(buffer[k]+sizeof(int), &acc_x[k], sizeof(short)); toBytes(buffer[k]+sizeof(int) + sizeof(short), &acc_y[k], sizeof(short)); toBytes(buffer[k]+sizeof(int) + sizeof(short)*2, &acc_z[k], sizeof(short)); toBytes(buffer[k]+sizeof(int) + sizeof(short)*3, &gyro_x[k], sizeof(short)); toBytes(buffer[k]+sizeof(int) + sizeof(short)*4, &gyro_y[k], sizeof(short)); toBytes(buffer[k]+sizeof(int) + sizeof(short)*5, &gyro_z[k], sizeof(short)); } /* Write what's left */ fwrite(buffer, relative, BUFFER_SIZE, gfp); // Write all data at once fflush(gfp); /* Append EOF and close file */ fprintf(gfp, "%c%c", -1,-1); // Write EOF characters fflush(gfp); fclose(gfp); // Close file /* Append this file to the records file */ appendRecord(); /* Prepare for next swimmer */ swimmer_id++; // Increment swimmer ID sprintf(fname, "/usb/swimmer%d.txt", swimmer_id); // Update current file name remove(fname); // If file with such ID exists remove it to avoid reading old data } /* Sends acquired data via Wi-Fi */ void transfer(void) { /* Vars */ char name[30]; // File name buffer /* File transfer prerequisites */ fclose(gfp); int requested_id = wifi.readByte(); // Get byte containing requested file ID sprintf(name, "/usb/swimmer%d.txt", requested_id); // Create file name based on current swimmer ID /* Handle transfer */ if(doesFileExist(name)) // At first check whether file exists (fopen used to freeze mbed) { /* Send ACK */ wifi.sendAck(); wait_ms(50); // Timeout is used to make sure C# gets ready (sockets are messy, flushing is pain) /* Actually try to send file */ printf("Sending %s\r\n", name); // Notify user which user is being sent if (wifi.sendFile(name)) // Send ! { leds_error(); // Handle error printf("Unable to send data (ID:%d)\r\n", requested_id); // Notify user via text also } else { printf("Swimmer %d finished\r\n", requested_id); // Otherwise all is AOK } } else { /* In case file doest not exist send NACK */ wifi.sendByte('#'); wifi.sendByte('F'); printf("Requested non-existing file...\r\n"); } } /* Sends log file*/ void sendLog(void) { /* Vars */ char name[30]; // File name buffer /* File transfer prerequisites */ sprintf(name, LOG_FILE); // Create file name from log name /* Handle transfer */ if(doesFileExist(name)) // At first check whether file exists (fopen used to freeze mbed) { /* Send ACK (should make this more abstract) */ wifi.sendAck(); wait_ms(50); // Timeout is used to make sure C# gets ready (sockets are messy, flushing is pain) /* Actually try to send file */ printf("Sending %s\r\n", name); // Notify user which user is being sent if (wifi.sendFile(name)) // Send ! { leds_error(); // Handle error printf("Unable to send log file\r\n"); // Notify user via text also } else { printf("Log file sent!\r\n"); // Otherwise all is AOK } } else { /* In case file doest not exist send NACK */ wifi.sendByte('#'); wifi.sendByte('F'); printf("Requested non-existing file...\r\n"); } } /* Sends records file*/ void sendRecords(void) { /* Handle transfer */ if(doesFileExist(RECORDS_FILE)) // At first check whether file exists (fopen used to freeze mbed) { wait_ms(50); // Timeout is used to make sure C# gets ready (sockets are messy, flushing is pain) /* Actually try to send file */ printf("Sending %s\r\n", RECORDS_FILE); // Notify user which user is being sent if (wifi.sendFile(RECORDS_FILE)) // Send ! { leds_error(); // Handle error printf("Unable to send records file\r\n"); // Notify user via text also } else { printf("Records file sent!\r\n"); // Otherwise all is AOK } } else { /* In case file doest not exist send NACK */ wifi.sendByte('#'); wifi.sendByte('F'); printf("Requested non-existing file...\r\n"); } } /* Halts board */ void halt(void) { if (1 == savingFlag) // If saving's in progress stop it, to make sure file system won't get corrupted { stopSaving(); } systemRequest = 0; blink(); btn_latch_n = 1; } /* Begins new scope (clears all data && rests swimmer_id counder) */ void beginScope(void) { /* Clear all files and reset swimmer_id only when not after reset */ if(swimmer_id != 0) // Redundancy check { appendLog("New scope"); clearRoot(); // Clears all files on root of USB flash disk swimmer_id = 0; // Resets simmer_id counter sprintf(fname, "/usb/swimmer%d.txt", swimmer_id); // Update current file name } } // Functions -> Generic functions ============================================== /* Sends status */ void sendStatus(void) { uint8_t checksum = SOH + savingFlag + battLevel + swimmer_id; // Calculate checksum wifi.sendByte(SOH); // Send start of heading wifi.sendByte(savingFlag); // Send state of saving wifi.sendByte(battLevel); // Sends current battery level wifi.sendByte(swimmer_id); // Sends current swimmer id index wifi.sendByte(checksum); // Send checksum } void blink(void) { if(led_system) { led_system = 0; } wait_ms(200); led_system = 1; wait_ms(200); led_system = 0; } // Main ======================================================================== int main() { /* Begin by initialization */ boardInit(); // Initialize board /* Set zeroth swimmer name */ sprintf(fname, "/usb/swimmer%d.txt", swimmer_id); // Prepare zeroth swimmer filename /* Main while */ while (1) { /* Shutdown handler */ shutdownHandler(); /* Read command from wifly */ char cmd = wifi.getCmd(); /* Master switch */ switch (cmd) { /* start measuring data periodically and save them info file */ case SAVING_START: { wifi.sendAck(); leds_off(); // Turn off all leds startSaving(); // Actually start saving printf("Saving swimmer %d...\r\n", swimmer_id); // Notify user led_measuring = 1; // Turn on led_measuring break; // Break from switch } /* stop saving data */ case SAVING_STOP: { wifi.sendAck(); leds_off(); // Turn off all leds stopSaving(); // Actually stop saving printf("Stopped...\r\n"); // Notify user break; // Break from switch } /* Send all data */ case TRANSFER_REQUEST: { wifi.sendAck(); leds_off(); // Turn off all leds led_sending = 1; // Turn on led_sending printf("Sending data...\r\n"); // Notify user that data is being sent transfer(); // Actually transfer data printf("Sending finished...\r\n"); // Notify user that data was sent successfully leds_off(); // Turn off all leds again break; // Break from switch } /* Begin new scope */ case SCOPE_BEGIN: { wifi.sendAck(); leds_off(); // Turn off all leds led_measuring = led_saving = 1; // Turn on two leds to depict special behaviour printf("Starting new scope...\r\n"); // Notify user that new scope is beginning beginScope(); // Begin scope ! (clear all data && reset swimmer_id counter) leds_off(); // Turn off all leds break; // Break } /* Send log file */ case SEND_LOG: { wifi.sendAck(); leds_off(); // Turn off all leds led_measuring = led_saving = 1; // Turn on two leds to depict special behaviour printf("Sending log...\r\n"); // Notify user that new scope is beginning sendLog(); // Send log file leds_off(); // Turn off all leds break; // Break } /* Send records file */ case SEND_RECORDS: { wifi.sendAck(); leds_off(); // Turn off all leds led_measuring = led_saving = 1; // Turn on two leds to depict special behaviour printf("Sending records...\r\n"); // Notify user that new scope is beginning sendRecords(); // Send records file leds_off(); // Turn off all leds break; // Break } /* Halt swimfly */ case HALT: { wifi.sendAck(); leds_off(); // Turn off all leds led_measuring = led_saving = 1; // Turn on two leds to depict special behaviour halt(); // Halt swimfly leds_off(); // Turn off all leds break; // Break } /* Ready */ case CHECK_READY: { wifi.sendAck(); leds_off(); // Turn off all leds sendStatus(); // Sends status message break; // Break } /* Nothing on serial */ case 'N': { /* Handle data measuring */ if(measuringFlag) // Wait for timer to set the flag again and again { measure(); // Measure ! measuringFlag = 0; // Reset flag } break; // Break from switch } /* Everything else is ballast */ default : { wifi.sendNack(); leds_error(); // Turn on all leds printf("Command %c is unknown!\r\n", cmd); // Notify user break; // Break from switch } } wdt.kick(); // Kick watchdog each iteration } }