Maxim Integrated's IoT development kit.

Dependencies:   MAX30101 MAX30003 MAX113XX_Pixi MAX30205 max32630fthr USBDevice

Committer:
Mahir Ozturk
Date:
Tue Mar 20 16:28:33 2018 +0300
Revision:
6:aeb5a4c194c3
Parent:
5:ff721fa88519
Child:
7:2c9c8b6a28a7
Add a workaround for __possibly__ a bug in the Max30101 driver

Change-Id: I180ff670ba0dc48663e5be2b73a268c402c74759

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Mahir Ozturk 1:efe9cad8942f 1 /*******************************************************************************
Mahir Ozturk 1:efe9cad8942f 2 * Copyright (C) 2018 Maxim Integrated Products, Inc., All Rights Reserved.
Mahir Ozturk 1:efe9cad8942f 3 *
Mahir Ozturk 1:efe9cad8942f 4 * Permission is hereby granted, free of charge, to any person obtaining a
Mahir Ozturk 1:efe9cad8942f 5 * copy of this software and associated documentation files (the "Software"),
Mahir Ozturk 1:efe9cad8942f 6 * to deal in the Software without restriction, including without limitation
Mahir Ozturk 1:efe9cad8942f 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
Mahir Ozturk 1:efe9cad8942f 8 * and/or sell copies of the Software, and to permit persons to whom the
Mahir Ozturk 1:efe9cad8942f 9 * Software is furnished to do so, subject to the following conditions:
Mahir Ozturk 1:efe9cad8942f 10 *
Mahir Ozturk 1:efe9cad8942f 11 * The above copyright notice and this permission notice shall be included
Mahir Ozturk 1:efe9cad8942f 12 * in all copies or substantial portions of the Software.
Mahir Ozturk 1:efe9cad8942f 13 *
Mahir Ozturk 1:efe9cad8942f 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
Mahir Ozturk 1:efe9cad8942f 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Mahir Ozturk 1:efe9cad8942f 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Mahir Ozturk 1:efe9cad8942f 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
Mahir Ozturk 1:efe9cad8942f 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
Mahir Ozturk 1:efe9cad8942f 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
Mahir Ozturk 1:efe9cad8942f 20 * OTHER DEALINGS IN THE SOFTWARE.
Mahir Ozturk 1:efe9cad8942f 21 *
Mahir Ozturk 1:efe9cad8942f 22 * Except as contained in this notice, the name of Maxim Integrated
Mahir Ozturk 1:efe9cad8942f 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
Mahir Ozturk 1:efe9cad8942f 24 * Products, Inc. Branding Policy.
Mahir Ozturk 1:efe9cad8942f 25 *
Mahir Ozturk 1:efe9cad8942f 26 * The mere transfer of this software does not imply any licenses
Mahir Ozturk 1:efe9cad8942f 27 * of trade secrets, proprietary technology, copyrights, patents,
Mahir Ozturk 1:efe9cad8942f 28 * trademarks, maskwork rights, or any other form of intellectual
Mahir Ozturk 1:efe9cad8942f 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
Mahir Ozturk 1:efe9cad8942f 30 * ownership rights.
Mahir Ozturk 1:efe9cad8942f 31 *******************************************************************************
Mahir Ozturk 1:efe9cad8942f 32 */
Mahir Ozturk 1:efe9cad8942f 33 #include <events/mbed_events.h>
Mahir Ozturk 1:efe9cad8942f 34
Mahir Ozturk 1:efe9cad8942f 35 #include <mbed.h>
Mahir Ozturk 1:efe9cad8942f 36 #include <rtos.h>
Mahir Ozturk 1:efe9cad8942f 37 #include "ble/BLE.h"
Mahir Ozturk 1:efe9cad8942f 38 #include "ble/Gap.h"
Mahir Ozturk 1:efe9cad8942f 39 #include "max32630fthr.h"
Mahir Ozturk 1:efe9cad8942f 40
Mahir Ozturk 1:efe9cad8942f 41 #if defined(LIB_MAX30003)
Mahir Ozturk 1:efe9cad8942f 42 #include "MAX30003.h"
Mahir Ozturk 1:efe9cad8942f 43 #endif
Mahir Ozturk 1:efe9cad8942f 44
Mahir Ozturk 1:efe9cad8942f 45 #if defined(LIB_MAX30205)
Mahir Ozturk 1:efe9cad8942f 46 #include "MAX30205.h"
Mahir Ozturk 1:efe9cad8942f 47 #endif
Mahir Ozturk 1:efe9cad8942f 48
Mahir Ozturk 1:efe9cad8942f 49 #if defined(LIB_MAX30101)
Mahir Ozturk 1:efe9cad8942f 50 #include "MAX30101.h"
Mahir Ozturk 1:efe9cad8942f 51 #include "max30101_algo.h"
Mahir Ozturk 1:efe9cad8942f 52 #endif
Mahir Ozturk 1:efe9cad8942f 53
Mahir Ozturk 1:efe9cad8942f 54 #if defined(LIB_MAX113XX_PIXI)
Mahir Ozturk 1:efe9cad8942f 55 #include "MAX113XX_Pixi.h"
Mahir Ozturk 1:efe9cad8942f 56 #include "MAX11301Hex.h"
Mahir Ozturk 1:efe9cad8942f 57 #endif
Mahir Ozturk 1:efe9cad8942f 58
Mahir Ozturk 1:efe9cad8942f 59 /******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 60
Mahir Ozturk 1:efe9cad8942f 61 MAX32630FTHR pegasus(MAX32630FTHR::VIO_3V3);
Mahir Ozturk 1:efe9cad8942f 62
Mahir Ozturk 1:efe9cad8942f 63 InterruptIn button(P2_3);
Mahir Ozturk 1:efe9cad8942f 64
Mahir Ozturk 1:efe9cad8942f 65 SPI spim2(SPI2_MOSI, SPI2_MISO, SPI2_SCK);
Mahir Ozturk 1:efe9cad8942f 66
Mahir Ozturk 1:efe9cad8942f 67 I2C i2c1(I2C1_SDA, I2C1_SCL); /* I2C bus, P3_4 = SDA, P3_5 = SCL */
Mahir Ozturk 1:efe9cad8942f 68
Mahir Ozturk 1:efe9cad8942f 69 /* LEDs */
Mahir Ozturk 1:efe9cad8942f 70 DigitalOut rLED(LED1, LED_OFF);
Mahir Ozturk 1:efe9cad8942f 71 DigitalOut gLED(LED2, LED_OFF);
Mahir Ozturk 1:efe9cad8942f 72 DigitalOut bLED(LED3, LED_OFF);
Mahir Ozturk 1:efe9cad8942f 73
Mahir Ozturk 1:efe9cad8942f 74 /* Hardware serial port over DAPLink */
Mahir Ozturk 1:efe9cad8942f 75 Serial daplink(USBTX, USBRX, 115200);
Mahir Ozturk 1:efe9cad8942f 76
Mahir Ozturk 2:68ffd74e3b5c 77 int aliveLedEventId;
Mahir Ozturk 2:68ffd74e3b5c 78
Mahir Ozturk 1:efe9cad8942f 79 /******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 80 const static char DEVICE_NAME[] = MAXIM_PLATFORM_NAME;
Mahir Ozturk 1:efe9cad8942f 81 static const uint16_t uuid16_list[] = {0xFFFF}; //Custom UUID, FFFF is reserved for development
Mahir Ozturk 1:efe9cad8942f 82
Mahir Ozturk 1:efe9cad8942f 83 /* Set Up custom Characteristics */
Mahir Ozturk 1:efe9cad8942f 84 UUID iotServiceUUID ("00001520-1d66-11e8-b467-0ed5f89f718b");
Mahir Ozturk 1:efe9cad8942f 85
Mahir Ozturk 1:efe9cad8942f 86 UUID uuidButtonPressedNotify("00001522-1d66-11e8-b467-0ed5f89f718b");
Mahir Ozturk 1:efe9cad8942f 87 static uint8_t buttonPressedCount = 0;
Mahir Ozturk 1:efe9cad8942f 88 GattCharacteristic gattCharButtonPressedNotify(uuidButtonPressedNotify, &buttonPressedCount, 1, 1,
Mahir Ozturk 1:efe9cad8942f 89 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
Mahir Ozturk 1:efe9cad8942f 90
Mahir Ozturk 1:efe9cad8942f 91 UUID uuidRGBLED("00001523-1d66-11e8-b467-0ed5f89f718b");
Mahir Ozturk 1:efe9cad8942f 92 static uint8_t RGBLedInitValue[] = {LED_OFF, LED_OFF, LED_OFF};
Mahir Ozturk 1:efe9cad8942f 93 ReadWriteArrayGattCharacteristic<uint8_t, sizeof(RGBLedInitValue)> gattCharRGBLed(uuidRGBLED, RGBLedInitValue);
Mahir Ozturk 1:efe9cad8942f 94
Mahir Ozturk 1:efe9cad8942f 95 #if defined(LIB_MAX30003_ECG)
Mahir Ozturk 1:efe9cad8942f 96 UUID uuidECG("00001524-1d66-11e8-b467-0ed5f89f718b");
Mahir Ozturk 1:efe9cad8942f 97 static int16_t ECGInitValue = 0xABCD;
Mahir Ozturk 1:efe9cad8942f 98 ReadOnlyGattCharacteristic<int16_t> gattCharECG(uuidECG, &ECGInitValue,
Mahir Ozturk 1:efe9cad8942f 99 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
Mahir Ozturk 1:efe9cad8942f 100 #else
Mahir Ozturk 1:efe9cad8942f 101 UUID uuidBPM("00001524-1d66-11e8-b467-0ed5f89f718b");
Mahir Ozturk 1:efe9cad8942f 102 static float BPMInitValue = 0.0;
Mahir Ozturk 1:efe9cad8942f 103 ReadOnlyGattCharacteristic<float> gattCharBPM(uuidBPM, &BPMInitValue,
Mahir Ozturk 1:efe9cad8942f 104 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
Mahir Ozturk 1:efe9cad8942f 105 #endif
Mahir Ozturk 1:efe9cad8942f 106
Mahir Ozturk 1:efe9cad8942f 107 #if defined(LIB_MAX30101)
Mahir Ozturk 1:efe9cad8942f 108 UUID uuidHeartRate("00001525-1d66-11e8-b467-0ed5f89f718b");
Mahir Ozturk 1:efe9cad8942f 109 static uint16_t HeartRateInitValue = 0xEEFF;
Mahir Ozturk 1:efe9cad8942f 110 ReadOnlyGattCharacteristic<uint16_t> gattCharHeartRate(uuidHeartRate, &HeartRateInitValue,
Mahir Ozturk 1:efe9cad8942f 111 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
Mahir Ozturk 1:efe9cad8942f 112
Mahir Ozturk 1:efe9cad8942f 113 UUID uuidSPO2("00001526-1d66-11e8-b467-0ed5f89f718b");
Mahir Ozturk 1:efe9cad8942f 114 static uint16_t SPO2InitValue = 0xAABB;
Mahir Ozturk 1:efe9cad8942f 115 ReadOnlyGattCharacteristic<uint16_t> gattCharSPO2(uuidSPO2, &SPO2InitValue,
Mahir Ozturk 1:efe9cad8942f 116 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
Mahir Ozturk 1:efe9cad8942f 117 #endif
Mahir Ozturk 1:efe9cad8942f 118
Mahir Ozturk 1:efe9cad8942f 119 #if defined(LIB_MAX113XX_PIXI)
Mahir Ozturk 1:efe9cad8942f 120 UUID uuidADC("00001527-1d66-11e8-b467-0ed5f89f718b");
Mahir Ozturk 5:ff721fa88519 121 static float ADCInitValue = 0;
Mahir Ozturk 5:ff721fa88519 122 ReadOnlyGattCharacteristic<float> gattCharADC(uuidADC, &ADCInitValue,
Mahir Ozturk 3:7e9a93b6b82b 123 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
Mahir Ozturk 1:efe9cad8942f 124 #endif
Mahir Ozturk 1:efe9cad8942f 125
Mahir Ozturk 1:efe9cad8942f 126 #if defined(LIB_MAX30205)
Mahir Ozturk 1:efe9cad8942f 127 UUID uuidTemp("00001528-1d66-11e8-b467-0ed5f89f718b");
Mahir Ozturk 1:efe9cad8942f 128 static float TempInitValue = 26.5;
Mahir Ozturk 1:efe9cad8942f 129 ReadOnlyGattCharacteristic<float> gattCharTemp(uuidTemp, &TempInitValue,
Mahir Ozturk 1:efe9cad8942f 130 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
Mahir Ozturk 1:efe9cad8942f 131 #endif
Mahir Ozturk 1:efe9cad8942f 132
Mahir Ozturk 1:efe9cad8942f 133 /* Set up custom service */
Mahir Ozturk 1:efe9cad8942f 134 GattCharacteristic *characteristics[] = {&gattCharRGBLed, &gattCharButtonPressedNotify,
Mahir Ozturk 1:efe9cad8942f 135 #if defined(LIB_MAX30003_ECG)
Mahir Ozturk 1:efe9cad8942f 136 &gattCharECG,
Mahir Ozturk 1:efe9cad8942f 137 #else
Mahir Ozturk 1:efe9cad8942f 138 &gattCharBPM,
Mahir Ozturk 1:efe9cad8942f 139 #endif
Mahir Ozturk 1:efe9cad8942f 140 #if defined(LIB_MAX30205)
Mahir Ozturk 1:efe9cad8942f 141 &gattCharTemp,
Mahir Ozturk 1:efe9cad8942f 142 #endif
Mahir Ozturk 1:efe9cad8942f 143 #if defined(LIB_MAX30101)
Mahir Ozturk 1:efe9cad8942f 144 &gattCharHeartRate,
Mahir Ozturk 1:efe9cad8942f 145 &gattCharSPO2,
Mahir Ozturk 1:efe9cad8942f 146 #endif
Mahir Ozturk 1:efe9cad8942f 147 #if defined(LIB_MAX113XX_PIXI)
Mahir Ozturk 1:efe9cad8942f 148 &gattCharADC,
Mahir Ozturk 1:efe9cad8942f 149 #endif
Mahir Ozturk 1:efe9cad8942f 150 };
Mahir Ozturk 1:efe9cad8942f 151
Mahir Ozturk 1:efe9cad8942f 152 GattService iotService(iotServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
Mahir Ozturk 1:efe9cad8942f 153
Mahir Ozturk 1:efe9cad8942f 154 /******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 155
Mahir Ozturk 1:efe9cad8942f 156 Mutex ble_mutex;
Mahir Ozturk 1:efe9cad8942f 157
Mahir Ozturk 1:efe9cad8942f 158 static EventQueue eventQueue(/* event count */ 10 * /* event size */ 32);
Mahir Ozturk 1:efe9cad8942f 159
Mahir Ozturk 1:efe9cad8942f 160 ble_error_t bleGattAttrWrite(GattAttribute::Handle_t handle, const uint8_t *value, uint16_t size)
Mahir Ozturk 1:efe9cad8942f 161 {
Mahir Ozturk 1:efe9cad8942f 162 BLE &ble = BLE::Instance();
Mahir Ozturk 1:efe9cad8942f 163 ble_error_t ret;
Mahir Ozturk 1:efe9cad8942f 164
Mahir Ozturk 1:efe9cad8942f 165 ble_mutex.lock();
Mahir Ozturk 1:efe9cad8942f 166
Mahir Ozturk 1:efe9cad8942f 167 ret = ble.gattServer().write(handle, value, size);
Mahir Ozturk 1:efe9cad8942f 168
Mahir Ozturk 1:efe9cad8942f 169 ble_mutex.unlock();
Mahir Ozturk 1:efe9cad8942f 170
Mahir Ozturk 1:efe9cad8942f 171 return ret;
Mahir Ozturk 1:efe9cad8942f 172 }
Mahir Ozturk 1:efe9cad8942f 173
Mahir Ozturk 1:efe9cad8942f 174 void updateButtonState(uint8_t newState) {
Mahir Ozturk 1:efe9cad8942f 175 printf("Button pressed...\r\n");
Mahir Ozturk 1:efe9cad8942f 176 bleGattAttrWrite(gattCharButtonPressedNotify.getValueHandle(), (uint8_t *)&newState, sizeof(uint8_t));
Mahir Ozturk 1:efe9cad8942f 177 }
Mahir Ozturk 1:efe9cad8942f 178
Mahir Ozturk 1:efe9cad8942f 179 void buttonPressedCallback(void)
Mahir Ozturk 1:efe9cad8942f 180 {
Mahir Ozturk 1:efe9cad8942f 181 eventQueue.call(Callback<void(uint8_t)>(&updateButtonState), ++buttonPressedCount);
Mahir Ozturk 1:efe9cad8942f 182 }
Mahir Ozturk 1:efe9cad8942f 183
Mahir Ozturk 1:efe9cad8942f 184 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
Mahir Ozturk 1:efe9cad8942f 185 {
Mahir Ozturk 1:efe9cad8942f 186 printf("disc\r\n");
Mahir Ozturk 1:efe9cad8942f 187 BLE::Instance().gap().startAdvertising(); // restart advertising
Mahir Ozturk 1:efe9cad8942f 188 }
Mahir Ozturk 1:efe9cad8942f 189
Mahir Ozturk 1:efe9cad8942f 190 /* Connection */
Mahir Ozturk 1:efe9cad8942f 191 void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
Mahir Ozturk 1:efe9cad8942f 192 {
Mahir Ozturk 1:efe9cad8942f 193 printf("succ\r\n");
Mahir Ozturk 1:efe9cad8942f 194 }
Mahir Ozturk 1:efe9cad8942f 195
Mahir Ozturk 1:efe9cad8942f 196 void blinkCallback(void)
Mahir Ozturk 1:efe9cad8942f 197 {
Mahir Ozturk 2:68ffd74e3b5c 198 gLED = !gLED;
Mahir Ozturk 1:efe9cad8942f 199 }
Mahir Ozturk 1:efe9cad8942f 200
Mahir Ozturk 1:efe9cad8942f 201 void onBleInitError(BLE &ble, ble_error_t error)
Mahir Ozturk 1:efe9cad8942f 202 {
Mahir Ozturk 1:efe9cad8942f 203 /* Initialization error handling should go here */
Mahir Ozturk 1:efe9cad8942f 204 }
Mahir Ozturk 1:efe9cad8942f 205
Mahir Ozturk 1:efe9cad8942f 206 /**
Mahir Ozturk 1:efe9cad8942f 207 * This callback allows the LEDService to receive updates to the ledState Characteristic.
Mahir Ozturk 1:efe9cad8942f 208 *
Mahir Ozturk 1:efe9cad8942f 209 * @param[in] params
Mahir Ozturk 1:efe9cad8942f 210 * Information about the characteristic being updated.
Mahir Ozturk 1:efe9cad8942f 211 */
Mahir Ozturk 1:efe9cad8942f 212 void onDataWrittenCallback(const GattWriteCallbackParams *params)
Mahir Ozturk 1:efe9cad8942f 213 {
Mahir Ozturk 1:efe9cad8942f 214 if ((params->handle == gattCharRGBLed.getValueHandle()) && (params->len >= 3)) {
Mahir Ozturk 1:efe9cad8942f 215 rLED = (params->data[0] != 0) ? LED_OFF : LED_ON;
Mahir Ozturk 1:efe9cad8942f 216 gLED = (params->data[1] != 0) ? LED_OFF : LED_ON;
Mahir Ozturk 1:efe9cad8942f 217 bLED = (params->data[2] != 0) ? LED_OFF : LED_ON;
Mahir Ozturk 1:efe9cad8942f 218 }
Mahir Ozturk 1:efe9cad8942f 219 }
Mahir Ozturk 1:efe9cad8942f 220
Mahir Ozturk 1:efe9cad8942f 221 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
Mahir Ozturk 1:efe9cad8942f 222 {
Mahir Ozturk 1:efe9cad8942f 223 BLE& ble = params->ble;
Mahir Ozturk 1:efe9cad8942f 224 ble_error_t error = params->error;
Mahir Ozturk 1:efe9cad8942f 225
Mahir Ozturk 1:efe9cad8942f 226 if (error != BLE_ERROR_NONE) {
Mahir Ozturk 1:efe9cad8942f 227 /* In case of error, forward the error handling to onBleInitError */
Mahir Ozturk 1:efe9cad8942f 228 onBleInitError(ble, error);
Mahir Ozturk 1:efe9cad8942f 229 return;
Mahir Ozturk 1:efe9cad8942f 230 }
Mahir Ozturk 1:efe9cad8942f 231
Mahir Ozturk 1:efe9cad8942f 232 /* Ensure that it is the default instance of BLE */
Mahir Ozturk 1:efe9cad8942f 233 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
Mahir Ozturk 1:efe9cad8942f 234 return;
Mahir Ozturk 1:efe9cad8942f 235 }
Mahir Ozturk 1:efe9cad8942f 236
Mahir Ozturk 1:efe9cad8942f 237 ble.gap().onDisconnection(disconnectionCallback);
Mahir Ozturk 1:efe9cad8942f 238 ble.gap().onConnection(connectionCallback);
Mahir Ozturk 1:efe9cad8942f 239
Mahir Ozturk 1:efe9cad8942f 240 ble.gattServer().onDataWritten(onDataWrittenCallback);
Mahir Ozturk 1:efe9cad8942f 241
Mahir Ozturk 1:efe9cad8942f 242 ble.gattServer().addService(iotService);
Mahir Ozturk 1:efe9cad8942f 243
Mahir Ozturk 1:efe9cad8942f 244 /* setup advertising */
Mahir Ozturk 1:efe9cad8942f 245 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
Mahir Ozturk 1:efe9cad8942f 246 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
Mahir Ozturk 1:efe9cad8942f 247 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
Mahir Ozturk 1:efe9cad8942f 248 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
Mahir Ozturk 1:efe9cad8942f 249 ble.gap().setAdvertisingInterval(1000); /* 1000ms. */
Mahir Ozturk 1:efe9cad8942f 250 ble.gap().startAdvertising();
Mahir Ozturk 1:efe9cad8942f 251
Mahir Ozturk 1:efe9cad8942f 252 button.fall(buttonPressedCallback);
Mahir Ozturk 1:efe9cad8942f 253 }
Mahir Ozturk 1:efe9cad8942f 254
Mahir Ozturk 1:efe9cad8942f 255 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
Mahir Ozturk 1:efe9cad8942f 256 BLE &ble = BLE::Instance();
Mahir Ozturk 1:efe9cad8942f 257 eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
Mahir Ozturk 1:efe9cad8942f 258 }
Mahir Ozturk 1:efe9cad8942f 259
Mahir Ozturk 1:efe9cad8942f 260 /******************************************************************************
Mahir Ozturk 1:efe9cad8942f 261 ************** MAX30205EVSYS *************************************************
Mahir Ozturk 1:efe9cad8942f 262 ******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 263 #if defined(LIB_MAX30205)
Mahir Ozturk 1:efe9cad8942f 264
Mahir Ozturk 2:68ffd74e3b5c 265 #define MAX30205_DATA_READ_PERIOD_MSEC 5000
Mahir Ozturk 1:efe9cad8942f 266
Mahir Ozturk 1:efe9cad8942f 267 MAX30205 max30205_temp_sensor(i2c1, 0x48); /* New MAX30205 on i2cBus */
Mahir Ozturk 1:efe9cad8942f 268
Mahir Ozturk 1:efe9cad8942f 269 Thread thread_max30205_reader;
Mahir Ozturk 1:efe9cad8942f 270
Mahir Ozturk 1:efe9cad8942f 271 bool max30205_config(MAX30205 &temp_sensor){
Mahir Ozturk 1:efe9cad8942f 272
Mahir Ozturk 1:efe9cad8942f 273 int rc = 0;
Mahir Ozturk 1:efe9cad8942f 274
Mahir Ozturk 1:efe9cad8942f 275 MAX30205::Configuration_u temp_cfg;
Mahir Ozturk 1:efe9cad8942f 276 temp_cfg.all = 0;
Mahir Ozturk 1:efe9cad8942f 277 temp_cfg.bits.shutdown = 1; // Shutdown mode
Mahir Ozturk 1:efe9cad8942f 278 temp_cfg.bits.comp_int = 1; // Interrupt mode
Mahir Ozturk 1:efe9cad8942f 279 temp_cfg.bits.os_polarity = 0; // Active low OS
Mahir Ozturk 1:efe9cad8942f 280 temp_cfg.bits.fault_queue = 1; // Two faults for OS condition
Mahir Ozturk 1:efe9cad8942f 281 temp_cfg.bits.data_format = 0; // Normal data format
Mahir Ozturk 1:efe9cad8942f 282 temp_cfg.bits.timeout = 0; // I2C timeout reset enabled
Mahir Ozturk 1:efe9cad8942f 283 temp_cfg.bits.one_shot = 0; // Start with one-shot = 0
Mahir Ozturk 1:efe9cad8942f 284
Mahir Ozturk 1:efe9cad8942f 285 rc = temp_sensor.writeConfiguration(temp_cfg); // Write config to MAX30205
Mahir Ozturk 1:efe9cad8942f 286
Mahir Ozturk 1:efe9cad8942f 287 return rc;
Mahir Ozturk 1:efe9cad8942f 288 }
Mahir Ozturk 1:efe9cad8942f 289
Mahir Ozturk 1:efe9cad8942f 290 void max30205_reader_task()
Mahir Ozturk 1:efe9cad8942f 291 {
Mahir Ozturk 1:efe9cad8942f 292 int rc = max30205_config(max30205_temp_sensor); // Configure sensor, return 0 on success
Mahir Ozturk 1:efe9cad8942f 293
Mahir Ozturk 1:efe9cad8942f 294 MAX30205::Configuration_u temp_cfg;
Mahir Ozturk 1:efe9cad8942f 295 uint16_t rawTemperatureRead;
Mahir Ozturk 1:efe9cad8942f 296 float temperature;
Mahir Ozturk 1:efe9cad8942f 297
Mahir Ozturk 1:efe9cad8942f 298 temp_cfg.all = 0;
Mahir Ozturk 1:efe9cad8942f 299
Mahir Ozturk 1:efe9cad8942f 300 daplink.printf("Starting MAX30205 Temperature Demo Application...\r\n");
Mahir Ozturk 1:efe9cad8942f 301
Mahir Ozturk 1:efe9cad8942f 302 while (1) {
Mahir Ozturk 1:efe9cad8942f 303 if (rc == 0) {
Mahir Ozturk 1:efe9cad8942f 304 /* Send one-shot cmd to begin conversion */
Mahir Ozturk 1:efe9cad8942f 305 temp_cfg.bits.one_shot = 1;
Mahir Ozturk 1:efe9cad8942f 306 rc = max30205_temp_sensor.writeConfiguration(temp_cfg);
Mahir Ozturk 1:efe9cad8942f 307
Mahir Ozturk 1:efe9cad8942f 308 Thread::wait(50);
Mahir Ozturk 1:efe9cad8942f 309
Mahir Ozturk 1:efe9cad8942f 310 /* Read the temperature data */
Mahir Ozturk 1:efe9cad8942f 311 rc = max30205_temp_sensor.readTemperature(rawTemperatureRead);
Mahir Ozturk 1:efe9cad8942f 312
Mahir Ozturk 1:efe9cad8942f 313 /* Convert temp data to Celsius */
Mahir Ozturk 1:efe9cad8942f 314 temperature = max30205_temp_sensor.toCelsius(rawTemperatureRead);
Mahir Ozturk 1:efe9cad8942f 315
Mahir Ozturk 1:efe9cad8942f 316 bleGattAttrWrite(gattCharTemp.getValueHandle(), (uint8_t *)&temperature, sizeof(temperature));
Mahir Ozturk 1:efe9cad8942f 317 daplink.printf("Temperature is %2.3f deg. C\r\n", temperature);
Mahir Ozturk 1:efe9cad8942f 318
Mahir Ozturk 2:68ffd74e3b5c 319 Thread::wait(MAX30205_BLE_NOTIFY_PERIOD_SEC * 1000);
Mahir Ozturk 1:efe9cad8942f 320
Mahir Ozturk 1:efe9cad8942f 321 } else {
Mahir Ozturk 1:efe9cad8942f 322 daplink.printf("Something went wrong, check the I2C bus and power connections...\r\n");
Mahir Ozturk 1:efe9cad8942f 323
Mahir Ozturk 2:68ffd74e3b5c 324 return;
Mahir Ozturk 1:efe9cad8942f 325 }
Mahir Ozturk 1:efe9cad8942f 326 }
Mahir Ozturk 1:efe9cad8942f 327 }
Mahir Ozturk 1:efe9cad8942f 328 #endif
Mahir Ozturk 1:efe9cad8942f 329
Mahir Ozturk 1:efe9cad8942f 330 /******************************************************************************
Mahir Ozturk 1:efe9cad8942f 331 ************** MAX30101WING **************************************************
Mahir Ozturk 1:efe9cad8942f 332 ******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 333 #if defined(LIB_MAX30101)
Mahir Ozturk 1:efe9cad8942f 334 #define MAX30101_IRQ_ASSERTED_ID 1
Mahir Ozturk 1:efe9cad8942f 335
Mahir Ozturk 1:efe9cad8942f 336 //variable for the algorithm
Mahir Ozturk 1:efe9cad8942f 337 uint16_t sampleRate =100;
Mahir Ozturk 1:efe9cad8942f 338 uint16_t compSpO2=1;
Mahir Ozturk 1:efe9cad8942f 339 int16_t ir_ac_comp =0;
Mahir Ozturk 1:efe9cad8942f 340 int16_t red_ac_comp=0;
Mahir Ozturk 1:efe9cad8942f 341 int16_t green_ac_comp=0;
Mahir Ozturk 1:efe9cad8942f 342 int16_t ir_ac_mag=0;
Mahir Ozturk 1:efe9cad8942f 343 int16_t red_ac_mag=0;
Mahir Ozturk 1:efe9cad8942f 344 int16_t green_ac_mag=0;
Mahir Ozturk 1:efe9cad8942f 345 uint16_t HRbpm2=0;
Mahir Ozturk 1:efe9cad8942f 346 uint16_t SpO2B=0;
Mahir Ozturk 1:efe9cad8942f 347 uint16_t DRdy=0;
Mahir Ozturk 1:efe9cad8942f 348
Mahir Ozturk 1:efe9cad8942f 349 //declare large variables outside of main
Mahir Ozturk 1:efe9cad8942f 350 uint32_t redData[500];//set array to max fifo size
Mahir Ozturk 1:efe9cad8942f 351 uint32_t irData[500];//set array to max fifo size
Mahir Ozturk 1:efe9cad8942f 352 uint32_t greenData[500];//set array to max fifo size
Mahir Ozturk 1:efe9cad8942f 353
Mahir Ozturk 1:efe9cad8942f 354 Thread thread_max30101_reader;
Mahir Ozturk 1:efe9cad8942f 355
Mahir Ozturk 1:efe9cad8942f 356 bool max30101_config(MAX30101 &op_sensor)
Mahir Ozturk 1:efe9cad8942f 357 {
Mahir Ozturk 1:efe9cad8942f 358
Mahir Ozturk 1:efe9cad8942f 359 //Reset Device
Mahir Ozturk 1:efe9cad8942f 360 MAX30101::ModeConfiguration_u modeConfig;
Mahir Ozturk 1:efe9cad8942f 361 modeConfig.all = 0;
Mahir Ozturk 1:efe9cad8942f 362 modeConfig.bits.reset = 1;
Mahir Ozturk 1:efe9cad8942f 363 modeConfig.bits.mode = MAX30101::MultiLedMode; // Sets SPO2 Mode
Mahir Ozturk 1:efe9cad8942f 364 int32_t rc = op_sensor.setModeConfiguration(modeConfig);
Mahir Ozturk 1:efe9cad8942f 365
Mahir Ozturk 1:efe9cad8942f 366 //enable MAX30101 interrupts
Mahir Ozturk 1:efe9cad8942f 367 MAX30101::InterruptBitField_u ints;
Mahir Ozturk 1:efe9cad8942f 368 if(rc == 0) {
Mahir Ozturk 1:efe9cad8942f 369 ints.all = 0;
Mahir Ozturk 1:efe9cad8942f 370 ints.bits.a_full = 1; // Enable FIFO almost full interrupt
Mahir Ozturk 1:efe9cad8942f 371 ints.bits.ppg_rdy =1; //Enables an interrupt when a new sample is ready
Mahir Ozturk 1:efe9cad8942f 372 rc = op_sensor.enableInterrupts(ints);
Mahir Ozturk 1:efe9cad8942f 373 }
Mahir Ozturk 1:efe9cad8942f 374
Mahir Ozturk 1:efe9cad8942f 375 //configure FIFO
Mahir Ozturk 1:efe9cad8942f 376 MAX30101::FIFO_Configuration_u fifoConfig;
Mahir Ozturk 1:efe9cad8942f 377 if(rc == 0) {
Mahir Ozturk 1:efe9cad8942f 378 fifoConfig.all = 0;
Mahir Ozturk 1:efe9cad8942f 379 fifoConfig.bits.fifo_a_full = 10; // Max level of 17 samples
Mahir Ozturk 1:efe9cad8942f 380 fifoConfig.bits.sample_average = MAX30101::AveragedSamples_0;// Average 0 samples
Mahir Ozturk 1:efe9cad8942f 381 rc = op_sensor.setFIFOConfiguration(fifoConfig);
Mahir Ozturk 1:efe9cad8942f 382 }
Mahir Ozturk 1:efe9cad8942f 383
Mahir Ozturk 1:efe9cad8942f 384 MAX30101::SpO2Configuration_u spo2Config;
Mahir Ozturk 1:efe9cad8942f 385 if(rc == 0) {
Mahir Ozturk 1:efe9cad8942f 386 spo2Config.all = 0; // clears register
Mahir Ozturk 1:efe9cad8942f 387 spo2Config.bits.spo2_adc_range = 1; //sets resolution to 4096 nAfs
Mahir Ozturk 1:efe9cad8942f 388 spo2Config.bits.spo2_sr = MAX30101::SR_100_Hz; // SpO2 SR = 100Hz
Mahir Ozturk 1:efe9cad8942f 389 spo2Config.bits.led_pw = MAX30101::PW_3; // 18-bit ADC resolution ~400us
Mahir Ozturk 1:efe9cad8942f 390 rc = op_sensor.setSpO2Configuration(spo2Config);
Mahir Ozturk 1:efe9cad8942f 391 }
Mahir Ozturk 1:efe9cad8942f 392
Mahir Ozturk 1:efe9cad8942f 393 //Set time slots for LEDS
Mahir Ozturk 1:efe9cad8942f 394 MAX30101::ModeControlReg_u multiLED;
Mahir Ozturk 1:efe9cad8942f 395 if (rc == 0) {
Mahir Ozturk 1:efe9cad8942f 396 //sets timing for control register 1
Mahir Ozturk 1:efe9cad8942f 397 multiLED.bits.lo_slot=1;
Mahir Ozturk 1:efe9cad8942f 398 multiLED.bits.hi_slot=2;
Mahir Ozturk 1:efe9cad8942f 399 rc = op_sensor.setMultiLEDModeControl(MAX30101::ModeControlReg1, multiLED);
Mahir Ozturk 1:efe9cad8942f 400 if (rc == 0) {
Mahir Ozturk 1:efe9cad8942f 401 multiLED.bits.lo_slot=3;
Mahir Ozturk 1:efe9cad8942f 402 multiLED.bits.hi_slot=0;
Mahir Ozturk 1:efe9cad8942f 403 rc = op_sensor.setMultiLEDModeControl(MAX30101::ModeControlReg2, multiLED);
Mahir Ozturk 1:efe9cad8942f 404 }
Mahir Ozturk 1:efe9cad8942f 405 }
Mahir Ozturk 1:efe9cad8942f 406
Mahir Ozturk 1:efe9cad8942f 407 //Set LED drive currents
Mahir Ozturk 1:efe9cad8942f 408 if(rc == 0) {
Mahir Ozturk 1:efe9cad8942f 409 // Heart Rate only, 1 LED channel, Pulse amp. = ~7mA
Mahir Ozturk 1:efe9cad8942f 410 rc = op_sensor.setLEDPulseAmplitude(MAX30101::LED1_PA, 0x24);
Mahir Ozturk 1:efe9cad8942f 411 //To include SPO2, 2 LED channel, Pulse amp. ~7mA
Mahir Ozturk 1:efe9cad8942f 412 if (rc == 0) {
Mahir Ozturk 1:efe9cad8942f 413 rc = op_sensor.setLEDPulseAmplitude(MAX30101::LED2_PA, 0x24);
Mahir Ozturk 1:efe9cad8942f 414 }
Mahir Ozturk 1:efe9cad8942f 415 if (rc == 0) {
Mahir Ozturk 1:efe9cad8942f 416 rc = op_sensor.setLEDPulseAmplitude(MAX30101::LED3_PA, 0x24);
Mahir Ozturk 1:efe9cad8942f 417 }
Mahir Ozturk 1:efe9cad8942f 418
Mahir Ozturk 1:efe9cad8942f 419 }
Mahir Ozturk 1:efe9cad8942f 420
Mahir Ozturk 1:efe9cad8942f 421 //Set operating mode
Mahir Ozturk 1:efe9cad8942f 422 modeConfig.all = 0;
Mahir Ozturk 1:efe9cad8942f 423 if(rc == 0) {
Mahir Ozturk 1:efe9cad8942f 424 modeConfig.bits.mode = MAX30101::MultiLedMode; // Sets multiLED mode
Mahir Ozturk 1:efe9cad8942f 425 rc = op_sensor.setModeConfiguration(modeConfig);
Mahir Ozturk 1:efe9cad8942f 426 }
Mahir Ozturk 1:efe9cad8942f 427
Mahir Ozturk 1:efe9cad8942f 428
Mahir Ozturk 1:efe9cad8942f 429 return rc;
Mahir Ozturk 1:efe9cad8942f 430 }
Mahir Ozturk 1:efe9cad8942f 431
Mahir Ozturk 1:efe9cad8942f 432 void max30101wing_pmic_config(I2C & i2c_bus, DigitalOut & pmic_en)
Mahir Ozturk 1:efe9cad8942f 433 {
Mahir Ozturk 1:efe9cad8942f 434
Mahir Ozturk 1:efe9cad8942f 435 const uint8_t PMIC_ADRS = 0x54;
Mahir Ozturk 1:efe9cad8942f 436 const uint8_t BBB_EXTRA_ADRS = 0x1C;
Mahir Ozturk 1:efe9cad8942f 437 const uint8_t BOOST_VOLTAGE = 0x05;
Mahir Ozturk 1:efe9cad8942f 438
Mahir Ozturk 1:efe9cad8942f 439 char data_buff[] = {BBB_EXTRA_ADRS, 0x40}; //BBBExtra register address
Mahir Ozturk 1:efe9cad8942f 440 //and data to enable passive
Mahir Ozturk 1:efe9cad8942f 441 //pull down.
Mahir Ozturk 1:efe9cad8942f 442 i2c_bus.write(PMIC_ADRS, data_buff,2); //write to BBBExtra register
Mahir Ozturk 1:efe9cad8942f 443
Mahir Ozturk 1:efe9cad8942f 444 data_buff[0] = BOOST_VOLTAGE;
Mahir Ozturk 1:efe9cad8942f 445 data_buff[1] = 0x08; //Boost voltage configuration
Mahir Ozturk 1:efe9cad8942f 446 //register followed by data
Mahir Ozturk 1:efe9cad8942f 447 //to set voltage to 4.5V 1f
Mahir Ozturk 1:efe9cad8942f 448 pmic_en = 0; //disables VLED 08
Mahir Ozturk 1:efe9cad8942f 449 i2c_bus.write(PMIC_ADRS, data_buff,2); //write to BBBExtra register
Mahir Ozturk 1:efe9cad8942f 450 pmic_en = 1; //enables VLED
Mahir Ozturk 1:efe9cad8942f 451 }
Mahir Ozturk 1:efe9cad8942f 452
Mahir Ozturk 1:efe9cad8942f 453 /* Op Sensor FIFO nearly full callback */
Mahir Ozturk 1:efe9cad8942f 454 void max30101_intr_callback()
Mahir Ozturk 1:efe9cad8942f 455 {
Mahir Ozturk 1:efe9cad8942f 456 thread_max30101_reader.signal_set(MAX30101_IRQ_ASSERTED_ID);
Mahir Ozturk 1:efe9cad8942f 457 }
Mahir Ozturk 1:efe9cad8942f 458
Mahir Ozturk 1:efe9cad8942f 459 void max30101_reader_task()
Mahir Ozturk 1:efe9cad8942f 460 {
Mahir Ozturk 1:efe9cad8942f 461 InterruptIn op_sensor_int(P3_2); // Config P3_2 as int. in for
Mahir Ozturk 1:efe9cad8942f 462 op_sensor_int.fall(max30101_intr_callback); // FIFO ready interrupt
Mahir Ozturk 1:efe9cad8942f 463
Mahir Ozturk 1:efe9cad8942f 464 DigitalOut VLED_EN(P3_3,0); //Enable for VLEDs
Mahir Ozturk 1:efe9cad8942f 465 max30101wing_pmic_config(i2c1, VLED_EN);
Mahir Ozturk 1:efe9cad8942f 466
Mahir Ozturk 1:efe9cad8942f 467 MAX30101 op_sensor(i2c1); // Create new MAX30101 on i2cBus
Mahir Ozturk 1:efe9cad8942f 468 int rc = max30101_config(op_sensor); // Config sensor, return 0 on success
Mahir Ozturk 1:efe9cad8942f 469
Mahir Ozturk 1:efe9cad8942f 470 MAX30101::InterruptBitField_u ints; // Read interrupt status to clear
Mahir Ozturk 1:efe9cad8942f 471 rc = op_sensor.getInterruptStatus(ints); // power on interrupt
Mahir Ozturk 1:efe9cad8942f 472
Mahir Ozturk 1:efe9cad8942f 473 uint8_t fifoData[MAX30101::MAX_FIFO_BYTES];
Mahir Ozturk 1:efe9cad8942f 474 uint16_t idx, readBytes;
Mahir Ozturk 1:efe9cad8942f 475 int32_t opSample;
Mahir Ozturk 1:efe9cad8942f 476 uint32_t sample;
Mahir Ozturk 1:efe9cad8942f 477 uint16_t HRTemp;
Mahir Ozturk 1:efe9cad8942f 478 uint16_t spo2Temp;
Mahir Ozturk 1:efe9cad8942f 479
Mahir Ozturk 2:68ffd74e3b5c 480 uint16_t lastValidHR = 0;
Mahir Ozturk 2:68ffd74e3b5c 481 uint16_t lastValidSPO2 = 0;
Mahir Ozturk 2:68ffd74e3b5c 482
Mahir Ozturk 1:efe9cad8942f 483 int r=0; //counter for redData position
Mahir Ozturk 1:efe9cad8942f 484 int ir=0; //counter for irData position
Mahir Ozturk 1:efe9cad8942f 485 int g =0; //counter for greenData position
Mahir Ozturk 1:efe9cad8942f 486 int c=0; //counter to print values
Mahir Ozturk 1:efe9cad8942f 487
Mahir Ozturk 1:efe9cad8942f 488 daplink.printf("Starting MAX30101 HeartRate / SPO2 Demo Application...\r\n");
Mahir Ozturk 1:efe9cad8942f 489 daplink.printf("Please wait a few seconds while data is being collected.\r\n");
Mahir Ozturk 1:efe9cad8942f 490
Mahir Ozturk 2:68ffd74e3b5c 491 Timer bleNotifyTimer;
Mahir Ozturk 2:68ffd74e3b5c 492
Mahir Ozturk 2:68ffd74e3b5c 493 bleNotifyTimer.start();
Mahir Ozturk 2:68ffd74e3b5c 494
Mahir Ozturk 1:efe9cad8942f 495 while (1) {
Mahir Ozturk 1:efe9cad8942f 496 if (rc == 0) {
Mahir Ozturk 1:efe9cad8942f 497 /* Check if op_sensor interrupt asserted */
Mahir Ozturk 1:efe9cad8942f 498 Thread::signal_wait(MAX30101_IRQ_ASSERTED_ID);
Mahir Ozturk 1:efe9cad8942f 499
Mahir Ozturk 1:efe9cad8942f 500 /* Read interrupt status to clear interrupt */
Mahir Ozturk 1:efe9cad8942f 501 rc = op_sensor.getInterruptStatus(ints);
Mahir Ozturk 1:efe9cad8942f 502
Mahir Ozturk 1:efe9cad8942f 503 /* Confirms proper read prior to executing */
Mahir Ozturk 1:efe9cad8942f 504 if (rc == 0) {
Mahir Ozturk 1:efe9cad8942f 505 // Read FIFO
Mahir Ozturk 1:efe9cad8942f 506 rc = op_sensor.readFIFO(MAX30101::ThreeLedChannels, fifoData, readBytes);
Mahir Ozturk 1:efe9cad8942f 507
Mahir Ozturk 1:efe9cad8942f 508 if (rc == 0) {
Mahir Ozturk 1:efe9cad8942f 509 /* Convert read bytes into samples */
Mahir Ozturk 1:efe9cad8942f 510 for (idx = 0; idx < readBytes; idx+=9) {
Mahir Ozturk 1:efe9cad8942f 511 if (r >= 500 || ir >= 500 || g >= 500) {
Mahir Ozturk 6:aeb5a4c194c3 512 daplink.printf("Overflow! r=%d ir=%d g=%d\r\n", r, ir, g);
Mahir Ozturk 6:aeb5a4c194c3 513 break;
Mahir Ozturk 1:efe9cad8942f 514 }
Mahir Ozturk 1:efe9cad8942f 515
Mahir Ozturk 1:efe9cad8942f 516 if (readBytes >= (idx + 8)) {
Mahir Ozturk 6:aeb5a4c194c3 517 redData[r++] = ((fifoData[idx] << 16) | (fifoData[idx + 1] << 8) | (fifoData[idx + 2])) & 0x03FFFF;
Mahir Ozturk 6:aeb5a4c194c3 518 irData[ir++] = ((fifoData[idx + 3] << 16) | (fifoData[idx + 4] << 8) | (fifoData[idx + 5])) & 0x03FFFF;
Mahir Ozturk 1:efe9cad8942f 519 greenData[g++] = ((fifoData[idx + 6] << 16) | (fifoData[idx + 7] << 8) | (fifoData[idx + 8])) & 0x03FFFF;
Mahir Ozturk 1:efe9cad8942f 520 }
Mahir Ozturk 1:efe9cad8942f 521 }
Mahir Ozturk 1:efe9cad8942f 522
Mahir Ozturk 1:efe9cad8942f 523 if ((r >= 500) && (ir >= 500) && (g >= 500)) {/* checks to make sure there are 500 */
Mahir Ozturk 1:efe9cad8942f 524 /* samples in data buffers */
Mahir Ozturk 1:efe9cad8942f 525
Mahir Ozturk 1:efe9cad8942f 526 /* runs the heart rate and SpO2 algorithm */
Mahir Ozturk 1:efe9cad8942f 527 for (c = 0, HRTemp = 0; c < r; c++) {
Mahir Ozturk 1:efe9cad8942f 528 HRSpO2Func(irData[c], redData[c],greenData[c], c,sampleRate, compSpO2,
Mahir Ozturk 1:efe9cad8942f 529 &ir_ac_comp,&red_ac_comp, &green_ac_comp, &ir_ac_mag,&red_ac_mag,
Mahir Ozturk 1:efe9cad8942f 530 &green_ac_mag, &HRbpm2,&SpO2B,&DRdy);
Mahir Ozturk 1:efe9cad8942f 531 if (DRdy) {
Mahir Ozturk 1:efe9cad8942f 532 HRTemp = HRbpm2;
Mahir Ozturk 1:efe9cad8942f 533 spo2Temp = SpO2B;
Mahir Ozturk 1:efe9cad8942f 534 }
Mahir Ozturk 1:efe9cad8942f 535 }
Mahir Ozturk 1:efe9cad8942f 536
Mahir Ozturk 1:efe9cad8942f 537 /* If the above algorithm returns a valid heart rate on the last sample, it is printed */
Mahir Ozturk 1:efe9cad8942f 538 if (DRdy == 1) {
Mahir Ozturk 1:efe9cad8942f 539 daplink.printf("Heart Rate = %i\r\n",HRbpm2);
Mahir Ozturk 1:efe9cad8942f 540 daplink.printf("SPO2 = %i\r\n",SpO2B);
Mahir Ozturk 2:68ffd74e3b5c 541 lastValidHR = HRbpm2;
Mahir Ozturk 2:68ffd74e3b5c 542 lastValidSPO2 = SpO2B;
Mahir Ozturk 1:efe9cad8942f 543 } else if (HRTemp != 0) { /* if a valid heart was calculated at all, it is printed */
Mahir Ozturk 1:efe9cad8942f 544 daplink.printf("Heart Rate = %i\r\n",HRTemp);
Mahir Ozturk 1:efe9cad8942f 545 daplink.printf("SPO2 = %i\r\n",spo2Temp);
Mahir Ozturk 2:68ffd74e3b5c 546 lastValidHR = HRTemp;
Mahir Ozturk 2:68ffd74e3b5c 547 lastValidSPO2 = spo2Temp;
Mahir Ozturk 1:efe9cad8942f 548 } else {
Mahir Ozturk 1:efe9cad8942f 549 daplink.printf("Calculation failed...waiting for more samples...\r\n");
Mahir Ozturk 1:efe9cad8942f 550 daplink.printf("Please keep your finger on the MAX30101 sensor with minimal movement.\r\n");
Mahir Ozturk 1:efe9cad8942f 551 }
Mahir Ozturk 1:efe9cad8942f 552
Mahir Ozturk 1:efe9cad8942f 553 /* dump the first hundred samples after calculation */
Mahir Ozturk 1:efe9cad8942f 554 for (c = 100; c < 500; c++) {
Mahir Ozturk 1:efe9cad8942f 555 redData[c - 100] = redData[c];
Mahir Ozturk 1:efe9cad8942f 556 irData[c - 100] = irData[c];
Mahir Ozturk 1:efe9cad8942f 557 greenData[c - 100] = greenData[c];
Mahir Ozturk 1:efe9cad8942f 558 }
Mahir Ozturk 1:efe9cad8942f 559
Mahir Ozturk 1:efe9cad8942f 560 /* reset counters */
Mahir Ozturk 1:efe9cad8942f 561 r = 400;
Mahir Ozturk 1:efe9cad8942f 562 ir = 400;
Mahir Ozturk 1:efe9cad8942f 563 g = 400;
Mahir Ozturk 1:efe9cad8942f 564 }
Mahir Ozturk 2:68ffd74e3b5c 565
Mahir Ozturk 2:68ffd74e3b5c 566 if (bleNotifyTimer.read_ms() >= (MAX30101_BLE_NOTIFY_PERIOD_SEC * 1000)) {
Mahir Ozturk 2:68ffd74e3b5c 567 bleGattAttrWrite(gattCharHeartRate.getValueHandle(), (uint8_t *)&lastValidHR, sizeof(lastValidHR));
Mahir Ozturk 2:68ffd74e3b5c 568 bleGattAttrWrite(gattCharSPO2.getValueHandle(), (uint8_t *)&lastValidSPO2, sizeof(lastValidSPO2));
Mahir Ozturk 2:68ffd74e3b5c 569 bleNotifyTimer.reset();
Mahir Ozturk 2:68ffd74e3b5c 570 }
Mahir Ozturk 1:efe9cad8942f 571 }
Mahir Ozturk 1:efe9cad8942f 572 }
Mahir Ozturk 1:efe9cad8942f 573 } else { // If rc != 0, a communication error has occurred
Mahir Ozturk 1:efe9cad8942f 574
Mahir Ozturk 1:efe9cad8942f 575 daplink.printf("Something went wrong, "
Mahir Ozturk 1:efe9cad8942f 576 "check the I2C bus or power connections... \r\n");
Mahir Ozturk 1:efe9cad8942f 577
Mahir Ozturk 2:68ffd74e3b5c 578 return;
Mahir Ozturk 1:efe9cad8942f 579 }
Mahir Ozturk 1:efe9cad8942f 580
Mahir Ozturk 1:efe9cad8942f 581 }
Mahir Ozturk 1:efe9cad8942f 582 }
Mahir Ozturk 1:efe9cad8942f 583 #endif
Mahir Ozturk 1:efe9cad8942f 584
Mahir Ozturk 1:efe9cad8942f 585 /******************************************************************************
Mahir Ozturk 1:efe9cad8942f 586 ************** MAX30003WING (ECG) *********************************************
Mahir Ozturk 1:efe9cad8942f 587 ******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 588 #if defined(LIB_MAX30003_ECG)
Mahir Ozturk 1:efe9cad8942f 589 #define MAX30003_IRQ_ASSERTED_SIGNAL_ID 1
Mahir Ozturk 1:efe9cad8942f 590
Mahir Ozturk 1:efe9cad8942f 591 MAX30003 max30003(spim2, SPI2_SS); /* MAX30003WING board */
Mahir Ozturk 1:efe9cad8942f 592
Mahir Ozturk 1:efe9cad8942f 593 Thread thread_max30003_reader;
Mahir Ozturk 1:efe9cad8942f 594
Mahir Ozturk 1:efe9cad8942f 595 void ecg_config(MAX30003& ecgAFE) {
Mahir Ozturk 1:efe9cad8942f 596
Mahir Ozturk 1:efe9cad8942f 597 // Reset ECG to clear registers
Mahir Ozturk 1:efe9cad8942f 598 ecgAFE.writeRegister( MAX30003::SW_RST , 0);
Mahir Ozturk 1:efe9cad8942f 599
Mahir Ozturk 1:efe9cad8942f 600 // General config register setting
Mahir Ozturk 1:efe9cad8942f 601 MAX30003::GeneralConfiguration_u CNFG_GEN_r;
Mahir Ozturk 1:efe9cad8942f 602 CNFG_GEN_r.bits.en_ecg = 1; // Enable ECG channel
Mahir Ozturk 1:efe9cad8942f 603 CNFG_GEN_r.bits.rbiasn = 1; // Enable resistive bias on negative input
Mahir Ozturk 1:efe9cad8942f 604 CNFG_GEN_r.bits.rbiasp = 1; // Enable resistive bias on positive input
Mahir Ozturk 1:efe9cad8942f 605 CNFG_GEN_r.bits.en_rbias = 1; // Enable resistive bias
Mahir Ozturk 1:efe9cad8942f 606 CNFG_GEN_r.bits.imag = 2; // Current magnitude = 10nA
Mahir Ozturk 1:efe9cad8942f 607 CNFG_GEN_r.bits.en_dcloff = 1; // Enable DC lead-off detection
Mahir Ozturk 1:efe9cad8942f 608 ecgAFE.writeRegister( MAX30003::CNFG_GEN , CNFG_GEN_r.all);
Mahir Ozturk 1:efe9cad8942f 609
Mahir Ozturk 1:efe9cad8942f 610
Mahir Ozturk 1:efe9cad8942f 611 // ECG Config register setting
Mahir Ozturk 1:efe9cad8942f 612 MAX30003::ECGConfiguration_u CNFG_ECG_r;
Mahir Ozturk 1:efe9cad8942f 613 CNFG_ECG_r.bits.dlpf = 1; // Digital LPF cutoff = 40Hz
Mahir Ozturk 1:efe9cad8942f 614 CNFG_ECG_r.bits.dhpf = 1; // Digital HPF cutoff = 0.5Hz
Mahir Ozturk 1:efe9cad8942f 615 CNFG_ECG_r.bits.gain = 3; // ECG gain = 160V/V
Mahir Ozturk 1:efe9cad8942f 616 CNFG_ECG_r.bits.rate = 2; // Sample rate = 128 sps
Mahir Ozturk 1:efe9cad8942f 617 ecgAFE.writeRegister( MAX30003::CNFG_ECG , CNFG_ECG_r.all);
Mahir Ozturk 1:efe9cad8942f 618
Mahir Ozturk 1:efe9cad8942f 619
Mahir Ozturk 1:efe9cad8942f 620 //R-to-R configuration
Mahir Ozturk 1:efe9cad8942f 621 MAX30003::RtoR1Configuration_u CNFG_RTOR_r;
Mahir Ozturk 1:efe9cad8942f 622 CNFG_RTOR_r.bits.en_rtor = 1; // Enable R-to-R detection
Mahir Ozturk 1:efe9cad8942f 623 ecgAFE.writeRegister( MAX30003::CNFG_RTOR1 , CNFG_RTOR_r.all);
Mahir Ozturk 1:efe9cad8942f 624
Mahir Ozturk 1:efe9cad8942f 625
Mahir Ozturk 1:efe9cad8942f 626 //Manage interrupts register setting
Mahir Ozturk 1:efe9cad8942f 627 MAX30003::ManageInterrupts_u MNG_INT_r;
Mahir Ozturk 1:efe9cad8942f 628 MNG_INT_r.bits.efit = 0b00011; // Assert EINT w/ 4 unread samples
Mahir Ozturk 1:efe9cad8942f 629 MNG_INT_r.bits.clr_rrint = 0b01; // Clear R-to-R on RTOR reg. read back
Mahir Ozturk 1:efe9cad8942f 630 ecgAFE.writeRegister( MAX30003::MNGR_INT , MNG_INT_r.all);
Mahir Ozturk 1:efe9cad8942f 631
Mahir Ozturk 1:efe9cad8942f 632
Mahir Ozturk 1:efe9cad8942f 633 //Enable interrupts register setting
Mahir Ozturk 1:efe9cad8942f 634 MAX30003::EnableInterrupts_u EN_INT_r;
Mahir Ozturk 1:efe9cad8942f 635 EN_INT_r.all = 0;
Mahir Ozturk 1:efe9cad8942f 636 EN_INT_r.bits.en_eint = 1; // Enable EINT interrupt
Mahir Ozturk 1:efe9cad8942f 637 EN_INT_r.bits.en_rrint = 0; // Disable R-to-R interrupt
Mahir Ozturk 1:efe9cad8942f 638 EN_INT_r.bits.intb_type = 3; // Open-drain NMOS with internal pullup
Mahir Ozturk 1:efe9cad8942f 639 ecgAFE.writeRegister( MAX30003::EN_INT , EN_INT_r.all);
Mahir Ozturk 1:efe9cad8942f 640
Mahir Ozturk 1:efe9cad8942f 641
Mahir Ozturk 1:efe9cad8942f 642 //Dyanmic modes config
Mahir Ozturk 1:efe9cad8942f 643 MAX30003::ManageDynamicModes_u MNG_DYN_r;
Mahir Ozturk 1:efe9cad8942f 644 MNG_DYN_r.bits.fast = 0; // Fast recovery mode disabled
Mahir Ozturk 1:efe9cad8942f 645 ecgAFE.writeRegister( MAX30003::MNGR_DYN , MNG_DYN_r.all);
Mahir Ozturk 1:efe9cad8942f 646
Mahir Ozturk 1:efe9cad8942f 647 // MUX Config
Mahir Ozturk 1:efe9cad8942f 648 MAX30003::MuxConfiguration_u CNFG_MUX_r;
Mahir Ozturk 1:efe9cad8942f 649 CNFG_MUX_r.bits.openn = 0; // Connect ECGN to AFE channel
Mahir Ozturk 1:efe9cad8942f 650 CNFG_MUX_r.bits.openp = 0; // Connect ECGP to AFE channel
Mahir Ozturk 1:efe9cad8942f 651 ecgAFE.writeRegister( MAX30003::CNFG_EMUX , CNFG_MUX_r.all);
Mahir Ozturk 1:efe9cad8942f 652
Mahir Ozturk 1:efe9cad8942f 653 return;
Mahir Ozturk 1:efe9cad8942f 654 }
Mahir Ozturk 1:efe9cad8942f 655
Mahir Ozturk 1:efe9cad8942f 656 /* ECG FIFO nearly full callback */
Mahir Ozturk 1:efe9cad8942f 657 //volatile bool ecgFIFOIntFlag = 0;
Mahir Ozturk 1:efe9cad8942f 658 void ecgFIFO_callback() {
Mahir Ozturk 1:efe9cad8942f 659
Mahir Ozturk 1:efe9cad8942f 660 thread_max30003_reader.signal_set(MAX30003_IRQ_ASSERTED_SIGNAL_ID);
Mahir Ozturk 1:efe9cad8942f 661 //ecgFIFOIntFlag = 1;
Mahir Ozturk 1:efe9cad8942f 662
Mahir Ozturk 1:efe9cad8942f 663 }
Mahir Ozturk 1:efe9cad8942f 664
Mahir Ozturk 1:efe9cad8942f 665 void max30003_reader_task()
Mahir Ozturk 1:efe9cad8942f 666 {
Mahir Ozturk 1:efe9cad8942f 667 // Constants
Mahir Ozturk 1:efe9cad8942f 668 const int EINT_STATUS_MASK = 1 << 23;
Mahir Ozturk 1:efe9cad8942f 669 const int FIFO_OVF_MASK = 0x7;
Mahir Ozturk 1:efe9cad8942f 670 const int FIFO_VALID_SAMPLE_MASK = 0x0;
Mahir Ozturk 1:efe9cad8942f 671 const int FIFO_FAST_SAMPLE_MASK = 0x1;
Mahir Ozturk 1:efe9cad8942f 672 const int ETAG_BITS_MASK = 0x7;
Mahir Ozturk 1:efe9cad8942f 673
Mahir Ozturk 1:efe9cad8942f 674 InterruptIn ecgFIFO_int(P5_4); // Config P5_4 as int. in for the
Mahir Ozturk 1:efe9cad8942f 675 ecgFIFO_int.fall(&ecgFIFO_callback); // ecg FIFO almost full interrupt
Mahir Ozturk 1:efe9cad8942f 676
Mahir Ozturk 1:efe9cad8942f 677 SPI spiBus(SPI2_MOSI, SPI2_MISO, SPI2_SCK); // SPI bus, P5_1 = MOSI,
Mahir Ozturk 1:efe9cad8942f 678 // P5_2 = MISO, P5_0 = SCK
Mahir Ozturk 1:efe9cad8942f 679
Mahir Ozturk 1:efe9cad8942f 680 MAX30003 ecgAFE(spiBus, P5_3); // New MAX30003 on spiBus, CS = P5_3
Mahir Ozturk 1:efe9cad8942f 681 ecg_config(ecgAFE); // Config ECG
Mahir Ozturk 1:efe9cad8942f 682
Mahir Ozturk 1:efe9cad8942f 683
Mahir Ozturk 1:efe9cad8942f 684 ecgAFE.writeRegister( MAX30003::SYNCH , 0);
Mahir Ozturk 1:efe9cad8942f 685
Mahir Ozturk 1:efe9cad8942f 686 uint32_t ecgFIFO, readECGSamples, idx, ETAG[32], status;
Mahir Ozturk 1:efe9cad8942f 687 int16_t ecgSample[32];
Mahir Ozturk 1:efe9cad8942f 688
Mahir Ozturk 1:efe9cad8942f 689 daplink.printf("Starting MAX30003 ECG Demo Application...\r\n");
Mahir Ozturk 1:efe9cad8942f 690
Mahir Ozturk 1:efe9cad8942f 691 while (1) {
Mahir Ozturk 1:efe9cad8942f 692
Mahir Ozturk 1:efe9cad8942f 693 // Read back ECG samples from the FIFO
Mahir Ozturk 1:efe9cad8942f 694 thread_max30003_reader.signal_wait(MAX30003_IRQ_ASSERTED_SIGNAL_ID);
Mahir Ozturk 1:efe9cad8942f 695
Mahir Ozturk 1:efe9cad8942f 696 status = ecgAFE.readRegister( MAX30003::STATUS ); // Read the STATUS register
Mahir Ozturk 1:efe9cad8942f 697
Mahir Ozturk 1:efe9cad8942f 698 // Check if EINT interrupt asserted
Mahir Ozturk 1:efe9cad8942f 699 if ( ( status & EINT_STATUS_MASK ) == EINT_STATUS_MASK ) {
Mahir Ozturk 1:efe9cad8942f 700
Mahir Ozturk 1:efe9cad8942f 701 readECGSamples = 0; // Reset sample counter
Mahir Ozturk 1:efe9cad8942f 702
Mahir Ozturk 1:efe9cad8942f 703 do {
Mahir Ozturk 1:efe9cad8942f 704 ecgFIFO = ecgAFE.readRegister( MAX30003::ECG_FIFO ); // Read FIFO
Mahir Ozturk 1:efe9cad8942f 705 ecgSample[readECGSamples] = ecgFIFO >> 8; // Isolate voltage data
Mahir Ozturk 1:efe9cad8942f 706 ETAG[readECGSamples] = ( ecgFIFO >> 3 ) & ETAG_BITS_MASK; // Isolate ETAG
Mahir Ozturk 1:efe9cad8942f 707 readECGSamples++; // Increment sample counter
Mahir Ozturk 1:efe9cad8942f 708
Mahir Ozturk 1:efe9cad8942f 709 // Check that sample is not last sample in FIFO
Mahir Ozturk 1:efe9cad8942f 710 } while ( ETAG[readECGSamples-1] == FIFO_VALID_SAMPLE_MASK ||
Mahir Ozturk 1:efe9cad8942f 711 ETAG[readECGSamples-1] == FIFO_FAST_SAMPLE_MASK );
Mahir Ozturk 1:efe9cad8942f 712
Mahir Ozturk 1:efe9cad8942f 713 // Check if FIFO has overflowed
Mahir Ozturk 1:efe9cad8942f 714 if( ETAG[readECGSamples - 1] == FIFO_OVF_MASK ){
Mahir Ozturk 1:efe9cad8942f 715 ecgAFE.writeRegister( MAX30003::FIFO_RST , 0); // Reset FIFO
Mahir Ozturk 1:efe9cad8942f 716 rLED = 1;//notifies the user that an over flow occured
Mahir Ozturk 1:efe9cad8942f 717 }
Mahir Ozturk 1:efe9cad8942f 718
Mahir Ozturk 1:efe9cad8942f 719 // Print results
Mahir Ozturk 1:efe9cad8942f 720 for( idx = 0; idx < readECGSamples; idx++ ) {
Mahir Ozturk 1:efe9cad8942f 721 daplink.printf("%6d\r\n", ecgSample[idx]);
Mahir Ozturk 1:efe9cad8942f 722
Mahir Ozturk 1:efe9cad8942f 723 bleGattAttrWrite(gattCharECG.getValueHandle(),
Mahir Ozturk 1:efe9cad8942f 724 (uint8_t *)&ecgSample[idx], sizeof(ecgSample[idx]));
Mahir Ozturk 1:efe9cad8942f 725 }
Mahir Ozturk 1:efe9cad8942f 726 }
Mahir Ozturk 1:efe9cad8942f 727 }
Mahir Ozturk 1:efe9cad8942f 728 }
Mahir Ozturk 1:efe9cad8942f 729
Mahir Ozturk 1:efe9cad8942f 730 #endif
Mahir Ozturk 1:efe9cad8942f 731
Mahir Ozturk 1:efe9cad8942f 732 /******************************************************************************
Mahir Ozturk 1:efe9cad8942f 733 ************** MAX30003WING (BPM) *********************************************
Mahir Ozturk 1:efe9cad8942f 734 *******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 735 #if defined(LIB_MAX30003)
Mahir Ozturk 1:efe9cad8942f 736
Mahir Ozturk 1:efe9cad8942f 737 #define MAX30003_IRQ_ASSERTED_SIGNAL_ID 1
Mahir Ozturk 1:efe9cad8942f 738
Mahir Ozturk 1:efe9cad8942f 739 MAX30003 max30003(spim2, SPI2_SS); /* MAX30003WING board */
Mahir Ozturk 1:efe9cad8942f 740
Mahir Ozturk 1:efe9cad8942f 741 Thread thread_max30003_reader;
Mahir Ozturk 1:efe9cad8942f 742
Mahir Ozturk 1:efe9cad8942f 743 /* ECG FIFO nearly full callback */
Mahir Ozturk 1:efe9cad8942f 744 void ecgFIFO_callback()
Mahir Ozturk 1:efe9cad8942f 745 {
Mahir Ozturk 1:efe9cad8942f 746 thread_max30003_reader.signal_set(MAX30003_IRQ_ASSERTED_SIGNAL_ID);
Mahir Ozturk 1:efe9cad8942f 747 }
Mahir Ozturk 1:efe9cad8942f 748
Mahir Ozturk 1:efe9cad8942f 749 void ecg_config(MAX30003& ecgAFE)
Mahir Ozturk 1:efe9cad8942f 750 {
Mahir Ozturk 1:efe9cad8942f 751 // Reset ECG to clear registers
Mahir Ozturk 1:efe9cad8942f 752 ecgAFE.writeRegister( MAX30003::SW_RST , 0);
Mahir Ozturk 1:efe9cad8942f 753
Mahir Ozturk 1:efe9cad8942f 754 // General config register setting
Mahir Ozturk 1:efe9cad8942f 755 MAX30003::GeneralConfiguration_u CNFG_GEN_r;
Mahir Ozturk 1:efe9cad8942f 756 CNFG_GEN_r.bits.en_ecg = 1; // Enable ECG channel
Mahir Ozturk 1:efe9cad8942f 757 CNFG_GEN_r.bits.rbiasn = 1; // Enable resistive bias on negative input
Mahir Ozturk 1:efe9cad8942f 758 CNFG_GEN_r.bits.rbiasp = 1; // Enable resistive bias on positive input
Mahir Ozturk 1:efe9cad8942f 759 CNFG_GEN_r.bits.en_rbias = 1; // Enable resistive bias
Mahir Ozturk 1:efe9cad8942f 760 CNFG_GEN_r.bits.imag = 2; // Current magnitude = 10nA
Mahir Ozturk 1:efe9cad8942f 761 CNFG_GEN_r.bits.en_dcloff = 1; // Enable DC lead-off detection
Mahir Ozturk 1:efe9cad8942f 762 ecgAFE.writeRegister( MAX30003::CNFG_GEN , CNFG_GEN_r.all);
Mahir Ozturk 1:efe9cad8942f 763
Mahir Ozturk 1:efe9cad8942f 764
Mahir Ozturk 1:efe9cad8942f 765 // ECG Config register setting
Mahir Ozturk 1:efe9cad8942f 766 MAX30003::ECGConfiguration_u CNFG_ECG_r;
Mahir Ozturk 1:efe9cad8942f 767 CNFG_ECG_r.bits.dlpf = 1; // Digital LPF cutoff = 40Hz
Mahir Ozturk 1:efe9cad8942f 768 CNFG_ECG_r.bits.dhpf = 1; // Digital HPF cutoff = 0.5Hz
Mahir Ozturk 1:efe9cad8942f 769 CNFG_ECG_r.bits.gain = 3; // ECG gain = 160V/V
Mahir Ozturk 1:efe9cad8942f 770 CNFG_ECG_r.bits.rate = 2; // Sample rate = 128 sps
Mahir Ozturk 1:efe9cad8942f 771 ecgAFE.writeRegister( MAX30003::CNFG_ECG , CNFG_ECG_r.all);
Mahir Ozturk 1:efe9cad8942f 772
Mahir Ozturk 1:efe9cad8942f 773
Mahir Ozturk 1:efe9cad8942f 774 //R-to-R configuration
Mahir Ozturk 1:efe9cad8942f 775 MAX30003::RtoR1Configuration_u CNFG_RTOR_r;
Mahir Ozturk 1:efe9cad8942f 776 CNFG_RTOR_r.bits.wndw = 0b0011; // WNDW = 96ms
Mahir Ozturk 1:efe9cad8942f 777 CNFG_RTOR_r.bits.rgain = 0b1111; // Auto-scale gain
Mahir Ozturk 1:efe9cad8942f 778 CNFG_RTOR_r.bits.pavg = 0b11; // 16-average
Mahir Ozturk 1:efe9cad8942f 779 CNFG_RTOR_r.bits.ptsf = 0b0011; // PTSF = 4/16
Mahir Ozturk 1:efe9cad8942f 780 CNFG_RTOR_r.bits.en_rtor = 1; // Enable R-to-R detection
Mahir Ozturk 1:efe9cad8942f 781 ecgAFE.writeRegister( MAX30003::CNFG_RTOR1 , CNFG_RTOR_r.all);
Mahir Ozturk 1:efe9cad8942f 782
Mahir Ozturk 1:efe9cad8942f 783
Mahir Ozturk 1:efe9cad8942f 784 //Manage interrupts register setting
Mahir Ozturk 1:efe9cad8942f 785 MAX30003::ManageInterrupts_u MNG_INT_r;
Mahir Ozturk 1:efe9cad8942f 786 MNG_INT_r.bits.efit = 0b00011; // Assert EINT w/ 4 unread samples
Mahir Ozturk 1:efe9cad8942f 787 MNG_INT_r.bits.clr_rrint = 0b01; // Clear R-to-R on RTOR reg. read back
Mahir Ozturk 1:efe9cad8942f 788 ecgAFE.writeRegister( MAX30003::MNGR_INT , MNG_INT_r.all);
Mahir Ozturk 1:efe9cad8942f 789
Mahir Ozturk 1:efe9cad8942f 790
Mahir Ozturk 1:efe9cad8942f 791 //Enable interrupts register setting
Mahir Ozturk 1:efe9cad8942f 792 MAX30003::EnableInterrupts_u EN_INT_r;
Mahir Ozturk 1:efe9cad8942f 793 EN_INT_r.bits.en_eint = 1; // Enable EINT interrupt
Mahir Ozturk 1:efe9cad8942f 794 EN_INT_r.bits.en_rrint = 1; // Enable R-to-R interrupt
Mahir Ozturk 1:efe9cad8942f 795 EN_INT_r.bits.intb_type = 3; // Open-drain NMOS with internal pullup
Mahir Ozturk 1:efe9cad8942f 796 ecgAFE.writeRegister( MAX30003::EN_INT , EN_INT_r.all);
Mahir Ozturk 1:efe9cad8942f 797
Mahir Ozturk 1:efe9cad8942f 798
Mahir Ozturk 1:efe9cad8942f 799 //Dyanmic modes config
Mahir Ozturk 1:efe9cad8942f 800 MAX30003::ManageDynamicModes_u MNG_DYN_r;
Mahir Ozturk 1:efe9cad8942f 801 MNG_DYN_r.bits.fast = 0; // Fast recovery mode disabled
Mahir Ozturk 1:efe9cad8942f 802 ecgAFE.writeRegister( MAX30003::MNGR_DYN , MNG_DYN_r.all);
Mahir Ozturk 1:efe9cad8942f 803
Mahir Ozturk 1:efe9cad8942f 804 // MUX Config
Mahir Ozturk 1:efe9cad8942f 805 MAX30003::MuxConfiguration_u CNFG_MUX_r;
Mahir Ozturk 1:efe9cad8942f 806 CNFG_MUX_r.bits.openn = 0; // Connect ECGN to AFE channel
Mahir Ozturk 1:efe9cad8942f 807 CNFG_MUX_r.bits.openp = 0; // Connect ECGP to AFE channel
Mahir Ozturk 1:efe9cad8942f 808 ecgAFE.writeRegister( MAX30003::CNFG_EMUX , CNFG_MUX_r.all);
Mahir Ozturk 1:efe9cad8942f 809
Mahir Ozturk 1:efe9cad8942f 810 return;
Mahir Ozturk 1:efe9cad8942f 811 }
Mahir Ozturk 1:efe9cad8942f 812
Mahir Ozturk 1:efe9cad8942f 813 void max30003_reader_task()
Mahir Ozturk 1:efe9cad8942f 814 {
Mahir Ozturk 1:efe9cad8942f 815 // Constants
Mahir Ozturk 1:efe9cad8942f 816 const int EINT_STATUS = 1 << 23;
Mahir Ozturk 1:efe9cad8942f 817 const int RTOR_STATUS = 1 << 10;
Mahir Ozturk 1:efe9cad8942f 818 const int RTOR_REG_OFFSET = 10;
Mahir Ozturk 3:7e9a93b6b82b 819 const float RTOR_LSB_RES = 0.0078125f;
Mahir Ozturk 1:efe9cad8942f 820 const int FIFO_OVF = 0x7;
Mahir Ozturk 1:efe9cad8942f 821 const int FIFO_VALID_SAMPLE = 0x0;
Mahir Ozturk 1:efe9cad8942f 822 const int FIFO_FAST_SAMPLE = 0x1;
Mahir Ozturk 1:efe9cad8942f 823 const int ETAG_BITS = 0x7;
Mahir Ozturk 1:efe9cad8942f 824
Mahir Ozturk 1:efe9cad8942f 825 InterruptIn ecgFIFO_int(P5_4); // Config P5_4 as int. in for the
Mahir Ozturk 1:efe9cad8942f 826 ecgFIFO_int.fall(&ecgFIFO_callback); // ecg FIFO almost full interrupt
Mahir Ozturk 1:efe9cad8942f 827
Mahir Ozturk 1:efe9cad8942f 828 ecg_config(max30003); // Config ECG
Mahir Ozturk 1:efe9cad8942f 829
Mahir Ozturk 1:efe9cad8942f 830 max30003.writeRegister( MAX30003::SYNCH , 0);
Mahir Ozturk 1:efe9cad8942f 831
Mahir Ozturk 1:efe9cad8942f 832 uint32_t ecgFIFO, RtoR, readECGSamples, idx, ETAG[32], status;
Mahir Ozturk 1:efe9cad8942f 833 int16_t ecgSample[32];
Mahir Ozturk 1:efe9cad8942f 834 float BPM;
Mahir Ozturk 2:68ffd74e3b5c 835 Timer bleNotifyTimer;
Mahir Ozturk 1:efe9cad8942f 836
Mahir Ozturk 2:68ffd74e3b5c 837 bleNotifyTimer.start();
Mahir Ozturk 1:efe9cad8942f 838 while (1) {
Mahir Ozturk 1:efe9cad8942f 839 // Read back ECG samples from the FIFO
Mahir Ozturk 1:efe9cad8942f 840 thread_max30003_reader.signal_wait(MAX30003_IRQ_ASSERTED_SIGNAL_ID);
Mahir Ozturk 1:efe9cad8942f 841
Mahir Ozturk 5:ff721fa88519 842 while (1) {
Mahir Ozturk 5:ff721fa88519 843 /* Read back ECG samples from the FIFO */
Mahir Ozturk 5:ff721fa88519 844 status = max30003.readRegister( MAX30003::STATUS ); // Read the STATUS register
Mahir Ozturk 5:ff721fa88519 845
Mahir Ozturk 5:ff721fa88519 846 if (status & (RTOR_STATUS | EINT_STATUS) == 0) {
Mahir Ozturk 5:ff721fa88519 847 break;
Mahir Ozturk 5:ff721fa88519 848 }
Mahir Ozturk 1:efe9cad8942f 849
Mahir Ozturk 5:ff721fa88519 850 // Check if R-to-R interrupt asserted
Mahir Ozturk 5:ff721fa88519 851 if ((status & RTOR_STATUS) == RTOR_STATUS) {
Mahir Ozturk 5:ff721fa88519 852
Mahir Ozturk 5:ff721fa88519 853 daplink.printf("R-to-R Interrupt \r\n");
Mahir Ozturk 1:efe9cad8942f 854
Mahir Ozturk 5:ff721fa88519 855 // Read RtoR register
Mahir Ozturk 5:ff721fa88519 856 RtoR = max30003.readRegister( MAX30003::RTOR ) >> RTOR_REG_OFFSET;
Mahir Ozturk 5:ff721fa88519 857
Mahir Ozturk 5:ff721fa88519 858 // Convert to BPM
Mahir Ozturk 5:ff721fa88519 859 BPM = 1.0f / ( RtoR * RTOR_LSB_RES / 60.0f );
Mahir Ozturk 5:ff721fa88519 860
Mahir Ozturk 5:ff721fa88519 861 daplink.printf("BPM: %.2f\r\n", BPM);
Mahir Ozturk 1:efe9cad8942f 862
Mahir Ozturk 5:ff721fa88519 863 if (bleNotifyTimer.read_ms() >= (MAX30003_BLE_NOTIFY_PERIOD_SEC * 1000)) {
Mahir Ozturk 5:ff721fa88519 864 bleGattAttrWrite(gattCharBPM.getValueHandle(), (uint8_t *)&BPM, sizeof(BPM));
Mahir Ozturk 5:ff721fa88519 865 bleNotifyTimer.reset();
Mahir Ozturk 5:ff721fa88519 866 }
Mahir Ozturk 5:ff721fa88519 867 }
Mahir Ozturk 1:efe9cad8942f 868
Mahir Ozturk 5:ff721fa88519 869 // Check if EINT interrupt asserted
Mahir Ozturk 5:ff721fa88519 870 if ((status & EINT_STATUS) == EINT_STATUS) {
Mahir Ozturk 5:ff721fa88519 871 readECGSamples = 0; // Reset sample counter
Mahir Ozturk 1:efe9cad8942f 872
Mahir Ozturk 5:ff721fa88519 873 do {
Mahir Ozturk 5:ff721fa88519 874 ecgFIFO = max30003.readRegister( MAX30003::ECG_FIFO ); // Read FIFO
Mahir Ozturk 5:ff721fa88519 875 ecgSample[readECGSamples] = ecgFIFO >> 8; // Isolate voltage data
Mahir Ozturk 5:ff721fa88519 876 ETAG[readECGSamples] = ( ecgFIFO >> 3 ) & ETAG_BITS; // Isolate ETAG
Mahir Ozturk 5:ff721fa88519 877 readECGSamples++; // Increment sample counter
Mahir Ozturk 1:efe9cad8942f 878
Mahir Ozturk 5:ff721fa88519 879 // Check that sample is not last sample in FIFO
Mahir Ozturk 5:ff721fa88519 880 } while (ETAG[readECGSamples-1] == FIFO_VALID_SAMPLE ||
Mahir Ozturk 5:ff721fa88519 881 ETAG[readECGSamples-1] == FIFO_FAST_SAMPLE);
Mahir Ozturk 5:ff721fa88519 882
Mahir Ozturk 5:ff721fa88519 883 // Check if FIFO has overflowed
Mahir Ozturk 5:ff721fa88519 884 if (ETAG[readECGSamples - 1] == FIFO_OVF){
Mahir Ozturk 5:ff721fa88519 885 max30003.writeRegister( MAX30003::FIFO_RST , 0); // Reset FIFO
Mahir Ozturk 5:ff721fa88519 886 rLED = 1;
Mahir Ozturk 5:ff721fa88519 887 }
Mahir Ozturk 2:68ffd74e3b5c 888 }
Mahir Ozturk 1:efe9cad8942f 889 }
Mahir Ozturk 1:efe9cad8942f 890
Mahir Ozturk 1:efe9cad8942f 891 }
Mahir Ozturk 1:efe9cad8942f 892 }
Mahir Ozturk 1:efe9cad8942f 893
Mahir Ozturk 1:efe9cad8942f 894 #endif
Mahir Ozturk 1:efe9cad8942f 895
Mahir Ozturk 1:efe9cad8942f 896 /******************************************************************************
Mahir Ozturk 1:efe9cad8942f 897 ************** MAX11301WING ***************************************************
Mahir Ozturk 1:efe9cad8942f 898 *******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 899 #if defined(LIB_MAX113XX_PIXI)
Mahir Ozturk 1:efe9cad8942f 900
Mahir Ozturk 1:efe9cad8942f 901 #define MAX113XX_DATA_READ_PERIOD_MSEC 2000
Mahir Ozturk 1:efe9cad8942f 902 #define MAX113XX_I2C_ADDRESS 0x38
Mahir Ozturk 1:efe9cad8942f 903
Mahir Ozturk 1:efe9cad8942f 904 Thread thread_max11301_reader;
Mahir Ozturk 1:efe9cad8942f 905
Mahir Ozturk 1:efe9cad8942f 906 void max11301_reader_task()
Mahir Ozturk 1:efe9cad8942f 907 {
Mahir Ozturk 1:efe9cad8942f 908 uint16_t adcData;
Mahir Ozturk 1:efe9cad8942f 909 float adcVoltage;
Mahir Ozturk 1:efe9cad8942f 910
Mahir Ozturk 1:efe9cad8942f 911 MAX113XX_I2C pixi(i2c1, MAX113XX_I2C::MAX11301, MAX113XX_I2C_ADDRESS, P5_5);
Mahir Ozturk 1:efe9cad8942f 912
Mahir Ozturk 1:efe9cad8942f 913 pixi.dacWrite(MAX113XX_Pixi::PORT0, 0x000); // Pixi PORT0 is -5V
Mahir Ozturk 1:efe9cad8942f 914 pixi.dacWrite(MAX113XX_Pixi::PORT1, 0xFFF); // Pixi PORT1 is +5V
Mahir Ozturk 1:efe9cad8942f 915
Mahir Ozturk 1:efe9cad8942f 916 daplink.printf("Starting MAX11301 PIXI ADC Demo Application...\r\n");
Mahir Ozturk 1:efe9cad8942f 917
Mahir Ozturk 1:efe9cad8942f 918 while (1) {
Mahir Ozturk 1:efe9cad8942f 919 pixi.singleEndedADCRead(MAX113XX_Pixi::PORT9, adcData); // Read value from PORT9
Mahir Ozturk 1:efe9cad8942f 920 adcVoltage = -5 + 2.442e-3 * adcData; // Convert ADC val. to a voltage
Mahir Ozturk 1:efe9cad8942f 921
Mahir Ozturk 1:efe9cad8942f 922 daplink.printf("ADC Read is : %i,\tVoltage is %1.3f V \r\n", adcData, adcVoltage);
Mahir Ozturk 1:efe9cad8942f 923
Mahir Ozturk 5:ff721fa88519 924 bleGattAttrWrite(gattCharADC.getValueHandle(), (uint8_t *)&adcVoltage, sizeof(adcVoltage));
Mahir Ozturk 1:efe9cad8942f 925
Mahir Ozturk 2:68ffd74e3b5c 926 Thread::wait(MAX113XX_PIXI_BLE_NOTIFY_PERIOD_SEC * 1000);
Mahir Ozturk 1:efe9cad8942f 927 }
Mahir Ozturk 1:efe9cad8942f 928 }
Mahir Ozturk 1:efe9cad8942f 929 #endif
Mahir Ozturk 1:efe9cad8942f 930
Mahir Ozturk 1:efe9cad8942f 931 /******************************************************************************
Mahir Ozturk 1:efe9cad8942f 932 ******************************************************************************
Mahir Ozturk 1:efe9cad8942f 933 ******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 934
Mahir Ozturk 1:efe9cad8942f 935 int main()
Mahir Ozturk 1:efe9cad8942f 936 {
Mahir Ozturk 1:efe9cad8942f 937 osStatus status;
Mahir Ozturk 2:68ffd74e3b5c 938 rLED = LED_OFF; gLED = LED_OFF; bLED = LED_OFF; // red
Mahir Ozturk 1:efe9cad8942f 939
Mahir Ozturk 2:68ffd74e3b5c 940 aliveLedEventId = eventQueue.call_every(1000, blinkCallback);
Mahir Ozturk 1:efe9cad8942f 941
Mahir Ozturk 1:efe9cad8942f 942 daplink.printf("Initializing BLE service...\r\n");
Mahir Ozturk 1:efe9cad8942f 943
Mahir Ozturk 2:68ffd74e3b5c 944 BLE &ble = BLE::Instance();
Mahir Ozturk 2:68ffd74e3b5c 945 ble.onEventsToProcess(scheduleBleEventsProcessing);
Mahir Ozturk 2:68ffd74e3b5c 946 ble.init(bleInitComplete);
Mahir Ozturk 1:efe9cad8942f 947
Mahir Ozturk 1:efe9cad8942f 948 #if defined(LIB_MAX30205)
Mahir Ozturk 2:68ffd74e3b5c 949 status = thread_max30205_reader.start(max30205_reader_task);
Mahir Ozturk 2:68ffd74e3b5c 950 if (status != osOK) {
Mahir Ozturk 2:68ffd74e3b5c 951 daplink.printf("Starting thread_max30205_reader thread failed(%d)!\r\n", status);
Mahir Ozturk 2:68ffd74e3b5c 952 }
Mahir Ozturk 1:efe9cad8942f 953 #endif
Mahir Ozturk 1:efe9cad8942f 954
Mahir Ozturk 1:efe9cad8942f 955 #if defined(LIB_MAX30101)
Mahir Ozturk 2:68ffd74e3b5c 956 status = thread_max30101_reader.start(max30101_reader_task);
Mahir Ozturk 2:68ffd74e3b5c 957 if (status != osOK) {
Mahir Ozturk 2:68ffd74e3b5c 958 daplink.printf("Starting thread_max30205_reader thread failed(%d)!\r\n", status);
Mahir Ozturk 2:68ffd74e3b5c 959 }
Mahir Ozturk 1:efe9cad8942f 960 #endif
Mahir Ozturk 1:efe9cad8942f 961
Mahir Ozturk 1:efe9cad8942f 962 #if defined(LIB_MAX30003)
Mahir Ozturk 2:68ffd74e3b5c 963 status = thread_max30003_reader.start(max30003_reader_task);
Mahir Ozturk 2:68ffd74e3b5c 964 if (status != osOK) {
Mahir Ozturk 2:68ffd74e3b5c 965 daplink.printf("Starting thread_max30205_reader thread failed(%d)!\r\n", status);
Mahir Ozturk 2:68ffd74e3b5c 966 }
Mahir Ozturk 1:efe9cad8942f 967 #endif
Mahir Ozturk 1:efe9cad8942f 968
Mahir Ozturk 1:efe9cad8942f 969 #if defined(LIB_MAX113XX_PIXI)
Mahir Ozturk 2:68ffd74e3b5c 970 status = thread_max11301_reader.start(max11301_reader_task);
Mahir Ozturk 2:68ffd74e3b5c 971 if (status != osOK) {
Mahir Ozturk 2:68ffd74e3b5c 972 daplink.printf("Starting thread_max30205_reader thread failed(%d)!\r\n", status);
Mahir Ozturk 2:68ffd74e3b5c 973 }
Mahir Ozturk 1:efe9cad8942f 974 #endif
Mahir Ozturk 1:efe9cad8942f 975
Mahir Ozturk 2:68ffd74e3b5c 976 eventQueue.dispatch_forever();
Mahir Ozturk 1:efe9cad8942f 977
Mahir Ozturk 2:68ffd74e3b5c 978 return 0;
Mahir Ozturk 1:efe9cad8942f 979 }
Mahir Ozturk 1:efe9cad8942f 980