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