Maxim Integrated / Mbed OS MAXREFDES220_HEART_RATE_MONITOR

Dependencies:   USBDevice max32630fthr

Fork of MAXREFDES220# 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 
00039 SSInterface::SSInterface(I2C &i2cBus, PinName ss_mfio, PinName ss_reset)
00040     :m_i2cBus(&i2cBus), m_spiBus(NULL), mfio_pin(ss_mfio), reset_pin(ss_reset), irq_pin(ss_mfio)
00041 {
00042     reset_pin.input();
00043     irq_pin.fall(callback(this, &SSInterface::irq_handler));
00044 
00045     reset_to_main_app();
00046     get_data_type(&data_type, &sc_en);
00047 }
00048 
00049 SSInterface::SSInterface(SPI &spiBus, PinName ss_mfio, PinName ss_reset)
00050     :m_i2cBus(NULL), m_spiBus(&spiBus), mfio_pin(ss_mfio), reset_pin(ss_reset), irq_pin(ss_mfio)
00051 {
00052     reset_pin.input();
00053     irq_pin.fall(callback(this, &SSInterface::irq_handler));
00054 
00055     reset_to_main_app();
00056     get_data_type(&data_type, &sc_en);
00057 }
00058 
00059 SSInterface::~SSInterface()
00060 {
00061 }
00062 
00063 SS_STATUS SSInterface::reset_to_main_app()
00064 {
00065     irq_pin.disable_irq();
00066 #if 0
00067     uint8_t cmd_bytes[] = { SS_FAM_W_MODE, SS_CMDIDX_MODE };
00068     uint8_t data[] = { 0x00 };
00069 
00070     SS_STATUS status = ss_int->write_cmd(
00071             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00072             &data[0], ARRAY_SIZE(data),
00073             SS_STARTUP_TIME);
00074     if (status == SS_SUCCESS)
00075         in_bootldr = false;
00076     return status;
00077 #else
00078     reset_pin.output();
00079     cfg_mfio(PIN_OUTPUT);
00080     reset_pin.write(0);
00081     wait_ms(SS_RESET_TIME);
00082     mfio_pin.write(1);
00083     reset_pin.write(1);
00084     wait_ms(SS_STARTUP_TIME);
00085     cfg_mfio(PIN_INPUT);
00086     reset_pin.input();
00087     // Verify we exited bootloader mode
00088     if (in_bootldr_mode() == 0)
00089         return SS_SUCCESS;
00090     else
00091         return SS_ERR_UNKNOWN;
00092 #endif
00093 
00094     irq_pin.enable_irq();
00095 }
00096 
00097 SS_STATUS SSInterface::reset_to_bootloader()
00098 {
00099     irq_pin.disable_irq();
00100 #if 0
00101     uint8_t cmd_bytes[] = { SS_FAM_W_MODE, SS_CMDIDX_MODE };
00102     uint8_t data[] = { SS_MASK_MODE_BOOTLDR };
00103 
00104     SS_STATUS status = ss_int->write_cmd(
00105             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00106             &data[0], ARRAY_SIZE(data),
00107             SS_STARTUP_TIME);
00108     if (status == SS_SUCCESS)
00109         in_bootldr = true;
00110     return status;
00111 #else
00112     reset_pin.output();
00113     cfg_mfio(PIN_OUTPUT);
00114     reset_pin.write(0);
00115     wait_ms(SS_RESET_TIME);
00116     mfio_pin.write(0);
00117     reset_pin.write(1);
00118     wait_ms(SS_STARTUP_TIME);
00119     cfg_mfio(PIN_INPUT);
00120     reset_pin.input();
00121     // Verify we entered bootloader mode
00122     if (in_bootldr_mode() < 0)
00123         return SS_ERR_UNKNOWN;
00124     return SS_SUCCESS;
00125 #endif
00126 
00127     irq_pin.disable_irq();
00128 }
00129 
00130 SS_STATUS SSInterface::reset()
00131 {
00132     int bootldr = in_bootldr_mode();
00133     if (bootldr > 0)
00134         return reset_to_bootloader();
00135     else if (bootldr == 0)
00136         return reset_to_main_app();
00137     else
00138         return SS_ERR_UNKNOWN;
00139 }
00140 
00141 SS_STATUS SSInterface::self_test(int idx, uint8_t *result, int sleep_ms){
00142     uint8_t cmd_bytes[] = {SS_FAM_R_SELFTEST, idx};
00143     uint8_t rxbuf[2];
00144     SS_STATUS ret;
00145 
00146     result[0] = 0xFF;
00147     ret = read_cmd(cmd_bytes, 2, (uint8_t *)0, 0, rxbuf, ARRAY_SIZE(rxbuf), sleep_ms);
00148     result[0] = rxbuf[1];
00149     return ret;
00150 }
00151 
00152 void SSInterface::cfg_mfio(PinDirection dir)
00153 {
00154     if (dir == PIN_INPUT) {
00155         mfio_pin.input();
00156         mfio_pin.mode(PullUp);
00157     } else {
00158         mfio_pin.output();
00159     }
00160 }
00161 
00162 void SSInterface::enable_irq()
00163 {
00164     irq_pin.enable_irq();
00165 }
00166 void SSInterface::disable_irq()
00167 {
00168     irq_pin.disable_irq();
00169 }
00170 
00171 void SSInterface::mfio_selftest(){
00172     disable_irq();
00173     irq_pin.fall(callback(this, &SSInterface::irq_handler_selftest));
00174     enable_irq();
00175 }
00176 
00177 int SSInterface::in_bootldr_mode()
00178 {
00179     uint8_t cmd_bytes[] = { SS_FAM_R_MODE, SS_CMDIDX_MODE };
00180     uint8_t rxbuf[2] = { 0 };
00181 
00182     SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00183             0, 0,
00184             &rxbuf[0], ARRAY_SIZE(rxbuf));
00185     if (status != SS_SUCCESS)
00186         return -1;
00187 
00188     return (rxbuf[1] & SS_MASK_MODE_BOOTLDR);
00189 }
00190 
00191 const char* SSInterface::get_ss_fw_version()
00192 {
00193     uint8_t cmd_bytes[2];
00194     uint8_t rxbuf[4];
00195 
00196     int bootldr = in_bootldr_mode();
00197 
00198     if (bootldr > 0) {
00199         cmd_bytes[0] = SS_FAM_R_BOOTLOADER;
00200         cmd_bytes[1] = SS_CMDIDX_BOOTFWVERSION;
00201     } else if (bootldr == 0) {
00202         cmd_bytes[0] = SS_FAM_R_IDENTITY;
00203         cmd_bytes[1] = SS_CMDIDX_FWVERSION;
00204     } else {
00205         return plat_name;
00206     }
00207 
00208     SS_STATUS status = read_cmd(
00209              &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00210              0, 0,
00211              &rxbuf[0], ARRAY_SIZE(rxbuf));
00212 
00213     if (status == SS_SUCCESS) {
00214         snprintf(fw_version, sizeof(fw_version),
00215             "%d.%d.%d", rxbuf[1], rxbuf[2], rxbuf[3]);
00216         pr_info("fw_version:%s\r\n", fw_version);
00217     }
00218 
00219     return &fw_version[0];
00220 }
00221 
00222 const char* SSInterface::get_ss_platform_name()
00223 {
00224     uint8_t cmd_bytes[] = { SS_FAM_R_IDENTITY, SS_CMDIDX_PLATTYPE };
00225     uint8_t rxbuf[2];
00226 
00227     SS_STATUS status = read_cmd(
00228             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00229             0, 0,
00230             &rxbuf[0], ARRAY_SIZE(rxbuf));
00231 
00232     if (status == SS_SUCCESS) {
00233         if (rxbuf[1] == SS_PLAT_MAX3263X) {
00234             if (in_bootldr_mode() > 0) {
00235                 plat_name = SS_BOOTLOADER_PLATFORM_MAX3263X;
00236             } else {
00237                 plat_name = SS_PLATFORM_MAX3263X;
00238             }
00239         } else if (rxbuf[1] == SS_PLAT_MAX32660) {
00240             if (in_bootldr_mode() > 0) {
00241                 plat_name = SS_BOOTLOADER_PLATFORM_MAX32660;
00242             } else {
00243                 plat_name = SS_PLATFORM_MAX32660;
00244             }
00245         }
00246     }
00247 
00248     return plat_name;
00249 }
00250 
00251 SS_STATUS SSInterface::write_cmd(uint8_t *cmd_bytes, int cmd_bytes_len,
00252     uint8_t *data, int data_len,
00253     int sleep_ms)
00254 {
00255     int total_len = data_len + cmd_bytes_len;
00256 
00257     if (total_len <= SS_SMALL_BUF_SIZE) {
00258         return write_cmd_small(cmd_bytes, cmd_bytes_len, data, data_len, sleep_ms);
00259     } else if (total_len <= SS_LARGE_BUF_SIZE) {
00260         return write_cmd_large(cmd_bytes, cmd_bytes_len, data, data_len, sleep_ms);
00261     } else {
00262         assert_msg(true, "Tried to send I2C tx larger than maximum allowed size\n");
00263         return SS_ERR_DATA_FORMAT; 
00264     }
00265 }
00266 
00267 SS_STATUS SSInterface::write_cmd(uint8_t *tx_buf, int tx_len, int sleep_ms)
00268 {
00269     pr_info("write_cmd: ");
00270     for (int i = 0; i < tx_len; i++) {
00271         pr_info("0x%02X ", tx_buf[i]);
00272     }
00273     pr_info("\r\n");
00274 
00275     int ret = 0;
00276     ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)tx_buf, tx_len);
00277 
00278     if (ret != 0) {
00279         pr_err("m_i2cBus->write returned %d\r\n", ret);
00280         return SS_ERR_UNAVAILABLE;
00281     }
00282 
00283     wait_ms(sleep_ms);
00284 
00285     char status_byte;
00286     ret |= m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, &status_byte, 1);
00287 
00288     if (ret != 0) {
00289         pr_err("m_i2cBus->read returned %d\r\n", ret);
00290         return SS_ERR_UNAVAILABLE;
00291     }
00292 
00293     pr_info("status_byte: %d\r\n", status_byte);
00294 
00295     return (SS_STATUS)status_byte;
00296 }
00297 
00298 SS_STATUS SSInterface::write_cmd_small(uint8_t *cmd_bytes, int cmd_bytes_len,
00299                        uint8_t *data, int data_len,
00300                        int sleep_ms)
00301 {
00302     uint8_t write_buf[SS_SMALL_BUF_SIZE];
00303     memcpy(write_buf, cmd_bytes, cmd_bytes_len);
00304     memcpy(write_buf + cmd_bytes_len, data, data_len);
00305 
00306     SS_STATUS status = write_cmd(write_buf, cmd_bytes_len + data_len, sleep_ms);
00307     return status;
00308 }
00309 
00310 SS_STATUS SSInterface::write_cmd_large(uint8_t *cmd_bytes, int cmd_bytes_len,
00311                        uint8_t *data, int data_len,
00312                        int sleep_ms)
00313 {
00314     uint8_t write_buf[SS_LARGE_BUF_SIZE];
00315     memcpy(write_buf, cmd_bytes, cmd_bytes_len);
00316     memcpy(write_buf + cmd_bytes_len, data, data_len);
00317 
00318     SS_STATUS status = write_cmd(write_buf, cmd_bytes_len + data_len, sleep_ms);
00319     return status;
00320 }
00321 
00322 SS_STATUS SSInterface::read_cmd(uint8_t *cmd_bytes, int cmd_bytes_len,
00323     uint8_t *data, int data_len,
00324     uint8_t *rxbuf, int rxbuf_sz,
00325     int sleep_ms)
00326 {
00327     int ret = 0;
00328 
00329     pr_info("read_cmd: ");
00330     for (int i = 0; i < cmd_bytes_len; i++) {
00331         pr_info("0x%02X ", cmd_bytes[i]);
00332     }
00333     pr_info("\r\n");
00334 
00335     ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)cmd_bytes, cmd_bytes_len, (data_len != 0));
00336 
00337     if (data_len != 0) {
00338         ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)data, data_len, false);
00339     }
00340 
00341     if (ret != 0) {
00342         pr_err("m_i2cBus->write returned %d\r\n", ret);
00343         return SS_ERR_UNAVAILABLE;
00344     }
00345 
00346     wait_ms(sleep_ms);
00347 
00348     ret |= m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, (char*)rxbuf, rxbuf_sz);
00349 
00350     if (ret != 0) {
00351         pr_err("m_i2cBus->read returned %d\r\n", ret);
00352         return SS_ERR_UNAVAILABLE;
00353     }
00354 
00355     wait_ms(sleep_ms);
00356     pr_info("status_byte: %d\r\n", rxbuf[0]);
00357     pr_info("data: ");
00358     for (int i = 1; i < rxbuf_sz; i++) {
00359         pr_info("0x%02X ", rxbuf[i]);
00360     }
00361     pr_info("\r\n");
00362 
00363     return (SS_STATUS)rxbuf[0];
00364 }
00365 
00366 SS_STATUS SSInterface::get_reg(int idx, uint8_t addr, uint32_t *val)
00367 {
00368     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");
00369 
00370     uint8_t cmd_bytes[] = { SS_FAM_R_REGATTRIBS, (uint8_t)idx };
00371     uint8_t rx_reg_attribs[3] = {0};
00372 
00373     SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00374                                 0, 0,
00375                                 &rx_reg_attribs[0], ARRAY_SIZE(rx_reg_attribs));
00376 
00377     if (status != SS_SUCCESS)
00378         return status;
00379 
00380     int reg_width = rx_reg_attribs[1];
00381 
00382     uint8_t cmd_bytes2[] = { SS_FAM_R_READREG, (uint8_t)idx, addr };
00383     uint8_t rxbuf[5] = {0};
00384 
00385     status = read_cmd(&cmd_bytes2[0], ARRAY_SIZE(cmd_bytes2),
00386                         0, 0,
00387                         &rxbuf[0], ARRAY_SIZE(rxbuf));
00388 
00389     if (status == SS_SUCCESS) {
00390         *val = 0;
00391         for (int i = 0; i < reg_width; i++) {
00392             *val = (*val << 8) | rxbuf[i + 1];
00393         }
00394     }
00395 
00396     return status;
00397 }
00398 
00399 SS_STATUS SSInterface::set_reg(int idx, uint8_t addr, uint32_t val, int byte_size)
00400 {
00401     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");
00402 
00403     uint8_t cmd_bytes[] = { SS_FAM_W_WRITEREG, (uint8_t)idx, addr };
00404     uint8_t data_bytes[4];
00405     for (int i = 0; i < byte_size; i++) {
00406         data_bytes[i] = (val >> (8 * (byte_size - 1)) & 0xFF);
00407     }
00408 
00409     SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00410                                 &data_bytes[0], byte_size);
00411 
00412     return status;
00413 }
00414 
00415 SS_STATUS SSInterface::dump_reg(int idx, addr_val_pair* reg_vals, int reg_vals_sz, int* num_regs)
00416 {
00417     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");
00418 
00419     uint8_t cmd_bytes[] = { SS_FAM_R_REGATTRIBS, (uint8_t)idx };
00420     uint8_t rx_reg_attribs[3] = {0};
00421 
00422     SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00423                                 0, 0,
00424                                 &rx_reg_attribs[0], ARRAY_SIZE(rx_reg_attribs));
00425 
00426     if (status != SS_SUCCESS)
00427         return status;
00428 
00429     int reg_width = rx_reg_attribs[1];
00430     *num_regs = rx_reg_attribs[2];
00431     assert_msg((*num_regs <= reg_vals_sz), "Need to increase reg_vals array to hold all dump_reg data");
00432     assert_msg(((size_t)reg_width <= sizeof(uint32_t)), "IC returned register values greater than 4 bytes in width");
00433 
00434     int dump_reg_sz = (*num_regs) * (reg_width + 1) + 1; //+1 to reg_width for address, +1 for status byte
00435 
00436     uint8_t rxbuf[512];
00437     assert_msg(((size_t)dump_reg_sz <= sizeof(rxbuf)), "Need to increase buffer size to receive dump_reg data");
00438 
00439     cmd_bytes[0] = SS_FAM_R_DUMPREG;
00440     status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00441                                 0, 0,
00442                                 &rxbuf[0], dump_reg_sz, SS_DUMP_REG_SLEEP_MS);
00443 
00444     if (status != SS_SUCCESS)
00445         return status;
00446 
00447     //rxbuf format is [status][addr0](reg_width x [val0])[addr1](reg_width x [val1])...
00448     for (int reg = 0; reg < *num_regs; reg++) {
00449         reg_vals[reg].addr = rxbuf[(reg * (reg_width + 1)) + 1];
00450         uint32_t *val = &(reg_vals[reg].val);
00451         *val = 0;
00452         for (int byte = 0; byte < reg_width; byte++) {
00453             *val = (*val << 8) | rxbuf[(reg * (reg_width + 1)) + byte + 2];
00454         }
00455     }
00456 
00457     return SS_SUCCESS;
00458 }
00459 
00460 SS_STATUS SSInterface::enable_sensor(int idx, int mode, ss_data_req *data_req)
00461 {
00462     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");
00463     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");
00464     assert_msg((mode != 0), "Tried to enable sensor to mode 0, but mode 0 is disable");
00465 
00466     uint8_t cmd_bytes[] = { SS_FAM_W_SENSORMODE, (uint8_t)idx, (uint8_t)mode };
00467 
00468     SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS);
00469 
00470     if (status == SS_SUCCESS) {
00471         sensor_enabled_mode[idx] = mode;
00472         sensor_data_reqs[idx] = data_req;
00473     }
00474     return status;
00475 }
00476 
00477 SS_STATUS SSInterface::disable_sensor(int idx)
00478 {
00479     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");
00480     uint8_t cmd_bytes[] = { SS_FAM_W_SENSORMODE, (uint8_t)idx, 0 };
00481 
00482     SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS);
00483 
00484     if (status == SS_SUCCESS) {
00485         sensor_enabled_mode[idx] = 0;
00486         sensor_data_reqs[idx] = 0;
00487     }
00488 
00489     return status;
00490 }
00491 
00492 SS_STATUS SSInterface::enable_algo(int idx, int mode, ss_data_req *data_req)
00493 {
00494     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");
00495     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");
00496     assert_msg((mode != 0), "Tried to enable algo to mode 0, but mode 0 is disable");
00497 
00498     uint8_t cmd_bytes[] = { SS_FAM_W_ALGOMODE, (uint8_t)idx, (uint8_t)mode };
00499 
00500     SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS);
00501 
00502     if (status == SS_SUCCESS) {
00503         algo_enabled_mode[idx] = mode;
00504         algo_data_reqs[idx] = data_req;
00505     }
00506 
00507     return status;
00508 }
00509 
00510 SS_STATUS SSInterface::disable_algo(int idx)
00511 {
00512     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");
00513     uint8_t cmd_bytes[] = { SS_FAM_W_ALGOMODE, (uint8_t)idx, 0 };
00514 
00515     SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS);
00516 
00517     if (status == SS_SUCCESS) {
00518         algo_enabled_mode[idx] = 0;
00519         algo_data_reqs[idx] = 0;
00520     }
00521 
00522     return status;
00523 }
00524 
00525 SS_STATUS SSInterface::set_data_type(int data_type, bool sc_en)
00526 {
00527     assert_msg((data_type >= 0) && (data_type <= 3), "Invalid value for data_type");
00528     uint8_t cmd_bytes[] = { SS_FAM_W_COMMCHAN, SS_CMDIDX_OUTPUTMODE };
00529     uint8_t data_bytes[] = { (uint8_t)((sc_en ? SS_MASK_OUTPUTMODE_SC_EN : 0) |
00530                             ((data_type << SS_SHIFT_OUTPUTMODE_DATATYPE) & SS_MASK_OUTPUTMODE_DATATYPE)) };
00531 
00532     SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00533                                 &data_bytes[0], ARRAY_SIZE(data_bytes));
00534 
00535     this->data_type = data_type;
00536     this->sc_en = sc_en;
00537 
00538     return status;
00539 }
00540 
00541 
00542 SS_STATUS SSInterface::get_data_type(int *data_type, bool *sc_en)
00543 {
00544     uint8_t cmd_bytes[] = { SS_FAM_R_COMMCHAN, SS_CMDIDX_OUTPUTMODE };
00545     uint8_t rxbuf[2] = {0};
00546 
00547     SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00548                                 0, 0,
00549                                 &rxbuf[0], ARRAY_SIZE(rxbuf));
00550     if (status == SS_SUCCESS) {
00551         *data_type =
00552             (rxbuf[1] & SS_MASK_OUTPUTMODE_DATATYPE) >> SS_SHIFT_OUTPUTMODE_DATATYPE;
00553         *sc_en =
00554             (bool)((rxbuf[1] & SS_MASK_OUTPUTMODE_SC_EN) >> SS_SHIFT_OUTPUTMODE_SC_EN);
00555     }
00556 
00557     return status;
00558 }
00559 
00560 void SSInterface::fifo_sample_size(int data_type, int *sample_size)
00561 {
00562     *sample_size = 0;
00563 
00564     if (data_type == SS_DATATYPE_RAW || data_type == SS_DATATYPE_BOTH) {
00565         for (int i = 0; i < SS_MAX_SUPPORTED_SENSOR_NUM; i++) {
00566             if (sensor_enabled_mode[i]) {
00567                 assert_msg(sensor_data_reqs[i], "no ss_data_req found for enabled sensor");
00568                 *sample_size += sensor_data_reqs[i]->data_size;
00569             }
00570         }
00571     }
00572 
00573     if (data_type == SS_DATATYPE_ALGO || data_type == SS_DATATYPE_BOTH) {
00574         for (int i = 0; i < SS_MAX_SUPPORTED_ALGO_NUM; i++) {
00575             if (algo_enabled_mode[i]) {
00576                 assert_msg(algo_data_reqs[i], "no ss_data_req found for enabled algo");
00577                 *sample_size += algo_data_reqs[i]->data_size;
00578             }
00579         }
00580     }
00581 }
00582 
00583 SS_STATUS SSInterface::num_avail_samples(int *num_samples)
00584 {
00585     uint8_t cmd_bytes[] = { SS_FAM_R_OUTPUTFIFO, SS_CMDIDX_OUT_NUMSAMPLES };
00586     uint8_t rxbuf[2] = {0};
00587 
00588     SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00589                                 0, 0,
00590                                 &rxbuf[0], ARRAY_SIZE(rxbuf));
00591 
00592     if (status == SS_SUCCESS) {
00593         *num_samples = rxbuf[1];
00594     }
00595 
00596     return status;
00597 }
00598 
00599 SS_STATUS SSInterface::read_fifo_data(
00600     int num_samples, int sample_size,
00601     uint8_t* databuf, int databuf_sz)
00602 {
00603     int bytes_to_read = num_samples * sample_size + 1; //+1 for status byte
00604     assert_msg((bytes_to_read <= databuf_sz), "databuf too small");
00605 
00606     uint8_t cmd_bytes[] = { SS_FAM_R_OUTPUTFIFO, SS_CMDIDX_READFIFO };
00607 
00608     pr_err("[reading %d bytes (%d samples)\r\n", bytes_to_read, num_samples);
00609 
00610     SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00611                                 0, 0,
00612                                 databuf, bytes_to_read, 15);
00613 
00614     return status;
00615 }
00616 
00617 void SSInterface::irq_handler()
00618 {
00619     uint8_t databuf[512];
00620     uint8_t sample_count;
00621 
00622     uint8_t cmd_bytes[] = { SS_FAM_R_STATUS, SS_CMDIDX_STATUS };
00623     uint8_t rxbuf[2] = {0};
00624 
00625     irq_pin.disable_irq();
00626 
00627     SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
00628                                 0, 0,
00629                                 &rxbuf[0], ARRAY_SIZE(rxbuf));
00630 
00631     if (status != SS_SUCCESS) {
00632         pr_err("Couldn't read status byte of SmartSensor!");
00633         irq_pin.enable_irq();
00634         return;
00635     }
00636 
00637     if (rxbuf[1] & SS_MASK_STATUS_ERR) {
00638         pr_err("SmartSensor status error: %d", rxbuf[1] & SS_MASK_STATUS_ERR);
00639     }
00640     if (rxbuf[1] & SS_MASK_STATUS_FIFO_OUT_OVR) {
00641         pr_err("SmartSensor Output FIFO overflow!");
00642     }
00643     if (rxbuf[1] & SS_MASK_STATUS_FIFO_IN_OVR) {
00644         pr_err("SmartSensor Input FIFO overflow!");
00645     }
00646 
00647     if (rxbuf[1] & SS_MASK_STATUS_DATA_RDY) {
00648         int num_samples;
00649         status = num_avail_samples(&num_samples);
00650         if (status != SS_SUCCESS)
00651         {
00652             pr_err("Couldn't read number of available samples in SmartSensor Output FIFO");
00653             irq_pin.enable_irq();
00654             return;
00655         }
00656 
00657         if (num_samples <= 0)
00658         {
00659             irq_pin.enable_irq();
00660             return;
00661         }
00662 
00663 
00664         int sample_size;
00665         fifo_sample_size(data_type, &sample_size);
00666 
00667         size_t bytes_to_read = num_samples * sample_size + 1; //+1 for status byte
00668         if (bytes_to_read > sizeof(databuf)) {
00669             //Reduce number of samples to read to fit in buffer
00670             num_samples = (sizeof(databuf) - 1) / sample_size;
00671         }
00672 
00673         status = read_fifo_data(num_samples, sample_size, &databuf[0], sizeof(databuf));
00674         if (status != SS_SUCCESS)
00675         {
00676             pr_err("Couldn't read from SmartSensor Output FIFO");
00677             irq_pin.enable_irq();
00678             return;
00679         }
00680 
00681         //Skip status byte
00682         uint8_t *data_ptr = &databuf[1];
00683 
00684         int i = 0;
00685         for (i = 0; i < num_samples; i++) {
00686             if (sc_en) {
00687                 sample_count = *data_ptr++;
00688                 pr_info("Received sample #%d", sample_count);
00689             }
00690                 
00691             //Chop up data and send to modules with enabled sensors
00692             if (data_type == SS_DATATYPE_RAW || data_type == SS_DATATYPE_BOTH) {
00693                 for (int i = 0; i < SS_MAX_SUPPORTED_SENSOR_NUM; i++) {
00694                     if (sensor_enabled_mode[i]) {
00695                         assert_msg(sensor_data_reqs[i], 
00696                                 "no ss_data_req found for enabled sensor");
00697                         sensor_data_reqs[i]->callback(data_ptr);
00698                         data_ptr += sensor_data_reqs[i]->data_size;
00699                     }
00700                 }
00701             }
00702             if (data_type == SS_DATATYPE_ALGO || data_type == SS_DATATYPE_BOTH) {
00703                 for (int i = 0; i < SS_MAX_SUPPORTED_ALGO_NUM; i++) {
00704                     if (algo_enabled_mode[i]) {
00705                         assert_msg(algo_data_reqs[i], 
00706                                 "no ss_data_req found for enabled algo");
00707                         algo_data_reqs[i]->callback(data_ptr);
00708                         data_ptr += algo_data_reqs[i]->data_size;
00709                     }
00710                 }
00711             }
00712         }
00713     }
00714     irq_pin.enable_irq();
00715 }
00716 
00717 void SSInterface::irq_handler_selftest(){
00718     mfio_int_happened = true;
00719 }
00720 
00721 bool SSInterface::reset_mfio_irq(){
00722     bool ret = mfio_int_happened;
00723     mfio_int_happened = false;
00724     irq_pin.disable_irq();
00725     irq_pin.fall(callback(this, &SSInterface::irq_handler));
00726     irq_pin.enable_irq();
00727     return ret;
00728 }