Paul Jeon / Mbed 2 deprecated RD117_MBED

Dependencies:   max32625pico mbed SerialInterface USBDevice

Committer:
mjoun
Date:
Fri Jan 31 18:27:53 2020 +0000
Revision:
9:42ab3b212395
Parent:
7:8bc9fad71b8c
changed

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mjoun 7:8bc9fad71b8c 1 /* mbed Microcontroller Library
mjoun 7:8bc9fad71b8c 2 * Copyright (c) 2006-2015 ARM Limited
mjoun 7:8bc9fad71b8c 3 *
mjoun 7:8bc9fad71b8c 4 * Licensed under the Apache License, Version 2.0 (the "License");
mjoun 7:8bc9fad71b8c 5 * you may not use this file except in compliance with the License.
mjoun 7:8bc9fad71b8c 6 * You may obtain a copy of the License at
mjoun 7:8bc9fad71b8c 7 *
mjoun 7:8bc9fad71b8c 8 * http://www.apache.org/licenses/LICENSE-2.0
mjoun 7:8bc9fad71b8c 9 *
mjoun 7:8bc9fad71b8c 10 * Unless required by applicable law or agreed to in writing, software
mjoun 7:8bc9fad71b8c 11 * distributed under the License is distributed on an "AS IS" BASIS,
mjoun 7:8bc9fad71b8c 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mjoun 7:8bc9fad71b8c 13 * See the License for the specific language governing permissions and
mjoun 7:8bc9fad71b8c 14 * limitations under the License.
mjoun 7:8bc9fad71b8c 15 */
mjoun 7:8bc9fad71b8c 16
mjoun 7:8bc9fad71b8c 17 #include <mbed.h>
mjoun 7:8bc9fad71b8c 18 #include "algorithm.h"
mjoun 7:8bc9fad71b8c 19 #include "MAX30102.h"
mjoun 7:8bc9fad71b8c 20 #include "max32625pico.h"
mjoun 7:8bc9fad71b8c 21
mjoun 7:8bc9fad71b8c 22 #include "ble/BLE.h"
mjoun 7:8bc9fad71b8c 23 #include "ble/Gap.h"
mjoun 7:8bc9fad71b8c 24 #include "ble/services/HeartRateService.h"
mjoun 7:8bc9fad71b8c 25
mjoun 7:8bc9fad71b8c 26 #define MAX_BRIGHTNESS 255
mjoun 7:8bc9fad71b8c 27
mjoun 7:8bc9fad71b8c 28 Serial pc(USBTX, USBRX);
mjoun 7:8bc9fad71b8c 29
mjoun 7:8bc9fad71b8c 30 DigitalOut led2(LED2, 1);
mjoun 7:8bc9fad71b8c 31
mjoun 7:8bc9fad71b8c 32 uint32_t aun_ir_buffer[500]; //IR LED sensor data
mjoun 7:8bc9fad71b8c 33 int32_t n_ir_buffer_length; //data length
mjoun 7:8bc9fad71b8c 34 uint32_t aun_red_buffer[500]; //Red LED sensor data
mjoun 7:8bc9fad71b8c 35 int32_t n_sp02; //SPO2 value
mjoun 7:8bc9fad71b8c 36 int8_t ch_spo2_valid; //indicator to show if the SP02 calculation is valid
mjoun 7:8bc9fad71b8c 37 int32_t n_heart_rate; //heart rate value
mjoun 7:8bc9fad71b8c 38 int8_t ch_hr_valid; //indicator to show if the heart rate calculation is valid
mjoun 7:8bc9fad71b8c 39 uint8_t uch_dummy;
mjoun 7:8bc9fad71b8c 40 uint32_t un_min, un_max, un_prev_data; //variables to calculate the on-board LED brightness that reflects the heartbeats
mjoun 7:8bc9fad71b8c 41 int i;
mjoun 7:8bc9fad71b8c 42 int32_t n_brightness;
mjoun 7:8bc9fad71b8c 43 float f_temp;
mjoun 7:8bc9fad71b8c 44 uint8_t hrmCounter;
mjoun 7:8bc9fad71b8c 45
mjoun 7:8bc9fad71b8c 46
mjoun 7:8bc9fad71b8c 47 #ifdef TARGET_MAX32625PICO
mjoun 7:8bc9fad71b8c 48 PwmOut led1(LED3); //initializes the pwm output that connects to the on board LED
mjoun 7:8bc9fad71b8c 49 DigitalIn INT(P3_0); //pin P30 connects to the interrupt output pin of the MAX30102
mjoun 7:8bc9fad71b8c 50 #endif
mjoun 7:8bc9fad71b8c 51
mjoun 7:8bc9fad71b8c 52 MAX32625PICO pico(MAX32625PICO::IOH_DIP_IN, MAX32625PICO::VIO_IOH, MAX32625PICO::VIO_1V8);
mjoun 7:8bc9fad71b8c 53 // the setup routine runs once when you press reset:
mjoun 7:8bc9fad71b8c 54
mjoun 7:8bc9fad71b8c 55 const static char DEVICE_NAME[] = "HRM";
mjoun 7:8bc9fad71b8c 56 //static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE};
mjoun 7:8bc9fad71b8c 57
mjoun 7:8bc9fad71b8c 58 //static HeartRateService *hrServicePtr;
mjoun 7:8bc9fad71b8c 59
mjoun 7:8bc9fad71b8c 60 static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE);
mjoun 7:8bc9fad71b8c 61
mjoun 7:8bc9fad71b8c 62 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
mjoun 7:8bc9fad71b8c 63 {
mjoun 7:8bc9fad71b8c 64 BLE::Instance().gap().startAdvertising(); // restart advertising
mjoun 7:8bc9fad71b8c 65 }
mjoun 7:8bc9fad71b8c 66
mjoun 7:8bc9fad71b8c 67 void checkHR(){
mjoun 7:8bc9fad71b8c 68
mjoun 7:8bc9fad71b8c 69 i=0;
mjoun 7:8bc9fad71b8c 70 un_min=0x3FFFF;
mjoun 7:8bc9fad71b8c 71 un_max=0;
mjoun 7:8bc9fad71b8c 72
mjoun 7:8bc9fad71b8c 73 //dumping the first 100 sets of samples in the memory and shift the last 400 sets of samples to the top
mjoun 7:8bc9fad71b8c 74 for(i=100;i<500;i++)
mjoun 7:8bc9fad71b8c 75 {
mjoun 7:8bc9fad71b8c 76 aun_red_buffer[i-100]=aun_red_buffer[i];
mjoun 7:8bc9fad71b8c 77 aun_ir_buffer[i-100]=aun_ir_buffer[i];
mjoun 7:8bc9fad71b8c 78
mjoun 7:8bc9fad71b8c 79 //update the signal min and max
mjoun 7:8bc9fad71b8c 80 if(un_min>aun_red_buffer[i])
mjoun 7:8bc9fad71b8c 81 un_min=aun_red_buffer[i];
mjoun 7:8bc9fad71b8c 82 if(un_max<aun_red_buffer[i])
mjoun 7:8bc9fad71b8c 83 un_max=aun_red_buffer[i];
mjoun 7:8bc9fad71b8c 84 }
mjoun 7:8bc9fad71b8c 85
mjoun 7:8bc9fad71b8c 86 //take 100 sets of samples before calculating the heart rate.
mjoun 7:8bc9fad71b8c 87 for(i=400;i<500;i++)
mjoun 7:8bc9fad71b8c 88 {
mjoun 7:8bc9fad71b8c 89 un_prev_data=aun_red_buffer[i-1];
mjoun 7:8bc9fad71b8c 90 //while(INT.read()==1);
mjoun 7:8bc9fad71b8c 91 maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));
mjoun 7:8bc9fad71b8c 92
mjoun 7:8bc9fad71b8c 93 if(aun_red_buffer[i]>un_prev_data)
mjoun 7:8bc9fad71b8c 94 {
mjoun 7:8bc9fad71b8c 95 f_temp=aun_red_buffer[i]-un_prev_data;
mjoun 7:8bc9fad71b8c 96 f_temp/=(un_max-un_min);
mjoun 7:8bc9fad71b8c 97 f_temp*=MAX_BRIGHTNESS;
mjoun 7:8bc9fad71b8c 98 n_brightness-=(int)f_temp;
mjoun 7:8bc9fad71b8c 99 if(n_brightness<0)
mjoun 7:8bc9fad71b8c 100 n_brightness=0;
mjoun 7:8bc9fad71b8c 101 }
mjoun 7:8bc9fad71b8c 102 else
mjoun 7:8bc9fad71b8c 103 {
mjoun 7:8bc9fad71b8c 104 f_temp=un_prev_data-aun_red_buffer[i];
mjoun 7:8bc9fad71b8c 105 f_temp/=(un_max-un_min);
mjoun 7:8bc9fad71b8c 106 f_temp*=MAX_BRIGHTNESS;
mjoun 7:8bc9fad71b8c 107 n_brightness+=(int)f_temp;
mjoun 7:8bc9fad71b8c 108 if(n_brightness>MAX_BRIGHTNESS)
mjoun 7:8bc9fad71b8c 109 n_brightness=MAX_BRIGHTNESS;
mjoun 7:8bc9fad71b8c 110 }
mjoun 7:8bc9fad71b8c 111 #if defined(TARGET_KL25Z) || defined(TARGET_MAX32625PICO)
mjoun 7:8bc9fad71b8c 112 led1.write(1-(float)n_brightness/256);
mjoun 7:8bc9fad71b8c 113 #endif
mjoun 7:8bc9fad71b8c 114
mjoun 7:8bc9fad71b8c 115
mjoun 7:8bc9fad71b8c 116 }
mjoun 7:8bc9fad71b8c 117 maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
mjoun 7:8bc9fad71b8c 118 }
mjoun 7:8bc9fad71b8c 119
mjoun 7:8bc9fad71b8c 120 void updateSensorValue() {
mjoun 7:8bc9fad71b8c 121 // Do blocking calls or whatever is necessary for sensor polling.
mjoun 7:8bc9fad71b8c 122 // In our case, we simply update the HRM measurement.
mjoun 7:8bc9fad71b8c 123
mjoun 7:8bc9fad71b8c 124
mjoun 7:8bc9fad71b8c 125 checkHR();
mjoun 7:8bc9fad71b8c 126
mjoun 7:8bc9fad71b8c 127 hrmCounter = n_heart_rate;
mjoun 7:8bc9fad71b8c 128
mjoun 7:8bc9fad71b8c 129 hrServicePtr->updateHeartRate(hrmCounter);
mjoun 7:8bc9fad71b8c 130 }
mjoun 7:8bc9fad71b8c 131
mjoun 7:8bc9fad71b8c 132 void periodicCallback(void)
mjoun 7:8bc9fad71b8c 133 {
mjoun 7:8bc9fad71b8c 134
mjoun 7:8bc9fad71b8c 135 if (BLE::Instance().getGapState().connected) {
mjoun 7:8bc9fad71b8c 136 eventQueue.call(updateSensorValue);
mjoun 7:8bc9fad71b8c 137 }
mjoun 7:8bc9fad71b8c 138 }
mjoun 7:8bc9fad71b8c 139
mjoun 7:8bc9fad71b8c 140
mjoun 7:8bc9fad71b8c 141
mjoun 7:8bc9fad71b8c 142 void onBleInitError(BLE &ble, ble_error_t error)
mjoun 7:8bc9fad71b8c 143 {
mjoun 7:8bc9fad71b8c 144 (void)ble;
mjoun 7:8bc9fad71b8c 145 (void)error;
mjoun 7:8bc9fad71b8c 146 /* Initialization error handling should go here */
mjoun 7:8bc9fad71b8c 147 }
mjoun 7:8bc9fad71b8c 148
mjoun 7:8bc9fad71b8c 149 void printMacAddress()
mjoun 7:8bc9fad71b8c 150 {
mjoun 7:8bc9fad71b8c 151 /* Print out device MAC address to the console*/
mjoun 7:8bc9fad71b8c 152 Gap::AddressType_t addr_type;
mjoun 7:8bc9fad71b8c 153 Gap::Address_t address;
mjoun 7:8bc9fad71b8c 154 BLE::Instance().gap().getAddress(&addr_type, address);
mjoun 7:8bc9fad71b8c 155 printf("DEVICE MAC ADDRESS: ");
mjoun 7:8bc9fad71b8c 156 for (int i = 5; i >= 1; i--){
mjoun 7:8bc9fad71b8c 157 printf("%02x:", address[i]);
mjoun 7:8bc9fad71b8c 158 }
mjoun 7:8bc9fad71b8c 159 printf("%02x\r\n", address[0]);
mjoun 7:8bc9fad71b8c 160 }
mjoun 7:8bc9fad71b8c 161
mjoun 7:8bc9fad71b8c 162 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
mjoun 7:8bc9fad71b8c 163 {
mjoun 7:8bc9fad71b8c 164 BLE& ble = params->ble;
mjoun 7:8bc9fad71b8c 165 ble_error_t error = params->error;
mjoun 7:8bc9fad71b8c 166
mjoun 7:8bc9fad71b8c 167 if (error != BLE_ERROR_NONE) {
mjoun 7:8bc9fad71b8c 168 onBleInitError(ble, error);
mjoun 7:8bc9fad71b8c 169 return;
mjoun 7:8bc9fad71b8c 170 }
mjoun 7:8bc9fad71b8c 171
mjoun 7:8bc9fad71b8c 172 if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
mjoun 7:8bc9fad71b8c 173 return;
mjoun 7:8bc9fad71b8c 174 }
mjoun 7:8bc9fad71b8c 175
mjoun 7:8bc9fad71b8c 176 ble.gap().onDisconnection(disconnectionCallback);
mjoun 7:8bc9fad71b8c 177
mjoun 7:8bc9fad71b8c 178 /* Setup primary service. */
mjoun 7:8bc9fad71b8c 179 hrServicePtr = new HeartRateService(ble, hrmCounter, HeartRateService::LOCATION_FINGER);
mjoun 7:8bc9fad71b8c 180
mjoun 7:8bc9fad71b8c 181 /* Setup advertising. */
mjoun 7:8bc9fad71b8c 182 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
mjoun 7:8bc9fad71b8c 183 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
mjoun 7:8bc9fad71b8c 184 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
mjoun 7:8bc9fad71b8c 185 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
mjoun 7:8bc9fad71b8c 186 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
mjoun 7:8bc9fad71b8c 187 ble.gap().setAdvertisingInterval(1000); /* 1000ms */
mjoun 7:8bc9fad71b8c 188 ble.gap().startAdvertising();
mjoun 7:8bc9fad71b8c 189
mjoun 7:8bc9fad71b8c 190 printMacAddress();
mjoun 7:8bc9fad71b8c 191 }
mjoun 7:8bc9fad71b8c 192
mjoun 7:8bc9fad71b8c 193 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
mjoun 7:8bc9fad71b8c 194 BLE &ble = BLE::Instance();
mjoun 7:8bc9fad71b8c 195 eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
mjoun 7:8bc9fad71b8c 196 }
mjoun 7:8bc9fad71b8c 197
mjoun 7:8bc9fad71b8c 198 int main()
mjoun 7:8bc9fad71b8c 199 {
mjoun 7:8bc9fad71b8c 200 pc.baud(9600);
mjoun 7:8bc9fad71b8c 201 maxim_max30102_reset(); //resets the MAX30102
mjoun 7:8bc9fad71b8c 202
mjoun 7:8bc9fad71b8c 203 pc.printf("Init...\n %ld\n", n_heart_rate);
mjoun 7:8bc9fad71b8c 204
mjoun 7:8bc9fad71b8c 205
mjoun 7:8bc9fad71b8c 206 //read and clear status register
mjoun 7:8bc9fad71b8c 207 maxim_max30102_read_reg(0,&uch_dummy);
mjoun 7:8bc9fad71b8c 208
mjoun 7:8bc9fad71b8c 209
mjoun 7:8bc9fad71b8c 210 maxim_max30102_init(); //initializes the MAX30102
mjoun 7:8bc9fad71b8c 211
mjoun 7:8bc9fad71b8c 212 n_brightness=0;
mjoun 7:8bc9fad71b8c 213 un_min=0x3FFFF;
mjoun 7:8bc9fad71b8c 214 un_max=0;
mjoun 7:8bc9fad71b8c 215
mjoun 7:8bc9fad71b8c 216 n_ir_buffer_length=500; //buffer length of 100 stores 5 seconds of samples running at 100sps
mjoun 7:8bc9fad71b8c 217
mjoun 7:8bc9fad71b8c 218 //read the first 500 samples, and determine the signal range
mjoun 7:8bc9fad71b8c 219 for(i=0;i<n_ir_buffer_length;i++)
mjoun 7:8bc9fad71b8c 220 {
mjoun 7:8bc9fad71b8c 221 //while(INT.read()==1); //wait until the interrupt pin asserts
mjoun 7:8bc9fad71b8c 222
mjoun 7:8bc9fad71b8c 223 maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i)); //read from MAX30102 FIFO
mjoun 7:8bc9fad71b8c 224
mjoun 7:8bc9fad71b8c 225 if(un_min>aun_red_buffer[i])
mjoun 7:8bc9fad71b8c 226 un_min=aun_red_buffer[i]; //update signal min
mjoun 7:8bc9fad71b8c 227 if(un_max<aun_red_buffer[i])
mjoun 7:8bc9fad71b8c 228 un_max=aun_red_buffer[i]; //update signal max
mjoun 7:8bc9fad71b8c 229
mjoun 7:8bc9fad71b8c 230 }
mjoun 7:8bc9fad71b8c 231 un_prev_data=aun_red_buffer[i];
mjoun 7:8bc9fad71b8c 232 //pc.printf("%ld\n", un_prev_data);
mjoun 7:8bc9fad71b8c 233
mjoun 7:8bc9fad71b8c 234 //calculate heart rate and SpO2 after first 500 samples (first 5 seconds of samples)
mjoun 7:8bc9fad71b8c 235 maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
mjoun 7:8bc9fad71b8c 236
mjoun 7:8bc9fad71b8c 237
mjoun 7:8bc9fad71b8c 238 //pc.printf(pn_heart_rate);
mjoun 7:8bc9fad71b8c 239 //pch_hr_valid --> 1 if heart rate value is valid
mjoun 7:8bc9fad71b8c 240
mjoun 7:8bc9fad71b8c 241 while(1)
mjoun 7:8bc9fad71b8c 242 {
mjoun 7:8bc9fad71b8c 243
mjoun 7:8bc9fad71b8c 244 //eventQueue.call_every(500, periodicCallback);
mjoun 7:8bc9fad71b8c 245
mjoun 7:8bc9fad71b8c 246 //BLE &ble = BLE::Instance();
mjoun 7:8bc9fad71b8c 247 //ble.onEventsToProcess(scheduleBleEventsProcessing);
mjoun 7:8bc9fad71b8c 248 //ble.init(bleInitComplete);
mjoun 7:8bc9fad71b8c 249 //pc.printf("%ld", un_prev_data);
mjoun 7:8bc9fad71b8c 250 pc.printf("%ld\n", n_heart_rate);
mjoun 7:8bc9fad71b8c 251
mjoun 7:8bc9fad71b8c 252
mjoun 7:8bc9fad71b8c 253 //eventQueue.dispatch_forever();
mjoun 7:8bc9fad71b8c 254
mjoun 7:8bc9fad71b8c 255
mjoun 7:8bc9fad71b8c 256 }
mjoun 7:8bc9fad71b8c 257 }