Host software for the MAXREFDES220 Heart Rate Monitor Smart Sensor. Hosted on the MAX32630FTHR.

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:
Wed Apr 11 16:42:37 2018 -0700
Revision:
1:7a55c0c7d6d9
Parent:
0:da5f5b56060a
Child:
5:e458409e913f
Fix compiler warnings

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 0:da5f5b56060a 38
Shaun Kelsey 0:da5f5b56060a 39 SSInterface::SSInterface(I2C &i2cBus, PinName ss_mfio, PinName ss_reset)
Shaun Kelsey 0:da5f5b56060a 40 :m_i2cBus(&i2cBus), m_spiBus(NULL), mfio_pin(ss_mfio), reset_pin(ss_reset), irq_pin(ss_mfio)
Shaun Kelsey 0:da5f5b56060a 41 {
Shaun Kelsey 0:da5f5b56060a 42 reset_pin.input();
Shaun Kelsey 0:da5f5b56060a 43 irq_pin.fall(callback(this, &SSInterface::irq_handler));
Shaun Kelsey 0:da5f5b56060a 44
Shaun Kelsey 0:da5f5b56060a 45 reset_to_main_app();
Shaun Kelsey 0:da5f5b56060a 46 get_data_type(&data_type, &sc_en);
Shaun Kelsey 0:da5f5b56060a 47 }
Shaun Kelsey 0:da5f5b56060a 48
Shaun Kelsey 0:da5f5b56060a 49 SSInterface::SSInterface(SPI &spiBus, PinName ss_mfio, PinName ss_reset)
Shaun Kelsey 0:da5f5b56060a 50 :m_i2cBus(NULL), m_spiBus(&spiBus), mfio_pin(ss_mfio), reset_pin(ss_reset), irq_pin(ss_mfio)
Shaun Kelsey 0:da5f5b56060a 51 {
Shaun Kelsey 0:da5f5b56060a 52 reset_pin.input();
Shaun Kelsey 0:da5f5b56060a 53 irq_pin.fall(callback(this, &SSInterface::irq_handler));
Shaun Kelsey 0:da5f5b56060a 54
Shaun Kelsey 0:da5f5b56060a 55 reset_to_main_app();
Shaun Kelsey 0:da5f5b56060a 56 get_data_type(&data_type, &sc_en);
Shaun Kelsey 0:da5f5b56060a 57 }
Shaun Kelsey 0:da5f5b56060a 58
Shaun Kelsey 0:da5f5b56060a 59 SSInterface::~SSInterface()
Shaun Kelsey 0:da5f5b56060a 60 {
Shaun Kelsey 0:da5f5b56060a 61 }
Shaun Kelsey 0:da5f5b56060a 62
Shaun Kelsey 0:da5f5b56060a 63 SS_STATUS SSInterface::reset_to_main_app()
Shaun Kelsey 0:da5f5b56060a 64 {
Shaun Kelsey 0:da5f5b56060a 65 irq_pin.disable_irq();
Shaun Kelsey 0:da5f5b56060a 66 #if 0
Shaun Kelsey 0:da5f5b56060a 67 uint8_t cmd_bytes[] = { SS_FAM_W_MODE, SS_CMDIDX_MODE };
Shaun Kelsey 0:da5f5b56060a 68 uint8_t data[] = { 0x00 };
Shaun Kelsey 0:da5f5b56060a 69
Shaun Kelsey 0:da5f5b56060a 70 SS_STATUS status = ss_int->write_cmd(
Shaun Kelsey 0:da5f5b56060a 71 &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 72 &data[0], ARRAY_SIZE(data),
Shaun Kelsey 0:da5f5b56060a 73 SS_STARTUP_TIME);
Shaun Kelsey 0:da5f5b56060a 74 if (status == SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 75 in_bootldr = false;
Shaun Kelsey 0:da5f5b56060a 76 return status;
Shaun Kelsey 0:da5f5b56060a 77 #else
Shaun Kelsey 0:da5f5b56060a 78 reset_pin.output();
Shaun Kelsey 0:da5f5b56060a 79 cfg_mfio(PIN_OUTPUT);
Shaun Kelsey 0:da5f5b56060a 80 reset_pin.write(0);
Shaun Kelsey 0:da5f5b56060a 81 wait_ms(SS_RESET_TIME);
Shaun Kelsey 0:da5f5b56060a 82 mfio_pin.write(1);
Shaun Kelsey 0:da5f5b56060a 83 reset_pin.write(1);
Shaun Kelsey 0:da5f5b56060a 84 wait_ms(SS_STARTUP_TIME);
Shaun Kelsey 0:da5f5b56060a 85 cfg_mfio(PIN_INPUT);
Shaun Kelsey 0:da5f5b56060a 86 reset_pin.input();
Shaun Kelsey 0:da5f5b56060a 87 // Verify we exited bootloader mode
Shaun Kelsey 0:da5f5b56060a 88 if (in_bootldr_mode() == 0)
Shaun Kelsey 0:da5f5b56060a 89 return SS_SUCCESS;
Shaun Kelsey 0:da5f5b56060a 90 else
Shaun Kelsey 0:da5f5b56060a 91 return SS_ERR_UNKNOWN;
Shaun Kelsey 0:da5f5b56060a 92 #endif
Shaun Kelsey 0:da5f5b56060a 93
Shaun Kelsey 0:da5f5b56060a 94 irq_pin.enable_irq();
Shaun Kelsey 0:da5f5b56060a 95 }
Shaun Kelsey 0:da5f5b56060a 96
Shaun Kelsey 0:da5f5b56060a 97 SS_STATUS SSInterface::reset_to_bootloader()
Shaun Kelsey 0:da5f5b56060a 98 {
Shaun Kelsey 0:da5f5b56060a 99 irq_pin.disable_irq();
Shaun Kelsey 0:da5f5b56060a 100 #if 0
Shaun Kelsey 0:da5f5b56060a 101 uint8_t cmd_bytes[] = { SS_FAM_W_MODE, SS_CMDIDX_MODE };
Shaun Kelsey 0:da5f5b56060a 102 uint8_t data[] = { SS_MASK_MODE_BOOTLDR };
Shaun Kelsey 0:da5f5b56060a 103
Shaun Kelsey 0:da5f5b56060a 104 SS_STATUS status = ss_int->write_cmd(
Shaun Kelsey 0:da5f5b56060a 105 &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 106 &data[0], ARRAY_SIZE(data),
Shaun Kelsey 0:da5f5b56060a 107 SS_STARTUP_TIME);
Shaun Kelsey 0:da5f5b56060a 108 if (status == SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 109 in_bootldr = true;
Shaun Kelsey 0:da5f5b56060a 110 return status;
Shaun Kelsey 0:da5f5b56060a 111 #else
Shaun Kelsey 0:da5f5b56060a 112 reset_pin.output();
Shaun Kelsey 0:da5f5b56060a 113 cfg_mfio(PIN_OUTPUT);
Shaun Kelsey 0:da5f5b56060a 114 reset_pin.write(0);
Shaun Kelsey 0:da5f5b56060a 115 wait_ms(SS_RESET_TIME);
Shaun Kelsey 0:da5f5b56060a 116 mfio_pin.write(0);
Shaun Kelsey 0:da5f5b56060a 117 reset_pin.write(1);
Shaun Kelsey 0:da5f5b56060a 118 wait_ms(SS_STARTUP_TIME);
Shaun Kelsey 0:da5f5b56060a 119 cfg_mfio(PIN_INPUT);
Shaun Kelsey 0:da5f5b56060a 120 reset_pin.input();
Shaun Kelsey 0:da5f5b56060a 121 // Verify we entered bootloader mode
Shaun Kelsey 0:da5f5b56060a 122 if (in_bootldr_mode() < 0)
Shaun Kelsey 0:da5f5b56060a 123 return SS_ERR_UNKNOWN;
Shaun Kelsey 0:da5f5b56060a 124 return SS_SUCCESS;
Shaun Kelsey 0:da5f5b56060a 125 #endif
Shaun Kelsey 0:da5f5b56060a 126
Shaun Kelsey 0:da5f5b56060a 127 irq_pin.disable_irq();
Shaun Kelsey 0:da5f5b56060a 128 }
Shaun Kelsey 0:da5f5b56060a 129
Shaun Kelsey 0:da5f5b56060a 130 SS_STATUS SSInterface::reset()
Shaun Kelsey 0:da5f5b56060a 131 {
Shaun Kelsey 0:da5f5b56060a 132 int bootldr = in_bootldr_mode();
Shaun Kelsey 0:da5f5b56060a 133 if (bootldr > 0)
Shaun Kelsey 0:da5f5b56060a 134 return reset_to_bootloader();
Shaun Kelsey 0:da5f5b56060a 135 else if (bootldr == 0)
Shaun Kelsey 0:da5f5b56060a 136 return reset_to_main_app();
Shaun Kelsey 0:da5f5b56060a 137 else
Shaun Kelsey 0:da5f5b56060a 138 return SS_ERR_UNKNOWN;
Shaun Kelsey 0:da5f5b56060a 139 }
Shaun Kelsey 0:da5f5b56060a 140
Shaun Kelsey 0:da5f5b56060a 141 SS_STATUS SSInterface::self_test(int idx, uint8_t *result, int sleep_ms){
Shaun Kelsey 0:da5f5b56060a 142 uint8_t cmd_bytes[] = {SS_FAM_R_SELFTEST, idx};
Shaun Kelsey 0:da5f5b56060a 143 uint8_t rxbuf[2];
Shaun Kelsey 0:da5f5b56060a 144 SS_STATUS ret;
Shaun Kelsey 0:da5f5b56060a 145
Shaun Kelsey 0:da5f5b56060a 146 result[0] = 0xFF;
Shaun Kelsey 0:da5f5b56060a 147 ret = read_cmd(cmd_bytes, 2, (uint8_t *)0, 0, rxbuf, ARRAY_SIZE(rxbuf), sleep_ms);
Shaun Kelsey 0:da5f5b56060a 148 result[0] = rxbuf[1];
Shaun Kelsey 0:da5f5b56060a 149 return ret;
Shaun Kelsey 0:da5f5b56060a 150 }
Shaun Kelsey 0:da5f5b56060a 151
Shaun Kelsey 0:da5f5b56060a 152 void SSInterface::cfg_mfio(PinDirection dir)
Shaun Kelsey 0:da5f5b56060a 153 {
Shaun Kelsey 0:da5f5b56060a 154 if (dir == PIN_INPUT) {
Shaun Kelsey 0:da5f5b56060a 155 mfio_pin.input();
Shaun Kelsey 0:da5f5b56060a 156 mfio_pin.mode(PullUp);
Shaun Kelsey 0:da5f5b56060a 157 } else {
Shaun Kelsey 0:da5f5b56060a 158 mfio_pin.output();
Shaun Kelsey 0:da5f5b56060a 159 }
Shaun Kelsey 0:da5f5b56060a 160 }
Shaun Kelsey 0:da5f5b56060a 161
Shaun Kelsey 0:da5f5b56060a 162 void SSInterface::enable_irq()
Shaun Kelsey 0:da5f5b56060a 163 {
Shaun Kelsey 0:da5f5b56060a 164 irq_pin.enable_irq();
Shaun Kelsey 0:da5f5b56060a 165 }
Shaun Kelsey 0:da5f5b56060a 166 void SSInterface::disable_irq()
Shaun Kelsey 0:da5f5b56060a 167 {
Shaun Kelsey 0:da5f5b56060a 168 irq_pin.disable_irq();
Shaun Kelsey 0:da5f5b56060a 169 }
Shaun Kelsey 0:da5f5b56060a 170
Shaun Kelsey 0:da5f5b56060a 171 void SSInterface::mfio_selftest(){
Shaun Kelsey 0:da5f5b56060a 172 disable_irq();
Shaun Kelsey 0:da5f5b56060a 173 irq_pin.fall(callback(this, &SSInterface::irq_handler_selftest));
Shaun Kelsey 0:da5f5b56060a 174 enable_irq();
Shaun Kelsey 0:da5f5b56060a 175 }
Shaun Kelsey 0:da5f5b56060a 176
Shaun Kelsey 0:da5f5b56060a 177 int SSInterface::in_bootldr_mode()
Shaun Kelsey 0:da5f5b56060a 178 {
Shaun Kelsey 0:da5f5b56060a 179 uint8_t cmd_bytes[] = { SS_FAM_R_MODE, SS_CMDIDX_MODE };
Shaun Kelsey 0:da5f5b56060a 180 uint8_t rxbuf[2] = { 0 };
Shaun Kelsey 0:da5f5b56060a 181
Shaun Kelsey 0:da5f5b56060a 182 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 183 0, 0,
Shaun Kelsey 0:da5f5b56060a 184 &rxbuf[0], ARRAY_SIZE(rxbuf));
Shaun Kelsey 0:da5f5b56060a 185 if (status != SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 186 return -1;
Shaun Kelsey 0:da5f5b56060a 187
Shaun Kelsey 0:da5f5b56060a 188 return (rxbuf[1] & SS_MASK_MODE_BOOTLDR);
Shaun Kelsey 0:da5f5b56060a 189 }
Shaun Kelsey 0:da5f5b56060a 190
Shaun Kelsey 0:da5f5b56060a 191 const char* SSInterface::get_ss_fw_version()
Shaun Kelsey 0:da5f5b56060a 192 {
Shaun Kelsey 0:da5f5b56060a 193 uint8_t cmd_bytes[2];
Shaun Kelsey 0:da5f5b56060a 194 uint8_t rxbuf[4];
Shaun Kelsey 0:da5f5b56060a 195
Shaun Kelsey 0:da5f5b56060a 196 int bootldr = in_bootldr_mode();
Shaun Kelsey 0:da5f5b56060a 197
Shaun Kelsey 0:da5f5b56060a 198 if (bootldr > 0) {
Shaun Kelsey 0:da5f5b56060a 199 cmd_bytes[0] = SS_FAM_R_BOOTLOADER;
Shaun Kelsey 0:da5f5b56060a 200 cmd_bytes[1] = SS_CMDIDX_BOOTFWVERSION;
Shaun Kelsey 0:da5f5b56060a 201 } else if (bootldr == 0) {
Shaun Kelsey 0:da5f5b56060a 202 cmd_bytes[0] = SS_FAM_R_IDENTITY;
Shaun Kelsey 0:da5f5b56060a 203 cmd_bytes[1] = SS_CMDIDX_FWVERSION;
Shaun Kelsey 0:da5f5b56060a 204 } else {
Shaun Kelsey 0:da5f5b56060a 205 return plat_name;
Shaun Kelsey 0:da5f5b56060a 206 }
Shaun Kelsey 0:da5f5b56060a 207
Shaun Kelsey 0:da5f5b56060a 208 SS_STATUS status = read_cmd(
Shaun Kelsey 0:da5f5b56060a 209 &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 210 0, 0,
Shaun Kelsey 0:da5f5b56060a 211 &rxbuf[0], ARRAY_SIZE(rxbuf));
Shaun Kelsey 0:da5f5b56060a 212
Shaun Kelsey 0:da5f5b56060a 213 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 214 snprintf(fw_version, sizeof(fw_version),
Shaun Kelsey 0:da5f5b56060a 215 "%d.%d.%d", rxbuf[1], rxbuf[2], rxbuf[3]);
Shaun Kelsey 0:da5f5b56060a 216 pr_info("fw_version:%s\r\n", fw_version);
Shaun Kelsey 0:da5f5b56060a 217 }
Shaun Kelsey 0:da5f5b56060a 218
Shaun Kelsey 0:da5f5b56060a 219 return &fw_version[0];
Shaun Kelsey 0:da5f5b56060a 220 }
Shaun Kelsey 0:da5f5b56060a 221
Shaun Kelsey 0:da5f5b56060a 222 const char* SSInterface::get_ss_platform_name()
Shaun Kelsey 0:da5f5b56060a 223 {
Shaun Kelsey 0:da5f5b56060a 224 uint8_t cmd_bytes[] = { SS_FAM_R_IDENTITY, SS_CMDIDX_PLATTYPE };
Shaun Kelsey 0:da5f5b56060a 225 uint8_t rxbuf[2];
Shaun Kelsey 0:da5f5b56060a 226
Shaun Kelsey 0:da5f5b56060a 227 SS_STATUS status = read_cmd(
Shaun Kelsey 0:da5f5b56060a 228 &cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 229 0, 0,
Shaun Kelsey 0:da5f5b56060a 230 &rxbuf[0], ARRAY_SIZE(rxbuf));
Shaun Kelsey 0:da5f5b56060a 231
Shaun Kelsey 0:da5f5b56060a 232 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 233 if (rxbuf[1] == SS_PLAT_MAX3263X) {
Shaun Kelsey 0:da5f5b56060a 234 if (in_bootldr_mode() > 0) {
Shaun Kelsey 0:da5f5b56060a 235 plat_name = SS_BOOTLOADER_PLATFORM_MAX3263X;
Shaun Kelsey 0:da5f5b56060a 236 } else {
Shaun Kelsey 0:da5f5b56060a 237 plat_name = SS_PLATFORM_MAX3263X;
Shaun Kelsey 0:da5f5b56060a 238 }
Shaun Kelsey 0:da5f5b56060a 239 } else if (rxbuf[1] == SS_PLAT_MAX32660) {
Shaun Kelsey 0:da5f5b56060a 240 if (in_bootldr_mode() > 0) {
Shaun Kelsey 0:da5f5b56060a 241 plat_name = SS_BOOTLOADER_PLATFORM_MAX32660;
Shaun Kelsey 0:da5f5b56060a 242 } else {
Shaun Kelsey 0:da5f5b56060a 243 plat_name = SS_PLATFORM_MAX32660;
Shaun Kelsey 0:da5f5b56060a 244 }
Shaun Kelsey 0:da5f5b56060a 245 }
Shaun Kelsey 0:da5f5b56060a 246 }
Shaun Kelsey 0:da5f5b56060a 247
Shaun Kelsey 0:da5f5b56060a 248 return plat_name;
Shaun Kelsey 0:da5f5b56060a 249 }
Shaun Kelsey 0:da5f5b56060a 250
Shaun Kelsey 0:da5f5b56060a 251 SS_STATUS SSInterface::write_cmd(uint8_t *cmd_bytes, int cmd_bytes_len,
Shaun Kelsey 0:da5f5b56060a 252 uint8_t *data, int data_len,
Shaun Kelsey 0:da5f5b56060a 253 int sleep_ms)
Shaun Kelsey 0:da5f5b56060a 254 {
Shaun Kelsey 0:da5f5b56060a 255 int total_len = data_len + cmd_bytes_len;
Shaun Kelsey 0:da5f5b56060a 256
Shaun Kelsey 0:da5f5b56060a 257 if (total_len <= SS_SMALL_BUF_SIZE) {
Shaun Kelsey 0:da5f5b56060a 258 return write_cmd_small(cmd_bytes, cmd_bytes_len, data, data_len, sleep_ms);
Shaun Kelsey 0:da5f5b56060a 259 } else if (total_len <= SS_LARGE_BUF_SIZE) {
Shaun Kelsey 0:da5f5b56060a 260 return write_cmd_large(cmd_bytes, cmd_bytes_len, data, data_len, sleep_ms);
Shaun Kelsey 0:da5f5b56060a 261 } else {
Shaun Kelsey 0:da5f5b56060a 262 assert_msg(true, "Tried to send I2C tx larger than maximum allowed size\n");
Shaun Kelsey 0:da5f5b56060a 263 return SS_ERR_DATA_FORMAT;
Shaun Kelsey 0:da5f5b56060a 264 }
Shaun Kelsey 0:da5f5b56060a 265 }
Shaun Kelsey 0:da5f5b56060a 266
Shaun Kelsey 0:da5f5b56060a 267 SS_STATUS SSInterface::write_cmd(uint8_t *tx_buf, int tx_len, int sleep_ms)
Shaun Kelsey 0:da5f5b56060a 268 {
Shaun Kelsey 0:da5f5b56060a 269 pr_info("write_cmd: ");
Shaun Kelsey 0:da5f5b56060a 270 for (int i = 0; i < tx_len; i++) {
Shaun Kelsey 0:da5f5b56060a 271 pr_info("0x%02X ", tx_buf[i]);
Shaun Kelsey 0:da5f5b56060a 272 }
Shaun Kelsey 0:da5f5b56060a 273 pr_info("\r\n");
Shaun Kelsey 0:da5f5b56060a 274
Shaun Kelsey 0:da5f5b56060a 275 int ret = 0;
Shaun Kelsey 0:da5f5b56060a 276 ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)tx_buf, tx_len);
Shaun Kelsey 0:da5f5b56060a 277
Shaun Kelsey 0:da5f5b56060a 278 if (ret != 0) {
Shaun Kelsey 0:da5f5b56060a 279 pr_err("m_i2cBus->write returned %d\r\n", ret);
Shaun Kelsey 0:da5f5b56060a 280 return SS_ERR_UNAVAILABLE;
Shaun Kelsey 0:da5f5b56060a 281 }
Shaun Kelsey 0:da5f5b56060a 282
Shaun Kelsey 0:da5f5b56060a 283 wait_ms(sleep_ms);
Shaun Kelsey 0:da5f5b56060a 284
Shaun Kelsey 0:da5f5b56060a 285 char status_byte;
Shaun Kelsey 0:da5f5b56060a 286 ret |= m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, &status_byte, 1);
Shaun Kelsey 0:da5f5b56060a 287
Shaun Kelsey 0:da5f5b56060a 288 if (ret != 0) {
Shaun Kelsey 0:da5f5b56060a 289 pr_err("m_i2cBus->read returned %d\r\n", ret);
Shaun Kelsey 0:da5f5b56060a 290 return SS_ERR_UNAVAILABLE;
Shaun Kelsey 0:da5f5b56060a 291 }
Shaun Kelsey 0:da5f5b56060a 292
Shaun Kelsey 0:da5f5b56060a 293 pr_info("status_byte: %d\r\n", status_byte);
Shaun Kelsey 0:da5f5b56060a 294
Shaun Kelsey 0:da5f5b56060a 295 return (SS_STATUS)status_byte;
Shaun Kelsey 0:da5f5b56060a 296 }
Shaun Kelsey 0:da5f5b56060a 297
Shaun Kelsey 0:da5f5b56060a 298 SS_STATUS SSInterface::write_cmd_small(uint8_t *cmd_bytes, int cmd_bytes_len,
Shaun Kelsey 0:da5f5b56060a 299 uint8_t *data, int data_len,
Shaun Kelsey 0:da5f5b56060a 300 int sleep_ms)
Shaun Kelsey 0:da5f5b56060a 301 {
Shaun Kelsey 0:da5f5b56060a 302 uint8_t write_buf[SS_SMALL_BUF_SIZE];
Shaun Kelsey 0:da5f5b56060a 303 memcpy(write_buf, cmd_bytes, cmd_bytes_len);
Shaun Kelsey 0:da5f5b56060a 304 memcpy(write_buf + cmd_bytes_len, data, data_len);
Shaun Kelsey 0:da5f5b56060a 305
Shaun Kelsey 0:da5f5b56060a 306 SS_STATUS status = write_cmd(write_buf, cmd_bytes_len + data_len, sleep_ms);
Shaun Kelsey 0:da5f5b56060a 307 return status;
Shaun Kelsey 0:da5f5b56060a 308 }
Shaun Kelsey 0:da5f5b56060a 309
Shaun Kelsey 0:da5f5b56060a 310 SS_STATUS SSInterface::write_cmd_large(uint8_t *cmd_bytes, int cmd_bytes_len,
Shaun Kelsey 0:da5f5b56060a 311 uint8_t *data, int data_len,
Shaun Kelsey 0:da5f5b56060a 312 int sleep_ms)
Shaun Kelsey 0:da5f5b56060a 313 {
Shaun Kelsey 0:da5f5b56060a 314 uint8_t write_buf[SS_LARGE_BUF_SIZE];
Shaun Kelsey 0:da5f5b56060a 315 memcpy(write_buf, cmd_bytes, cmd_bytes_len);
Shaun Kelsey 0:da5f5b56060a 316 memcpy(write_buf + cmd_bytes_len, data, data_len);
Shaun Kelsey 0:da5f5b56060a 317
Shaun Kelsey 0:da5f5b56060a 318 SS_STATUS status = write_cmd(write_buf, cmd_bytes_len + data_len, sleep_ms);
Shaun Kelsey 0:da5f5b56060a 319 return status;
Shaun Kelsey 0:da5f5b56060a 320 }
Shaun Kelsey 0:da5f5b56060a 321
Shaun Kelsey 0:da5f5b56060a 322 SS_STATUS SSInterface::read_cmd(uint8_t *cmd_bytes, int cmd_bytes_len,
Shaun Kelsey 0:da5f5b56060a 323 uint8_t *data, int data_len,
Shaun Kelsey 0:da5f5b56060a 324 uint8_t *rxbuf, int rxbuf_sz,
Shaun Kelsey 0:da5f5b56060a 325 int sleep_ms)
Shaun Kelsey 0:da5f5b56060a 326 {
Shaun Kelsey 0:da5f5b56060a 327 int ret = 0;
Shaun Kelsey 0:da5f5b56060a 328
Shaun Kelsey 0:da5f5b56060a 329 pr_info("read_cmd: ");
Shaun Kelsey 0:da5f5b56060a 330 for (int i = 0; i < cmd_bytes_len; i++) {
Shaun Kelsey 0:da5f5b56060a 331 pr_info("0x%02X ", cmd_bytes[i]);
Shaun Kelsey 0:da5f5b56060a 332 }
Shaun Kelsey 0:da5f5b56060a 333 pr_info("\r\n");
Shaun Kelsey 0:da5f5b56060a 334
Shaun Kelsey 0:da5f5b56060a 335 ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)cmd_bytes, cmd_bytes_len, (data_len != 0));
Shaun Kelsey 0:da5f5b56060a 336
Shaun Kelsey 0:da5f5b56060a 337 if (data_len != 0) {
Shaun Kelsey 0:da5f5b56060a 338 ret |= m_i2cBus->write(SS_I2C_8BIT_SLAVE_ADDR, (char*)data, data_len, false);
Shaun Kelsey 0:da5f5b56060a 339 }
Shaun Kelsey 0:da5f5b56060a 340
Shaun Kelsey 0:da5f5b56060a 341 if (ret != 0) {
Shaun Kelsey 0:da5f5b56060a 342 pr_err("m_i2cBus->write returned %d\r\n", ret);
Shaun Kelsey 0:da5f5b56060a 343 return SS_ERR_UNAVAILABLE;
Shaun Kelsey 0:da5f5b56060a 344 }
Shaun Kelsey 0:da5f5b56060a 345
Shaun Kelsey 0:da5f5b56060a 346 wait_ms(sleep_ms);
Shaun Kelsey 0:da5f5b56060a 347
Shaun Kelsey 0:da5f5b56060a 348 ret |= m_i2cBus->read(SS_I2C_8BIT_SLAVE_ADDR, (char*)rxbuf, rxbuf_sz);
Shaun Kelsey 0:da5f5b56060a 349
Shaun Kelsey 0:da5f5b56060a 350 if (ret != 0) {
Shaun Kelsey 0:da5f5b56060a 351 pr_err("m_i2cBus->read returned %d\r\n", ret);
Shaun Kelsey 0:da5f5b56060a 352 return SS_ERR_UNAVAILABLE;
Shaun Kelsey 0:da5f5b56060a 353 }
Shaun Kelsey 0:da5f5b56060a 354
Shaun Kelsey 0:da5f5b56060a 355 wait_ms(sleep_ms);
Shaun Kelsey 0:da5f5b56060a 356 pr_info("status_byte: %d\r\n", rxbuf[0]);
Shaun Kelsey 0:da5f5b56060a 357 pr_info("data: ");
Shaun Kelsey 0:da5f5b56060a 358 for (int i = 1; i < rxbuf_sz; i++) {
Shaun Kelsey 0:da5f5b56060a 359 pr_info("0x%02X ", rxbuf[i]);
Shaun Kelsey 0:da5f5b56060a 360 }
Shaun Kelsey 0:da5f5b56060a 361 pr_info("\r\n");
Shaun Kelsey 0:da5f5b56060a 362
Shaun Kelsey 0:da5f5b56060a 363 return (SS_STATUS)rxbuf[0];
Shaun Kelsey 0:da5f5b56060a 364 }
Shaun Kelsey 0:da5f5b56060a 365
Shaun Kelsey 0:da5f5b56060a 366 SS_STATUS SSInterface::get_reg(int idx, uint8_t addr, uint32_t *val)
Shaun Kelsey 0:da5f5b56060a 367 {
Shaun Kelsey 0:da5f5b56060a 368 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 369
Shaun Kelsey 0:da5f5b56060a 370 uint8_t cmd_bytes[] = { SS_FAM_R_REGATTRIBS, (uint8_t)idx };
Shaun Kelsey 0:da5f5b56060a 371 uint8_t rx_reg_attribs[3] = {0};
Shaun Kelsey 0:da5f5b56060a 372
Shaun Kelsey 0:da5f5b56060a 373 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 374 0, 0,
Shaun Kelsey 0:da5f5b56060a 375 &rx_reg_attribs[0], ARRAY_SIZE(rx_reg_attribs));
Shaun Kelsey 0:da5f5b56060a 376
Shaun Kelsey 0:da5f5b56060a 377 if (status != SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 378 return status;
Shaun Kelsey 0:da5f5b56060a 379
Shaun Kelsey 0:da5f5b56060a 380 int reg_width = rx_reg_attribs[1];
Shaun Kelsey 0:da5f5b56060a 381
Shaun Kelsey 0:da5f5b56060a 382 uint8_t cmd_bytes2[] = { SS_FAM_R_READREG, (uint8_t)idx, addr };
Shaun Kelsey 0:da5f5b56060a 383 uint8_t rxbuf[5] = {0};
Shaun Kelsey 0:da5f5b56060a 384
Shaun Kelsey 0:da5f5b56060a 385 status = read_cmd(&cmd_bytes2[0], ARRAY_SIZE(cmd_bytes2),
Shaun Kelsey 0:da5f5b56060a 386 0, 0,
Shaun Kelsey 0:da5f5b56060a 387 &rxbuf[0], ARRAY_SIZE(rxbuf));
Shaun Kelsey 0:da5f5b56060a 388
Shaun Kelsey 0:da5f5b56060a 389 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 390 *val = 0;
Shaun Kelsey 0:da5f5b56060a 391 for (int i = 0; i < reg_width; i++) {
Shaun Kelsey 0:da5f5b56060a 392 *val = (*val << 8) | rxbuf[i + 1];
Shaun Kelsey 0:da5f5b56060a 393 }
Shaun Kelsey 0:da5f5b56060a 394 }
Shaun Kelsey 0:da5f5b56060a 395
Shaun Kelsey 0:da5f5b56060a 396 return status;
Shaun Kelsey 0:da5f5b56060a 397 }
Shaun Kelsey 0:da5f5b56060a 398
Shaun Kelsey 0:da5f5b56060a 399 SS_STATUS SSInterface::set_reg(int idx, uint8_t addr, uint32_t val, int byte_size)
Shaun Kelsey 0:da5f5b56060a 400 {
Shaun Kelsey 0:da5f5b56060a 401 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 402
Shaun Kelsey 0:da5f5b56060a 403 uint8_t cmd_bytes[] = { SS_FAM_W_WRITEREG, (uint8_t)idx, addr };
Shaun Kelsey 0:da5f5b56060a 404 uint8_t data_bytes[4];
Shaun Kelsey 0:da5f5b56060a 405 for (int i = 0; i < byte_size; i++) {
Shaun Kelsey 0:da5f5b56060a 406 data_bytes[i] = (val >> (8 * (byte_size - 1)) & 0xFF);
Shaun Kelsey 0:da5f5b56060a 407 }
Shaun Kelsey 0:da5f5b56060a 408
Shaun Kelsey 0:da5f5b56060a 409 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 410 &data_bytes[0], byte_size);
Shaun Kelsey 0:da5f5b56060a 411
Shaun Kelsey 0:da5f5b56060a 412 return status;
Shaun Kelsey 0:da5f5b56060a 413 }
Shaun Kelsey 0:da5f5b56060a 414
Shaun Kelsey 0:da5f5b56060a 415 SS_STATUS SSInterface::dump_reg(int idx, addr_val_pair* reg_vals, int reg_vals_sz, int* num_regs)
Shaun Kelsey 0:da5f5b56060a 416 {
Shaun Kelsey 0:da5f5b56060a 417 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 418
Shaun Kelsey 0:da5f5b56060a 419 uint8_t cmd_bytes[] = { SS_FAM_R_REGATTRIBS, (uint8_t)idx };
Shaun Kelsey 0:da5f5b56060a 420 uint8_t rx_reg_attribs[3] = {0};
Shaun Kelsey 0:da5f5b56060a 421
Shaun Kelsey 0:da5f5b56060a 422 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 423 0, 0,
Shaun Kelsey 0:da5f5b56060a 424 &rx_reg_attribs[0], ARRAY_SIZE(rx_reg_attribs));
Shaun Kelsey 0:da5f5b56060a 425
Shaun Kelsey 0:da5f5b56060a 426 if (status != SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 427 return status;
Shaun Kelsey 0:da5f5b56060a 428
Shaun Kelsey 0:da5f5b56060a 429 int reg_width = rx_reg_attribs[1];
Shaun Kelsey 0:da5f5b56060a 430 *num_regs = rx_reg_attribs[2];
Shaun Kelsey 0:da5f5b56060a 431 assert_msg((*num_regs <= reg_vals_sz), "Need to increase reg_vals array to hold all dump_reg data");
Shaun Kelsey 0:da5f5b56060a 432 assert_msg(((size_t)reg_width <= sizeof(uint32_t)), "IC returned register values greater than 4 bytes in width");
Shaun Kelsey 0:da5f5b56060a 433
Shaun Kelsey 0:da5f5b56060a 434 int dump_reg_sz = (*num_regs) * (reg_width + 1) + 1; //+1 to reg_width for address, +1 for status byte
Shaun Kelsey 0:da5f5b56060a 435
Shaun Kelsey 0:da5f5b56060a 436 uint8_t rxbuf[512];
Shaun Kelsey 0:da5f5b56060a 437 assert_msg(((size_t)dump_reg_sz <= sizeof(rxbuf)), "Need to increase buffer size to receive dump_reg data");
Shaun Kelsey 0:da5f5b56060a 438
Shaun Kelsey 0:da5f5b56060a 439 cmd_bytes[0] = SS_FAM_R_DUMPREG;
Shaun Kelsey 0:da5f5b56060a 440 status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 441 0, 0,
Shaun Kelsey 0:da5f5b56060a 442 &rxbuf[0], dump_reg_sz, SS_DUMP_REG_SLEEP_MS);
Shaun Kelsey 0:da5f5b56060a 443
Shaun Kelsey 0:da5f5b56060a 444 if (status != SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 445 return status;
Shaun Kelsey 0:da5f5b56060a 446
Shaun Kelsey 0:da5f5b56060a 447 //rxbuf format is [status][addr0](reg_width x [val0])[addr1](reg_width x [val1])...
Shaun Kelsey 0:da5f5b56060a 448 for (int reg = 0; reg < *num_regs; reg++) {
Shaun Kelsey 0:da5f5b56060a 449 reg_vals[reg].addr = rxbuf[(reg * (reg_width + 1)) + 1];
Shaun Kelsey 0:da5f5b56060a 450 uint32_t *val = &(reg_vals[reg].val);
Shaun Kelsey 0:da5f5b56060a 451 *val = 0;
Shaun Kelsey 0:da5f5b56060a 452 for (int byte = 0; byte < reg_width; byte++) {
Shaun Kelsey 0:da5f5b56060a 453 *val = (*val << 8) | rxbuf[(reg * (reg_width + 1)) + byte + 2];
Shaun Kelsey 0:da5f5b56060a 454 }
Shaun Kelsey 0:da5f5b56060a 455 }
Shaun Kelsey 0:da5f5b56060a 456
Shaun Kelsey 0:da5f5b56060a 457 return SS_SUCCESS;
Shaun Kelsey 0:da5f5b56060a 458 }
Shaun Kelsey 0:da5f5b56060a 459
Shaun Kelsey 0:da5f5b56060a 460 SS_STATUS SSInterface::enable_sensor(int idx, int mode, ss_data_req *data_req)
Shaun Kelsey 0:da5f5b56060a 461 {
Shaun Kelsey 0:da5f5b56060a 462 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 463 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 464 assert_msg((mode != 0), "Tried to enable sensor to mode 0, but mode 0 is disable");
Shaun Kelsey 0:da5f5b56060a 465
Shaun Kelsey 0:da5f5b56060a 466 uint8_t cmd_bytes[] = { SS_FAM_W_SENSORMODE, (uint8_t)idx, (uint8_t)mode };
Shaun Kelsey 0:da5f5b56060a 467
Shaun Kelsey 0:da5f5b56060a 468 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS);
Shaun Kelsey 0:da5f5b56060a 469
Shaun Kelsey 0:da5f5b56060a 470 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 471 sensor_enabled_mode[idx] = mode;
Shaun Kelsey 0:da5f5b56060a 472 sensor_data_reqs[idx] = data_req;
Shaun Kelsey 0:da5f5b56060a 473 }
Shaun Kelsey 0:da5f5b56060a 474 return status;
Shaun Kelsey 0:da5f5b56060a 475 }
Shaun Kelsey 0:da5f5b56060a 476
Shaun Kelsey 0:da5f5b56060a 477 SS_STATUS SSInterface::disable_sensor(int idx)
Shaun Kelsey 0:da5f5b56060a 478 {
Shaun Kelsey 0:da5f5b56060a 479 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 480 uint8_t cmd_bytes[] = { SS_FAM_W_SENSORMODE, (uint8_t)idx, 0 };
Shaun Kelsey 0:da5f5b56060a 481
Shaun Kelsey 0:da5f5b56060a 482 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS);
Shaun Kelsey 0:da5f5b56060a 483
Shaun Kelsey 0:da5f5b56060a 484 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 485 sensor_enabled_mode[idx] = 0;
Shaun Kelsey 0:da5f5b56060a 486 sensor_data_reqs[idx] = 0;
Shaun Kelsey 0:da5f5b56060a 487 }
Shaun Kelsey 0:da5f5b56060a 488
Shaun Kelsey 0:da5f5b56060a 489 return status;
Shaun Kelsey 0:da5f5b56060a 490 }
Shaun Kelsey 0:da5f5b56060a 491
Shaun Kelsey 0:da5f5b56060a 492 SS_STATUS SSInterface::enable_algo(int idx, int mode, ss_data_req *data_req)
Shaun Kelsey 0:da5f5b56060a 493 {
Shaun Kelsey 0:da5f5b56060a 494 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 495 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 496 assert_msg((mode != 0), "Tried to enable algo to mode 0, but mode 0 is disable");
Shaun Kelsey 0:da5f5b56060a 497
Shaun Kelsey 0:da5f5b56060a 498 uint8_t cmd_bytes[] = { SS_FAM_W_ALGOMODE, (uint8_t)idx, (uint8_t)mode };
Shaun Kelsey 0:da5f5b56060a 499
Shaun Kelsey 0:da5f5b56060a 500 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS);
Shaun Kelsey 0:da5f5b56060a 501
Shaun Kelsey 0:da5f5b56060a 502 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 503 algo_enabled_mode[idx] = mode;
Shaun Kelsey 0:da5f5b56060a 504 algo_data_reqs[idx] = data_req;
Shaun Kelsey 0:da5f5b56060a 505 }
Shaun Kelsey 0:da5f5b56060a 506
Shaun Kelsey 0:da5f5b56060a 507 return status;
Shaun Kelsey 0:da5f5b56060a 508 }
Shaun Kelsey 0:da5f5b56060a 509
Shaun Kelsey 0:da5f5b56060a 510 SS_STATUS SSInterface::disable_algo(int idx)
Shaun Kelsey 0:da5f5b56060a 511 {
Shaun Kelsey 0:da5f5b56060a 512 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 513 uint8_t cmd_bytes[] = { SS_FAM_W_ALGOMODE, (uint8_t)idx, 0 };
Shaun Kelsey 0:da5f5b56060a 514
Shaun Kelsey 0:da5f5b56060a 515 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes), 0, 0, SS_ENABLE_SENSOR_SLEEP_MS);
Shaun Kelsey 0:da5f5b56060a 516
Shaun Kelsey 0:da5f5b56060a 517 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 518 algo_enabled_mode[idx] = 0;
Shaun Kelsey 0:da5f5b56060a 519 algo_data_reqs[idx] = 0;
Shaun Kelsey 0:da5f5b56060a 520 }
Shaun Kelsey 0:da5f5b56060a 521
Shaun Kelsey 0:da5f5b56060a 522 return status;
Shaun Kelsey 0:da5f5b56060a 523 }
Shaun Kelsey 0:da5f5b56060a 524
Shaun Kelsey 0:da5f5b56060a 525 SS_STATUS SSInterface::set_data_type(int data_type, bool sc_en)
Shaun Kelsey 0:da5f5b56060a 526 {
Shaun Kelsey 0:da5f5b56060a 527 assert_msg((data_type >= 0) && (data_type <= 3), "Invalid value for data_type");
Shaun Kelsey 0:da5f5b56060a 528 uint8_t cmd_bytes[] = { SS_FAM_W_COMMCHAN, SS_CMDIDX_OUTPUTMODE };
Shaun Kelsey 1:7a55c0c7d6d9 529 uint8_t data_bytes[] = { (uint8_t)((sc_en ? SS_MASK_OUTPUTMODE_SC_EN : 0) |
Shaun Kelsey 1:7a55c0c7d6d9 530 ((data_type << SS_SHIFT_OUTPUTMODE_DATATYPE) & SS_MASK_OUTPUTMODE_DATATYPE)) };
Shaun Kelsey 0:da5f5b56060a 531
Shaun Kelsey 0:da5f5b56060a 532 SS_STATUS status = write_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 533 &data_bytes[0], ARRAY_SIZE(data_bytes));
Shaun Kelsey 0:da5f5b56060a 534
Shaun Kelsey 0:da5f5b56060a 535 this->data_type = data_type;
Shaun Kelsey 0:da5f5b56060a 536 this->sc_en = sc_en;
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
Shaun Kelsey 0:da5f5b56060a 542 SS_STATUS SSInterface::get_data_type(int *data_type, bool *sc_en)
Shaun Kelsey 0:da5f5b56060a 543 {
Shaun Kelsey 0:da5f5b56060a 544 uint8_t cmd_bytes[] = { SS_FAM_R_COMMCHAN, SS_CMDIDX_OUTPUTMODE };
Shaun Kelsey 0:da5f5b56060a 545 uint8_t rxbuf[2] = {0};
Shaun Kelsey 0:da5f5b56060a 546
Shaun Kelsey 0:da5f5b56060a 547 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 548 0, 0,
Shaun Kelsey 0:da5f5b56060a 549 &rxbuf[0], ARRAY_SIZE(rxbuf));
Shaun Kelsey 0:da5f5b56060a 550 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 551 *data_type =
Shaun Kelsey 0:da5f5b56060a 552 (rxbuf[1] & SS_MASK_OUTPUTMODE_DATATYPE) >> SS_SHIFT_OUTPUTMODE_DATATYPE;
Shaun Kelsey 0:da5f5b56060a 553 *sc_en =
Shaun Kelsey 0:da5f5b56060a 554 (bool)((rxbuf[1] & SS_MASK_OUTPUTMODE_SC_EN) >> SS_SHIFT_OUTPUTMODE_SC_EN);
Shaun Kelsey 0:da5f5b56060a 555 }
Shaun Kelsey 0:da5f5b56060a 556
Shaun Kelsey 0:da5f5b56060a 557 return status;
Shaun Kelsey 0:da5f5b56060a 558 }
Shaun Kelsey 0:da5f5b56060a 559
Shaun Kelsey 0:da5f5b56060a 560 void SSInterface::fifo_sample_size(int data_type, int *sample_size)
Shaun Kelsey 0:da5f5b56060a 561 {
Shaun Kelsey 0:da5f5b56060a 562 *sample_size = 0;
Shaun Kelsey 0:da5f5b56060a 563
Shaun Kelsey 0:da5f5b56060a 564 if (data_type == SS_DATATYPE_RAW || data_type == SS_DATATYPE_BOTH) {
Shaun Kelsey 0:da5f5b56060a 565 for (int i = 0; i < SS_MAX_SUPPORTED_SENSOR_NUM; i++) {
Shaun Kelsey 0:da5f5b56060a 566 if (sensor_enabled_mode[i]) {
Shaun Kelsey 0:da5f5b56060a 567 assert_msg(sensor_data_reqs[i], "no ss_data_req found for enabled sensor");
Shaun Kelsey 0:da5f5b56060a 568 *sample_size += sensor_data_reqs[i]->data_size;
Shaun Kelsey 0:da5f5b56060a 569 }
Shaun Kelsey 0:da5f5b56060a 570 }
Shaun Kelsey 0:da5f5b56060a 571 }
Shaun Kelsey 0:da5f5b56060a 572
Shaun Kelsey 0:da5f5b56060a 573 if (data_type == SS_DATATYPE_ALGO || data_type == SS_DATATYPE_BOTH) {
Shaun Kelsey 0:da5f5b56060a 574 for (int i = 0; i < SS_MAX_SUPPORTED_ALGO_NUM; i++) {
Shaun Kelsey 0:da5f5b56060a 575 if (algo_enabled_mode[i]) {
Shaun Kelsey 0:da5f5b56060a 576 assert_msg(algo_data_reqs[i], "no ss_data_req found for enabled algo");
Shaun Kelsey 0:da5f5b56060a 577 *sample_size += algo_data_reqs[i]->data_size;
Shaun Kelsey 0:da5f5b56060a 578 }
Shaun Kelsey 0:da5f5b56060a 579 }
Shaun Kelsey 0:da5f5b56060a 580 }
Shaun Kelsey 0:da5f5b56060a 581 }
Shaun Kelsey 0:da5f5b56060a 582
Shaun Kelsey 0:da5f5b56060a 583 SS_STATUS SSInterface::num_avail_samples(int *num_samples)
Shaun Kelsey 0:da5f5b56060a 584 {
Shaun Kelsey 0:da5f5b56060a 585 uint8_t cmd_bytes[] = { SS_FAM_R_OUTPUTFIFO, SS_CMDIDX_OUT_NUMSAMPLES };
Shaun Kelsey 0:da5f5b56060a 586 uint8_t rxbuf[2] = {0};
Shaun Kelsey 0:da5f5b56060a 587
Shaun Kelsey 0:da5f5b56060a 588 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 589 0, 0,
Shaun Kelsey 0:da5f5b56060a 590 &rxbuf[0], ARRAY_SIZE(rxbuf));
Shaun Kelsey 0:da5f5b56060a 591
Shaun Kelsey 0:da5f5b56060a 592 if (status == SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 593 *num_samples = rxbuf[1];
Shaun Kelsey 0:da5f5b56060a 594 }
Shaun Kelsey 0:da5f5b56060a 595
Shaun Kelsey 0:da5f5b56060a 596 return status;
Shaun Kelsey 0:da5f5b56060a 597 }
Shaun Kelsey 0:da5f5b56060a 598
Shaun Kelsey 0:da5f5b56060a 599 SS_STATUS SSInterface::read_fifo_data(
Shaun Kelsey 0:da5f5b56060a 600 int num_samples, int sample_size,
Shaun Kelsey 0:da5f5b56060a 601 uint8_t* databuf, int databuf_sz)
Shaun Kelsey 0:da5f5b56060a 602 {
Shaun Kelsey 0:da5f5b56060a 603 int bytes_to_read = num_samples * sample_size + 1; //+1 for status byte
Shaun Kelsey 0:da5f5b56060a 604 assert_msg((bytes_to_read <= databuf_sz), "databuf too small");
Shaun Kelsey 0:da5f5b56060a 605
Shaun Kelsey 0:da5f5b56060a 606 uint8_t cmd_bytes[] = { SS_FAM_R_OUTPUTFIFO, SS_CMDIDX_READFIFO };
Shaun Kelsey 0:da5f5b56060a 607
Shaun Kelsey 0:da5f5b56060a 608 pr_err("[reading %d bytes (%d samples)\r\n", bytes_to_read, num_samples);
Shaun Kelsey 0:da5f5b56060a 609
Shaun Kelsey 0:da5f5b56060a 610 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 611 0, 0,
Shaun Kelsey 0:da5f5b56060a 612 databuf, bytes_to_read, 15);
Shaun Kelsey 0:da5f5b56060a 613
Shaun Kelsey 0:da5f5b56060a 614 return status;
Shaun Kelsey 0:da5f5b56060a 615 }
Shaun Kelsey 0:da5f5b56060a 616
Shaun Kelsey 0:da5f5b56060a 617 void SSInterface::irq_handler()
Shaun Kelsey 0:da5f5b56060a 618 {
Shaun Kelsey 0:da5f5b56060a 619 uint8_t databuf[512];
Shaun Kelsey 0:da5f5b56060a 620 uint8_t sample_count;
Shaun Kelsey 0:da5f5b56060a 621
Shaun Kelsey 0:da5f5b56060a 622 uint8_t cmd_bytes[] = { SS_FAM_R_STATUS, SS_CMDIDX_STATUS };
Shaun Kelsey 0:da5f5b56060a 623 uint8_t rxbuf[2] = {0};
Shaun Kelsey 0:da5f5b56060a 624
Shaun Kelsey 0:da5f5b56060a 625 irq_pin.disable_irq();
Shaun Kelsey 0:da5f5b56060a 626
Shaun Kelsey 0:da5f5b56060a 627 SS_STATUS status = read_cmd(&cmd_bytes[0], ARRAY_SIZE(cmd_bytes),
Shaun Kelsey 0:da5f5b56060a 628 0, 0,
Shaun Kelsey 0:da5f5b56060a 629 &rxbuf[0], ARRAY_SIZE(rxbuf));
Shaun Kelsey 0:da5f5b56060a 630
Shaun Kelsey 0:da5f5b56060a 631 if (status != SS_SUCCESS) {
Shaun Kelsey 0:da5f5b56060a 632 pr_err("Couldn't read status byte of SmartSensor!");
Shaun Kelsey 0:da5f5b56060a 633 irq_pin.enable_irq();
Shaun Kelsey 0:da5f5b56060a 634 return;
Shaun Kelsey 0:da5f5b56060a 635 }
Shaun Kelsey 0:da5f5b56060a 636
Shaun Kelsey 0:da5f5b56060a 637 if (rxbuf[1] & SS_MASK_STATUS_ERR) {
Shaun Kelsey 0:da5f5b56060a 638 pr_err("SmartSensor status error: %d", rxbuf[1] & SS_MASK_STATUS_ERR);
Shaun Kelsey 0:da5f5b56060a 639 }
Shaun Kelsey 0:da5f5b56060a 640 if (rxbuf[1] & SS_MASK_STATUS_FIFO_OUT_OVR) {
Shaun Kelsey 0:da5f5b56060a 641 pr_err("SmartSensor Output FIFO overflow!");
Shaun Kelsey 0:da5f5b56060a 642 }
Shaun Kelsey 0:da5f5b56060a 643 if (rxbuf[1] & SS_MASK_STATUS_FIFO_IN_OVR) {
Shaun Kelsey 0:da5f5b56060a 644 pr_err("SmartSensor Input FIFO overflow!");
Shaun Kelsey 0:da5f5b56060a 645 }
Shaun Kelsey 0:da5f5b56060a 646
Shaun Kelsey 0:da5f5b56060a 647 if (rxbuf[1] & SS_MASK_STATUS_DATA_RDY) {
Shaun Kelsey 0:da5f5b56060a 648 int num_samples;
Shaun Kelsey 0:da5f5b56060a 649 status = num_avail_samples(&num_samples);
Shaun Kelsey 0:da5f5b56060a 650 if (status != SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 651 {
Shaun Kelsey 0:da5f5b56060a 652 pr_err("Couldn't read number of available samples in SmartSensor Output FIFO");
Shaun Kelsey 0:da5f5b56060a 653 irq_pin.enable_irq();
Shaun Kelsey 0:da5f5b56060a 654 return;
Shaun Kelsey 0:da5f5b56060a 655 }
Shaun Kelsey 0:da5f5b56060a 656
Shaun Kelsey 0:da5f5b56060a 657 if (num_samples <= 0)
Shaun Kelsey 0:da5f5b56060a 658 {
Shaun Kelsey 0:da5f5b56060a 659 irq_pin.enable_irq();
Shaun Kelsey 0:da5f5b56060a 660 return;
Shaun Kelsey 0:da5f5b56060a 661 }
Shaun Kelsey 0:da5f5b56060a 662
Shaun Kelsey 0:da5f5b56060a 663
Shaun Kelsey 0:da5f5b56060a 664 int sample_size;
Shaun Kelsey 0:da5f5b56060a 665 fifo_sample_size(data_type, &sample_size);
Shaun Kelsey 0:da5f5b56060a 666
Shaun Kelsey 1:7a55c0c7d6d9 667 size_t bytes_to_read = num_samples * sample_size + 1; //+1 for status byte
Shaun Kelsey 0:da5f5b56060a 668 if (bytes_to_read > sizeof(databuf)) {
Shaun Kelsey 0:da5f5b56060a 669 //Reduce number of samples to read to fit in buffer
Shaun Kelsey 0:da5f5b56060a 670 num_samples = (sizeof(databuf) - 1) / sample_size;
Shaun Kelsey 0:da5f5b56060a 671 }
Shaun Kelsey 0:da5f5b56060a 672
Shaun Kelsey 0:da5f5b56060a 673 status = read_fifo_data(num_samples, sample_size, &databuf[0], sizeof(databuf));
Shaun Kelsey 0:da5f5b56060a 674 if (status != SS_SUCCESS)
Shaun Kelsey 0:da5f5b56060a 675 {
Shaun Kelsey 0:da5f5b56060a 676 pr_err("Couldn't read from SmartSensor Output FIFO");
Shaun Kelsey 0:da5f5b56060a 677 irq_pin.enable_irq();
Shaun Kelsey 0:da5f5b56060a 678 return;
Shaun Kelsey 0:da5f5b56060a 679 }
Shaun Kelsey 0:da5f5b56060a 680
Shaun Kelsey 0:da5f5b56060a 681 //Skip status byte
Shaun Kelsey 0:da5f5b56060a 682 uint8_t *data_ptr = &databuf[1];
Shaun Kelsey 0:da5f5b56060a 683
Shaun Kelsey 0:da5f5b56060a 684 int i = 0;
Shaun Kelsey 0:da5f5b56060a 685 for (i = 0; i < num_samples; i++) {
Shaun Kelsey 0:da5f5b56060a 686 if (sc_en) {
Shaun Kelsey 0:da5f5b56060a 687 sample_count = *data_ptr++;
Shaun Kelsey 0:da5f5b56060a 688 pr_info("Received sample #%d", sample_count);
Shaun Kelsey 0:da5f5b56060a 689 }
Shaun Kelsey 0:da5f5b56060a 690
Shaun Kelsey 0:da5f5b56060a 691 //Chop up data and send to modules with enabled sensors
Shaun Kelsey 0:da5f5b56060a 692 if (data_type == SS_DATATYPE_RAW || data_type == SS_DATATYPE_BOTH) {
Shaun Kelsey 0:da5f5b56060a 693 for (int i = 0; i < SS_MAX_SUPPORTED_SENSOR_NUM; i++) {
Shaun Kelsey 0:da5f5b56060a 694 if (sensor_enabled_mode[i]) {
Shaun Kelsey 0:da5f5b56060a 695 assert_msg(sensor_data_reqs[i],
Shaun Kelsey 0:da5f5b56060a 696 "no ss_data_req found for enabled sensor");
Shaun Kelsey 0:da5f5b56060a 697 sensor_data_reqs[i]->callback(data_ptr);
Shaun Kelsey 0:da5f5b56060a 698 data_ptr += sensor_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 if (data_type == SS_DATATYPE_ALGO || data_type == SS_DATATYPE_BOTH) {
Shaun Kelsey 0:da5f5b56060a 703 for (int i = 0; i < SS_MAX_SUPPORTED_ALGO_NUM; i++) {
Shaun Kelsey 0:da5f5b56060a 704 if (algo_enabled_mode[i]) {
Shaun Kelsey 0:da5f5b56060a 705 assert_msg(algo_data_reqs[i],
Shaun Kelsey 0:da5f5b56060a 706 "no ss_data_req found for enabled algo");
Shaun Kelsey 0:da5f5b56060a 707 algo_data_reqs[i]->callback(data_ptr);
Shaun Kelsey 0:da5f5b56060a 708 data_ptr += algo_data_reqs[i]->data_size;
Shaun Kelsey 0:da5f5b56060a 709 }
Shaun Kelsey 0:da5f5b56060a 710 }
Shaun Kelsey 0:da5f5b56060a 711 }
Shaun Kelsey 0:da5f5b56060a 712 }
Shaun Kelsey 0:da5f5b56060a 713 }
Shaun Kelsey 0:da5f5b56060a 714 irq_pin.enable_irq();
Shaun Kelsey 0:da5f5b56060a 715 }
Shaun Kelsey 0:da5f5b56060a 716
Shaun Kelsey 0:da5f5b56060a 717 void SSInterface::irq_handler_selftest(){
Shaun Kelsey 0:da5f5b56060a 718 mfio_int_happened = true;
Shaun Kelsey 0:da5f5b56060a 719 }
Shaun Kelsey 0:da5f5b56060a 720
Shaun Kelsey 0:da5f5b56060a 721 bool SSInterface::reset_mfio_irq(){
Shaun Kelsey 0:da5f5b56060a 722 bool ret = mfio_int_happened;
Shaun Kelsey 0:da5f5b56060a 723 mfio_int_happened = false;
Shaun Kelsey 0:da5f5b56060a 724 irq_pin.disable_irq();
Shaun Kelsey 0:da5f5b56060a 725 irq_pin.fall(callback(this, &SSInterface::irq_handler));
Shaun Kelsey 0:da5f5b56060a 726 irq_pin.enable_irq();
Shaun Kelsey 0:da5f5b56060a 727 return ret;
Shaun Kelsey 0:da5f5b56060a 728 }