Maxim Integrated / Mbed OS MAXREFDES220#

Dependencies:   USBDevice max32630fthr

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 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 }