Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: max32630fthr Adafruit_FeatherOLED USBDevice
EcgComm.cpp
00001 /*************************************************************************** 00002 * Copyright (C) 2017 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 00034 #include "EcgComm.h" 00035 #include "EcgComm_Defines.h" 00036 #include <ctype.h> 00037 #include "CRC8.h" 00038 #include "Peripherals.h" 00039 #include "utils.h" 00040 #include "MAX30001_Helper.h" 00041 #include "BLE_ICARUS.h" 00042 00043 #define ECG_REG_COUNT 64 00044 00045 const char *cmd_tbl_ecg[] = { 00046 "int", 00047 "get_format ecg 1", 00048 "get_format ecg 2", 00049 "read ecg 1", //ecg 00050 "read ecg 2", //android app data streaming mode 00051 "get_reg ecg", 00052 "set_reg ecg", 00053 "dump_reg ecg", 00054 "set_cfg ecg invert" 00055 }; 00056 00057 typedef union { 00058 struct { 00059 uint32_t ptag :3; 00060 uint32_t etag :3; 00061 uint32_t ecg_data :16; 00062 uint32_t reserved :8; 00063 }; 00064 int32_t ecg_data_whole; 00065 } ecg_data_parser; 00066 00067 EcgComm::EcgComm(USBSerial* USB): 00068 SensorComm("ecg", true) 00069 { 00070 m_USB = USB; 00071 } 00072 00073 void EcgComm::stop() 00074 { 00075 int ret; 00076 comm_mutex.lock(); 00077 data_report_mode = 0; 00078 comm_mutex.unlock(); 00079 sample_count = 0; 00080 ret = sensor->sensor_enable(0); 00081 if (ret < 0) { 00082 pr_err("sensor_enable failed. ret: %d", ret); 00083 } 00084 } 00085 00086 bool EcgComm::parse_command(const char* cmd) 00087 { 00088 int i; 00089 int ret = EXIT_SUCCESS; 00090 uint8_t reg_addr; 00091 uint32_t reg_val = 0; 00092 bool recognizedCmd = false; 00093 uint8_t params[32]; 00094 char charbuf[768]; 00095 int data_len = 0; 00096 addr_val_pair reg_vals[ECG_REG_COUNT]; 00097 int comma = 0; 00098 00099 if (sensor == NULL) { 00100 pr_err("sensor object is invalid!"); 00101 return false; 00102 } 00103 00104 for (i = 0; i < NUM_CMDS; i++) { 00105 if (starts_with(cmd, cmd_tbl_ecg[i])) { 00106 cmd_state_t user_cmd = (cmd_state_t)i; 00107 recognizedCmd = true; 00108 switch (user_cmd) { 00109 case get_format_1: 00110 if(AsciiEn) 00111 { 00112 m_USB->printf("\r\n%s format=smpleCnt,ecg err=0\r\n", 00113 cmd); 00114 } 00115 else 00116 { 00117 00118 if(BLE::Instance().gap().getState().connected) { 00119 data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s enc=bin cs=1 format={smpleCnt,8},{rtor,14},{rtorbpm,8}," 00120 "{pTag.0,3},{eTag.0,3},{ecg.0,18}," 00121 "{pTag.1,3},{eTag.1,3},{ecg.1,18}," 00122 "{pTag.2,3},{eTag.2,3},{ecg.2,18}," 00123 "{pTag.3,3},{eTag.3,3},{ecg.3,18} err=0\r\n", cmd); 00124 } else { 00125 m_USB->printf("\r\n%s enc=bin cs=1 format={smpleCnt,8},{pTag,3},{eTag,3}," 00126 "{ecg,18},{rtor,14},{rtorbpm,8} err=0\r\n", cmd); 00127 } 00128 } 00129 break; 00130 case get_format_2: 00131 if(AsciiEn) 00132 { 00133 m_USB->printf("\r\n%s format=smpleCnt,rtor err=0\r\n", 00134 cmd); 00135 } 00136 else 00137 { 00138 data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s enc=bin cs=1 format={smplCnt,8},{rtor,15} err=0\r\n", 00139 cmd); 00140 m_USB->printf(charbuf); 00141 } 00142 break; 00143 case ecg_mode: 00144 00145 comm_mutex.lock(); 00146 data_report_mode = ecg_mode; 00147 comm_mutex.unlock(); 00148 ret = sensor->sensor_enable(1); 00149 if (ret < 0) { 00150 pr_err("sensor_enable failed. ret: %d", ret); 00151 } 00152 00153 data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, ret); 00154 m_USB->printf(charbuf); 00155 break; 00156 case ecg_mode_2: 00157 comm_mutex.lock(); 00158 data_report_mode = ecg_mode_2; 00159 comm_mutex.unlock(); 00160 ret = ((MAX30001_Helper*)sensor)->Max30001Helper_SetECGSampleRate(MAX30001_Helper::k128SPS); 00161 ret |= sensor->sensor_enable(1); 00162 if (ret < 0) { 00163 pr_err("sensor_enable failed. ret: %d", ret); 00164 } 00165 00166 data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, ret); 00167 m_USB->printf(charbuf); 00168 break; 00169 00170 case get_reg: 00171 reg_addr = 0; 00172 reg_val = 0; 00173 ret = parse_get_reg_cmd(cmd, sensor_type, ®_addr); 00174 if (!ret) { 00175 ret = sensor->MS_max30001readRegister(reg_addr, ®_val); 00176 if(ret == 0) { 00177 data_len = snprintf(charbuf, sizeof(charbuf), 00178 "\r\n%s reg_val=%08X err=%d\r\n", cmd, reg_val, ret); 00179 m_USB->printf(charbuf); 00180 }else { 00181 data_len = snprintf(charbuf, sizeof(charbuf), 00182 "\r\n%s err=%d\r\n", cmd, ret); 00183 m_USB->printf(charbuf); 00184 } 00185 }else{ 00186 data_len = snprintf(charbuf, sizeof(charbuf), 00187 "\r\n%s err=%d\r\n", cmd, ret); 00188 m_USB->printf(charbuf); 00189 } 00190 break; 00191 case set_reg: 00192 reg_addr = 0; 00193 reg_val = 0; 00194 ret = parse_set_reg_cmd(cmd, sensor_type, ®_addr, ®_val); 00195 if (!ret) { 00196 ret = sensor->MS_max30001writeRegister(reg_addr, reg_val); 00197 if(ret == 0) { 00198 data_len = snprintf(charbuf, sizeof(charbuf), 00199 "\r\n%s err=%d\r\n", cmd, ret); 00200 m_USB->printf(charbuf); 00201 }else { 00202 data_len = snprintf(charbuf, sizeof(charbuf), 00203 "\r\n%s err=%d\r\n", cmd, ret); 00204 m_USB->printf(charbuf); 00205 } 00206 }else{ 00207 data_len = snprintf(charbuf, sizeof(charbuf), 00208 "\r\n%s err=%d\r\n", cmd, ret); 00209 m_USB->printf(charbuf); 00210 } 00211 break; 00212 case dump_regs: 00213 for (int j = 0; j < ECG_REG_COUNT; j++) { 00214 reg_vals[j].addr = 0xFF; 00215 } 00216 ret = sensor->dump_registers(reg_vals); 00217 00218 if (ret) { 00219 m_USB->printf("\r\n%s err=%d\n", cmd, ret); 00220 data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\n", cmd, ret); 00221 } 00222 else { 00223 data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s reg_val=", cmd); 00224 comma = false; 00225 00226 for (int reg = 0; reg < ECG_REG_COUNT; reg++) { 00227 if(reg_vals[reg].addr == 0xFF) 00228 break; 00229 00230 if (comma) { 00231 data_len += snprintf(charbuf + data_len, 00232 sizeof(charbuf) - data_len - 1, ","); 00233 } 00234 data_len += snprintf(charbuf + data_len, 00235 sizeof(charbuf) - data_len - 1, 00236 "{%X,%X}", (unsigned int)reg_vals[reg].addr, (unsigned int)reg_vals[reg].val); 00237 comma = 1; 00238 } 00239 data_len += snprintf(charbuf + data_len, sizeof(charbuf) - data_len - 1, " err=0\r\n"); 00240 m_USB->printf(charbuf); 00241 } 00242 break; 00243 case InterruptInit: 00244 ret = ECG_Parse_Parameters_Single((cmd + strlen(cmd_tbl_ecg[i])), params, kInterruptParametersCount); 00245 if(ret != 0){ 00246 printf("ECG_Parse_Parameters_Single has failed\n"); 00247 break; 00248 } 00249 ret = sensor->MS_max30001_INT_assignment(params[0], params[1], params[2], 00250 params[3], params[4], params[5], 00251 params[6], params[7], params[8], 00252 params[9], params[10], params[11], 00253 params[12], params[13], params[14], 00254 params[15], params[16]); 00255 m_USB->printf("\r\n%s err=%d\r\n", cmd, ret == 0 ? 0 : -255); 00256 break; 00257 00258 case set_cfg_ecg_invert: { 00259 ret = ((MAX30001_Helper*)sensor)->MAX30001_Helper_Invert_Waveform(); 00260 m_USB->printf("\r\n%s err=%d\r\n", cmd, ret); 00261 } break; 00262 00263 default: 00264 break; 00265 } 00266 00267 00268 if (BLE::Instance().gap().getState().connected) { 00269 BLE_Icarus_AddtoQueue((uint8_t *)charbuf, (int32_t)sizeof(charbuf), data_len); 00270 } 00271 00272 00273 } 00274 } 00275 00276 return recognizedCmd; 00277 } 00278 00279 int EcgComm::data_report_execute(char* buf, int size) 00280 { 00281 int ret = 0; 00282 int16_t data_len = 0; 00283 uint8_t tmp_report_mode; 00284 ecg_sensor_report sensor_report = {0}; 00285 ecg_sensor_report sensor_report_2 = {0}; 00286 ecg_sensor_report sensor_report_3 = {0}; 00287 ecg_sensor_report sensor_report_4 = {0}; 00288 ecg1_comm_packet* data_packet; 00289 ecg_comm_packet_ble* data_packet_ble; 00290 00291 if(!is_enabled()) 00292 return 0; 00293 00294 if (sensor == NULL) 00295 return 0; 00296 00297 comm_mutex.lock(); 00298 tmp_report_mode = data_report_mode; 00299 comm_mutex.unlock(); 00300 00301 if(((MAX30001_Helper*)sensor)->Max30001Helper_getInterruptStatus()) { 00302 ((MAX30001_Helper*)sensor)->Max30001Helper_max30001_int_handler(); 00303 ((MAX30001_Helper*)sensor)->Max30001Helper_setInterruptStatus(false); 00304 } 00305 00306 switch(tmp_report_mode) { 00307 case ecg_mode: 00308 case ecg_mode_2: 00309 if(AsciiEn){ 00310 00311 ret = ((MAX30001_Helper*)sensor)->get_sensor_report(sensor_report); 00312 00313 if (ret < 0) 00314 return 0; 00315 data_len = snprintf(buf, size - 1, 00316 "%lu,%ld,%d,%d,%.3f,%.3f,%.3f\r\n", 00317 sample_count++, 00318 sensor_report.ecg, 00319 sensor_report.rtor, 00320 sensor_report.rtor_bpm, 00321 sensor_report.x, 00322 sensor_report.y, 00323 sensor_report.z); 00324 } 00325 else{ 00326 if((m_sensorcomm_ble_interface_exists_ | m_sensorcomm_flash_rec_started_) && (((MAX30001_Helper*)sensor)->MAX30001_Helper_Queue_Size() >= m_ecg_ble_packet_count_)) { 00327 00328 ret = ((MAX30001_Helper*)sensor)->get_sensor_report(sensor_report); 00329 ret |= ((MAX30001_Helper*)sensor)->get_sensor_report(sensor_report_2); 00330 ret |= ((MAX30001_Helper*)sensor)->get_sensor_report(sensor_report_3); 00331 ret |= ((MAX30001_Helper*)sensor)->get_sensor_report(sensor_report_4); 00332 00333 if (ret < 0) 00334 return 0; 00335 data_packet_ble = (ecg_comm_packet_ble*)buf; 00336 data_packet_ble->start_byte = 0xAA; 00337 data_packet_ble->sample_count = sample_count; 00338 sample_count += m_ecg_ble_packet_count_; 00339 data_packet_ble->ecg = sensor_report.ecg; 00340 data_packet_ble->ecg_2 = sensor_report_2.ecg; 00341 data_packet_ble->ecg_3 = sensor_report_3.ecg; 00342 data_packet_ble->ecg_4 = sensor_report_4.ecg; 00343 data_packet_ble->rtor = (sensor_report.rtor | sensor_report_2.rtor | sensor_report_3.rtor | sensor_report_4.rtor); 00344 data_packet_ble->rtor_bpm = (sensor_report.rtor_bpm | sensor_report_2.rtor_bpm | sensor_report_3.rtor_bpm | sensor_report_4.rtor_bpm); 00345 data_packet_ble->crc8 = crc8((uint8_t*)data_packet_ble, sizeof(*data_packet_ble) - sizeof(uint8_t)); 00346 data_len = sizeof(*data_packet_ble); 00347 } else if((m_sensorcomm_ble_interface_exists_ == 0) & (m_sensorcomm_flash_rec_started_ == 0)) { 00348 00349 ret = ((MAX30001_Helper*)sensor)->get_sensor_report(sensor_report); 00350 00351 if (ret < 0) 00352 return 0; 00353 data_packet = (ecg1_comm_packet*)buf; 00354 data_packet->start_byte = 0xAA; 00355 data_packet->sample_count = sample_count++; 00356 data_packet->ecg = sensor_report.ecg; 00357 data_packet->rtor = sensor_report.rtor; 00358 data_packet->rtor_bpm = sensor_report.rtor_bpm; 00359 data_packet->crc8 = crc8((uint8_t*)data_packet, sizeof(*data_packet) - sizeof(uint8_t)); 00360 data_len = sizeof(*data_packet); 00361 } 00362 } 00363 break; 00364 default: 00365 break; 00366 } 00367 00368 if (data_len < 0) { 00369 pr_err("snprintf buf failed"); 00370 } else if (data_len > size) { 00371 pr_err("buffer is insufficient to hold data"); 00372 } 00373 00374 return data_len; 00375 } 00376 00377 // this function parses the parameters for max30001_ECG_InitStart function 00378 int EcgComm::ECG_Parse_Parameters(char *substring, uint8_t parameters[], uint8_t parameters_len){ 00379 char *pt_ch = substring; 00380 00381 if(strlen(pt_ch) < (parameters_len*2)){ 00382 pr_err("Wrong number of params"); 00383 return -1; 00384 }else{ 00385 if(ConvertHexString2Decimal(pt_ch, parameters, parameters_len) != 0) 00386 return -1; 00387 for(int i = 0; i < parameters_len; ++i){ 00388 printf("%d\n", parameters[i]); 00389 } 00390 } 00391 return 0; 00392 } 00393 00394 // this function parses the parameters for max30001_ECG_InitStart function for single digits 00395 int EcgComm::ECG_Parse_Parameters_Single(const char *substring, uint8_t parameters[], uint8_t parameters_len){ 00396 const char *pt_ch = substring; 00397 int i = 0; 00398 unsigned char num_found = 0; 00399 00400 if(strlen(pt_ch) < (parameters_len)){ 00401 pr_err("Wrong number of params"); 00402 return -1; 00403 }else{ 00404 for(i = 0; i < parameters_len; ++i){ 00405 if(getHexDigit(pt_ch[i], &num_found)){ 00406 parameters[i] = num_found; 00407 } 00408 else{ 00409 pr_err("parsing of parameters failed"); 00410 return -1; 00411 } 00412 } 00413 for(i = 0; i < parameters_len; ++i){ 00414 printf("%d\n", parameters[i]); 00415 } 00416 } 00417 return 0; 00418 00419 } 00420 00421 char getHexDigit(char ch_hex, uint8_t *bt_hex) 00422 { 00423 if (ch_hex >= '0' && ch_hex <= '9') 00424 *bt_hex = ch_hex - '0'; 00425 else if (ch_hex >= 'A' && ch_hex <= 'F') 00426 *bt_hex = ch_hex - 'A' + 10; 00427 else if (ch_hex >= 'a' && ch_hex <= 'f') 00428 *bt_hex = ch_hex - 'a' + 10; 00429 else 00430 return false; 00431 return true; 00432 } 00433 00434 00435 int ConvertHexString2Decimal(char *pt_ch, uint8_t *bt_hex, int len){ 00436 00437 if(strlen(pt_ch) < ((uint32_t)len * 2)) 00438 return -1; 00439 00440 for(int i = 0; i < len; ++i){ 00441 uint8_t hex_digit; 00442 // Get most significant hex digit 00443 if (!getHexDigit(*(pt_ch++), &hex_digit)) 00444 return -1; 00445 else 00446 { 00447 hex_digit <<= 4; 00448 bt_hex[i] = hex_digit; 00449 } 00450 // Get least significant digit 00451 if (!getHexDigit(*(pt_ch++), &hex_digit)) 00452 return -1; 00453 else{ 00454 bt_hex[i] |= hex_digit; 00455 } 00456 } 00457 return 0; 00458 } 00459 00460 00461
Generated on Wed Jul 13 2022 22:33:03 by
1.7.2