Chanel Richardson / Mbed OS vitalsplus-max86150_chanel

Dependencies:   max32630fthr USBDevice

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers bt32630.h Source File

bt32630.h

00001 #include "HeartRateService.h"
00002 #include "ECGService.h"
00003 #include "PPGService.h"
00004 #include "filters.h"
00005 #include "panTompkins.h"
00006 
00007 //Register definitions
00008 #define MAX86150_Addr 0xBC //updated per I2Cscanner, 8 bit version of 7 bit code 0x5E
00009 #define maxi2cFreq 1000000
00010 #define recommendedi2cFreq 400000
00011  
00012 #define BaudRate 115200
00013 
00014 #define WINDOW_SIZE 25 // number of samples for moving winfow integration for HR algo preprocessing. Effective window_size is half of this value
00015 #define BUFF_SIZE 136  // TODO: decouple BUFF_SIZE and FIR_SIZE. now program crashes if != 136
00016 #define FIR_SIZE 136
00017 
00018 extern MAX86150 max86150Sensor;
00019 extern Serial pc;
00020 extern I2C i2c;
00021 extern BLE &ble;
00022 const static char     DEVICE_NAME[] = "MAX32630";
00023 static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE};
00024 
00025 //
00026 extern int k; // loop iteration
00027 extern float signal[BUFF_SIZE]; //store signal segment to be filtered
00028 extern float bp_signal[BUFF_SIZE];
00029 extern float derivative[BUFF_SIZE];
00030 extern float squared[BUFF_SIZE];
00031 extern float integral[BUFF_SIZE];
00032 extern bool outputSignal[BUFF_SIZE];
00033 
00034 //
00035 extern int rr1[8], rr2[8], rravg1, rravg2, rrlow , rrhigh , rrmiss ;
00036 extern long unsigned int i, j, sample , current , lastQRS , lastSlope , currentSlope ;
00037 extern float peak_i , peak_f , threshold_i1 , threshold_i2 , threshold_f1 , threshold_f2 , spk_i , spk_f , npk_i , npk_f ;
00038 extern bool qrs, regular, prevRegular;
00039 
00040 // Variables for preprocessing
00041 extern float y ; //filtered sample to be displayed
00042 extern float prev_y ; // keep track of previous output to calculate derivative
00043 extern float sq_y;
00044 extern float movmean; // result of moving window integration
00045 
00046 
00047 static int16_t hrmCounter = 100; // init HRM to 100bps
00048 extern HeartRateService *hrServicePtr;
00049 //extern ECGService *hrServicePtr;
00050 
00051 static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE);
00052 
00053 
00054 void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
00055 {
00056     pc.printf("Connected to BLE Client...\n");
00057    max86150Sensor.begin(i2c, recommendedi2cFreq, MAX86150_Addr); 
00058     wait_ms(300);
00059    
00060     //unsigned char partID = max86150Sensor.readPartID();
00061     unsigned char partID = max86150Sensor.readRegister8(MAX86150_Addr,0xFF);
00062     pc.printf("Part ID is: %X\n",partID);
00063     while (partID != 0x1E) {/* Connection to sensor is not established */ }
00064     
00065     
00066     //***** SETUP SENSOR */
00067     max86150Sensor.setup(); //Configure sensor
00068     wait_ms(300);
00069     pc.printf("SYSCONTOL REG: %x\n", max86150Sensor.readRegister8(MAX86150_Addr,0x0D));
00070     pc.printf("FIFO CONFIG: %X\n",max86150Sensor.readRegister8(MAX86150_Addr,0x08));
00071     pc.printf("INT_EN1: %X\n", max86150Sensor.readRegister8(MAX86150_Addr,0x02));
00072     pc.printf("INT_EN2: %X\n", max86150Sensor.readRegister8(MAX86150_Addr,0x03));
00073     pc.printf("INT STATUS1: %X\n",max86150Sensor.readRegister8(MAX86150_Addr,0x00));
00074     pc.printf("INT STATUS2: %X\n",max86150Sensor.readRegister8(MAX86150_Addr,0x01));
00075     //*************************************************************//
00076     panTompkinsInit();
00077     max86150Sensor.clearFIFO();
00078     max86150Sensor.writeRegister8(MAX86150_Addr,0x0D,0x04); //start FIFO
00079   
00080 }
00081 
00082 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
00083 {
00084     BLE::Instance().gap().startAdvertising(); // restart advertising
00085 }
00086 
00087 void updateSensorValue() {
00088     // Do blocking calls or whatever is necessary for sensor polling.
00089     // In our case, we simply update the HRM measurement.
00090     int16_t ecgsigned16;
00091     uint32_t ppgRed16;
00092     if(max86150Sensor.check()>0){         
00093        // if buffer is full
00094         if (sample >= BUFF_SIZE){
00095             for (k=0; k<BUFF_SIZE-1; k++){  //discard oldest sample, shift samples in buffer
00096                 signal[k] = signal[k+1];
00097                 bp_signal[k] = bp_signal[k+1];
00098                 derivative[k] = derivative[k+1];
00099                 integral[k] = integral[k+1];
00100                 squared[k] = squared[k+1];
00101                 
00102             }
00103             current = BUFF_SIZE-1;   // indicates that buffer is full
00104             prev_y = y;
00105             y = 0.0;  // reset filter output for current sample
00106         }else{ //Buffer is not full yet
00107             current = sample; //position at buffer is same as sample number
00108         }
00109         ecgsigned16 = (int16_t) (max86150Sensor.getFIFOECG()>>2); //read an ECG sample
00110         ppgRed16 = max86150Sensor.getFIFORed();
00111         max86150Sensor.nextSample();    // advance tail to get sample in next iteration
00112         signal[current] = (float)ecgsigned16; //add sample to buffer
00113         sample++;
00114         
00115         if (current< FIR_SIZE-1){
00116             // buffer is not full yet
00117         }else{ //buffer is full, filter current sample
00118             for(k = 0; k < FIR_SIZE; k++){ //FIR bandpass filter
00119                 y = y + FIR_BP[k] * signal[current-k];
00120             }
00121             bp_signal[current] = y;
00122         }
00123         sq_y = pow(y-prev_y,2);
00124         squared[current] = sq_y;
00125         //moving window integration
00126         movmean = 0.0; // reset for current sample
00127         for(k=0; k<(int)WINDOW_SIZE/2; k++){
00128             //pc.printf("%d\n",(int)current - (int)(WINDOW_SIZE));
00129             if ((int)current - (int)(WINDOW_SIZE) > k){ //there are enough samples in squared[]
00130                // movmean = movmean + squared[(current-k-(int)WINDOW_SIZE/2)] + squared[current+k-(int)WINDOW_SIZE/2];
00131                 movmean = movmean + squared[current-k];
00132                 
00133             }else{
00134                 break;
00135             }          
00136         }
00137         movmean = movmean/(float)(k+1);
00138         integral[current] = movmean;
00139         
00140          //
00141          //pc.printf("%d\n",ppgRed16);
00142             
00143         //hrServicePtr->updateHeartRate(ecgsigned16); //send ECG sample
00144         // TODO: call pan_tompkins()
00145         
00146         panTompkinsIter();
00147         //pc.printf("%f %f %f \n",movmean/1000, y/50,(movmean/1000)*(float)outputSignal[current]);
00148         int HR = (int)((FS*60)/rr1[7]);
00149         int avg_HR = (int)((FS*60)/rravg1);
00150         pc.printf("%f %f %d %d\n", y/50,(movmean/1000)*outputSignal[current],HR,avg_HR);
00151         //pc.printf("%f f\n",y,y*(float)outputSignal[current]);
00152         hrServicePtr->updateHeartRate((uint8_t)avg_HR);
00153         
00154     }
00155     
00156     
00157     
00158 }
00159 
00160 void periodicCallback(void)
00161 {
00162 
00163     if (BLE::Instance().getGapState().connected) {
00164         eventQueue.call(updateSensorValue);
00165     }
00166 }
00167 
00168 void onBleInitError(BLE &ble, ble_error_t error)
00169 {
00170     (void)ble;
00171     (void)error;
00172    /* Initialization error handling should go here */
00173 }
00174 
00175 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
00176 {
00177     BLE&        ble   = params->ble;
00178     ble_error_t error = params->error;
00179 
00180     if (error != BLE_ERROR_NONE) {
00181         onBleInitError(ble, error);
00182         return;
00183     }
00184 
00185     if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
00186         return;
00187     }
00188 
00189     ble.gap().onDisconnection(disconnectionCallback);
00190     ble.gap().onConnection(connectionCallback);
00191 
00192     /* Setup primary service. */
00193     hrServicePtr = new HeartRateService(ble, (uint8_t)hrmCounter, HeartRateService::LOCATION_FINGER);
00194     //hrServicePtr = new ECGService(ble, hrmCounter);
00195 
00196     pc.printf("Setup primary service ...\n");
00197 
00198     /* Setup advertising. */
00199     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00200     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
00201     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
00202     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
00203 
00204     ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00205     ble.gap().setAdvertisingInterval(1000); /* 1000ms */
00206  
00207     ble.gap().startAdvertising();
00208 
00209     pc.printf("Exiting bleInitComplete() ... \n");
00210     return;
00211 }   
00212 
00213 
00214 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
00215     BLE &ble = BLE::Instance();
00216     eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
00217 }