test

Dependencies:   BMI160 max32630hsp3 MemoryLCD USBDevice

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
+*/
+
+