Maxim Integrated / Mbed OS MAXREFDES101_SOURCE

Dependencies:   max32630fthr Adafruit_FeatherOLED USBDevice

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers EcgComm.cpp Source File

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, &reg_addr);
00174                     if (!ret) {
00175                         ret = sensor->MS_max30001readRegister(reg_addr, &reg_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, &reg_addr, &reg_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