TEST

Dependencies:   max32630fthr Adafruit_FeatherOLED USBDevice

Revision:
1:f60eafbf009a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Interfaces/SmartSensor/SSInterface.cpp	Wed Apr 10 14:56:25 2019 +0300
@@ -0,0 +1,1148 @@
+/***************************************************************************
+* Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+****************************************************************************
+*/
+
+#include "SSInterface.h"
+
+#include "../../Utilities/mxm_assert.h"
+#include "Peripherals.h"
+#include "utils.h"
+#include "i2cm.h"
+
+#include "pwrman_regs.h"
+#include "ioman.h"
+
+
+
+SSInterface::SSInterface(I2C &i2cBus, PinName ss_mfio, PinName ss_reset)
+	:m_i2cBus(&i2cBus), m_spiBus(NULL),
+	mfio_pin(ss_mfio), reset_pin(ss_reset), irq_pin(ss_mfio)/*,
+	irq_evt(1000000, "irq")*/
+{
+	reset_pin.input();
+	irq_pin.fall(callback(this, &SSInterface::irq_handler));
+
+	//reset_to_main_app();
+	//get_data_type(&data_type, &sc_en);
+	ebl_mode = EBL_GPIO_TRIGGER_MODE;
+}
+
+SSInterface::SSInterface(SPI &spiBus, PinName ss_mfio, PinName ss_reset)
+	:m_i2cBus(NULL), m_spiBus(&spiBus),
+	mfio_pin(ss_mfio), reset_pin(ss_reset), irq_pin(ss_mfio)/*,
+	irq_evt(1000000, "irq")*/
+{
+	reset_pin.input();
+	irq_pin.fall(callback(this, &SSInterface::irq_handler));
+
+	//reset_to_main_app();
+	//get_data_type(&data_type, &sc_en);
+	ebl_mode = EBL_GPIO_TRIGGER_MODE;
+}
+
+SSInterface::~SSInterface()
+{
+}
+
+SS_STATUS SSInterface::reset_to_main_app()
+{
+	SS_STATUS status;
+	disable_irq();
+
+	int bootldr = in_bootldr_mode();
+	if (bootldr > 0) {
+		status = exit_from_bootloader();
+	} else if (bootldr == 0) {
+		reset_pin.output();
+
+	        if (ebl_mode == EBL_GPIO_TRIGGER_MODE)
+		cfg_mfio(PIN_OUTPUT);
+
+		reset_pin.write(0);
+		wait_ms(SS_RESET_TIME);
+
+		if (ebl_mode == EBL_GPIO_TRIGGER_MODE)
+			mfio_pin.write(1);
+
+		reset_pin.write(1);
+		wait_ms(SS_STARTUP_TO_MAIN_APP_TIME);
+
+		if (ebl_mode == EBL_GPIO_TRIGGER_MODE)
+			cfg_mfio(PIN_INPUT);
+
+		reset_pin.input();
+		status = SS_SUCCESS;
+	} else
+		status = SS_ERR_UNKNOWN;
+	enable_irq();
+	return status;
+}
+
+SS_STATUS SSInterface::reset_to_bootloader()
+{
+	disable_irq();
+	int bootldr = in_bootldr_mode();
+	if (bootldr > 0) {
+		enable_irq();
+		return SS_SUCCESS;
+	}
+	reset_pin.output();
+	if (ebl_mode == EBL_GPIO_TRIGGER_MODE)
+		cfg_mfio(PIN_OUTPUT);
+
+	reset_pin.write(0);
+	wait_ms(SS_RESET_TIME);
+	if (ebl_mode == EBL_GPIO_TRIGGER_MODE)
+		 mfio_pin.write(0);
+
+	reset_pin.write(1);
+	wait_ms(SS_STARTUP_TO_BTLDR_TIME);
+	reset_pin.input();
+
+	if (ebl_mode == EBL_CMD_TRIGGER_MODE)
+		stay_in_bootloader();
+
+	if (ebl_mode == EBL_GPIO_TRIGGER_MODE) {
+		cfg_mfio(PIN_INPUT);
+		stay_in_bootloader();
+	}
+
+	 // Verify we entered bootloader mode
+	if (in_bootldr_mode() < 0) {
+		enable_irq();
+		return SS_ERR_UNKNOWN;
+	}
+	enable_irq();
+	return SS_SUCCESS;
+}
+
+SS_STATUS SSInterface::exit_from_bootloader()
+{
+	uint8_t cmd_bytes[] = { SS_FAM_W_MODE, SS_CMDIDX_MODE };
+	uint8_t data[] = { 0x00 };
+
+	SS_STATUS status = write_cmd(
+			&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+			&data[0], ARRAY_SIZE(data));
+
+	in_bootldr = (status == SS_SUCCESS) ? true : false;
+	return status;
+}
+
+SS_STATUS SSInterface::stay_in_bootloader()
+{
+	uint8_t cmd_bytes[] = { SS_FAM_W_MODE, SS_CMDIDX_MODE };
+	uint8_t data[] = { SS_MASK_MODE_BOOTLDR };
+
+	SS_STATUS status = write_cmd(
+			&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+			&data[0], ARRAY_SIZE(data));
+
+	in_bootldr = (status == SS_SUCCESS) ? true : false;
+	return status;
+}
+
+int SSInterface::get_ebl_mode()
+{
+	return ebl_mode;
+}
+
+SS_STATUS SSInterface::set_ebl_mode(uint8_t mode)
+{
+	if (mode == EBL_CMD_TRIGGER_MODE || mode == EBL_GPIO_TRIGGER_MODE) {
+		ebl_mode = mode;
+		return SS_SUCCESS;
+	} else {
+		return SS_ERR_INPUT_VALUE;
+	}
+}
+
+SS_STATUS SSInterface::reset()
+{
+	int bootldr = in_bootldr_mode();
+	if (bootldr > 0)
+		return reset_to_bootloader();
+	else if (bootldr == 0)
+		return reset_to_main_app();
+	else
+		return SS_ERR_UNKNOWN;
+}
+
+SS_STATUS SSInterface::self_test(int idx, uint8_t *result, int sleep_ms){
+    uint8_t cmd_bytes[] = { SS_FAM_R_SELFTEST, (uint8_t)idx };
+    uint8_t rxbuf[2];
+    SS_STATUS ret;
+
+	result[0] = 0xFF;
+	ret = read_cmd(cmd_bytes, 2, (uint8_t *)0, 0, rxbuf, ARRAY_SIZE(rxbuf), sleep_ms);
+	result[0] = rxbuf[1];
+	return ret;
+}
+
+void SSInterface::cfg_mfio(PinDirection dir)
+{
+	if (dir == PIN_INPUT) {
+		mfio_pin.input();
+		mfio_pin.mode(PullUp);
+	} else {
+		disable_irq();
+		mfio_pin.output();
+	}
+}
+
+void SSInterface::enable_irq()
+{
+	irq_pin.enable_irq();
+}
+void SSInterface::disable_irq()
+{
+	irq_pin.disable_irq();
+}
+
+void SSInterface::mfio_selftest(){
+	disable_irq();
+	irq_pin.fall(callback(this, &SSInterface::irq_handler_selftest));
+	enable_irq();
+}
+
+int SSInterface::in_bootldr_mode()
+{
+	uint8_t cmd_bytes[] = { SS_FAM_R_MODE, SS_CMDIDX_MODE };
+	uint8_t rxbuf[2] = { 0 };
+
+	SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+			0, 0,
+			&rxbuf[0], ARRAY_SIZE(rxbuf));
+	if (status != SS_SUCCESS)
+		return -1;
+
+	return (rxbuf[1] & SS_MASK_MODE_BOOTLDR);
+}
+
+const char* SSInterface::get_ss_fw_version()
+{
+    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 plat_name;
+	}
+
+    SS_STATUS status = read_cmd(
+             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+             0, 0,
+             &rxbuf[0], ARRAY_SIZE(rxbuf));
+
+    if (status == SS_SUCCESS) {
+        snprintf(fw_version, sizeof(fw_version),
+            "%d.%d.%d", rxbuf[1], rxbuf[2], rxbuf[3]);
+		pr_info("fw_version:%s\r\n", fw_version);
+    }
+
+    return &fw_version[0];
+}
+
+const char* SSInterface::get_ss_algo_version()
+{
+    uint8_t cmd_bytes[3];
+    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;
+		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 plat_name;
+	}
+
+    SS_STATUS status = read_cmd(
+             &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+             0, 0,
+             &rxbuf[0], ARRAY_SIZE(rxbuf));
+
+    if (status == SS_SUCCESS) {
+        snprintf(algo_version, sizeof(algo_version),
+            "%d.%d.%d", rxbuf[1], rxbuf[2], rxbuf[3]);
+		pr_info("algo_version:%s\r\n", fw_version);
+    }
+
+    return &algo_version[0];
+}
+const char* SSInterface::get_ss_platform_name()
+{
+    uint8_t cmd_bytes[] = { SS_FAM_R_IDENTITY, SS_CMDIDX_PLATTYPE };
+    uint8_t rxbuf[2];
+
+    SS_STATUS status = read_cmd(
+            &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+            0, 0,
+            &rxbuf[0], ARRAY_SIZE(rxbuf));
+
+    if (status == SS_SUCCESS) {
+        if (rxbuf[1] == SS_PLAT_MAX3263X) {
+			if (in_bootldr_mode() > 0) {
+				plat_name = SS_BOOTLOADER_PLATFORM_MAX3263X;
+			} else {
+	            plat_name = SS_PLATFORM_MAX3263X;
+			}
+        } else if (rxbuf[1] == SS_PLAT_MAX32660) {
+			if (in_bootldr_mode() > 0) {
+				plat_name = SS_BOOTLOADER_PLATFORM_MAX32660;
+			} else {
+				plat_name = SS_PLATFORM_MAX32660;
+			}
+        }
+    }
+
+    return plat_name;
+}
+
+SS_STATUS SSInterface::write_cmd(uint8_t *cmd_bytes, int cmd_bytes_len,
+	uint8_t *data, int data_len,
+    int sleep_ms)
+{
+    int total_len = data_len + cmd_bytes_len;
+
+    if (total_len <= SS_SMALL_BUF_SIZE) {
+        return write_cmd_small(cmd_bytes, cmd_bytes_len, data, data_len, sleep_ms);
+    } else if (total_len <= SS_MED_BUF_SIZE) {
+        return write_cmd_medium(cmd_bytes, cmd_bytes_len, data, data_len, sleep_ms);
+    } else if (total_len <= SS_LARGE_BUF_SIZE) {
+        return write_cmd_large(cmd_bytes, cmd_bytes_len, data, data_len, sleep_ms);
+    } else {
+    	mxm_assert_msg(true, "Tried to send I2C tx larger than maximum allowed size\n");
+        return SS_ERR_DATA_FORMAT; 
+    }
+}
+
+#include "i2cm.h"
+void dump_i2c_regs(int idx)
+{
+	mxc_i2cm_regs_t *i2cm = MXC_I2CM_GET_I2CM(idx);
+	pr_err("****************************\r\n"
+		"I2CM(%d) registers Dump\r\n"
+		"i2cm: %p\r\n"
+		"fs_clk_div : 0x%X\r\n"
+		"timeout : 0x%X\r\n"
+		"ctrl : 0x%X\r\n"
+		"trans : 0x%X\r\n"
+		"intfl : 0x%X\r\n"
+		"inten : 0x%X\r\n"
+		"bb : 0x%X\r\n"
+		"****************************\r\n",
+		idx,
+		i2cm,
+		i2cm->fs_clk_div,
+		i2cm->timeout,
+		i2cm->ctrl,
+		i2cm->trans,
+		i2cm->intfl,
+		i2cm->inten,
+		i2cm->bb);
+
+	/* Clean flags */
+	i2cm->intfl = i2cm->intfl;
+}
+
+SS_STATUS SSInterface::write_cmd(uint8_t *tx_buf, int tx_len, int sleep_ms)
+{
+	pr_info("write_cmd: ");
+	for (int i = 0; i < tx_len; i++) {
+		pr_info("0x%02X ", tx_buf[i]);
+	}
+	pr_info("\r\n");
+
+    int ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)tx_buf, tx_len);
+
+	int retries = 4;
+	while (ret != 0 && retries-- > 0) {
+		pr_err("i2c wr retry\r\n");
+		wait_ms(1);
+	ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)tx_buf, tx_len);
+	}
+
+    if (ret != 0) {
+    	pr_err("m_i2cBus->write returned %d\r\n", ret);
+
+        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) {
+		pr_info("i2c rd retry\r\n");
+		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) {
+
+    	pr_err("m_i2cBus->read returned %d, ss status_byte %d\r\n", ret, status_byte);
+        return SS_ERR_UNAVAILABLE;
+    }
+
+	pr_info("status_byte: %d\r\n", status_byte);
+
+	return (SS_STATUS)status_byte;
+}
+
+SS_STATUS SSInterface::write_cmd_small(uint8_t *cmd_bytes, int cmd_bytes_len,
+                       uint8_t *data, int data_len,
+                       int sleep_ms)
+{
+    uint8_t write_buf[SS_SMALL_BUF_SIZE];
+    memcpy(write_buf, cmd_bytes, cmd_bytes_len);
+    memcpy(write_buf + cmd_bytes_len, data, data_len);
+
+	SS_STATUS status = write_cmd(write_buf, cmd_bytes_len + data_len, sleep_ms);
+	return status;
+}
+
+SS_STATUS SSInterface::write_cmd_medium(uint8_t *cmd_bytes, int cmd_bytes_len,
+                       uint8_t *data, int data_len,
+                       int sleep_ms)
+{
+    uint8_t write_buf[SS_MED_BUF_SIZE];
+    memcpy(write_buf, cmd_bytes, cmd_bytes_len);
+    memcpy(write_buf + cmd_bytes_len, data, data_len);
+
+	SS_STATUS status = write_cmd(write_buf, cmd_bytes_len + data_len, sleep_ms);
+	return status;
+}
+
+SS_STATUS SSInterface::write_cmd_large(uint8_t *cmd_bytes, int cmd_bytes_len,
+                       uint8_t *data, int data_len,
+                       int sleep_ms)
+{
+    uint8_t write_buf[SS_LARGE_BUF_SIZE];
+    memcpy(write_buf, cmd_bytes, cmd_bytes_len);
+    memcpy(write_buf + cmd_bytes_len, data, data_len);
+
+	SS_STATUS status = write_cmd(write_buf, cmd_bytes_len + data_len, sleep_ms);
+	return status;
+}
+
+SS_STATUS SSInterface::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)
+{
+#if 0
+	pr_info("read_cmd: ");
+	for (int i = 0; i < cmd_bytes_len; i++) {
+		pr_info("0x%02X ", cmd_bytes[i]);
+	}
+	pr_info("\r\n");
+
+#endif
+
+	int retries = 4;
+
+    int ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)cmd_bytes, cmd_bytes_len, (data_len != 0));
+#ifdef SHOW_I2C_DEBUG_MESSAGES
+    printf("ret1 : %d\rt\n",ret);
+#endif
+    if (data_len != 0) {
+        ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)data, data_len, false);
+#ifdef SHOW_I2C_DEBUG_MESSAGES
+        printf("ret2 : %d\rt\n",ret);
+#endif
+    }
+
+	while (ret != 0 && retries-- > 0) {
+
+		pr_err("i2c wr retry\r\n");
+		wait_ms(1);
+	ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)cmd_bytes, cmd_bytes_len, (data_len != 0));
+#ifdef SHOW_I2C_DEBUG_MESSAGES
+	printf("ret3 : %d\rt\n",ret);
+#endif
+	    if (data_len != 0) {
+	        ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)data, data_len, false);
+#ifdef SHOW_I2C_DEBUG_MESSAGES
+	        printf("ret4 : %d\rt\n",ret);
+#endif
+	    }
+	}
+
+    if (ret != 0) {
+    	pr_err("m_i2cBus->write returned %d\r\n", ret);
+
+        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) {
+		pr_info("i2c rd retry\r\n");
+		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) {
+    	pr_err("m_i2cBus->read returned %d, ss status_byte %d\r\n", ret, rxbuf[0]);
+
+        return SS_ERR_UNAVAILABLE;
+    }
+
+	pr_info("status_byte: %d\r\n", rxbuf[0]);
+	pr_info("data: ");
+	for (int i = 1; i < rxbuf_sz; i++) {
+		pr_info("0x%02X ", rxbuf[i]);
+	}
+	pr_info("\r\n");
+
+    return (SS_STATUS)rxbuf[0];
+}
+
+SS_STATUS SSInterface::get_reg(int idx, uint8_t addr, uint32_t *val)
+{
+	mxm_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");
+
+	uint8_t cmd_bytes[] = { SS_FAM_R_REGATTRIBS, (uint8_t)idx };
+	uint8_t rx_reg_attribs[3] = {0};
+
+	SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								0, 0,
+								&rx_reg_attribs[0], ARRAY_SIZE(rx_reg_attribs));
+
+	if (status != SS_SUCCESS)
+		return status;
+
+	int reg_width = rx_reg_attribs[1];
+
+	uint8_t cmd_bytes2[] = { SS_FAM_R_READREG, (uint8_t)idx, addr };
+	uint8_t rxbuf[5] = {0};
+
+	status = read_cmd(&cmd_bytes2[0], ARRAY_SIZE(cmd_bytes2),
+						0, 0,
+						&rxbuf[0], reg_width + 1);
+
+	if (status == SS_SUCCESS) {
+		*val = 0;
+		for (int i = 0; i < reg_width; i++) {
+			*val = (*val << 8) | rxbuf[i + 1];
+		}
+	}
+
+	return status;
+}
+
+SS_STATUS SSInterface::set_reg(int idx, uint8_t addr, uint32_t val, int byte_size)
+{
+	mxm_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");
+
+	uint8_t cmd_bytes[] = { SS_FAM_W_WRITEREG, (uint8_t)idx, addr };
+	uint8_t data_bytes[4];
+	for (int i = 0; i < byte_size; i++) {
+		data_bytes[i] = (val >> (8 * (byte_size - 1)) & 0xFF);
+	}
+
+	SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								&data_bytes[0], byte_size, SS_ENABLE_SENSOR_SLEEP_MS);
+
+	return status;
+}
+
+SS_STATUS SSInterface::dump_reg(int idx, addr_val_pair* reg_vals, int reg_vals_sz, int* num_regs)
+{
+	mxm_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");
+
+	uint8_t cmd_bytes[] = { SS_FAM_R_REGATTRIBS, (uint8_t)idx };
+	uint8_t rx_reg_attribs[3] = {0};
+
+	SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								0, 0,
+								&rx_reg_attribs[0], ARRAY_SIZE(rx_reg_attribs));
+
+	if (status != SS_SUCCESS)
+		return status;
+
+	int reg_width = rx_reg_attribs[1];
+	*num_regs = rx_reg_attribs[2];
+	mxm_assert_msg((*num_regs <= reg_vals_sz), "Need to increase reg_vals array to hold all dump_reg data");
+	mxm_assert_msg(((size_t)reg_width <= sizeof(uint32_t)), "IC returned register values greater than 4 bytes in width");
+
+	int dump_reg_sz = (*num_regs) * (reg_width + 1) + 1; //+1 to reg_width for address, +1 for status byte
+
+	uint8_t rxbuf[512];
+	mxm_assert_msg(((size_t)dump_reg_sz <= sizeof(rxbuf)), "Need to increase buffer size to receive dump_reg data");
+
+	cmd_bytes[0] = SS_FAM_R_DUMPREG;
+	status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								0, 0,
+								&rxbuf[0], dump_reg_sz, SS_DUMP_REG_SLEEP_MS);
+
+	if (status != SS_SUCCESS)
+		return status;
+
+	//rxbuf format is [status][addr0](reg_width x [val0])[addr1](reg_width x [val1])...
+	for (int reg = 0; reg < *num_regs; reg++) {
+		reg_vals[reg].addr = rxbuf[(reg * (reg_width + 1)) + 1];
+		uint32_t *val = &(reg_vals[reg].val);
+		*val = 0;
+		for (int byte = 0; byte < reg_width; byte++) {
+			*val = (*val << 8) | rxbuf[(reg * (reg_width + 1)) + byte + 2];
+		}
+	}
+
+	return SS_SUCCESS;
+}
+
+SS_STATUS SSInterface::enable_sensor(int idx, int mode, ss_data_req *data_req, uint8_t ext_mode)
+{
+	mxm_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");
+	mxm_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");
+	mxm_assert_msg((mode != 0), "Tried to enable sensor to mode 0, but mode 0 is disable");
+
+
+	uint8_t cmd_bytes[] = { SS_FAM_W_SENSORMODE, (uint8_t)idx, (uint8_t)mode, ext_mode };
+
+	SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, 5 * SS_ENABLE_SENSOR_SLEEP_MS);
+
+	if (status == SS_SUCCESS) {
+		sensor_enabled_mode[idx] = mode;
+		sensor_data_reqs[idx] = data_req;
+	}
+	return status;
+}
+
+SS_STATUS SSInterface::disable_sensor(int idx)
+{
+	mxm_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");
+	uint8_t cmd_bytes[] = { SS_FAM_W_SENSORMODE, (uint8_t)idx, 0 };
+
+	SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS);
+
+	if (status == SS_SUCCESS) {
+		sensor_enabled_mode[idx] = 0;
+		sensor_data_reqs[idx] = 0;
+	}
+
+	return status;
+}
+
+SS_STATUS SSInterface::enable_algo(int idx, int mode, ss_data_req *data_req)
+{
+	mxm_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");
+	mxm_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");
+	mxm_assert_msg((mode != 0), "Tried to enable algo to mode 0, but mode 0 is disable");
+
+	uint8_t cmd_bytes[] = { SS_FAM_W_ALGOMODE, (uint8_t)idx, (uint8_t)mode };
+
+	SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, 25 * SS_ENABLE_SENSOR_SLEEP_MS);
+
+	if (status == SS_SUCCESS) {
+		algo_enabled_mode[idx] = mode;
+		algo_data_reqs[idx] = data_req;
+	}
+
+	return status;
+}
+
+SS_STATUS SSInterface::disable_algo(int idx)
+{
+	mxm_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");
+	uint8_t cmd_bytes[] = { SS_FAM_W_ALGOMODE, (uint8_t)idx, 0 };
+
+	SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS);
+
+	if (status == SS_SUCCESS) {
+		algo_enabled_mode[idx] = 0;
+		algo_data_reqs[idx] = 0;
+	}
+
+	return status;
+}
+
+SS_STATUS SSInterface::set_algo_cfg(int algo_idx, int cfg_idx, uint8_t *cfg, int cfg_sz)
+{
+	mxm_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");
+	mxm_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");
+
+	uint8_t cmd_bytes[] = { SS_FAM_W_ALGOCONFIG, (uint8_t)algo_idx, (uint8_t)cfg_idx };
+	SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								 cfg, cfg_sz);
+
+	return status;
+}
+
+SS_STATUS SSInterface::get_algo_cfg(int algo_idx, int cfg_idx, uint8_t *cfg, int cfg_sz)
+{
+	mxm_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");
+	mxm_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");
+
+	uint8_t cmd_bytes[] = { SS_FAM_R_ALGOCONFIG, (uint8_t)algo_idx, (uint8_t)cfg_idx };
+	SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								0, 0,
+								cfg, cfg_sz);
+
+	return status;
+}
+
+//--------------------------------------------------------------
+SS_STATUS SSInterface::send_raw(uint8_t *rawdata, int rawdata_sz)
+{
+	SS_STATUS status = write_cmd(&rawdata[0], rawdata_sz, 5 * SS_ENABLE_SENSOR_SLEEP_MS);
+	return status;
+}
+//---------------------------------------------------------------
+SS_STATUS SSInterface::set_data_type(int data_type, bool sc_en)
+{
+	mxm_assert_msg((data_type >= 0) && (data_type <= 3), "Invalid value for data_type");
+	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)) };
+
+	SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								&data_bytes[0], ARRAY_SIZE(data_bytes));
+
+	this->data_type = data_type;
+	this->sc_en = sc_en;
+
+	return status;
+}
+
+
+SS_STATUS SSInterface::get_data_type(int *data_type, bool *sc_en)
+{
+	uint8_t cmd_bytes[] = { SS_FAM_R_COMMCHAN, SS_CMDIDX_OUTPUTMODE };
+	uint8_t rxbuf[2] = {0};
+
+	SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								0, 0,
+								&rxbuf[0], ARRAY_SIZE(rxbuf));
+	if (status == 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;
+}
+
+SS_STATUS SSInterface::set_fifo_thresh(int thresh)
+{
+	mxm_assert_msg((thresh > 0 && thresh <= 255), "Invalid value for fifo a full threshold");
+	uint8_t cmd_bytes[] = { SS_FAM_W_COMMCHAN, SS_CMDIDX_FIFOAFULL };
+	uint8_t data_bytes[] = { (uint8_t)thresh };
+
+	SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								&data_bytes[0], ARRAY_SIZE(data_bytes));
+	return status;
+}
+
+SS_STATUS SSInterface::get_fifo_thresh(int *thresh)
+{
+	uint8_t cmd_bytes[] = { SS_FAM_R_COMMCHAN, SS_CMDIDX_FIFOAFULL };
+	uint8_t rxbuf[2] = {0};
+
+	SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								0, 0,
+								&rxbuf[0], ARRAY_SIZE(rxbuf));
+
+	if (status == SS_SUCCESS) {
+		*thresh = rxbuf[1];
+	}
+
+	return status;
+}
+
+SS_STATUS SSInterface::ss_comm_check()
+{
+	uint8_t cmd_bytes[] = { SS_FAM_R_IDENTITY, SS_CMDIDX_PLATTYPE };
+	uint8_t rxbuf[2];
+
+	SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								0, 0,
+								&rxbuf[0], ARRAY_SIZE(rxbuf));
+
+	int tries = 4;
+	while (status == SS_ERR_TRY_AGAIN && tries--) {
+		wait_ms(1000);
+		status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+							0, 0,
+							&rxbuf[0], ARRAY_SIZE(rxbuf));
+	}
+
+	return status;
+}
+
+void SSInterface::fifo_sample_size(int data_type, int *sample_size)
+{
+	*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 (sensor_enabled_mode[i]) {
+				mxm_assert_msg(sensor_data_reqs[i], "no ss_data_req found for enabled sensor");
+				*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 (algo_enabled_mode[i]) {
+				mxm_assert_msg(algo_data_reqs[i], "no ss_data_req found for enabled algo");
+				*sample_size += algo_data_reqs[i]->data_size;
+			}
+		}
+	}
+}
+
+
+SS_STATUS SSInterface::num_avail_samples(int *num_samples)
+{
+	uint8_t cmd_bytes[] = { SS_FAM_R_OUTPUTFIFO, SS_CMDIDX_OUT_NUMSAMPLES };
+	uint8_t rxbuf[2] = {0};
+
+	SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								0, 0,
+								&rxbuf[0], ARRAY_SIZE(rxbuf), SS_DEFAULT2_CMD_SLEEP_MS);
+
+	if (status == SS_SUCCESS) {
+		*num_samples = rxbuf[1];
+	}
+
+	return status;
+}
+
+SS_STATUS SSInterface::get_log_len(int *log_len)
+{
+	uint8_t cmd_bytes[] = { SS_FAM_R_LOG, SS_CMDIDX_R_LOG_LEN };
+	uint8_t rxbuf[2] = {0};
+
+	SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								0, 0,
+								&rxbuf[0], ARRAY_SIZE(rxbuf), 1);
+
+	if (status == SS_SUCCESS) {
+		*log_len = (rxbuf[1] << 8) | rxbuf[0];
+	}
+
+	return status;
+}
+
+
+SS_STATUS SSInterface::get_sensor_sample_size(uint8_t sensor_id, uint8_t *sample_size)
+{
+	uint8_t cmd_bytes[] = { SS_FAM_R_INPUTFIFO, SS_CMDIDX_SAMPLE_SIZE, sensor_id };
+	uint8_t rxbuf[2]; /* status + sample size */
+
+	pr_info("[Reading external sample size for id: %d\n", sensor_id);
+	SS_STATUS status = read_cmd(cmd_bytes, ARRAY_SIZE(cmd_bytes),
+								NULL, 0,
+								rxbuf, sizeof(rxbuf));
+	*sample_size = rxbuf[1];
+	return status;
+}
+
+SS_STATUS SSInterface::get_input_fifo_size(int *fifo_size)
+{
+	uint8_t cmd_bytes[] = { SS_FAM_R_INPUTFIFO, SS_CMDIDX_INPUT_FIFO_SIZE};
+	uint8_t rxbuf[3]; /* status + fifo size */
+
+	pr_info("[Reading external Input FIFO size.\n");
+	SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								NULL, 0,
+								rxbuf, sizeof(rxbuf), SS_DEFAULT2_CMD_SLEEP_MS);
+	*fifo_size = rxbuf[1] << 8 | rxbuf[2];
+	return status;
+}
+
+SS_STATUS SSInterface::get_sensor_fifo_size(uint8_t sensor_id, int *fifo_size)
+{
+	uint8_t cmd_bytes[] = { SS_FAM_R_INPUTFIFO, SS_CMDIDX_SENSOR_FIFO_SIZE, sensor_id};
+	uint8_t rxbuf[3]; /* status + fifo size */
+
+	pr_info("[Reading sensor's FIFO size for id: %d\n", sensor_id);
+	SS_STATUS status = read_cmd(cmd_bytes, ARRAY_SIZE(cmd_bytes),
+								NULL, 0,
+								rxbuf, sizeof(rxbuf));
+	*fifo_size = rxbuf[1] << 8 | rxbuf[2];
+	return status;
+}
+
+SS_STATUS SSInterface::get_num_samples_in_sensor_fifo(uint8_t sensor_id, int *fifo_size)
+{
+	uint8_t cmd_bytes[] = { SS_FAM_R_INPUTFIFO, SS_CMDIDX_NUM_SAMPLES_SENSOR_FIFO, sensor_id};
+	uint8_t rxbuf[3]; /* status + fifo size */
+
+	pr_info("[Reading sensor's FIFO size for id: %d\n", sensor_id);
+	SS_STATUS status = read_cmd(cmd_bytes, ARRAY_SIZE(cmd_bytes),
+								NULL, 0,
+								rxbuf, sizeof(rxbuf));
+	*fifo_size = rxbuf[1] << 8 | rxbuf[2];
+	return status;
+}
+
+SS_STATUS SSInterface::get_num_bytes_in_input_fifo(int *fifo_size)
+{
+	uint8_t cmd_bytes[] = { SS_FAM_R_INPUTFIFO, SS_CMDIDX_NUM_SAMPLES_INPUT_FIFO};
+	uint8_t rxbuf[3]; /* status + fifo size */
+
+	pr_info("[Reading input FIFO size for id\n");
+	SS_STATUS status = read_cmd(cmd_bytes, ARRAY_SIZE(cmd_bytes),
+								NULL, 0,
+								rxbuf, sizeof(rxbuf),
+								SS_DEFAULT2_CMD_SLEEP_MS);
+	*fifo_size = rxbuf[1] << 8 | rxbuf[2];
+	return status;
+}
+
+SS_STATUS SSInterface::feed_to_input_fifo(uint8_t *tx_buf, int tx_buf_sz, int *nb_written)
+{
+	int ret;
+	uint8_t rxbuf[3];
+
+	tx_buf[0] = SS_FAM_W_INPUTFIFO;
+	tx_buf[1] = SS_CMDIDX_WRITE_FIFO;
+
+	ret = read_cmd(&tx_buf[0], tx_buf_sz,
+			NULL, 0,
+			rxbuf, sizeof(rxbuf), SS_DEFAULT3_CMD_SLEEP_MS);
+
+	*nb_written = rxbuf[1] * 256 + rxbuf[2];
+	return (SS_STATUS)ret;
+}
+
+SS_STATUS SSInterface::read_fifo_data(int num_samples, int sample_size,
+	uint8_t* databuf, int databuf_sz)
+{
+	int bytes_to_read = num_samples * sample_size + 1; //+1 for status byte
+	mxm_assert_msg((bytes_to_read <= databuf_sz), "databuf too small");
+
+	uint8_t cmd_bytes[] = { SS_FAM_R_OUTPUTFIFO, SS_CMDIDX_READFIFO };
+
+	pr_info("[reading %d bytes (%d samples)\r\n", bytes_to_read, num_samples);
+
+	SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								0, 0,
+								databuf, bytes_to_read, 10);
+
+	return status;
+}
+
+SS_STATUS SSInterface::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 };
+
+	pr_info("[reading %d bytes (%d samples)\r\n", bytes_to_read, bytes_to_read);
+
+	SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								0, 0,
+								log_buf, bytes_to_read, 5);
+
+	return status;
+}
+
+static uint8_t databuf[512];
+void SSInterface::ss_execute_once(){
+
+	if(m_irq_received_ == false)
+		return;
+
+	uint8_t sample_count;
+	m_irq_received_ = false;
+	uint8_t cmd_bytes[] = { SS_FAM_R_STATUS, SS_CMDIDX_STATUS };
+	uint8_t rxbuf[2] = {0};
+
+	//irq_evt.start();
+
+	disable_irq();
+
+	SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
+								0, 0,
+								&rxbuf[0], ARRAY_SIZE(rxbuf), SS_DEFAULT2_CMD_SLEEP_MS);
+	pr_info("ss_int: %2X", rxbuf[1]);
+
+	if (status != SS_SUCCESS) {
+		pr_err("Couldn't read status byte of SmartSensor!");
+		enable_irq();
+		//irq_evt.stop();
+		return;
+	}
+
+	if (rxbuf[1] & SS_MASK_STATUS_ERR) {
+		pr_err("SmartSensor status error: %d", rxbuf[1] & SS_MASK_STATUS_ERR);
+	}
+	if (rxbuf[1] & SS_MASK_STATUS_FIFO_OUT_OVR) {
+		pr_err("SmartSensor Output FIFO overflow!");
+	}
+	if (rxbuf[1] & SS_MASK_STATUS_FIFO_IN_OVR) {
+		pr_err("SmartSensor Input FIFO overflow!");
+	}
+
+	if (rxbuf[1] & SS_MASK_STATUS_LOG_OVR) {
+		pr_err("SmartSensor log overflow!");
+	}
+
+	if (rxbuf[1] & SS_MASK_STATUS_LOG_RDY) {
+		pr_err("SmartSensor Log ready");
+		int log_len;
+		status = get_log_len(&log_len);
+		if (status != SS_SUCCESS)
+		{
+			pr_err("Couldn't read log lenght");
+			enable_irq();
+			//irq_evt.stop();
+			return;
+		}
+
+		mxm_assert_msg((log_len <= sizeof(databuf)), "log size in SS longer than buffer");
+		status = read_ss_log(log_len, &databuf[0], sizeof(databuf));
+		if (status != SS_SUCCESS)
+		{
+			pr_err("Couldn't read from SmartSensor Log");
+			enable_irq();
+			//irq_evt.stop();
+			return;
+		}
+
+		databuf[log_len] = 0;
+		Peripherals::usbSerial()->printf("\r\n%s", (char *)databuf);
+	}
+
+	if (rxbuf[1] & SS_MASK_STATUS_DATA_RDY) {
+		int num_samples = 1;
+		status = num_avail_samples(&num_samples);
+		if (status != SS_SUCCESS)
+		{
+			pr_err("Couldn't read number of available samples in SmartSensor Output FIFO");
+			enable_irq();
+			//irq_evt.stop();
+			return;
+		}
+
+		int sample_size;
+		fifo_sample_size(data_type, &sample_size);
+
+		int bytes_to_read = num_samples * sample_size + 1; //+1 for status byte
+		if ((uint32_t)bytes_to_read > sizeof(databuf)) {
+			//Reduce number of samples to read to fit in buffer
+			num_samples = (sizeof(databuf) - 1) / sample_size;
+		}
+
+		wait_ms(5);
+		status = read_fifo_data(num_samples, sample_size, &databuf[0], sizeof(databuf));
+		if (status != SS_SUCCESS)
+		{
+			pr_err("Couldn't read from SmartSensor Output FIFO");
+			enable_irq();
+			//irq_evt.stop();
+			return;
+		}
+
+		//Skip status byte
+		uint8_t *data_ptr = &databuf[1];
+
+		int i = 0;
+		for (i = 0; i < num_samples; i++) {
+			if (sc_en) {
+				sample_count = *data_ptr++;
+				pr_info("Received sample #%d", sample_count);
+			}
+
+			//Chop up data and send to modules with enabled sensors
+			if (data_type == SS_DATATYPE_RAW || data_type == SS_DATATYPE_BOTH) {
+				for (int i = 0; i < SS_MAX_SUPPORTED_SENSOR_NUM; i++) {
+					if (sensor_enabled_mode[i]) {
+						mxm_assert_msg(sensor_data_reqs[i],
+								"no ss_data_req found for enabled sensor");
+						sensor_data_reqs[i]->callback(data_ptr);
+						data_ptr += 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 (algo_enabled_mode[i]) {
+					mxm_assert_msg(algo_data_reqs[i],
+								"no ss_data_req found for enabled algo");
+						algo_data_reqs[i]->callback(data_ptr);
+						data_ptr += algo_data_reqs[i]->data_size;
+					}
+				}
+			}
+		}
+	}
+	enable_irq();
+	//irq_evt.stop();
+}
+
+void SSInterface::ss_clear_interrupt_flag(){
+	m_irq_received_ = false;
+}
+
+void SSInterface::irq_handler()
+{
+	m_irq_received_ = true;
+}
+
+void SSInterface::irq_handler_selftest(){
+	mfio_int_happened = true;
+}
+
+bool SSInterface::reset_mfio_irq(){
+	bool ret = mfio_int_happened;
+	mfio_int_happened = false;
+	disable_irq();
+	irq_pin.fall(callback(this, &SSInterface::irq_handler));
+	enable_irq();
+	return ret;
+}