Maxim Integrated's IoT development kit.

Dependencies:   MAX30101 MAX30003 MAX113XX_Pixi MAX30205 max32630fthr USBDevice

Committer:
Mahir Ozturk
Date:
Thu Mar 15 17:13:40 2018 +0300
Revision:
2:68ffd74e3b5c
Parent:
1:efe9cad8942f
Child:
3:7e9a93b6b82b
Add BLE Notification period setting, code cleaning

Change-Id: Ib49ed44fe0fb2ccf03f2379e1cd086e5a36e7e49

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 1:efe9cad8942f 121 static float ADCInitValue = 2.5;
Mahir Ozturk 1:efe9cad8942f 122 ReadOnlyGattCharacteristic<float> gattCharADC(uuidADC, &ADCInitValue,
Mahir Ozturk 1:efe9cad8942f 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 1:efe9cad8942f 512 daplink.printf("Overflow!");
Mahir Ozturk 1:efe9cad8942f 513 }
Mahir Ozturk 1:efe9cad8942f 514
Mahir Ozturk 1:efe9cad8942f 515 if (readBytes >= (idx + 2)) {
Mahir Ozturk 1:efe9cad8942f 516 redData[r++] = ((fifoData[idx] << 16) | (fifoData[idx + 1] << 8) | (fifoData[idx + 2])) & 0x03FFFF;
Mahir Ozturk 1:efe9cad8942f 517 }
Mahir Ozturk 1:efe9cad8942f 518
Mahir Ozturk 1:efe9cad8942f 519 if (readBytes >= (idx + 5)) {
Mahir Ozturk 1:efe9cad8942f 520 irData[ir++] = ((fifoData[idx + 3] << 16) | (fifoData[idx + 4] << 8) | (fifoData[idx + 5])) & 0x03FFFF;
Mahir Ozturk 1:efe9cad8942f 521 }
Mahir Ozturk 1:efe9cad8942f 522
Mahir Ozturk 1:efe9cad8942f 523 if (readBytes >= (idx + 8)) {
Mahir Ozturk 1:efe9cad8942f 524 greenData[g++] = ((fifoData[idx + 6] << 16) | (fifoData[idx + 7] << 8) | (fifoData[idx + 8])) & 0x03FFFF;
Mahir Ozturk 1:efe9cad8942f 525 }
Mahir Ozturk 1:efe9cad8942f 526 }
Mahir Ozturk 1:efe9cad8942f 527
Mahir Ozturk 1:efe9cad8942f 528 if ((r >= 500) && (ir >= 500) && (g >= 500)) {/* checks to make sure there are 500 */
Mahir Ozturk 1:efe9cad8942f 529 /* samples in data buffers */
Mahir Ozturk 1:efe9cad8942f 530
Mahir Ozturk 1:efe9cad8942f 531 /* runs the heart rate and SpO2 algorithm */
Mahir Ozturk 1:efe9cad8942f 532 for (c = 0, HRTemp = 0; c < r; c++) {
Mahir Ozturk 1:efe9cad8942f 533 HRSpO2Func(irData[c], redData[c],greenData[c], c,sampleRate, compSpO2,
Mahir Ozturk 1:efe9cad8942f 534 &ir_ac_comp,&red_ac_comp, &green_ac_comp, &ir_ac_mag,&red_ac_mag,
Mahir Ozturk 1:efe9cad8942f 535 &green_ac_mag, &HRbpm2,&SpO2B,&DRdy);
Mahir Ozturk 1:efe9cad8942f 536 if (DRdy) {
Mahir Ozturk 1:efe9cad8942f 537 HRTemp = HRbpm2;
Mahir Ozturk 1:efe9cad8942f 538 spo2Temp = SpO2B;
Mahir Ozturk 1:efe9cad8942f 539 }
Mahir Ozturk 1:efe9cad8942f 540 }
Mahir Ozturk 1:efe9cad8942f 541
Mahir Ozturk 1:efe9cad8942f 542 /* If the above algorithm returns a valid heart rate on the last sample, it is printed */
Mahir Ozturk 1:efe9cad8942f 543 if (DRdy == 1) {
Mahir Ozturk 1:efe9cad8942f 544 daplink.printf("Heart Rate = %i\r\n",HRbpm2);
Mahir Ozturk 1:efe9cad8942f 545 daplink.printf("SPO2 = %i\r\n",SpO2B);
Mahir Ozturk 2:68ffd74e3b5c 546 lastValidHR = HRbpm2;
Mahir Ozturk 2:68ffd74e3b5c 547 lastValidSPO2 = SpO2B;
Mahir Ozturk 1:efe9cad8942f 548 } else if (HRTemp != 0) { /* if a valid heart was calculated at all, it is printed */
Mahir Ozturk 1:efe9cad8942f 549 daplink.printf("Heart Rate = %i\r\n",HRTemp);
Mahir Ozturk 1:efe9cad8942f 550 daplink.printf("SPO2 = %i\r\n",spo2Temp);
Mahir Ozturk 2:68ffd74e3b5c 551 lastValidHR = HRTemp;
Mahir Ozturk 2:68ffd74e3b5c 552 lastValidSPO2 = spo2Temp;
Mahir Ozturk 1:efe9cad8942f 553 } else {
Mahir Ozturk 1:efe9cad8942f 554 daplink.printf("Calculation failed...waiting for more samples...\r\n");
Mahir Ozturk 1:efe9cad8942f 555 daplink.printf("Please keep your finger on the MAX30101 sensor with minimal movement.\r\n");
Mahir Ozturk 1:efe9cad8942f 556 }
Mahir Ozturk 1:efe9cad8942f 557
Mahir Ozturk 1:efe9cad8942f 558 /* dump the first hundred samples after calculation */
Mahir Ozturk 1:efe9cad8942f 559 for (c = 100; c < 500; c++) {
Mahir Ozturk 1:efe9cad8942f 560 redData[c - 100] = redData[c];
Mahir Ozturk 1:efe9cad8942f 561 irData[c - 100] = irData[c];
Mahir Ozturk 1:efe9cad8942f 562 greenData[c - 100] = greenData[c];
Mahir Ozturk 1:efe9cad8942f 563 }
Mahir Ozturk 1:efe9cad8942f 564
Mahir Ozturk 1:efe9cad8942f 565 /* reset counters */
Mahir Ozturk 1:efe9cad8942f 566 r = 400;
Mahir Ozturk 1:efe9cad8942f 567 ir = 400;
Mahir Ozturk 1:efe9cad8942f 568 g = 400;
Mahir Ozturk 1:efe9cad8942f 569 }
Mahir Ozturk 2:68ffd74e3b5c 570
Mahir Ozturk 2:68ffd74e3b5c 571 if (bleNotifyTimer.read_ms() >= (MAX30101_BLE_NOTIFY_PERIOD_SEC * 1000)) {
Mahir Ozturk 2:68ffd74e3b5c 572 bleGattAttrWrite(gattCharHeartRate.getValueHandle(), (uint8_t *)&lastValidHR, sizeof(lastValidHR));
Mahir Ozturk 2:68ffd74e3b5c 573 bleGattAttrWrite(gattCharSPO2.getValueHandle(), (uint8_t *)&lastValidSPO2, sizeof(lastValidSPO2));
Mahir Ozturk 2:68ffd74e3b5c 574 bleNotifyTimer.reset();
Mahir Ozturk 2:68ffd74e3b5c 575 }
Mahir Ozturk 1:efe9cad8942f 576 }
Mahir Ozturk 1:efe9cad8942f 577 }
Mahir Ozturk 1:efe9cad8942f 578 } else { // If rc != 0, a communication error has occurred
Mahir Ozturk 1:efe9cad8942f 579
Mahir Ozturk 1:efe9cad8942f 580 daplink.printf("Something went wrong, "
Mahir Ozturk 1:efe9cad8942f 581 "check the I2C bus or power connections... \r\n");
Mahir Ozturk 1:efe9cad8942f 582
Mahir Ozturk 2:68ffd74e3b5c 583 return;
Mahir Ozturk 1:efe9cad8942f 584 }
Mahir Ozturk 1:efe9cad8942f 585
Mahir Ozturk 1:efe9cad8942f 586 }
Mahir Ozturk 1:efe9cad8942f 587 }
Mahir Ozturk 1:efe9cad8942f 588 #endif
Mahir Ozturk 1:efe9cad8942f 589
Mahir Ozturk 1:efe9cad8942f 590 /******************************************************************************
Mahir Ozturk 1:efe9cad8942f 591 ************** MAX30003WING (ECG) *********************************************
Mahir Ozturk 1:efe9cad8942f 592 ******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 593 #if defined(LIB_MAX30003_ECG)
Mahir Ozturk 1:efe9cad8942f 594 #define MAX30003_IRQ_ASSERTED_SIGNAL_ID 1
Mahir Ozturk 1:efe9cad8942f 595
Mahir Ozturk 1:efe9cad8942f 596 MAX30003 max30003(spim2, SPI2_SS); /* MAX30003WING board */
Mahir Ozturk 1:efe9cad8942f 597
Mahir Ozturk 1:efe9cad8942f 598 Thread thread_max30003_reader;
Mahir Ozturk 1:efe9cad8942f 599
Mahir Ozturk 1:efe9cad8942f 600 void ecg_config(MAX30003& ecgAFE) {
Mahir Ozturk 1:efe9cad8942f 601
Mahir Ozturk 1:efe9cad8942f 602 // Reset ECG to clear registers
Mahir Ozturk 1:efe9cad8942f 603 ecgAFE.writeRegister( MAX30003::SW_RST , 0);
Mahir Ozturk 1:efe9cad8942f 604
Mahir Ozturk 1:efe9cad8942f 605 // General config register setting
Mahir Ozturk 1:efe9cad8942f 606 MAX30003::GeneralConfiguration_u CNFG_GEN_r;
Mahir Ozturk 1:efe9cad8942f 607 CNFG_GEN_r.bits.en_ecg = 1; // Enable ECG channel
Mahir Ozturk 1:efe9cad8942f 608 CNFG_GEN_r.bits.rbiasn = 1; // Enable resistive bias on negative input
Mahir Ozturk 1:efe9cad8942f 609 CNFG_GEN_r.bits.rbiasp = 1; // Enable resistive bias on positive input
Mahir Ozturk 1:efe9cad8942f 610 CNFG_GEN_r.bits.en_rbias = 1; // Enable resistive bias
Mahir Ozturk 1:efe9cad8942f 611 CNFG_GEN_r.bits.imag = 2; // Current magnitude = 10nA
Mahir Ozturk 1:efe9cad8942f 612 CNFG_GEN_r.bits.en_dcloff = 1; // Enable DC lead-off detection
Mahir Ozturk 1:efe9cad8942f 613 ecgAFE.writeRegister( MAX30003::CNFG_GEN , CNFG_GEN_r.all);
Mahir Ozturk 1:efe9cad8942f 614
Mahir Ozturk 1:efe9cad8942f 615
Mahir Ozturk 1:efe9cad8942f 616 // ECG Config register setting
Mahir Ozturk 1:efe9cad8942f 617 MAX30003::ECGConfiguration_u CNFG_ECG_r;
Mahir Ozturk 1:efe9cad8942f 618 CNFG_ECG_r.bits.dlpf = 1; // Digital LPF cutoff = 40Hz
Mahir Ozturk 1:efe9cad8942f 619 CNFG_ECG_r.bits.dhpf = 1; // Digital HPF cutoff = 0.5Hz
Mahir Ozturk 1:efe9cad8942f 620 CNFG_ECG_r.bits.gain = 3; // ECG gain = 160V/V
Mahir Ozturk 1:efe9cad8942f 621 CNFG_ECG_r.bits.rate = 2; // Sample rate = 128 sps
Mahir Ozturk 1:efe9cad8942f 622 ecgAFE.writeRegister( MAX30003::CNFG_ECG , CNFG_ECG_r.all);
Mahir Ozturk 1:efe9cad8942f 623
Mahir Ozturk 1:efe9cad8942f 624
Mahir Ozturk 1:efe9cad8942f 625 //R-to-R configuration
Mahir Ozturk 1:efe9cad8942f 626 MAX30003::RtoR1Configuration_u CNFG_RTOR_r;
Mahir Ozturk 1:efe9cad8942f 627 CNFG_RTOR_r.bits.en_rtor = 1; // Enable R-to-R detection
Mahir Ozturk 1:efe9cad8942f 628 ecgAFE.writeRegister( MAX30003::CNFG_RTOR1 , CNFG_RTOR_r.all);
Mahir Ozturk 1:efe9cad8942f 629
Mahir Ozturk 1:efe9cad8942f 630
Mahir Ozturk 1:efe9cad8942f 631 //Manage interrupts register setting
Mahir Ozturk 1:efe9cad8942f 632 MAX30003::ManageInterrupts_u MNG_INT_r;
Mahir Ozturk 1:efe9cad8942f 633 MNG_INT_r.bits.efit = 0b00011; // Assert EINT w/ 4 unread samples
Mahir Ozturk 1:efe9cad8942f 634 MNG_INT_r.bits.clr_rrint = 0b01; // Clear R-to-R on RTOR reg. read back
Mahir Ozturk 1:efe9cad8942f 635 ecgAFE.writeRegister( MAX30003::MNGR_INT , MNG_INT_r.all);
Mahir Ozturk 1:efe9cad8942f 636
Mahir Ozturk 1:efe9cad8942f 637
Mahir Ozturk 1:efe9cad8942f 638 //Enable interrupts register setting
Mahir Ozturk 1:efe9cad8942f 639 MAX30003::EnableInterrupts_u EN_INT_r;
Mahir Ozturk 1:efe9cad8942f 640 EN_INT_r.all = 0;
Mahir Ozturk 1:efe9cad8942f 641 EN_INT_r.bits.en_eint = 1; // Enable EINT interrupt
Mahir Ozturk 1:efe9cad8942f 642 EN_INT_r.bits.en_rrint = 0; // Disable R-to-R interrupt
Mahir Ozturk 1:efe9cad8942f 643 EN_INT_r.bits.intb_type = 3; // Open-drain NMOS with internal pullup
Mahir Ozturk 1:efe9cad8942f 644 ecgAFE.writeRegister( MAX30003::EN_INT , EN_INT_r.all);
Mahir Ozturk 1:efe9cad8942f 645
Mahir Ozturk 1:efe9cad8942f 646
Mahir Ozturk 1:efe9cad8942f 647 //Dyanmic modes config
Mahir Ozturk 1:efe9cad8942f 648 MAX30003::ManageDynamicModes_u MNG_DYN_r;
Mahir Ozturk 1:efe9cad8942f 649 MNG_DYN_r.bits.fast = 0; // Fast recovery mode disabled
Mahir Ozturk 1:efe9cad8942f 650 ecgAFE.writeRegister( MAX30003::MNGR_DYN , MNG_DYN_r.all);
Mahir Ozturk 1:efe9cad8942f 651
Mahir Ozturk 1:efe9cad8942f 652 // MUX Config
Mahir Ozturk 1:efe9cad8942f 653 MAX30003::MuxConfiguration_u CNFG_MUX_r;
Mahir Ozturk 1:efe9cad8942f 654 CNFG_MUX_r.bits.openn = 0; // Connect ECGN to AFE channel
Mahir Ozturk 1:efe9cad8942f 655 CNFG_MUX_r.bits.openp = 0; // Connect ECGP to AFE channel
Mahir Ozturk 1:efe9cad8942f 656 ecgAFE.writeRegister( MAX30003::CNFG_EMUX , CNFG_MUX_r.all);
Mahir Ozturk 1:efe9cad8942f 657
Mahir Ozturk 1:efe9cad8942f 658 return;
Mahir Ozturk 1:efe9cad8942f 659 }
Mahir Ozturk 1:efe9cad8942f 660
Mahir Ozturk 1:efe9cad8942f 661 /* ECG FIFO nearly full callback */
Mahir Ozturk 1:efe9cad8942f 662 //volatile bool ecgFIFOIntFlag = 0;
Mahir Ozturk 1:efe9cad8942f 663 void ecgFIFO_callback() {
Mahir Ozturk 1:efe9cad8942f 664
Mahir Ozturk 1:efe9cad8942f 665 thread_max30003_reader.signal_set(MAX30003_IRQ_ASSERTED_SIGNAL_ID);
Mahir Ozturk 1:efe9cad8942f 666 //ecgFIFOIntFlag = 1;
Mahir Ozturk 1:efe9cad8942f 667
Mahir Ozturk 1:efe9cad8942f 668 }
Mahir Ozturk 1:efe9cad8942f 669
Mahir Ozturk 1:efe9cad8942f 670 void max30003_reader_task()
Mahir Ozturk 1:efe9cad8942f 671 {
Mahir Ozturk 1:efe9cad8942f 672 // Constants
Mahir Ozturk 1:efe9cad8942f 673 const int EINT_STATUS_MASK = 1 << 23;
Mahir Ozturk 1:efe9cad8942f 674 const int FIFO_OVF_MASK = 0x7;
Mahir Ozturk 1:efe9cad8942f 675 const int FIFO_VALID_SAMPLE_MASK = 0x0;
Mahir Ozturk 1:efe9cad8942f 676 const int FIFO_FAST_SAMPLE_MASK = 0x1;
Mahir Ozturk 1:efe9cad8942f 677 const int ETAG_BITS_MASK = 0x7;
Mahir Ozturk 1:efe9cad8942f 678
Mahir Ozturk 1:efe9cad8942f 679 InterruptIn ecgFIFO_int(P5_4); // Config P5_4 as int. in for the
Mahir Ozturk 1:efe9cad8942f 680 ecgFIFO_int.fall(&ecgFIFO_callback); // ecg FIFO almost full interrupt
Mahir Ozturk 1:efe9cad8942f 681
Mahir Ozturk 1:efe9cad8942f 682 SPI spiBus(SPI2_MOSI, SPI2_MISO, SPI2_SCK); // SPI bus, P5_1 = MOSI,
Mahir Ozturk 1:efe9cad8942f 683 // P5_2 = MISO, P5_0 = SCK
Mahir Ozturk 1:efe9cad8942f 684
Mahir Ozturk 1:efe9cad8942f 685 MAX30003 ecgAFE(spiBus, P5_3); // New MAX30003 on spiBus, CS = P5_3
Mahir Ozturk 1:efe9cad8942f 686 ecg_config(ecgAFE); // Config ECG
Mahir Ozturk 1:efe9cad8942f 687
Mahir Ozturk 1:efe9cad8942f 688
Mahir Ozturk 1:efe9cad8942f 689 ecgAFE.writeRegister( MAX30003::SYNCH , 0);
Mahir Ozturk 1:efe9cad8942f 690
Mahir Ozturk 1:efe9cad8942f 691 uint32_t ecgFIFO, readECGSamples, idx, ETAG[32], status;
Mahir Ozturk 1:efe9cad8942f 692 int16_t ecgSample[32];
Mahir Ozturk 1:efe9cad8942f 693
Mahir Ozturk 1:efe9cad8942f 694 daplink.printf("Starting MAX30003 ECG Demo Application...\r\n");
Mahir Ozturk 1:efe9cad8942f 695
Mahir Ozturk 1:efe9cad8942f 696 while (1) {
Mahir Ozturk 1:efe9cad8942f 697
Mahir Ozturk 1:efe9cad8942f 698 // Read back ECG samples from the FIFO
Mahir Ozturk 1:efe9cad8942f 699 thread_max30003_reader.signal_wait(MAX30003_IRQ_ASSERTED_SIGNAL_ID);
Mahir Ozturk 1:efe9cad8942f 700
Mahir Ozturk 1:efe9cad8942f 701 status = ecgAFE.readRegister( MAX30003::STATUS ); // Read the STATUS register
Mahir Ozturk 1:efe9cad8942f 702
Mahir Ozturk 1:efe9cad8942f 703 // Check if EINT interrupt asserted
Mahir Ozturk 1:efe9cad8942f 704 if ( ( status & EINT_STATUS_MASK ) == EINT_STATUS_MASK ) {
Mahir Ozturk 1:efe9cad8942f 705
Mahir Ozturk 1:efe9cad8942f 706 readECGSamples = 0; // Reset sample counter
Mahir Ozturk 1:efe9cad8942f 707
Mahir Ozturk 1:efe9cad8942f 708 do {
Mahir Ozturk 1:efe9cad8942f 709 ecgFIFO = ecgAFE.readRegister( MAX30003::ECG_FIFO ); // Read FIFO
Mahir Ozturk 1:efe9cad8942f 710 ecgSample[readECGSamples] = ecgFIFO >> 8; // Isolate voltage data
Mahir Ozturk 1:efe9cad8942f 711 ETAG[readECGSamples] = ( ecgFIFO >> 3 ) & ETAG_BITS_MASK; // Isolate ETAG
Mahir Ozturk 1:efe9cad8942f 712 readECGSamples++; // Increment sample counter
Mahir Ozturk 1:efe9cad8942f 713
Mahir Ozturk 1:efe9cad8942f 714 // Check that sample is not last sample in FIFO
Mahir Ozturk 1:efe9cad8942f 715 } while ( ETAG[readECGSamples-1] == FIFO_VALID_SAMPLE_MASK ||
Mahir Ozturk 1:efe9cad8942f 716 ETAG[readECGSamples-1] == FIFO_FAST_SAMPLE_MASK );
Mahir Ozturk 1:efe9cad8942f 717
Mahir Ozturk 1:efe9cad8942f 718 // Check if FIFO has overflowed
Mahir Ozturk 1:efe9cad8942f 719 if( ETAG[readECGSamples - 1] == FIFO_OVF_MASK ){
Mahir Ozturk 1:efe9cad8942f 720 ecgAFE.writeRegister( MAX30003::FIFO_RST , 0); // Reset FIFO
Mahir Ozturk 1:efe9cad8942f 721 rLED = 1;//notifies the user that an over flow occured
Mahir Ozturk 1:efe9cad8942f 722 }
Mahir Ozturk 1:efe9cad8942f 723
Mahir Ozturk 1:efe9cad8942f 724 // Print results
Mahir Ozturk 1:efe9cad8942f 725 for( idx = 0; idx < readECGSamples; idx++ ) {
Mahir Ozturk 1:efe9cad8942f 726 daplink.printf("%6d\r\n", ecgSample[idx]);
Mahir Ozturk 1:efe9cad8942f 727
Mahir Ozturk 1:efe9cad8942f 728 bleGattAttrWrite(gattCharECG.getValueHandle(),
Mahir Ozturk 1:efe9cad8942f 729 (uint8_t *)&ecgSample[idx], sizeof(ecgSample[idx]));
Mahir Ozturk 1:efe9cad8942f 730 }
Mahir Ozturk 1:efe9cad8942f 731 }
Mahir Ozturk 1:efe9cad8942f 732 }
Mahir Ozturk 1:efe9cad8942f 733 }
Mahir Ozturk 1:efe9cad8942f 734
Mahir Ozturk 1:efe9cad8942f 735 #endif
Mahir Ozturk 1:efe9cad8942f 736
Mahir Ozturk 1:efe9cad8942f 737 /******************************************************************************
Mahir Ozturk 1:efe9cad8942f 738 ************** MAX30003WING (BPM) *********************************************
Mahir Ozturk 1:efe9cad8942f 739 *******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 740 #if defined(LIB_MAX30003)
Mahir Ozturk 1:efe9cad8942f 741
Mahir Ozturk 1:efe9cad8942f 742 #define MAX30003_IRQ_ASSERTED_SIGNAL_ID 1
Mahir Ozturk 1:efe9cad8942f 743
Mahir Ozturk 1:efe9cad8942f 744 MAX30003 max30003(spim2, SPI2_SS); /* MAX30003WING board */
Mahir Ozturk 1:efe9cad8942f 745
Mahir Ozturk 1:efe9cad8942f 746 Thread thread_max30003_reader;
Mahir Ozturk 1:efe9cad8942f 747
Mahir Ozturk 1:efe9cad8942f 748 /* ECG FIFO nearly full callback */
Mahir Ozturk 1:efe9cad8942f 749 void ecgFIFO_callback()
Mahir Ozturk 1:efe9cad8942f 750 {
Mahir Ozturk 1:efe9cad8942f 751 thread_max30003_reader.signal_set(MAX30003_IRQ_ASSERTED_SIGNAL_ID);
Mahir Ozturk 1:efe9cad8942f 752 }
Mahir Ozturk 1:efe9cad8942f 753
Mahir Ozturk 1:efe9cad8942f 754 void ecg_config(MAX30003& ecgAFE)
Mahir Ozturk 1:efe9cad8942f 755 {
Mahir Ozturk 1:efe9cad8942f 756 // Reset ECG to clear registers
Mahir Ozturk 1:efe9cad8942f 757 ecgAFE.writeRegister( MAX30003::SW_RST , 0);
Mahir Ozturk 1:efe9cad8942f 758
Mahir Ozturk 1:efe9cad8942f 759 // General config register setting
Mahir Ozturk 1:efe9cad8942f 760 MAX30003::GeneralConfiguration_u CNFG_GEN_r;
Mahir Ozturk 1:efe9cad8942f 761 CNFG_GEN_r.bits.en_ecg = 1; // Enable ECG channel
Mahir Ozturk 1:efe9cad8942f 762 CNFG_GEN_r.bits.rbiasn = 1; // Enable resistive bias on negative input
Mahir Ozturk 1:efe9cad8942f 763 CNFG_GEN_r.bits.rbiasp = 1; // Enable resistive bias on positive input
Mahir Ozturk 1:efe9cad8942f 764 CNFG_GEN_r.bits.en_rbias = 1; // Enable resistive bias
Mahir Ozturk 1:efe9cad8942f 765 CNFG_GEN_r.bits.imag = 2; // Current magnitude = 10nA
Mahir Ozturk 1:efe9cad8942f 766 CNFG_GEN_r.bits.en_dcloff = 1; // Enable DC lead-off detection
Mahir Ozturk 1:efe9cad8942f 767 ecgAFE.writeRegister( MAX30003::CNFG_GEN , CNFG_GEN_r.all);
Mahir Ozturk 1:efe9cad8942f 768
Mahir Ozturk 1:efe9cad8942f 769
Mahir Ozturk 1:efe9cad8942f 770 // ECG Config register setting
Mahir Ozturk 1:efe9cad8942f 771 MAX30003::ECGConfiguration_u CNFG_ECG_r;
Mahir Ozturk 1:efe9cad8942f 772 CNFG_ECG_r.bits.dlpf = 1; // Digital LPF cutoff = 40Hz
Mahir Ozturk 1:efe9cad8942f 773 CNFG_ECG_r.bits.dhpf = 1; // Digital HPF cutoff = 0.5Hz
Mahir Ozturk 1:efe9cad8942f 774 CNFG_ECG_r.bits.gain = 3; // ECG gain = 160V/V
Mahir Ozturk 1:efe9cad8942f 775 CNFG_ECG_r.bits.rate = 2; // Sample rate = 128 sps
Mahir Ozturk 1:efe9cad8942f 776 ecgAFE.writeRegister( MAX30003::CNFG_ECG , CNFG_ECG_r.all);
Mahir Ozturk 1:efe9cad8942f 777
Mahir Ozturk 1:efe9cad8942f 778
Mahir Ozturk 1:efe9cad8942f 779 //R-to-R configuration
Mahir Ozturk 1:efe9cad8942f 780 MAX30003::RtoR1Configuration_u CNFG_RTOR_r;
Mahir Ozturk 1:efe9cad8942f 781 CNFG_RTOR_r.bits.wndw = 0b0011; // WNDW = 96ms
Mahir Ozturk 1:efe9cad8942f 782 CNFG_RTOR_r.bits.rgain = 0b1111; // Auto-scale gain
Mahir Ozturk 1:efe9cad8942f 783 CNFG_RTOR_r.bits.pavg = 0b11; // 16-average
Mahir Ozturk 1:efe9cad8942f 784 CNFG_RTOR_r.bits.ptsf = 0b0011; // PTSF = 4/16
Mahir Ozturk 1:efe9cad8942f 785 CNFG_RTOR_r.bits.en_rtor = 1; // Enable R-to-R detection
Mahir Ozturk 1:efe9cad8942f 786 ecgAFE.writeRegister( MAX30003::CNFG_RTOR1 , CNFG_RTOR_r.all);
Mahir Ozturk 1:efe9cad8942f 787
Mahir Ozturk 1:efe9cad8942f 788
Mahir Ozturk 1:efe9cad8942f 789 //Manage interrupts register setting
Mahir Ozturk 1:efe9cad8942f 790 MAX30003::ManageInterrupts_u MNG_INT_r;
Mahir Ozturk 1:efe9cad8942f 791 MNG_INT_r.bits.efit = 0b00011; // Assert EINT w/ 4 unread samples
Mahir Ozturk 1:efe9cad8942f 792 MNG_INT_r.bits.clr_rrint = 0b01; // Clear R-to-R on RTOR reg. read back
Mahir Ozturk 1:efe9cad8942f 793 ecgAFE.writeRegister( MAX30003::MNGR_INT , MNG_INT_r.all);
Mahir Ozturk 1:efe9cad8942f 794
Mahir Ozturk 1:efe9cad8942f 795
Mahir Ozturk 1:efe9cad8942f 796 //Enable interrupts register setting
Mahir Ozturk 1:efe9cad8942f 797 MAX30003::EnableInterrupts_u EN_INT_r;
Mahir Ozturk 1:efe9cad8942f 798 EN_INT_r.bits.en_eint = 1; // Enable EINT interrupt
Mahir Ozturk 1:efe9cad8942f 799 EN_INT_r.bits.en_rrint = 1; // Enable R-to-R interrupt
Mahir Ozturk 1:efe9cad8942f 800 EN_INT_r.bits.intb_type = 3; // Open-drain NMOS with internal pullup
Mahir Ozturk 1:efe9cad8942f 801 ecgAFE.writeRegister( MAX30003::EN_INT , EN_INT_r.all);
Mahir Ozturk 1:efe9cad8942f 802
Mahir Ozturk 1:efe9cad8942f 803
Mahir Ozturk 1:efe9cad8942f 804 //Dyanmic modes config
Mahir Ozturk 1:efe9cad8942f 805 MAX30003::ManageDynamicModes_u MNG_DYN_r;
Mahir Ozturk 1:efe9cad8942f 806 MNG_DYN_r.bits.fast = 0; // Fast recovery mode disabled
Mahir Ozturk 1:efe9cad8942f 807 ecgAFE.writeRegister( MAX30003::MNGR_DYN , MNG_DYN_r.all);
Mahir Ozturk 1:efe9cad8942f 808
Mahir Ozturk 1:efe9cad8942f 809 // MUX Config
Mahir Ozturk 1:efe9cad8942f 810 MAX30003::MuxConfiguration_u CNFG_MUX_r;
Mahir Ozturk 1:efe9cad8942f 811 CNFG_MUX_r.bits.openn = 0; // Connect ECGN to AFE channel
Mahir Ozturk 1:efe9cad8942f 812 CNFG_MUX_r.bits.openp = 0; // Connect ECGP to AFE channel
Mahir Ozturk 1:efe9cad8942f 813 ecgAFE.writeRegister( MAX30003::CNFG_EMUX , CNFG_MUX_r.all);
Mahir Ozturk 1:efe9cad8942f 814
Mahir Ozturk 1:efe9cad8942f 815 return;
Mahir Ozturk 1:efe9cad8942f 816 }
Mahir Ozturk 1:efe9cad8942f 817
Mahir Ozturk 1:efe9cad8942f 818 void max30003_reader_task()
Mahir Ozturk 1:efe9cad8942f 819 {
Mahir Ozturk 1:efe9cad8942f 820 // Constants
Mahir Ozturk 1:efe9cad8942f 821 const int EINT_STATUS = 1 << 23;
Mahir Ozturk 1:efe9cad8942f 822 const int RTOR_STATUS = 1 << 10;
Mahir Ozturk 1:efe9cad8942f 823 const int RTOR_REG_OFFSET = 10;
Mahir Ozturk 1:efe9cad8942f 824 const float RTOR_LSB_RES = 0.008f;
Mahir Ozturk 1:efe9cad8942f 825 const int FIFO_OVF = 0x7;
Mahir Ozturk 1:efe9cad8942f 826 const int FIFO_VALID_SAMPLE = 0x0;
Mahir Ozturk 1:efe9cad8942f 827 const int FIFO_FAST_SAMPLE = 0x1;
Mahir Ozturk 1:efe9cad8942f 828 const int ETAG_BITS = 0x7;
Mahir Ozturk 1:efe9cad8942f 829
Mahir Ozturk 1:efe9cad8942f 830 InterruptIn ecgFIFO_int(P5_4); // Config P5_4 as int. in for the
Mahir Ozturk 1:efe9cad8942f 831 ecgFIFO_int.fall(&ecgFIFO_callback); // ecg FIFO almost full interrupt
Mahir Ozturk 1:efe9cad8942f 832
Mahir Ozturk 1:efe9cad8942f 833 ecg_config(max30003); // Config ECG
Mahir Ozturk 1:efe9cad8942f 834
Mahir Ozturk 1:efe9cad8942f 835 max30003.writeRegister( MAX30003::SYNCH , 0);
Mahir Ozturk 1:efe9cad8942f 836
Mahir Ozturk 1:efe9cad8942f 837 uint32_t ecgFIFO, RtoR, readECGSamples, idx, ETAG[32], status;
Mahir Ozturk 1:efe9cad8942f 838 int16_t ecgSample[32];
Mahir Ozturk 1:efe9cad8942f 839 float BPM;
Mahir Ozturk 2:68ffd74e3b5c 840 Timer bleNotifyTimer;
Mahir Ozturk 1:efe9cad8942f 841
Mahir Ozturk 2:68ffd74e3b5c 842 bleNotifyTimer.start();
Mahir Ozturk 1:efe9cad8942f 843 while (1) {
Mahir Ozturk 1:efe9cad8942f 844 // Read back ECG samples from the FIFO
Mahir Ozturk 1:efe9cad8942f 845 thread_max30003_reader.signal_wait(MAX30003_IRQ_ASSERTED_SIGNAL_ID);
Mahir Ozturk 1:efe9cad8942f 846
Mahir Ozturk 1:efe9cad8942f 847 /* Read back ECG samples from the FIFO */
Mahir Ozturk 1:efe9cad8942f 848 status = max30003.readRegister( MAX30003::STATUS ); // Read the STATUS register
Mahir Ozturk 1:efe9cad8942f 849
Mahir Ozturk 1:efe9cad8942f 850 // Check if R-to-R interrupt asserted
Mahir Ozturk 1:efe9cad8942f 851 if ((status & RTOR_STATUS) == RTOR_STATUS) {
Mahir Ozturk 1:efe9cad8942f 852
Mahir Ozturk 1:efe9cad8942f 853 daplink.printf("R-to-R Interrupt \r\n");
Mahir Ozturk 1:efe9cad8942f 854
Mahir Ozturk 1:efe9cad8942f 855 // Read RtoR register
Mahir Ozturk 1:efe9cad8942f 856 RtoR = max30003.readRegister( MAX30003::RTOR ) >> RTOR_REG_OFFSET;
Mahir Ozturk 1:efe9cad8942f 857
Mahir Ozturk 1:efe9cad8942f 858 // Convert to BPM
Mahir Ozturk 1:efe9cad8942f 859 BPM = 1.0f / ( RtoR * RTOR_LSB_RES / 60.0f );
Mahir Ozturk 1:efe9cad8942f 860
Mahir Ozturk 1:efe9cad8942f 861 daplink.printf("BPM: %.2f\r\n", BPM);
Mahir Ozturk 1:efe9cad8942f 862
Mahir Ozturk 2:68ffd74e3b5c 863 if (bleNotifyTimer.read_ms() >= (MAX30003_BLE_NOTIFY_PERIOD_SEC * 1000)) {
Mahir Ozturk 2:68ffd74e3b5c 864 bleGattAttrWrite(gattCharBPM.getValueHandle(), (uint8_t *)&BPM, sizeof(BPM));
Mahir Ozturk 2:68ffd74e3b5c 865 bleNotifyTimer.reset();
Mahir Ozturk 2:68ffd74e3b5c 866 }
Mahir Ozturk 1:efe9cad8942f 867 }
Mahir Ozturk 1:efe9cad8942f 868
Mahir Ozturk 1:efe9cad8942f 869 // Check if EINT interrupt asserted
Mahir Ozturk 1:efe9cad8942f 870 if ((status & EINT_STATUS) == EINT_STATUS) {
Mahir Ozturk 1:efe9cad8942f 871 readECGSamples = 0; // Reset sample counter
Mahir Ozturk 1:efe9cad8942f 872
Mahir Ozturk 1:efe9cad8942f 873 do {
Mahir Ozturk 2:68ffd74e3b5c 874 ecgFIFO = max30003.readRegister( MAX30003::ECG_FIFO ); // Read FIFO
Mahir Ozturk 2:68ffd74e3b5c 875 ecgSample[readECGSamples] = ecgFIFO >> 8; // Isolate voltage data
Mahir Ozturk 2:68ffd74e3b5c 876 ETAG[readECGSamples] = ( ecgFIFO >> 3 ) & ETAG_BITS; // Isolate ETAG
Mahir Ozturk 2:68ffd74e3b5c 877 readECGSamples++; // Increment sample counter
Mahir Ozturk 1:efe9cad8942f 878
Mahir Ozturk 1:efe9cad8942f 879 // Check that sample is not last sample in FIFO
Mahir Ozturk 1:efe9cad8942f 880 } while (ETAG[readECGSamples-1] == FIFO_VALID_SAMPLE ||
Mahir Ozturk 1:efe9cad8942f 881 ETAG[readECGSamples-1] == FIFO_FAST_SAMPLE);
Mahir Ozturk 1:efe9cad8942f 882
Mahir Ozturk 1:efe9cad8942f 883 // Check if FIFO has overflowed
Mahir Ozturk 1:efe9cad8942f 884 if (ETAG[readECGSamples - 1] == FIFO_OVF){
Mahir Ozturk 1:efe9cad8942f 885 max30003.writeRegister( MAX30003::FIFO_RST , 0); // Reset FIFO
Mahir Ozturk 1:efe9cad8942f 886 rLED = 1;
Mahir Ozturk 1:efe9cad8942f 887 }
Mahir Ozturk 1:efe9cad8942f 888 }
Mahir Ozturk 1:efe9cad8942f 889 }
Mahir Ozturk 1:efe9cad8942f 890 }
Mahir Ozturk 1:efe9cad8942f 891
Mahir Ozturk 1:efe9cad8942f 892 #endif
Mahir Ozturk 1:efe9cad8942f 893
Mahir Ozturk 1:efe9cad8942f 894 /******************************************************************************
Mahir Ozturk 1:efe9cad8942f 895 ************** MAX11301WING ***************************************************
Mahir Ozturk 1:efe9cad8942f 896 *******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 897 #if defined(LIB_MAX113XX_PIXI)
Mahir Ozturk 1:efe9cad8942f 898
Mahir Ozturk 1:efe9cad8942f 899 #define MAX113XX_DATA_READ_PERIOD_MSEC 2000
Mahir Ozturk 1:efe9cad8942f 900 #define MAX113XX_I2C_ADDRESS 0x38
Mahir Ozturk 1:efe9cad8942f 901
Mahir Ozturk 1:efe9cad8942f 902 Thread thread_max11301_reader;
Mahir Ozturk 1:efe9cad8942f 903
Mahir Ozturk 1:efe9cad8942f 904 void max11301_reader_task()
Mahir Ozturk 1:efe9cad8942f 905 {
Mahir Ozturk 1:efe9cad8942f 906 uint16_t adcData;
Mahir Ozturk 1:efe9cad8942f 907 float adcVoltage;
Mahir Ozturk 1:efe9cad8942f 908
Mahir Ozturk 1:efe9cad8942f 909 MAX113XX_I2C pixi(i2c1, MAX113XX_I2C::MAX11301, MAX113XX_I2C_ADDRESS, P5_5);
Mahir Ozturk 1:efe9cad8942f 910
Mahir Ozturk 1:efe9cad8942f 911 pixi.dacWrite(MAX113XX_Pixi::PORT0, 0x000); // Pixi PORT0 is -5V
Mahir Ozturk 1:efe9cad8942f 912 pixi.dacWrite(MAX113XX_Pixi::PORT1, 0xFFF); // Pixi PORT1 is +5V
Mahir Ozturk 1:efe9cad8942f 913
Mahir Ozturk 1:efe9cad8942f 914 daplink.printf("Starting MAX11301 PIXI ADC Demo Application...\r\n");
Mahir Ozturk 1:efe9cad8942f 915
Mahir Ozturk 1:efe9cad8942f 916 while (1) {
Mahir Ozturk 1:efe9cad8942f 917 pixi.singleEndedADCRead(MAX113XX_Pixi::PORT9, adcData); // Read value from PORT9
Mahir Ozturk 1:efe9cad8942f 918 adcVoltage = -5 + 2.442e-3 * adcData; // Convert ADC val. to a voltage
Mahir Ozturk 1:efe9cad8942f 919
Mahir Ozturk 1:efe9cad8942f 920 daplink.printf("ADC Read is : %i,\tVoltage is %1.3f V \r\n", adcData, adcVoltage);
Mahir Ozturk 1:efe9cad8942f 921
Mahir Ozturk 1:efe9cad8942f 922 bleGattAttrWrite(gattCharADC.getValueHandle(), (uint8_t *)&adcVoltage, sizeof(adcVoltage));
Mahir Ozturk 1:efe9cad8942f 923
Mahir Ozturk 2:68ffd74e3b5c 924 Thread::wait(MAX113XX_PIXI_BLE_NOTIFY_PERIOD_SEC * 1000);
Mahir Ozturk 1:efe9cad8942f 925 }
Mahir Ozturk 1:efe9cad8942f 926 }
Mahir Ozturk 1:efe9cad8942f 927 #endif
Mahir Ozturk 1:efe9cad8942f 928
Mahir Ozturk 1:efe9cad8942f 929 /******************************************************************************
Mahir Ozturk 1:efe9cad8942f 930 ******************************************************************************
Mahir Ozturk 1:efe9cad8942f 931 ******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 932
Mahir Ozturk 1:efe9cad8942f 933 int main()
Mahir Ozturk 1:efe9cad8942f 934 {
Mahir Ozturk 1:efe9cad8942f 935 osStatus status;
Mahir Ozturk 2:68ffd74e3b5c 936 rLED = LED_OFF; gLED = LED_OFF; bLED = LED_OFF; // red
Mahir Ozturk 1:efe9cad8942f 937
Mahir Ozturk 2:68ffd74e3b5c 938 aliveLedEventId = eventQueue.call_every(1000, blinkCallback);
Mahir Ozturk 1:efe9cad8942f 939
Mahir Ozturk 1:efe9cad8942f 940 daplink.printf("Initializing BLE service...\r\n");
Mahir Ozturk 1:efe9cad8942f 941
Mahir Ozturk 2:68ffd74e3b5c 942 BLE &ble = BLE::Instance();
Mahir Ozturk 2:68ffd74e3b5c 943 ble.onEventsToProcess(scheduleBleEventsProcessing);
Mahir Ozturk 2:68ffd74e3b5c 944 ble.init(bleInitComplete);
Mahir Ozturk 1:efe9cad8942f 945
Mahir Ozturk 1:efe9cad8942f 946 #if defined(LIB_MAX30205)
Mahir Ozturk 2:68ffd74e3b5c 947 status = thread_max30205_reader.start(max30205_reader_task);
Mahir Ozturk 2:68ffd74e3b5c 948 if (status != osOK) {
Mahir Ozturk 2:68ffd74e3b5c 949 daplink.printf("Starting thread_max30205_reader thread failed(%d)!\r\n", status);
Mahir Ozturk 2:68ffd74e3b5c 950 }
Mahir Ozturk 1:efe9cad8942f 951 #endif
Mahir Ozturk 1:efe9cad8942f 952
Mahir Ozturk 1:efe9cad8942f 953 #if defined(LIB_MAX30101)
Mahir Ozturk 2:68ffd74e3b5c 954 status = thread_max30101_reader.start(max30101_reader_task);
Mahir Ozturk 2:68ffd74e3b5c 955 if (status != osOK) {
Mahir Ozturk 2:68ffd74e3b5c 956 daplink.printf("Starting thread_max30205_reader thread failed(%d)!\r\n", status);
Mahir Ozturk 2:68ffd74e3b5c 957 }
Mahir Ozturk 1:efe9cad8942f 958 #endif
Mahir Ozturk 1:efe9cad8942f 959
Mahir Ozturk 1:efe9cad8942f 960 #if defined(LIB_MAX30003)
Mahir Ozturk 2:68ffd74e3b5c 961 status = thread_max30003_reader.start(max30003_reader_task);
Mahir Ozturk 2:68ffd74e3b5c 962 if (status != osOK) {
Mahir Ozturk 2:68ffd74e3b5c 963 daplink.printf("Starting thread_max30205_reader thread failed(%d)!\r\n", status);
Mahir Ozturk 2:68ffd74e3b5c 964 }
Mahir Ozturk 1:efe9cad8942f 965 #endif
Mahir Ozturk 1:efe9cad8942f 966
Mahir Ozturk 1:efe9cad8942f 967 #if defined(LIB_MAX113XX_PIXI)
Mahir Ozturk 2:68ffd74e3b5c 968 status = thread_max11301_reader.start(max11301_reader_task);
Mahir Ozturk 2:68ffd74e3b5c 969 if (status != osOK) {
Mahir Ozturk 2:68ffd74e3b5c 970 daplink.printf("Starting thread_max30205_reader thread failed(%d)!\r\n", status);
Mahir Ozturk 2:68ffd74e3b5c 971 }
Mahir Ozturk 1:efe9cad8942f 972 #endif
Mahir Ozturk 1:efe9cad8942f 973
Mahir Ozturk 2:68ffd74e3b5c 974 eventQueue.dispatch_forever();
Mahir Ozturk 1:efe9cad8942f 975
Mahir Ozturk 2:68ffd74e3b5c 976 return 0;
Mahir Ozturk 1:efe9cad8942f 977 }
Mahir Ozturk 1:efe9cad8942f 978