I've got some basic filter code setup (but not yet tested).
Dependencies: BLE_API Queue mbed nRF51822
Fork of BLE_HeartRate by
main.cpp
- Committer:
- roysandberg
- Date:
- 2015-06-28
- Revision:
- 62:8e2fbe131b53
- Parent:
- 61:1de72bdab0ef
File content as of revision 62:8e2fbe131b53:
/* mbed Microcontroller Library * Copyright (c) 2006-2013 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "mbed.h" #include <qrsdet.h> #include "queue.h" #include "BLEDevice.h" #include "HeartRateService.h" #include "DeviceInformationService.h" /* Enable the following if you need to throttle the connection interval. This has * the effect of reducing energy consumption after a connection is made; * particularly for applications where the central may want a fast connection * interval.*/ #define UPDATE_PARAMS_FOR_LONGER_CONNECTION_INTERVAL 0 // SAMPLE_RATE is defined in qrsdet.h #define MS_PER_SAMPLE (1000/SAMPLE_RATE) extern void setup_sampler(void (*function)(uint32_t)); extern int BeatDetectAndClassify(int ecgSample, int *beatType, int *beatMatch); // defined in bdac.cpp extern void ResetBDAC(void); BLEDevice ble; DigitalOut led1(LED1); PwmOut LRA(P0_15); InterruptIn button1(P0_17); // button 1 InterruptIn button2(P0_18); // button 2 InterruptIn button3(P0_19); // button 3 InterruptIn button4(P0_20); // button 4 //Serial pc (P0_9, P0_11); // TX, RX volatile uint8_t hrmCounter = 128; volatile uint16_t ecgSample = 0; volatile int sampleCounter=0; #define ITEMS_IN_QUEUE 50 Queue ecgQueue ( sizeof(int), ITEMS_IN_QUEUE ); // queue of hrmCounter values bool itemAddedToQueue = true; const static char DEVICE_NAME[] = "HRM1"; static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE, GattService::UUID_DEVICE_INFORMATION_SERVICE }; void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) { ble.startAdvertising(); // restart advertising } void power0() { LRA.write(0.0); } void power1() { LRA.write(0.55); } void power2() { LRA.write(0.85); } void power3() { LRA.write(1.0); } void sampler_callback(uint32_t value) { //hrmCounter = (uint8_t) ((value+127) % 255); ecgSample = (uint16_t) value; itemAddedToQueue = ecgQueue.PutIrq((void*)&ecgSample); } int main(void) { uint16_t value; int beatType; int beatMatch; int samplesSinceLastR; int lastSamplesSinceLastR=0; int sampleOffset=0; char* beatName; led1 = 1; // Ticker ticker; //ticker.attach(periodicCallback, 0.1); // blink LED every second button1.rise(&power0); button2.rise(&power1); button3.rise(&power2); button4.rise(&power3); LRA.period_us(50); // 50 uS -> 20 Khz (needs to be between 10Khz and 250Khz) LRA.write(0.0); // Off. < 50% = 0ff printf("Initializing BLE...\r\n"); ble.init(); ble.onDisconnection(disconnectionCallback); /* Setup primary service. */ //uint8_t hrmCounter = 100; // init HRM to 100bps HeartRateService hrService(ble, hrmCounter, HeartRateService::LOCATION_FINGER); /* Setup auxiliary service. */ DeviceInformationService deviceInfo(ble, "ARM", "Model1", "SN1", "hw-rev1", "fw-rev1", "soft-rev1"); /* Setup advertising. */ printf("Setting up advertising...\r\n"); ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR); ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.setAdvertisingInterval(1000); ble.startAdvertising(); setup_sampler(&sampler_callback); ResetBDAC(); // reset the beat detector and classifier printf("Starting...\r\n"); // infinite loop while (1) { // check for trigger from periodicCallback() if (ble.getGapState().connected) { while (ecgQueue.GetNumberOfItems()>0) { ecgQueue.Get(&value); samplesSinceLastR = BeatDetectAndClassify(value, &beatType, &beatMatch); if (samplesSinceLastR != 0) { printf("[C] samplesSinceLastR=%d, type=%d\r\n", value, beatType); } //hrService.updateHeartRate(value); led1 = !led1; } } else { if (!itemAddedToQueue) { printf("Queue overflow.\n\r"); itemAddedToQueue = true; } while (ecgQueue.GetNumberOfItems()>0) { sampleCounter++; ecgQueue.Get(&value); samplesSinceLastR = BeatDetectAndClassify(value, &beatType, &beatMatch); if (samplesSinceLastR != 0) { sampleOffset = lastSamplesSinceLastR - samplesSinceLastR; if (beatType == 1) { beatName = "Normal"; } else if (beatType == 5) { beatName = "Ectopic"; } else { beatName = "Unknown"; } printf("[NC] interval_ms=%d, bpm=%d, samplesSinceLastR=%d (%s)\r\n", ((sampleCounter-sampleOffset)*MS_PER_SAMPLE), (60000/((sampleCounter-sampleOffset)*MS_PER_SAMPLE)), value, beatName); sampleCounter=0; lastSamplesSinceLastR = samplesSinceLastR; } } ble.waitForEvent(); // low power wait for event } } }