Maxim Integrated / Mbed OS MAXREFDES220_HR_SPO2_MONITOR

Dependencies:   max32630fthr USBDevice

Fork of MAXREFDES220_HEART_RATE_MONITOR by Maxim Integrated

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SSInterface.cpp Source File

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 }