Maxim Integrated's IoT development kit.

Dependencies:   MAX30101 MAX30003 MAX113XX_Pixi MAX30205 max32630fthr USBDevice

Committer:
Mahir Ozturk
Date:
Fri May 04 11:51:53 2018 +0300
Revision:
10:dbeda3ffffb8
Parent:
7:2c9c8b6a28a7
Child:
11:04292fba5078
Remove compiler warnings, cosmetic changes

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 7:2c9c8b6a28a7 33 #include <config.h>
Mahir Ozturk 7:2c9c8b6a28a7 34 #include <mbed.h>
Mahir Ozturk 1:efe9cad8942f 35 #include <events/mbed_events.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 10:dbeda3ffffb8 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 10:dbeda3ffffb8 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 10:dbeda3ffffb8 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 10:dbeda3ffffb8 215 rLED = (params->data[0] != 0) ? LED_OFF : LED_ON;
Mahir Ozturk 10:dbeda3ffffb8 216 gLED = (params->data[1] != 0) ? LED_OFF : LED_ON;
Mahir Ozturk 10:dbeda3ffffb8 217 bLED = (params->data[2] != 0) ? LED_OFF : LED_ON;
Mahir Ozturk 10:dbeda3ffffb8 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 10:dbeda3ffffb8 223 BLE& ble = params->ble;
Mahir Ozturk 10:dbeda3ffffb8 224 ble_error_t error = params->error;
Mahir Ozturk 1:efe9cad8942f 225
Mahir Ozturk 10:dbeda3ffffb8 226 if (error != BLE_ERROR_NONE) {
Mahir Ozturk 10:dbeda3ffffb8 227 /* In case of error, forward the error handling to onBleInitError */
Mahir Ozturk 10:dbeda3ffffb8 228 onBleInitError(ble, error);
Mahir Ozturk 10:dbeda3ffffb8 229 return;
Mahir Ozturk 10:dbeda3ffffb8 230 }
Mahir Ozturk 1:efe9cad8942f 231
Mahir Ozturk 10:dbeda3ffffb8 232 /* Ensure that it is the default instance of BLE */
Mahir Ozturk 10:dbeda3ffffb8 233 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
Mahir Ozturk 10:dbeda3ffffb8 234 return;
Mahir Ozturk 10:dbeda3ffffb8 235 }
Mahir Ozturk 1:efe9cad8942f 236
Mahir Ozturk 10:dbeda3ffffb8 237 ble.gap().onDisconnection(disconnectionCallback);
Mahir Ozturk 10:dbeda3ffffb8 238 ble.gap().onConnection(connectionCallback);
Mahir Ozturk 1:efe9cad8942f 239
Mahir Ozturk 10:dbeda3ffffb8 240 ble.gattServer().onDataWritten(onDataWrittenCallback);
Mahir Ozturk 1:efe9cad8942f 241
Mahir Ozturk 10:dbeda3ffffb8 242 ble.gattServer().addService(iotService);
Mahir Ozturk 1:efe9cad8942f 243
Mahir Ozturk 10:dbeda3ffffb8 244 /* setup advertising */
Mahir Ozturk 10:dbeda3ffffb8 245 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
Mahir Ozturk 10:dbeda3ffffb8 246 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
Mahir Ozturk 10:dbeda3ffffb8 247 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
Mahir Ozturk 10:dbeda3ffffb8 248 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
Mahir Ozturk 10:dbeda3ffffb8 249 ble.gap().setAdvertisingInterval(1000); /* 1000ms. */
Mahir Ozturk 10:dbeda3ffffb8 250 ble.gap().startAdvertising();
Mahir Ozturk 1:efe9cad8942f 251
Mahir Ozturk 10:dbeda3ffffb8 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 10:dbeda3ffffb8 256 BLE &ble = BLE::Instance();
Mahir Ozturk 10:dbeda3ffffb8 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 1:efe9cad8942f 265 MAX30205 max30205_temp_sensor(i2c1, 0x48); /* New MAX30205 on i2cBus */
Mahir Ozturk 1:efe9cad8942f 266
Mahir Ozturk 1:efe9cad8942f 267 Thread thread_max30205_reader;
Mahir Ozturk 1:efe9cad8942f 268
Mahir Ozturk 1:efe9cad8942f 269 bool max30205_config(MAX30205 &temp_sensor){
Mahir Ozturk 1:efe9cad8942f 270
Mahir Ozturk 10:dbeda3ffffb8 271 int rc = 0;
Mahir Ozturk 1:efe9cad8942f 272
Mahir Ozturk 10:dbeda3ffffb8 273 MAX30205::Configuration_u temp_cfg;
Mahir Ozturk 10:dbeda3ffffb8 274 temp_cfg.all = 0;
Mahir Ozturk 10:dbeda3ffffb8 275 temp_cfg.bits.shutdown = 1; // Shutdown mode
Mahir Ozturk 10:dbeda3ffffb8 276 temp_cfg.bits.comp_int = 1; // Interrupt mode
Mahir Ozturk 10:dbeda3ffffb8 277 temp_cfg.bits.os_polarity = 0; // Active low OS
Mahir Ozturk 10:dbeda3ffffb8 278 temp_cfg.bits.fault_queue = 1; // Two faults for OS condition
Mahir Ozturk 10:dbeda3ffffb8 279 temp_cfg.bits.data_format = 0; // Normal data format
Mahir Ozturk 10:dbeda3ffffb8 280 temp_cfg.bits.timeout = 0; // I2C timeout reset enabled
Mahir Ozturk 10:dbeda3ffffb8 281 temp_cfg.bits.one_shot = 0; // Start with one-shot = 0
Mahir Ozturk 1:efe9cad8942f 282
Mahir Ozturk 10:dbeda3ffffb8 283 rc = temp_sensor.writeConfiguration(temp_cfg); // Write config to MAX30205
Mahir Ozturk 1:efe9cad8942f 284
Mahir Ozturk 10:dbeda3ffffb8 285 return rc;
Mahir Ozturk 1:efe9cad8942f 286 }
Mahir Ozturk 1:efe9cad8942f 287
Mahir Ozturk 1:efe9cad8942f 288 void max30205_reader_task()
Mahir Ozturk 1:efe9cad8942f 289 {
Mahir Ozturk 1:efe9cad8942f 290 int rc = max30205_config(max30205_temp_sensor); // Configure sensor, return 0 on success
Mahir Ozturk 1:efe9cad8942f 291
Mahir Ozturk 1:efe9cad8942f 292 MAX30205::Configuration_u temp_cfg;
Mahir Ozturk 1:efe9cad8942f 293 uint16_t rawTemperatureRead;
Mahir Ozturk 1:efe9cad8942f 294 float temperature;
Mahir Ozturk 1:efe9cad8942f 295
Mahir Ozturk 1:efe9cad8942f 296 temp_cfg.all = 0;
Mahir Ozturk 1:efe9cad8942f 297
Mahir Ozturk 1:efe9cad8942f 298 daplink.printf("Starting MAX30205 Temperature Demo Application...\r\n");
Mahir Ozturk 1:efe9cad8942f 299
Mahir Ozturk 1:efe9cad8942f 300 while (1) {
Mahir Ozturk 1:efe9cad8942f 301 if (rc == 0) {
Mahir Ozturk 1:efe9cad8942f 302 /* Send one-shot cmd to begin conversion */
Mahir Ozturk 1:efe9cad8942f 303 temp_cfg.bits.one_shot = 1;
Mahir Ozturk 1:efe9cad8942f 304 rc = max30205_temp_sensor.writeConfiguration(temp_cfg);
Mahir Ozturk 1:efe9cad8942f 305
Mahir Ozturk 1:efe9cad8942f 306 Thread::wait(50);
Mahir Ozturk 1:efe9cad8942f 307
Mahir Ozturk 1:efe9cad8942f 308 /* Read the temperature data */
Mahir Ozturk 1:efe9cad8942f 309 rc = max30205_temp_sensor.readTemperature(rawTemperatureRead);
Mahir Ozturk 1:efe9cad8942f 310
Mahir Ozturk 1:efe9cad8942f 311 /* Convert temp data to Celsius */
Mahir Ozturk 1:efe9cad8942f 312 temperature = max30205_temp_sensor.toCelsius(rawTemperatureRead);
Mahir Ozturk 1:efe9cad8942f 313
Mahir Ozturk 1:efe9cad8942f 314 bleGattAttrWrite(gattCharTemp.getValueHandle(), (uint8_t *)&temperature, sizeof(temperature));
Mahir Ozturk 1:efe9cad8942f 315 daplink.printf("Temperature is %2.3f deg. C\r\n", temperature);
Mahir Ozturk 1:efe9cad8942f 316
Mahir Ozturk 2:68ffd74e3b5c 317 Thread::wait(MAX30205_BLE_NOTIFY_PERIOD_SEC * 1000);
Mahir Ozturk 1:efe9cad8942f 318
Mahir Ozturk 1:efe9cad8942f 319 } else {
Mahir Ozturk 1:efe9cad8942f 320 daplink.printf("Something went wrong, check the I2C bus and power connections...\r\n");
Mahir Ozturk 1:efe9cad8942f 321
Mahir Ozturk 2:68ffd74e3b5c 322 return;
Mahir Ozturk 1:efe9cad8942f 323 }
Mahir Ozturk 1:efe9cad8942f 324 }
Mahir Ozturk 1:efe9cad8942f 325 }
Mahir Ozturk 1:efe9cad8942f 326 #endif
Mahir Ozturk 1:efe9cad8942f 327
Mahir Ozturk 1:efe9cad8942f 328 /******************************************************************************
Mahir Ozturk 1:efe9cad8942f 329 ************** MAX30101WING **************************************************
Mahir Ozturk 1:efe9cad8942f 330 ******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 331 #if defined(LIB_MAX30101)
Mahir Ozturk 1:efe9cad8942f 332 #define MAX30101_IRQ_ASSERTED_ID 1
Mahir Ozturk 1:efe9cad8942f 333
Mahir Ozturk 1:efe9cad8942f 334 //variable for the algorithm
Mahir Ozturk 10:dbeda3ffffb8 335 uint16_t sampleRate = 100;
Mahir Ozturk 10:dbeda3ffffb8 336 uint16_t compSpO2 = 1;
Mahir Ozturk 10:dbeda3ffffb8 337 int16_t ir_ac_comp = 0;
Mahir Ozturk 10:dbeda3ffffb8 338 int16_t red_ac_comp = 0;
Mahir Ozturk 10:dbeda3ffffb8 339 int16_t green_ac_comp = 0;
Mahir Ozturk 10:dbeda3ffffb8 340 int16_t ir_ac_mag = 0;
Mahir Ozturk 10:dbeda3ffffb8 341 int16_t red_ac_mag = 0;
Mahir Ozturk 10:dbeda3ffffb8 342 int16_t green_ac_mag = 0;
Mahir Ozturk 10:dbeda3ffffb8 343 uint16_t HRbpm2 = 0;
Mahir Ozturk 10:dbeda3ffffb8 344 uint16_t SpO2B = 0;
Mahir Ozturk 10:dbeda3ffffb8 345 uint16_t DRdy = 0;
Mahir Ozturk 1:efe9cad8942f 346
Mahir Ozturk 1:efe9cad8942f 347 //declare large variables outside of main
Mahir Ozturk 1:efe9cad8942f 348 uint32_t redData[500];//set array to max fifo size
Mahir Ozturk 1:efe9cad8942f 349 uint32_t irData[500];//set array to max fifo size
Mahir Ozturk 1:efe9cad8942f 350 uint32_t greenData[500];//set array to max fifo size
Mahir Ozturk 1:efe9cad8942f 351
Mahir Ozturk 1:efe9cad8942f 352 Thread thread_max30101_reader;
Mahir Ozturk 1:efe9cad8942f 353
Mahir Ozturk 1:efe9cad8942f 354 bool max30101_config(MAX30101 &op_sensor)
Mahir Ozturk 1:efe9cad8942f 355 {
Mahir Ozturk 10:dbeda3ffffb8 356 //Reset Device
Mahir Ozturk 10:dbeda3ffffb8 357 MAX30101::ModeConfiguration_u modeConfig;
Mahir Ozturk 10:dbeda3ffffb8 358 modeConfig.all = 0;
Mahir Ozturk 10:dbeda3ffffb8 359 modeConfig.bits.reset = 1;
Mahir Ozturk 10:dbeda3ffffb8 360 modeConfig.bits.mode = MAX30101::MultiLedMode; // Sets SPO2 Mode
Mahir Ozturk 10:dbeda3ffffb8 361 int32_t rc = op_sensor.setModeConfiguration(modeConfig);
Mahir Ozturk 1:efe9cad8942f 362
Mahir Ozturk 10:dbeda3ffffb8 363 //enable MAX30101 interrupts
Mahir Ozturk 10:dbeda3ffffb8 364 MAX30101::InterruptBitField_u ints;
Mahir Ozturk 10:dbeda3ffffb8 365 if (rc == 0) {
Mahir Ozturk 10:dbeda3ffffb8 366 ints.all = 0;
Mahir Ozturk 10:dbeda3ffffb8 367 ints.bits.a_full = 1; // Enable FIFO almost full interrupt
Mahir Ozturk 10:dbeda3ffffb8 368 ints.bits.ppg_rdy =1; //Enables an interrupt when a new sample is ready
Mahir Ozturk 10:dbeda3ffffb8 369 rc = op_sensor.enableInterrupts(ints);
Mahir Ozturk 10:dbeda3ffffb8 370 }
Mahir Ozturk 1:efe9cad8942f 371
Mahir Ozturk 10:dbeda3ffffb8 372 //configure FIFO
Mahir Ozturk 10:dbeda3ffffb8 373 MAX30101::FIFO_Configuration_u fifoConfig;
Mahir Ozturk 10:dbeda3ffffb8 374 if (rc == 0) {
Mahir Ozturk 10:dbeda3ffffb8 375 fifoConfig.all = 0;
Mahir Ozturk 10:dbeda3ffffb8 376 fifoConfig.bits.fifo_a_full = 10; // Max level of 17 samples
Mahir Ozturk 10:dbeda3ffffb8 377 fifoConfig.bits.sample_average = MAX30101::AveragedSamples_0;// Average 0 samples
Mahir Ozturk 10:dbeda3ffffb8 378 rc = op_sensor.setFIFOConfiguration(fifoConfig);
Mahir Ozturk 10:dbeda3ffffb8 379 }
Mahir Ozturk 1:efe9cad8942f 380
Mahir Ozturk 10:dbeda3ffffb8 381 MAX30101::SpO2Configuration_u spo2Config;
Mahir Ozturk 10:dbeda3ffffb8 382 if (rc == 0) {
Mahir Ozturk 10:dbeda3ffffb8 383 spo2Config.all = 0; // clears register
Mahir Ozturk 10:dbeda3ffffb8 384 spo2Config.bits.spo2_adc_range = 1; //sets resolution to 4096 nAfs
Mahir Ozturk 10:dbeda3ffffb8 385 spo2Config.bits.spo2_sr = MAX30101::SR_100_Hz; // SpO2 SR = 100Hz
Mahir Ozturk 10:dbeda3ffffb8 386 spo2Config.bits.led_pw = MAX30101::PW_3; // 18-bit ADC resolution ~400us
Mahir Ozturk 10:dbeda3ffffb8 387 rc = op_sensor.setSpO2Configuration(spo2Config);
Mahir Ozturk 10:dbeda3ffffb8 388 }
Mahir Ozturk 1:efe9cad8942f 389
Mahir Ozturk 10:dbeda3ffffb8 390 //Set time slots for LEDS
Mahir Ozturk 10:dbeda3ffffb8 391 MAX30101::ModeControlReg_u multiLED;
Mahir Ozturk 10:dbeda3ffffb8 392 if (rc == 0) {
Mahir Ozturk 10:dbeda3ffffb8 393 //sets timing for control register 1
Mahir Ozturk 10:dbeda3ffffb8 394 multiLED.bits.lo_slot=1;
Mahir Ozturk 10:dbeda3ffffb8 395 multiLED.bits.hi_slot=2;
Mahir Ozturk 10:dbeda3ffffb8 396 rc = op_sensor.setMultiLEDModeControl(MAX30101::ModeControlReg1, multiLED);
Mahir Ozturk 10:dbeda3ffffb8 397 if (rc == 0) {
Mahir Ozturk 10:dbeda3ffffb8 398 multiLED.bits.lo_slot=3;
Mahir Ozturk 10:dbeda3ffffb8 399 multiLED.bits.hi_slot=0;
Mahir Ozturk 10:dbeda3ffffb8 400 rc = op_sensor.setMultiLEDModeControl(MAX30101::ModeControlReg2, multiLED);
Mahir Ozturk 10:dbeda3ffffb8 401 }
Mahir Ozturk 10:dbeda3ffffb8 402 }
Mahir Ozturk 1:efe9cad8942f 403
Mahir Ozturk 10:dbeda3ffffb8 404 //Set LED drive currents
Mahir Ozturk 10:dbeda3ffffb8 405 if (rc == 0) {
Mahir Ozturk 10:dbeda3ffffb8 406 // Heart Rate only, 1 LED channel, Pulse amp. = ~7mA
Mahir Ozturk 10:dbeda3ffffb8 407 rc = op_sensor.setLEDPulseAmplitude(MAX30101::LED1_PA, 0x24);
Mahir Ozturk 10:dbeda3ffffb8 408 //To include SPO2, 2 LED channel, Pulse amp. ~7mA
Mahir Ozturk 10:dbeda3ffffb8 409 if (rc == 0) {
Mahir Ozturk 10:dbeda3ffffb8 410 rc = op_sensor.setLEDPulseAmplitude(MAX30101::LED2_PA, 0x24);
Mahir Ozturk 10:dbeda3ffffb8 411 }
Mahir Ozturk 10:dbeda3ffffb8 412 if (rc == 0) {
Mahir Ozturk 10:dbeda3ffffb8 413 rc = op_sensor.setLEDPulseAmplitude(MAX30101::LED3_PA, 0x24);
Mahir Ozturk 10:dbeda3ffffb8 414 }
Mahir Ozturk 10:dbeda3ffffb8 415 }
Mahir Ozturk 1:efe9cad8942f 416
Mahir Ozturk 10:dbeda3ffffb8 417 //Set operating mode
Mahir Ozturk 10:dbeda3ffffb8 418 modeConfig.all = 0;
Mahir Ozturk 10:dbeda3ffffb8 419 if (rc == 0) {
Mahir Ozturk 10:dbeda3ffffb8 420 modeConfig.bits.mode = MAX30101::MultiLedMode; // Sets multiLED mode
Mahir Ozturk 10:dbeda3ffffb8 421 rc = op_sensor.setModeConfiguration(modeConfig);
Mahir Ozturk 10:dbeda3ffffb8 422 }
Mahir Ozturk 1:efe9cad8942f 423
Mahir Ozturk 10:dbeda3ffffb8 424 return rc;
Mahir Ozturk 1:efe9cad8942f 425 }
Mahir Ozturk 1:efe9cad8942f 426
Mahir Ozturk 1:efe9cad8942f 427 void max30101wing_pmic_config(I2C & i2c_bus, DigitalOut & pmic_en)
Mahir Ozturk 1:efe9cad8942f 428 {
Mahir Ozturk 10:dbeda3ffffb8 429 const uint8_t PMIC_ADRS = 0x54;
Mahir Ozturk 10:dbeda3ffffb8 430 const uint8_t BBB_EXTRA_ADRS = 0x1C;
Mahir Ozturk 10:dbeda3ffffb8 431 const uint8_t BOOST_VOLTAGE = 0x05;
Mahir Ozturk 1:efe9cad8942f 432
Mahir Ozturk 10:dbeda3ffffb8 433 char data_buff[] = {BBB_EXTRA_ADRS, 0x40}; //BBBExtra register address
Mahir Ozturk 10:dbeda3ffffb8 434 //and data to enable passive
Mahir Ozturk 10:dbeda3ffffb8 435 //pull down.
Mahir Ozturk 10:dbeda3ffffb8 436 i2c_bus.write(PMIC_ADRS, data_buff,2); //write to BBBExtra register
Mahir Ozturk 1:efe9cad8942f 437
Mahir Ozturk 10:dbeda3ffffb8 438 data_buff[0] = BOOST_VOLTAGE;
Mahir Ozturk 10:dbeda3ffffb8 439 data_buff[1] = 0x08; //Boost voltage configuration
Mahir Ozturk 10:dbeda3ffffb8 440 //register followed by data
Mahir Ozturk 10:dbeda3ffffb8 441 //to set voltage to 4.5V 1f
Mahir Ozturk 10:dbeda3ffffb8 442 pmic_en = 0; //disables VLED 08
Mahir Ozturk 10:dbeda3ffffb8 443 i2c_bus.write(PMIC_ADRS, data_buff,2); //write to BBBExtra register
Mahir Ozturk 10:dbeda3ffffb8 444 pmic_en = 1; //enables VLED
Mahir Ozturk 1:efe9cad8942f 445 }
Mahir Ozturk 1:efe9cad8942f 446
Mahir Ozturk 1:efe9cad8942f 447 /* Op Sensor FIFO nearly full callback */
Mahir Ozturk 1:efe9cad8942f 448 void max30101_intr_callback()
Mahir Ozturk 1:efe9cad8942f 449 {
Mahir Ozturk 1:efe9cad8942f 450 thread_max30101_reader.signal_set(MAX30101_IRQ_ASSERTED_ID);
Mahir Ozturk 1:efe9cad8942f 451 }
Mahir Ozturk 1:efe9cad8942f 452
Mahir Ozturk 1:efe9cad8942f 453 void max30101_reader_task()
Mahir Ozturk 1:efe9cad8942f 454 {
Mahir Ozturk 1:efe9cad8942f 455 InterruptIn op_sensor_int(P3_2); // Config P3_2 as int. in for
Mahir Ozturk 1:efe9cad8942f 456 op_sensor_int.fall(max30101_intr_callback); // FIFO ready interrupt
Mahir Ozturk 1:efe9cad8942f 457
Mahir Ozturk 1:efe9cad8942f 458 DigitalOut VLED_EN(P3_3,0); //Enable for VLEDs
Mahir Ozturk 1:efe9cad8942f 459 max30101wing_pmic_config(i2c1, VLED_EN);
Mahir Ozturk 1:efe9cad8942f 460
Mahir Ozturk 1:efe9cad8942f 461 MAX30101 op_sensor(i2c1); // Create new MAX30101 on i2cBus
Mahir Ozturk 1:efe9cad8942f 462 int rc = max30101_config(op_sensor); // Config sensor, return 0 on success
Mahir Ozturk 1:efe9cad8942f 463
Mahir Ozturk 1:efe9cad8942f 464 MAX30101::InterruptBitField_u ints; // Read interrupt status to clear
Mahir Ozturk 1:efe9cad8942f 465 rc = op_sensor.getInterruptStatus(ints); // power on interrupt
Mahir Ozturk 1:efe9cad8942f 466
Mahir Ozturk 1:efe9cad8942f 467 uint8_t fifoData[MAX30101::MAX_FIFO_BYTES];
Mahir Ozturk 1:efe9cad8942f 468 uint16_t idx, readBytes;
Mahir Ozturk 1:efe9cad8942f 469 uint16_t HRTemp;
Mahir Ozturk 1:efe9cad8942f 470 uint16_t spo2Temp;
Mahir Ozturk 1:efe9cad8942f 471
Mahir Ozturk 2:68ffd74e3b5c 472 uint16_t lastValidHR = 0;
Mahir Ozturk 2:68ffd74e3b5c 473 uint16_t lastValidSPO2 = 0;
Mahir Ozturk 2:68ffd74e3b5c 474
Mahir Ozturk 1:efe9cad8942f 475 int r=0; //counter for redData position
Mahir Ozturk 1:efe9cad8942f 476 int ir=0; //counter for irData position
Mahir Ozturk 1:efe9cad8942f 477 int g =0; //counter for greenData position
Mahir Ozturk 1:efe9cad8942f 478 int c=0; //counter to print values
Mahir Ozturk 1:efe9cad8942f 479
Mahir Ozturk 1:efe9cad8942f 480 daplink.printf("Starting MAX30101 HeartRate / SPO2 Demo Application...\r\n");
Mahir Ozturk 1:efe9cad8942f 481 daplink.printf("Please wait a few seconds while data is being collected.\r\n");
Mahir Ozturk 1:efe9cad8942f 482
Mahir Ozturk 10:dbeda3ffffb8 483 Timer bleNotifyTimer;
Mahir Ozturk 2:68ffd74e3b5c 484
Mahir Ozturk 10:dbeda3ffffb8 485 bleNotifyTimer.start();
Mahir Ozturk 2:68ffd74e3b5c 486
Mahir Ozturk 1:efe9cad8942f 487 while (1) {
Mahir Ozturk 1:efe9cad8942f 488 if (rc == 0) {
Mahir Ozturk 1:efe9cad8942f 489 /* Check if op_sensor interrupt asserted */
Mahir Ozturk 1:efe9cad8942f 490 Thread::signal_wait(MAX30101_IRQ_ASSERTED_ID);
Mahir Ozturk 1:efe9cad8942f 491
Mahir Ozturk 1:efe9cad8942f 492 /* Read interrupt status to clear interrupt */
Mahir Ozturk 1:efe9cad8942f 493 rc = op_sensor.getInterruptStatus(ints);
Mahir Ozturk 1:efe9cad8942f 494
Mahir Ozturk 1:efe9cad8942f 495 /* Confirms proper read prior to executing */
Mahir Ozturk 1:efe9cad8942f 496 if (rc == 0) {
Mahir Ozturk 1:efe9cad8942f 497 // Read FIFO
Mahir Ozturk 1:efe9cad8942f 498 rc = op_sensor.readFIFO(MAX30101::ThreeLedChannels, fifoData, readBytes);
Mahir Ozturk 1:efe9cad8942f 499
Mahir Ozturk 1:efe9cad8942f 500 if (rc == 0) {
Mahir Ozturk 1:efe9cad8942f 501 /* Convert read bytes into samples */
Mahir Ozturk 1:efe9cad8942f 502 for (idx = 0; idx < readBytes; idx+=9) {
Mahir Ozturk 1:efe9cad8942f 503 if (r >= 500 || ir >= 500 || g >= 500) {
Mahir Ozturk 6:aeb5a4c194c3 504 daplink.printf("Overflow! r=%d ir=%d g=%d\r\n", r, ir, g);
Mahir Ozturk 6:aeb5a4c194c3 505 break;
Mahir Ozturk 1:efe9cad8942f 506 }
Mahir Ozturk 1:efe9cad8942f 507
Mahir Ozturk 1:efe9cad8942f 508 if (readBytes >= (idx + 8)) {
Mahir Ozturk 6:aeb5a4c194c3 509 redData[r++] = ((fifoData[idx] << 16) | (fifoData[idx + 1] << 8) | (fifoData[idx + 2])) & 0x03FFFF;
Mahir Ozturk 6:aeb5a4c194c3 510 irData[ir++] = ((fifoData[idx + 3] << 16) | (fifoData[idx + 4] << 8) | (fifoData[idx + 5])) & 0x03FFFF;
Mahir Ozturk 1:efe9cad8942f 511 greenData[g++] = ((fifoData[idx + 6] << 16) | (fifoData[idx + 7] << 8) | (fifoData[idx + 8])) & 0x03FFFF;
Mahir Ozturk 1:efe9cad8942f 512 }
Mahir Ozturk 1:efe9cad8942f 513 }
Mahir Ozturk 1:efe9cad8942f 514
Mahir Ozturk 1:efe9cad8942f 515 if ((r >= 500) && (ir >= 500) && (g >= 500)) {/* checks to make sure there are 500 */
Mahir Ozturk 1:efe9cad8942f 516 /* samples in data buffers */
Mahir Ozturk 1:efe9cad8942f 517
Mahir Ozturk 1:efe9cad8942f 518 /* runs the heart rate and SpO2 algorithm */
Mahir Ozturk 1:efe9cad8942f 519 for (c = 0, HRTemp = 0; c < r; c++) {
Mahir Ozturk 1:efe9cad8942f 520 HRSpO2Func(irData[c], redData[c],greenData[c], c,sampleRate, compSpO2,
Mahir Ozturk 1:efe9cad8942f 521 &ir_ac_comp,&red_ac_comp, &green_ac_comp, &ir_ac_mag,&red_ac_mag,
Mahir Ozturk 1:efe9cad8942f 522 &green_ac_mag, &HRbpm2,&SpO2B,&DRdy);
Mahir Ozturk 1:efe9cad8942f 523 if (DRdy) {
Mahir Ozturk 1:efe9cad8942f 524 HRTemp = HRbpm2;
Mahir Ozturk 1:efe9cad8942f 525 spo2Temp = SpO2B;
Mahir Ozturk 1:efe9cad8942f 526 }
Mahir Ozturk 1:efe9cad8942f 527 }
Mahir Ozturk 1:efe9cad8942f 528
Mahir Ozturk 1:efe9cad8942f 529 /* If the above algorithm returns a valid heart rate on the last sample, it is printed */
Mahir Ozturk 1:efe9cad8942f 530 if (DRdy == 1) {
Mahir Ozturk 1:efe9cad8942f 531 daplink.printf("Heart Rate = %i\r\n",HRbpm2);
Mahir Ozturk 1:efe9cad8942f 532 daplink.printf("SPO2 = %i\r\n",SpO2B);
Mahir Ozturk 2:68ffd74e3b5c 533 lastValidHR = HRbpm2;
Mahir Ozturk 2:68ffd74e3b5c 534 lastValidSPO2 = SpO2B;
Mahir Ozturk 1:efe9cad8942f 535 } else if (HRTemp != 0) { /* if a valid heart was calculated at all, it is printed */
Mahir Ozturk 1:efe9cad8942f 536 daplink.printf("Heart Rate = %i\r\n",HRTemp);
Mahir Ozturk 1:efe9cad8942f 537 daplink.printf("SPO2 = %i\r\n",spo2Temp);
Mahir Ozturk 2:68ffd74e3b5c 538 lastValidHR = HRTemp;
Mahir Ozturk 2:68ffd74e3b5c 539 lastValidSPO2 = spo2Temp;
Mahir Ozturk 1:efe9cad8942f 540 } else {
Mahir Ozturk 1:efe9cad8942f 541 daplink.printf("Calculation failed...waiting for more samples...\r\n");
Mahir Ozturk 1:efe9cad8942f 542 daplink.printf("Please keep your finger on the MAX30101 sensor with minimal movement.\r\n");
Mahir Ozturk 1:efe9cad8942f 543 }
Mahir Ozturk 1:efe9cad8942f 544
Mahir Ozturk 1:efe9cad8942f 545 /* dump the first hundred samples after calculation */
Mahir Ozturk 1:efe9cad8942f 546 for (c = 100; c < 500; c++) {
Mahir Ozturk 1:efe9cad8942f 547 redData[c - 100] = redData[c];
Mahir Ozturk 1:efe9cad8942f 548 irData[c - 100] = irData[c];
Mahir Ozturk 1:efe9cad8942f 549 greenData[c - 100] = greenData[c];
Mahir Ozturk 1:efe9cad8942f 550 }
Mahir Ozturk 1:efe9cad8942f 551
Mahir Ozturk 1:efe9cad8942f 552 /* reset counters */
Mahir Ozturk 1:efe9cad8942f 553 r = 400;
Mahir Ozturk 1:efe9cad8942f 554 ir = 400;
Mahir Ozturk 1:efe9cad8942f 555 g = 400;
Mahir Ozturk 1:efe9cad8942f 556 }
Mahir Ozturk 2:68ffd74e3b5c 557
Mahir Ozturk 2:68ffd74e3b5c 558 if (bleNotifyTimer.read_ms() >= (MAX30101_BLE_NOTIFY_PERIOD_SEC * 1000)) {
Mahir Ozturk 2:68ffd74e3b5c 559 bleGattAttrWrite(gattCharHeartRate.getValueHandle(), (uint8_t *)&lastValidHR, sizeof(lastValidHR));
Mahir Ozturk 2:68ffd74e3b5c 560 bleGattAttrWrite(gattCharSPO2.getValueHandle(), (uint8_t *)&lastValidSPO2, sizeof(lastValidSPO2));
Mahir Ozturk 2:68ffd74e3b5c 561 bleNotifyTimer.reset();
Mahir Ozturk 2:68ffd74e3b5c 562 }
Mahir Ozturk 1:efe9cad8942f 563 }
Mahir Ozturk 1:efe9cad8942f 564 }
Mahir Ozturk 1:efe9cad8942f 565 } else { // If rc != 0, a communication error has occurred
Mahir Ozturk 1:efe9cad8942f 566
Mahir Ozturk 1:efe9cad8942f 567 daplink.printf("Something went wrong, "
Mahir Ozturk 1:efe9cad8942f 568 "check the I2C bus or power connections... \r\n");
Mahir Ozturk 1:efe9cad8942f 569
Mahir Ozturk 2:68ffd74e3b5c 570 return;
Mahir Ozturk 1:efe9cad8942f 571 }
Mahir Ozturk 1:efe9cad8942f 572
Mahir Ozturk 1:efe9cad8942f 573 }
Mahir Ozturk 1:efe9cad8942f 574 }
Mahir Ozturk 1:efe9cad8942f 575 #endif
Mahir Ozturk 1:efe9cad8942f 576
Mahir Ozturk 1:efe9cad8942f 577 /******************************************************************************
Mahir Ozturk 1:efe9cad8942f 578 ************** MAX30003WING (ECG) *********************************************
Mahir Ozturk 1:efe9cad8942f 579 ******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 580 #if defined(LIB_MAX30003_ECG)
Mahir Ozturk 1:efe9cad8942f 581 #define MAX30003_IRQ_ASSERTED_SIGNAL_ID 1
Mahir Ozturk 1:efe9cad8942f 582
Mahir Ozturk 1:efe9cad8942f 583 MAX30003 max30003(spim2, SPI2_SS); /* MAX30003WING board */
Mahir Ozturk 1:efe9cad8942f 584
Mahir Ozturk 1:efe9cad8942f 585 Thread thread_max30003_reader;
Mahir Ozturk 1:efe9cad8942f 586
Mahir Ozturk 1:efe9cad8942f 587 void ecg_config(MAX30003& ecgAFE) {
Mahir Ozturk 10:dbeda3ffffb8 588 // Reset ECG to clear registers
Mahir Ozturk 10:dbeda3ffffb8 589 ecgAFE.writeRegister( MAX30003::SW_RST , 0);
Mahir Ozturk 1:efe9cad8942f 590
Mahir Ozturk 10:dbeda3ffffb8 591 // General config register setting
Mahir Ozturk 10:dbeda3ffffb8 592 MAX30003::GeneralConfiguration_u CNFG_GEN_r;
Mahir Ozturk 10:dbeda3ffffb8 593 CNFG_GEN_r.bits.en_ecg = 1; // Enable ECG channel
Mahir Ozturk 10:dbeda3ffffb8 594 CNFG_GEN_r.bits.rbiasn = 1; // Enable resistive bias on negative input
Mahir Ozturk 10:dbeda3ffffb8 595 CNFG_GEN_r.bits.rbiasp = 1; // Enable resistive bias on positive input
Mahir Ozturk 10:dbeda3ffffb8 596 CNFG_GEN_r.bits.en_rbias = 1; // Enable resistive bias
Mahir Ozturk 10:dbeda3ffffb8 597 CNFG_GEN_r.bits.imag = 2; // Current magnitude = 10nA
Mahir Ozturk 10:dbeda3ffffb8 598 CNFG_GEN_r.bits.en_dcloff = 1; // Enable DC lead-off detection
Mahir Ozturk 10:dbeda3ffffb8 599 ecgAFE.writeRegister( MAX30003::CNFG_GEN , CNFG_GEN_r.all);
Mahir Ozturk 1:efe9cad8942f 600
Mahir Ozturk 1:efe9cad8942f 601
Mahir Ozturk 10:dbeda3ffffb8 602 // ECG Config register setting
Mahir Ozturk 10:dbeda3ffffb8 603 MAX30003::ECGConfiguration_u CNFG_ECG_r;
Mahir Ozturk 10:dbeda3ffffb8 604 CNFG_ECG_r.bits.dlpf = 1; // Digital LPF cutoff = 40Hz
Mahir Ozturk 10:dbeda3ffffb8 605 CNFG_ECG_r.bits.dhpf = 1; // Digital HPF cutoff = 0.5Hz
Mahir Ozturk 10:dbeda3ffffb8 606 CNFG_ECG_r.bits.gain = 3; // ECG gain = 160V/V
Mahir Ozturk 10:dbeda3ffffb8 607 CNFG_ECG_r.bits.rate = 2; // Sample rate = 128 sps
Mahir Ozturk 10:dbeda3ffffb8 608 ecgAFE.writeRegister( MAX30003::CNFG_ECG , CNFG_ECG_r.all);
Mahir Ozturk 10:dbeda3ffffb8 609
Mahir Ozturk 10:dbeda3ffffb8 610
Mahir Ozturk 10:dbeda3ffffb8 611 //R-to-R configuration
Mahir Ozturk 10:dbeda3ffffb8 612 MAX30003::RtoR1Configuration_u CNFG_RTOR_r;
Mahir Ozturk 10:dbeda3ffffb8 613 CNFG_RTOR_r.bits.en_rtor = 1; // Enable R-to-R detection
Mahir Ozturk 10:dbeda3ffffb8 614 ecgAFE.writeRegister( MAX30003::CNFG_RTOR1 , CNFG_RTOR_r.all);
Mahir Ozturk 1:efe9cad8942f 615
Mahir Ozturk 1:efe9cad8942f 616
Mahir Ozturk 10:dbeda3ffffb8 617 //Manage interrupts register setting
Mahir Ozturk 10:dbeda3ffffb8 618 MAX30003::ManageInterrupts_u MNG_INT_r;
Mahir Ozturk 10:dbeda3ffffb8 619 MNG_INT_r.bits.efit = 0b00011; // Assert EINT w/ 4 unread samples
Mahir Ozturk 10:dbeda3ffffb8 620 MNG_INT_r.bits.clr_rrint = 0b01; // Clear R-to-R on RTOR reg. read back
Mahir Ozturk 10:dbeda3ffffb8 621 ecgAFE.writeRegister( MAX30003::MNGR_INT , MNG_INT_r.all);
Mahir Ozturk 1:efe9cad8942f 622
Mahir Ozturk 1:efe9cad8942f 623
Mahir Ozturk 10:dbeda3ffffb8 624 //Enable interrupts register setting
Mahir Ozturk 10:dbeda3ffffb8 625 MAX30003::EnableInterrupts_u EN_INT_r;
Mahir Ozturk 10:dbeda3ffffb8 626 EN_INT_r.all = 0;
Mahir Ozturk 10:dbeda3ffffb8 627 EN_INT_r.bits.en_eint = 1; // Enable EINT interrupt
Mahir Ozturk 10:dbeda3ffffb8 628 EN_INT_r.bits.en_rrint = 0; // Disable R-to-R interrupt
Mahir Ozturk 10:dbeda3ffffb8 629 EN_INT_r.bits.intb_type = 3; // Open-drain NMOS with internal pullup
Mahir Ozturk 10:dbeda3ffffb8 630 ecgAFE.writeRegister( MAX30003::EN_INT , EN_INT_r.all);
Mahir Ozturk 1:efe9cad8942f 631
Mahir Ozturk 1:efe9cad8942f 632
Mahir Ozturk 10:dbeda3ffffb8 633 //Dyanmic modes config
Mahir Ozturk 10:dbeda3ffffb8 634 MAX30003::ManageDynamicModes_u MNG_DYN_r;
Mahir Ozturk 10:dbeda3ffffb8 635 MNG_DYN_r.bits.fast = 0; // Fast recovery mode disabled
Mahir Ozturk 10:dbeda3ffffb8 636 ecgAFE.writeRegister( MAX30003::MNGR_DYN , MNG_DYN_r.all);
Mahir Ozturk 1:efe9cad8942f 637
Mahir Ozturk 10:dbeda3ffffb8 638 // MUX Config
Mahir Ozturk 10:dbeda3ffffb8 639 MAX30003::MuxConfiguration_u CNFG_MUX_r;
Mahir Ozturk 10:dbeda3ffffb8 640 CNFG_MUX_r.bits.openn = 0; // Connect ECGN to AFE channel
Mahir Ozturk 10:dbeda3ffffb8 641 CNFG_MUX_r.bits.openp = 0; // Connect ECGP to AFE channel
Mahir Ozturk 10:dbeda3ffffb8 642 ecgAFE.writeRegister( MAX30003::CNFG_EMUX , CNFG_MUX_r.all);
Mahir Ozturk 1:efe9cad8942f 643
Mahir Ozturk 10:dbeda3ffffb8 644 return;
Mahir Ozturk 1:efe9cad8942f 645 }
Mahir Ozturk 1:efe9cad8942f 646
Mahir Ozturk 1:efe9cad8942f 647 /* ECG FIFO nearly full callback */
Mahir Ozturk 1:efe9cad8942f 648 void ecgFIFO_callback() {
Mahir Ozturk 1:efe9cad8942f 649 thread_max30003_reader.signal_set(MAX30003_IRQ_ASSERTED_SIGNAL_ID);
Mahir Ozturk 1:efe9cad8942f 650 }
Mahir Ozturk 1:efe9cad8942f 651
Mahir Ozturk 1:efe9cad8942f 652 void max30003_reader_task()
Mahir Ozturk 1:efe9cad8942f 653 {
Mahir Ozturk 1:efe9cad8942f 654 // Constants
Mahir Ozturk 10:dbeda3ffffb8 655 const int EINT_STATUS_MASK = 1 << 23;
Mahir Ozturk 10:dbeda3ffffb8 656 const int FIFO_OVF_MASK = 0x7;
Mahir Ozturk 10:dbeda3ffffb8 657 const int FIFO_VALID_SAMPLE_MASK = 0x0;
Mahir Ozturk 10:dbeda3ffffb8 658 const int FIFO_FAST_SAMPLE_MASK = 0x1;
Mahir Ozturk 1:efe9cad8942f 659 const int ETAG_BITS_MASK = 0x7;
Mahir Ozturk 1:efe9cad8942f 660
Mahir Ozturk 10:dbeda3ffffb8 661 uint32_t ecgFIFO, readECGSamples, idx, ETAG[32], status;
Mahir Ozturk 10:dbeda3ffffb8 662
Mahir Ozturk 1:efe9cad8942f 663 InterruptIn ecgFIFO_int(P5_4); // Config P5_4 as int. in for the
Mahir Ozturk 1:efe9cad8942f 664 ecgFIFO_int.fall(&ecgFIFO_callback); // ecg FIFO almost full interrupt
Mahir Ozturk 1:efe9cad8942f 665
Mahir Ozturk 1:efe9cad8942f 666 SPI spiBus(SPI2_MOSI, SPI2_MISO, SPI2_SCK); // SPI bus, P5_1 = MOSI,
Mahir Ozturk 1:efe9cad8942f 667 // P5_2 = MISO, P5_0 = SCK
Mahir Ozturk 1:efe9cad8942f 668
Mahir Ozturk 1:efe9cad8942f 669 MAX30003 ecgAFE(spiBus, P5_3); // New MAX30003 on spiBus, CS = P5_3
Mahir Ozturk 1:efe9cad8942f 670 ecg_config(ecgAFE); // Config ECG
Mahir Ozturk 1:efe9cad8942f 671
Mahir Ozturk 1:efe9cad8942f 672 ecgAFE.writeRegister( MAX30003::SYNCH , 0);
Mahir Ozturk 1:efe9cad8942f 673
Mahir Ozturk 1:efe9cad8942f 674 daplink.printf("Starting MAX30003 ECG Demo Application...\r\n");
Mahir Ozturk 1:efe9cad8942f 675
Mahir Ozturk 1:efe9cad8942f 676 while (1) {
Mahir Ozturk 1:efe9cad8942f 677
Mahir Ozturk 1:efe9cad8942f 678 // Read back ECG samples from the FIFO
Mahir Ozturk 1:efe9cad8942f 679 thread_max30003_reader.signal_wait(MAX30003_IRQ_ASSERTED_SIGNAL_ID);
Mahir Ozturk 1:efe9cad8942f 680
Mahir Ozturk 1:efe9cad8942f 681 status = ecgAFE.readRegister( MAX30003::STATUS ); // Read the STATUS register
Mahir Ozturk 1:efe9cad8942f 682
Mahir Ozturk 1:efe9cad8942f 683 // Check if EINT interrupt asserted
Mahir Ozturk 1:efe9cad8942f 684 if ( ( status & EINT_STATUS_MASK ) == EINT_STATUS_MASK ) {
Mahir Ozturk 1:efe9cad8942f 685
Mahir Ozturk 1:efe9cad8942f 686 readECGSamples = 0; // Reset sample counter
Mahir Ozturk 1:efe9cad8942f 687
Mahir Ozturk 1:efe9cad8942f 688 do {
Mahir Ozturk 1:efe9cad8942f 689 ecgFIFO = ecgAFE.readRegister( MAX30003::ECG_FIFO ); // Read FIFO
Mahir Ozturk 1:efe9cad8942f 690 ETAG[readECGSamples] = ( ecgFIFO >> 3 ) & ETAG_BITS_MASK; // Isolate ETAG
Mahir Ozturk 1:efe9cad8942f 691 readECGSamples++; // Increment sample counter
Mahir Ozturk 1:efe9cad8942f 692
Mahir Ozturk 1:efe9cad8942f 693 // Check that sample is not last sample in FIFO
Mahir Ozturk 1:efe9cad8942f 694 } while ( ETAG[readECGSamples-1] == FIFO_VALID_SAMPLE_MASK ||
Mahir Ozturk 1:efe9cad8942f 695 ETAG[readECGSamples-1] == FIFO_FAST_SAMPLE_MASK );
Mahir Ozturk 1:efe9cad8942f 696
Mahir Ozturk 1:efe9cad8942f 697 // Check if FIFO has overflowed
Mahir Ozturk 1:efe9cad8942f 698 if( ETAG[readECGSamples - 1] == FIFO_OVF_MASK ){
Mahir Ozturk 1:efe9cad8942f 699 ecgAFE.writeRegister( MAX30003::FIFO_RST , 0); // Reset FIFO
Mahir Ozturk 1:efe9cad8942f 700 rLED = 1;//notifies the user that an over flow occured
Mahir Ozturk 1:efe9cad8942f 701 }
Mahir Ozturk 1:efe9cad8942f 702
Mahir Ozturk 1:efe9cad8942f 703 // Print results
Mahir Ozturk 1:efe9cad8942f 704 for( idx = 0; idx < readECGSamples; idx++ ) {
Mahir Ozturk 1:efe9cad8942f 705 daplink.printf("%6d\r\n", ecgSample[idx]);
Mahir Ozturk 1:efe9cad8942f 706
Mahir Ozturk 1:efe9cad8942f 707 bleGattAttrWrite(gattCharECG.getValueHandle(),
Mahir Ozturk 1:efe9cad8942f 708 (uint8_t *)&ecgSample[idx], sizeof(ecgSample[idx]));
Mahir Ozturk 1:efe9cad8942f 709 }
Mahir Ozturk 1:efe9cad8942f 710 }
Mahir Ozturk 1:efe9cad8942f 711 }
Mahir Ozturk 1:efe9cad8942f 712 }
Mahir Ozturk 1:efe9cad8942f 713
Mahir Ozturk 1:efe9cad8942f 714 #endif
Mahir Ozturk 1:efe9cad8942f 715
Mahir Ozturk 1:efe9cad8942f 716 /******************************************************************************
Mahir Ozturk 1:efe9cad8942f 717 ************** MAX30003WING (BPM) *********************************************
Mahir Ozturk 1:efe9cad8942f 718 *******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 719 #if defined(LIB_MAX30003)
Mahir Ozturk 1:efe9cad8942f 720
Mahir Ozturk 1:efe9cad8942f 721 #define MAX30003_IRQ_ASSERTED_SIGNAL_ID 1
Mahir Ozturk 1:efe9cad8942f 722
Mahir Ozturk 1:efe9cad8942f 723 MAX30003 max30003(spim2, SPI2_SS); /* MAX30003WING board */
Mahir Ozturk 1:efe9cad8942f 724
Mahir Ozturk 1:efe9cad8942f 725 Thread thread_max30003_reader;
Mahir Ozturk 1:efe9cad8942f 726
Mahir Ozturk 1:efe9cad8942f 727 /* ECG FIFO nearly full callback */
Mahir Ozturk 1:efe9cad8942f 728 void ecgFIFO_callback()
Mahir Ozturk 1:efe9cad8942f 729 {
Mahir Ozturk 1:efe9cad8942f 730 thread_max30003_reader.signal_set(MAX30003_IRQ_ASSERTED_SIGNAL_ID);
Mahir Ozturk 1:efe9cad8942f 731 }
Mahir Ozturk 1:efe9cad8942f 732
Mahir Ozturk 1:efe9cad8942f 733 void ecg_config(MAX30003& ecgAFE)
Mahir Ozturk 1:efe9cad8942f 734 {
Mahir Ozturk 10:dbeda3ffffb8 735 // Reset ECG to clear registers
Mahir Ozturk 10:dbeda3ffffb8 736 ecgAFE.writeRegister( MAX30003::SW_RST , 0);
Mahir Ozturk 1:efe9cad8942f 737
Mahir Ozturk 10:dbeda3ffffb8 738 // General config register setting
Mahir Ozturk 10:dbeda3ffffb8 739 MAX30003::GeneralConfiguration_u CNFG_GEN_r;
Mahir Ozturk 10:dbeda3ffffb8 740 CNFG_GEN_r.bits.en_ecg = 1; // Enable ECG channel
Mahir Ozturk 10:dbeda3ffffb8 741 CNFG_GEN_r.bits.rbiasn = 1; // Enable resistive bias on negative input
Mahir Ozturk 10:dbeda3ffffb8 742 CNFG_GEN_r.bits.rbiasp = 1; // Enable resistive bias on positive input
Mahir Ozturk 10:dbeda3ffffb8 743 CNFG_GEN_r.bits.en_rbias = 1; // Enable resistive bias
Mahir Ozturk 10:dbeda3ffffb8 744 CNFG_GEN_r.bits.imag = 2; // Current magnitude = 10nA
Mahir Ozturk 10:dbeda3ffffb8 745 CNFG_GEN_r.bits.en_dcloff = 1; // Enable DC lead-off detection
Mahir Ozturk 10:dbeda3ffffb8 746 ecgAFE.writeRegister( MAX30003::CNFG_GEN , CNFG_GEN_r.all);
Mahir Ozturk 1:efe9cad8942f 747
Mahir Ozturk 1:efe9cad8942f 748
Mahir Ozturk 10:dbeda3ffffb8 749 // ECG Config register setting
Mahir Ozturk 10:dbeda3ffffb8 750 MAX30003::ECGConfiguration_u CNFG_ECG_r;
Mahir Ozturk 10:dbeda3ffffb8 751 CNFG_ECG_r.bits.dlpf = 1; // Digital LPF cutoff = 40Hz
Mahir Ozturk 10:dbeda3ffffb8 752 CNFG_ECG_r.bits.dhpf = 1; // Digital HPF cutoff = 0.5Hz
Mahir Ozturk 10:dbeda3ffffb8 753 CNFG_ECG_r.bits.gain = 3; // ECG gain = 160V/V
Mahir Ozturk 10:dbeda3ffffb8 754 CNFG_ECG_r.bits.rate = 2; // Sample rate = 128 sps
Mahir Ozturk 10:dbeda3ffffb8 755 ecgAFE.writeRegister( MAX30003::CNFG_ECG , CNFG_ECG_r.all);
Mahir Ozturk 1:efe9cad8942f 756
Mahir Ozturk 1:efe9cad8942f 757
Mahir Ozturk 10:dbeda3ffffb8 758 //R-to-R configuration
Mahir Ozturk 10:dbeda3ffffb8 759 MAX30003::RtoR1Configuration_u CNFG_RTOR_r;
Mahir Ozturk 10:dbeda3ffffb8 760 CNFG_RTOR_r.bits.wndw = 0b0011; // WNDW = 96ms
Mahir Ozturk 10:dbeda3ffffb8 761 CNFG_RTOR_r.bits.rgain = 0b1111; // Auto-scale gain
Mahir Ozturk 10:dbeda3ffffb8 762 CNFG_RTOR_r.bits.pavg = 0b11; // 16-average
Mahir Ozturk 10:dbeda3ffffb8 763 CNFG_RTOR_r.bits.ptsf = 0b0011; // PTSF = 4/16
Mahir Ozturk 10:dbeda3ffffb8 764 CNFG_RTOR_r.bits.en_rtor = 1; // Enable R-to-R detection
Mahir Ozturk 10:dbeda3ffffb8 765 ecgAFE.writeRegister( MAX30003::CNFG_RTOR1 , CNFG_RTOR_r.all);
Mahir Ozturk 1:efe9cad8942f 766
Mahir Ozturk 1:efe9cad8942f 767
Mahir Ozturk 10:dbeda3ffffb8 768 //Manage interrupts register setting
Mahir Ozturk 10:dbeda3ffffb8 769 MAX30003::ManageInterrupts_u MNG_INT_r;
Mahir Ozturk 10:dbeda3ffffb8 770 MNG_INT_r.bits.efit = 0b00011; // Assert EINT w/ 4 unread samples
Mahir Ozturk 10:dbeda3ffffb8 771 MNG_INT_r.bits.clr_rrint = 0b01; // Clear R-to-R on RTOR reg. read back
Mahir Ozturk 10:dbeda3ffffb8 772 ecgAFE.writeRegister( MAX30003::MNGR_INT , MNG_INT_r.all);
Mahir Ozturk 1:efe9cad8942f 773
Mahir Ozturk 1:efe9cad8942f 774
Mahir Ozturk 10:dbeda3ffffb8 775 //Enable interrupts register setting
Mahir Ozturk 10:dbeda3ffffb8 776 MAX30003::EnableInterrupts_u EN_INT_r;
Mahir Ozturk 10:dbeda3ffffb8 777 EN_INT_r.bits.en_eint = 1; // Enable EINT interrupt
Mahir Ozturk 10:dbeda3ffffb8 778 EN_INT_r.bits.en_rrint = 1; // Enable R-to-R interrupt
Mahir Ozturk 10:dbeda3ffffb8 779 EN_INT_r.bits.intb_type = 3; // Open-drain NMOS with internal pullup
Mahir Ozturk 10:dbeda3ffffb8 780 ecgAFE.writeRegister( MAX30003::EN_INT , EN_INT_r.all);
Mahir Ozturk 1:efe9cad8942f 781
Mahir Ozturk 1:efe9cad8942f 782
Mahir Ozturk 10:dbeda3ffffb8 783 //Dyanmic modes config
Mahir Ozturk 10:dbeda3ffffb8 784 MAX30003::ManageDynamicModes_u MNG_DYN_r;
Mahir Ozturk 10:dbeda3ffffb8 785 MNG_DYN_r.bits.fast = 0; // Fast recovery mode disabled
Mahir Ozturk 10:dbeda3ffffb8 786 ecgAFE.writeRegister( MAX30003::MNGR_DYN , MNG_DYN_r.all);
Mahir Ozturk 1:efe9cad8942f 787
Mahir Ozturk 10:dbeda3ffffb8 788 // MUX Config
Mahir Ozturk 10:dbeda3ffffb8 789 MAX30003::MuxConfiguration_u CNFG_MUX_r;
Mahir Ozturk 10:dbeda3ffffb8 790 CNFG_MUX_r.bits.openn = 0; // Connect ECGN to AFE channel
Mahir Ozturk 10:dbeda3ffffb8 791 CNFG_MUX_r.bits.openp = 0; // Connect ECGP to AFE channel
Mahir Ozturk 10:dbeda3ffffb8 792 ecgAFE.writeRegister( MAX30003::CNFG_EMUX , CNFG_MUX_r.all);
Mahir Ozturk 1:efe9cad8942f 793
Mahir Ozturk 10:dbeda3ffffb8 794 return;
Mahir Ozturk 1:efe9cad8942f 795 }
Mahir Ozturk 1:efe9cad8942f 796
Mahir Ozturk 1:efe9cad8942f 797 void max30003_reader_task()
Mahir Ozturk 1:efe9cad8942f 798 {
Mahir Ozturk 10:dbeda3ffffb8 799 // Constants
Mahir Ozturk 10:dbeda3ffffb8 800 const int EINT_STATUS = 1 << 23;
Mahir Ozturk 10:dbeda3ffffb8 801 const int RTOR_STATUS = 1 << 10;
Mahir Ozturk 10:dbeda3ffffb8 802 const int RTOR_REG_OFFSET = 10;
Mahir Ozturk 10:dbeda3ffffb8 803 const float RTOR_LSB_RES = 0.0078125f;
Mahir Ozturk 10:dbeda3ffffb8 804 const int FIFO_OVF = 0x7;
Mahir Ozturk 10:dbeda3ffffb8 805 const int FIFO_VALID_SAMPLE = 0x0;
Mahir Ozturk 10:dbeda3ffffb8 806 const int FIFO_FAST_SAMPLE = 0x1;
Mahir Ozturk 10:dbeda3ffffb8 807 const int ETAG_BITS = 0x7;
Mahir Ozturk 1:efe9cad8942f 808
Mahir Ozturk 10:dbeda3ffffb8 809 uint32_t ecgFIFO, RtoR, readECGSamples, ETAG[32], status;
Mahir Ozturk 10:dbeda3ffffb8 810 float BPM;
Mahir Ozturk 10:dbeda3ffffb8 811 Timer bleNotifyTimer;
Mahir Ozturk 1:efe9cad8942f 812
Mahir Ozturk 10:dbeda3ffffb8 813 InterruptIn ecgFIFO_int(P5_4); // Config P5_4 as int. in for the
Mahir Ozturk 10:dbeda3ffffb8 814 ecgFIFO_int.fall(&ecgFIFO_callback); // ecg FIFO almost full interrupt
Mahir Ozturk 1:efe9cad8942f 815
Mahir Ozturk 10:dbeda3ffffb8 816 ecg_config(max30003); // Config ECG
Mahir Ozturk 1:efe9cad8942f 817
Mahir Ozturk 10:dbeda3ffffb8 818 max30003.writeRegister( MAX30003::SYNCH , 0);
Mahir Ozturk 10:dbeda3ffffb8 819
Mahir Ozturk 10:dbeda3ffffb8 820 bleNotifyTimer.start();
Mahir Ozturk 10:dbeda3ffffb8 821 while (1) {
Mahir Ozturk 1:efe9cad8942f 822 // Read back ECG samples from the FIFO
Mahir Ozturk 1:efe9cad8942f 823 thread_max30003_reader.signal_wait(MAX30003_IRQ_ASSERTED_SIGNAL_ID);
Mahir Ozturk 1:efe9cad8942f 824
Mahir Ozturk 5:ff721fa88519 825 while (1) {
Mahir Ozturk 5:ff721fa88519 826 /* Read back ECG samples from the FIFO */
Mahir Ozturk 5:ff721fa88519 827 status = max30003.readRegister( MAX30003::STATUS ); // Read the STATUS register
Mahir Ozturk 5:ff721fa88519 828
Mahir Ozturk 10:dbeda3ffffb8 829 if ((status & (RTOR_STATUS | EINT_STATUS)) == 0) {
Mahir Ozturk 5:ff721fa88519 830 break;
Mahir Ozturk 5:ff721fa88519 831 }
Mahir Ozturk 1:efe9cad8942f 832
Mahir Ozturk 5:ff721fa88519 833 // Check if R-to-R interrupt asserted
Mahir Ozturk 5:ff721fa88519 834 if ((status & RTOR_STATUS) == RTOR_STATUS) {
Mahir Ozturk 5:ff721fa88519 835
Mahir Ozturk 5:ff721fa88519 836 daplink.printf("R-to-R Interrupt \r\n");
Mahir Ozturk 1:efe9cad8942f 837
Mahir Ozturk 5:ff721fa88519 838 // Read RtoR register
Mahir Ozturk 5:ff721fa88519 839 RtoR = max30003.readRegister( MAX30003::RTOR ) >> RTOR_REG_OFFSET;
Mahir Ozturk 5:ff721fa88519 840
Mahir Ozturk 5:ff721fa88519 841 // Convert to BPM
Mahir Ozturk 5:ff721fa88519 842 BPM = 1.0f / ( RtoR * RTOR_LSB_RES / 60.0f );
Mahir Ozturk 5:ff721fa88519 843
Mahir Ozturk 5:ff721fa88519 844 daplink.printf("BPM: %.2f\r\n", BPM);
Mahir Ozturk 1:efe9cad8942f 845
Mahir Ozturk 5:ff721fa88519 846 if (bleNotifyTimer.read_ms() >= (MAX30003_BLE_NOTIFY_PERIOD_SEC * 1000)) {
Mahir Ozturk 5:ff721fa88519 847 bleGattAttrWrite(gattCharBPM.getValueHandle(), (uint8_t *)&BPM, sizeof(BPM));
Mahir Ozturk 5:ff721fa88519 848 bleNotifyTimer.reset();
Mahir Ozturk 5:ff721fa88519 849 }
Mahir Ozturk 5:ff721fa88519 850 }
Mahir Ozturk 1:efe9cad8942f 851
Mahir Ozturk 5:ff721fa88519 852 // Check if EINT interrupt asserted
Mahir Ozturk 5:ff721fa88519 853 if ((status & EINT_STATUS) == EINT_STATUS) {
Mahir Ozturk 5:ff721fa88519 854 readECGSamples = 0; // Reset sample counter
Mahir Ozturk 1:efe9cad8942f 855
Mahir Ozturk 5:ff721fa88519 856 do {
Mahir Ozturk 5:ff721fa88519 857 ecgFIFO = max30003.readRegister( MAX30003::ECG_FIFO ); // Read FIFO
Mahir Ozturk 5:ff721fa88519 858 ETAG[readECGSamples] = ( ecgFIFO >> 3 ) & ETAG_BITS; // Isolate ETAG
Mahir Ozturk 5:ff721fa88519 859 readECGSamples++; // Increment sample counter
Mahir Ozturk 1:efe9cad8942f 860
Mahir Ozturk 5:ff721fa88519 861 // Check that sample is not last sample in FIFO
Mahir Ozturk 5:ff721fa88519 862 } while (ETAG[readECGSamples-1] == FIFO_VALID_SAMPLE ||
Mahir Ozturk 5:ff721fa88519 863 ETAG[readECGSamples-1] == FIFO_FAST_SAMPLE);
Mahir Ozturk 5:ff721fa88519 864
Mahir Ozturk 5:ff721fa88519 865 // Check if FIFO has overflowed
Mahir Ozturk 5:ff721fa88519 866 if (ETAG[readECGSamples - 1] == FIFO_OVF){
Mahir Ozturk 5:ff721fa88519 867 max30003.writeRegister( MAX30003::FIFO_RST , 0); // Reset FIFO
Mahir Ozturk 5:ff721fa88519 868 rLED = 1;
Mahir Ozturk 5:ff721fa88519 869 }
Mahir Ozturk 2:68ffd74e3b5c 870 }
Mahir Ozturk 1:efe9cad8942f 871 }
Mahir Ozturk 1:efe9cad8942f 872
Mahir Ozturk 1:efe9cad8942f 873 }
Mahir Ozturk 1:efe9cad8942f 874 }
Mahir Ozturk 1:efe9cad8942f 875
Mahir Ozturk 1:efe9cad8942f 876 #endif
Mahir Ozturk 1:efe9cad8942f 877
Mahir Ozturk 1:efe9cad8942f 878 /******************************************************************************
Mahir Ozturk 1:efe9cad8942f 879 ************** MAX11301WING ***************************************************
Mahir Ozturk 1:efe9cad8942f 880 *******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 881 #if defined(LIB_MAX113XX_PIXI)
Mahir Ozturk 1:efe9cad8942f 882
Mahir Ozturk 1:efe9cad8942f 883 #define MAX113XX_DATA_READ_PERIOD_MSEC 2000
Mahir Ozturk 1:efe9cad8942f 884 #define MAX113XX_I2C_ADDRESS 0x38
Mahir Ozturk 1:efe9cad8942f 885
Mahir Ozturk 1:efe9cad8942f 886 Thread thread_max11301_reader;
Mahir Ozturk 1:efe9cad8942f 887
Mahir Ozturk 1:efe9cad8942f 888 void max11301_reader_task()
Mahir Ozturk 1:efe9cad8942f 889 {
Mahir Ozturk 10:dbeda3ffffb8 890 uint16_t adcData;
Mahir Ozturk 10:dbeda3ffffb8 891 float adcVoltage;
Mahir Ozturk 1:efe9cad8942f 892
Mahir Ozturk 10:dbeda3ffffb8 893 MAX113XX_I2C pixi(i2c1, MAX113XX_I2C::MAX11301, MAX113XX_I2C_ADDRESS, P5_5);
Mahir Ozturk 1:efe9cad8942f 894
Mahir Ozturk 10:dbeda3ffffb8 895 pixi.dacWrite(MAX113XX_Pixi::PORT0, 0x000); // Pixi PORT0 is -5V
Mahir Ozturk 10:dbeda3ffffb8 896 pixi.dacWrite(MAX113XX_Pixi::PORT1, 0xFFF); // Pixi PORT1 is +5V
Mahir Ozturk 1:efe9cad8942f 897
Mahir Ozturk 10:dbeda3ffffb8 898 daplink.printf("Starting MAX11301 PIXI ADC Demo Application...\r\n");
Mahir Ozturk 1:efe9cad8942f 899
Mahir Ozturk 10:dbeda3ffffb8 900 while (1) {
Mahir Ozturk 10:dbeda3ffffb8 901 pixi.singleEndedADCRead(MAX113XX_Pixi::PORT9, adcData); // Read value from PORT9
Mahir Ozturk 10:dbeda3ffffb8 902 adcVoltage = -5 + 2.442e-3 * adcData; // Convert ADC val. to a voltage
Mahir Ozturk 1:efe9cad8942f 903
Mahir Ozturk 10:dbeda3ffffb8 904 daplink.printf("ADC Read is : %i,\tVoltage is %1.3f V \r\n", adcData, adcVoltage);
Mahir Ozturk 1:efe9cad8942f 905
Mahir Ozturk 10:dbeda3ffffb8 906 bleGattAttrWrite(gattCharADC.getValueHandle(), (uint8_t *)&adcVoltage, sizeof(adcVoltage));
Mahir Ozturk 1:efe9cad8942f 907
Mahir Ozturk 10:dbeda3ffffb8 908 Thread::wait(MAX113XX_PIXI_BLE_NOTIFY_PERIOD_SEC * 1000);
Mahir Ozturk 10:dbeda3ffffb8 909 }
Mahir Ozturk 1:efe9cad8942f 910 }
Mahir Ozturk 1:efe9cad8942f 911 #endif
Mahir Ozturk 1:efe9cad8942f 912
Mahir Ozturk 1:efe9cad8942f 913 /******************************************************************************
Mahir Ozturk 1:efe9cad8942f 914 ******************************************************************************
Mahir Ozturk 1:efe9cad8942f 915 ******************************************************************************/
Mahir Ozturk 1:efe9cad8942f 916
Mahir Ozturk 1:efe9cad8942f 917 int main()
Mahir Ozturk 1:efe9cad8942f 918 {
Mahir Ozturk 1:efe9cad8942f 919 osStatus status;
Mahir Ozturk 2:68ffd74e3b5c 920 rLED = LED_OFF; gLED = LED_OFF; bLED = LED_OFF; // red
Mahir Ozturk 1:efe9cad8942f 921
Mahir Ozturk 2:68ffd74e3b5c 922 aliveLedEventId = eventQueue.call_every(1000, blinkCallback);
Mahir Ozturk 1:efe9cad8942f 923
Mahir Ozturk 10:dbeda3ffffb8 924 daplink.printf("Initializing BLE service...\r\n");
Mahir Ozturk 1:efe9cad8942f 925
Mahir Ozturk 2:68ffd74e3b5c 926 BLE &ble = BLE::Instance();
Mahir Ozturk 2:68ffd74e3b5c 927 ble.onEventsToProcess(scheduleBleEventsProcessing);
Mahir Ozturk 2:68ffd74e3b5c 928 ble.init(bleInitComplete);
Mahir Ozturk 1:efe9cad8942f 929
Mahir Ozturk 1:efe9cad8942f 930 #if defined(LIB_MAX30205)
Mahir Ozturk 2:68ffd74e3b5c 931 status = thread_max30205_reader.start(max30205_reader_task);
Mahir Ozturk 2:68ffd74e3b5c 932 if (status != osOK) {
Mahir Ozturk 2:68ffd74e3b5c 933 daplink.printf("Starting thread_max30205_reader thread failed(%d)!\r\n", status);
Mahir Ozturk 2:68ffd74e3b5c 934 }
Mahir Ozturk 1:efe9cad8942f 935 #endif
Mahir Ozturk 1:efe9cad8942f 936
Mahir Ozturk 1:efe9cad8942f 937 #if defined(LIB_MAX30101)
Mahir Ozturk 2:68ffd74e3b5c 938 status = thread_max30101_reader.start(max30101_reader_task);
Mahir Ozturk 2:68ffd74e3b5c 939 if (status != osOK) {
Mahir Ozturk 2:68ffd74e3b5c 940 daplink.printf("Starting thread_max30205_reader thread failed(%d)!\r\n", status);
Mahir Ozturk 2:68ffd74e3b5c 941 }
Mahir Ozturk 1:efe9cad8942f 942 #endif
Mahir Ozturk 1:efe9cad8942f 943
Mahir Ozturk 1:efe9cad8942f 944 #if defined(LIB_MAX30003)
Mahir Ozturk 2:68ffd74e3b5c 945 status = thread_max30003_reader.start(max30003_reader_task);
Mahir Ozturk 2:68ffd74e3b5c 946 if (status != osOK) {
Mahir Ozturk 2:68ffd74e3b5c 947 daplink.printf("Starting thread_max30205_reader thread failed(%d)!\r\n", status);
Mahir Ozturk 2:68ffd74e3b5c 948 }
Mahir Ozturk 1:efe9cad8942f 949 #endif
Mahir Ozturk 1:efe9cad8942f 950
Mahir Ozturk 1:efe9cad8942f 951 #if defined(LIB_MAX113XX_PIXI)
Mahir Ozturk 2:68ffd74e3b5c 952 status = thread_max11301_reader.start(max11301_reader_task);
Mahir Ozturk 2:68ffd74e3b5c 953 if (status != osOK) {
Mahir Ozturk 2:68ffd74e3b5c 954 daplink.printf("Starting thread_max30205_reader thread failed(%d)!\r\n", status);
Mahir Ozturk 2:68ffd74e3b5c 955 }
Mahir Ozturk 1:efe9cad8942f 956 #endif
Mahir Ozturk 1:efe9cad8942f 957
Mahir Ozturk 2:68ffd74e3b5c 958 eventQueue.dispatch_forever();
Mahir Ozturk 1:efe9cad8942f 959
Mahir Ozturk 2:68ffd74e3b5c 960 return 0;
Mahir Ozturk 1:efe9cad8942f 961 }
Mahir Ozturk 1:efe9cad8942f 962