Chanel's edits
Dependencies: max32630fthr USBDevice
Diff: bt32630.h
- Revision:
- 14:ee2175578993
- Parent:
- 10:28b8729cf5dc
- Child:
- 15:b15b4b6c6da8
diff -r a555fd1253e7 -r ee2175578993 bt32630.h --- a/bt32630.h Mon Mar 09 08:17:00 2020 +0000 +++ b/bt32630.h Tue Mar 10 08:22:53 2020 +0000 @@ -1,11 +1,46 @@ //#include "HeartRateService.h" #include "ECGService.h" +#include "PPGService.h" +#include "filters.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[] = "Nordic_HRM"; 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 int rr1[8], rr2[8], rravg1, rravg2, rrlow , rrhigh , rrmiss ; +extern long unsigned int i, j, sample_idx , curr , 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; @@ -17,6 +52,29 @@ 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)); + //*************************************************************// + + max86150Sensor.clearFIFO(); + max86150Sensor.writeRegister8(MAX86150_Addr,0x0D,0x04); //start FIFO + } void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) @@ -27,23 +85,64 @@ void updateSensorValue() { // Do blocking calls or whatever is necessary for sensor polling. // In our case, we simply update the HRM measurement. - /* - hrmCounter++; - // 100 <= HRM bps <=175 - if (hrmCounter == 175) { - hrmCounter = 100; + int16_t ecgsigned16; + uint32_t ppgRed16; + if(max86150Sensor.check()>0){ + // if buffer is full + if (sample_idx >= 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]; + + } + curr = 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 + curr = sample_idx; //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[curr] = (float)ecgsigned16; //add sample to buffer + sample_idx++; + + if (curr< 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[curr-k]; + } + bp_signal[curr] = y; + } + sq_y = pow(y-prev_y,2); + squared[curr] = 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)curr - (int)(WINDOW_SIZE)); + if ((int)curr - (int)(WINDOW_SIZE) > k){ //there are enough samples in squared[] + // movmean = movmean + squared[(curr-k-(int)WINDOW_SIZE/2)] + squared[curr+k-(int)WINDOW_SIZE/2]; + movmean = movmean + squared[curr-k]; + + }else{ + break; + } + } + movmean = movmean/(float)(k+1); + integral[curr] = movmean; + + //pc.printf("%f %f %f\n",movmean/1000, y/50,(float)ppgRed16/1000); + //pc.printf("%d\n",ppgRed16); + + hrServicePtr->updateHeartRate(ecgsigned16); //send ECG sample + // TODO: call pan_tompkins() + } - - //hrmCounter = 133; - hrServicePtr->updateHeartRate(hrmCounter); - */ - int16_t ecgsigned16; - if(max86150Sensor.check()>0){ - ecgsigned16 = (int16_t) (max86150Sensor.getFIFOECG()>>2); - max86150Sensor.nextSample(); - //hrServicePtr->updateHeartRate(ecgsigned16); - pc.printf("%d\n",ecgsigned16); - } + }