20200716 read Status Register each second

Dependencies:   SDFileSystem mbed-os-example-ble-GattServer max32630fthr

Committer:
aureliocarella
Date:
Thu Jul 16 14:59:04 2020 +0000
Revision:
21:51e162c130a9
20200716

Who changed what in which revision?

UserRevisionLine numberNew contents of line
aureliocarella 21:51e162c130a9 1 /*******************************************************************************
aureliocarella 21:51e162c130a9 2 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
aureliocarella 21:51e162c130a9 3 *
aureliocarella 21:51e162c130a9 4 * Permission is hereby granted, free of charge, to any person obtaining a
aureliocarella 21:51e162c130a9 5 * copy of this software and associated documentation files (the "Software"),
aureliocarella 21:51e162c130a9 6 * to deal in the Software without restriction, including without limitation
aureliocarella 21:51e162c130a9 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
aureliocarella 21:51e162c130a9 8 * and/or sell copies of the Software, and to permit persons to whom the
aureliocarella 21:51e162c130a9 9 * Software is furnished to do so, subject to the following conditions:
aureliocarella 21:51e162c130a9 10 *
aureliocarella 21:51e162c130a9 11 * The above copyright notice and this permission notice shall be included
aureliocarella 21:51e162c130a9 12 * in all copies or substantial portions of the Software.
aureliocarella 21:51e162c130a9 13 *
aureliocarella 21:51e162c130a9 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
aureliocarella 21:51e162c130a9 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
aureliocarella 21:51e162c130a9 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
aureliocarella 21:51e162c130a9 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
aureliocarella 21:51e162c130a9 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
aureliocarella 21:51e162c130a9 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
aureliocarella 21:51e162c130a9 20 * OTHER DEALINGS IN THE SOFTWARE.
aureliocarella 21:51e162c130a9 21 *
aureliocarella 21:51e162c130a9 22 * Except as contained in this notice, the name of Maxim Integrated
aureliocarella 21:51e162c130a9 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
aureliocarella 21:51e162c130a9 24 * Products, Inc. Branding Policy.
aureliocarella 21:51e162c130a9 25 *
aureliocarella 21:51e162c130a9 26 * The mere transfer of this software does not imply any licenses
aureliocarella 21:51e162c130a9 27 * of trade secrets, proprietary technology, copyrights, patents,
aureliocarella 21:51e162c130a9 28 * trademarks, maskwork rights, or any other form of intellectual
aureliocarella 21:51e162c130a9 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
aureliocarella 21:51e162c130a9 30 * ownership rights.
aureliocarella 21:51e162c130a9 31 *******************************************************************************
aureliocarella 21:51e162c130a9 32 */
aureliocarella 21:51e162c130a9 33 #include "mbed.h"
aureliocarella 21:51e162c130a9 34 #include "Logging.h"
aureliocarella 21:51e162c130a9 35 #include "Streaming.h"
aureliocarella 21:51e162c130a9 36 #include "RpcServer.h"
aureliocarella 21:51e162c130a9 37 #include "S25FS512.h"
aureliocarella 21:51e162c130a9 38 #include "PacketFifo.h"
aureliocarella 21:51e162c130a9 39 #include "DataLoggingService.h"
aureliocarella 21:51e162c130a9 40 #include "HspLed.h"
aureliocarella 21:51e162c130a9 41 #include "MAX30001_helper.h"
aureliocarella 21:51e162c130a9 42 #include "StringInOut.h"
aureliocarella 21:51e162c130a9 43 #include "StringHelper.h"
aureliocarella 21:51e162c130a9 44 #include "Peripherals.h"
aureliocarella 21:51e162c130a9 45 #include "Device_Logging.h"
aureliocarella 21:51e162c130a9 46
aureliocarella 21:51e162c130a9 47 /// BMP280 logging object reference
aureliocarella 21:51e162c130a9 48 extern Device_Logging *bmp280_Logging;
aureliocarella 21:51e162c130a9 49 /// MAX14720 instance 0 logging object reference
aureliocarella 21:51e162c130a9 50 extern Device_Logging *MAX30205_0_Logging;
aureliocarella 21:51e162c130a9 51 /// MAX14720 instance 1 logging object reference
aureliocarella 21:51e162c130a9 52 extern Device_Logging *MAX30205_1_Logging;
aureliocarella 21:51e162c130a9 53
aureliocarella 21:51e162c130a9 54 #define PING_PONG_BUFFER_SIZE 512
aureliocarella 21:51e162c130a9 55 #define HALF_OF_PING_PONG_BUFFER_SIZE PING_PONG_BUFFER_SIZE / 2
aureliocarella 21:51e162c130a9 56 #define MISSION_DEFINITION_SIZE 4096
aureliocarella 21:51e162c130a9 57 #define MISSION_FILE_NAME_LEN 32
aureliocarella 21:51e162c130a9 58
aureliocarella 21:51e162c130a9 59 eLoggingTrigger loggingTrigger;
aureliocarella 21:51e162c130a9 60
aureliocarella 21:51e162c130a9 61 /// file on SDCard where mission strings are stored
aureliocarella 21:51e162c130a9 62 char missionFileName[MISSION_FILE_NAME_LEN] = "/sd/missions.txt";
aureliocarella 21:51e162c130a9 63
aureliocarella 21:51e162c130a9 64 /// data file on SDCard where mission strings are stored
aureliocarella 21:51e162c130a9 65 char dataFileName[MISSION_FILE_NAME_LEN] = "/sd/data.txt";
aureliocarella 21:51e162c130a9 66
aureliocarella 21:51e162c130a9 67 /// buffer where mission strings are stored
aureliocarella 21:51e162c130a9 68 char loggingMissionCmds[MISSION_DEFINITION_SIZE];
aureliocarella 21:51e162c130a9 69 /// This houses two 256 byte ram concatenated to act as a ping-pong
aureliocarella 21:51e162c130a9 70 uint8_t PingPong_SRAM[PING_PONG_BUFFER_SIZE];
aureliocarella 21:51e162c130a9 71 uint32_t buttonTrigger = 0;
aureliocarella 21:51e162c130a9 72
aureliocarella 21:51e162c130a9 73 eLoggingOutput loggingOutput;
aureliocarella 21:51e162c130a9 74 // extern int bleStartCommand;
aureliocarella 21:51e162c130a9 75 bool volatile globalFlag;
aureliocarella 21:51e162c130a9 76 extern int highDataRate;
aureliocarella 21:51e162c130a9 77 static uint32_t currentPage;
aureliocarella 21:51e162c130a9 78 static uint32_t sramIndex;
aureliocarella 21:51e162c130a9 79 /// flag to indicate that sram buffer 0 is dirty and will need to be flushed
aureliocarella 21:51e162c130a9 80 static uint32_t sram_buffer_0_dirty;
aureliocarella 21:51e162c130a9 81 /// flag to indicate that sram buffer 1 is dirty and will need to be flushed
aureliocarella 21:51e162c130a9 82 static uint32_t sram_buffer_1_dirty;
aureliocarella 21:51e162c130a9 83 /// usb byte buffer for sending out a bulk transfer
aureliocarella 21:51e162c130a9 84 static uint8_t usb_block[64];
aureliocarella 21:51e162c130a9 85 /// running index used to accumulate bytes to send as a block via bulk transfer
aureliocarella 21:51e162c130a9 86 static uint16_t usb_block_index = 0;
aureliocarella 21:51e162c130a9 87
aureliocarella 21:51e162c130a9 88 typedef enum {
aureliocarella 21:51e162c130a9 89 eStartEvent_NULL,
aureliocarella 21:51e162c130a9 90 eStartEvent_BLE,
aureliocarella 21:51e162c130a9 91 eStartEvent_BUTTON,
aureliocarella 21:51e162c130a9 92 eStartEvent_RPC_TO_USB,
aureliocarella 21:51e162c130a9 93 eStartEvent_RPC_TO_FLASH
aureliocarella 21:51e162c130a9 94 } eStartEvent;
aureliocarella 21:51e162c130a9 95 static eStartEvent startEvent;
aureliocarella 21:51e162c130a9 96
aureliocarella 21:51e162c130a9 97 /**
aureliocarella 21:51e162c130a9 98 * @brief Sets a flag to start USB logging (streaming)
aureliocarella 21:51e162c130a9 99 */
aureliocarella 21:51e162c130a9 100 void LoggingService_StartLoggingUsb(void) {
aureliocarella 21:51e162c130a9 101 loggingTrigger = eTriggerLog_RPC_USB;
aureliocarella 21:51e162c130a9 102 }
aureliocarella 21:51e162c130a9 103
aureliocarella 21:51e162c130a9 104 /**
aureliocarella 21:51e162c130a9 105 * @brief Sets a flag to start flash logging
aureliocarella 21:51e162c130a9 106 */
aureliocarella 21:51e162c130a9 107 void LoggingService_StartLoggingFlash(void) {
aureliocarella 21:51e162c130a9 108 loggingTrigger = eTriggerLog_RPC_FLASH;
aureliocarella 21:51e162c130a9 109 }
aureliocarella 21:51e162c130a9 110
aureliocarella 21:51e162c130a9 111 /**
aureliocarella 21:51e162c130a9 112 * @brief Checks the various logging start condition
aureliocarella 21:51e162c130a9 113 * @return 1 if a start condition is true, 0 if there is no start condition
aureliocarella 21:51e162c130a9 114 */
aureliocarella 21:51e162c130a9 115 static bool _LoggingService_CheckStartCondition(void) {
aureliocarella 21:51e162c130a9 116 bool buttonPressed;
aureliocarella 21:51e162c130a9 117 buttonPressed = Peripherals::pushButton()->GetButtonFallState();
aureliocarella 21:51e162c130a9 118
aureliocarella 21:51e162c130a9 119 // default not logging USB or flash
aureliocarella 21:51e162c130a9 120 loggingOutput = eLogToNothing;
aureliocarella 21:51e162c130a9 121 startEvent = eStartEvent_NULL;
aureliocarella 21:51e162c130a9 122 if (buttonPressed) {
aureliocarella 21:51e162c130a9 123 Peripherals::pushButton()->clearButtonFallState();
aureliocarella 21:51e162c130a9 124 // a falling state has been detected... wait for a fraction of a second and
aureliocarella 21:51e162c130a9 125 // re-read the pin
aureliocarella 21:51e162c130a9 126 // only start datalogging if the pin was released within this wait time
aureliocarella 21:51e162c130a9 127 wait(0.75f);
aureliocarella 21:51e162c130a9 128 int buttonRead = Peripherals::pushButton()->Read();
aureliocarella 21:51e162c130a9 129 // if after a period of time the button is still pressed then get out
aureliocarella 21:51e162c130a9 130 if (buttonRead == 0)
aureliocarella 21:51e162c130a9 131 return 0;
aureliocarella 21:51e162c130a9 132 buttonTrigger = 0;
aureliocarella 21:51e162c130a9 133
aureliocarella 21:51e162c130a9 134 loggingTrigger = eTriggerLog_BUTTON;
aureliocarella 21:51e162c130a9 135 loggingOutput = eLogToFlash;
aureliocarella 21:51e162c130a9 136 startEvent = eStartEvent_BUTTON;
aureliocarella 21:51e162c130a9 137 return true;
aureliocarella 21:51e162c130a9 138 }
aureliocarella 21:51e162c130a9 139 if (loggingTrigger == eTriggerLog_RPC_FLASH) {
aureliocarella 21:51e162c130a9 140 loggingOutput = eLogToFlash;
aureliocarella 21:51e162c130a9 141 startEvent = eStartEvent_RPC_TO_FLASH;
aureliocarella 21:51e162c130a9 142 return true;
aureliocarella 21:51e162c130a9 143 }
aureliocarella 21:51e162c130a9 144 /*if (Peripherals::hspBLE()->getStartDataLogging()) {
aureliocarella 21:51e162c130a9 145 loggingTrigger = eTriggerLog_BLE;
aureliocarella 21:51e162c130a9 146 loggingOutput = eLogToFlash;
aureliocarella 21:51e162c130a9 147 startEvent = eStartEvent_BLE;
aureliocarella 21:51e162c130a9 148 return true;
aureliocarella 21:51e162c130a9 149 }*/
aureliocarella 21:51e162c130a9 150 // check if start is from RPC call for USB streaming
aureliocarella 21:51e162c130a9 151 if (loggingTrigger == eTriggerLog_RPC_USB) {
aureliocarella 21:51e162c130a9 152 loggingOutput = eLogtoUsb;
aureliocarella 21:51e162c130a9 153 startEvent = eStartEvent_RPC_TO_USB;
aureliocarella 21:51e162c130a9 154 return true;
aureliocarella 21:51e162c130a9 155 }
aureliocarella 21:51e162c130a9 156 return false;
aureliocarella 21:51e162c130a9 157 }
aureliocarella 21:51e162c130a9 158
aureliocarella 21:51e162c130a9 159 /**
aureliocarella 21:51e162c130a9 160 * @brief Read the mission string from flash into a buffer
aureliocarella 21:51e162c130a9 161 * @return false if a mission was not defined, true if mission was read and
aureliocarella 21:51e162c130a9 162 * buffered
aureliocarella 21:51e162c130a9 163 */
aureliocarella 21:51e162c130a9 164 static bool _LoggingService_ReadMissionFromFlash(void) {
aureliocarella 21:51e162c130a9 165 // get mission from flash
aureliocarella 21:51e162c130a9 166 Logging_ReadMissionFromFlash((uint8_t *)loggingMissionCmds);
aureliocarella 21:51e162c130a9 167 if (Logging_IsMissionDefined((uint8_t *)loggingMissionCmds) == 0) {
aureliocarella 21:51e162c130a9 168 return false;
aureliocarella 21:51e162c130a9 169 }
aureliocarella 21:51e162c130a9 170 printf(loggingMissionCmds);
aureliocarella 21:51e162c130a9 171 fflush(stdout);
aureliocarella 21:51e162c130a9 172 RPC_ProcessCmds(loggingMissionCmds);
aureliocarella 21:51e162c130a9 173 return true;
aureliocarella 21:51e162c130a9 174 }
aureliocarella 21:51e162c130a9 175
aureliocarella 21:51e162c130a9 176 /**
aureliocarella 21:51e162c130a9 177 * @brief Read the mission string from SDCARD into a buffer
aureliocarella 21:51e162c130a9 178 * @return false if a mission was not defined, true if mission was read and
aureliocarella 21:51e162c130a9 179 * buffered
aureliocarella 21:51e162c130a9 180 */
aureliocarella 21:51e162c130a9 181 static bool _LoggingService_ReadMissionFromSDCard(void) {
aureliocarella 21:51e162c130a9 182 // get mission from flash
aureliocarella 21:51e162c130a9 183 Logging_ReadMissionFromSDCard((uint8_t *)loggingMissionCmds);
aureliocarella 21:51e162c130a9 184 if (Logging_IsMissionDefined((uint8_t *)loggingMissionCmds) == 0) {
aureliocarella 21:51e162c130a9 185 return false;
aureliocarella 21:51e162c130a9 186 }
aureliocarella 21:51e162c130a9 187 printf(loggingMissionCmds);
aureliocarella 21:51e162c130a9 188 fflush(stdout);
aureliocarella 21:51e162c130a9 189 RPC_ProcessCmds(loggingMissionCmds);
aureliocarella 21:51e162c130a9 190 return true;
aureliocarella 21:51e162c130a9 191 }
aureliocarella 21:51e162c130a9 192
aureliocarella 21:51e162c130a9 193 /**
aureliocarella 21:51e162c130a9 194 * @brief Process a RPC command that is pointed to.
aureliocarella 21:51e162c130a9 195 * @param cmd RPC string to process
aureliocarella 21:51e162c130a9 196 */
aureliocarella 21:51e162c130a9 197 void ProcessCmd(char *cmd) {
aureliocarella 21:51e162c130a9 198 char cmd_[256];
aureliocarella 21:51e162c130a9 199 char reply[512];
aureliocarella 21:51e162c130a9 200 strcpy(cmd_, cmd);
aureliocarella 21:51e162c130a9 201 RPC_call(cmd_, reply);
aureliocarella 21:51e162c130a9 202 }
aureliocarella 21:51e162c130a9 203
aureliocarella 21:51e162c130a9 204 /**
aureliocarella 21:51e162c130a9 205 * @brief Buffer sensor fifo data in ram buffers, when a ram buffer is full (a
aureliocarella 21:51e162c130a9 206 * flash page worth of data is accumulated) then flash that buffer.
aureliocarella 21:51e162c130a9 207 * A buffer ping pong method is used so that one buffer can be flashing as
aureliocarella 21:51e162c130a9 208 * the other buffer fills with sensor fifo data.
aureliocarella 21:51e162c130a9 209 * @param fifoData Sensor data taken from the fifo to be stored into flash
aureliocarella 21:51e162c130a9 210 */
aureliocarella 21:51e162c130a9 211 static void _LoggingServer_OutputToFlash(uint32_t fifoData) {
aureliocarella 21:51e162c130a9 212 uint32_t index;
aureliocarella 21:51e162c130a9 213 char str[128];
aureliocarella 21:51e162c130a9 214 uint8_t *ptr;
aureliocarella 21:51e162c130a9 215 //
aureliocarella 21:51e162c130a9 216 // Log To Flash
aureliocarella 21:51e162c130a9 217 //
aureliocarella 21:51e162c130a9 218 // i.e. there is data, read one 32-bit size data at a time.
aureliocarella 21:51e162c130a9 219 // put the fifo data into the ping-pong SRAM
aureliocarella 21:51e162c130a9 220 PingPong_SRAM[sramIndex++] = fifoData & 0xFF; // LSByte goes into index N
aureliocarella 21:51e162c130a9 221 PingPong_SRAM[sramIndex++] = (fifoData >> 8) & 0xFF;
aureliocarella 21:51e162c130a9 222 PingPong_SRAM[sramIndex++] = (fifoData >> 16) & 0xFF;
aureliocarella 21:51e162c130a9 223 PingPong_SRAM[sramIndex++] = (fifoData >> 24) & 0xFF; // MSByte goes into index N+3
aureliocarella 21:51e162c130a9 224
aureliocarella 21:51e162c130a9 225 // flag this buffer as dirty
aureliocarella 21:51e162c130a9 226 if (sramIndex <= 256)
aureliocarella 21:51e162c130a9 227 sram_buffer_0_dirty = 1;
aureliocarella 21:51e162c130a9 228 else
aureliocarella 21:51e162c130a9 229 sram_buffer_1_dirty = 1;
aureliocarella 21:51e162c130a9 230
aureliocarella 21:51e162c130a9 231 if (sramIndex == 256 ||
aureliocarella 21:51e162c130a9 232 sramIndex == 512) // Either Ping SRAM or Pong SRAM location is full
aureliocarella 21:51e162c130a9 233 { // therefore write to Flash
aureliocarella 21:51e162c130a9 234
aureliocarella 21:51e162c130a9 235 index = sramIndex - 256;
aureliocarella 21:51e162c130a9 236 ptr = &PingPong_SRAM[index];
aureliocarella 21:51e162c130a9 237 sprintf(str, "currentPage=%d", currentPage);
aureliocarella 21:51e162c130a9 238 Peripherals::s25FS512()->writePage_Helper(currentPage, ptr, 0);
aureliocarella 21:51e162c130a9 239
aureliocarella 21:51e162c130a9 240 // this page is no longer dirty
aureliocarella 21:51e162c130a9 241 if (index == 0)
aureliocarella 21:51e162c130a9 242 sram_buffer_0_dirty = 0;
aureliocarella 21:51e162c130a9 243 if (index == 256)
aureliocarella 21:51e162c130a9 244 sram_buffer_1_dirty = 0;
aureliocarella 21:51e162c130a9 245
aureliocarella 21:51e162c130a9 246 currentPage++;
aureliocarella 21:51e162c130a9 247 }
aureliocarella 21:51e162c130a9 248 sramIndex = sramIndex % 512; // Wrap around the index
aureliocarella 21:51e162c130a9 249 }
aureliocarella 21:51e162c130a9 250
aureliocarella 21:51e162c130a9 251 /**
aureliocarella 21:51e162c130a9 252 * @brief Buffer sensor fifo data in ram buffers, when a ram buffer is full (a
aureliocarella 21:51e162c130a9 253 * flash page worth of data is accumulated) then flash that buffer.
aureliocarella 21:51e162c130a9 254 * A buffer ping pong method is used so that one buffer can be flashing as
aureliocarella 21:51e162c130a9 255 * the other buffer fills with sensor fifo data.
aureliocarella 21:51e162c130a9 256 * @param fifoData Sensor data taken from the fifo to be stored into flash
aureliocarella 21:51e162c130a9 257 */
aureliocarella 21:51e162c130a9 258 static void _LoggingServer_OutputToSDCard(FILE* fp, uint32_t fifoData) {
aureliocarella 21:51e162c130a9 259 if (fp != NULL){
aureliocarella 21:51e162c130a9 260 fwrite(&fifoData,sizeof(fifoData),1,fp);
aureliocarella 21:51e162c130a9 261 }
aureliocarella 21:51e162c130a9 262 }
aureliocarella 21:51e162c130a9 263
aureliocarella 21:51e162c130a9 264 /**
aureliocarella 21:51e162c130a9 265 * @brief If flash ram buffers are flagged as dirty, flush to flash
aureliocarella 21:51e162c130a9 266 */
aureliocarella 21:51e162c130a9 267 static void _LoggingServer_WriteDirtySramBufferToFlash(void) {
aureliocarella 21:51e162c130a9 268 uint8_t *ptr = PingPong_SRAM;
aureliocarella 21:51e162c130a9 269 if (sram_buffer_0_dirty == 0 && sram_buffer_1_dirty == 0)
aureliocarella 21:51e162c130a9 270 return;
aureliocarella 21:51e162c130a9 271 if (sram_buffer_0_dirty == 1) {
aureliocarella 21:51e162c130a9 272 ptr += 0;
aureliocarella 21:51e162c130a9 273 }
aureliocarella 21:51e162c130a9 274 if (sram_buffer_1_dirty == 1) {
aureliocarella 21:51e162c130a9 275 ptr += 256;
aureliocarella 21:51e162c130a9 276 }
aureliocarella 21:51e162c130a9 277 printf("_LoggingServer_WriteDirtySramBufferToFlash:%d,%d\n",
aureliocarella 21:51e162c130a9 278 sram_buffer_0_dirty, sram_buffer_1_dirty);
aureliocarella 21:51e162c130a9 279 fflush(stdout);
aureliocarella 21:51e162c130a9 280 // s25fs512_WritePage_Helper(currentPage, ptr, 0);
aureliocarella 21:51e162c130a9 281 Peripherals::s25FS512()->writePage_Helper(currentPage, ptr, 0);
aureliocarella 21:51e162c130a9 282 }
aureliocarella 21:51e162c130a9 283
aureliocarella 21:51e162c130a9 284 /**
aureliocarella 21:51e162c130a9 285 * @brief Initialize the USB block running index
aureliocarella 21:51e162c130a9 286 * @param fifoData Sensor data taken from the fifo to be sent out USB
aureliocarella 21:51e162c130a9 287 */
aureliocarella 21:51e162c130a9 288 static void _LoggingServer_OutputToCdcAcm(uint32_t fifoData) {
aureliocarella 21:51e162c130a9 289 uint8_t *ptr;
aureliocarella 21:51e162c130a9 290 uint8_t str[16];
aureliocarella 21:51e162c130a9 291 sprintf((char *)str, "%X ", fifoData);
aureliocarella 21:51e162c130a9 292 ptr = str;
aureliocarella 21:51e162c130a9 293 usb_block_index = 0;
aureliocarella 21:51e162c130a9 294 while (*ptr != 0) {
aureliocarella 21:51e162c130a9 295 usb_block[usb_block_index] = *ptr;
aureliocarella 21:51e162c130a9 296 ptr++;
aureliocarella 21:51e162c130a9 297 usb_block_index++;
aureliocarella 21:51e162c130a9 298 }
aureliocarella 21:51e162c130a9 299 //Peripherals::usbSerial()->writeBlock(usb_block, usb_block_index);
aureliocarella 21:51e162c130a9 300 }
aureliocarella 21:51e162c130a9 301
aureliocarella 21:51e162c130a9 302 /**
aureliocarella 21:51e162c130a9 303 * @brief Initialize the USB block running index
aureliocarella 21:51e162c130a9 304 */
aureliocarella 21:51e162c130a9 305 static void _LoggingServer_OutputToCdcAcm_Start(void) { usb_block_index = 0; }
aureliocarella 21:51e162c130a9 306
aureliocarella 21:51e162c130a9 307 /**
aureliocarella 21:51e162c130a9 308 * @brief Buffer up fifoData from sensors, do a USB block transfer if buffer is
aureliocarella 21:51e162c130a9 309 * full
aureliocarella 21:51e162c130a9 310 * @param fifoData Sensor data taken from the fifo to be send out USB within a
aureliocarella 21:51e162c130a9 311 * bulk block transfer
aureliocarella 21:51e162c130a9 312 * @return Return the success status of the writeblock operation
aureliocarella 21:51e162c130a9 313 */
aureliocarella 21:51e162c130a9 314 static bool _LoggingServer_OutputToCdcAcm_Block(uint32_t fifoData) {
aureliocarella 21:51e162c130a9 315 uint8_t str[64];
aureliocarella 21:51e162c130a9 316 uint8_t *ptr;
aureliocarella 21:51e162c130a9 317 bool result;
aureliocarella 21:51e162c130a9 318 //
aureliocarella 21:51e162c130a9 319 // Log to CDCACM
aureliocarella 21:51e162c130a9 320 //
aureliocarella 21:51e162c130a9 321 result = true;
aureliocarella 21:51e162c130a9 322 sprintf((char *)str, "%X ", fifoData);
aureliocarella 21:51e162c130a9 323 ptr = str;
aureliocarella 21:51e162c130a9 324 while (*ptr != 0) {
aureliocarella 21:51e162c130a9 325 usb_block[usb_block_index] = *ptr;
aureliocarella 21:51e162c130a9 326 ptr++;
aureliocarella 21:51e162c130a9 327 usb_block_index++;
aureliocarella 21:51e162c130a9 328 if (usb_block_index >= 64) {
aureliocarella 21:51e162c130a9 329 //result = Peripherals::usbSerial()->writeBlock(usb_block, 64);
aureliocarella 21:51e162c130a9 330 usb_block_index = 0;
aureliocarella 21:51e162c130a9 331 }
aureliocarella 21:51e162c130a9 332 }
aureliocarella 21:51e162c130a9 333 return result;
aureliocarella 21:51e162c130a9 334 }
aureliocarella 21:51e162c130a9 335
aureliocarella 21:51e162c130a9 336 /**
aureliocarella 21:51e162c130a9 337 * @brief Output a full USB block via bulk transfer
aureliocarella 21:51e162c130a9 338 */
aureliocarella 21:51e162c130a9 339 static void _LoggingServer_OutputToCdcAcm_End(void) {
aureliocarella 21:51e162c130a9 340 if (usb_block_index == 0)
aureliocarella 21:51e162c130a9 341 return;
aureliocarella 21:51e162c130a9 342 //Peripherals::usbSerial()->writeBlock(usb_block, usb_block_index - 1);
aureliocarella 21:51e162c130a9 343 }
aureliocarella 21:51e162c130a9 344
aureliocarella 21:51e162c130a9 345 /**
aureliocarella 21:51e162c130a9 346 * @brief Blink LED pattern that indicates that the flash end boundary has been
aureliocarella 21:51e162c130a9 347 * reached
aureliocarella 21:51e162c130a9 348 */
aureliocarella 21:51e162c130a9 349 static void BlinkEndOfDatalogging(void) {
aureliocarella 21:51e162c130a9 350 // blink to signal end of logging
aureliocarella 21:51e162c130a9 351 Peripherals::hspLed()->pattern(0x55555555, 20);
aureliocarella 21:51e162c130a9 352 wait(2);
aureliocarella 21:51e162c130a9 353 }
aureliocarella 21:51e162c130a9 354
aureliocarella 21:51e162c130a9 355 /**
aureliocarella 21:51e162c130a9 356 * @brief Reads the first data page of flash, if all FF's then the page is empty
aureliocarella 21:51e162c130a9 357 * @return 1 if the flash is empty as indicated by the first data page of the
aureliocarella 21:51e162c130a9 358 * flash, 0 if not
aureliocarella 21:51e162c130a9 359 */
aureliocarella 21:51e162c130a9 360 int isFlashEmpty(void) {
aureliocarella 21:51e162c130a9 361 int i;
aureliocarella 21:51e162c130a9 362 uint8_t data[256];
aureliocarella 21:51e162c130a9 363 int firstDataPage = Logging_GetLoggingStartPage();
aureliocarella 21:51e162c130a9 364 Peripherals::s25FS512()->readPages_Helper(firstDataPage, firstDataPage, data, 0);
aureliocarella 21:51e162c130a9 365 for (i = 0; i < 256; i++) {
aureliocarella 21:51e162c130a9 366 if (data[i] != 0xFF)
aureliocarella 21:51e162c130a9 367 return 0;
aureliocarella 21:51e162c130a9 368 }
aureliocarella 21:51e162c130a9 369 return 1;
aureliocarella 21:51e162c130a9 370 }
aureliocarella 21:51e162c130a9 371
aureliocarella 21:51e162c130a9 372 /**
aureliocarella 21:51e162c130a9 373 * @brief Reads the first data from SDCard, if all FF's then the page is empty
aureliocarella 21:51e162c130a9 374 * @return 1 if the flash is empty as indicated by the first data page of the
aureliocarella 21:51e162c130a9 375 * flash, 0 if not
aureliocarella 21:51e162c130a9 376 */
aureliocarella 21:51e162c130a9 377 int isSDCardWithoutDataLog(void) {
aureliocarella 21:51e162c130a9 378 FILE *fp = NULL;
aureliocarella 21:51e162c130a9 379 fp = fopen(dataFileName, "rb");
aureliocarella 21:51e162c130a9 380 if (fp != NULL) {
aureliocarella 21:51e162c130a9 381 uint8_t count = 0;
aureliocarella 21:51e162c130a9 382 do
aureliocarella 21:51e162c130a9 383 {
aureliocarella 21:51e162c130a9 384 count ++;
aureliocarella 21:51e162c130a9 385 char c = (char)fgetc(fp);
aureliocarella 21:51e162c130a9 386 if (count > 2)
aureliocarella 21:51e162c130a9 387 {
aureliocarella 21:51e162c130a9 388 fclose(fp);
aureliocarella 21:51e162c130a9 389 return 0;
aureliocarella 21:51e162c130a9 390 }
aureliocarella 21:51e162c130a9 391 } while(!feof(fp));
aureliocarella 21:51e162c130a9 392 fclose(fp);
aureliocarella 21:51e162c130a9 393 }
aureliocarella 21:51e162c130a9 394 return 1;
aureliocarella 21:51e162c130a9 395
aureliocarella 21:51e162c130a9 396 }
aureliocarella 21:51e162c130a9 397
aureliocarella 21:51e162c130a9 398 /**
aureliocarella 21:51e162c130a9 399 * @brief Blink LED pattern that indicates that the flash is not empty and a new
aureliocarella 21:51e162c130a9 400 * flash logging session can not occur
aureliocarella 21:51e162c130a9 401 */
aureliocarella 21:51e162c130a9 402 void BlinkFlashNotEmpty(void) {
aureliocarella 21:51e162c130a9 403 Peripherals::hspLed()->pattern(0x55555555, 20);
aureliocarella 21:51e162c130a9 404 wait(1);
aureliocarella 21:51e162c130a9 405 }
aureliocarella 21:51e162c130a9 406
aureliocarella 21:51e162c130a9 407 void ExecuteDefaultMission(void) {
aureliocarella 21:51e162c130a9 408 ProcessCmd("/MAX30001/CAL_InitStart 01 01 01 03 7FF 00");
aureliocarella 21:51e162c130a9 409 ProcessCmd("/MAX30001/ECG_InitStart 01 01 01 00 02 03 1F 0 00 00 01");
aureliocarella 21:51e162c130a9 410 ProcessCmd("/MAX30001/RtoR_InitStart 01 03 0F 00 03 01 00 00 01");
aureliocarella 21:51e162c130a9 411 ProcessCmd("/MAX30001/Rbias_FMSTR_Init 01 02 01 01 00");
aureliocarella 21:51e162c130a9 412 }
aureliocarella 21:51e162c130a9 413
aureliocarella 21:51e162c130a9 414 void LoggingService_Init(void) { loggingTrigger = eTriggerLog_NULL; }
aureliocarella 21:51e162c130a9 415
aureliocarella 21:51e162c130a9 416 /**
aureliocarella 21:51e162c130a9 417 * @brief This routine checks to see if a USB or flash logging action needs to be taken
aureliocarella 21:51e162c130a9 418 * The routine checks for a start condition via button press, USB command, or BLE command
aureliocarella 21:51e162c130a9 419 * Once one of these start conditions is present, the logging begins until stopped or memory is full
aureliocarella 21:51e162c130a9 420 * @return 1 if successful, 0 if error or logging was aborted and no logging occurred
aureliocarella 21:51e162c130a9 421 */
aureliocarella 21:51e162c130a9 422 uint8_t LoggingService_ServiceRoutine(void) {
aureliocarella 21:51e162c130a9 423 uint32_t fifoData;
aureliocarella 21:51e162c130a9 424 uint32_t endPage;
aureliocarella 21:51e162c130a9 425 FILE *fp;
aureliocarella 21:51e162c130a9 426 // USBSerial *usbSerial = Peripherals::usbSerial();
aureliocarella 21:51e162c130a9 427 // BMP280 *bmp280 = Peripherals::bmp280();
aureliocarella 21:51e162c130a9 428 bool buttonPressed;
aureliocarella 21:51e162c130a9 429 bool endSDLogging = false;
aureliocarella 21:51e162c130a9 430 int packetBurstCount = 0;
aureliocarella 21:51e162c130a9 431 HspLed *hspLed = Peripherals::hspLed();
aureliocarella 21:51e162c130a9 432
aureliocarella 21:51e162c130a9 433 sramIndex = 0;
aureliocarella 21:51e162c130a9 434 // only start logging if conditions exist
aureliocarella 21:51e162c130a9 435
aureliocarella 21:51e162c130a9 436 if (_LoggingService_CheckStartCondition() == false) return 0;
aureliocarella 21:51e162c130a9 437 printf("Begin Logging...");
aureliocarella 21:51e162c130a9 438 if (startEvent == eStartEvent_NULL) printf("eStartEvent_NULL...");
aureliocarella 21:51e162c130a9 439 if (startEvent == eStartEvent_BLE) printf("eStartEvent_BLE...");
aureliocarella 21:51e162c130a9 440 if (startEvent == eStartEvent_BUTTON) printf("eStartEvent_BUTTON...");
aureliocarella 21:51e162c130a9 441 if (startEvent == eStartEvent_RPC_TO_USB) printf("eStartEvent_RPC_TO_USB...");
aureliocarella 21:51e162c130a9 442 if (startEvent == eStartEvent_RPC_TO_FLASH) printf("eStartEvent_RPC_TO_FLASH...");
aureliocarella 21:51e162c130a9 443 fflush(stdout);
aureliocarella 21:51e162c130a9 444
aureliocarella 21:51e162c130a9 445 // start logging stuttered blink pattern
aureliocarella 21:51e162c130a9 446 hspLed->pattern(0xA0F3813, 20);
aureliocarella 21:51e162c130a9 447
aureliocarella 21:51e162c130a9 448 if (startEvent == eStartEvent_RPC_TO_FLASH ||
aureliocarella 21:51e162c130a9 449 startEvent == eStartEvent_BUTTON) {
aureliocarella 21:51e162c130a9 450 // check to see if datalog already in flash... abort and force user to erase
aureliocarella 21:51e162c130a9 451 // flash if needed
aureliocarella 21:51e162c130a9 452 if (loggingOutput == eLogToFlash) {
aureliocarella 21:51e162c130a9 453 if (isSDCardWithoutDataLog() == 0) {
aureliocarella 21:51e162c130a9 454 Logging_SetStart(false);
aureliocarella 21:51e162c130a9 455 // bleStartCommand = 0x00;
aureliocarella 21:51e162c130a9 456 BlinkFlashNotEmpty();
aureliocarella 21:51e162c130a9 457 hspLed->blink(1000);
aureliocarella 21:51e162c130a9 458 printf("Abort Logging, flash log exists. ");
aureliocarella 21:51e162c130a9 459 fflush(stdout);
aureliocarella 21:51e162c130a9 460 return 0;
aureliocarella 21:51e162c130a9 461 }
aureliocarella 21:51e162c130a9 462 }
aureliocarella 21:51e162c130a9 463 }
aureliocarella 21:51e162c130a9 464
aureliocarella 21:51e162c130a9 465 if (startEvent == eStartEvent_BLE) {
aureliocarella 21:51e162c130a9 466 // check for mission in flash
aureliocarella 21:51e162c130a9 467 if (_LoggingService_ReadMissionFromSDCard() == false) {
aureliocarella 21:51e162c130a9 468 // if there is no mission in flash then do a default mission for the sake
aureliocarella 21:51e162c130a9 469 // of ble Android app working "out-of-the-box" and stream RtoR and Accel
aureliocarella 21:51e162c130a9 470 printf("No Mission in Flash...ExecuteDefaultMission...");
aureliocarella 21:51e162c130a9 471 fflush(stdout);
aureliocarella 21:51e162c130a9 472 ExecuteDefaultMission();
aureliocarella 21:51e162c130a9 473 // do not log this data
aureliocarella 21:51e162c130a9 474 loggingOutput = eLogToNothing;
aureliocarella 21:51e162c130a9 475 } else {
aureliocarella 21:51e162c130a9 476 // there is a mission in flash check if there is already logged data
aureliocarella 21:51e162c130a9 477 if (isSDCardWithoutDataLog() == 0) {
aureliocarella 21:51e162c130a9 478 // just do default mission
aureliocarella 21:51e162c130a9 479 printf("Logged Data Detected...ExecuteDefaultMission...");
aureliocarella 21:51e162c130a9 480 fflush(stdout);
aureliocarella 21:51e162c130a9 481 ExecuteDefaultMission();
aureliocarella 21:51e162c130a9 482 // do not log this data
aureliocarella 21:51e162c130a9 483 loggingOutput = eLogToNothing;
aureliocarella 21:51e162c130a9 484 } else {
aureliocarella 21:51e162c130a9 485 // flag that we are logging to flash
aureliocarella 21:51e162c130a9 486 loggingOutput = eLogToFlash;
aureliocarella 21:51e162c130a9 487 }
aureliocarella 21:51e162c130a9 488 }
aureliocarella 21:51e162c130a9 489 }
aureliocarella 21:51e162c130a9 490
aureliocarella 21:51e162c130a9 491 // if we are logging to flash then read mission in flash
aureliocarella 21:51e162c130a9 492 if (loggingOutput == eLogToFlash) {
aureliocarella 21:51e162c130a9 493 if (_LoggingService_ReadMissionFromSDCard() ==
aureliocarella 21:51e162c130a9 494 false) { // if there is no mission in flash then get out
aureliocarella 21:51e162c130a9 495 Logging_SetStart(false);
aureliocarella 21:51e162c130a9 496 Peripherals::hspLed()->pattern(0xC3C3C3C3, 20);
aureliocarella 21:51e162c130a9 497 wait(2);
aureliocarella 21:51e162c130a9 498 printf("Abort Logging, Mission does not exist. ");
aureliocarella 21:51e162c130a9 499 fflush(stdout);
aureliocarella 21:51e162c130a9 500 return 0;
aureliocarella 21:51e162c130a9 501 }
aureliocarella 21:51e162c130a9 502 currentPage = Logging_GetLoggingStartPage();
aureliocarella 21:51e162c130a9 503 endPage = Logging_GetLoggingEndPage();
aureliocarella 21:51e162c130a9 504 }
aureliocarella 21:51e162c130a9 505
aureliocarella 21:51e162c130a9 506 MAX30001_Helper_SetupInterrupts();
aureliocarella 21:51e162c130a9 507 if (MAX30001_AnyStreamingSet() == 1) {
aureliocarella 21:51e162c130a9 508 MAX30001_Helper_StartSync();
aureliocarella 21:51e162c130a9 509 }
aureliocarella 21:51e162c130a9 510
aureliocarella 21:51e162c130a9 511 SetDataLoggingStream(TRUE);
aureliocarella 21:51e162c130a9 512
aureliocarella 21:51e162c130a9 513 /* while (usbSerial->readable()) {
aureliocarella 21:51e162c130a9 514 usbSerial->_getc();
aureliocarella 21:51e162c130a9 515 }
aureliocarella 21:51e162c130a9 516 fifo_clear(GetUSBIncomingFifo()); // clear USB serial incoming fifo
aureliocarella 21:51e162c130a9 517 fifo_clear(GetStreamOutFifo());
aureliocarella 21:51e162c130a9 518 */
aureliocarella 21:51e162c130a9 519 sram_buffer_0_dirty = 0;
aureliocarella 21:51e162c130a9 520 sram_buffer_1_dirty = 0;
aureliocarella 21:51e162c130a9 521
aureliocarella 21:51e162c130a9 522
aureliocarella 21:51e162c130a9 523 if (loggingOutput == eLogToNothing) printf("eLogToNothing..."); fflush(stdout);
aureliocarella 21:51e162c130a9 524 if (loggingOutput == eLogToFlash) printf("eLogToFlash..."); fflush(stdout);
aureliocarella 21:51e162c130a9 525 if (loggingOutput == eLogtoUsb) printf("eLogtoUsb..."); fflush(stdout);
aureliocarella 21:51e162c130a9 526 printf("highDataRate=%d...",highDataRate); fflush(stdout);
aureliocarella 21:51e162c130a9 527
aureliocarella 21:51e162c130a9 528
aureliocarella 21:51e162c130a9 529 Peripherals::timestampTimer()->reset();
aureliocarella 21:51e162c130a9 530 Peripherals::timestampTimer()->start();
aureliocarella 21:51e162c130a9 531
aureliocarella 21:51e162c130a9 532 _LoggingServer_OutputToCdcAcm_Start();
aureliocarella 21:51e162c130a9 533 while (1) {
aureliocarella 21:51e162c130a9 534 if (loggingOutput == eLogToFlash) {
aureliocarella 21:51e162c130a9 535 // check if we are at the end of flash
aureliocarella 21:51e162c130a9 536 if (currentPage >= endPage) {
aureliocarella 21:51e162c130a9 537 BlinkEndOfDatalogging(); // blink for 3 seconds to signal end of logging
aureliocarella 21:51e162c130a9 538 break;
aureliocarella 21:51e162c130a9 539 }
aureliocarella 21:51e162c130a9 540 }
aureliocarella 21:51e162c130a9 541
aureliocarella 21:51e162c130a9 542 if (startEvent == eStartEvent_BUTTON) {
aureliocarella 21:51e162c130a9 543 buttonPressed = Peripherals::pushButton()->GetButtonFallState();
aureliocarella 21:51e162c130a9 544 if (buttonPressed) {
aureliocarella 21:51e162c130a9 545 printf("button pressed, flush the FIFO buffer to SDCard before ending logging\r\n");
aureliocarella 21:51e162c130a9 546 Peripherals::pushButton()->clearButtonFallState();
aureliocarella 21:51e162c130a9 547 // if there is a dirty sram buffer... flush it to flash
aureliocarella 21:51e162c130a9 548 _LoggingServer_WriteDirtySramBufferToFlash();
aureliocarella 21:51e162c130a9 549 endSDLogging = true;
aureliocarella 21:51e162c130a9 550 }
aureliocarella 21:51e162c130a9 551 }
aureliocarella 21:51e162c130a9 552
aureliocarella 21:51e162c130a9 553 /* if (startEvent == eStartEvent_RPC_TO_USB ||
aureliocarella 21:51e162c130a9 554 startEvent == eStartEvent_RPC_TO_FLASH) {
aureliocarella 21:51e162c130a9 555 if (usbSerial->available()) {
aureliocarella 21:51e162c130a9 556 if (loggingOutput == eLogToFlash) {
aureliocarella 21:51e162c130a9 557 _LoggingServer_WriteDirtySramBufferToFlash();
aureliocarella 21:51e162c130a9 558 }
aureliocarella 21:51e162c130a9 559 wait(0.2f);
aureliocarella 21:51e162c130a9 560 while (usbSerial->available()) {
aureliocarella 21:51e162c130a9 561 usbSerial->_getc();
aureliocarella 21:51e162c130a9 562 }
aureliocarella 21:51e162c130a9 563 fifo_clear(GetUSBIncomingFifo()); // clear USB serial incoming fifo
aureliocarella 21:51e162c130a9 564 fifo_clear(GetStreamOutFifo());
aureliocarella 21:51e162c130a9 565 break;
aureliocarella 21:51e162c130a9 566 }
aureliocarella 21:51e162c130a9 567 }*/
aureliocarella 21:51e162c130a9 568 if (fp == NULL && loggingOutput == eLogToFlash)
aureliocarella 21:51e162c130a9 569 fp = fopen(dataFileName, "ab+");
aureliocarella 21:51e162c130a9 570 // check to see if data is available
aureliocarella 21:51e162c130a9 571 packetBurstCount = 0;
aureliocarella 21:51e162c130a9 572 while (PacketFifo_Empty() == 0) {
aureliocarella 21:51e162c130a9 573 printf("*");
aureliocarella 21:51e162c130a9 574 if (packetBurstCount >= 100 && endSDLogging == false)
aureliocarella 21:51e162c130a9 575 break;
aureliocarella 21:51e162c130a9 576 fifoData = PacketFifo_GetUint32();
aureliocarella 21:51e162c130a9 577 if (loggingOutput == eLogToFlash) {
aureliocarella 21:51e162c130a9 578 //_LoggingServer_OutputToFlash(fifoData);
aureliocarella 21:51e162c130a9 579 _LoggingServer_OutputToSDCard(fp, fifoData);
aureliocarella 21:51e162c130a9 580 }
aureliocarella 21:51e162c130a9 581 if (loggingOutput == eLogtoUsb) {
aureliocarella 21:51e162c130a9 582 if (highDataRate == 0)
aureliocarella 21:51e162c130a9 583 _LoggingServer_OutputToCdcAcm(fifoData);
aureliocarella 21:51e162c130a9 584 else
aureliocarella 21:51e162c130a9 585 _LoggingServer_OutputToCdcAcm_Block(fifoData);
aureliocarella 21:51e162c130a9 586 }
aureliocarella 21:51e162c130a9 587 packetBurstCount++;
aureliocarella 21:51e162c130a9 588 }
aureliocarella 21:51e162c130a9 589
aureliocarella 21:51e162c130a9 590 if (endSDLogging) {
aureliocarella 21:51e162c130a9 591 endSDLogging = false;
aureliocarella 21:51e162c130a9 592 if (fp != NULL) fclose(fp);
aureliocarella 21:51e162c130a9 593 fp == NULL;
aureliocarella 21:51e162c130a9 594 BlinkEndOfDatalogging(); // blink for 3 seconds to signal end of logging
aureliocarella 21:51e162c130a9 595 break;
aureliocarella 21:51e162c130a9 596 }
aureliocarella 21:51e162c130a9 597
aureliocarella 21:51e162c130a9 598 }
aureliocarella 21:51e162c130a9 599 _LoggingServer_OutputToCdcAcm_End();
aureliocarella 21:51e162c130a9 600 printf("End Logging.\n");
aureliocarella 21:51e162c130a9 601 fflush(stdout);
aureliocarella 21:51e162c130a9 602
aureliocarella 21:51e162c130a9 603 MAX30001_Helper_Stop(); // if any MAX30001 streams have been started, stop
aureliocarella 21:51e162c130a9 604 // them
aureliocarella 21:51e162c130a9 605 SetDataLoggingStream(FALSE);
aureliocarella 21:51e162c130a9 606 Peripherals::timestampTimer()->stop();
aureliocarella 21:51e162c130a9 607 hspLed->blink(1000);
aureliocarella 21:51e162c130a9 608 // default to non-usb packet speed optimizing
aureliocarella 21:51e162c130a9 609 highDataRate = 0;
aureliocarella 21:51e162c130a9 610 loggingTrigger = eTriggerLog_NULL;
aureliocarella 21:51e162c130a9 611 return 1;
aureliocarella 21:51e162c130a9 612 }
aureliocarella 21:51e162c130a9 613