Arun Raj / Mbed OS MAXREFDES101_SOURCE

Dependencies:   max32630fthr Adafruit_FeatherOLED USBDevice

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SSMAX8614XComm.cpp Source File

SSMAX8614XComm.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 "DSInterface.h"
00035 #include "SSMAX8614XComm.h"
00036 
00037 #include "../../../../Utilities/mxm_assert.h"
00038 #include "flc.h"
00039 #include "flc_regs.h"
00040 #include "Peripherals.h"
00041 #include "utils.h"
00042 #include "CRC8.h"
00043 
00044 
00045 #include "BLE_ICARUS.h"
00046 
00047 
00048 
00049 
00050 // By default, host accel is enabled
00051 
00052 //#define FORCE_RESET_WHEN_FAILED
00053 
00054 #define MAX_NUM_WR_ACC_SAMPLES          5
00055 #define BMI160_SAMPLE_RATE              25
00056 
00057 static const char* const cmd_tbl[] = {
00058     "get_format ppg 0",
00059     "read ppg 0",       // moved here to match parser index "3"
00060     "get_reg ppg",
00061     "set_reg ppg",
00062     "dump_reg ppg",
00063     "set_cfg ppg agc 0",
00064     "set_cfg ppg agc 1",
00065     "self_test ppg os58",
00066     "self_test ppg acc",
00067     "set_cfg whrmaecscd aecenable",
00068     "get_cfg whrmaecscd aecenable",
00069     "set_cfg whrmaecscd scdenable",
00070     "get_cfg whrmaecscd scdenable",
00071     "set_cfg whrmaecscd adjpdperiod",
00072     "get_cfg whrmaecscd adjpdperiod",
00073     "set_cfg whrmaecscd debouncewin",
00074     "get_cfg whrmaecscd debouncewin",
00075     "set_cfg whrmaecscd motionthreshold",
00076     "get_cfg whrmaecscd motionthreshold",
00077     "set_cfg whrmaecscd minpdcurrent",
00078     "get_cfg whrmaecscd minpdcurrent",
00079     "set_cfg whrmaecscd pdconfig",
00080     "get_cfg whrmaecscd pdconfig",
00081     "set_cfg whrmaecscd ledconfig",
00082     "get_cfg whrmaecscd ledconfig", 
00083     "send_raw",  // write raw data to I2C (Slave address will be perpended)
00084     "set_cfg accel_sh 0",   // disables sensorhub accel, host accel is used 
00085     "set_cfg accel_sh 1",   // enables sensorhub accel, host accel is not used
00086     "set_cfg whrm conf_level", //sets the conf level coming from the GUI inside the internal flash
00087     "set_cfg whrm hr_expiration", ////sets the expiration dfuration coming from the GUI inside the internal flash
00088 
00089 };
00090 
00091 SSMAX8614XComm::SSMAX8614XComm(USBSerial *USB, SSInterface* ssInterface, DSInterface* dsInterface)
00092     :SensorComm("ppg", true), m_USB(USB), ss_int(ssInterface), ds_int(dsInterface), agc_enabled(true)
00093 {
00094     max8614x_mode1_data_req.data_size = SSMAX8614X_MODE1_DATASIZE;
00095     max8614x_mode1_data_req.callback = callback(this, &SSMAX8614XComm::max8614x_data_rx);
00096 
00097     whrm_mode1_data_req.data_size = SSWHRM_MODE1_DATASIZE;
00098     whrm_mode1_data_req.callback = callback(this, &SSMAX8614XComm::whrm_data_rx_mode1);
00099 
00100     whrm_mode2_data_req.data_size = SSWHRM_MODEX_DATASIZE;
00101     whrm_mode2_data_req.callback = callback(this, &SSMAX8614XComm::whrm_data_rx_mode2);
00102     
00103     accel_mode1_data_req.data_size = SSACCEL_MODE1_DATASIZE;
00104     accel_mode1_data_req.callback = callback(this, &SSMAX8614XComm::accel_data_rx);
00105 
00106     agc_mode1_data_req.data_size = SSAGC_MODE1_DATASIZE;
00107     agc_mode1_data_req.callback = callback(this, &SSMAX8614XComm::agc_data_rx);
00108 
00109     queue_init(&max8614x_queue, max8614x_queue_buf, sizeof(max8614x_mode1_data), sizeof(max8614x_queue_buf));
00110     queue_init(&whrm_queue, whrm_queue_buf, sizeof(whrm_modeX_data), sizeof(whrm_queue_buf));
00111 
00112     queue_init(&accel_output_queue, accel_output_queue_buf, sizeof(accel_mode1_data), sizeof(accel_output_queue_buf));
00113     queue_init(&accel_input_queue, accel_input_queue_buf, sizeof(accel_mode1_data), sizeof(accel_input_queue_buf));
00114 
00115     
00116     sensor_algo_en_dis_.sensorhub_accel = 1;   // enable sensor hub accel by default
00117 
00118     m_bmi160 = 0;
00119 
00120     input_fifo_size = 0;
00121     sensor_data_from_host = false;
00122 }
00123 
00124 void SSMAX8614XComm::stop()
00125 {
00126     status_algo_sensors_st sensor_algo_en_dis_temp;
00127     comm_mutex.lock();
00128     ss_int->disable_irq();
00129     data_report_mode = 0;
00130     sample_count = 0;
00131 
00132     if (sensor_algo_en_dis_.max8614x_enabled) {
00133         ss_int->disable_sensor(SS_SENSORIDX_MAX86140);
00134         queue_reset(&max8614x_queue);
00135     }
00136 
00137     if (sensor_algo_en_dis_.accel_enabled) {
00138         ss_int->disable_sensor(SS_SENSORIDX_ACCEL);
00139         queue_reset(&accel_output_queue);
00140     }
00141 
00142     if (sensor_algo_en_dis_.whrm_enabled) {
00143         ss_int->disable_algo(SS_ALGOIDX_WHRM);
00144         queue_reset(&whrm_queue);
00145     }
00146 
00147     // store a copy of settings
00148     sensor_algo_en_dis_temp.status_vals = sensor_algo_en_dis_.status_vals;
00149     // clear all settings
00150     sensor_algo_en_dis_.status_vals = 0;
00151     //recover settings that need to be maintained
00152     sensor_algo_en_dis_.sensorhub_accel = sensor_algo_en_dis_temp.sensorhub_accel;
00153     ss_int->ss_clear_interrupt_flag();
00154     ss_int->enable_irq();
00155 
00156     if(sensor_algo_en_dis_.sensorhub_accel==0){
00157         m_bmi160->reset();
00158         queue_reset(&accel_input_queue);
00159     }
00160 
00161 
00162     comm_mutex.unlock();
00163     input_fifo_size = 0;
00164     sensor_data_from_host = false;
00165 }
00166 
00167 int SSMAX8614XComm::parse_cal_str(const char *ptr_ch, const char *cmd, uint8_t *cal_data, int cal_data_sz)
00168 {
00169     char ascii_byte[] = { 0, 0, 0 };
00170     const char* sptr = ptr_ch + strlen(cmd);
00171     int found = 0;
00172     int ssfound;
00173     unsigned int val32;
00174 
00175     //Eat spaces after cmd
00176     while (*sptr != ' ' && *sptr != '\0') { sptr++; }
00177     if (*sptr == '\0')
00178         return -1;
00179     sptr++;
00180 
00181     while (found < cal_data_sz) {
00182         if (*sptr == '\0')
00183             break;
00184         ascii_byte[0] = *sptr++;
00185         ascii_byte[1] = *sptr++;
00186         ssfound = sscanf(ascii_byte, "%x", &val32);
00187         if (ssfound != 1)
00188             break;
00189         *(cal_data + found) = (uint8_t)val32;
00190         //pr_err("cal_data[%d]=%d\r\n", found, val32);
00191         found++;
00192     }
00193 
00194     //pr_err("total found: %d\r\n", found);
00195     if (found < cal_data_sz)
00196         return -1;
00197     return 0;
00198 }
00199 
00200 int SSMAX8614XComm::parse_str(const char *ptr_ch, const char *cmd, uint8_t *data, int data_sz)
00201 {
00202     char ascii_byte[] = { 0, 0, 0 };
00203     const char* sptr = ptr_ch + strlen(cmd);
00204     int found = 0;
00205     int ssfound;
00206     unsigned int val32;
00207 
00208     //Eat spaces after cmd
00209     while (*sptr != ' ' && *sptr != '\0') { sptr++; }
00210     if (*sptr == '\0')
00211         return -1;
00212     sptr++;
00213 
00214     while (found < data_sz) {
00215         if (*sptr == '\0')
00216             break;
00217         ascii_byte[0] = *sptr++;
00218         ascii_byte[1] = *sptr++;
00219         ssfound = sscanf(ascii_byte, "%x", &val32);
00220         if (ssfound != 1)
00221             return -1;
00222         *(data + found) = (uint8_t)val32;
00223         pr_err("cal_data[%d]=%d\r\n", found, val32);
00224         found++;
00225     }
00226 
00227     pr_err("total found: %d\r\n", found);
00228     return found;
00229 }
00230 
00231 
00232 void SSMAX8614XComm::setBMI160(BMI160_I2C *pbmi160)
00233 {
00234     if (pbmi160) {
00235         m_bmi160 = pbmi160;
00236         m_bmi160->reset();
00237     }
00238 }
00239 
00240 
00241 int SSMAX8614XComm::get_sensor_xyz(accel_data_t &accel_data) {
00242     int ret = 0;
00243 if(sensor_algo_en_dis_.sensorhub_accel==0){
00244     BMI160::SensorData stacc_data = {0};
00245     if (m_bmi160) {
00246         ret = m_bmi160->getSensorXYZ(stacc_data, BMI160::SENS_2G);
00247         if (ret < 0)
00248             return ret;
00249     }
00250 
00251     accel_data.x = stacc_data.xAxis.scaled;
00252     accel_data.y = stacc_data.yAxis.scaled;
00253     accel_data.z = stacc_data.zAxis.scaled;
00254 
00255     accel_data.x_raw = stacc_data.xAxis.raw;
00256     accel_data.y_raw = stacc_data.yAxis.raw;
00257     accel_data.z_raw = stacc_data.zAxis.raw;
00258 
00259 }
00260 
00261     return ret;
00262 }
00263 
00264 bool SSMAX8614XComm::parse_command(const char* cmd)
00265 {
00266     int ret;
00267     SS_STATUS status;
00268     bool recognizedCmd = false;
00269     int data_len = 0;
00270     char charbuf[768];
00271     addr_val_pair reg_vals[64];
00272 
00273     if (!ss_int) {
00274         pr_err("No SmartSensor Interface defined!");
00275         return false;
00276     }
00277     if (!ds_int) {
00278         pr_err("No DeviceStudio Interface defined!");
00279         return false;
00280     }
00281 
00282     for (int i = 0; i < NUM_CMDS; i++) {
00283         if (starts_with(cmd, cmd_tbl[i])) {
00284             cmd_state_t user_cmd = (cmd_state_t)i;
00285             recognizedCmd = true;
00286 
00287             switch (user_cmd) {
00288                 case set_cfg_accel_sh_dis:
00289                 {
00290                     sensor_algo_en_dis_.sensorhub_accel = 0;
00291                     m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00292 
00293                 } break;
00294                 case set_cfg_accel_sh_en:
00295                 {
00296                     sensor_algo_en_dis_.sensorhub_accel = 1;
00297                     m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00298 
00299                 } break;
00300                 case set_cfg_ppg_conf_level:
00301                 {
00302                     int j=24;
00303                     char temp_buf[4];
00304                     uint32_t PpgConfLevel[2];
00305                     while(cmd[j]!='\0'){
00306                         temp_buf[j-24] = cmd[j];
00307                         j++;
00308                     }
00309                     temp_buf[j-24]='\0';
00310                     sscanf(temp_buf,"%u",&PpgConfLevel[0]);
00311 
00312                     PpgConfLevel[1] = (*(uint32_t *)PPG_EXPIRE_DURATION_FLASH_ADDRESS);
00313 
00314                     if(FLC_Init()!=0){
00315                         m_USB->printf("\r\n%s err=Initializing flash\r\n", cmd);
00316                         break;
00317                     }
00318                     if( FLC_PageErase(PPG_CONF_LEVEL_FLASH_ADDRESS, MXC_V_FLC_ERASE_CODE_PAGE_ERASE, MXC_V_FLC_FLSH_UNLOCK_KEY)!=0 ){
00319                         m_USB->printf("\r\n%s err=Erasing page\r\n", cmd);
00320                         break;
00321                     }
00322                     if(FLC_Write(PPG_CONF_LEVEL_FLASH_ADDRESS,PpgConfLevel,sizeof(PpgConfLevel),MXC_V_FLC_FLSH_UNLOCK_KEY)!=0){
00323                         m_USB->printf("\r\n%s err=Writing flash\r\n", cmd);
00324                         break;
00325                     }
00326                     m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00327 
00328                 } break;
00329                 case set_cfg_ppg_expire_duration:
00330                 {
00331                     int j=27;
00332                     char temp_buf[4];
00333                     uint32_t PpgExpireDuration[2];
00334                     while(cmd[j]!='\0'){
00335                         temp_buf[j-27] = cmd[j];
00336                         j++;
00337                     }
00338                     temp_buf[j-27]='\0';
00339                     sscanf(temp_buf,"%u",&PpgExpireDuration[1]);
00340 
00341                     PpgExpireDuration[0] = (*(uint32_t *)PPG_CONF_LEVEL_FLASH_ADDRESS);
00342 
00343                     if(FLC_Init()!=0){
00344                         m_USB->printf("\r\n%s err=Initializing flash\r\n", cmd);
00345                         break;
00346                     }
00347                     if( FLC_PageErase(PPG_EXPIRE_DURATION_FLASH_ADDRESS, MXC_V_FLC_ERASE_CODE_PAGE_ERASE, MXC_V_FLC_FLSH_UNLOCK_KEY)!=0 ){
00348                         m_USB->printf("\r\n%s err=Erasing page\r\n", cmd);
00349                         break;
00350                     }
00351                     if(FLC_Write(PPG_CONF_LEVEL_FLASH_ADDRESS,PpgExpireDuration,sizeof(PpgExpireDuration),MXC_V_FLC_FLSH_UNLOCK_KEY)!=0){
00352                         m_USB->printf("\r\n%s err=Writing flash\r\n", cmd);
00353                         break;
00354                     }
00355                     m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00356 
00357                 } break;
00358                 case get_format_ppg_0:
00359                 {
00360                     if(AsciiEn)
00361                     {
00362                         if (ds_int->algo_report_mode == 1){
00363                             m_USB->printf("\r\n%s format=smpleCnt,grnCnt,led2,led3,grn2Cnt,led5,led6,"
00364                                     "accelX,accelY,accelZ,hr,hrconf,r,activity err=0\r\n", cmd);
00365                         }
00366                         else { // report mode 2
00367                             m_USB->printf("\r\n%s format=smpleCnt,grnCnt,led2,led3,grn2Cnt,led5,led6,"
00368                                     "accelX,accelY,accelZ,hr,hrconf,r,rconf,activity,walkSteps,runSteps,"
00369                                     "energyKcal,stepCadence,isLedCurrentAdj,adjLedCurrent,isTAdj,adjT,isFAdj,"
00370                                     "adjF,aecSmpAve,aecState,isAECMotion,scdStatus err=0\r\n", cmd);
00371                         }
00372                     }
00373                     else{
00374                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s enc=bin cs=1 format={smpleCnt,16},"
00375                                 "{grnCnt,20},{grn2Cnt,20},{accelX,14,3},{accelY,14,3},"
00376                                 "{accelZ,14,3},{hr,12},{hrconf,8},{r,11,1},{activity,8} err=0\r\n", cmd);
00377                         m_USB->printf(charbuf);
00378                     }
00379                 } break;
00380 
00381                 case read_ppg_0:
00382                 {
00383                     sample_count = 0;
00384 
00385                     status = ss_int->get_input_fifo_size(&input_fifo_size);
00386                     if (status != SS_SUCCESS) {
00387                         data_len = snprintf(charbuf, sizeof(charbuf) - 1,
00388                                 "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00389                         data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00390                                 "FAILED at line %d\n", __LINE__);
00391                         m_USB->printf(charbuf);
00392                         break;
00393                     }
00394 
00395                     status = ss_int->set_data_type(SS_DATATYPE_BOTH, false);
00396                     if (status != SS_SUCCESS) {
00397                         data_len = snprintf(charbuf, sizeof(charbuf) - 1,
00398                                 "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00399                         data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00400                                 "FAILED at line %d, set DATA_TYPE\n, ", __LINE__);
00401 #ifdef FORCE_RESET_WHEN_FAILED
00402                             ret = ss_int->reset();
00403                             data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00404                                     "\r\nReset!\r\n");
00405 #endif
00406                         m_USB->printf(charbuf);
00407                         break;
00408                     }
00409 
00410                     status = ss_int->set_fifo_thresh(5);
00411                     if (status != SS_SUCCESS) {
00412                         data_len = snprintf(charbuf, sizeof(charbuf) - 1,
00413                                 "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00414                         data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00415                                 "FAILED at line %d, set thresh\n", __LINE__);
00416 #ifdef FORCE_RESET_WHEN_FAILED
00417                             ret = ss_int->reset();
00418                             data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00419                                     "\r\nReset!\r\n");
00420 #endif
00421                         m_USB->printf(charbuf);
00422                         break;
00423                     }
00424 
00425 
00426                     if (status != SS_SUCCESS) {
00427                         data_len = snprintf(charbuf, sizeof(charbuf) - 1,
00428                                 "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00429                         data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00430                                 "FAILED at line %d - agc_enabled: %d\n", __LINE__, agc_enabled);
00431                         ss_int->enable_irq();
00432 
00433 #ifdef FORCE_RESET_WHEN_FAILED
00434                             ret = ss_int->reset();
00435                             data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00436                                     "\r\nReset!\r\n");
00437 #endif
00438                         m_USB->printf(charbuf);
00439                         break;
00440                     }
00441 
00442                     ss_int->disable_irq();
00443 
00444                     status = ss_int->enable_sensor(SS_SENSORIDX_MAX86140, 1, &max8614x_mode1_data_req);
00445                     if (status != SS_SUCCESS) {
00446                         data_len = snprintf(charbuf, sizeof(charbuf) - 1,
00447                                 "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00448                         data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00449                                 "FAILED at line %d, enable max86140\n", __LINE__);
00450                         ss_int->enable_irq();
00451     #ifdef FORCE_RESET_WHEN_FAILED
00452                         ret = ss_int->reset();
00453                         data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00454                                 "\r\nReset!\r\n");
00455     #endif
00456                         m_USB->printf(charbuf);
00457                         break;
00458                     }
00459                     sensor_algo_en_dis_.max8614x_enabled = 1;
00460 
00461 
00462 
00463                     if (sensor_algo_en_dis_.sensorhub_accel) {
00464                         status = ss_int->enable_sensor(SS_SENSORIDX_ACCEL, 1, &accel_mode1_data_req, SH_INPUT_DATA_DIRECT_SENSOR);
00465                         if (status != SS_SUCCESS) {
00466                             data_len = snprintf(charbuf, sizeof(charbuf) - 1,
00467                                 "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00468                             data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00469                                 "FAILED at line %d\n", __LINE__);
00470                             ss_int->enable_irq();
00471     #ifdef FORCE_RESET_WHEN_FAILED
00472                             ret = ss_int->reset();
00473                             data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00474                                 "\r\nReset!\r\n");
00475     #endif
00476                             m_USB->printf(charbuf);
00477                             break;
00478                         }
00479                         sensor_algo_en_dis_.accel_enabled = 1;
00480                     }
00481                     else {
00482                         m_bmi160->BMI160_DefaultInitalize();
00483                         if (m_bmi160->setSampleRate(BMI160_SAMPLE_RATE) != 0) {
00484                             pr_err("Unable to set BMI160's sample rate\n");
00485                             data_len = snprintf(charbuf , sizeof(charbuf) - 1,
00486                                 "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00487                             data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00488                                 "FAILED at line %d\n", __LINE__);
00489                             ss_int->enable_irq();
00490     #ifdef FORCE_RESET_WHEN_FAILED
00491                             ret = ss_int->reset();
00492                             data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00493                                 "\r\nReset!\r\n");
00494     #endif
00495                             m_USB->printf(charbuf);
00496                             break;
00497                         }
00498 
00499                         ret = m_bmi160->enable_data_ready_interrupt();
00500                         if(ret != E_SUCCESS){
00501                             pr_err("Unable to enable BMI160 Interrupt, ret: %d\n", ret);
00502                             break;
00503                         }
00504 
00505 
00506 
00507                         status = ss_int->enable_sensor(SS_SENSORIDX_ACCEL, 1, &accel_mode1_data_req, SH_INPUT_DATA_FROM_HOST);
00508                         if (status != SS_SUCCESS) {
00509                             data_len = snprintf(charbuf, sizeof(charbuf) - 1,
00510                                 "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00511                             data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00512                                 "FAILED at line %d\n", __LINE__);
00513                             ss_int->enable_irq();
00514     #ifdef FORCE_RESET_WHEN_FAILED
00515                             ret = ss_int->reset();
00516                             data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00517                                 "\r\nReset!\r\n");
00518     #endif
00519                             m_USB->printf(charbuf);
00520                             break;
00521                         }
00522                         sensor_data_from_host = true;
00523                         sensor_algo_en_dis_.accel_enabled = 1;
00524                     }
00525 
00526 
00527                     if (ds_int->algo_report_mode == 2)
00528                         status = ss_int->enable_algo(SS_ALGOIDX_WHRM, 2, &whrm_mode2_data_req);
00529                     else // default is mode 1
00530                         status = ss_int->enable_algo(SS_ALGOIDX_WHRM, 1, &whrm_mode1_data_req);
00531                     if (status != SS_SUCCESS) {
00532                         data_len = snprintf(charbuf, sizeof(charbuf) - 1,
00533                                 "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00534                         data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00535                                 "FAILED at line %d, enable whrm\n", __LINE__);
00536                         ss_int->enable_irq();
00537     #ifdef FORCE_RESET_WHEN_FAILED
00538                         ret = ss_int->reset();
00539                         data_len += snprintf(charbuf+data_len, sizeof(charbuf)- data_len - 1,
00540                                 "\r\nReset!\r\n");
00541     #endif
00542                         m_USB->printf(charbuf);
00543                         break;
00544                     }
00545                     sensor_algo_en_dis_.whrm_enabled = 1;
00546 
00547 
00548                     comm_mutex.lock();
00549                     data_report_mode = read_ppg_0;
00550                     comm_mutex.unlock();
00551                     data_len = snprintf(charbuf, sizeof(charbuf) - 1,
00552                             "\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00553                     m_USB->printf(charbuf);
00554                     ss_int->enable_irq();
00555                 } break;
00556 
00557                 case get_reg_ppg:
00558                 {
00559                     uint8_t addr;
00560                     uint32_t val;
00561 
00562                     ret = parse_get_reg_cmd(cmd, sensor_type, &addr);
00563                     if (!ret) {
00564                         status = ss_int->get_reg(SS_SENSORIDX_MAX86140, addr, &val);
00565                         if (status == SS_SUCCESS) {
00566                             data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s reg_val=%02X err=%d\r\n", cmd, (uint8_t)val, COMM_SUCCESS);
00567                             m_USB->printf(charbuf);
00568                         } else {
00569                             data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00570                             m_USB->printf(charbuf);
00571                         }
00572                     } else {
00573                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00574                         m_USB->printf(charbuf);
00575                     }
00576 
00577                 } break;
00578 
00579                 case set_reg_ppg:
00580                 {
00581                     uint8_t addr;
00582                     uint8_t val;
00583 
00584                     ret = parse_set_reg_cmd(cmd, sensor_type, &addr, &val);
00585                     if (!ret) {
00586                         status = ss_int->set_reg(SS_SENSORIDX_MAX86140, addr, val, SSMAX8614X_REG_SIZE);
00587                         if (status == SS_SUCCESS) {
00588                             data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00589                             m_USB->printf(charbuf);
00590                         } else {
00591                             data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00592                             m_USB->printf(charbuf);
00593                         }
00594                     } else {
00595                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00596                         m_USB->printf(charbuf);
00597                     }
00598 
00599                 } break;
00600 
00601                 case dump_reg_ppg:
00602                 {
00603                     int num_regs;
00604                     status = ss_int->dump_reg(SS_SENSORIDX_MAX86140, &reg_vals[0], ARRAY_SIZE(reg_vals), &num_regs);
00605                     if (status == SS_SUCCESS) {
00606                         bool comma = false;
00607                         data_len += snprintf(charbuf + data_len, sizeof(charbuf) - data_len - 1, "\r\n%s reg_val=", cmd);
00608                         for (int reg = 0; reg < num_regs; reg++) {
00609                             if (comma) {
00610                                 data_len += snprintf(charbuf + data_len, sizeof(charbuf) - data_len - 1, ",");
00611                             }
00612                             data_len += snprintf(charbuf + data_len, sizeof(charbuf) - data_len - 1,
00613                                             "{%X,%lX}", reg_vals[reg].addr, reg_vals[reg].val);
00614                             comma = true;
00615                         }
00616                         data_len += snprintf(charbuf + data_len, sizeof(charbuf) - data_len - 1, " err=%d\r\n", COMM_SUCCESS);
00617                         m_USB->printf(charbuf);
00618 
00619                     } else {
00620                         data_len += snprintf(charbuf + data_len, sizeof(charbuf) - data_len - 1,
00621                                 "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00622                         m_USB->printf(charbuf);
00623                     }
00624 
00625                 } break;
00626 
00627                 case set_agc_en:
00628                 {
00629                     agc_enabled = true;
00630                     status = ss_int->enable_algo(SS_ALGOIDX_AGC, 1, &agc_mode1_data_req);
00631                     sensor_algo_en_dis_.agc_enabled = 1;
00632                     m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00633                 } break;
00634 
00635                 case set_agc_dis:
00636                 {
00637                     agc_enabled = false;
00638                     status = ss_int->disable_algo(SS_ALGOIDX_AGC);
00639                     sensor_algo_en_dis_.agc_enabled = 0;
00640                     m_USB->printf("\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00641                 } break;
00642 
00643                 case self_test_ppg_os58:
00644                 {
00645                     ret = selftest_max8614x();
00646                     data_len += snprintf(charbuf + data_len, sizeof(charbuf) - data_len - 1,
00647                             "%s selftest_max8614x: err=<%d>\r\n", cmd, ret);
00648                     m_USB->printf(charbuf);
00649                 } break;
00650 
00651                 case self_test_ppg_acc:
00652                 {
00653                     ret = selftest_accelerometer();
00654                     data_len += snprintf(charbuf + data_len, sizeof(charbuf) - data_len - 1,
00655                             "%s selftest_accelerometer: err=<%d>\r\n", cmd, ret);
00656                     m_USB->printf(charbuf);
00657                 } break;
00658 
00659                 //--------- WHRM_AEC_SCD AEC ENABLE
00660                 case set_cfg_whrmaecscd_aecenable:
00661                 {
00662                     uint8_t val[1];
00663                     ret = (parse_cmd_data(cmd, cmd_tbl[i], &val[0], 1, true) != 1);
00664                     if (ret) {
00665                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00666                         m_USB->printf(charbuf);
00667                         break;
00668                     }
00669 
00670                     uint8_t Temp[1] = { (uint8_t)(val[0]) };
00671 
00672                     status = ss_int->set_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_AEC_ENABLE, &Temp[0], 1);
00673                     if (status == SS_SUCCESS)
00674                     {
00675                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00676                         m_USB->printf(charbuf);
00677                     }
00678                     else
00679                     {
00680                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00681                         m_USB->printf(charbuf);
00682                     }
00683 
00684                 } break;
00685 
00686                 case get_cfg_whrmaecscd_aecenable:
00687                 {
00688                     uint8_t rxBuff[1+1];  // first byte is status
00689                     char outstr[2*sizeof(rxBuff)];
00690                     int str_idx = 0;
00691                     uint8_t *Temp = &rxBuff[1];
00692                     uint8_t val[1];
00693 
00694                     status = ss_int->get_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_AEC_ENABLE, &rxBuff[0], sizeof(rxBuff));
00695                     for (int i = 0; i < sizeof(rxBuff)-1; i++)
00696                         str_idx += snprintf(outstr + str_idx, sizeof(outstr) - str_idx - 1, "%02X", Temp[i]);
00697 
00698                     data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s value=%s err=%d\r\n", cmd, outstr, COMM_SUCCESS);
00699                     m_USB->printf(charbuf);
00700 
00701                 } break;
00702 
00703                 //--------- WHRM_AEC_SCD SCD ENABLE
00704                 case set_cfg_whrmaecscd_scdenable:
00705                 {
00706                     uint8_t val[1];
00707                     ret = (parse_cmd_data(cmd, cmd_tbl[i], &val[0], 1, true) != 1);
00708                     if (ret) {
00709                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00710                         m_USB->printf(charbuf);
00711                         break;
00712                     }
00713 
00714                     uint8_t Temp[1] = { (uint8_t)(val[0]) };
00715 
00716                     status = ss_int->set_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_SCD_ENABLE, &Temp[0], 1);
00717                     if (status == SS_SUCCESS)
00718                     {
00719                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00720                         m_USB->printf(charbuf);
00721                     }
00722                     else
00723                     {
00724                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00725                         m_USB->printf(charbuf);
00726                     }
00727 
00728                 } break;
00729 
00730                 case get_cfg_whrmaecscd_scdenable:
00731                 {
00732                     uint8_t rxBuff[1+1];  // first byte is status
00733                     char outstr[2*sizeof(rxBuff)];
00734                     int str_idx = 0;
00735                     uint8_t *Temp = &rxBuff[1];
00736                     uint8_t val[1];
00737 
00738                     status = ss_int->get_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_SCD_ENABLE, &rxBuff[0], sizeof(rxBuff));
00739                     for (int i = 0; i < sizeof(rxBuff)-1; i++)
00740                         str_idx += snprintf(outstr + str_idx, sizeof(outstr) - str_idx - 1, "%02X", Temp[i]);
00741 
00742                     data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s value=%s err=%d\r\n", cmd, outstr, COMM_SUCCESS);
00743                     m_USB->printf(charbuf);
00744 
00745                 } break;
00746 
00747                 //--------- WHRM_AEC_SCD ADJ TARGET PD PERIOD
00748                 case set_cfg_whrmaecscd_adjpdperiod:
00749                 {
00750                     uint16_t val[1];
00751                     ret = (parse_cmd_data(cmd, cmd_tbl[i], &val[0], 1, true) != 1);
00752                     if (ret) {
00753                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00754                         m_USB->printf(charbuf);
00755                         break;
00756                     }
00757 
00758                     uint8_t Temp[2] = { (uint8_t)((val[0] >> (1*8)) & 0xFF),  (uint8_t)((val[0] >> (0*8)) & 0xFF)};
00759 
00760                     status = ss_int->set_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_ADJ_TARGET_PD_CURRENT_PERIOD, &Temp[0], 2);
00761                     if (status == SS_SUCCESS)
00762                     {
00763                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00764                         m_USB->printf(charbuf);
00765                     }
00766                     else
00767                     {
00768                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00769                         m_USB->printf(charbuf);
00770                     }
00771 
00772                 } break;
00773 
00774                 case get_cfg_whrmaecscd_adjpdperiod:
00775                 {
00776                     uint8_t rxBuff[2+1];  // first byte is status
00777                     char outstr[2*sizeof(rxBuff)];
00778                     int str_idx = 0;
00779                     uint8_t *Temp = &rxBuff[1];
00780                     uint8_t val[1];
00781 
00782                     status = ss_int->get_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_ADJ_TARGET_PD_CURRENT_PERIOD, &rxBuff[0], sizeof(rxBuff));
00783                     for (int i = 0; i < sizeof(rxBuff)-1; i++)
00784                         str_idx += snprintf(outstr + str_idx, sizeof(outstr) - str_idx - 1, "%02X", Temp[i]);
00785 
00786                     data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s value=%s err=%d\r\n", cmd, outstr, COMM_SUCCESS);
00787                     m_USB->printf(charbuf);
00788 
00789                 } break;
00790 
00791                 //--------- WHRM_AEC_SCD DEBOUNCE WINDOW
00792                 case set_cfg_whrmaecscd_debouncewin:
00793                 {
00794                     uint16_t val[1];
00795                     ret = (parse_cmd_data(cmd, cmd_tbl[i], &val[0], 1, true) != 1);
00796                     if (ret) {
00797                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00798                         m_USB->printf(charbuf);
00799                         break;
00800                     }
00801 
00802                     uint8_t Temp[2] = { (uint8_t)((val[0] >> (1*8)) & 0xFF),  (uint8_t)((val[0] >> (0*8)) & 0xFF)};
00803 
00804                     status = ss_int->set_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_SCD_DEBOUNCE_WINDOW, &Temp[0], 2);
00805                     if (status == SS_SUCCESS)
00806                     {
00807                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00808                         m_USB->printf(charbuf);
00809                     }
00810                     else
00811                     {
00812                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00813                         m_USB->printf(charbuf);
00814                     }
00815 
00816                 } break;
00817 
00818                 case get_cfg_whrmaecscd_debouncewin:
00819                 {
00820                     uint8_t rxBuff[2+1];  // first byte is status
00821                     char outstr[2*sizeof(rxBuff)];
00822                     int str_idx = 0;
00823                     uint8_t *Temp = &rxBuff[1];
00824                     uint8_t val[1];
00825 
00826                     status = ss_int->get_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_SCD_DEBOUNCE_WINDOW, &rxBuff[0], sizeof(rxBuff));
00827                     for (int i = 0; i < sizeof(rxBuff)-1; i++)
00828                         str_idx += snprintf(outstr + str_idx, sizeof(outstr) - str_idx - 1, "%02X", Temp[i]);
00829 
00830                     data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s value=%s err=%d\r\n", cmd, outstr, COMM_SUCCESS);
00831                     m_USB->printf(charbuf);
00832 
00833                 } break;
00834 
00835                 //--------- WHRM_AEC_SCD MOTION MAG THRESHOLD
00836                 case set_cfg_whrmaecscd_motionthreshold:
00837                 {
00838                     uint16_t val[1];
00839                     ret = (parse_cmd_data(cmd, cmd_tbl[i], &val[0], 1, true) != 1);
00840                     if (ret) {
00841                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00842                         m_USB->printf(charbuf);
00843                         break;
00844                     }
00845 
00846                     uint8_t Temp[2] = { (uint8_t)((val[0] >> (1*8)) & 0xFF),  (uint8_t)((val[0] >> (0*8)) & 0xFF)};
00847 
00848                     status = ss_int->set_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_MOTION_MAG_THRESHOLD, &Temp[0], 2);
00849                     if (status == SS_SUCCESS)
00850                     {
00851                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00852                         m_USB->printf(charbuf);
00853                     }
00854                     else
00855                     {
00856                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00857                         m_USB->printf(charbuf);
00858                     }
00859 
00860                 } break;
00861 
00862                 case get_cfg_whrmaecscd_motionthreshold:
00863                 {
00864                     uint8_t rxBuff[2+1];  // first byte is status
00865                     char outstr[2*sizeof(rxBuff)];
00866                     int str_idx = 0;
00867                     uint8_t *Temp = &rxBuff[1];
00868                     uint8_t val[1];
00869 
00870                     status = ss_int->get_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_MOTION_MAG_THRESHOLD, &rxBuff[0], sizeof(rxBuff));
00871                     for (int i = 0; i < sizeof(rxBuff)-1; i++)
00872                         str_idx += snprintf(outstr + str_idx, sizeof(outstr) - str_idx - 1, "%02X", Temp[i]);
00873 
00874                     data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s value=%s err=%d\r\n", cmd, outstr, COMM_SUCCESS);
00875                     m_USB->printf(charbuf);
00876 
00877                 } break;
00878 
00879                 //--------- WHRM_AEC_SCD MIN PD CURRENT
00880                 case set_cfg_whrmaecscd_minpdcurrent:
00881                 {
00882                     uint16_t val[1];
00883                     ret = (parse_cmd_data(cmd, cmd_tbl[i], &val[0], 1, true) != 1);
00884                     if (ret) {
00885                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00886                         m_USB->printf(charbuf);
00887                         break;
00888                     }
00889 
00890                     uint8_t Temp[2] = { (uint8_t)((val[0] >> (1*8)) & 0xFF),  (uint8_t)((val[0] >> (0*8)) & 0xFF)};
00891 
00892                     status = ss_int->set_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_MIN_PD_CURRENT, &Temp[0], 2);
00893                     if (status == SS_SUCCESS)
00894                     {
00895                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00896                         m_USB->printf(charbuf);
00897                     }
00898                     else
00899                     {
00900                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00901                         m_USB->printf(charbuf);
00902                     }
00903 
00904                 } break;
00905 
00906                 case get_cfg_whrmaecscd_minpdcurrent:
00907                 {
00908                     uint8_t rxBuff[2+1];  // first byte is status
00909                     char outstr[2*sizeof(rxBuff)];
00910                     int str_idx = 0;
00911                     uint8_t *Temp = &rxBuff[1];
00912                     uint8_t val[1];
00913 
00914                     status = ss_int->get_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_MIN_PD_CURRENT, &rxBuff[0], sizeof(rxBuff));
00915                     for (int i = 0; i < sizeof(rxBuff)-1; i++)
00916                         str_idx += snprintf(outstr + str_idx, sizeof(outstr) - str_idx - 1, "%02X", Temp[i]);
00917 
00918                     data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s value=%s err=%d\r\n", cmd, outstr, COMM_SUCCESS);
00919                     m_USB->printf(charbuf);
00920 
00921                 } break;
00922 
00923                 //--------- WHRM_AEC_SCD PD CONFIG
00924                 case set_cfg_whrmaecscd_pdconfig:
00925                 {
00926                     uint8_t val[1];
00927                     ret = (parse_cmd_data(cmd, cmd_tbl[i], &val[0], 1, true) != 1);
00928                     if (ret) {
00929                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00930                         m_USB->printf(charbuf);
00931                         break;
00932                     }
00933 
00934                     uint8_t Temp[1] = { (uint8_t)(val[0]) };
00935 
00936                     status = ss_int->set_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_PD_CONFIG, &Temp[0], 1);
00937                     if (status == SS_SUCCESS)
00938                     {
00939                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00940                         m_USB->printf(charbuf);
00941                     }
00942                     else
00943                     {
00944                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00945                         m_USB->printf(charbuf);
00946                     }
00947 
00948                 } break;
00949 
00950                 case get_cfg_whrmaecscd_pdconfig:
00951                 {
00952                     uint8_t rxBuff[1+1];  // first byte is status
00953                     char outstr[2*sizeof(rxBuff)];
00954                     int str_idx = 0;
00955                     uint8_t *Temp = &rxBuff[1];
00956                     uint8_t val[1];
00957 
00958                     status = ss_int->get_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_PD_CONFIG, &rxBuff[0], sizeof(rxBuff));
00959                     for (int i = 0; i < sizeof(rxBuff)-1; i++)
00960                         str_idx += snprintf(outstr + str_idx, sizeof(outstr) - str_idx - 1, "%02X", Temp[i]);
00961 
00962                     data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s value=%s err=%d\r\n", cmd, outstr, COMM_SUCCESS);
00963                     m_USB->printf(charbuf);
00964 
00965                 } break;
00966 
00967                 //--------- WHRM_AEC_SCD LED CONFIG
00968                 case set_cfg_whrmaecscd_ledconfig:
00969                 {
00970                     uint8_t val[1];
00971                     ret = (parse_cmd_data(cmd, cmd_tbl[i], &val[0], 1, true) != 1);
00972                     if (ret) {
00973                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_INVALID_PARAM);
00974                         m_USB->printf(charbuf);
00975                         break;
00976                     }
00977 
00978                     uint8_t Temp[1] = { (uint8_t)(val[0]) };
00979 
00980                     status = ss_int->set_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_LED_CONFIG, &Temp[0], 1);
00981                     if (status == SS_SUCCESS)
00982                     {
00983                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
00984                         m_USB->printf(charbuf);
00985                     }
00986                     else
00987                     {
00988                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
00989                         m_USB->printf(charbuf);
00990                     }
00991 
00992                 } break;
00993 
00994                 case get_cfg_whrmaecscd_ledconfig:
00995                 {
00996                     uint8_t rxBuff[1+1];  // first byte is status
00997                     char outstr[2*sizeof(rxBuff)];
00998                     int str_idx = 0;
00999                     uint8_t *Temp = &rxBuff[1];
01000                     uint8_t val[1];
01001 
01002                     status = ss_int->get_algo_cfg(SS_ALGOIDX_WHRM, SS_CFGIDX_WHRM_LED_CONFIG, &rxBuff[0], sizeof(rxBuff));
01003                     for (int i = 0; i < sizeof(rxBuff)-1; i++)
01004                         str_idx += snprintf(outstr + str_idx, sizeof(outstr) - str_idx - 1, "%02X", Temp[i]);
01005 
01006                     data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s value=%s err=%d\r\n", cmd, outstr, COMM_SUCCESS);
01007                     m_USB->printf(charbuf);
01008 
01009                 } break;
01010 
01011                 //---------  SEND RAW
01012                 case send_raw:
01013                 {
01014                     int size=0;
01015                     uint8_t data[256];  // max size of command
01016 
01017                     size = parse_str(cmd, cmd_tbl[i], data, sizeof(data));
01018                     status = ss_int->send_raw(data, size);
01019 
01020                     if (status == SS_SUCCESS)
01021                     {
01022                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_SUCCESS);
01023                         m_USB->printf(charbuf);
01024                     }
01025                     else
01026                     {
01027                         data_len = snprintf(charbuf, sizeof(charbuf), "\r\n%s err=%d\r\n", cmd, COMM_GENERAL_ERROR);
01028                         m_USB->printf(charbuf);
01029                     }
01030 
01031                 } break;
01032                 //--------------------------------------------------------
01033 
01034                 default:
01035                 {
01036                     mxm_assert_msg(false, "Invalid switch case!");
01037                 } break;
01038 
01039             }
01040             
01041 
01042     if (BLE::Instance().gap().getState().connected) {
01043         BLE_Icarus_AddtoQueue((uint8_t *)charbuf, (int32_t)sizeof(charbuf), data_len);
01044     }
01045 
01046 
01047             break;
01048 
01049         }
01050     }
01051 
01052     return recognizedCmd;
01053 }
01054 
01055 void SSMAX8614XComm::max8614x_data_rx(uint8_t* data_ptr)
01056 {
01057     max8614x_mode1_data sample;
01058     sample.led1 = (data_ptr[0] << 16) | (data_ptr[1] << 8) | data_ptr[2];
01059     sample.led2 = (data_ptr[3] << 16) | (data_ptr[4] << 8) | data_ptr[5];
01060     sample.led3 = (data_ptr[6] << 16) | (data_ptr[7] << 8) | data_ptr[8];
01061     sample.led4 = (data_ptr[9] << 16) | (data_ptr[10] << 8) | data_ptr[11];
01062     sample.led5 = (data_ptr[12] << 16) | (data_ptr[13] << 8) | data_ptr[14];
01063     sample.led6 = (data_ptr[15] << 16) | (data_ptr[16] << 8) | data_ptr[17];
01064 
01065     pr_info("led1=%.6X led2=%.6X led3=%.6X led4=%.6X led5=%.6X led6=%.6X\r\n",
01066             sample.led1, sample.led2, sample.led3, sample.led4, sample.led5, sample.led6);
01067 
01068     enqueue(&max8614x_queue, &sample);
01069 }
01070 
01071 void SSMAX8614XComm::whrm_data_rx_mode1(uint8_t* data_ptr)
01072 {
01073     whrm_modeX_data sample;
01074 
01075     sample.hr = (data_ptr[0] << 8) | data_ptr[1];
01076     sample.hr_conf = data_ptr[2];
01077     sample.rr = (data_ptr[3] << 8) | data_ptr[4];
01078     sample.activity_class = data_ptr[5];
01079     //m_USB->printf("\r\n Md1- hr:%d  conf:%d  rr:%d  act:%d\r\n", sample.hr,sample.hr_conf,sample.rr,sample.activity_class );
01080     enqueue(&whrm_queue, &sample);
01081     pr_info("hr=%.1f conf=%d rr=%.1f rr_conf=%d status=%d\r\n", (float)sample.hr / 10.0, sample.hr_conf, (float)sample.rr/10, sample.rr_conf,sample.activity_class);    
01082 }
01083 
01084 void SSMAX8614XComm::whrm_data_rx_mode2(uint8_t* data_ptr)
01085 {
01086     whrm_modeX_data sample;
01087 
01088     sample.hr = (data_ptr[0] << 8) | data_ptr[1];
01089     sample.hr_conf = data_ptr[2];
01090     sample.rr = (data_ptr[3] << 8) | data_ptr[4];
01091     sample.activity_class = data_ptr[5];
01092     sample.rr_conf = data_ptr[6];   
01093     sample.walk_steps = (data_ptr[7] << 24) | (data_ptr[8] << 16) |(data_ptr[9] << 8) | data_ptr[10];
01094     sample.run_steps = (data_ptr[11] << 24) | (data_ptr[12] << 16) |(data_ptr[13] << 8) | data_ptr[14];         
01095     sample.kcal = (data_ptr[15] << 24) | (data_ptr[16] << 16) |(data_ptr[17] << 8) | data_ptr[18];          
01096     sample.cadence = (data_ptr[19] << 24) | (data_ptr[20] << 16) |(data_ptr[21] << 8) | data_ptr[22];           
01097     sample.is_led_cur_adj = data_ptr[23];
01098     sample.adj_led_cur = (data_ptr[24] << 8) | data_ptr[25];
01099     sample.is_t_int_cur_adj = data_ptr[26];
01100     sample.adj_t_int_cur = (data_ptr[27] << 8) | data_ptr[28];
01101     sample.is_f_smp_adj = data_ptr[29];
01102     sample.adj_f_smp = data_ptr[30];        
01103     sample.smp_ave = data_ptr[31];
01104     sample.state = data_ptr[32];
01105     sample.is_high_motion = data_ptr[33];
01106     sample.status = data_ptr[34];
01107 
01108     //m_USB->printf("\r\nMd2- hr:%d  conf:%d  rr:%d  act:%d\r\n", sample.hr,sample.hr_conf,sample.rr,sample.activity_class );
01109     enqueue(&whrm_queue, &sample);
01110     pr_info("hr=%.1f conf=%d rr=%.1f rr_conf=%d status=%d\r\n", (float)sample.hr / 10.0, sample.hr_conf, (float)sample.rr/10, sample.rr_conf,sample.activity_class);    
01111 }
01112 
01113 
01114 void SSMAX8614XComm::accel_data_rx(uint8_t* data_ptr)
01115 {
01116     //See API doc for data format
01117     accel_mode1_data sample;
01118     sample.x = (data_ptr[0] << 8) | data_ptr[1];
01119     sample.y = (data_ptr[2] << 8) | data_ptr[3];
01120     sample.z = (data_ptr[4] << 8) | data_ptr[5];
01121 
01122     enqueue(&accel_input_queue, &sample);
01123 }
01124 
01125 void SSMAX8614XComm::agc_data_rx(uint8_t* data_ptr)
01126 {
01127     //NOP: AGC does not collect data
01128 }
01129 
01130 int SSMAX8614XComm::data_report_execute(char* buf, int size)
01131 {
01132     uint8_t tmp_report_mode;
01133     max8614x_mode1_data max8614x_sample = { 0 };
01134     whrm_modeX_data whrm_sample_modeX = { 0 };
01135     //wspo2_modeX_data wspo2_sample_modeX = { 0 };
01136     accel_mode1_data accel_sample = { 0 };
01137 
01138 
01139     accel_data_t accel_data = {0};
01140 
01141     int16_t data_len = 0;
01142 
01143     static uint8_t isReportEnabled = 0;
01144 
01145     if (size <= 0)
01146     {
01147         m_USB->printf("\r\nError: RepSize = %d\r\n", size);
01148         return 0;
01149     }
01150 
01151     if (isReportEnabled != is_enabled())
01152     {
01153         isReportEnabled = is_enabled();
01154         m_USB->printf("\r\nRep Enable = %d \r\n",isReportEnabled);
01155     }
01156 
01157     if (!is_enabled())
01158     {
01159         return 0;
01160     }
01161 
01162     ss_int->ss_execute_once();
01163 
01164     comm_mutex.lock();
01165     tmp_report_mode = data_report_mode;
01166     comm_mutex.unlock();
01167 
01168 
01169     while (sensor_data_from_host) {
01170         accel_data_t accel_data = {0};
01171 
01172         int ret;
01173         ret = get_sensor_xyz(accel_data);
01174         if (ret < 0)
01175             break;
01176 
01177         accel_mode1_data acc_sample;
01178         acc_sample.x = (int16_t)(accel_data.x*1000);
01179         acc_sample.y = (int16_t)(accel_data.y*1000);
01180         acc_sample.z = (int16_t)(accel_data.z*1000);
01181 
01182         if (enqueue(&accel_output_queue, &acc_sample) < 0)
01183             pr_err("Thrown an accel sample\n");
01184 
01185         if (queue_len(&accel_output_queue) < MAX_NUM_WR_ACC_SAMPLES)
01186             break;
01187 
01188         int num_bytes = 0;
01189         SS_STATUS status = ss_int->get_num_bytes_in_input_fifo(&num_bytes);
01190         if (status != SS_SUCCESS) {
01191             pr_err("Unable to read num bytes in input fifo\r\n");
01192             break;
01193         }
01194 
01195         int num_tx = input_fifo_size - num_bytes;
01196         mxm_assert_msg((num_tx >= 0), "num_tx can't be negative");
01197         if (num_tx <= 0)
01198             break;
01199 
01200         int num_samples = num_tx / sizeof(accel_mode1_data);
01201         num_samples = min(num_samples, MAX_NUM_WR_ACC_SAMPLES);
01202         num_tx = num_samples * sizeof(accel_mode1_data);
01203 
01204         if (num_samples == 0) {
01205             pr_err("Input FIFO is Full\n");
01206             break;
01207         }
01208 
01209         accel_mode1_data peek_buf[num_samples];
01210         ret = queue_front_n(&accel_output_queue, peek_buf, num_samples, num_samples * sizeof(accel_mode1_data));
01211         if (ret < 0)
01212             mxm_assert_msg((num_tx >= 0), "Unable to peek samples from accel queue. Something is wrong.");
01213 
01214         uint8_t tx_buf[2 + num_tx]; /* 2 bytes were allocated for commands */
01215         for (int i = 2, j = 0; j < num_samples; i+= sizeof(accel_mode1_data), j++) {
01216             acc_sample = peek_buf[j];
01217 
01218             tx_buf[i] = acc_sample.x;
01219             tx_buf[i + 1] = acc_sample.x >> 8;
01220 
01221             tx_buf[i + 2] = acc_sample.y;
01222             tx_buf[i + 3] = acc_sample.y >> 8;
01223 
01224             tx_buf[i + 4] = acc_sample.z;
01225             tx_buf[i + 5] = acc_sample.z >> 8;
01226 
01227         }
01228 
01229         int num_wr_bytes = 0;
01230         int nb_expected = num_tx;
01231         status = ss_int->feed_to_input_fifo(tx_buf, num_tx + 2, &num_wr_bytes);
01232         if (status != SS_SUCCESS) {
01233             pr_err("Unable to write accel data. num_tx: %d. status: %d\r\n", num_tx, status);
01234             break;
01235         }
01236 
01237         int num_written_samples = num_wr_bytes / sizeof(accel_mode1_data);
01238         if (num_written_samples == 0)
01239             break;
01240 
01241         ret = queue_pop_n(&accel_output_queue, num_written_samples);
01242         if (ret < 0)
01243             mxm_assert_msg((num_tx >= 0), "Unable to popped samples out from accel queue. Something is wrong.");
01244 
01245         break;
01246     }
01247 
01248 
01249     switch (tmp_report_mode) {
01250         case read_ppg_0:
01251         {
01252             if (1
01253 
01254 
01255                 && (queue_len(&max8614x_queue) > 0 && sensor_algo_en_dis_.max8614x_enabled)
01256 
01257 
01258 
01259                 && (queue_len(&accel_input_queue) > 0 && sensor_algo_en_dis_.accel_enabled)
01260 
01261 
01262 
01263                 && (queue_len(&whrm_queue) > 0 && sensor_algo_en_dis_.whrm_enabled)
01264 
01265                 )
01266             {
01267 
01268                 if(sensor_algo_en_dis_.max8614x_enabled)
01269                     dequeue(&max8614x_queue, &max8614x_sample);
01270 
01271 
01272 
01273                 if(sensor_algo_en_dis_.accel_enabled)
01274                     dequeue(&accel_input_queue, &accel_sample);
01275 
01276 
01277 
01278                 if(sensor_algo_en_dis_.whrm_enabled){
01279                     dequeue(&whrm_queue, &whrm_sample_modeX);
01280                     instant_hr = whrm_sample_modeX.hr * 0.1;
01281                     instant_hr_conf = whrm_sample_modeX.hr_conf;
01282                     instant_hr_activityClass = whrm_sample_modeX.activity_class;
01283                 }
01284 
01285 
01286                 if (AsciiEn) {
01287                     // mode 2 only for ASCII
01288                     if (ds_int->algo_report_mode == 2){
01289                         data_len = snprintf(buf, size - 1, 
01290                         "%u,%lu,%lu,%lu,%lu,%lu,%lu,%.3f,%.3f,%.3f,%.1f,%d,%.1f,%d,%d,%lu,%lu,%lu,%lu,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\r\n",
01291                             sample_count++,
01292                             max8614x_sample.led1,max8614x_sample.led2,max8614x_sample.led3,max8614x_sample.led4,max8614x_sample.led5,max8614x_sample.led6,
01293                             accel_sample.x * 0.001,accel_sample.y * 0.001,accel_sample.z * 0.001,
01294                             whrm_sample_modeX.hr * 0.1, whrm_sample_modeX.hr_conf, whrm_sample_modeX.rr * 0.1,whrm_sample_modeX.rr_conf,whrm_sample_modeX.activity_class,
01295                             whrm_sample_modeX.walk_steps, whrm_sample_modeX.run_steps, whrm_sample_modeX.kcal, whrm_sample_modeX.cadence,
01296                             whrm_sample_modeX.is_led_cur_adj, whrm_sample_modeX.adj_led_cur, whrm_sample_modeX.is_t_int_cur_adj, whrm_sample_modeX.adj_t_int_cur,
01297                             whrm_sample_modeX.is_f_smp_adj, whrm_sample_modeX.adj_f_smp,
01298                             whrm_sample_modeX.smp_ave, whrm_sample_modeX.state, whrm_sample_modeX.is_high_motion, whrm_sample_modeX.status);                        
01299                     }
01300                     else {
01301                         data_len = snprintf(buf, size - 1, "%u,%lu,%lu,%lu,%lu,%lu,%lu,%.3f,%.3f,%.3f,%.1f,%d,%.1f,%d\r\n",
01302                             sample_count++,
01303                             max8614x_sample.led1,
01304                             max8614x_sample.led2,
01305                             max8614x_sample.led3,
01306                             max8614x_sample.led4,
01307                             max8614x_sample.led5,
01308                             max8614x_sample.led6,
01309                             accel_sample.x * 0.001,
01310                             accel_sample.y * 0.001,
01311                             accel_sample.z * 0.001,
01312                             whrm_sample_modeX.hr * 0.1,
01313                             whrm_sample_modeX.hr_conf,
01314                             whrm_sample_modeX.rr * 0.1,
01315                             whrm_sample_modeX.activity_class);
01316                     }
01317                 }
01318                 else { // bin report
01319 
01320 
01321                     mxm_assert_msg(((uint32_t)size > sizeof(ds_pkt_data_mode2_compact)), "data_report_execute buffer too small");
01322                     ds_pkt_data_mode2_compact* data_packet = (ds_pkt_data_mode2_compact*)buf;
01323                     data_packet->start_byte = DS_BINARY_PACKET_START_BYTE;
01324                     data_packet->sample_cnt = sample_count++;
01325                     data_packet->grnCnt = max8614x_sample.led1;
01326                     data_packet->grn2Cnt = max8614x_sample.led4;
01327                     data_packet->hr = (whrm_sample_modeX.hr * 0.1);
01328                     data_packet->x = (int16_t)(accel_sample.x);
01329                     data_packet->y = (int16_t)(accel_sample.y);
01330                     data_packet->z = (int16_t)(accel_sample.z);
01331                     data_packet->hr_confidence = whrm_sample_modeX.hr_conf;
01332                     data_packet->rr = whrm_sample_modeX.rr;
01333                     data_packet->status = whrm_sample_modeX.activity_class;
01334                     data_packet->crc8 = crc8((uint8_t*)data_packet, sizeof(*data_packet) - sizeof(uint8_t));
01335                     data_len = sizeof(*data_packet);
01336                 }
01337             }
01338             else
01339             {
01340                 //m_USB->printf("\r\nError Printing: max8614x_q:%d, max8614x_enabled:%d,  \r\n",queue_len(&max8614x_queue), sensor_algo_en_dis_.max8614x_enabled );
01341                 //m_USB->printf("\r\n                accel_q:%d,    accel_enabled:%d,  \r\n",queue_len(&accel_input_queue), sensor_algo_en_dis_.accel_enabled);
01342                 //m_USB->printf("\r\n                whrm_queue:%d,whrm_enabled:%d,  \r\n",queue_len(&whrm_queue) , sensor_algo_en_dis_.whrm_enabled);
01343 
01344             }
01345         } break;
01346 
01347         default:
01348         {
01349             m_USB->printf("\r\nError tmp_report_mode=%d\r\n", tmp_report_mode);
01350             return 0;
01351         }
01352     }
01353 
01354     if (data_len < 0) {
01355         pr_err("snprintf console_tx_buf failed");
01356     } else if (data_len > size) {
01357         pr_err("buffer is insufficient to hold data");
01358     }
01359 
01360     return data_len;
01361 }
01362 
01363 // TODO: convert this to PPG sensor test
01364 int SSMAX8614XComm::selftest_max8614x(){
01365     int ret;
01366     uint8_t test_result;
01367     bool test_failed = false;
01368     m_USB->printf("starting selftest_max8614x\r\n");
01369     // configure mfio pin for self test
01370     ss_int->mfio_selftest();
01371     ret = ss_int->self_test(SS_SENSORIDX_MAX86140, &test_result, 1000);
01372     if(ret != SS_SUCCESS){
01373         m_USB->printf("ss_int->self_test(SS_SENSORIDX_MAX86140, &test_result) has failed err<-1>\r\n");
01374         test_failed = true;
01375     }
01376     // reset mfio pin to old state
01377     if(!ss_int->reset_mfio_irq()){
01378         m_USB->printf("smart sensor reset_mfio_irq has failed err<-1>\r\n");
01379         test_failed = true;
01380     }
01381     // reset the sensor to turn off the LED
01382     ret = ss_int->reset();
01383     if(test_failed | !self_test_result_evaluate("selftest_max8614x", test_result)){
01384         return -1;
01385     }else{
01386         return SS_SUCCESS;
01387     }
01388 }
01389 
01390 int SSMAX8614XComm::selftest_accelerometer(){
01391     int ret;
01392     uint8_t test_result;
01393     bool test_failed = false;
01394     m_USB->printf("starting selftest_accelerometer\r\n");
01395     ret = ss_int->self_test(SS_SENSORIDX_ACCEL, &test_result, 1000);
01396     if(ret != SS_SUCCESS){
01397         m_USB->printf("ss_int->self_test(SS_SENSORIDX_ACCEL, &test_result) has failed err<-1>\r\n");
01398         test_failed = true;
01399     }
01400     // reset the sensor to turn off the LED
01401     ret = ss_int->reset();
01402     if(ret != SS_SUCCESS){
01403         m_USB->printf("smart sensor reset has failed err<-1>\r\n");
01404         test_failed = true;
01405     }
01406     if(test_failed | !self_test_result_evaluate("selftest_accelerometer", test_result)){
01407         return -1;
01408     }else{
01409         return SS_SUCCESS;
01410     }
01411 }
01412 
01413 bool SSMAX8614XComm::self_test_result_evaluate(const char *message, uint8_t result){
01414     // check i2c response status
01415     if(result != 0x00){
01416         m_USB->printf("%s has failed % 02X err<-1>\r\n", message, result);
01417         if((result & FAILURE_COMM))
01418             m_USB->printf("%s communication has failed err<-1>\r\n", message);
01419         if(result & FAILURE_INTERRUPT)
01420             m_USB->printf("%s interrupt pin check has failed err<-1>\r\n", message);
01421         return false;
01422     }
01423     return true;
01424 }
01425 
01426 unsigned char SSMAX8614XComm::get_sensor_id() {
01427     return SENSOR_ID_SSMAX8614X; //TODO: assign the correct number
01428 }