Chanel's edits
Dependencies: max32630fthr USBDevice
bt32630.h
- Committer:
- saleiferis
- Date:
- 2020-03-18
- Revision:
- 17:65a8b29f6bac
- Parent:
- 16:f6bfa6b66e96
- Child:
- 18:1ad357c3df71
- Child:
- 19:f230229cb6f3
File content as of revision 17:65a8b29f6bac:
//#include "HeartRateService.h" #include "ECGService.h" #include "PPGService.h" #include "filters.h" #include "panTompkins.h" //Register definitions #define MAX86150_Addr 0xBC //updated per I2Cscanner, 8 bit version of 7 bit code 0x5E #define maxi2cFreq 1000000 #define recommendedi2cFreq 400000 #define BaudRate 115200 #define WINDOW_SIZE 25 // number of samples for moving winfow integration for HR algo preprocessing. Effective window_size is half of this value #define BUFF_SIZE 136 // TODO: decouple BUFF_SIZE and FIR_SIZE. now program crashes if != 136 #define FIR_SIZE 136 extern MAX86150 max86150Sensor; extern Serial pc; extern I2C i2c; extern BLE &ble; const static char DEVICE_NAME[] = "MAX32630"; static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE}; // extern int k; // loop iteration extern float signal[BUFF_SIZE]; //store signal segment to be filtered extern float bp_signal[BUFF_SIZE]; extern float derivative[BUFF_SIZE]; extern float squared[BUFF_SIZE]; extern float integral[BUFF_SIZE]; extern bool outputSignal[BUFF_SIZE]; // extern int rr1[8], rr2[8], rravg1, rravg2, rrlow , rrhigh , rrmiss ; extern long unsigned int i, j, sample , current , lastQRS , lastSlope , currentSlope ; extern float peak_i , peak_f , threshold_i1 , threshold_i2 , threshold_f1 , threshold_f2 , spk_i , spk_f , npk_i , npk_f ; extern bool qrs, regular, prevRegular; // Variables for preprocessing extern float y ; //filtered sample to be displayed extern float prev_y ; // keep track of previous output to calculate derivative extern float sq_y; extern float movmean; // result of moving window integration static int16_t hrmCounter = 100; // init HRM to 100bps //static HeartRateService *hrServicePtr; extern ECGService *hrServicePtr; static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE); void connectionCallback(const Gap::ConnectionCallbackParams_t *params) { pc.printf("Connected to BLE Client...\n"); max86150Sensor.begin(i2c, recommendedi2cFreq, MAX86150_Addr); wait_ms(300); //unsigned char partID = max86150Sensor.readPartID(); unsigned char partID = max86150Sensor.readRegister8(MAX86150_Addr,0xFF); pc.printf("Part ID is: %X\n",partID); while (partID != 0x1E) {/* Connection to sensor is not established */ } //***** SETUP SENSOR */ max86150Sensor.setup(); //Configure sensor wait_ms(300); pc.printf("SYSCONTOL REG: %x\n", max86150Sensor.readRegister8(MAX86150_Addr,0x0D)); pc.printf("FIFO CONFIG: %X\n",max86150Sensor.readRegister8(MAX86150_Addr,0x08)); pc.printf("INT_EN1: %X\n", max86150Sensor.readRegister8(MAX86150_Addr,0x02)); pc.printf("INT_EN2: %X\n", max86150Sensor.readRegister8(MAX86150_Addr,0x03)); pc.printf("INT STATUS1: %X\n",max86150Sensor.readRegister8(MAX86150_Addr,0x00)); pc.printf("INT STATUS2: %X\n",max86150Sensor.readRegister8(MAX86150_Addr,0x01)); //*************************************************************// panTompkinsInit(); max86150Sensor.clearFIFO(); max86150Sensor.writeRegister8(MAX86150_Addr,0x0D,0x04); //start FIFO } void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) { BLE::Instance().gap().startAdvertising(); // restart advertising } void updateSensorValue() { // Do blocking calls or whatever is necessary for sensor polling. // In our case, we simply update the HRM measurement. int16_t ecgsigned16; uint32_t ppgRed16; if(max86150Sensor.check()>0){ // if buffer is full if (sample >= BUFF_SIZE){ for (k=0; k<BUFF_SIZE-1; k++){ //discard oldest sample, shift samples in buffer signal[k] = signal[k+1]; bp_signal[k] = bp_signal[k+1]; derivative[k] = derivative[k+1]; integral[k] = integral[k+1]; squared[k] = squared[k+1]; } current = BUFF_SIZE-1; // indicates that buffer is full prev_y = y; y = 0.0; // reset filter output for current sample }else{ //Buffer is not full yet current = sample; //position at buffer is same as sample number } ecgsigned16 = (int16_t) (max86150Sensor.getFIFOECG()>>2); //read an ECG sample ppgRed16 = max86150Sensor.getFIFORed(); max86150Sensor.nextSample(); // advance tail to get sample in next iteration signal[current] = (float)ecgsigned16; //add sample to buffer sample++; if (current< FIR_SIZE-1){ // buffer is not full yet }else{ //buffer is full, filter current sample for(k = 0; k < FIR_SIZE; k++){ //FIR bandpass filter y = y + FIR_BP[k] * signal[current-k]; } bp_signal[current] = y; } sq_y = pow(y-prev_y,2); squared[current] = sq_y; //moving window integration movmean = 0.0; // reset for current sample for(k=0; k<(int)WINDOW_SIZE/2; k++){ //pc.printf("%d\n",(int)current - (int)(WINDOW_SIZE)); if ((int)current - (int)(WINDOW_SIZE) > k){ //there are enough samples in squared[] // movmean = movmean + squared[(current-k-(int)WINDOW_SIZE/2)] + squared[current+k-(int)WINDOW_SIZE/2]; movmean = movmean + squared[current-k]; }else{ break; } } movmean = movmean/(float)(k+1); integral[current] = movmean; // //pc.printf("%d\n",ppgRed16); //hrServicePtr->updateHeartRate(ecgsigned16); //send ECG sample // TODO: call pan_tompkins() panTompkinsIter(); //pc.printf("%f %f %f \n",movmean/1000, y/50,(movmean/1000)*(float)outputSignal[current]); int HR = (int)((FS*60)/rr1[7]); int avg_HR = (int)((FS*60)/rravg1); pc.printf("%f %f %d %d\n", y/50,(movmean/1000)*outputSignal[current],HR,avg_HR); //pc.printf("%f f\n",y,y*(float)outputSignal[current]); hrServicePtr->updateHeartRate(avg_HR); } } void periodicCallback(void) { if (BLE::Instance().getGapState().connected) { eventQueue.call(updateSensorValue); } } void onBleInitError(BLE &ble, ble_error_t error) { (void)ble; (void)error; /* Initialization error handling should go here */ } void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) { BLE& ble = params->ble; ble_error_t error = params->error; if (error != BLE_ERROR_NONE) { onBleInitError(ble, error); return; } if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { return; } ble.gap().onDisconnection(disconnectionCallback); ble.gap().onConnection(connectionCallback); /* Setup primary service. */ //hrServicePtr = new HeartRateService(ble, hrmCounter, HeartRateService::LOCATION_FINGER); hrServicePtr = new ECGService(ble, hrmCounter); pc.printf("Setup primary service ...\n"); /* Setup advertising. */ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.gap().setAdvertisingInterval(1000); /* 1000ms */ ble.gap().startAdvertising(); pc.printf("Exiting bleInitComplete() ... \n"); return; } void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) { BLE &ble = BLE::Instance(); eventQueue.call(Callback<void()>(&ble, &BLE::processEvents)); }