test
Dependencies: BMI160 max32630hsp3 MemoryLCD USBDevice
Diff: SHComm/SHComm.cpp
- Revision:
- 0:ac4dea3e2894
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SHComm/SHComm.cpp Mon Mar 18 10:21:53 2019 +0300 @@ -0,0 +1,1411 @@ +/* + * SHcomm.cpp + * + * Created on: Nov 16, 2018 + * Author: Yagmur.Gok + */ + +/* +#ifdef __cplusplus +extern "C" { +#endif +*/ + +#include <events/mbed_events.h> +#include <mbed.h> +#include "mbed.h" + +#include "SHComm.h" + + +#define SS_I2C_8BIT_SLAVE_ADDR 0xAA +#define SENSORHUB_I2C_ADRESS SS_I2C_8BIT_SLAVE_ADDR + +#define ENABLED ((int)(1)) +#define DISABLED ((int)(0)) + +#define SS_DUMP_REG_SLEEP_MS (100) +#define SS_ENABLE_SENSOR_SLEEP_MS (20) +#define SS_DEFAULT_CMD_SLEEP_MS (2) +#define SS_WAIT_BETWEEN_TRIES_MS (2) +#define SS_CMD_WAIT_PULLTRANS_MS (5) +#define SS_FEEDFIFO_CMD_SLEEP_MS (30) + + +#define SS_DEFAULT_RETRIES ((int) (4)) +#define SS_ZERO_DELAY 0 +#define SS_ZERO_BYTES 0 + + +/*define sample size of algorithm and raw sensor data in bytes*/ +#define SH_ALGO_WHRM_SAMPLE_DATABYTES 4 +#define SH_ALGO_SP02_SAMPLE_DATABYTES 4 + + +/*define command sequences given in Maxim ME32664 user manual*/ +#define SH_GET_HUB_STATUS_CMDSEQ {0x00,0x00} +#define SH_SET_OPERATING_MODE_CMDSEQ(opMode) {0x01,0x00,opMode} + #define SH_SET_OPERATING_MODE_BOOTLOADER_CMDSEQ {0x02,0x00,0x08} + #define SH_SET_OPERATING_MODE_APPLICATION_CMDSEQ {0x02,0x00,0x00} + #define SH_SET_OPERATING_MODE_RESET_CMDSEQ {0x02,0x00,0x02} +#define SH_GET_OPERATING_MODE_CMDSEQ {0x02,0x00} + +#define SH_SET_OUTPUT_MODE_CMDSEQ( outMode) {0x10,0x00, outMode} + #define SH_SET_OUTMODE_NODATA_CMDSEQ {0x10,0x00,0x00} + #define SH_SET_OUTMODE_SENSORDATA_CMDSEQ {0x10,0x00,0x01} + #define SH_SET_OUTMODE_ALGODATA_CMDSEQ {0x10,0x00,0x02} + #define SH_SET_OUTMODE_PAUSE_CMDSEQ {0x10,0x00,0x04} + #define SH_SET_OUTMODE_SENSAMPLECNT_CMDSEQ {0x10,0x00,0x05} + #define SH_SET_OUTMODE_ALGOSAMPLECNT_CMDSEQ {0x10,0x00,0x06} + #define SH_SET_OUTMODE_ALGOSENSAMPLECNT_CMDSEQ {0x10,0x00,0x07} + +#define SH_GET_OUTPUT_MODE_CMDSEQ {0x11,0x00} + +#define SH_DFIFO_SET_INT_THRESHOLD_CMDSEQ( ucThreshold ) {0x10,0x01,ucThreshold} +#define SH_DFIFO_GET_INT_THRESHOLD_CMDSEQ {0x11,0x01} + +#define SH_DFIFO_GET_NSAMPLES_CMDSEQ {0x12,0x00} +#define SH_DFIFO_PULL_SAMPLE_CMDSEQ {0x12,0x01} +#define SH_GET_EXTINPUT_FIFOSZ_CMDSEQ {0x13,0x01} +#define SH_GET_SAMPLEBYTECNT_INPUTFIFO_CMDSEQ {0x13,0x04} +#define SH_FEED_TO_INPUTFIFO_CMDSEQ {0x14,0x00} + +#define SH_WRITE_SENSORREG_CMDSEQ( sensorIdx , regAddr ) { 0x40, sensorIdx , regAddr} +#define SH_READ_SENSORREG_CMDSEQ( sensorIdx , regAddr ) { 0x41, sensorIdx , regAddr} +#define SH_READ_AFE_ATTRIBUTES_CMDSEQ(sensorIdx) { 0x42, sensorIdx} +#define SH_READ_ALLREGISTERS_CMDSEQ(sensorIdx) { 0x43, sensorIdx} + +#define SH_ENABLE_SENSOR_CMDSEQ(sensorIdx , extMode) {0x44, sensorIdx, 0x01 , extMode } +#define SH_DISABLE_SENSOR_CMDSEQ(sensorIdx) {0x44, sensorIdx, 0x00} + + +#define SH_AGC_SET_ADCRANGE_CMDSEQ( uiPercentage) {0x50, 0x00, 0x00 , uiPercentage} +#define SH_AGC_SET_STEPSZ_CMDSEQ( uiPercentage) {0x50, 0x00, 0x01 , uiPercentage} +#define SH_AGC_SET_SENSITIVITY_CMDSEQ( uiPercentage) {0x50, 0x00, 0x02 , uiPercentage} +#define SH_AGC_SET_NSAMPLESAVRAGING_CMDSEQ( ucNsamples) {0x50, 0x00, 0x03 , uiNsamples} +#define SH_WHRM_SET_SAMPRATE_CMDSEQ( ucNsamples) {0x50, 0x02, 0x03 , uiNsamples} + + +#define SH_ENABLE_ALGO_CMDSEQ( algoIdx) { 0x52, algoIdx , 0x01} +#define SH_DISABLE_ALGO_CMDSEQ( algoIdx) { 0x52, algoIdx , 0x00} + +#define SH_SET_ALGO_CONFIGURATION_CMDSEQ( algoIdx, cgfIdx) { 0x50 , algoIdx, cgfIdx } +#define SH_GET_ALGO_CONFIGURATION_CMDSEQ( algoIdx, cgfIdx) { 0x51 , algoIdx, cgfIdx } + +#define SH_COMM_CHECK_CMDSEQ {0xFF, 0x00} + + + +//phase2 additions +#define SH_CHECKIF_BOOTLDRMODE_CMDSEQ { 0x02, 0x00 } +#define SH_SELFTEST_CMDSEQ(idx) { 0x70, (uint8_t)idx } +#define SH_EXIT_BOOTLDRMODE_CMDSEQ { 0x01, 0x00 } +#define SH_GETLOGSIZE_CMDSEQ { 0x90, 0x01 } +#define SH_READHUBLOGS_CMDSEQ { 0x90, 0x00 } + +#define SH_GET_BOOTLDRPAGESIZE_CMDSEQ { 0x81, 0x01 } +#define SH_SET_BOOTLDRPAGECOUNT_CMDSEQ { 0x80, 0x02 } + +#define BOOTLOADER_MAX_PAGE_SIZE 8192 + +/* BOOTLOADER HOST */ +#define EBL_CMD_TRIGGER_MODE 0 +#define EBL_GPIO_TRIGGER_MODE 1 + + + +/* + * define the "platform specific" hardware interface which SSinterface requires: + * 1. master i2c port + * 2. interrupt attachable I/O pin (mfio) + * 3. I/O pin for reset + * Note: Definitions below are for MAX32630FTR Pagasus board . Modify for your platform. + **/ + +I2C *m_i2cBus; /*i2c bus sensor hub is connected to*/ + +PinName ss_mfio(P5_4); /* platform specific mfio event pin */ +PinName ss_reset(P5_6); /* platform specific sensor hub reset pin */ +DigitalInOut mfio_pin(ss_mfio); /* mfio pin mode be I/O */ +DigitalInOut reset_pin(ss_reset); /* reset pin mode be I/O */ +InterruptIn irq_pin(ss_mfio); /* define mfio pin interrupt attachable*/ + + +/* + * SSI API funcions + * NOTE: Generic functions for any platform. + * exceptions: below needs needs modification according to platform and HAL drivers + * 1. Hard reset function + * 2. Enable/disable mfio event interrput + * 3. mfio pin interrupt routine + * + * **/ + +/*global buffer for sensor i2c commands+data*/ +uint8_t sh_write_buf[512]; +static volatile bool m_irq_received_ = false; +static volatile bool mfio_int_happened = false; + +/* sensor hub states */ +static bool sc_en = false; +static int data_type = 0; +static int is_sensor_enabled[SS_MAX_SUPPORTED_SENSOR_NUM] = {0}; +static int is_algo_enabled[SS_MAX_SUPPORTED_ALGO_NUM] = {0}; +static int enabled_algo_mode[SS_MAX_SUPPORTED_ALGO_NUM] = {0}; +static int sensor_sample_sz[SS_MAX_SUPPORTED_SENSOR_NUM] = {0}; +static int algo_sample_sz[SS_MAX_SUPPORTED_ALGO_NUM] = {0}; + +/* Mode to control sesnor hub resets. ie via GPIO based hard reset or Command based soft reset*/ +static uint8_t ebl_mode = EBL_GPIO_TRIGGER_MODE; + +/* desc : + * Func to init master i2c hardware comm interface with sennor hub + * init mfio interrupt pin and attach irq to pin + * init reset pin + * params: + * N/A + */ + + +void sh_irq_handler(); +void sh_init_hwcomm_interface(){ + static I2C ssI2C(P3_4, P3_5); /*set up sensor hub i2c communication at 400 kHz*/ + ssI2C.frequency(400000); + m_i2cBus = &ssI2C; + + reset_pin.input(); + reset_pin.mode(PullUp); + mfio_pin.input(); /*set mfio as input for getting mfio event reporting when sesnor hub is on application mode */ + mfio_pin.mode(PullUp); + + irq_pin.fall(sh_irq_handler); /*attach falling edge interrupt to mfio pin for mfio event reporting */ + + return; +} + +/* mfio pin event reporting related interrupt functions*/ +/* + * data ready event reporting isr from sensor hub + * + * params: + * N/A + * */ +void sh_irq_handler() +{ + m_irq_received_ = true; +} +void sh_clear_mfio_event_flag(void){ + m_irq_received_ = false; +} + +bool sh_has_mfio_event(void){ + return m_irq_received_; +} + +/* desc: + * func to enable event reporting from sensor hub + * + * params: + * N/A + * */ +void sh_enable_irq_mfioevent(void) +{ + irq_pin.enable_irq(); +} + +/* desc: + * func to disable event reporting from sensor hub + * + * params: + * N/A + * */ +void sh_disable_irq_mfioevent(void) +{ + irq_pin.disable_irq(); +} + +/* desc: + * reset event reporting process from sensor hub, on host side + * + * params: + * N/A + **/ +bool sh_reset_mfio_irq(){ + bool ret = mfio_int_happened; + mfio_int_happened = false; + sh_disable_irq_mfioevent(); + irq_pin.fall(sh_irq_handler); + sh_enable_irq_mfioevent(); + return ret; +} + + +/* + * desc: + * function to reset sensor hub and put to application mode after reset interface and get data format. + * + * params: + * + * __I wakeupMode : 0x00 : application mode + * 0x08 : bootloader mode + * */ +int sh_hard_reset(int wakeupMode){ + + int status; + sh_disable_irq_mfioevent(); + reset_pin.output(); + mfio_pin.output(); + + reset_pin.write(0); + wait_ms(SS_RESET_TIME); + + if( (wakeupMode & 0xFF) == 0 ) { + + mfio_pin.write(1); + reset_pin.write(1); + wait_ms(SS_STARTUP_TO_MAIN_APP_TIME); + + }else { + + mfio_pin.write(0); + reset_pin.write(1); + wait_ms(SS_STARTUP_TO_BTLDR_TIME); + } + mfio_pin.input(); + mfio_pin.mode(PullUp); + reset_pin.input(); + sh_enable_irq_mfioevent(); + + +} + + +int sh_set_ebl_mode(const uint8_t mode) +{ + int status; + if (mode == EBL_CMD_TRIGGER_MODE || mode == EBL_GPIO_TRIGGER_MODE) { + ebl_mode = mode; + status = SS_SUCCESS; + } else + status = SS_ERR_INPUT_VALUE; + + return status; +} + +const int sh_get_ebl_mode(void) +{ + return ebl_mode; +} + +int sh_reset_to_bootloader(void){ + + int status; + uint8_t hubMode; + + if(ebl_mode == EBL_GPIO_TRIGGER_MODE) + sh_hard_reset(0x08); + if(ebl_mode == EBL_CMD_TRIGGER_MODE) + status = sh_set_sensorhub_operating_mode(0x08); + + status = sh_get_sensorhub_operating_mode(&hubMode); + if( status != 0x00 /*SS_SUCCESS*/ || hubMode != 0x08 ){ + status = -1; + } + + return status; + +} + +static bool in_bootldr; + + +int in_bootldr_mode() +{ + uint8_t cmd_bytes[] = { SS_FAM_R_MODE, SS_CMDIDX_MODE }; + uint8_t rxbuf[2] = { 0 }; + + int status = sh_read_cmd(&cmd_bytes[0], sizeof(cmd_bytes), + 0, 0, + &rxbuf[0], sizeof(rxbuf), SS_DEFAULT_CMD_SLEEP_MS); + if (status != SS_SUCCESS) + return -1; + + return (rxbuf[1] & SS_MASK_MODE_BOOTLDR); +} + +int exit_from_bootloader(void) +{ + uint8_t cmd_bytes[] = { SS_FAM_W_MODE, SS_CMDIDX_MODE }; + uint8_t data[] = { 0x00 }; + + int status = sh_write_cmd_with_data( &cmd_bytes[0], sizeof(cmd_bytes), + &data[0], 1 /*sizeof(data)*/, + 10*SS_DEFAULT_CMD_SLEEP_MS); + + in_bootldr = (status == SS_SUCCESS) ? true : false; + + return status; +} + +static int stay_in_bootloader() +{ + uint8_t cmd_bytes[] = { SS_FAM_W_MODE, SS_CMDIDX_MODE }; + uint8_t data[] = { SS_MASK_MODE_BOOTLDR }; + + int status = sh_write_cmd_with_data( + &cmd_bytes[0], sizeof(cmd_bytes), + &data[0], sizeof(data), SS_DEFAULT_CMD_SLEEP_MS); + + in_bootldr = (status == SS_SUCCESS) ? true : false; + return status; +} + + +static void cfg_mfio(PinDirection dir) +{ + if (dir == PIN_INPUT) { + mfio_pin.input(); + mfio_pin.mode(PullUp); + } else { + sh_enable_irq_mfioevent(); + mfio_pin.output(); + } +} + +int sh_debug_reset_to_bootloader(void) +{ + + int status = -1; + + sh_disable_irq_mfioevent(); + if (ebl_mode == EBL_GPIO_TRIGGER_MODE) { + + reset_pin.output(); + cfg_mfio(PIN_OUTPUT); + reset_pin.write(0); + wait_ms(SS_RESET_TIME); + mfio_pin.write(0); + reset_pin.write(1); + wait_ms(SS_STARTUP_TO_BTLDR_TIME); + cfg_mfio(PIN_INPUT); + reset_pin.input(); + sh_enable_irq_mfioevent(); + stay_in_bootloader(); + if (in_bootldr_mode() < 0) + status = SS_ERR_UNKNOWN; + else + status = SS_SUCCESS; + + }else{ + stay_in_bootloader(); + sh_enable_irq_mfioevent(); + status = SS_SUCCESS; + + } + + return status; +} + + +int sh_reset_to_main_app(void) +{ + int status = -1; + sh_disable_irq_mfioevent(); + if (ebl_mode == EBL_GPIO_TRIGGER_MODE) { + + reset_pin.output(); + cfg_mfio(PIN_OUTPUT); + mfio_pin.write(0); + wait_ms(SS_RESET_TIME - 5); + reset_pin.write(0); + wait_ms(SS_RESET_TIME - 5); + mfio_pin.write(1); + wait_ms(SS_RESET_TIME - 5); + reset_pin.write(1); + //wait_ms(50); + //mfio_pin.write(0); + wait_ms(2*SS_STARTUP_TO_MAIN_APP_TIME); + cfg_mfio(PIN_INPUT); + reset_pin.input(); + + sh_enable_irq_mfioevent(); + // Verify we exited bootloader mode + if (in_bootldr_mode() == 0) + status = SS_SUCCESS; + else + status = SS_ERR_UNKNOWN; + }else{ + status = exit_from_bootloader(); + sh_enable_irq_mfioevent(); + } + + return status; + +} + +/* + * desc: + * function to init sensor comm interface and get data format. + * + * */ +void sh_init_hubinterface(void){ + + sh_init_hwcomm_interface(); + //sh_get_data_type(&data_type, &sc_en); + return; +} + + +/* + * + * SENSOR HUB COMMUNICATION INTERFACE ( Defined in MAX32664 User Guide ) API FUNCTIONS + * + * + * */ + + +//PHASE2 ADDITIONS: + +int sh_self_test(int idx, uint8_t *result, int sleep_ms){ + + uint8_t cmd_bytes[] = { SS_FAM_R_SELFTEST, (uint8_t)idx }; // = SH_SELFTEST_CMDSEQ; + uint8_t rxbuf[2]; + result[0] = 0xFF; + + int status = sh_read_cmd(&cmd_bytes[0],sizeof(cmd_bytes) , + 0, 0, + &rxbuf[0], sizeof(rxbuf), + sleep_ms ); + + if (status != SS_SUCCESS) + return SS_ERR_TRY_AGAIN; + + result[0] = rxbuf[1]; + return status; +} + +const char* sh_get_hub_fw_version(void) +{ + uint8_t cmd_bytes[2]; + uint8_t rxbuf[4]; + + static char fw_version[32] = "SENSORHUB"; + + int bootldr = sh_checkif_bootldr_mode(); + + if (bootldr > 0) { + cmd_bytes[0] = SS_FAM_R_BOOTLOADER; + cmd_bytes[1] = SS_CMDIDX_BOOTFWVERSION; + } else if (bootldr == 0) { + cmd_bytes[0] = SS_FAM_R_IDENTITY; + cmd_bytes[1] = SS_CMDIDX_FWVERSION; + } else { + + return &fw_version[0]; + } + + int status = sh_read_cmd( &cmd_bytes[0], sizeof(cmd_bytes), + 0, 0, + &rxbuf[0], sizeof(rxbuf), + SS_DEFAULT_CMD_SLEEP_MS ); + + if (status == SS_SUCCESS) { + snprintf(fw_version, sizeof(fw_version), + "%d.%d.%d", rxbuf[1], rxbuf[2], rxbuf[3]); + } + + return &fw_version[0]; +} + + +const char* sh_get_hub_algo_version(void) +{ + uint8_t cmd_bytes[3]; + uint8_t rxbuf[4]; + + static char algo_version[64] = "SENSORHUBALGORITHMS"; + + int bootldr = sh_checkif_bootldr_mode(); + + if (bootldr > 0) { + cmd_bytes[0] = SS_FAM_R_BOOTLOADER; + cmd_bytes[1] = SS_CMDIDX_BOOTFWVERSION; + cmd_bytes[2] = 0; + } else if (bootldr == 0) { + cmd_bytes[0] = SS_FAM_R_IDENTITY; + cmd_bytes[1] = SS_CMDIDX_ALGOVER; + cmd_bytes[2] = SS_CMDIDX_AVAILSENSORS; + } else { + + return &algo_version[0]; + } + + int status = sh_read_cmd( &cmd_bytes[0], sizeof(cmd_bytes), + 0, 0, + &rxbuf[0], sizeof(rxbuf), + SS_DEFAULT_CMD_SLEEP_MS ); + + if (status == SS_SUCCESS) { + snprintf(algo_version, sizeof(algo_version), + "%d.%d.%d", rxbuf[1], rxbuf[2], rxbuf[3]); + + } + + return &algo_version[0]; +} + +int sh_send_raw(uint8_t *rawdata, int rawdata_sz) +{ + return sh_write_cmd(&rawdata[0], rawdata_sz, 5 * SS_ENABLE_SENSOR_SLEEP_MS); +} + +int sh_get_log_len(int *log_len) +{ + uint8_t cmd_bytes[] = { SS_FAM_R_LOG, SS_CMDIDX_R_LOG_LEN }; // = SH_GETLOGSIZE_CMDSEQ; + uint8_t rxbuf[2] = {0}; + int logLen = 0; + + int status = sh_read_cmd(&cmd_bytes[0], sizeof(cmd_bytes), + 0, 0, + &rxbuf[0], sizeof(rxbuf), + SS_DEFAULT_CMD_SLEEP_MS ); + + if (status == SS_SUCCESS) { + logLen = (rxbuf[1] << 8) | rxbuf[0]; + } + *log_len = logLen; + + return status; +} + +int sh_read_ss_log(int num_bytes, uint8_t *log_buf, int log_buf_sz) +{ + int bytes_to_read = num_bytes + 1; //+1 for status byte + //mxm_assert_msg((bytes_to_read <= log_buf_sz), "log_buf too small"); + + uint8_t cmd_bytes[] = { SS_FAM_R_LOG, SS_CMDIDX_R_LOG_DATA }; // = SH_READHUBLOGS_CMDSEQ; + + int status = sh_read_cmd(&cmd_bytes[0], sizeof(cmd_bytes), + 0, 0, + log_buf, bytes_to_read, + SS_CMD_WAIT_PULLTRANS_MS ); + + return status; +} + +// END OF PHASE2 ADDITIONS + + + + +int sh_write_cmd( uint8_t *tx_buf, + int tx_len, + int sleep_ms) +{ + int retries = SS_DEFAULT_RETRIES; + int ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)tx_buf, tx_len); + while (ret != 0 && retries-- > 0) { + + wait_ms(1); + ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)tx_buf, tx_len); + } + if (ret != 0) + return SS_ERR_UNAVAILABLE; + + + wait_ms(sleep_ms); + + char status_byte; + ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, &status_byte, 1); + bool try_again = (status_byte == SS_ERR_TRY_AGAIN); + while ((ret != 0 || try_again) + && retries-- > 0) { + wait_ms(sleep_ms); + ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, &status_byte, 1); + try_again = (status_byte == SS_ERR_TRY_AGAIN); + } + + if (ret != 0 || try_again) + return SS_ERR_UNAVAILABLE; + + return (int) (SS_STATUS)status_byte; +} + + +int sh_write_cmd_with_data(uint8_t *cmd_bytes, + int cmd_bytes_len, + uint8_t *data, + int data_len, + int cmd_delay_ms) +{ + memcpy(sh_write_buf, cmd_bytes, cmd_bytes_len); + memcpy(sh_write_buf + cmd_bytes_len, data, data_len); + int status = sh_write_cmd(sh_write_buf,cmd_bytes_len + data_len, cmd_delay_ms); + return status; +} + + +int sh_read_cmd( uint8_t *cmd_bytes, + int cmd_bytes_len, + uint8_t *data, + int data_len, + uint8_t *rxbuf, + int rxbuf_sz, + int sleep_ms ) +{ + + int retries = SS_DEFAULT_RETRIES; + + int ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)cmd_bytes, cmd_bytes_len, (data_len != 0)); + if (data_len != 0) + ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)data, data_len, false); + + + while (ret != 0 && retries-- > 0) { + wait_ms(1); + ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)cmd_bytes, cmd_bytes_len, (data_len != 0)); + if (data_len != 0) + ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)data, data_len, false); + + } + if (ret != 0) + return SS_ERR_UNAVAILABLE; + + + wait_ms(sleep_ms); + + ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, (char*)rxbuf, rxbuf_sz); + bool try_again = (rxbuf[0] == SS_ERR_TRY_AGAIN); + while ((ret != 0 || try_again) && retries-- > 0) { + wait_ms(sleep_ms); + ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, (char*)rxbuf, rxbuf_sz); + try_again = (rxbuf[0] == SS_ERR_TRY_AGAIN); + } + if (ret != 0 || try_again) + return SS_ERR_UNAVAILABLE; + + return (int) ((SS_STATUS)rxbuf[0]); +} + + + +int sh_get_sensorhub_status(uint8_t *hubStatus){ + + uint8_t ByteSeq[] = SH_GET_HUB_STATUS_CMDSEQ; + uint8_t rxbuf[2] = { 0 }; + + int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq), + 0, 0, + &rxbuf[0], sizeof(rxbuf), + SS_DEFAULT_CMD_SLEEP_MS); + + *hubStatus = rxbuf[1]; + return status; +} + + +int sh_get_sensorhub_operating_mode(uint8_t *hubMode){ + + uint8_t ByteSeq[] = SH_GET_OPERATING_MODE_CMDSEQ; + uint8_t rxbuf[2] = { 0 }; + + int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq), + 0, 0, + &rxbuf[0], sizeof(rxbuf), + SS_DEFAULT_CMD_SLEEP_MS); + + *hubMode = rxbuf[1]; + return status; +} + + +int sh_set_sensorhub_operating_mode(uint8_t hubMode){ + + uint8_t ByteSeq[] = SH_SET_OPERATING_MODE_CMDSEQ(hubMode); + int status = sh_write_cmd( &ByteSeq[0],sizeof(ByteSeq), SS_DEFAULT_CMD_SLEEP_MS); + return status; + +} + + +//int sh_set_data_type( uint8_t outMode) +int sh_set_data_type(int data_type_, bool sc_en_) +{ + +#if 0 + uint8_t dataTypeSc = (uint8_t)((sc_en ? SS_MASK_OUTPUTMODE_SC_EN : 0) | ((data_type << SS_SHIFT_OUTPUTMODE_DATATYPE) & SS_MASK_OUTPUTMODE_DATATYPE)); + uint8_t ByteSeq[] = SH_SET_OUTPUT_MODE_CMDSEQ( dataTypeSc); + int status = sh_write_cmd( &ByteSeq[0],sizeof(ByteSeq), SS_DEFAULT_CMD_SLEEP_MS); + if( status == 0x00){ + data_type = data_type_; + sc_en = sc_en_; + } +#endif + + uint8_t cmd_bytes[] = { SS_FAM_W_COMMCHAN, SS_CMDIDX_OUTPUTMODE }; + uint8_t data_bytes[] = { (uint8_t)((sc_en_ ? SS_MASK_OUTPUTMODE_SC_EN : 0) | + ((data_type_ << SS_SHIFT_OUTPUTMODE_DATATYPE) & SS_MASK_OUTPUTMODE_DATATYPE)) }; + + int status = sh_write_cmd_with_data(&cmd_bytes[0], sizeof(cmd_bytes), + &data_bytes[0], sizeof(data_bytes), + SS_DEFAULT_CMD_SLEEP_MS); + data_type = data_type_; + sc_en = sc_en_; + + return status; +} + + +int sh_get_data_type(int *data_type_, bool *sc_en_){ + + uint8_t ByteSeq[] = SH_GET_OUTPUT_MODE_CMDSEQ; + uint8_t rxbuf[2] = {0}; + int status = sh_read_cmd( &ByteSeq[0], sizeof(ByteSeq), + 0, 0, + &rxbuf[0], sizeof(rxbuf), + SS_DEFAULT_CMD_SLEEP_MS); + if (status == 0x00 /*SS_SUCCESS*/) { + *data_type_ = + (rxbuf[1] & SS_MASK_OUTPUTMODE_DATATYPE) >> SS_SHIFT_OUTPUTMODE_DATATYPE; + *sc_en_ = + (bool)((rxbuf[1] & SS_MASK_OUTPUTMODE_SC_EN) >> SS_SHIFT_OUTPUTMODE_SC_EN); + + } + + return status; + +} + + +int sh_set_fifo_thresh( int threshold ){ + +#if 0 + uint8_t ucThresh = (uint8_t) (threshold & 0xFF); + uint8_t ByteSeq[] = SH_DFIFO_SET_INT_THRESHOLD_CMDSEQ(ucThresh ); + int status = sh_write_cmd( &ByteSeq[0],sizeof(ByteSeq), SS_DEFAULT_CMD_SLEEP_MS); + return status; +#endif + + uint8_t cmd_bytes[] = { SS_FAM_W_COMMCHAN, SS_CMDIDX_FIFOAFULL }; + uint8_t data_bytes[] = { (uint8_t)threshold }; + + int status = sh_write_cmd_with_data(&cmd_bytes[0], sizeof(cmd_bytes), + &data_bytes[0], sizeof(data_bytes), + SS_DEFAULT_CMD_SLEEP_MS + ); + return status; + +} + + +int sh_get_fifo_thresh(int *thresh){ + + uint8_t ByteSeq[] = SH_DFIFO_GET_INT_THRESHOLD_CMDSEQ; + uint8_t rxbuf[2] = {0}; + int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq), + 0, 0, + &rxbuf[0], sizeof(rxbuf), + SS_DEFAULT_CMD_SLEEP_MS); + + *thresh = (int) rxbuf[1]; + + return status; + +} + + +int sh_ss_comm_check(void){ + + + uint8_t ByteSeq[] = SH_COMM_CHECK_CMDSEQ; + uint8_t rxbuf[2]; + + int status = sh_read_cmd( &ByteSeq[0], sizeof(ByteSeq), + 0, 0, + &rxbuf[0], sizeof(rxbuf), + SS_DEFAULT_CMD_SLEEP_MS ); + + int tries = 4; + while (status == SS_ERR_TRY_AGAIN && tries--) { + wait_ms(1000); + status = sh_read_cmd( &ByteSeq[0], sizeof(ByteSeq), + 0, 0, + &rxbuf[0], sizeof(rxbuf), + SS_DEFAULT_CMD_SLEEP_MS ); + + } + + return status; +} + + +int sh_num_avail_samples(int *numSamples) { + + uint8_t ByteSeq[] = SH_DFIFO_GET_NSAMPLES_CMDSEQ; + uint8_t rxbuf[2] = {0}; + + int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq), + 0, 0, + &rxbuf[0], sizeof(rxbuf), + 1); + + *numSamples = (int) rxbuf[1]; + + return status; +} + + +int sh_read_fifo_data( int numSamples, + int sampleSize, + uint8_t* databuf, + int databufSz) { + + int bytes_to_read = numSamples * sampleSize + 1; //+1 for status byte + + uint8_t ByteSeq[] = SH_DFIFO_PULL_SAMPLE_CMDSEQ; + int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq), + 0, 0, + databuf, bytes_to_read, + 10); + + return status; +} + + +/* + * desc: + * func to read sample size for SmartSensor input FIFO for extrenal accel data + * + * params: + * __O sampSize: size of data sample struct in bytes + * returns: + * 1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success + * + **/ +int sh_read_input_fifo_samplesz( int *sampSize){ + + /* NOT IMPLEMENTED IN SS INTERFACE */ + +} + +/* + * desc: + * func to write data samples to SmartSensor input FIFO for extrenal accel data + * + * params: + ... + * returns: + * 1 byte status (SS_STATUS) : 0x00 (SS_SUCCESS) on success + */ +int sh_write_input_fifo( void *arg){ + + /* NOT IMPLEMENTED IN SS INTERFACE */ + +} + + +int sh_set_reg(int idx, uint8_t addr, uint32_t val, int regSz){ + + uint8_t ByteSeq[] = SH_WRITE_SENSORREG_CMDSEQ( ((uint8_t)idx) , addr ); + uint8_t data_bytes[4]; + for (int i = 0; i < regSz; i++) { + data_bytes[i] = (val >> (8 * (regSz - 1)) & 0xFF); + } + int status = sh_write_cmd_with_data( &ByteSeq[0], sizeof(ByteSeq), + &data_bytes[0], (uint8_t) regSz, + SS_DEFAULT_CMD_SLEEP_MS); + + return status; +} + + +int sh_get_reg(int idx, uint8_t addr, uint32_t *val){ + + + uint32_t i32tmp; + uint8_t ByteSeq[] = SH_READ_AFE_ATTRIBUTES_CMDSEQ(((uint8_t) idx)); + uint8_t rxbuf[3] = {0}; + + int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq), + 0, 0, + &rxbuf[0], sizeof(rxbuf), + SS_DEFAULT_CMD_SLEEP_MS); + + + if(status == 0x00 /* SS_SUCCESS */) { + + int reg_width = rxbuf[1]; + uint8_t ByteSeq2[] = SH_READ_SENSORREG_CMDSEQ( ((uint8_t)idx) , addr ); + uint8_t rxbuf2[5] = {0}; + status = sh_read_cmd(&ByteSeq2[0], sizeof(ByteSeq2), + 0, 0, + &rxbuf2[0], reg_width + 1, + SS_DEFAULT_CMD_SLEEP_MS); + + if (status == 0x00 /* SS_SUCCESS */) { + i32tmp = 0; + for (int i = 0; i < reg_width; i++) { + i32tmp = (i32tmp << 8) | rxbuf2[i + 1]; + } + *val = i32tmp; + } + } + + return status; + +} + + +int sh_sensor_enable( int idx , int sensorSampleSz , uint8_t ext_mode ){ + + uint8_t ByteSeq[] = SH_ENABLE_SENSOR_CMDSEQ( ((uint8_t) idx) , ((uint8_t) ext_mode)); + int status = sh_write_cmd( &ByteSeq[0],sizeof(ByteSeq), 5 * SS_ENABLE_SENSOR_SLEEP_MS); + if(status == 0x00){ + + is_sensor_enabled[idx] = ENABLED; + sensor_sample_sz[idx] = sensorSampleSz; + } + return status; + +} + + +int sh_sensor_disable( int idx ){ + + uint8_t ByteSeq[] = SH_DISABLE_SENSOR_CMDSEQ( ((uint8_t) idx)); + int status = sh_write_cmd( &ByteSeq[0],sizeof(ByteSeq), SS_ENABLE_SENSOR_SLEEP_MS); + if(status == 0x00){ + + is_sensor_enabled[idx] = DISABLED; + } + return status; + +} + + +int sh_get_input_fifo_size(int *fifo_size) +{ + + uint8_t ByteSeq[] = SH_GET_EXTINPUT_FIFOSZ_CMDSEQ; + uint8_t rxbuf[3]; /* status + fifo size */ + + + int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq), + 0, 0, + rxbuf, sizeof(rxbuf), 2*SS_DEFAULT_CMD_SLEEP_MS); + + *fifo_size = rxbuf[1] << 8 | rxbuf[2]; + return status; +} + + +int sh_feed_to_input_fifo(uint8_t *tx_buf, int tx_buf_sz, int *nb_written) +{ + int status; + + uint8_t ByteSeq[] = SH_FEED_TO_INPUTFIFO_CMDSEQ; + uint8_t rxbuf[3]; + + tx_buf[0] = 0x14; + tx_buf[1] = 0x00; + + status= sh_read_cmd(tx_buf, tx_buf_sz, + 0, 0, + rxbuf, sizeof(rxbuf), SS_FEEDFIFO_CMD_SLEEP_MS); + + *nb_written = rxbuf[1] * 256 + rxbuf[2]; + return status; +} + + +int sh_get_num_bytes_in_input_fifo(int *fifo_size) +{ + + uint8_t ByteSeq[] = SH_GET_SAMPLEBYTECNT_INPUTFIFO_CMDSEQ; + uint8_t rxbuf[3]; /* status + fifo size */ + + + int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq), + 0, 0, + rxbuf, sizeof(rxbuf), + 2*SS_DEFAULT_CMD_SLEEP_MS); + + *fifo_size = rxbuf[1] << 8 | rxbuf[2]; + return status; +} + + +/* + * ALGARITIM RELATED FUNCTIONS :) + * + * + * + * + * + * */ + + +int sh_enable_algo(int idx , int algoSampleSz){ + + uint8_t ByteSeq[] = SH_ENABLE_ALGO_CMDSEQ( ((uint8_t) idx) ); + int status = sh_write_cmd( &ByteSeq[0],sizeof(ByteSeq), 25 * SS_ENABLE_SENSOR_SLEEP_MS); + if(status == 0x00){ + + is_algo_enabled[idx] = ENABLED; + algo_sample_sz[idx] = algoSampleSz; + } + return status; + +} + + +int sh_enable_algo_withmode(int idx, int mode, int algoSampleSz) +{ + + uint8_t cmd_bytes[] = { SS_FAM_W_ALGOMODE, (uint8_t)idx, (uint8_t)mode }; + + int status = sh_write_cmd_with_data(&cmd_bytes[0], sizeof(cmd_bytes), 0, 0, 25 * SS_ENABLE_SENSOR_SLEEP_MS); + + if (status == SS_SUCCESS) { + is_algo_enabled[idx] = ENABLED; + algo_sample_sz[idx] = algoSampleSz; + enabled_algo_mode[idx] = mode; + } + + return status; +} + + + +int sh_disable_algo(int idx){ + + uint8_t ByteSeq[] = SH_DISABLE_ALGO_CMDSEQ( ((uint8_t) idx) ); + int status = sh_write_cmd( &ByteSeq[0],sizeof(ByteSeq), SS_ENABLE_SENSOR_SLEEP_MS ); + if(status == 0x00){ + + is_algo_enabled[idx] = DISABLED; + } + return status; + +} + + +int sh_set_algo_cfg(int algo_idx, int cfg_idx, uint8_t *cfg, int cfg_sz){ + + uint8_t ByteSeq[] = SH_SET_ALGO_CONFIGURATION_CMDSEQ( ((uint8_t) algo_idx) , ((uint8_t) cfg_idx) ); + int status = sh_write_cmd_with_data( &ByteSeq[0], sizeof(ByteSeq), + cfg, cfg_sz, + SS_DEFAULT_CMD_SLEEP_MS); + + return status; + +} + + +int sh_get_algo_cfg(int algo_idx, int cfg_idx, uint8_t *cfg, int cfg_sz){ + + uint8_t ByteSeq[] = SH_GET_ALGO_CONFIGURATION_CMDSEQ( ((uint8_t) algo_idx) , ((uint8_t) cfg_idx) ); + int status = sh_read_cmd(&ByteSeq[0], sizeof(ByteSeq), + 0, 0, + cfg, cfg_sz, + SS_DEFAULT_CMD_SLEEP_MS); + return status; + +} + + +/* + * desc: + * func to get active cumulative sample size of sensor hub in order to + * calculate number of bytes to be read from sensor hub report data buffer + * + * params: + * __I data_type : active data type of sensor hub -> no data :0 (SS_DATATYPE_PAUSE) + * raw sensor data only :1 (SS_DATATYPE_RAW) + * algo data only :2 (SS_DATATYPE_ALGO) + * algo+raw data :3 (SS_DATATYPE_BOTH) + * __O sample_size : calculated active cumulative sample size + + * returns: + * N/A + * + **/ +static void fifo_sample_size(int data_type_, int *sample_size) +{ + + int tmpSz = 0; + //*sample_size = 0; + + if (data_type_ == SS_DATATYPE_RAW || data_type_ == SS_DATATYPE_BOTH) { + for (int i = 0; i < SS_MAX_SUPPORTED_SENSOR_NUM; i++) { + if (is_sensor_enabled[i]) { + tmpSz += sensor_sample_sz[i]; + //*sample_size += sensor_data_reqs[i]->data_size; + } + } + } + + if (data_type_ == SS_DATATYPE_ALGO || data_type_ == SS_DATATYPE_BOTH) { + for (int i = 0; i < SS_MAX_SUPPORTED_ALGO_NUM; i++) { + if (is_algo_enabled[i]) { + tmpSz += algo_sample_sz[i]; + //*sample_size += algo_data_reqs[i]->data_size; + } + } + } + + *sample_size = tmpSz; +} + + +int sh_ss_execute_once( uint8_t *databuf , int databufLen , int *nSamplesRead){ + + if(m_irq_received_ == false) { + *nSamplesRead = 0; + return -1; + } + + uint8_t sample_count; + + sh_disable_irq_mfioevent(); + sh_clear_mfio_event_flag(); + + uint8_t hubStatus = 0; + int status = sh_get_sensorhub_status(&hubStatus); + if(status != 0x00 /*SS_SUCCESS*/){ + *nSamplesRead = 0; + sh_enable_irq_mfioevent(); + return status; + } + + if (hubStatus & SS_MASK_STATUS_DATA_RDY) { + + int num_samples = 1; + status = sh_num_avail_samples(&num_samples); + if (status != 0x00 /*SS_SUCCESS*/){ + *nSamplesRead = 0; + sh_enable_irq_mfioevent(); + return status; + } + + + int sample_size; + fifo_sample_size(data_type, &sample_size); + /*DEBUG */// + + + int bytes_to_read = num_samples * sample_size + 1; //+1 for status byte + if ( bytes_to_read > databufLen) { + //Reduce number of samples to read to fit in buffer + num_samples = (databufLen - 1) / sample_size; + } + + + wait_ms(5); + status = sh_read_fifo_data(num_samples, sample_size, &databuf[0], databufLen); + if(status != 0x00 /*SS_SUCCESS*/){ + *nSamplesRead = 0; + sh_enable_irq_mfioevent(); + return status; + } + *nSamplesRead = num_samples; + } + + sh_enable_irq_mfioevent(); + return status; +} + + + +/* + * BOOTLOADER RELATED FUNCTIONS + * + * + * */ + +static const int aes_nonce_sz = 11; +static const int aes_auth_sz = 16; +static int bl_comm_delay_factor = 1; + + + +int sh_set_bootloader_delayfactor(const int factor ) { + + int status = -1; + if( factor >= 1 && factor < 51){ + bl_comm_delay_factor = factor; + status = 0x00; + } + + return status; + +} + +const int sh_get_bootloader_delayfactor(void){ + + return bl_comm_delay_factor; +} + +int sh_exit_from_bootloader(void) +{ + + return sh_reset_to_main_app(); //sh_set_sensorhub_operating_mode(0x00); +} + +int sh_put_in_bootloader(void) +{ + return sh_set_sensorhub_operating_mode( 0x08); +} + +int sh_checkif_bootldr_mode(void) +{ + uint8_t hubMode; + int status = sh_get_sensorhub_operating_mode(&hubMode); + return (status != SS_SUCCESS)? -1:(hubMode & SS_MASK_MODE_BOOTLDR); +} + +int sh_get_bootloader_pagesz(int *pagesz){ + + //uint8_t ByteSeq[]= SH_GET_BOOTLDRPAGESIZE_CMDSEQ; + uint8_t ByteSeq[]= { SS_FAM_R_BOOTLOADER, SS_CMDIDX_PAGESIZE }; + uint8_t rxbuf[3]; + int sz = 0; + + int status = sh_read_cmd( &ByteSeq[0], sizeof(ByteSeq), + 0, 0, + &rxbuf[0], sizeof(rxbuf), + SS_DEFAULT_CMD_SLEEP_MS); + if (status == 0x00) { + //rxbuf holds page size in big-endian format + sz = (256*(int)rxbuf[1]) + rxbuf[2]; + if(sz > BOOTLOADER_MAX_PAGE_SIZE ) { + sz = -2; + } + } + + *pagesz = sz; + + return status; + +} + +int sh_set_bootloader_numberofpages(const int pageCount){ + + //uint8_t ByteSeq[] = SH_SET_BOOTLDRPAGECOUNT_CMDSEQ; + uint8_t ByteSeq[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SETNUMPAGES }; + //num pages = 256*MSB + LSB + uint8_t data_bytes[] = { (uint8_t)((pageCount >> 8) & 0xFF), (uint8_t)(pageCount & 0xFF) }; + + int status = sh_write_cmd_with_data(&ByteSeq[0], sizeof(ByteSeq), + &data_bytes[0], sizeof(data_bytes), + bl_comm_delay_factor * SS_DEFAULT_CMD_SLEEP_MS ); + + return status; + +} + +int sh_set_bootloader_iv(uint8_t iv_bytes[aes_nonce_sz]){ + + uint8_t ByteSeq[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SETIV }; + int status = sh_write_cmd_with_data( &ByteSeq[0], sizeof(ByteSeq), + &iv_bytes[0], aes_nonce_sz /*sizeof(iv_bytes)*/, + bl_comm_delay_factor * SS_DEFAULT_CMD_SLEEP_MS + ); + + return status; + +} + + +int sh_set_bootloader_auth(uint8_t auth_bytes[aes_auth_sz]){ + + uint8_t ByteSeq[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SETAUTH }; + int status = sh_write_cmd_with_data( &ByteSeq[0], sizeof(ByteSeq), + &auth_bytes[0], aes_auth_sz /*sizeof(auth_bytes)*/, + bl_comm_delay_factor * SS_DEFAULT_CMD_SLEEP_MS + ); + + return status; + +} + + +int sh_set_bootloader_erase(void){ + + uint8_t ByteSeq[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_ERASE }; + + int status = sh_write_cmd_with_data(&ByteSeq[0], sizeof(ByteSeq), + 0, 0, + bl_comm_delay_factor * SS_BOOTLOADER_ERASE_DELAY); + + return status; + +} + + +int sh_bootloader_flashpage(uint8_t *flashDataPreceedByCmdBytes , const int page_size){ + + static const int flash_cmdbytes_len = 2; + static const int check_bytes_len = 16; + static const int page_write_time_ms = 200; + + //static const uint8_t ByteSeq[] = { SS_FAM_W_BOOTLOADER, SS_CMDIDX_SENDPAGE }; + int status = -1; + + if( (*flashDataPreceedByCmdBytes == SS_FAM_W_BOOTLOADER) && ( *(flashDataPreceedByCmdBytes+1) == SS_CMDIDX_SENDPAGE ) ) { + + /* We do not use sh_write_cmd_with_data function because internal buffers of the function + is limited to 512 bytes which does not support if flashing page size is bigger */ + status = sh_write_cmd(flashDataPreceedByCmdBytes, page_size + check_bytes_len + flash_cmdbytes_len, bl_comm_delay_factor * page_write_time_ms); + + } + return status; + +} + + +int sh_get_ss_fw_version(uint8_t *fwDesciptor , uint8_t *descSize) +{ + + int status = -1; + uint8_t cmd_bytes[2]; + uint8_t rxbuf[4]; + + int bootldr = in_bootldr_mode(); + + if (bootldr > 0) { + cmd_bytes[0] = SS_FAM_R_BOOTLOADER; + cmd_bytes[1] = SS_CMDIDX_BOOTFWVERSION; + } else if (bootldr == 0) { + cmd_bytes[0] = SS_FAM_R_IDENTITY; + cmd_bytes[1] = SS_CMDIDX_FWVERSION; + } else { + return -1; + } + + status = sh_read_cmd( &cmd_bytes[0], sizeof(cmd_bytes), + 0, 0, + &rxbuf[0], sizeof(rxbuf) , + SS_DEFAULT_CMD_SLEEP_MS ); + + if (status == 0x00 /*SS_SUCCESS*/) { + *fwDesciptor = rxbuf[1]; + *(fwDesciptor + 1) = rxbuf[2]; + *(fwDesciptor + 2) = rxbuf[3]; + *descSize = 3; + }else{ + *descSize = 0; + } + + return status; + +} + + +/* +#ifdef __cplusplus +} +#endif +*/ + +