Maxim Integrated / Mbed OS MAXREFDES220_HR_SPO2_MONITOR

Dependencies:   max32630fthr USBDevice

Fork of MAXREFDES220_HEART_RATE_MONITOR by Maxim Integrated

Finger Heart Rate Monitor and SpO2 Monitor

The MAXREFDES220 Smart Sensor FeatherWing board is a integrated solution for providing finger-based heart rate measurements and SpO2 (blood oxygen saturation). This evaluation board interfaces to the host computer using the I2C interface. Heart rate outpu is available in beats per minute (BPM) and SpO2 is reported in percentages.; the PPG (photoplethysmography) raw data is also available. The board has an MAX30101 chip which is a low power heart rate monitor with adjustable sample rates and adjustable LED currents. The low cost MAX32664 microcontroller is pre-flashed with C code for finger-based pulse rate and SpO2 monitoring. Bootloader software is included to allow for future algorithms or updates to the algorithm from Maxim Integrated.

Ordering information will be available soon.

Note: SpO2 values are not calibrated. Calibration should be performed using the final end product.

Warning

The MAXREFDES220 source code listed is dated and only compatible with the 1.2.8a.msbl. The latest sample host source code is available on the MAX32664 website.

MAXREFDES220 FeatherWing Pinout Connections

/media/uploads/phonemacro/maxrefdes220_pinouts_heart_rate_monitor.jpg

