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 USBDevice
Fork of MAXREFDES220_HEART_RATE_MONITOR by
SSInterface.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 "SSInterface.h" 00035 #include "Peripherals.h" 00036 #include "assert.h" 00037 #include "utils.h" 00038 #include "i2cm.h" 00039 00040 SSInterface::SSInterface(I2C &i2cBus, PinName ss_mfio, PinName ss_reset) 00041 :m_i2cBus(&i2cBus), m_spiBus(NULL), 00042 mfio_pin(ss_mfio), reset_pin(ss_reset), irq_pin(ss_mfio)/*, 00043 irq_evt(1000000, "irq")*/ 00044 { 00045 reset_pin.input(); 00046 irq_pin.fall(callback(this, &SSInterface::irq_handler)); 00047 00048 reset_to_main_app(); 00049 get_data_type(&data_type, &sc_en); 00050 } 00051 00052 SSInterface::SSInterface(SPI &spiBus, PinName ss_mfio, PinName ss_reset) 00053 :m_i2cBus(NULL), m_spiBus(&spiBus), 00054 mfio_pin(ss_mfio), reset_pin(ss_reset), irq_pin(ss_mfio)/*, 00055 irq_evt(1000000, "irq")*/ 00056 { 00057 reset_pin.input(); 00058 irq_pin.fall(callback(this, &SSInterface::irq_handler)); 00059 00060 reset_to_main_app(); 00061 get_data_type(&data_type, &sc_en); 00062 } 00063 00064 SSInterface::~SSInterface() 00065 { 00066 } 00067 00068 SS_STATUS SSInterface::reset_to_main_app() 00069 { 00070 irq_pin.disable_irq(); 00071 #if defined(BOOTLOADER_USES_MFIO) 00072 reset_pin.output(); 00073 cfg_mfio(PIN_OUTPUT); 00074 reset_pin.write(0); 00075 wait_ms(SS_RESET_TIME); 00076 mfio_pin.write(1); 00077 reset_pin.write(1); 00078 wait_ms(SS_STARTUP_TO_MAIN_APP_TIME); 00079 cfg_mfio(PIN_INPUT); 00080 reset_pin.input(); 00081 irq_pin.enable_irq(); 00082 // Verify we exited bootloader mode 00083 if (in_bootldr_mode() == 0) 00084 return SS_SUCCESS; 00085 else 00086 return SS_ERR_UNKNOWN; 00087 #else 00088 SS_STATUS status = exit_from_bootloader(); 00089 irq_pin.enable_irq(); 00090 return status; 00091 #endif 00092 } 00093 00094 SS_STATUS SSInterface::reset_to_bootloader() 00095 { 00096 irq_pin.disable_irq(); 00097 #if defined(BOOTLOADER_USES_MFIO) 00098 reset_pin.output(); 00099 cfg_mfio(PIN_OUTPUT); 00100 reset_pin.write(0); 00101 wait_ms(SS_RESET_TIME); 00102 mfio_pin.write(0); 00103 reset_pin.write(1); 00104 wait_ms(SS_STARTUP_TO_BTLDR_TIME); 00105 cfg_mfio(PIN_INPUT); 00106 reset_pin.input(); 00107 irq_pin.enable_irq(); 00108 stay_in_bootloader(); 00109 00110 // Verify we entered bootloader mode 00111 if (in_bootldr_mode() < 0) 00112 return SS_ERR_UNKNOWN; 00113 return SS_SUCCESS; 00114 #else 00115 stay_in_bootloader(); 00116 irq_pin.enable_irq(); 00117 return SS_SUCCESS; 00118 #endif 00119 } 00120 00121 SS_STATUS SSInterface::exit_from_bootloader() 00122 { 00123 uint8_t cmd_bytes[] = { SS_FAM_W_MODE, SS_CMDIDX_MODE }; 00124 uint8_t data[] = { 0x00 }; 00125 00126 SS_STATUS status = write_cmd( 00127 &cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00128 &data[0], ARRAY_SIZE(data)); 00129 00130 in_bootldr = (status == SS_SUCCESS) ? true : false; 00131 return status; 00132 } 00133 00134 SS_STATUS SSInterface::stay_in_bootloader() 00135 { 00136 uint8_t cmd_bytes[] = { SS_FAM_W_MODE, SS_CMDIDX_MODE }; 00137 uint8_t data[] = { SS_MASK_MODE_BOOTLDR }; 00138 00139 SS_STATUS status = write_cmd( 00140 &cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00141 &data[0], ARRAY_SIZE(data)); 00142 00143 in_bootldr = (status == SS_SUCCESS) ? true : false; 00144 return status; 00145 } 00146 00147 SS_STATUS SSInterface::reset() 00148 { 00149 int bootldr = in_bootldr_mode(); 00150 if (bootldr > 0) 00151 return reset_to_bootloader(); 00152 else if (bootldr == 0) 00153 return reset_to_main_app(); 00154 else 00155 return SS_ERR_UNKNOWN; 00156 } 00157 00158 SS_STATUS SSInterface::self_test(int idx, uint8_t *result, int sleep_ms){ 00159 uint8_t cmd_bytes[] = { SS_FAM_R_SELFTEST, (uint8_t)idx }; 00160 uint8_t rxbuf[2]; 00161 SS_STATUS ret; 00162 00163 result[0] = 0xFF; 00164 ret = read_cmd(cmd_bytes, 2, (uint8_t *)0, 0, rxbuf, ARRAY_SIZE(rxbuf), sleep_ms); 00165 result[0] = rxbuf[1]; 00166 return ret; 00167 } 00168 00169 void SSInterface::cfg_mfio(PinDirection dir) 00170 { 00171 if (dir == PIN_INPUT) { 00172 mfio_pin.input(); 00173 mfio_pin.mode(PullUp); 00174 } else { 00175 mfio_pin.output(); 00176 } 00177 } 00178 00179 void SSInterface::enable_irq() 00180 { 00181 irq_pin.enable_irq(); 00182 } 00183 void SSInterface::disable_irq() 00184 { 00185 irq_pin.disable_irq(); 00186 } 00187 00188 void SSInterface::mfio_selftest(){ 00189 disable_irq(); 00190 irq_pin.fall(callback(this, &SSInterface::irq_handler_selftest)); 00191 enable_irq(); 00192 } 00193 00194 int SSInterface::in_bootldr_mode() 00195 { 00196 uint8_t cmd_bytes[] = { SS_FAM_R_MODE, SS_CMDIDX_MODE }; 00197 uint8_t rxbuf[2] = { 0 }; 00198 00199 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00200 0, 0, 00201 &rxbuf[0], ARRAY_SIZE(rxbuf)); 00202 if (status != SS_SUCCESS) 00203 return -1; 00204 00205 return (rxbuf[1] & SS_MASK_MODE_BOOTLDR); 00206 } 00207 00208 const char* SSInterface::get_ss_fw_version() 00209 { 00210 uint8_t cmd_bytes[2]; 00211 uint8_t rxbuf[4]; 00212 00213 int bootldr = in_bootldr_mode(); 00214 00215 if (bootldr > 0) { 00216 cmd_bytes[0] = SS_FAM_R_BOOTLOADER; 00217 cmd_bytes[1] = SS_CMDIDX_BOOTFWVERSION; 00218 } else if (bootldr == 0) { 00219 cmd_bytes[0] = SS_FAM_R_IDENTITY; 00220 cmd_bytes[1] = SS_CMDIDX_FWVERSION; 00221 } else { 00222 return plat_name; 00223 } 00224 00225 SS_STATUS status = read_cmd( 00226 &cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00227 0, 0, 00228 &rxbuf[0], ARRAY_SIZE(rxbuf)); 00229 00230 if (status == SS_SUCCESS) { 00231 snprintf(fw_version, sizeof(fw_version), 00232 "%d.%d.%d", rxbuf[1], rxbuf[2], rxbuf[3]); 00233 pr_info("fw_version:%s\r\n", fw_version); 00234 } 00235 00236 return &fw_version[0]; 00237 } 00238 00239 const char* SSInterface::get_ss_algo_version() 00240 { 00241 uint8_t cmd_bytes[3]; 00242 uint8_t rxbuf[4]; 00243 00244 int bootldr = in_bootldr_mode(); 00245 00246 if (bootldr > 0) { 00247 cmd_bytes[0] = SS_FAM_R_BOOTLOADER; 00248 cmd_bytes[1] = SS_CMDIDX_BOOTFWVERSION; 00249 cmd_bytes[2] = 0; 00250 } else if (bootldr == 0) { 00251 cmd_bytes[0] = SS_FAM_R_IDENTITY; 00252 cmd_bytes[1] = SS_CMDIDX_ALGOVER; 00253 cmd_bytes[2] = SS_CMDIDX_AVAILSENSORS; 00254 } else { 00255 return plat_name; 00256 } 00257 00258 SS_STATUS status = read_cmd( 00259 &cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00260 0, 0, 00261 &rxbuf[0], ARRAY_SIZE(rxbuf)); 00262 00263 if (status == SS_SUCCESS) { 00264 snprintf(algo_version, sizeof(algo_version), 00265 "%d.%d.%d", rxbuf[1], rxbuf[2], rxbuf[3]); 00266 pr_info("algo_version:%s\r\n", fw_version); 00267 } 00268 00269 return &algo_version[0]; 00270 } 00271 const char* SSInterface::get_ss_platform_name() 00272 { 00273 uint8_t cmd_bytes[] = { SS_FAM_R_IDENTITY, SS_CMDIDX_PLATTYPE }; 00274 uint8_t rxbuf[2]; 00275 00276 SS_STATUS status = read_cmd( 00277 &cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00278 0, 0, 00279 &rxbuf[0], ARRAY_SIZE(rxbuf)); 00280 00281 if (status == SS_SUCCESS) { 00282 if (rxbuf[1] == SS_PLAT_MAX3263X) { 00283 if (in_bootldr_mode() > 0) { 00284 plat_name = SS_BOOTLOADER_PLATFORM_MAX3263X; 00285 } else { 00286 plat_name = SS_PLATFORM_MAX3263X; 00287 } 00288 } else if (rxbuf[1] == SS_PLAT_MAX32660) { 00289 if (in_bootldr_mode() > 0) { 00290 plat_name = SS_BOOTLOADER_PLATFORM_MAX32660; 00291 } else { 00292 plat_name = SS_PLATFORM_MAX32660; 00293 } 00294 } 00295 } 00296 00297 return plat_name; 00298 } 00299 00300 SS_STATUS SSInterface::write_cmd(uint8_t *cmd_bytes, int cmd_bytes_len, 00301 uint8_t *data, int data_len, 00302 int sleep_ms) 00303 { 00304 int total_len = data_len + cmd_bytes_len; 00305 00306 if (total_len <= SS_SMALL_BUF_SIZE) { 00307 return write_cmd_small(cmd_bytes, cmd_bytes_len, data, data_len, sleep_ms); 00308 } else if (total_len <= SS_MED_BUF_SIZE) { 00309 return write_cmd_medium(cmd_bytes, cmd_bytes_len, data, data_len, sleep_ms); 00310 } else if (total_len <= SS_LARGE_BUF_SIZE) { 00311 return write_cmd_large(cmd_bytes, cmd_bytes_len, data, data_len, sleep_ms); 00312 } else { 00313 assert_msg(true, "Tried to send I2C tx larger than maximum allowed size\n"); 00314 return SS_ERR_DATA_FORMAT; 00315 } 00316 } 00317 00318 SS_STATUS SSInterface::write_cmd(uint8_t *tx_buf, int tx_len, int sleep_ms) 00319 { 00320 pr_info("write_cmd: "); 00321 for (int i = 0; i < tx_len; i++) { 00322 pr_info("0x%02X ", tx_buf[i]); 00323 } 00324 pr_info("\r\n"); 00325 00326 int ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)tx_buf, tx_len); 00327 00328 int retries = 4; 00329 while (ret != 0 && retries-- > 0) { 00330 pr_err("i2c wr retry\r\n"); 00331 wait_ms(1); 00332 ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)tx_buf, tx_len); 00333 } 00334 00335 if (ret != 0) { 00336 pr_err("m_i2cBus->write returned %d\r\n", ret); 00337 return SS_ERR_UNAVAILABLE; 00338 } 00339 00340 wait_ms(sleep_ms); 00341 00342 char status_byte; 00343 ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, &status_byte, 1); 00344 bool try_again = (status_byte == SS_ERR_TRY_AGAIN); 00345 while ((ret != 0 || try_again) 00346 && retries-- > 0) { 00347 pr_info("i2c rd retry\r\n"); 00348 wait_ms(sleep_ms); 00349 ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, &status_byte, 1); 00350 try_again = (status_byte == SS_ERR_TRY_AGAIN); 00351 } 00352 00353 if (ret != 0 || try_again) { 00354 pr_err("m_i2cBus->read returned %d, ss status_byte %d\r\n", ret, status_byte); 00355 return SS_ERR_UNAVAILABLE; 00356 } 00357 00358 pr_info("status_byte: %d\r\n", status_byte); 00359 00360 return (SS_STATUS)status_byte; 00361 } 00362 00363 SS_STATUS SSInterface::write_cmd_small(uint8_t *cmd_bytes, int cmd_bytes_len, 00364 uint8_t *data, int data_len, 00365 int sleep_ms) 00366 { 00367 uint8_t write_buf[SS_SMALL_BUF_SIZE]; 00368 memcpy(write_buf, cmd_bytes, cmd_bytes_len); 00369 memcpy(write_buf + cmd_bytes_len, data, data_len); 00370 00371 SS_STATUS status = write_cmd(write_buf, cmd_bytes_len + data_len, sleep_ms); 00372 return status; 00373 } 00374 00375 SS_STATUS SSInterface::write_cmd_medium(uint8_t *cmd_bytes, int cmd_bytes_len, 00376 uint8_t *data, int data_len, 00377 int sleep_ms) 00378 { 00379 uint8_t write_buf[SS_MED_BUF_SIZE]; 00380 memcpy(write_buf, cmd_bytes, cmd_bytes_len); 00381 memcpy(write_buf + cmd_bytes_len, data, data_len); 00382 00383 SS_STATUS status = write_cmd(write_buf, cmd_bytes_len + data_len, sleep_ms); 00384 return status; 00385 } 00386 00387 SS_STATUS SSInterface::write_cmd_large(uint8_t *cmd_bytes, int cmd_bytes_len, 00388 uint8_t *data, int data_len, 00389 int sleep_ms) 00390 { 00391 uint8_t write_buf[SS_LARGE_BUF_SIZE]; 00392 memcpy(write_buf, cmd_bytes, cmd_bytes_len); 00393 memcpy(write_buf + cmd_bytes_len, data, data_len); 00394 00395 SS_STATUS status = write_cmd(write_buf, cmd_bytes_len + data_len, sleep_ms); 00396 return status; 00397 } 00398 00399 SS_STATUS SSInterface::read_cmd(uint8_t *cmd_bytes, int cmd_bytes_len, 00400 uint8_t *data, int data_len, 00401 uint8_t *rxbuf, int rxbuf_sz, 00402 int sleep_ms) 00403 { 00404 pr_info("read_cmd: "); 00405 for (int i = 0; i < cmd_bytes_len; i++) { 00406 pr_info("0x%02X ", cmd_bytes[i]); 00407 } 00408 pr_info("\r\n"); 00409 00410 00411 int retries = 4; 00412 00413 int ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)cmd_bytes, cmd_bytes_len, (data_len != 0)); 00414 00415 if (data_len != 0) { 00416 ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)data, data_len, false); 00417 } 00418 00419 while (ret != 0 && retries-- > 0) { 00420 pr_err("i2c wr retry\r\n"); 00421 wait_ms(1); 00422 ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)cmd_bytes, cmd_bytes_len, (data_len != 0)); 00423 if (data_len != 0) { 00424 ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)data, data_len, false); 00425 } 00426 } 00427 00428 if (ret != 0) { 00429 pr_err("m_i2cBus->write returned %d\r\n", ret); 00430 return SS_ERR_UNAVAILABLE; 00431 } 00432 00433 wait_ms(sleep_ms); 00434 00435 ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, (char*)rxbuf, rxbuf_sz); 00436 bool try_again = (rxbuf[0] == SS_ERR_TRY_AGAIN); 00437 while ((ret != 0 || try_again) && retries-- > 0) { 00438 pr_info("i2c rd retry\r\n"); 00439 wait_ms(sleep_ms); 00440 ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, (char*)rxbuf, rxbuf_sz); 00441 try_again = (rxbuf[0] == SS_ERR_TRY_AGAIN); 00442 } 00443 if (ret != 0 || try_again) { 00444 pr_err("m_i2cBus->read returned %d, ss status_byte %d\r\n", ret, rxbuf[0]); 00445 return SS_ERR_UNAVAILABLE; 00446 } 00447 00448 pr_info("status_byte: %d\r\n", rxbuf[0]); 00449 pr_info("data: "); 00450 for (int i = 1; i < rxbuf_sz; i++) { 00451 pr_info("0x%02X ", rxbuf[i]); 00452 } 00453 pr_info("\r\n"); 00454 00455 return (SS_STATUS)rxbuf[0]; 00456 } 00457 00458 SS_STATUS SSInterface::get_reg(int idx, uint8_t addr, uint32_t *val) 00459 { 00460 assert_msg((idx <= SS_MAX_SUPPORTED_SENSOR_NUM), "idx must be < SS_MAX_SUPPORTED_SENSOR_NUM, or update code to handle variable length idx values"); 00461 00462 uint8_t cmd_bytes[] = { SS_FAM_R_REGATTRIBS, (uint8_t)idx }; 00463 uint8_t rx_reg_attribs[3] = {0}; 00464 00465 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00466 0, 0, 00467 &rx_reg_attribs[0], ARRAY_SIZE(rx_reg_attribs)); 00468 00469 if (status != SS_SUCCESS) 00470 return status; 00471 00472 int reg_width = rx_reg_attribs[1]; 00473 00474 uint8_t cmd_bytes2[] = { SS_FAM_R_READREG, (uint8_t)idx, addr }; 00475 uint8_t rxbuf[5] = {0}; 00476 00477 status = read_cmd(&cmd_bytes2[0], ARRAY_SIZE(cmd_bytes2), 00478 0, 0, 00479 &rxbuf[0], reg_width + 1); 00480 00481 if (status == SS_SUCCESS) { 00482 *val = 0; 00483 for (int i = 0; i < reg_width; i++) { 00484 *val = (*val << 8) | rxbuf[i + 1]; 00485 } 00486 } 00487 00488 return status; 00489 } 00490 00491 SS_STATUS SSInterface::set_reg(int idx, uint8_t addr, uint32_t val, int byte_size) 00492 { 00493 assert_msg((idx <= SS_MAX_SUPPORTED_SENSOR_NUM), "idx must be < SS_MAX_SUPPORTED_SENSOR_NUM, or update code to handle variable length idx values"); 00494 00495 uint8_t cmd_bytes[] = { SS_FAM_W_WRITEREG, (uint8_t)idx, addr }; 00496 uint8_t data_bytes[4]; 00497 for (int i = 0; i < byte_size; i++) { 00498 data_bytes[i] = (val >> (8 * (byte_size - 1)) & 0xFF); 00499 } 00500 00501 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00502 &data_bytes[0], byte_size); 00503 00504 return status; 00505 } 00506 00507 SS_STATUS SSInterface::dump_reg(int idx, addr_val_pair* reg_vals, int reg_vals_sz, int* num_regs) 00508 { 00509 assert_msg((idx <= SS_MAX_SUPPORTED_SENSOR_NUM), "idx must be < SS_MAX_SUPPORTED_SENSOR_NUM, or update code to handle variable length idx values"); 00510 00511 uint8_t cmd_bytes[] = { SS_FAM_R_REGATTRIBS, (uint8_t)idx }; 00512 uint8_t rx_reg_attribs[3] = {0}; 00513 00514 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00515 0, 0, 00516 &rx_reg_attribs[0], ARRAY_SIZE(rx_reg_attribs)); 00517 00518 if (status != SS_SUCCESS) 00519 return status; 00520 00521 int reg_width = rx_reg_attribs[1]; 00522 *num_regs = rx_reg_attribs[2]; 00523 assert_msg((*num_regs <= reg_vals_sz), "Need to increase reg_vals array to hold all dump_reg data"); 00524 assert_msg(((size_t)reg_width <= sizeof(uint32_t)), "IC returned register values greater than 4 bytes in width"); 00525 00526 int dump_reg_sz = (*num_regs) * (reg_width + 1) + 1; //+1 to reg_width for address, +1 for status byte 00527 00528 uint8_t rxbuf[512]; 00529 assert_msg(((size_t)dump_reg_sz <= sizeof(rxbuf)), "Need to increase buffer size to receive dump_reg data"); 00530 00531 cmd_bytes[0] = SS_FAM_R_DUMPREG; 00532 status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00533 0, 0, 00534 &rxbuf[0], dump_reg_sz, SS_DUMP_REG_SLEEP_MS); 00535 00536 if (status != SS_SUCCESS) 00537 return status; 00538 00539 //rxbuf format is [status][addr0](reg_width x [val0])[addr1](reg_width x [val1])... 00540 for (int reg = 0; reg < *num_regs; reg++) { 00541 reg_vals[reg].addr = rxbuf[(reg * (reg_width + 1)) + 1]; 00542 uint32_t *val = &(reg_vals[reg].val); 00543 *val = 0; 00544 for (int byte = 0; byte < reg_width; byte++) { 00545 *val = (*val << 8) | rxbuf[(reg * (reg_width + 1)) + byte + 2]; 00546 } 00547 } 00548 00549 return SS_SUCCESS; 00550 } 00551 00552 SS_STATUS SSInterface::enable_sensor(int idx, int mode, ss_data_req *data_req) 00553 { 00554 assert_msg((idx <= SS_MAX_SUPPORTED_SENSOR_NUM), "idx must be < SS_MAX_SUPPORTED_SENSOR_NUM, or update code to handle variable length idx values"); 00555 assert_msg((mode <= SS_MAX_SUPPORTED_MODE_NUM), "mode must be < SS_MAX_SUPPORTED_MODE_NUM, or update code to handle variable length mode values"); 00556 assert_msg((mode != 0), "Tried to enable sensor to mode 0, but mode 0 is disable"); 00557 00558 00559 uint8_t cmd_bytes[] = { SS_FAM_W_SENSORMODE, (uint8_t)idx, (uint8_t)mode }; 00560 00561 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS); 00562 00563 if (status == SS_SUCCESS) { 00564 sensor_enabled_mode[idx] = mode; 00565 sensor_data_reqs[idx] = data_req; 00566 } 00567 return status; 00568 } 00569 00570 SS_STATUS SSInterface::disable_sensor(int idx) 00571 { 00572 assert_msg((idx <= SS_MAX_SUPPORTED_SENSOR_NUM), "idx must be < SS_MAX_SUPPORTED_SENSOR_NUM, or update code to handle variable length idx values"); 00573 uint8_t cmd_bytes[] = { SS_FAM_W_SENSORMODE, (uint8_t)idx, 0 }; 00574 00575 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS); 00576 00577 if (status == SS_SUCCESS) { 00578 sensor_enabled_mode[idx] = 0; 00579 sensor_data_reqs[idx] = 0; 00580 } 00581 00582 return status; 00583 } 00584 00585 SS_STATUS SSInterface::enable_algo(int idx, int mode, ss_data_req *data_req) 00586 { 00587 assert_msg((idx <= SS_MAX_SUPPORTED_ALGO_NUM), "idx must be < SS_MAX_SUPPORTED_ALGO_NUM, or update code to handle variable length idx values"); 00588 assert_msg((mode <= SS_MAX_SUPPORTED_MODE_NUM), "mode must be < SS_MAX_SUPPORTED_MODE_NUM, or update code to handle variable length mode values"); 00589 assert_msg((mode != 0), "Tried to enable algo to mode 0, but mode 0 is disable"); 00590 00591 uint8_t cmd_bytes[] = { SS_FAM_W_ALGOMODE, (uint8_t)idx, (uint8_t)mode }; 00592 00593 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, 4*SS_ENABLE_SENSOR_SLEEP_MS); 00594 00595 if (status == SS_SUCCESS) { 00596 algo_enabled_mode[idx] = mode; 00597 algo_data_reqs[idx] = data_req; 00598 } 00599 00600 return status; 00601 } 00602 00603 SS_STATUS SSInterface::disable_algo(int idx) 00604 { 00605 assert_msg((idx <= SS_MAX_SUPPORTED_ALGO_NUM), "idx must be < SS_MAX_SUPPORTED_ALGO_NUM, or update code to handle variable length idx values"); 00606 uint8_t cmd_bytes[] = { SS_FAM_W_ALGOMODE, (uint8_t)idx, 0 }; 00607 00608 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS); 00609 00610 if (status == SS_SUCCESS) { 00611 algo_enabled_mode[idx] = 0; 00612 algo_data_reqs[idx] = 0; 00613 } 00614 00615 return status; 00616 } 00617 00618 SS_STATUS SSInterface::set_algo_cfg(int algo_idx, int cfg_idx, uint8_t *cfg, int cfg_sz) 00619 { 00620 assert_msg((algo_idx <= SS_MAX_SUPPORTED_ALGO_NUM), "idx must be < SS_MAX_SUPPORTED_ALGO_NUM, or update code to handle variable length idx values"); 00621 assert_msg((cfg_idx <= SS_MAX_SUPPORTED_ALGO_CFG_NUM), "idx must be < SS_MAX_SUPPORTED_ALGO_CFG_NUM, or update code to handle variable length idx values"); 00622 00623 uint8_t cmd_bytes[] = { SS_FAM_W_ALGOCONFIG, (uint8_t)algo_idx, (uint8_t)cfg_idx }; 00624 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00625 cfg, cfg_sz); 00626 00627 return status; 00628 } 00629 00630 SS_STATUS SSInterface::get_algo_cfg(int algo_idx, int cfg_idx, uint8_t *cfg, int cfg_sz) 00631 { 00632 assert_msg((algo_idx <= SS_MAX_SUPPORTED_ALGO_NUM), "idx must be < SS_MAX_SUPPORTED_ALGO_NUM, or update code to handle variable length idx values"); 00633 assert_msg((cfg_idx <= SS_MAX_SUPPORTED_ALGO_CFG_NUM), "idx must be < SS_MAX_SUPPORTED_ALGO_CFG_NUM, or update code to handle variable length idx values"); 00634 00635 uint8_t cmd_bytes[] = { SS_FAM_R_ALGOCONFIG, (uint8_t)algo_idx, (uint8_t)cfg_idx }; 00636 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00637 0, 0, 00638 cfg, cfg_sz); 00639 00640 return status; 00641 } 00642 00643 SS_STATUS SSInterface::set_data_type(int data_type, bool sc_en) 00644 { 00645 assert_msg((data_type >= 0) && (data_type <= 3), "Invalid value for data_type"); 00646 uint8_t cmd_bytes[] = { SS_FAM_W_COMMCHAN, SS_CMDIDX_OUTPUTMODE }; 00647 uint8_t data_bytes[] = { (uint8_t)((sc_en ? SS_MASK_OUTPUTMODE_SC_EN : 0) | 00648 ((data_type << SS_SHIFT_OUTPUTMODE_DATATYPE) & SS_MASK_OUTPUTMODE_DATATYPE)) }; 00649 00650 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00651 &data_bytes[0], ARRAY_SIZE(data_bytes)); 00652 00653 this->data_type = data_type; 00654 this->sc_en = sc_en; 00655 00656 return status; 00657 } 00658 00659 00660 SS_STATUS SSInterface::get_data_type(int *data_type, bool *sc_en) 00661 { 00662 uint8_t cmd_bytes[] = { SS_FAM_R_COMMCHAN, SS_CMDIDX_OUTPUTMODE }; 00663 uint8_t rxbuf[2] = {0}; 00664 00665 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00666 0, 0, 00667 &rxbuf[0], ARRAY_SIZE(rxbuf)); 00668 if (status == SS_SUCCESS) { 00669 *data_type = 00670 (rxbuf[1] & SS_MASK_OUTPUTMODE_DATATYPE) >> SS_SHIFT_OUTPUTMODE_DATATYPE; 00671 *sc_en = 00672 (bool)((rxbuf[1] & SS_MASK_OUTPUTMODE_SC_EN) >> SS_SHIFT_OUTPUTMODE_SC_EN); 00673 } 00674 00675 return status; 00676 } 00677 00678 SS_STATUS SSInterface::set_fifo_thresh(int thresh) 00679 { 00680 assert_msg((thresh > 0 && thresh <= 255), "Invalid value for fifo a full threshold"); 00681 uint8_t cmd_bytes[] = { SS_FAM_W_COMMCHAN, SS_CMDIDX_FIFOAFULL }; 00682 uint8_t data_bytes[] = { (uint8_t)thresh }; 00683 00684 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00685 &data_bytes[0], ARRAY_SIZE(data_bytes)); 00686 return status; 00687 } 00688 00689 SS_STATUS SSInterface::get_fifo_thresh(int *thresh) 00690 { 00691 uint8_t cmd_bytes[] = { SS_FAM_R_COMMCHAN, SS_CMDIDX_FIFOAFULL }; 00692 uint8_t rxbuf[2] = {0}; 00693 00694 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00695 0, 0, 00696 &rxbuf[0], ARRAY_SIZE(rxbuf)); 00697 00698 if (status == SS_SUCCESS) { 00699 *thresh = rxbuf[1]; 00700 } 00701 00702 return status; 00703 } 00704 00705 SS_STATUS SSInterface::ss_comm_check() 00706 { 00707 uint8_t cmd_bytes[] = { SS_FAM_R_IDENTITY, SS_CMDIDX_PLATTYPE }; 00708 uint8_t rxbuf[2]; 00709 00710 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00711 0, 0, 00712 &rxbuf[0], ARRAY_SIZE(rxbuf)); 00713 00714 int tries = 4; 00715 while (status == SS_ERR_TRY_AGAIN && tries--) { 00716 wait_ms(1000); 00717 status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00718 0, 0, 00719 &rxbuf[0], ARRAY_SIZE(rxbuf)); 00720 } 00721 00722 return status; 00723 } 00724 00725 void SSInterface::fifo_sample_size(int data_type, int *sample_size) 00726 { 00727 *sample_size = 0; 00728 00729 if (data_type == SS_DATATYPE_RAW || data_type == SS_DATATYPE_BOTH) { 00730 for (int i = 0; i < SS_MAX_SUPPORTED_SENSOR_NUM; i++) { 00731 if (sensor_enabled_mode[i]) { 00732 assert_msg(sensor_data_reqs[i], "no ss_data_req found for enabled sensor"); 00733 *sample_size += sensor_data_reqs[i]->data_size; 00734 } 00735 } 00736 } 00737 00738 if (data_type == SS_DATATYPE_ALGO || data_type == SS_DATATYPE_BOTH) { 00739 for (int i = 0; i < SS_MAX_SUPPORTED_ALGO_NUM; i++) { 00740 if (algo_enabled_mode[i]) { 00741 assert_msg(algo_data_reqs[i], "no ss_data_req found for enabled algo"); 00742 *sample_size += algo_data_reqs[i]->data_size; 00743 } 00744 } 00745 } 00746 } 00747 00748 SS_STATUS SSInterface::num_avail_samples(int *num_samples) 00749 { 00750 uint8_t cmd_bytes[] = { SS_FAM_R_OUTPUTFIFO, SS_CMDIDX_OUT_NUMSAMPLES }; 00751 uint8_t rxbuf[2] = {0}; 00752 00753 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00754 0, 0, 00755 &rxbuf[0], ARRAY_SIZE(rxbuf), 1); 00756 00757 if (status == SS_SUCCESS) { 00758 *num_samples = rxbuf[1]; 00759 } 00760 00761 return status; 00762 } 00763 00764 SS_STATUS SSInterface::read_fifo_data( 00765 int num_samples, int sample_size, 00766 uint8_t* databuf, int databuf_sz) 00767 { 00768 int bytes_to_read = num_samples * sample_size + 1; //+1 for status byte 00769 assert_msg((bytes_to_read <= databuf_sz), "databuf too small"); 00770 00771 uint8_t cmd_bytes[] = { SS_FAM_R_OUTPUTFIFO, SS_CMDIDX_READFIFO }; 00772 00773 pr_info("[reading %d bytes (%d samples)\r\n", bytes_to_read, num_samples); 00774 00775 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00776 0, 0, 00777 databuf, bytes_to_read, 5); 00778 00779 return status; 00780 } 00781 00782 static uint8_t databuf[512]; 00783 void SSInterface::ss_execute_once(){ 00784 00785 if(m_irq_received_ == false) 00786 return; 00787 00788 uint8_t sample_count; 00789 m_irq_received_ = false; 00790 uint8_t cmd_bytes[] = { SS_FAM_R_STATUS, SS_CMDIDX_STATUS }; 00791 uint8_t rxbuf[2] = {0}; 00792 00793 // irq_evt.start(); 00794 00795 irq_pin.disable_irq(); 00796 00797 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 00798 0, 0, 00799 &rxbuf[0], ARRAY_SIZE(rxbuf)); 00800 00801 if (status != SS_SUCCESS) { 00802 pr_err("Couldn't read status byte of SmartSensor!"); 00803 irq_pin.enable_irq(); 00804 // irq_evt.stop(); 00805 return; 00806 } 00807 00808 if (rxbuf[1] & SS_MASK_STATUS_ERR) { 00809 pr_err("SmartSensor status error: %d", rxbuf[1] & SS_MASK_STATUS_ERR); 00810 } 00811 if (rxbuf[1] & SS_MASK_STATUS_FIFO_OUT_OVR) { 00812 pr_err("SmartSensor Output FIFO overflow!"); 00813 } 00814 if (rxbuf[1] & SS_MASK_STATUS_FIFO_IN_OVR) { 00815 pr_err("SmartSensor Input FIFO overflow!"); 00816 } 00817 00818 if (rxbuf[1] & SS_MASK_STATUS_DATA_RDY) { 00819 int num_samples = 1; 00820 status = num_avail_samples(&num_samples); 00821 if (status != SS_SUCCESS) 00822 { 00823 pr_err("Couldn't read number of available samples in SmartSensor Output FIFO"); 00824 irq_pin.enable_irq(); 00825 // irq_evt.stop(); 00826 return; 00827 } 00828 00829 int sample_size; 00830 fifo_sample_size(data_type, &sample_size); 00831 00832 int bytes_to_read = num_samples * sample_size + 1; //+1 for status byte 00833 if ((uint32_t)bytes_to_read > sizeof(databuf)) { 00834 //Reduce number of samples to read to fit in buffer 00835 num_samples = (sizeof(databuf) - 1) / sample_size; 00836 } 00837 00838 wait_ms(5); 00839 status = read_fifo_data(num_samples, sample_size, &databuf[0], sizeof(databuf)); 00840 if (status != SS_SUCCESS) 00841 { 00842 pr_err("Couldn't read from SmartSensor Output FIFO"); 00843 irq_pin.enable_irq(); 00844 // irq_evt.stop(); 00845 return; 00846 } 00847 00848 pr_info("read %d samples\r\n", num_samples); 00849 00850 //Skip status byte 00851 uint8_t *data_ptr = &databuf[1]; 00852 00853 int i = 0; 00854 for (i = 0; i < num_samples; i++) { 00855 if (sc_en) { 00856 sample_count = *data_ptr++; 00857 pr_info("Received sample #%d", sample_count); 00858 } 00859 00860 //Chop up data and send to modules with enabled sensors 00861 if (data_type == SS_DATATYPE_RAW || data_type == SS_DATATYPE_BOTH) { 00862 for (int i = 0; i < SS_MAX_SUPPORTED_SENSOR_NUM; i++) { 00863 if (sensor_enabled_mode[i]) { 00864 assert_msg(sensor_data_reqs[i], 00865 "no ss_data_req found for enabled sensor"); 00866 sensor_data_reqs[i]->callback(data_ptr); 00867 data_ptr += sensor_data_reqs[i]->data_size; 00868 } 00869 } 00870 } 00871 if (data_type == SS_DATATYPE_ALGO || data_type == SS_DATATYPE_BOTH) { 00872 for (int i = 0; i < SS_MAX_SUPPORTED_ALGO_NUM; i++) { 00873 if (algo_enabled_mode[i]) { 00874 assert_msg(algo_data_reqs[i], 00875 "no ss_data_req found for enabled algo"); 00876 algo_data_reqs[i]->callback(data_ptr); 00877 data_ptr += algo_data_reqs[i]->data_size; 00878 } 00879 } 00880 } 00881 } 00882 } 00883 irq_pin.enable_irq(); 00884 // irq_evt.stop(); 00885 } 00886 00887 void SSInterface::ss_clear_interrupt_flag(){ 00888 m_irq_received_ = false; 00889 } 00890 00891 void SSInterface::irq_handler() 00892 { 00893 m_irq_received_ = true; 00894 } 00895 00896 void SSInterface::irq_handler_selftest(){ 00897 mfio_int_happened = true; 00898 } 00899 00900 bool SSInterface::reset_mfio_irq(){ 00901 bool ret = mfio_int_happened; 00902 mfio_int_happened = false; 00903 irq_pin.disable_irq(); 00904 irq_pin.fall(callback(this, &SSInterface::irq_handler)); 00905 irq_pin.enable_irq(); 00906 return ret; 00907 }
Generated on Tue Jul 12 2022 10:59:32 by
1.7.2

Heart Rate SpO2 Algorithm EvKit Health Monitor Development System Board MAXREFDES220