MAX32620HSP (MAXREFDES100) RPC Example for Graphical User Interface
Dependencies: USBDevice
Fork of HSP_Release by
DataLoggingService.cpp
00001 /******************************************************************************* 00002 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved. 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a 00005 * copy of this software and associated documentation files (the "Software"), 00006 * to deal in the Software without restriction, including without limitation 00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00008 * and/or sell copies of the Software, and to permit persons to whom the 00009 * Software is furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included 00012 * in all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00017 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES 00018 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 00019 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 00020 * OTHER DEALINGS IN THE SOFTWARE. 00021 * 00022 * Except as contained in this notice, the name of Maxim Integrated 00023 * Products, Inc. shall not be used except as stated in the Maxim Integrated 00024 * Products, Inc. Branding Policy. 00025 * 00026 * The mere transfer of this software does not imply any licenses 00027 * of trade secrets, proprietary technology, copyrights, patents, 00028 * trademarks, maskwork rights, or any other form of intellectual 00029 * property whatsoever. Maxim Integrated Products, Inc. retains all 00030 * ownership rights. 00031 ******************************************************************************* 00032 */ 00033 #include "mbed.h" 00034 #include "USBSerial.h" 00035 #include "Logging.h" 00036 #include "Streaming.h" 00037 #include "RpcServer.h" 00038 #include "S25FS512.h" 00039 #include "BMP280.h" 00040 #include "PacketFifo.h" 00041 #include "DataLoggingService.h" 00042 #include "ServiceNonInterrupt.h" 00043 #include "HspLed.h" 00044 #include "MAX30001_helper.h" 00045 #include "MAX30101_helper.h" 00046 #include "StringInOut.h" 00047 #include "StringHelper.h" 00048 #include "Peripherals.h" 00049 #include "Device_Logging.h" 00050 00051 /// BMP280 logging object reference 00052 extern Device_Logging *bmp280_Logging; 00053 /// MAX14720 instance 0 logging object reference 00054 extern Device_Logging *MAX30205_0_Logging; 00055 /// MAX14720 instance 1 logging object reference 00056 extern Device_Logging *MAX30205_1_Logging; 00057 00058 #define PING_PONG_BUFFER_SIZE 512 00059 #define HALF_OF_PING_PONG_BUFFER_SIZE PING_PONG_BUFFER_SIZE / 2 00060 #define MISSION_DEFINITION_SIZE 4096 00061 00062 eLoggingTrigger loggingTrigger; 00063 00064 /// buffer where mission strings are stored 00065 char loggingMissionCmds[MISSION_DEFINITION_SIZE]; 00066 /// This houses two 256 byte ram concatenated to act as a ping-pong 00067 uint8_t PingPong_SRAM[PING_PONG_BUFFER_SIZE]; 00068 uint32_t buttonTrigger = 0; 00069 00070 eLoggingOutput loggingOutput; 00071 // extern int bleStartCommand; 00072 bool volatile globalFlag; 00073 extern int highDataRate; 00074 static uint32_t currentPage; 00075 static uint32_t sramIndex; 00076 /// flag to indicate that sram buffer 0 is dirty and will need to be flushed 00077 static uint32_t sram_buffer_0_dirty; 00078 /// flag to indicate that sram buffer 1 is dirty and will need to be flushed 00079 static uint32_t sram_buffer_1_dirty; 00080 /// usb byte buffer for sending out a bulk transfer 00081 static uint8_t usb_block[64]; 00082 /// running index used to accumulate bytes to send as a block via bulk transfer 00083 static uint16_t usb_block_index = 0; 00084 00085 typedef enum { 00086 eStartEvent_NULL, 00087 eStartEvent_BLE, 00088 eStartEvent_BUTTON, 00089 eStartEvent_RPC_TO_USB, 00090 eStartEvent_RPC_TO_FLASH 00091 } eStartEvent; 00092 static eStartEvent startEvent; 00093 00094 extern USBSerial *usbSerialPtr; 00095 00096 /** 00097 * @brief Sets a flag to start USB logging (streaming) 00098 */ 00099 void LoggingService_StartLoggingUsb(void) { 00100 loggingTrigger = eTriggerLog_RPC_USB; 00101 } 00102 00103 /** 00104 * @brief Sets a flag to start flash logging 00105 */ 00106 void LoggingService_StartLoggingFlash(void) { 00107 loggingTrigger = eTriggerLog_RPC_FLASH; 00108 } 00109 00110 /** 00111 * @brief Checks the various logging start condition 00112 * @return 1 if a start condition is true, 0 if there is no start condition 00113 */ 00114 static bool _LoggingService_CheckStartCondition(void) { 00115 bool buttonPressed; 00116 buttonPressed = Peripherals::pushButton()->GetButtonFallState(); 00117 00118 // default not logging USB or flash 00119 loggingOutput = eLogToNothing; 00120 startEvent = eStartEvent_NULL; 00121 if (buttonPressed) { 00122 Peripherals::pushButton()->clearButtonFallState(); 00123 // a falling state has been detected... wait for a fraction of a second and 00124 // re-read the pin 00125 // only start datalogging if the pin was released within this wait time 00126 wait(0.75f); 00127 int buttonRead = Peripherals::pushButton()->Read(); 00128 // if after a period of time the button is still pressed then get out 00129 if (buttonRead == 0) 00130 return 0; 00131 buttonTrigger = 0; 00132 00133 loggingTrigger = eTriggerLog_BUTTON; 00134 loggingOutput = eLogToFlash; 00135 startEvent = eStartEvent_BUTTON; 00136 return true; 00137 } 00138 if (loggingTrigger == eTriggerLog_RPC_FLASH) { 00139 loggingOutput = eLogToFlash; 00140 startEvent = eStartEvent_RPC_TO_FLASH; 00141 return true; 00142 } 00143 if (Peripherals::hspBLE()->getStartDataLogging()) { 00144 loggingTrigger = eTriggerLog_BLE; 00145 loggingOutput = eLogToFlash; 00146 startEvent = eStartEvent_BLE; 00147 return true; 00148 } 00149 // check if start is from RPC call for USB streaming 00150 if (loggingTrigger == eTriggerLog_RPC_USB) { 00151 loggingOutput = eLogtoUsb; 00152 startEvent = eStartEvent_RPC_TO_USB; 00153 return true; 00154 } 00155 return false; 00156 } 00157 00158 /** 00159 * @brief Read the mission string from flash into a buffer 00160 * @return false if a mission was not defined, true if mission was read and 00161 * buffered 00162 */ 00163 static bool _LoggingService_ReadMissionFromFlash(void) { 00164 // get mission from flash 00165 Logging_ReadMissionFromFlash((uint8_t *)loggingMissionCmds); 00166 if (Logging_IsMissionDefined((uint8_t *)loggingMissionCmds) == 0) { 00167 return false; 00168 } 00169 printf(loggingMissionCmds); 00170 fflush(stdout); 00171 RPC_ProcessCmds(loggingMissionCmds); 00172 return true; 00173 } 00174 00175 /** 00176 * @brief Process a RPC command that is pointed to. 00177 * @param cmd RPC string to process 00178 */ 00179 void ProcessCmd(const char *cmd) { 00180 char cmd_[256]; 00181 char reply[512]; 00182 strcpy(cmd_, cmd); 00183 RPC_call(cmd_, reply); 00184 } 00185 00186 /** 00187 * @brief Buffer sensor fifo data in ram buffers, when a ram buffer is full (a 00188 * flash page worth of data is accumulated) then flash that buffer. 00189 * A buffer ping pong method is used so that one buffer can be flashing as 00190 * the other buffer fills with sensor fifo data. 00191 * @param fifoData Sensor data taken from the fifo to be stored into flash 00192 */ 00193 static void _LoggingServer_OutputToFlash(uint32_t fifoData) { 00194 uint32_t index; 00195 char str[128]; 00196 uint8_t *ptr; 00197 // 00198 // Log To Flash 00199 // 00200 // i.e. there is data, read one 32-bit size data at a time. 00201 // put the fifo data into the ping-pong SRAM 00202 PingPong_SRAM[sramIndex++] = fifoData & 0xFF; // LSByte goes into index N 00203 PingPong_SRAM[sramIndex++] = (fifoData >> 8) & 0xFF; 00204 PingPong_SRAM[sramIndex++] = (fifoData >> 16) & 0xFF; 00205 PingPong_SRAM[sramIndex++] = (fifoData >> 24) & 0xFF; // MSByte goes into index N+3 00206 00207 // flag this buffer as dirty 00208 if (sramIndex <= 256) 00209 sram_buffer_0_dirty = 1; 00210 else 00211 sram_buffer_1_dirty = 1; 00212 00213 if (sramIndex == 256 || 00214 sramIndex == 512) // Either Ping SRAM or Pong SRAM location is full 00215 { // therefore write to Flash 00216 00217 index = sramIndex - 256; 00218 ptr = &PingPong_SRAM[index]; 00219 sprintf(str, "currentPage=%lu", currentPage); 00220 Peripherals::s25FS512()->writePage_Helper(currentPage, ptr, 0); 00221 00222 // this page is no longer dirty 00223 if (index == 0) 00224 sram_buffer_0_dirty = 0; 00225 if (index == 256) 00226 sram_buffer_1_dirty = 0; 00227 00228 currentPage++; 00229 } 00230 sramIndex = sramIndex % 512; // Wrap around the index 00231 } 00232 00233 /** 00234 * @brief If flash ram buffers are flagged as dirty, flush to flash 00235 */ 00236 static void _LoggingServer_WriteDirtySramBufferToFlash(void) { 00237 uint8_t *ptr = PingPong_SRAM; 00238 if (sram_buffer_0_dirty == 0 && sram_buffer_1_dirty == 0) 00239 return; 00240 if (sram_buffer_0_dirty == 1) { 00241 ptr += 0; 00242 } 00243 if (sram_buffer_1_dirty == 1) { 00244 ptr += 256; 00245 } 00246 printf("_LoggingServer_WriteDirtySramBufferToFlash:%lu,%lu\n", 00247 sram_buffer_0_dirty, sram_buffer_1_dirty); 00248 fflush(stdout); 00249 // s25fs512_WritePage_Helper(currentPage, ptr, 0); 00250 Peripherals::s25FS512()->writePage_Helper(currentPage, ptr, 0); 00251 } 00252 00253 /** 00254 * @brief Initialize the USB block running index 00255 * @param fifoData Sensor data taken from the fifo to be sent out USB 00256 */ 00257 static void _LoggingServer_OutputToCdcAcm(uint32_t fifoData) { 00258 uint8_t *ptr; 00259 uint8_t str[16]; 00260 sprintf((char *)str, "%X ", (unsigned int)fifoData); 00261 ptr = str; 00262 usb_block_index = 0; 00263 while (*ptr != 0) { 00264 usb_block[usb_block_index] = *ptr; 00265 ptr++; 00266 usb_block_index++; 00267 } 00268 usbSerialPtr->writeBlock(usb_block, usb_block_index); 00269 } 00270 00271 /** 00272 * @brief Initialize the USB block running index 00273 */ 00274 static void _LoggingServer_OutputToCdcAcm_Start(void) { usb_block_index = 0; } 00275 00276 /** 00277 * @brief Buffer up fifoData from sensors, do a USB block transfer if buffer is 00278 * full 00279 * @param fifoData Sensor data taken from the fifo to be send out USB within a 00280 * bulk block transfer 00281 * @return Return the success status of the writeblock operation 00282 */ 00283 static bool _LoggingServer_OutputToCdcAcm_Block(uint32_t fifoData) { 00284 uint8_t str[64]; 00285 uint8_t *ptr; 00286 bool result; 00287 // 00288 // Log to CDCACM 00289 // 00290 result = true; 00291 sprintf((char *)str, "%X ", (unsigned int)fifoData); 00292 ptr = str; 00293 while (*ptr != 0) { 00294 usb_block[usb_block_index] = *ptr; 00295 ptr++; 00296 usb_block_index++; 00297 if (usb_block_index >= 64) { 00298 result = usbSerialPtr->writeBlock(usb_block, 64); 00299 usb_block_index = 0; 00300 } 00301 } 00302 return result; 00303 } 00304 00305 /** 00306 * @brief Output a full USB block via bulk transfer 00307 */ 00308 static void _LoggingServer_OutputToCdcAcm_End(void) { 00309 if (usb_block_index == 0) 00310 return; 00311 usbSerialPtr->writeBlock(usb_block, usb_block_index - 1); 00312 } 00313 00314 /** 00315 * @brief Blink LED pattern that indicates that the flash end boundary has been 00316 * reached 00317 */ 00318 static void BlinkEndOfDatalogging(void) { 00319 // blink to signal end of logging 00320 Peripherals::hspLed()->pattern(0x55555555, 20); 00321 wait(2); 00322 } 00323 00324 /** 00325 * @brief Reads the first data page of flash, if all FF's then the page is empty 00326 * @return 1 if the flash is empty as indicated by the first data page of the 00327 * flash, 0 if not 00328 */ 00329 int isFlashEmpty(void) { 00330 int i; 00331 uint8_t data[256]; 00332 int firstDataPage = Logging_GetLoggingStartPage(); 00333 Peripherals::s25FS512()->readPages_Helper(firstDataPage, firstDataPage, data, 0); 00334 for (i = 0; i < 256; i++) { 00335 if (data[i] != 0xFF) 00336 return 0; 00337 } 00338 return 1; 00339 } 00340 00341 /** 00342 * @brief Blink LED pattern that indicates that the flash is not empty and a new 00343 * flash logging session can not occur 00344 */ 00345 void BlinkFlashNotEmpty(void) { 00346 Peripherals::hspLed()->pattern(0x55555555, 20); 00347 wait(1); 00348 } 00349 00350 void ExecuteDefaultMission(void) { 00351 ProcessCmd("/MAX30001/CAL_InitStart 01 01 01 03 7FF 00"); 00352 ProcessCmd("/MAX30001/ECG_InitStart 01 01 01 00 02 03 1F 0 00 00 01"); 00353 ProcessCmd("/MAX30001/RtoR_InitStart 01 03 0F 00 03 01 00 00 01"); 00354 ProcessCmd("/MAX30001/Rbias_FMSTR_Init 01 02 01 01 00"); 00355 ProcessCmd("/LIS2DH/InitStart 02 01"); 00356 } 00357 00358 void LoggingService_Init(void) { loggingTrigger = eTriggerLog_NULL; } 00359 00360 /** 00361 * @brief This routine checks to see if a USB or flash logging action needs to be taken 00362 * The routine checks for a start condition via button press, USB command, or BLE command 00363 * Once one of these start conditions is present, the logging begins until stopped or memory is full 00364 * @return 1 if successful, 0 if error or logging was aborted and no logging occurred 00365 */ 00366 uint8_t LoggingService_ServiceRoutine(void) { 00367 uint32_t fifoData; 00368 uint32_t endPage; 00369 //USBSerial *usbSerial = Peripherals::usbSerial(); 00370 // BMP280 *bmp280 = Peripherals::bmp280(); 00371 bool buttonPressed; 00372 int packetBurstCount = 0; 00373 HspLed *hspLed = Peripherals::hspLed(); 00374 00375 sramIndex = 0; 00376 // only start logging if conditions exist 00377 00378 if (_LoggingService_CheckStartCondition() == false) return 0; 00379 printf("Begin Logging..."); 00380 if (startEvent == eStartEvent_NULL) printf("eStartEvent_NULL..."); 00381 if (startEvent == eStartEvent_BLE) printf("eStartEvent_BLE..."); 00382 if (startEvent == eStartEvent_BUTTON) printf("eStartEvent_BUTTON..."); 00383 if (startEvent == eStartEvent_RPC_TO_USB) printf("eStartEvent_RPC_TO_USB..."); 00384 if (startEvent == eStartEvent_RPC_TO_FLASH) printf("eStartEvent_RPC_TO_FLASH..."); 00385 fflush(stdout); 00386 00387 // start logging stuttered blink pattern 00388 hspLed->pattern(0xA0F3813, 20); 00389 00390 if (startEvent == eStartEvent_RPC_TO_FLASH || 00391 startEvent == eStartEvent_BUTTON) { 00392 // check to see if datalog already in flash... abort and force user to erase 00393 // flash if needed 00394 if (loggingOutput == eLogToFlash) { 00395 if (isFlashEmpty() == 0) { 00396 Logging_SetStart(false); 00397 // bleStartCommand = 0x00; 00398 BlinkFlashNotEmpty(); 00399 hspLed->blink(1000); 00400 printf("Abort Logging, flash log exists. "); 00401 fflush(stdout); 00402 return 0; 00403 } 00404 } 00405 } 00406 00407 if (startEvent == eStartEvent_BLE) { 00408 // check for mission in flash 00409 if (_LoggingService_ReadMissionFromFlash() == false) { 00410 // if there is no mission in flash then do a default mission for the sake 00411 // of ble Android app working "out-of-the-box" and stream RtoR and Accel 00412 printf("No Mission in Flash...ExecuteDefaultMission..."); 00413 fflush(stdout); 00414 ExecuteDefaultMission(); 00415 // do not log this data 00416 loggingOutput = eLogToNothing; 00417 } else { 00418 // there is a mission in flash check if there is already logged data 00419 if (isFlashEmpty() == 0) { 00420 // just do default mission 00421 printf("Logged Data Detected...ExecuteDefaultMission..."); 00422 fflush(stdout); 00423 ExecuteDefaultMission(); 00424 // do not log this data 00425 loggingOutput = eLogToNothing; 00426 } else { 00427 // flag that we are logging to flash 00428 loggingOutput = eLogToFlash; 00429 } 00430 } 00431 } 00432 00433 // if we are logging to flash then read mission in flash 00434 if (loggingOutput == eLogToFlash) { 00435 if (_LoggingService_ReadMissionFromFlash() == 00436 false) { // if there is no mission in flash then get out 00437 Logging_SetStart(false); 00438 Peripherals::hspLed()->pattern(0xC3C3C3C3, 20); 00439 wait(2); 00440 printf("Abort Logging, Mission does not exist. "); 00441 fflush(stdout); 00442 return 0; 00443 } 00444 currentPage = Logging_GetLoggingStartPage(); 00445 endPage = Logging_GetLoggingEndPage(); 00446 } 00447 00448 MAX30001_Helper_SetupInterrupts(); 00449 if (MAX30001_AnyStreamingSet() == 1) { 00450 MAX30001_Helper_StartSync(); 00451 } 00452 00453 SetDataLoggingStream(TRUE); 00454 ServiceNonInterrupt_Init(); 00455 ServiceNonInterrupt_StartTimer(); 00456 00457 while (usbSerialPtr->readable()) { 00458 usbSerialPtr->_getc(); 00459 } 00460 fifo_clear(GetUSBIncomingFifo()); // clear USB serial incoming fifo 00461 fifo_clear(GetStreamOutFifo()); 00462 00463 sram_buffer_0_dirty = 0; 00464 sram_buffer_1_dirty = 0; 00465 00466 00467 if (loggingOutput == eLogToNothing) { printf("eLogToNothing..."); fflush(stdout); } 00468 if (loggingOutput == eLogToFlash) { printf("eLogToFlash..."); fflush(stdout); } 00469 if (loggingOutput == eLogtoUsb) { printf("eLogtoUsb..."); fflush(stdout); } 00470 printf("highDataRate=%u...",(unsigned int)highDataRate); fflush(stdout); 00471 00472 00473 Peripherals::timestampTimer()->reset(); 00474 Peripherals::timestampTimer()->start(); 00475 00476 _LoggingServer_OutputToCdcAcm_Start(); 00477 while (1) { 00478 if (loggingOutput == eLogToFlash) { 00479 // check if we are at the end of flash 00480 endPage = Logging_GetLoggingEndPage(); 00481 if (currentPage >= endPage) { 00482 BlinkEndOfDatalogging(); // blink for 3 seconds to signal end of logging 00483 break; 00484 } 00485 } 00486 00487 if (startEvent == eStartEvent_BUTTON) { 00488 buttonPressed = Peripherals::pushButton()->GetButtonFallState(); 00489 if (buttonPressed) { 00490 Peripherals::pushButton()->clearButtonFallState(); 00491 // if there is a dirty sram buffer... flush it to flash 00492 _LoggingServer_WriteDirtySramBufferToFlash(); 00493 BlinkEndOfDatalogging(); // blink for 3 seconds to signal end of logging 00494 break; 00495 } 00496 } 00497 00498 if (loggingTrigger == eTriggerLog_BLE) { 00499 if (Peripherals::hspBLE()->getStartDataLogging() == false) { 00500 // if there is a dirty sram buffer... flush it to flash 00501 _LoggingServer_WriteDirtySramBufferToFlash(); 00502 BlinkEndOfDatalogging(); // blink for 3 seconds to signal end of logging 00503 break; 00504 } 00505 } 00506 00507 if (startEvent == eStartEvent_RPC_TO_USB || 00508 startEvent == eStartEvent_RPC_TO_FLASH) { 00509 if (usbSerialPtr->available()) { 00510 if (loggingOutput == eLogToFlash) { 00511 _LoggingServer_WriteDirtySramBufferToFlash(); 00512 } 00513 wait(0.2f); 00514 while (usbSerialPtr->available()) { 00515 usbSerialPtr->_getc(); 00516 } 00517 fifo_clear(GetUSBIncomingFifo()); // clear USB serial incoming fifo 00518 fifo_clear(GetStreamOutFifo()); 00519 break; 00520 } 00521 } 00522 00523 // check to see if data is available 00524 packetBurstCount = 0; 00525 while (PacketFifo_Empty() == 0) { 00526 if (packetBurstCount >= 100) 00527 break; 00528 fifoData = PacketFifo_GetUint32(); 00529 if (loggingOutput == eLogToFlash) { 00530 _LoggingServer_OutputToFlash(fifoData); 00531 } 00532 if (loggingOutput == eLogtoUsb) { 00533 if (highDataRate == 0) 00534 _LoggingServer_OutputToCdcAcm(fifoData); 00535 else 00536 _LoggingServer_OutputToCdcAcm_Block(fifoData); 00537 } 00538 packetBurstCount++; 00539 } 00540 00541 if (PacketFifo_Empty() != 0) { 00542 Peripherals::ble()->waitForEvent(); 00543 } 00544 ServiceNonInterrupt_BMP280(bmp280_Logging); 00545 ServiceNonInterrupt_MAX30205(MAX30205_0_Logging, 00546 Peripherals::max30205_top(), 00547 PACKET_MAX30205_TEMP_TOP); 00548 ServiceNonInterrupt_MAX30205(MAX30205_1_Logging, 00549 Peripherals::max30205_bottom(), 00550 PACKET_MAX30205_TEMP_BOTTOM); 00551 } 00552 _LoggingServer_OutputToCdcAcm_End(); 00553 printf("End Logging.\n"); 00554 fflush(stdout); 00555 00556 bmp280_Logging->stop(); 00557 MAX30205_0_Logging->stop(); 00558 MAX30205_1_Logging->stop(); 00559 MAX30001_Helper_Stop(); // if any MAX30001 streams have been started, stop 00560 // them 00561 MAX30101_Helper_Stop(); // if any MAX30101 streams have been started, stop 00562 // them 00563 Peripherals::lis2dh()->stop(); 00564 SetDataLoggingStream(FALSE); 00565 Peripherals::timestampTimer()->stop(); 00566 hspLed->blink(1000); 00567 // default to non-usb packet speed optimizing 00568 highDataRate = 0; 00569 loggingTrigger = eTriggerLog_NULL; 00570 return 1; 00571 }
Generated on Tue Jul 12 2022 17:59:19 by 1.7.2