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
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, ®_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 }
Generated on Tue Jul 12 2022 20:09:29 by