Committer:
Shaun Kelsey
Date:
Thu May 24 14:54:28 2018 -0700
Revision:
5:e458409e913f
Parent:
1:7a55c0c7d6d9
Child:
7:3e2a5545f1d8
Bootloader feature additions

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Shaun Kelsey 0:da5f5b56060a 1 /***************************************************************************
Shaun Kelsey 0:da5f5b56060a 2 * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
Shaun Kelsey 0:da5f5b56060a 3 *
Shaun Kelsey 0:da5f5b56060a 4 * Permission is hereby granted, free of charge, to any person obtaining a
Shaun Kelsey 0:da5f5b56060a 5 * copy of this software and associated documentation files (the "Software"),
Shaun Kelsey 0:da5f5b56060a 6 * to deal in the Software without restriction, including without limitation
Shaun Kelsey 0:da5f5b56060a 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
Shaun Kelsey 0:da5f5b56060a 8 * and/or sell copies of the Software, and to permit persons to whom the
Shaun Kelsey 0:da5f5b56060a 9 * Software is furnished to do so, subject to the following conditions:
Shaun Kelsey 0:da5f5b56060a 10 *
Shaun Kelsey 0:da5f5b56060a 11 * The above copyright notice and this permission notice shall be included
Shaun Kelsey 0:da5f5b56060a 12 * in all copies or substantial portions of the Software.
Shaun Kelsey 0:da5f5b56060a 13 *
Shaun Kelsey 0:da5f5b56060a 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
Shaun Kelsey 0:da5f5b56060a 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Shaun Kelsey 0:da5f5b56060a 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Shaun Kelsey 0:da5f5b56060a 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
Shaun Kelsey 0:da5f5b56060a 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
Shaun Kelsey 0:da5f5b56060a 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
Shaun Kelsey 0:da5f5b56060a 20 * OTHER DEALINGS IN THE SOFTWARE.
Shaun Kelsey 0:da5f5b56060a 21 *
Shaun Kelsey 0:da5f5b56060a 22 * Except as contained in this notice, the name of Maxim Integrated
Shaun Kelsey 0:da5f5b56060a 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
Shaun Kelsey 0:da5f5b56060a 24 * Products, Inc. Branding Policy.
Shaun Kelsey 0:da5f5b56060a 25 *
Shaun Kelsey 0:da5f5b56060a 26 * The mere transfer of this software does not imply any licenses
Shaun Kelsey 0:da5f5b56060a 27 * of trade secrets, proprietary technology, copyrights, patents,
Shaun Kelsey 0:da5f5b56060a 28 * trademarks, maskwork rights, or any other form of intellectual
Shaun Kelsey 0:da5f5b56060a 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
Shaun Kelsey 0:da5f5b56060a 30 * ownership rights.
Shaun Kelsey 0:da5f5b56060a 31 ****************************************************************************
Shaun Kelsey 0:da5f5b56060a 32 */
Shaun Kelsey 0:da5f5b56060a 33
Shaun Kelsey 0:da5f5b56060a 34 #include "SSInterface.h"
Shaun Kelsey 0:da5f5b56060a 35 #include "Peripherals.h"
Shaun Kelsey 0:da5f5b56060a 36 #include "assert.h"
Shaun Kelsey 0:da5f5b56060a 37 #include "utils.h"
Shaun Kelsey 5:e458409e913f 38 #include "i2cm.h"
Shaun Kelsey 0:da5f5b56060a 39
Shaun Kelsey 0:da5f5b56060a 40 SSInterface::SSInterface(I2C &i2cBus, PinName ss_mfio, PinName ss_reset)
Shaun Kelsey 5:e458409e913f 41 :m_i2cBus(&i2cBus), m_spiBus(NULL),
Shaun Kelsey 5:e458409e913f 42 mfio_pin(ss_mfio), reset_pin(ss_reset), irq_pin(ss_mfio),
Shaun Kelsey 5:e458409e913f 43 irq_evt(1000000, "irq")
Shaun Kelsey 0:da5f5b56060a 44 {
Shaun Kelsey 0:da5f5b56060a 45 reset_pin.input();
Shaun Kelsey 0:da5f5b56060a 46 irq_pin.fall(callback(this, &SSInterface::irq_handler));
Shaun Kelsey 0:da5f5b56060a 47
Shaun Kelsey 0:da5f5b56060a 48 reset_to_main_app();
Shaun Kelsey 0:da5f5b56060a 49 get_data_type(&data_type, &sc_en);
Shaun Kelsey 0:da5f5b56060a 50 }
Shaun Kelsey 0:da5f5b56060a 51
Shaun Kelsey 0:da5f5b56060a 52 SSInterface::SSInterface(SPI &spiBus, PinName ss_mfio, PinName ss_reset)
Shaun Kelsey 5:e458409e913f 53 :m_i2cBus(NULL), m_spiBus(&spiBus),
Shaun Kelsey 5:e458409e913f 54 mfio_pin(ss_mfio), reset_pin(ss_reset), irq_pin(ss_mfio),
Shaun Kelsey 5:e458409e913f 55 irq_evt(1000000, "irq")
Shaun Kelsey 0:da5f5b56060a 56 {
Shaun Kelsey 0:da5f5b56060a 57 reset_pin.input();
Shaun Kelsey 0:da5f5b56060a 58 irq_pin.fall(callback(this, &SSInterface::irq_handler));
Shaun Kelsey 0:da5f5b56060a 59
Shaun Kelsey 0:da5f5b56060a 60 reset_to_main_app();
Shaun Kelsey 0:da5f5b56060a 61 get_data_type(&data_type, &sc_en);
Shaun Kelsey 0:da5f5b56060a 62 }
Shaun Kelsey 0:da5f5b56060a 63
Shaun Kelsey 0:da5f5b56060a 64 SSInterface::~SSInterface()
Shaun Kelsey 0:da5f5b56060a 65 {
Shaun Kelsey 0:da5f5b56060a 66 }
Shaun Kelsey 0:da5f5b56060a 67
Shaun Kelsey 0:da5f5b56060a 68 SS_STATUS SSInterface::reset_to_main_app()
Shaun Kelsey 0:da5f5b56060a 69 {
Shaun Kelsey 0:da5f5b56060a 70 irq_pin.disable_irq();
Shaun Kelsey 0:da5f5b56060a 71 #if 0
Shaun Kelsey 0:da5f5b56060a 72 uint8_t cmd_bytes[] = { SS_FAM_W_MODE, SS_CMDIDX_MODE };
Shaun Kelsey 0:da5f5b56060a 73 uint8_t data[] = { 0x00 };
Shaun Kelsey 0:da5f5b56060a 74
Shaun Kelsey 0:da5f5b56060a 75 SS_STATUS status = ss_int->write_cmd(
Shaun Kelsey 0:da5f5b56060a 76 &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 77 &data[0], ARRAY_SIZE(data),
Shaun Kelsey 0:da5f5b56060a 78 SS_STARTUP_TIME);
Shaun Kelsey 0:da5f5b56060a 79 if (status == SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 80 in_bootldr = false;
Shaun Kelsey 0:da5f5b56060a 81 return status;
Shaun Kelsey 0:da5f5b56060a 82 #else
Shaun Kelsey 0:da5f5b56060a 83 reset_pin.output();
Shaun Kelsey 0:da5f5b56060a 84 cfg_mfio(PIN_OUTPUT);
Shaun Kelsey 0:da5f5b56060a 85 reset_pin.write(0);
Shaun Kelsey 0:da5f5b56060a 86 wait_ms(SS_RESET_TIME);
Shaun Kelsey 0:da5f5b56060a 87 mfio_pin.write(1);
Shaun Kelsey 0:da5f5b56060a 88 reset_pin.write(1);
Shaun Kelsey 0:da5f5b56060a 89 wait_ms(SS_STARTUP_TIME);
Shaun Kelsey 0:da5f5b56060a 90 cfg_mfio(PIN_INPUT);
Shaun Kelsey 0:da5f5b56060a 91 reset_pin.input();
Shaun Kelsey 0:da5f5b56060a 92 // Verify we exited bootloader mode
Shaun Kelsey 0:da5f5b56060a 93 if (in_bootldr_mode() == 0)
Shaun Kelsey 0:da5f5b56060a 94 return SS_SUCCESS;
Shaun Kelsey 0:da5f5b56060a 95 else
Shaun Kelsey 0:da5f5b56060a 96 return SS_ERR_UNKNOWN;
Shaun Kelsey 0:da5f5b56060a 97 #endif
Shaun Kelsey 0:da5f5b56060a 98
Shaun Kelsey 0:da5f5b56060a 99 irq_pin.enable_irq();
Shaun Kelsey 0:da5f5b56060a 100 }
Shaun Kelsey 0:da5f5b56060a 101
Shaun Kelsey 0:da5f5b56060a 102 SS_STATUS SSInterface::reset_to_bootloader()
Shaun Kelsey 0:da5f5b56060a 103 {
Shaun Kelsey 0:da5f5b56060a 104 irq_pin.disable_irq();
Shaun Kelsey 0:da5f5b56060a 105 #if 0
Shaun Kelsey 0:da5f5b56060a 106 uint8_t cmd_bytes[] = { SS_FAM_W_MODE, SS_CMDIDX_MODE };
Shaun Kelsey 0:da5f5b56060a 107 uint8_t data[] = { SS_MASK_MODE_BOOTLDR };
Shaun Kelsey 0:da5f5b56060a 108
Shaun Kelsey 0:da5f5b56060a 109 SS_STATUS status = ss_int->write_cmd(
Shaun Kelsey 0:da5f5b56060a 110 &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 111 &data[0], ARRAY_SIZE(data),
Shaun Kelsey 0:da5f5b56060a 112 SS_STARTUP_TIME);
Shaun Kelsey 0:da5f5b56060a 113 if (status == SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 114 in_bootldr = true;
Shaun Kelsey 0:da5f5b56060a 115 return status;
Shaun Kelsey 0:da5f5b56060a 116 #else
Shaun Kelsey 0:da5f5b56060a 117 reset_pin.output();
Shaun Kelsey 0:da5f5b56060a 118 cfg_mfio(PIN_OUTPUT);
Shaun Kelsey 0:da5f5b56060a 119 reset_pin.write(0);
Shaun Kelsey 0:da5f5b56060a 120 wait_ms(SS_RESET_TIME);
Shaun Kelsey 0:da5f5b56060a 121 mfio_pin.write(0);
Shaun Kelsey 0:da5f5b56060a 122 reset_pin.write(1);
Shaun Kelsey 0:da5f5b56060a 123 wait_ms(SS_STARTUP_TIME);
Shaun Kelsey 0:da5f5b56060a 124 cfg_mfio(PIN_INPUT);
Shaun Kelsey 0:da5f5b56060a 125 reset_pin.input();
Shaun Kelsey 0:da5f5b56060a 126 // Verify we entered bootloader mode
Shaun Kelsey 0:da5f5b56060a 127 if (in_bootldr_mode() < 0)
Shaun Kelsey 0:da5f5b56060a 128 return SS_ERR_UNKNOWN;
Shaun Kelsey 0:da5f5b56060a 129 return SS_SUCCESS;
Shaun Kelsey 0:da5f5b56060a 130 #endif
Shaun Kelsey 0:da5f5b56060a 131
Shaun Kelsey 0:da5f5b56060a 132 irq_pin.disable_irq();
Shaun Kelsey 0:da5f5b56060a 133 }
Shaun Kelsey 0:da5f5b56060a 134
Shaun Kelsey 0:da5f5b56060a 135 SS_STATUS SSInterface::reset()
Shaun Kelsey 0:da5f5b56060a 136 {
Shaun Kelsey 0:da5f5b56060a 137 int bootldr = in_bootldr_mode();
Shaun Kelsey 0:da5f5b56060a 138 if (bootldr > 0)
Shaun Kelsey 0:da5f5b56060a 139 return reset_to_bootloader();
Shaun Kelsey 0:da5f5b56060a 140 else if (bootldr == 0)
Shaun Kelsey 0:da5f5b56060a 141 return reset_to_main_app();
Shaun Kelsey 0:da5f5b56060a 142 else
Shaun Kelsey 0:da5f5b56060a 143 return SS_ERR_UNKNOWN;
Shaun Kelsey 0:da5f5b56060a 144 }
Shaun Kelsey 0:da5f5b56060a 145
Shaun Kelsey 0:da5f5b56060a 146 SS_STATUS SSInterface::self_test(int idx, uint8_t *result, int sleep_ms){
Shaun Kelsey 5:e458409e913f 147 uint8_t cmd_bytes[] = { SS_FAM_R_SELFTEST, (uint8_t)idx };
Shaun Kelsey 0:da5f5b56060a 148 uint8_t rxbuf[2];
Shaun Kelsey 0:da5f5b56060a 149 SS_STATUS ret;
Shaun Kelsey 0:da5f5b56060a 150
Shaun Kelsey 0:da5f5b56060a 151 result[0] = 0xFF;
Shaun Kelsey 0:da5f5b56060a 152 ret = read_cmd(cmd_bytes, 2, (uint8_t *)0, 0, rxbuf, ARRAY_SIZE(rxbuf), sleep_ms);
Shaun Kelsey 0:da5f5b56060a 153 result[0] = rxbuf[1];
Shaun Kelsey 0:da5f5b56060a 154 return ret;
Shaun Kelsey 0:da5f5b56060a 155 }
Shaun Kelsey 0:da5f5b56060a 156
Shaun Kelsey 0:da5f5b56060a 157 void SSInterface::cfg_mfio(PinDirection dir)
Shaun Kelsey 0:da5f5b56060a 158 {
Shaun Kelsey 0:da5f5b56060a 159 if (dir == PIN_INPUT) {
Shaun Kelsey 0:da5f5b56060a 160 mfio_pin.input();
Shaun Kelsey 0:da5f5b56060a 161 mfio_pin.mode(PullUp);
Shaun Kelsey 0:da5f5b56060a 162 } else {
Shaun Kelsey 0:da5f5b56060a 163 mfio_pin.output();
Shaun Kelsey 0:da5f5b56060a 164 }
Shaun Kelsey 0:da5f5b56060a 165 }
Shaun Kelsey 0:da5f5b56060a 166
Shaun Kelsey 0:da5f5b56060a 167 void SSInterface::enable_irq()
Shaun Kelsey 0:da5f5b56060a 168 {
Shaun Kelsey 0:da5f5b56060a 169 irq_pin.enable_irq();
Shaun Kelsey 0:da5f5b56060a 170 }
Shaun Kelsey 0:da5f5b56060a 171 void SSInterface::disable_irq()
Shaun Kelsey 0:da5f5b56060a 172 {
Shaun Kelsey 0:da5f5b56060a 173 irq_pin.disable_irq();
Shaun Kelsey 0:da5f5b56060a 174 }
Shaun Kelsey 0:da5f5b56060a 175
Shaun Kelsey 0:da5f5b56060a 176 void SSInterface::mfio_selftest(){
Shaun Kelsey 0:da5f5b56060a 177 disable_irq();
Shaun Kelsey 0:da5f5b56060a 178 irq_pin.fall(callback(this, &SSInterface::irq_handler_selftest));
Shaun Kelsey 0:da5f5b56060a 179 enable_irq();
Shaun Kelsey 0:da5f5b56060a 180 }
Shaun Kelsey 0:da5f5b56060a 181
Shaun Kelsey 0:da5f5b56060a 182 int SSInterface::in_bootldr_mode()
Shaun Kelsey 0:da5f5b56060a 183 {
Shaun Kelsey 0:da5f5b56060a 184 uint8_t cmd_bytes[] = { SS_FAM_R_MODE, SS_CMDIDX_MODE };
Shaun Kelsey 0:da5f5b56060a 185 uint8_t rxbuf[2] = { 0 };
Shaun Kelsey 0:da5f5b56060a 186
Shaun Kelsey 0:da5f5b56060a 187 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 188 0, 0,
Shaun Kelsey 0:da5f5b56060a 189 &rxbuf[0], ARRAY_SIZE(rxbuf));
Shaun Kelsey 0:da5f5b56060a 190 if (status != SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 191 return -1;
Shaun Kelsey 0:da5f5b56060a 192
Shaun Kelsey 0:da5f5b56060a 193 return (rxbuf[1] & SS_MASK_MODE_BOOTLDR);
Shaun Kelsey 0:da5f5b56060a 194 }
Shaun Kelsey 0:da5f5b56060a 195
Shaun Kelsey 0:da5f5b56060a 196 const char* SSInterface::get_ss_fw_version()
Shaun Kelsey 0:da5f5b56060a 197 {
Shaun Kelsey 0:da5f5b56060a 198 uint8_t cmd_bytes[2];
Shaun Kelsey 0:da5f5b56060a 199 uint8_t rxbuf[4];
Shaun Kelsey 0:da5f5b56060a 200
Shaun Kelsey 0:da5f5b56060a 201 int bootldr = in_bootldr_mode();
Shaun Kelsey 0:da5f5b56060a 202
Shaun Kelsey 0:da5f5b56060a 203 if (bootldr > 0) {
Shaun Kelsey 0:da5f5b56060a 204 cmd_bytes[0] = SS_FAM_R_BOOTLOADER;
Shaun Kelsey 0:da5f5b56060a 205 cmd_bytes[1] = SS_CMDIDX_BOOTFWVERSION;
Shaun Kelsey 0:da5f5b56060a 206 } else if (bootldr == 0) {
Shaun Kelsey 0:da5f5b56060a 207 cmd_bytes[0] = SS_FAM_R_IDENTITY;
Shaun Kelsey 0:da5f5b56060a 208 cmd_bytes[1] = SS_CMDIDX_FWVERSION;
Shaun Kelsey 0:da5f5b56060a 209 } else {
Shaun Kelsey 0:da5f5b56060a 210 return plat_name;
Shaun Kelsey 0:da5f5b56060a 211 }
Shaun Kelsey 0:da5f5b56060a 212
Shaun Kelsey 0:da5f5b56060a 213 SS_STATUS status = read_cmd(
Shaun Kelsey 0:da5f5b56060a 214 &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 215 0, 0,
Shaun Kelsey 0:da5f5b56060a 216 &rxbuf[0], ARRAY_SIZE(rxbuf));
Shaun Kelsey 0:da5f5b56060a 217
Shaun Kelsey 0:da5f5b56060a 218 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 219 snprintf(fw_version, sizeof(fw_version),
Shaun Kelsey 0:da5f5b56060a 220 "%d.%d.%d", rxbuf[1], rxbuf[2], rxbuf[3]);
Shaun Kelsey 0:da5f5b56060a 221 pr_info("fw_version:%s\r\n", fw_version);
Shaun Kelsey 0:da5f5b56060a 222 }
Shaun Kelsey 0:da5f5b56060a 223
Shaun Kelsey 0:da5f5b56060a 224 return &fw_version[0];
Shaun Kelsey 0:da5f5b56060a 225 }
Shaun Kelsey 0:da5f5b56060a 226
Shaun Kelsey 0:da5f5b56060a 227 const char* SSInterface::get_ss_platform_name()
Shaun Kelsey 0:da5f5b56060a 228 {
Shaun Kelsey 0:da5f5b56060a 229 uint8_t cmd_bytes[] = { SS_FAM_R_IDENTITY, SS_CMDIDX_PLATTYPE };
Shaun Kelsey 0:da5f5b56060a 230 uint8_t rxbuf[2];
Shaun Kelsey 0:da5f5b56060a 231
Shaun Kelsey 0:da5f5b56060a 232 SS_STATUS status = read_cmd(
Shaun Kelsey 0:da5f5b56060a 233 &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 234 0, 0,
Shaun Kelsey 0:da5f5b56060a 235 &rxbuf[0], ARRAY_SIZE(rxbuf));
Shaun Kelsey 0:da5f5b56060a 236
Shaun Kelsey 0:da5f5b56060a 237 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 238 if (rxbuf[1] == SS_PLAT_MAX3263X) {
Shaun Kelsey 0:da5f5b56060a 239 if (in_bootldr_mode() > 0) {
Shaun Kelsey 0:da5f5b56060a 240 plat_name = SS_BOOTLOADER_PLATFORM_MAX3263X;
Shaun Kelsey 0:da5f5b56060a 241 } else {
Shaun Kelsey 0:da5f5b56060a 242 plat_name = SS_PLATFORM_MAX3263X;
Shaun Kelsey 0:da5f5b56060a 243 }
Shaun Kelsey 0:da5f5b56060a 244 } else if (rxbuf[1] == SS_PLAT_MAX32660) {
Shaun Kelsey 0:da5f5b56060a 245 if (in_bootldr_mode() > 0) {
Shaun Kelsey 0:da5f5b56060a 246 plat_name = SS_BOOTLOADER_PLATFORM_MAX32660;
Shaun Kelsey 0:da5f5b56060a 247 } else {
Shaun Kelsey 0:da5f5b56060a 248 plat_name = SS_PLATFORM_MAX32660;
Shaun Kelsey 0:da5f5b56060a 249 }
Shaun Kelsey 0:da5f5b56060a 250 }
Shaun Kelsey 0:da5f5b56060a 251 }
Shaun Kelsey 0:da5f5b56060a 252
Shaun Kelsey 0:da5f5b56060a 253 return plat_name;
Shaun Kelsey 0:da5f5b56060a 254 }
Shaun Kelsey 0:da5f5b56060a 255
Shaun Kelsey 0:da5f5b56060a 256 SS_STATUS SSInterface::write_cmd(uint8_t *cmd_bytes, int cmd_bytes_len,
Shaun Kelsey 0:da5f5b56060a 257 uint8_t *data, int data_len,
Shaun Kelsey 0:da5f5b56060a 258 int sleep_ms)
Shaun Kelsey 0:da5f5b56060a 259 {
Shaun Kelsey 0:da5f5b56060a 260 int total_len = data_len + cmd_bytes_len;
Shaun Kelsey 0:da5f5b56060a 261
Shaun Kelsey 0:da5f5b56060a 262 if (total_len <= SS_SMALL_BUF_SIZE) {
Shaun Kelsey 0:da5f5b56060a 263 return write_cmd_small(cmd_bytes, cmd_bytes_len, data, data_len, sleep_ms);
Shaun Kelsey 5:e458409e913f 264 } else if (total_len <= SS_MED_BUF_SIZE) {
Shaun Kelsey 5:e458409e913f 265 return write_cmd_medium(cmd_bytes, cmd_bytes_len, data, data_len, sleep_ms);
Shaun Kelsey 0:da5f5b56060a 266 } else if (total_len <= SS_LARGE_BUF_SIZE) {
Shaun Kelsey 0:da5f5b56060a 267 return write_cmd_large(cmd_bytes, cmd_bytes_len, data, data_len, sleep_ms);
Shaun Kelsey 0:da5f5b56060a 268 } else {
Shaun Kelsey 0:da5f5b56060a 269 assert_msg(true, "Tried to send I2C tx larger than maximum allowed size\n");
Shaun Kelsey 0:da5f5b56060a 270 return SS_ERR_DATA_FORMAT;
Shaun Kelsey 0:da5f5b56060a 271 }
Shaun Kelsey 0:da5f5b56060a 272 }
Shaun Kelsey 0:da5f5b56060a 273
Shaun Kelsey 0:da5f5b56060a 274 SS_STATUS SSInterface::write_cmd(uint8_t *tx_buf, int tx_len, int sleep_ms)
Shaun Kelsey 0:da5f5b56060a 275 {
Shaun Kelsey 0:da5f5b56060a 276 pr_info("write_cmd: ");
Shaun Kelsey 0:da5f5b56060a 277 for (int i = 0; i < tx_len; i++) {
Shaun Kelsey 0:da5f5b56060a 278 pr_info("0x%02X ", tx_buf[i]);
Shaun Kelsey 0:da5f5b56060a 279 }
Shaun Kelsey 0:da5f5b56060a 280 pr_info("\r\n");
Shaun Kelsey 0:da5f5b56060a 281
Shaun Kelsey 5:e458409e913f 282 int ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)tx_buf, tx_len);
Shaun Kelsey 5:e458409e913f 283
Shaun Kelsey 5:e458409e913f 284 int retries = 4;
Shaun Kelsey 5:e458409e913f 285 while (ret != 0 && retries-- > 0) {
Shaun Kelsey 5:e458409e913f 286 pr_err("i2c wr retry\r\n");
Shaun Kelsey 5:e458409e913f 287 wait_ms(1);
Shaun Kelsey 5:e458409e913f 288 ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)tx_buf, tx_len);
Shaun Kelsey 5:e458409e913f 289 }
Shaun Kelsey 0:da5f5b56060a 290
Shaun Kelsey 0:da5f5b56060a 291 if (ret != 0) {
Shaun Kelsey 0:da5f5b56060a 292 pr_err("m_i2cBus->write returned %d\r\n", ret);
Shaun Kelsey 0:da5f5b56060a 293 return SS_ERR_UNAVAILABLE;
Shaun Kelsey 0:da5f5b56060a 294 }
Shaun Kelsey 0:da5f5b56060a 295
Shaun Kelsey 0:da5f5b56060a 296 wait_ms(sleep_ms);
Shaun Kelsey 0:da5f5b56060a 297
Shaun Kelsey 0:da5f5b56060a 298 char status_byte;
Shaun Kelsey 5:e458409e913f 299 ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, &status_byte, 1);
Shaun Kelsey 5:e458409e913f 300 bool try_again = (status_byte == SS_ERR_TRY_AGAIN);
Shaun Kelsey 5:e458409e913f 301 while ((ret != 0 || try_again)
Shaun Kelsey 5:e458409e913f 302 && retries-- > 0) {
Shaun Kelsey 5:e458409e913f 303 pr_info("i2c rd retry\r\n");
Shaun Kelsey 5:e458409e913f 304 wait_ms(sleep_ms);
Shaun Kelsey 5:e458409e913f 305 ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, &status_byte, 1);
Shaun Kelsey 5:e458409e913f 306 try_again = (status_byte == SS_ERR_TRY_AGAIN);
Shaun Kelsey 5:e458409e913f 307 }
Shaun Kelsey 0:da5f5b56060a 308
Shaun Kelsey 5:e458409e913f 309 if (ret != 0 || try_again) {
Shaun Kelsey 5:e458409e913f 310 pr_err("m_i2cBus->read returned %d, ss status_byte %d\r\n", ret, status_byte);
Shaun Kelsey 0:da5f5b56060a 311 return SS_ERR_UNAVAILABLE;
Shaun Kelsey 0:da5f5b56060a 312 }
Shaun Kelsey 0:da5f5b56060a 313
Shaun Kelsey 0:da5f5b56060a 314 pr_info("status_byte: %d\r\n", status_byte);
Shaun Kelsey 0:da5f5b56060a 315
Shaun Kelsey 0:da5f5b56060a 316 return (SS_STATUS)status_byte;
Shaun Kelsey 0:da5f5b56060a 317 }
Shaun Kelsey 0:da5f5b56060a 318
Shaun Kelsey 0:da5f5b56060a 319 SS_STATUS SSInterface::write_cmd_small(uint8_t *cmd_bytes, int cmd_bytes_len,
Shaun Kelsey 0:da5f5b56060a 320 uint8_t *data, int data_len,
Shaun Kelsey 0:da5f5b56060a 321 int sleep_ms)
Shaun Kelsey 0:da5f5b56060a 322 {
Shaun Kelsey 0:da5f5b56060a 323 uint8_t write_buf[SS_SMALL_BUF_SIZE];
Shaun Kelsey 0:da5f5b56060a 324 memcpy(write_buf, cmd_bytes, cmd_bytes_len);
Shaun Kelsey 0:da5f5b56060a 325 memcpy(write_buf + cmd_bytes_len, data, data_len);
Shaun Kelsey 0:da5f5b56060a 326
Shaun Kelsey 0:da5f5b56060a 327 SS_STATUS status = write_cmd(write_buf, cmd_bytes_len + data_len, sleep_ms);
Shaun Kelsey 0:da5f5b56060a 328 return status;
Shaun Kelsey 0:da5f5b56060a 329 }
Shaun Kelsey 0:da5f5b56060a 330
Shaun Kelsey 5:e458409e913f 331 SS_STATUS SSInterface::write_cmd_medium(uint8_t *cmd_bytes, int cmd_bytes_len,
Shaun Kelsey 5:e458409e913f 332 uint8_t *data, int data_len,
Shaun Kelsey 5:e458409e913f 333 int sleep_ms)
Shaun Kelsey 5:e458409e913f 334 {
Shaun Kelsey 5:e458409e913f 335 uint8_t write_buf[SS_MED_BUF_SIZE];
Shaun Kelsey 5:e458409e913f 336 memcpy(write_buf, cmd_bytes, cmd_bytes_len);
Shaun Kelsey 5:e458409e913f 337 memcpy(write_buf + cmd_bytes_len, data, data_len);
Shaun Kelsey 5:e458409e913f 338
Shaun Kelsey 5:e458409e913f 339 SS_STATUS status = write_cmd(write_buf, cmd_bytes_len + data_len, sleep_ms);
Shaun Kelsey 5:e458409e913f 340 return status;
Shaun Kelsey 5:e458409e913f 341 }
Shaun Kelsey 5:e458409e913f 342
Shaun Kelsey 0:da5f5b56060a 343 SS_STATUS SSInterface::write_cmd_large(uint8_t *cmd_bytes, int cmd_bytes_len,
Shaun Kelsey 0:da5f5b56060a 344 uint8_t *data, int data_len,
Shaun Kelsey 0:da5f5b56060a 345 int sleep_ms)
Shaun Kelsey 0:da5f5b56060a 346 {
Shaun Kelsey 0:da5f5b56060a 347 uint8_t write_buf[SS_LARGE_BUF_SIZE];
Shaun Kelsey 0:da5f5b56060a 348 memcpy(write_buf, cmd_bytes, cmd_bytes_len);
Shaun Kelsey 0:da5f5b56060a 349 memcpy(write_buf + cmd_bytes_len, data, data_len);
Shaun Kelsey 0:da5f5b56060a 350
Shaun Kelsey 0:da5f5b56060a 351 SS_STATUS status = write_cmd(write_buf, cmd_bytes_len + data_len, sleep_ms);
Shaun Kelsey 0:da5f5b56060a 352 return status;
Shaun Kelsey 0:da5f5b56060a 353 }
Shaun Kelsey 0:da5f5b56060a 354
Shaun Kelsey 0:da5f5b56060a 355 SS_STATUS SSInterface::read_cmd(uint8_t *cmd_bytes, int cmd_bytes_len,
Shaun Kelsey 0:da5f5b56060a 356 uint8_t *data, int data_len,
Shaun Kelsey 0:da5f5b56060a 357 uint8_t *rxbuf, int rxbuf_sz,
Shaun Kelsey 0:da5f5b56060a 358 int sleep_ms)
Shaun Kelsey 0:da5f5b56060a 359 {
Shaun Kelsey 0:da5f5b56060a 360 pr_info("read_cmd: ");
Shaun Kelsey 0:da5f5b56060a 361 for (int i = 0; i < cmd_bytes_len; i++) {
Shaun Kelsey 0:da5f5b56060a 362 pr_info("0x%02X ", cmd_bytes[i]);
Shaun Kelsey 0:da5f5b56060a 363 }
Shaun Kelsey 0:da5f5b56060a 364 pr_info("\r\n");
Shaun Kelsey 0:da5f5b56060a 365
Shaun Kelsey 5:e458409e913f 366
Shaun Kelsey 5:e458409e913f 367 int retries = 4;
Shaun Kelsey 5:e458409e913f 368
Shaun Kelsey 5:e458409e913f 369 int ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)cmd_bytes, cmd_bytes_len, (data_len != 0));
Shaun Kelsey 0:da5f5b56060a 370
Shaun Kelsey 0:da5f5b56060a 371 if (data_len != 0) {
Shaun Kelsey 0:da5f5b56060a 372 ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)data, data_len, false);
Shaun Kelsey 0:da5f5b56060a 373 }
Shaun Kelsey 0:da5f5b56060a 374
Shaun Kelsey 5:e458409e913f 375 while (ret != 0 && retries-- > 0) {
Shaun Kelsey 5:e458409e913f 376 pr_err("i2c wr retry\r\n");
Shaun Kelsey 5:e458409e913f 377 wait_ms(1);
Shaun Kelsey 5:e458409e913f 378 ret = m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)cmd_bytes, cmd_bytes_len, (data_len != 0));
Shaun Kelsey 5:e458409e913f 379 if (data_len != 0) {
Shaun Kelsey 5:e458409e913f 380 ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)data, data_len, false);
Shaun Kelsey 5:e458409e913f 381 }
Shaun Kelsey 5:e458409e913f 382 }
Shaun Kelsey 5:e458409e913f 383
Shaun Kelsey 0:da5f5b56060a 384 if (ret != 0) {
Shaun Kelsey 0:da5f5b56060a 385 pr_err("m_i2cBus->write returned %d\r\n", ret);
Shaun Kelsey 0:da5f5b56060a 386 return SS_ERR_UNAVAILABLE;
Shaun Kelsey 0:da5f5b56060a 387 }
Shaun Kelsey 0:da5f5b56060a 388
Shaun Kelsey 0:da5f5b56060a 389 wait_ms(sleep_ms);
Shaun Kelsey 0:da5f5b56060a 390
Shaun Kelsey 5:e458409e913f 391 ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, (char*)rxbuf, rxbuf_sz);
Shaun Kelsey 5:e458409e913f 392 bool try_again = (rxbuf[0] == SS_ERR_TRY_AGAIN);
Shaun Kelsey 5:e458409e913f 393 while ((ret != 0 || try_again) && retries-- > 0) {
Shaun Kelsey 5:e458409e913f 394 pr_info("i2c rd retry\r\n");
Shaun Kelsey 5:e458409e913f 395 wait_ms(sleep_ms);
Shaun Kelsey 5:e458409e913f 396 ret = m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, (char*)rxbuf, rxbuf_sz);
Shaun Kelsey 5:e458409e913f 397 try_again = (rxbuf[0] == SS_ERR_TRY_AGAIN);
Shaun Kelsey 5:e458409e913f 398 }
Shaun Kelsey 5:e458409e913f 399 if (ret != 0 || try_again) {
Shaun Kelsey 5:e458409e913f 400 pr_err("m_i2cBus->read returned %d, ss status_byte %d\r\n", ret, rxbuf[0]);
Shaun Kelsey 0:da5f5b56060a 401 return SS_ERR_UNAVAILABLE;
Shaun Kelsey 0:da5f5b56060a 402 }
Shaun Kelsey 0:da5f5b56060a 403
Shaun Kelsey 0:da5f5b56060a 404 pr_info("status_byte: %d\r\n", rxbuf[0]);
Shaun Kelsey 0:da5f5b56060a 405 pr_info("data: ");
Shaun Kelsey 0:da5f5b56060a 406 for (int i = 1; i < rxbuf_sz; i++) {
Shaun Kelsey 0:da5f5b56060a 407 pr_info("0x%02X ", rxbuf[i]);
Shaun Kelsey 0:da5f5b56060a 408 }
Shaun Kelsey 0:da5f5b56060a 409 pr_info("\r\n");
Shaun Kelsey 0:da5f5b56060a 410
Shaun Kelsey 0:da5f5b56060a 411 return (SS_STATUS)rxbuf[0];
Shaun Kelsey 0:da5f5b56060a 412 }
Shaun Kelsey 0:da5f5b56060a 413
Shaun Kelsey 0:da5f5b56060a 414 SS_STATUS SSInterface::get_reg(int idx, uint8_t addr, uint32_t *val)
Shaun Kelsey 0:da5f5b56060a 415 {
Shaun Kelsey 0:da5f5b56060a 416 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");
Shaun Kelsey 0:da5f5b56060a 417
Shaun Kelsey 0:da5f5b56060a 418 uint8_t cmd_bytes[] = { SS_FAM_R_REGATTRIBS, (uint8_t)idx };
Shaun Kelsey 0:da5f5b56060a 419 uint8_t rx_reg_attribs[3] = {0};
Shaun Kelsey 0:da5f5b56060a 420
Shaun Kelsey 0:da5f5b56060a 421 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 422 0, 0,
Shaun Kelsey 0:da5f5b56060a 423 &rx_reg_attribs[0], ARRAY_SIZE(rx_reg_attribs));
Shaun Kelsey 0:da5f5b56060a 424
Shaun Kelsey 0:da5f5b56060a 425 if (status != SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 426 return status;
Shaun Kelsey 0:da5f5b56060a 427
Shaun Kelsey 0:da5f5b56060a 428 int reg_width = rx_reg_attribs[1];
Shaun Kelsey 0:da5f5b56060a 429
Shaun Kelsey 0:da5f5b56060a 430 uint8_t cmd_bytes2[] = { SS_FAM_R_READREG, (uint8_t)idx, addr };
Shaun Kelsey 0:da5f5b56060a 431 uint8_t rxbuf[5] = {0};
Shaun Kelsey 0:da5f5b56060a 432
Shaun Kelsey 0:da5f5b56060a 433 status = read_cmd(&cmd_bytes2[0], ARRAY_SIZE(cmd_bytes2),
Shaun Kelsey 0:da5f5b56060a 434 0, 0,
Shaun Kelsey 5:e458409e913f 435 &rxbuf[0], reg_width + 1);
Shaun Kelsey 0:da5f5b56060a 436
Shaun Kelsey 0:da5f5b56060a 437 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 438 *val = 0;
Shaun Kelsey 0:da5f5b56060a 439 for (int i = 0; i < reg_width; i++) {
Shaun Kelsey 0:da5f5b56060a 440 *val = (*val << 8) | rxbuf[i + 1];
Shaun Kelsey 0:da5f5b56060a 441 }
Shaun Kelsey 0:da5f5b56060a 442 }
Shaun Kelsey 0:da5f5b56060a 443
Shaun Kelsey 0:da5f5b56060a 444 return status;
Shaun Kelsey 0:da5f5b56060a 445 }
Shaun Kelsey 0:da5f5b56060a 446
Shaun Kelsey 0:da5f5b56060a 447 SS_STATUS SSInterface::set_reg(int idx, uint8_t addr, uint32_t val, int byte_size)
Shaun Kelsey 0:da5f5b56060a 448 {
Shaun Kelsey 0:da5f5b56060a 449 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");
Shaun Kelsey 0:da5f5b56060a 450
Shaun Kelsey 0:da5f5b56060a 451 uint8_t cmd_bytes[] = { SS_FAM_W_WRITEREG, (uint8_t)idx, addr };
Shaun Kelsey 0:da5f5b56060a 452 uint8_t data_bytes[4];
Shaun Kelsey 0:da5f5b56060a 453 for (int i = 0; i < byte_size; i++) {
Shaun Kelsey 0:da5f5b56060a 454 data_bytes[i] = (val >> (8 * (byte_size - 1)) & 0xFF);
Shaun Kelsey 0:da5f5b56060a 455 }
Shaun Kelsey 0:da5f5b56060a 456
Shaun Kelsey 0:da5f5b56060a 457 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 458 &data_bytes[0], byte_size);
Shaun Kelsey 0:da5f5b56060a 459
Shaun Kelsey 0:da5f5b56060a 460 return status;
Shaun Kelsey 0:da5f5b56060a 461 }
Shaun Kelsey 0:da5f5b56060a 462
Shaun Kelsey 0:da5f5b56060a 463 SS_STATUS SSInterface::dump_reg(int idx, addr_val_pair* reg_vals, int reg_vals_sz, int* num_regs)
Shaun Kelsey 0:da5f5b56060a 464 {
Shaun Kelsey 0:da5f5b56060a 465 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");
Shaun Kelsey 0:da5f5b56060a 466
Shaun Kelsey 0:da5f5b56060a 467 uint8_t cmd_bytes[] = { SS_FAM_R_REGATTRIBS, (uint8_t)idx };
Shaun Kelsey 0:da5f5b56060a 468 uint8_t rx_reg_attribs[3] = {0};
Shaun Kelsey 0:da5f5b56060a 469
Shaun Kelsey 0:da5f5b56060a 470 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 471 0, 0,
Shaun Kelsey 0:da5f5b56060a 472 &rx_reg_attribs[0], ARRAY_SIZE(rx_reg_attribs));
Shaun Kelsey 0:da5f5b56060a 473
Shaun Kelsey 0:da5f5b56060a 474 if (status != SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 475 return status;
Shaun Kelsey 0:da5f5b56060a 476
Shaun Kelsey 0:da5f5b56060a 477 int reg_width = rx_reg_attribs[1];
Shaun Kelsey 0:da5f5b56060a 478 *num_regs = rx_reg_attribs[2];
Shaun Kelsey 0:da5f5b56060a 479 assert_msg((*num_regs <= reg_vals_sz), "Need to increase reg_vals array to hold all dump_reg data");
Shaun Kelsey 0:da5f5b56060a 480 assert_msg(((size_t)reg_width <= sizeof(uint32_t)), "IC returned register values greater than 4 bytes in width");
Shaun Kelsey 0:da5f5b56060a 481
Shaun Kelsey 0:da5f5b56060a 482 int dump_reg_sz = (*num_regs) * (reg_width + 1) + 1; //+1 to reg_width for address, +1 for status byte
Shaun Kelsey 0:da5f5b56060a 483
Shaun Kelsey 0:da5f5b56060a 484 uint8_t rxbuf[512];
Shaun Kelsey 0:da5f5b56060a 485 assert_msg(((size_t)dump_reg_sz <= sizeof(rxbuf)), "Need to increase buffer size to receive dump_reg data");
Shaun Kelsey 0:da5f5b56060a 486
Shaun Kelsey 0:da5f5b56060a 487 cmd_bytes[0] = SS_FAM_R_DUMPREG;
Shaun Kelsey 0:da5f5b56060a 488 status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 489 0, 0,
Shaun Kelsey 0:da5f5b56060a 490 &rxbuf[0], dump_reg_sz, SS_DUMP_REG_SLEEP_MS);
Shaun Kelsey 0:da5f5b56060a 491
Shaun Kelsey 0:da5f5b56060a 492 if (status != SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 493 return status;
Shaun Kelsey 0:da5f5b56060a 494
Shaun Kelsey 0:da5f5b56060a 495 //rxbuf format is [status][addr0](reg_width x [val0])[addr1](reg_width x [val1])...
Shaun Kelsey 0:da5f5b56060a 496 for (int reg = 0; reg < *num_regs; reg++) {
Shaun Kelsey 0:da5f5b56060a 497 reg_vals[reg].addr = rxbuf[(reg * (reg_width + 1)) + 1];
Shaun Kelsey 0:da5f5b56060a 498 uint32_t *val = &(reg_vals[reg].val);
Shaun Kelsey 0:da5f5b56060a 499 *val = 0;
Shaun Kelsey 0:da5f5b56060a 500 for (int byte = 0; byte < reg_width; byte++) {
Shaun Kelsey 0:da5f5b56060a 501 *val = (*val << 8) | rxbuf[(reg * (reg_width + 1)) + byte + 2];
Shaun Kelsey 0:da5f5b56060a 502 }
Shaun Kelsey 0:da5f5b56060a 503 }
Shaun Kelsey 0:da5f5b56060a 504
Shaun Kelsey 0:da5f5b56060a 505 return SS_SUCCESS;
Shaun Kelsey 0:da5f5b56060a 506 }
Shaun Kelsey 0:da5f5b56060a 507
Shaun Kelsey 0:da5f5b56060a 508 SS_STATUS SSInterface::enable_sensor(int idx, int mode, ss_data_req *data_req)
Shaun Kelsey 0:da5f5b56060a 509 {
Shaun Kelsey 0:da5f5b56060a 510 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");
Shaun Kelsey 0:da5f5b56060a 511 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");
Shaun Kelsey 0:da5f5b56060a 512 assert_msg((mode != 0), "Tried to enable sensor to mode 0, but mode 0 is disable");
Shaun Kelsey 0:da5f5b56060a 513
Shaun Kelsey 5:e458409e913f 514
Shaun Kelsey 0:da5f5b56060a 515 uint8_t cmd_bytes[] = { SS_FAM_W_SENSORMODE, (uint8_t)idx, (uint8_t)mode };
Shaun Kelsey 0:da5f5b56060a 516
Shaun Kelsey 0:da5f5b56060a 517 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS);
Shaun Kelsey 0:da5f5b56060a 518
Shaun Kelsey 0:da5f5b56060a 519 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 520 sensor_enabled_mode[idx] = mode;
Shaun Kelsey 0:da5f5b56060a 521 sensor_data_reqs[idx] = data_req;
Shaun Kelsey 0:da5f5b56060a 522 }
Shaun Kelsey 0:da5f5b56060a 523 return status;
Shaun Kelsey 0:da5f5b56060a 524 }
Shaun Kelsey 0:da5f5b56060a 525
Shaun Kelsey 0:da5f5b56060a 526 SS_STATUS SSInterface::disable_sensor(int idx)
Shaun Kelsey 0:da5f5b56060a 527 {
Shaun Kelsey 0:da5f5b56060a 528 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");
Shaun Kelsey 0:da5f5b56060a 529 uint8_t cmd_bytes[] = { SS_FAM_W_SENSORMODE, (uint8_t)idx, 0 };
Shaun Kelsey 0:da5f5b56060a 530
Shaun Kelsey 0:da5f5b56060a 531 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS);
Shaun Kelsey 0:da5f5b56060a 532
Shaun Kelsey 0:da5f5b56060a 533 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 534 sensor_enabled_mode[idx] = 0;
Shaun Kelsey 0:da5f5b56060a 535 sensor_data_reqs[idx] = 0;
Shaun Kelsey 0:da5f5b56060a 536 }
Shaun Kelsey 0:da5f5b56060a 537
Shaun Kelsey 0:da5f5b56060a 538 return status;
Shaun Kelsey 0:da5f5b56060a 539 }
Shaun Kelsey 0:da5f5b56060a 540
Shaun Kelsey 0:da5f5b56060a 541 SS_STATUS SSInterface::enable_algo(int idx, int mode, ss_data_req *data_req)
Shaun Kelsey 0:da5f5b56060a 542 {
Shaun Kelsey 0:da5f5b56060a 543 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");
Shaun Kelsey 0:da5f5b56060a 544 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");
Shaun Kelsey 0:da5f5b56060a 545 assert_msg((mode != 0), "Tried to enable algo to mode 0, but mode 0 is disable");
Shaun Kelsey 0:da5f5b56060a 546
Shaun Kelsey 0:da5f5b56060a 547 uint8_t cmd_bytes[] = { SS_FAM_W_ALGOMODE, (uint8_t)idx, (uint8_t)mode };
Shaun Kelsey 0:da5f5b56060a 548
Shaun Kelsey 5:e458409e913f 549 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, 4*SS_ENABLE_SENSOR_SLEEP_MS);
Shaun Kelsey 0:da5f5b56060a 550
Shaun Kelsey 0:da5f5b56060a 551 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 552 algo_enabled_mode[idx] = mode;
Shaun Kelsey 0:da5f5b56060a 553 algo_data_reqs[idx] = data_req;
Shaun Kelsey 0:da5f5b56060a 554 }
Shaun Kelsey 0:da5f5b56060a 555
Shaun Kelsey 0:da5f5b56060a 556 return status;
Shaun Kelsey 0:da5f5b56060a 557 }
Shaun Kelsey 0:da5f5b56060a 558
Shaun Kelsey 0:da5f5b56060a 559 SS_STATUS SSInterface::disable_algo(int idx)
Shaun Kelsey 0:da5f5b56060a 560 {
Shaun Kelsey 0:da5f5b56060a 561 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");
Shaun Kelsey 0:da5f5b56060a 562 uint8_t cmd_bytes[] = { SS_FAM_W_ALGOMODE, (uint8_t)idx, 0 };
Shaun Kelsey 0:da5f5b56060a 563
Shaun Kelsey 0:da5f5b56060a 564 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS);
Shaun Kelsey 0:da5f5b56060a 565
Shaun Kelsey 0:da5f5b56060a 566 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 567 algo_enabled_mode[idx] = 0;
Shaun Kelsey 0:da5f5b56060a 568 algo_data_reqs[idx] = 0;
Shaun Kelsey 0:da5f5b56060a 569 }
Shaun Kelsey 0:da5f5b56060a 570
Shaun Kelsey 0:da5f5b56060a 571 return status;
Shaun Kelsey 0:da5f5b56060a 572 }
Shaun Kelsey 0:da5f5b56060a 573
Shaun Kelsey 5:e458409e913f 574 SS_STATUS SSInterface::set_algo_cfg(int algo_idx, int cfg_idx, uint8_t *cfg, int cfg_sz)
Shaun Kelsey 5:e458409e913f 575 {
Shaun Kelsey 5:e458409e913f 576 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");
Shaun Kelsey 5:e458409e913f 577 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");
Shaun Kelsey 5:e458409e913f 578
Shaun Kelsey 5:e458409e913f 579 uint8_t cmd_bytes[] = { SS_FAM_W_ALGOCONFIG, (uint8_t)algo_idx, (uint8_t)cfg_idx };
Shaun Kelsey 5:e458409e913f 580 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 5:e458409e913f 581 cfg, cfg_sz);
Shaun Kelsey 5:e458409e913f 582
Shaun Kelsey 5:e458409e913f 583 return status;
Shaun Kelsey 5:e458409e913f 584 }
Shaun Kelsey 5:e458409e913f 585
Shaun Kelsey 5:e458409e913f 586 SS_STATUS SSInterface::get_algo_cfg(int algo_idx, int cfg_idx, uint8_t *cfg, int cfg_sz)
Shaun Kelsey 5:e458409e913f 587 {
Shaun Kelsey 5:e458409e913f 588 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");
Shaun Kelsey 5:e458409e913f 589 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");
Shaun Kelsey 5:e458409e913f 590
Shaun Kelsey 5:e458409e913f 591 uint8_t cmd_bytes[] = { SS_FAM_R_ALGOCONFIG, (uint8_t)algo_idx, (uint8_t)cfg_idx };
Shaun Kelsey 5:e458409e913f 592 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 5:e458409e913f 593 0, 0,
Shaun Kelsey 5:e458409e913f 594 cfg, cfg_sz);
Shaun Kelsey 5:e458409e913f 595
Shaun Kelsey 5:e458409e913f 596 return status;
Shaun Kelsey 5:e458409e913f 597 }
Shaun Kelsey 5:e458409e913f 598
Shaun Kelsey 0:da5f5b56060a 599 SS_STATUS SSInterface::set_data_type(int data_type, bool sc_en)
Shaun Kelsey 0:da5f5b56060a 600 {
Shaun Kelsey 0:da5f5b56060a 601 assert_msg((data_type >= 0) && (data_type <= 3), "Invalid value for data_type");
Shaun Kelsey 0:da5f5b56060a 602 uint8_t cmd_bytes[] = { SS_FAM_W_COMMCHAN, SS_CMDIDX_OUTPUTMODE };
Shaun Kelsey 1:7a55c0c7d6d9 603 uint8_t data_bytes[] = { (uint8_t)((sc_en ? SS_MASK_OUTPUTMODE_SC_EN : 0) |
Shaun Kelsey 1:7a55c0c7d6d9 604 ((data_type << SS_SHIFT_OUTPUTMODE_DATATYPE) & SS_MASK_OUTPUTMODE_DATATYPE)) };
Shaun Kelsey 0:da5f5b56060a 605
Shaun Kelsey 0:da5f5b56060a 606 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 607 &data_bytes[0], ARRAY_SIZE(data_bytes));
Shaun Kelsey 0:da5f5b56060a 608
Shaun Kelsey 0:da5f5b56060a 609 this->data_type = data_type;
Shaun Kelsey 0:da5f5b56060a 610 this->sc_en = sc_en;
Shaun Kelsey 0:da5f5b56060a 611
Shaun Kelsey 0:da5f5b56060a 612 return status;
Shaun Kelsey 0:da5f5b56060a 613 }
Shaun Kelsey 0:da5f5b56060a 614
Shaun Kelsey 0:da5f5b56060a 615
Shaun Kelsey 0:da5f5b56060a 616 SS_STATUS SSInterface::get_data_type(int *data_type, bool *sc_en)
Shaun Kelsey 0:da5f5b56060a 617 {
Shaun Kelsey 0:da5f5b56060a 618 uint8_t cmd_bytes[] = { SS_FAM_R_COMMCHAN, SS_CMDIDX_OUTPUTMODE };
Shaun Kelsey 0:da5f5b56060a 619 uint8_t rxbuf[2] = {0};
Shaun Kelsey 0:da5f5b56060a 620
Shaun Kelsey 0:da5f5b56060a 621 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 622 0, 0,
Shaun Kelsey 0:da5f5b56060a 623 &rxbuf[0], ARRAY_SIZE(rxbuf));
Shaun Kelsey 0:da5f5b56060a 624 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 625 *data_type =
Shaun Kelsey 0:da5f5b56060a 626 (rxbuf[1] & SS_MASK_OUTPUTMODE_DATATYPE) >> SS_SHIFT_OUTPUTMODE_DATATYPE;
Shaun Kelsey 0:da5f5b56060a 627 *sc_en =
Shaun Kelsey 0:da5f5b56060a 628 (bool)((rxbuf[1] & SS_MASK_OUTPUTMODE_SC_EN) >> SS_SHIFT_OUTPUTMODE_SC_EN);
Shaun Kelsey 0:da5f5b56060a 629 }
Shaun Kelsey 0:da5f5b56060a 630
Shaun Kelsey 0:da5f5b56060a 631 return status;
Shaun Kelsey 0:da5f5b56060a 632 }
Shaun Kelsey 0:da5f5b56060a 633
Shaun Kelsey 5:e458409e913f 634 SS_STATUS SSInterface::set_fifo_thresh(int thresh)
Shaun Kelsey 5:e458409e913f 635 {
Shaun Kelsey 5:e458409e913f 636 assert_msg((thresh > 0 && thresh <= 255), "Invalid value for fifo a full threshold");
Shaun Kelsey 5:e458409e913f 637 uint8_t cmd_bytes[] = { SS_FAM_W_COMMCHAN, SS_CMDIDX_FIFOAFULL };
Shaun Kelsey 5:e458409e913f 638 uint8_t data_bytes[] = { (uint8_t)thresh };
Shaun Kelsey 5:e458409e913f 639
Shaun Kelsey 5:e458409e913f 640 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 5:e458409e913f 641 &data_bytes[0], ARRAY_SIZE(data_bytes));
Shaun Kelsey 5:e458409e913f 642 return status;
Shaun Kelsey 5:e458409e913f 643 }
Shaun Kelsey 5:e458409e913f 644
Shaun Kelsey 5:e458409e913f 645 SS_STATUS SSInterface::get_fifo_thresh(int *thresh)
Shaun Kelsey 5:e458409e913f 646 {
Shaun Kelsey 5:e458409e913f 647 uint8_t cmd_bytes[] = { SS_FAM_R_COMMCHAN, SS_CMDIDX_FIFOAFULL };
Shaun Kelsey 5:e458409e913f 648 uint8_t rxbuf[2] = {0};
Shaun Kelsey 5:e458409e913f 649
Shaun Kelsey 5:e458409e913f 650 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 5:e458409e913f 651 0, 0,
Shaun Kelsey 5:e458409e913f 652 &rxbuf[0], ARRAY_SIZE(rxbuf));
Shaun Kelsey 5:e458409e913f 653
Shaun Kelsey 5:e458409e913f 654 if (status == SS_SUCCESS) {
Shaun Kelsey 5:e458409e913f 655 *thresh = rxbuf[1];
Shaun Kelsey 5:e458409e913f 656 }
Shaun Kelsey 5:e458409e913f 657
Shaun Kelsey 5:e458409e913f 658 return status;
Shaun Kelsey 5:e458409e913f 659 }
Shaun Kelsey 5:e458409e913f 660
Shaun Kelsey 5:e458409e913f 661 SS_STATUS SSInterface::ss_comm_check()
Shaun Kelsey 5:e458409e913f 662 {
Shaun Kelsey 5:e458409e913f 663 uint8_t cmd_bytes[] = { SS_FAM_R_IDENTITY, SS_CMDIDX_PLATTYPE };
Shaun Kelsey 5:e458409e913f 664 uint8_t rxbuf[2];
Shaun Kelsey 5:e458409e913f 665
Shaun Kelsey 5:e458409e913f 666 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 5:e458409e913f 667 0, 0,
Shaun Kelsey 5:e458409e913f 668 &rxbuf[0], ARRAY_SIZE(rxbuf));
Shaun Kelsey 5:e458409e913f 669
Shaun Kelsey 5:e458409e913f 670 int tries = 4;
Shaun Kelsey 5:e458409e913f 671 while (status == SS_ERR_TRY_AGAIN && tries--) {
Shaun Kelsey 5:e458409e913f 672 wait_ms(1000);
Shaun Kelsey 5:e458409e913f 673 status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 5:e458409e913f 674 0, 0,
Shaun Kelsey 5:e458409e913f 675 &rxbuf[0], ARRAY_SIZE(rxbuf));
Shaun Kelsey 5:e458409e913f 676 }
Shaun Kelsey 5:e458409e913f 677
Shaun Kelsey 5:e458409e913f 678 return status;
Shaun Kelsey 5:e458409e913f 679 }
Shaun Kelsey 5:e458409e913f 680
Shaun Kelsey 0:da5f5b56060a 681 void SSInterface::fifo_sample_size(int data_type, int *sample_size)
Shaun Kelsey 0:da5f5b56060a 682 {
Shaun Kelsey 0:da5f5b56060a 683 *sample_size = 0;
Shaun Kelsey 0:da5f5b56060a 684
Shaun Kelsey 0:da5f5b56060a 685 if (data_type == SS_DATATYPE_RAW || data_type == SS_DATATYPE_BOTH) {
Shaun Kelsey 0:da5f5b56060a 686 for (int i = 0; i < SS_MAX_SUPPORTED_SENSOR_NUM; i++) {
Shaun Kelsey 0:da5f5b56060a 687 if (sensor_enabled_mode[i]) {
Shaun Kelsey 0:da5f5b56060a 688 assert_msg(sensor_data_reqs[i], "no ss_data_req found for enabled sensor");
Shaun Kelsey 0:da5f5b56060a 689 *sample_size += sensor_data_reqs[i]->data_size;
Shaun Kelsey 0:da5f5b56060a 690 }
Shaun Kelsey 0:da5f5b56060a 691 }
Shaun Kelsey 0:da5f5b56060a 692 }
Shaun Kelsey 0:da5f5b56060a 693
Shaun Kelsey 0:da5f5b56060a 694 if (data_type == SS_DATATYPE_ALGO || data_type == SS_DATATYPE_BOTH) {
Shaun Kelsey 0:da5f5b56060a 695 for (int i = 0; i < SS_MAX_SUPPORTED_ALGO_NUM; i++) {
Shaun Kelsey 0:da5f5b56060a 696 if (algo_enabled_mode[i]) {
Shaun Kelsey 0:da5f5b56060a 697 assert_msg(algo_data_reqs[i], "no ss_data_req found for enabled algo");
Shaun Kelsey 0:da5f5b56060a 698 *sample_size += algo_data_reqs[i]->data_size;
Shaun Kelsey 0:da5f5b56060a 699 }
Shaun Kelsey 0:da5f5b56060a 700 }
Shaun Kelsey 0:da5f5b56060a 701 }
Shaun Kelsey 0:da5f5b56060a 702 }
Shaun Kelsey 0:da5f5b56060a 703
Shaun Kelsey 0:da5f5b56060a 704 SS_STATUS SSInterface::num_avail_samples(int *num_samples)
Shaun Kelsey 0:da5f5b56060a 705 {
Shaun Kelsey 0:da5f5b56060a 706 uint8_t cmd_bytes[] = { SS_FAM_R_OUTPUTFIFO, SS_CMDIDX_OUT_NUMSAMPLES };
Shaun Kelsey 0:da5f5b56060a 707 uint8_t rxbuf[2] = {0};
Shaun Kelsey 0:da5f5b56060a 708
Shaun Kelsey 0:da5f5b56060a 709 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 710 0, 0,
Shaun Kelsey 5:e458409e913f 711 &rxbuf[0], ARRAY_SIZE(rxbuf), 1);
Shaun Kelsey 0:da5f5b56060a 712
Shaun Kelsey 0:da5f5b56060a 713 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 714 *num_samples = rxbuf[1];
Shaun Kelsey 0:da5f5b56060a 715 }
Shaun Kelsey 0:da5f5b56060a 716
Shaun Kelsey 0:da5f5b56060a 717 return status;
Shaun Kelsey 0:da5f5b56060a 718 }
Shaun Kelsey 0:da5f5b56060a 719
Shaun Kelsey 0:da5f5b56060a 720 SS_STATUS SSInterface::read_fifo_data(
Shaun Kelsey 0:da5f5b56060a 721 int num_samples, int sample_size,
Shaun Kelsey 0:da5f5b56060a 722 uint8_t* databuf, int databuf_sz)
Shaun Kelsey 0:da5f5b56060a 723 {
Shaun Kelsey 0:da5f5b56060a 724 int bytes_to_read = num_samples * sample_size + 1; //+1 for status byte
Shaun Kelsey 0:da5f5b56060a 725 assert_msg((bytes_to_read <= databuf_sz), "databuf too small");
Shaun Kelsey 0:da5f5b56060a 726
Shaun Kelsey 0:da5f5b56060a 727 uint8_t cmd_bytes[] = { SS_FAM_R_OUTPUTFIFO, SS_CMDIDX_READFIFO };
Shaun Kelsey 0:da5f5b56060a 728
Shaun Kelsey 5:e458409e913f 729 pr_info("[reading %d bytes (%d samples)\r\n", bytes_to_read, num_samples);
Shaun Kelsey 0:da5f5b56060a 730
Shaun Kelsey 0:da5f5b56060a 731 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 732 0, 0,
Shaun Kelsey 5:e458409e913f 733 databuf, bytes_to_read, 5);
Shaun Kelsey 0:da5f5b56060a 734
Shaun Kelsey 0:da5f5b56060a 735 return status;
Shaun Kelsey 0:da5f5b56060a 736 }
Shaun Kelsey 0:da5f5b56060a 737
Shaun Kelsey 5:e458409e913f 738 static uint8_t databuf[512];
Shaun Kelsey 5:e458409e913f 739 void SSInterface::ss_execute_once(){
Shaun Kelsey 5:e458409e913f 740
Shaun Kelsey 5:e458409e913f 741 if(m_irq_received_ == false)
Shaun Kelsey 5:e458409e913f 742 return;
Shaun Kelsey 5:e458409e913f 743
Shaun Kelsey 0:da5f5b56060a 744 uint8_t sample_count;
Shaun Kelsey 5:e458409e913f 745 m_irq_received_ = false;
Shaun Kelsey 0:da5f5b56060a 746 uint8_t cmd_bytes[] = { SS_FAM_R_STATUS, SS_CMDIDX_STATUS };
Shaun Kelsey 0:da5f5b56060a 747 uint8_t rxbuf[2] = {0};
Shaun Kelsey 0:da5f5b56060a 748
Shaun Kelsey 5:e458409e913f 749 irq_evt.start();
Shaun Kelsey 5:e458409e913f 750
Shaun Kelsey 0:da5f5b56060a 751 irq_pin.disable_irq();
Shaun Kelsey 0:da5f5b56060a 752
Shaun Kelsey 0:da5f5b56060a 753 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 754 0, 0,
Shaun Kelsey 0:da5f5b56060a 755 &rxbuf[0], ARRAY_SIZE(rxbuf));
Shaun Kelsey 0:da5f5b56060a 756
Shaun Kelsey 0:da5f5b56060a 757 if (status != SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 758 pr_err("Couldn't read status byte of SmartSensor!");
Shaun Kelsey 0:da5f5b56060a 759 irq_pin.enable_irq();
Shaun Kelsey 5:e458409e913f 760 irq_evt.stop();
Shaun Kelsey 0:da5f5b56060a 761 return;
Shaun Kelsey 0:da5f5b56060a 762 }
Shaun Kelsey 0:da5f5b56060a 763
Shaun Kelsey 0:da5f5b56060a 764 if (rxbuf[1] & SS_MASK_STATUS_ERR) {
Shaun Kelsey 0:da5f5b56060a 765 pr_err("SmartSensor status error: %d", rxbuf[1] & SS_MASK_STATUS_ERR);
Shaun Kelsey 0:da5f5b56060a 766 }
Shaun Kelsey 0:da5f5b56060a 767 if (rxbuf[1] & SS_MASK_STATUS_FIFO_OUT_OVR) {
Shaun Kelsey 0:da5f5b56060a 768 pr_err("SmartSensor Output FIFO overflow!");
Shaun Kelsey 0:da5f5b56060a 769 }
Shaun Kelsey 0:da5f5b56060a 770 if (rxbuf[1] & SS_MASK_STATUS_FIFO_IN_OVR) {
Shaun Kelsey 0:da5f5b56060a 771 pr_err("SmartSensor Input FIFO overflow!");
Shaun Kelsey 0:da5f5b56060a 772 }
Shaun Kelsey 0:da5f5b56060a 773
Shaun Kelsey 0:da5f5b56060a 774 if (rxbuf[1] & SS_MASK_STATUS_DATA_RDY) {
Shaun Kelsey 5:e458409e913f 775 int num_samples = 1;
Shaun Kelsey 0:da5f5b56060a 776 status = num_avail_samples(&num_samples);
Shaun Kelsey 0:da5f5b56060a 777 if (status != SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 778 {
Shaun Kelsey 0:da5f5b56060a 779 pr_err("Couldn't read number of available samples in SmartSensor Output FIFO");
Shaun Kelsey 0:da5f5b56060a 780 irq_pin.enable_irq();
Shaun Kelsey 5:e458409e913f 781 irq_evt.stop();
Shaun Kelsey 0:da5f5b56060a 782 return;
Shaun Kelsey 0:da5f5b56060a 783 }
Shaun Kelsey 0:da5f5b56060a 784
Shaun Kelsey 0:da5f5b56060a 785 int sample_size;
Shaun Kelsey 0:da5f5b56060a 786 fifo_sample_size(data_type, &sample_size);
Shaun Kelsey 0:da5f5b56060a 787
Shaun Kelsey 5:e458409e913f 788 int bytes_to_read = num_samples * sample_size + 1; //+1 for status byte
Shaun Kelsey 5:e458409e913f 789 if ((uint32_t)bytes_to_read > sizeof(databuf)) {
Shaun Kelsey 0:da5f5b56060a 790 //Reduce number of samples to read to fit in buffer
Shaun Kelsey 0:da5f5b56060a 791 num_samples = (sizeof(databuf) - 1) / sample_size;
Shaun Kelsey 0:da5f5b56060a 792 }
Shaun Kelsey 0:da5f5b56060a 793
Shaun Kelsey 5:e458409e913f 794 wait_ms(5);
Shaun Kelsey 0:da5f5b56060a 795 status = read_fifo_data(num_samples, sample_size, &databuf[0], sizeof(databuf));
Shaun Kelsey 0:da5f5b56060a 796 if (status != SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 797 {
Shaun Kelsey 0:da5f5b56060a 798 pr_err("Couldn't read from SmartSensor Output FIFO");
Shaun Kelsey 0:da5f5b56060a 799 irq_pin.enable_irq();
Shaun Kelsey 5:e458409e913f 800 irq_evt.stop();
Shaun Kelsey 0:da5f5b56060a 801 return;
Shaun Kelsey 0:da5f5b56060a 802 }
Shaun Kelsey 0:da5f5b56060a 803
Shaun Kelsey 5:e458409e913f 804 pr_info("read %d samples\r\n", num_samples);
Shaun Kelsey 5:e458409e913f 805
Shaun Kelsey 0:da5f5b56060a 806 //Skip status byte
Shaun Kelsey 0:da5f5b56060a 807 uint8_t *data_ptr = &databuf[1];
Shaun Kelsey 0:da5f5b56060a 808
Shaun Kelsey 0:da5f5b56060a 809 int i = 0;
Shaun Kelsey 0:da5f5b56060a 810 for (i = 0; i < num_samples; i++) {
Shaun Kelsey 0:da5f5b56060a 811 if (sc_en) {
Shaun Kelsey 0:da5f5b56060a 812 sample_count = *data_ptr++;
Shaun Kelsey 0:da5f5b56060a 813 pr_info("Received sample #%d", sample_count);
Shaun Kelsey 0:da5f5b56060a 814 }
Shaun Kelsey 0:da5f5b56060a 815
Shaun Kelsey 0:da5f5b56060a 816 //Chop up data and send to modules with enabled sensors
Shaun Kelsey 0:da5f5b56060a 817 if (data_type == SS_DATATYPE_RAW || data_type == SS_DATATYPE_BOTH) {
Shaun Kelsey 0:da5f5b56060a 818 for (int i = 0; i < SS_MAX_SUPPORTED_SENSOR_NUM; i++) {
Shaun Kelsey 0:da5f5b56060a 819 if (sensor_enabled_mode[i]) {
Shaun Kelsey 0:da5f5b56060a 820 assert_msg(sensor_data_reqs[i],
Shaun Kelsey 0:da5f5b56060a 821 "no ss_data_req found for enabled sensor");
Shaun Kelsey 0:da5f5b56060a 822 sensor_data_reqs[i]->callback(data_ptr);
Shaun Kelsey 0:da5f5b56060a 823 data_ptr += sensor_data_reqs[i]->data_size;
Shaun Kelsey 0:da5f5b56060a 824 }
Shaun Kelsey 0:da5f5b56060a 825 }
Shaun Kelsey 0:da5f5b56060a 826 }
Shaun Kelsey 0:da5f5b56060a 827 if (data_type == SS_DATATYPE_ALGO || data_type == SS_DATATYPE_BOTH) {
Shaun Kelsey 0:da5f5b56060a 828 for (int i = 0; i < SS_MAX_SUPPORTED_ALGO_NUM; i++) {
Shaun Kelsey 0:da5f5b56060a 829 if (algo_enabled_mode[i]) {
Shaun Kelsey 0:da5f5b56060a 830 assert_msg(algo_data_reqs[i],
Shaun Kelsey 0:da5f5b56060a 831 "no ss_data_req found for enabled algo");
Shaun Kelsey 0:da5f5b56060a 832 algo_data_reqs[i]->callback(data_ptr);
Shaun Kelsey 0:da5f5b56060a 833 data_ptr += algo_data_reqs[i]->data_size;
Shaun Kelsey 0:da5f5b56060a 834 }
Shaun Kelsey 0:da5f5b56060a 835 }
Shaun Kelsey 0:da5f5b56060a 836 }
Shaun Kelsey 0:da5f5b56060a 837 }
Shaun Kelsey 0:da5f5b56060a 838 }
Shaun Kelsey 0:da5f5b56060a 839 irq_pin.enable_irq();
Shaun Kelsey 5:e458409e913f 840 irq_evt.stop();
Shaun Kelsey 5:e458409e913f 841 }
Shaun Kelsey 5:e458409e913f 842
Shaun Kelsey 5:e458409e913f 843 void SSInterface::ss_clear_interrupt_flag(){
Shaun Kelsey 5:e458409e913f 844 m_irq_received_ = false;
Shaun Kelsey 5:e458409e913f 845 }
Shaun Kelsey 5:e458409e913f 846
Shaun Kelsey 5:e458409e913f 847 void SSInterface::irq_handler()
Shaun Kelsey 5:e458409e913f 848 {
Shaun Kelsey 5:e458409e913f 849 m_irq_received_ = true;
Shaun Kelsey 0:da5f5b56060a 850 }
Shaun Kelsey 0:da5f5b56060a 851
Shaun Kelsey 0:da5f5b56060a 852 void SSInterface::irq_handler_selftest(){
Shaun Kelsey 0:da5f5b56060a 853 mfio_int_happened = true;
Shaun Kelsey 0:da5f5b56060a 854 }
Shaun Kelsey 0:da5f5b56060a 855
Shaun Kelsey 0:da5f5b56060a 856 bool SSInterface::reset_mfio_irq(){
Shaun Kelsey 0:da5f5b56060a 857 bool ret = mfio_int_happened;
Shaun Kelsey 0:da5f5b56060a 858 mfio_int_happened = false;
Shaun Kelsey 0:da5f5b56060a 859 irq_pin.disable_irq();
Shaun Kelsey 0:da5f5b56060a 860 irq_pin.fall(callback(this, &SSInterface::irq_handler));
Shaun Kelsey 0:da5f5b56060a 861 irq_pin.enable_irq();
Shaun Kelsey 0:da5f5b56060a 862 return ret;
Shaun Kelsey 0:da5f5b56060a 863 }