Chanel's edits

Dependencies:   max32630fthr USBDevice

Committer:
saleiferis
Date:
Mon Mar 09 06:12:00 2020 +0000
Revision:
12:ad628acddbf7
Parent:
11:cbd9182d14d2
Child:
13:a555fd1253e7
preprossing is complete (raw->bandpass->square->moving integration) -- no BT

Who changed what in which revision?

UserRevisionLine numberNew contents of line
saleiferis 0:89ec48e52250 1 #include "mbed.h"
saleiferis 0:89ec48e52250 2 #include "math.h"
saleiferis 0:89ec48e52250 3 #include "max32630fthr.h"
saleiferis 0:89ec48e52250 4 #include "max86150.h"
saleiferis 0:89ec48e52250 5 #include "I2C.h"
saleiferis 0:89ec48e52250 6 #include "ble/BLE.h"
saleiferis 0:89ec48e52250 7 #include "ble/Gap.h"
saleiferis 7:4debec043316 8 //#include "ble/services/HeartRateService.h"
saleiferis 7:4debec043316 9 #include "ECGService.h"
saleiferis 1:6e6f7e3cc1e1 10 #include <events/mbed_events.h>
saleiferis 1:6e6f7e3cc1e1 11 #include "bt32630.h"
saleiferis 11:cbd9182d14d2 12 #include "filters.h"
saleiferis 0:89ec48e52250 13
saleiferis 0:89ec48e52250 14 //Register definitions
saleiferis 0:89ec48e52250 15 #define MAX86150_Addr 0xBC //updated per I2Cscanner, 8 bit version of 7 bit code 0x5E
saleiferis 0:89ec48e52250 16 #define maxi2cFreq 1000000
saleiferis 0:89ec48e52250 17 #define recommendedi2cFreq 400000
saleiferis 10:28b8729cf5dc 18
saleiferis 10:28b8729cf5dc 19 #define BaudRate 115200
saleiferis 0:89ec48e52250 20
saleiferis 12:ad628acddbf7 21 #define WINDOW_SIZE 10 // number of samples for moving winfow integration for HR algo preprocessing
saleiferis 12:ad628acddbf7 22 #define BUFF_SIZE 136 // FIR filter length
saleiferis 0:89ec48e52250 23
saleiferis 10:28b8729cf5dc 24 Serial pc(USBTX,USBRX,NULL,BaudRate);
saleiferis 10:28b8729cf5dc 25 InterruptIn intPin(P5_5); // interrupts currently not used
saleiferis 0:89ec48e52250 26 I2C i2c(I2C2_SDA, I2C2_SCL);
saleiferis 8:2005014df05c 27 MAX86150 max86150Sensor;
saleiferis 0:89ec48e52250 28
saleiferis 10:28b8729cf5dc 29 ECGService *hrServicePtr;
saleiferis 10:28b8729cf5dc 30
saleiferis 10:28b8729cf5dc 31 //Variables modified in inerrupt routine
saleiferis 12:ad628acddbf7 32 /*
saleiferis 10:28b8729cf5dc 33 volatile uint32_t intCount = 0;
saleiferis 8:2005014df05c 34 volatile bool intFlag = false;
saleiferis 9:171171516ebd 35 volatile uint8_t writePointer;
saleiferis 9:171171516ebd 36 volatile uint8_t readPointer;
saleiferis 9:171171516ebd 37 volatile uint32_t curr_time;
saleiferis 9:171171516ebd 38 volatile uint32_t prev_time;
saleiferis 9:171171516ebd 39 volatile int16_t samplesToRead;
saleiferis 12:ad628acddbf7 40 */
saleiferis 9:171171516ebd 41
saleiferis 12:ad628acddbf7 42 //Timer timer;
saleiferis 9:171171516ebd 43
saleiferis 1:6e6f7e3cc1e1 44 static events::EventQueue event_queue(/* event count */ 16 * EVENTS_EVENT_SIZE);
saleiferis 1:6e6f7e3cc1e1 45
saleiferis 10:28b8729cf5dc 46 /*
saleiferis 8:2005014df05c 47 void ISR_AFULL()
saleiferis 8:2005014df05c 48 {
saleiferis 9:171171516ebd 49 intPin.disable_irq();
saleiferis 8:2005014df05c 50 intFlag = true;
saleiferis 9:171171516ebd 51 readPointer = max86150Sensor.getReadPointer();
saleiferis 9:171171516ebd 52 writePointer = max86150Sensor.getWritePointer();
saleiferis 10:28b8729cf5dc 53 samplesToRead = (int8_t)writePointer - (int8_t)readPointer;
saleiferis 10:28b8729cf5dc 54 //if (samplesToRead < 0) samplesToRead+=32;
saleiferis 10:28b8729cf5dc 55 intCount++;
saleiferis 10:28b8729cf5dc 56 //intPin.enable_irq();
saleiferis 10:28b8729cf5dc 57
saleiferis 10:28b8729cf5dc 58 }*/
saleiferis 9:171171516ebd 59
saleiferis 10:28b8729cf5dc 60 /*
saleiferis 10:28b8729cf5dc 61 void ISR_DATA_READY()
saleiferis 10:28b8729cf5dc 62 {
saleiferis 10:28b8729cf5dc 63 intPin.disable_irq();
saleiferis 10:28b8729cf5dc 64 readPointer = max86150Sensor.getReadPointer();
saleiferis 10:28b8729cf5dc 65 writePointer = max86150Sensor.getWritePointer();
saleiferis 10:28b8729cf5dc 66 samplesToRead = (int8_t)writePointer - (int8_t)readPointer;
saleiferis 10:28b8729cf5dc 67 //if (samplesToRead < 0) samplesToRead+=32;
saleiferis 10:28b8729cf5dc 68 intCount++;
saleiferis 10:28b8729cf5dc 69 char data[3];
saleiferis 10:28b8729cf5dc 70 //char *p = data;
saleiferis 10:28b8729cf5dc 71 max86150Sensor.writeRegister8(MAX86150_Addr,0x07,0x01);
saleiferis 10:28b8729cf5dc 72 i2c.write(MAX86150_Addr,command, 1);
saleiferis 10:28b8729cf5dc 73 i2c.read(MAX86150_Addr, data, 3, false);
saleiferis 10:28b8729cf5dc 74 uint8_t temp[sizeof(int32_t)]; //Array of 4 bytes that we will convert into long
saleiferis 10:28b8729cf5dc 75 int32_t tempLong;
saleiferis 10:28b8729cf5dc 76 temp[1] = data[0];
saleiferis 10:28b8729cf5dc 77 temp[2] = data[1];
saleiferis 10:28b8729cf5dc 78 temp[3] = data[2];
saleiferis 10:28b8729cf5dc 79 temp[0] = 0;
saleiferis 10:28b8729cf5dc 80 //Convert array to long
saleiferis 10:28b8729cf5dc 81 memcpy(&tempLong, temp, sizeof(tempLong));
saleiferis 10:28b8729cf5dc 82 pc.printf("%d\n",tempLong);
saleiferis 10:28b8729cf5dc 83 intPin.enable_irq();
saleiferis 10:28b8729cf5dc 84 }*/
saleiferis 10:28b8729cf5dc 85
saleiferis 0:89ec48e52250 86 //////////
saleiferis 10:28b8729cf5dc 87 int main(){
saleiferis 0:89ec48e52250 88 max86150Sensor.begin(i2c, recommendedi2cFreq, MAX86150_Addr);
saleiferis 0:89ec48e52250 89 wait_ms(300);
saleiferis 4:4233f5538abf 90
saleiferis 0:89ec48e52250 91 //unsigned char partID = max86150Sensor.readPartID();
saleiferis 0:89ec48e52250 92 unsigned char partID = max86150Sensor.readRegister8(MAX86150_Addr,0xFF);
saleiferis 0:89ec48e52250 93 pc.printf("Part ID is: %X\n",partID);
saleiferis 10:28b8729cf5dc 94 while (partID != 0x1E) {/* Connection to sensor is not established */ }
saleiferis 2:a96a53e6c6a3 95
saleiferis 2:a96a53e6c6a3 96
saleiferis 10:28b8729cf5dc 97 //***** SETUP SENSOR */
saleiferis 10:28b8729cf5dc 98 max86150Sensor.setup(); //Configure sensor
saleiferis 10:28b8729cf5dc 99 wait_ms(300);
saleiferis 10:28b8729cf5dc 100 pc.printf("SYSCONTOL REG: %x\n", max86150Sensor.readRegister8(MAX86150_Addr,0x0D));
saleiferis 10:28b8729cf5dc 101 pc.printf("FIFO CONFIG: %X\n",max86150Sensor.readRegister8(MAX86150_Addr,0x08));
saleiferis 10:28b8729cf5dc 102 pc.printf("INT_EN1: %X\n", max86150Sensor.readRegister8(MAX86150_Addr,0x02));
saleiferis 10:28b8729cf5dc 103 pc.printf("INT_EN2: %X\n", max86150Sensor.readRegister8(MAX86150_Addr,0x03));
saleiferis 10:28b8729cf5dc 104 pc.printf("INT STATUS1: %X\n",max86150Sensor.readRegister8(MAX86150_Addr,0x00));
saleiferis 10:28b8729cf5dc 105 pc.printf("INT STATUS2: %X\n",max86150Sensor.readRegister8(MAX86150_Addr,0x01));
saleiferis 10:28b8729cf5dc 106
saleiferis 10:28b8729cf5dc 107 //*************************************************************//
saleiferis 10:28b8729cf5dc 108
saleiferis 10:28b8729cf5dc 109 max86150Sensor.clearFIFO();
saleiferis 10:28b8729cf5dc 110 max86150Sensor.writeRegister8(MAX86150_Addr,0x0D,0x04); //start FIFO
saleiferis 10:28b8729cf5dc 111
saleiferis 10:28b8729cf5dc 112 //******* SETUP BLUETOOTH *********
saleiferis 10:28b8729cf5dc 113 eventQueue.call_every(1, periodicCallback); // poll sensor every 1ms. New samples come every 5ms, so polling freq can potentially be decreased
saleiferis 1:6e6f7e3cc1e1 114 BLE &ble = BLE::Instance();
saleiferis 10:28b8729cf5dc 115 ble.onEventsToProcess(scheduleBleEventsProcessing);
saleiferis 10:28b8729cf5dc 116 //ble.init(bleInitComplete);
saleiferis 8:2005014df05c 117 //eventQueue.dispatch_forever();
saleiferis 4:4233f5538abf 118
saleiferis 10:28b8729cf5dc 119 // Below code is for testing interrupts and sensor polling without involving bluetooth API
saleiferis 10:28b8729cf5dc 120 // max86150Sensor.clearFIFO();
saleiferis 10:28b8729cf5dc 121 //intPin.fall(&ISR_DATA_READY);
saleiferis 10:28b8729cf5dc 122 // max86150Sensor.writeRegister8(MAX86150_Addr,0x0D,0x04);
saleiferis 10:28b8729cf5dc 123 int16_t ecgsigned16;
saleiferis 11:cbd9182d14d2 124 int i; // loop iteration
saleiferis 12:ad628acddbf7 125 int32_t sample_idx = 0; // number of samples read
saleiferis 12:ad628acddbf7 126 uint8_t curr; // keept track of buffer
saleiferis 12:ad628acddbf7 127 float signal[BUFF_SIZE]={0}; //store signal segment to be filtered
saleiferis 12:ad628acddbf7 128 float bp_signal[BUFF_SIZE]={0};
saleiferis 12:ad628acddbf7 129 float derivative[BUFF_SIZE]={0};
saleiferis 12:ad628acddbf7 130 float squared[BUFF_SIZE]={0};
saleiferis 12:ad628acddbf7 131 float integral[BUFF_SIZE] = {0};
saleiferis 12:ad628acddbf7 132 // uint8_t curr_movwin = 0; //keep track of squared[] buffer that is used for moving window integration
saleiferis 12:ad628acddbf7 133
saleiferis 12:ad628acddbf7 134 // Variables for preprocessing
saleiferis 11:cbd9182d14d2 135 float y = 0.0; //filtered sample to be displayed
saleiferis 12:ad628acddbf7 136 float prev_y = 0.0; // keep track of previous output to calculate derivative
saleiferis 12:ad628acddbf7 137 float sq_y = 0.0;
saleiferis 12:ad628acddbf7 138 float movmean = 0.0; // result of moving window integration
saleiferis 12:ad628acddbf7 139
saleiferis 12:ad628acddbf7 140 // Variables for peak-finding
saleiferis 12:ad628acddbf7 141 int rr1[8], rr2[8], rravg1, rravg2, rrlow = 0, rrhigh = 0, rrmiss = 0;
saleiferis 12:ad628acddbf7 142 //long unsigned int i, j, sample = 0, lastQRS = 0, lastSlope = 0, currentSlope = 0; //TODO: i is already declared FIX
saleiferis 12:ad628acddbf7 143 float peak_i = 0, peak_f = 0, threshold_i1 = 0, threshold_i2 = 0, threshold_f1 = 0, threshold_f2 = 0, spk_i = 0, spk_f = 0, npk_i = 0, npk_f = 0;
saleiferis 12:ad628acddbf7 144 bool qrs, regular = true, prevRegular;
saleiferis 12:ad628acddbf7 145 // Initializing the RR averages
saleiferis 12:ad628acddbf7 146 for (i = 0; i < 8; i++)
saleiferis 12:ad628acddbf7 147 {
saleiferis 12:ad628acddbf7 148 rr1[i] = 0;
saleiferis 12:ad628acddbf7 149 rr2[i] = 0;
saleiferis 12:ad628acddbf7 150 }
saleiferis 12:ad628acddbf7 151
saleiferis 9:171171516ebd 152
saleiferis 8:2005014df05c 153 while(1){
saleiferis 10:28b8729cf5dc 154 if(max86150Sensor.check()>0){
saleiferis 10:28b8729cf5dc 155
saleiferis 11:cbd9182d14d2 156 //ecgsigned16 = (int16_t) (max86150Sensor.getFIFOECG()>>2);
saleiferis 11:cbd9182d14d2 157 //max86150Sensor.nextSample();
saleiferis 11:cbd9182d14d2 158 //pc.printf("%f\n",(float)ecgsigned16);
saleiferis 11:cbd9182d14d2 159
saleiferis 12:ad628acddbf7 160 // if buffer is full
saleiferis 11:cbd9182d14d2 161 if (sample_idx >= BUFF_SIZE){
saleiferis 11:cbd9182d14d2 162 for (i=0; i<BUFF_SIZE-1; i++){ //discard oldest sample, shift samples in buffer
saleiferis 11:cbd9182d14d2 163 signal[i] = signal[i+1];
saleiferis 12:ad628acddbf7 164 bp_signal[i] = bp_signal[i+1];
saleiferis 12:ad628acddbf7 165 derivative[i] = derivative[i+1];
saleiferis 12:ad628acddbf7 166 integral[i] = integral[i+1];
saleiferis 12:ad628acddbf7 167 squared[i] = squared[i+1];
saleiferis 12:ad628acddbf7 168
saleiferis 11:cbd9182d14d2 169 }
saleiferis 11:cbd9182d14d2 170 curr = BUFF_SIZE-1; // indicates that buffer is full
saleiferis 12:ad628acddbf7 171 prev_y = y;
saleiferis 11:cbd9182d14d2 172 y = 0.0; // reset filter output for current sample
saleiferis 11:cbd9182d14d2 173 }else{ //Buffer is not full yet
saleiferis 12:ad628acddbf7 174 curr = (uint8_t)sample_idx; //position at buffer is same as sample number
saleiferis 11:cbd9182d14d2 175 }
saleiferis 11:cbd9182d14d2 176 ecgsigned16 = (int16_t) (max86150Sensor.getFIFOECG()>>2); //read a sample
saleiferis 11:cbd9182d14d2 177 max86150Sensor.nextSample(); // advance tail to get sample in next iteration
saleiferis 12:ad628acddbf7 178 signal[curr] = (float)ecgsigned16; //add sample to buffer
saleiferis 11:cbd9182d14d2 179 sample_idx++;
saleiferis 11:cbd9182d14d2 180
saleiferis 11:cbd9182d14d2 181 if (curr< BUFF_SIZE-1){
saleiferis 11:cbd9182d14d2 182 // buffer is not full yet
saleiferis 11:cbd9182d14d2 183 }else{ //buffer is full, filter current sample
saleiferis 11:cbd9182d14d2 184 for(i = 0; i < BUFF_SIZE; i++){ //FIR bandpass filter
saleiferis 11:cbd9182d14d2 185 y = y + FIR_BP[i] * signal[BUFF_SIZE-1-i];
saleiferis 11:cbd9182d14d2 186 }
saleiferis 12:ad628acddbf7 187 bp_signal[curr] = y;
saleiferis 12:ad628acddbf7 188 }
saleiferis 12:ad628acddbf7 189 sq_y = pow(y-prev_y,2);
saleiferis 12:ad628acddbf7 190 squared[curr] = sq_y;
saleiferis 12:ad628acddbf7 191 //moving window integration
saleiferis 12:ad628acddbf7 192 movmean = 0.0; // reset for current sample
saleiferis 12:ad628acddbf7 193 for(i=0; i<(int)WINDOW_SIZE/2; i++){
saleiferis 12:ad628acddbf7 194 //pc.printf("%d\n",(int)curr - (int)(WINDOW_SIZE));
saleiferis 12:ad628acddbf7 195 if ((int)curr - (int)(WINDOW_SIZE) > i){ //there are enough samples in squared[]
saleiferis 12:ad628acddbf7 196 // movmean = movmean + squared[(curr-i-(int)WINDOW_SIZE/2)] + squared[curr+i-(int)WINDOW_SIZE/2];
saleiferis 12:ad628acddbf7 197 movmean = movmean + squared[curr-i];
saleiferis 12:ad628acddbf7 198
saleiferis 12:ad628acddbf7 199 }else{
saleiferis 12:ad628acddbf7 200 break;
saleiferis 12:ad628acddbf7 201 }
saleiferis 11:cbd9182d14d2 202 }
saleiferis 12:ad628acddbf7 203 movmean = movmean/(float)(i+1);
saleiferis 12:ad628acddbf7 204 integral[curr] = movmean;
saleiferis 12:ad628acddbf7 205
saleiferis 12:ad628acddbf7 206 pc.printf("%f %f\n",movmean/1000, y/50);
saleiferis 12:ad628acddbf7 207
saleiferis 12:ad628acddbf7 208 // Preprocessing done
saleiferis 12:ad628acddbf7 209 // Start peak-finding
saleiferis 12:ad628acddbf7 210 //qrs = false;
saleiferis 12:ad628acddbf7 211 //if (integral[curr] >= threshold_i1 || highpass[current] >= threshold_f1){
saleiferis 12:ad628acddbf7 212 // peak_i = integral[curr];
saleiferis 12:ad628acddbf7 213 // peak_f = highpass[curr];
saleiferis 12:ad628acddbf7 214 //}
saleiferis 12:ad628acddbf7 215
saleiferis 12:ad628acddbf7 216
saleiferis 12:ad628acddbf7 217
saleiferis 12:ad628acddbf7 218
saleiferis 10:28b8729cf5dc 219 }
saleiferis 10:28b8729cf5dc 220 }
saleiferis 10:28b8729cf5dc 221
saleiferis 0:89ec48e52250 222 }