dsdaf

Dependencies:   FXOS8700 Hexi_KW40Z Hexi_OLED_SSD1351 MAX30101

Fork of HeartRate by Xi Han

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "mbed_events.h"
00003 #include "MAX30101.h"
00004 #include "Hexi_KW40Z.h"
00005 #include "Hexi_OLED_SSD1351.h"
00006 #include "OLED_types.h"
00007 #include "OpenSans_Font.h"
00008 #include "string.h"
00009 #include "FXOS8700.h"
00010 
00011 
00012 #define FIFO_DATA_MAX 288
00013 
00014 
00015 
00016 #define LED_ON      0
00017 #define LED_OFF     1
00018 
00019 void UpdateSensorData(void);
00020 void StartHaptic(void);
00021 void StopHaptic(void const *n);
00022 void txTask(void);
00023 
00024 DigitalOut led1(LED_GREEN); // RGB LED
00025 FXOS8700 accel(PTC11, PTC10);
00026 
00027 DigitalOut pwr1v8(PTA29);
00028 DigitalOut pwr3v3b(PTC13);
00029 DigitalOut pwr15v(PTB12);
00030 I2C i2c0(PTB1, PTB0);
00031 InterruptIn maximInterrupt(PTB18);
00032 Serial pc(USBTX, USBRX);
00033 
00034 DigitalOut redLed(LED1,1);
00035 DigitalOut greenLed(LED2,1);
00036 DigitalOut blueLed(LED3,1);
00037 DigitalOut haptic(PTB9);
00038 
00039 
00040 RtosTimer hapticTimer(StopHaptic, osTimerOnce);
00041 
00042 /* Instantiate the Hexi KW40Z Driver (UART TX, UART RX) */ 
00043 KW40Z kw40z_device(PTE24, PTE25);
00044 
00045 /* Instantiate the SSD1351 OLED Driver */ 
00046 SSD1351 oled(PTB22,PTB21,PTC13,PTB20,PTE6, PTD15); /* (MOSI,SCLK,POWER,CS,RST,DC) */
00047 
00048 /*Create a Thread to handle sending BLE Sensor Data */ 
00049 Thread txThread;
00050 
00051 EventQueue evqueue(32 * EVENTS_EVENT_SIZE);
00052 Thread t;
00053 
00054 MAX30101 hr(i2c0);
00055 
00056 int mask_ppg = 0;
00057 uint32_t count = 0;
00058 
00059 
00060 
00061 char text[20]; 
00062 
00063 uint8_t battery = 100;
00064 uint8_t light = 0;
00065 uint16_t humidity = 4500;
00066 uint16_t temperature = 2000;
00067 uint16_t pressure = 9000;
00068 uint16_t x = 0;
00069 uint16_t y = 5000;
00070 uint16_t z = 10000;
00071 
00072 // Variables
00073 float accel_data[3]; // Storage for the data from the sensor
00074 float accel_rms=0.0; // RMS value from the sensor
00075 float ax, ay, az; // Integer value from the sensor to be displayed
00076 const uint8_t *image1; // Pointer for the image1 to be displayed
00077 char text1[20]; // Text Buffer for dynamic value displayed
00078 char text2[20]; // Text Buffer for dynamic value displayed
00079 char text3[20]; // Text Buffer for dynamic value displayed
00080 float dot;
00081 float old_acc=0;
00082 float new_acc=0;
00083 float old_accx, old_accy, old_accz, old_dot=0.0;
00084 uint8_t StepNum = 0, StepNumber = 0;
00085 
00086 float filter_buf[75];
00087 
00088 /****************************Call Back Functions*******************************/
00089 
00090 float Filter(int s) 
00091 {
00092     accel.acquire_accel_data_g(accel_data);
00093     float filter_sum = 0.0;
00094     //printf("%d\n\r",s);
00095     for(int i = 0; i < 75; i++) 
00096     {
00097     filter_buf[i] = accel_data[s];
00098     //printf("%4.2f\n\r",filter_buf[i]);
00099     filter_sum += filter_buf[i];
00100     }
00101     return (float)(filter_sum / 75);
00102 }
00103 
00104 
00105 void ButtonRight(void)
00106 {
00107     StartHaptic();
00108     kw40z_device.ToggleAdvertisementMode();
00109 }
00110 
00111 void ButtonLeft(void)
00112 {
00113     StartHaptic();
00114     kw40z_device.ToggleAdvertisementMode();
00115 }
00116 
00117 void ButtonUp(void)
00118 {
00119     StartHaptic();
00120     oled.FillScreen(COLOR_BLACK);
00121 
00122     /* Get OLED Class Default Text Properties */
00123     oled_text_properties_t textProperties = {0};
00124     oled.GetTextProperties(&textProperties);    
00125         
00126     /* Change font color to Blue */ 
00127     textProperties.fontColor   = COLOR_BLUE;
00128     oled.SetTextProperties(&textProperties);
00129     strcpy((char *) text1,"Steps: ");
00130     oled.Label((uint8_t *)text1,3,45);      
00131     sprintf(text1,"%d",StepNumber);
00132       /* Display time reading in 35px by 15px textbox at(x=55, y=40) */
00133     oled.TextBox((uint8_t *)text1,70,45,20,15); //Increase textbox for more digits
00134     
00135     
00136 }
00137 void ButtonDown(void)
00138 {
00139     oled.FillScreen(COLOR_BLACK);
00140 
00141     /* Get OLED Class Default Text Properties */
00142     oled_text_properties_t textProperties = {0};
00143     oled.GetTextProperties(&textProperties);    
00144         
00145     /* Change font color to Blue */ 
00146     textProperties.fontColor   = COLOR_BLUE;
00147     oled.SetTextProperties(&textProperties);
00148     
00149     /* Display Bluetooth Label at x=17,y=65 */ 
00150     strcpy((char *) text,"BLUETOOTH");
00151     oled.Label((uint8_t *)text,17,65);
00152     
00153     /* Change font color to white */ 
00154     textProperties.fontColor   = COLOR_WHITE;
00155     textProperties.alignParam = OLED_TEXT_ALIGN_CENTER;
00156     oled.SetTextProperties(&textProperties);
00157     
00158     /* Display Label at x=22,y=80 */ 
00159     strcpy((char *) text,"Tap Below");
00160     oled.Label((uint8_t *)text,22,80);
00161     
00162     
00163 }
00164 void PassKey(void)
00165 {
00166     StartHaptic();
00167     strcpy((char *) text,"PAIR CODE");
00168     oled.TextBox((uint8_t *)text,0,25,95,18);
00169   
00170     /* Display Bond Pass Key in a 95px by 18px textbox at x=0,y=40 */
00171     sprintf(text,"%d", kw40z_device.GetPassKey());
00172     oled.TextBox((uint8_t *)text,0,40,95,18);
00173 }
00174 
00175 // Key modification: use the alert functionality enabled by the host-ble interface
00176 // to define our own command.
00177 void AlertReceived(uint8_t *data, uint8_t length)
00178 {
00179     StartHaptic();
00180     data[19] = 0;
00181     pc.printf("%s\n\r", data);
00182     
00183     // data (our command) must 20 bytes long.
00184     // CMD for turning on: 'ledonledonledonledon'
00185     if (data[4] == 'n') {
00186         greenLed = LED_ON;
00187         redLed = LED_ON;
00188         blueLed = LED_ON;
00189         pc.printf("on\n\r", data);
00190     
00191     // CMD for turning off: 'ledoffledoffledoffled'
00192     } else if (data[4] == 'f') {
00193         greenLed = LED_OFF;
00194         redLed = LED_OFF;
00195         blueLed = LED_OFF;
00196         pc.printf("off\n\r", data);
00197     }
00198 }
00199 void interruptHandlerQueued() {
00200     
00201     MAX30101::InterruptBitField_u interruptStatus;
00202     hr.getInterruptStatus(interruptStatus);
00203 //    printf("Interrupt Status: 0x%02x\r\n", interruptStatus.all);
00204     
00205     if (interruptStatus.bits.pwr_rdy == 0x1) {
00206 //        printf("Powered on\r\n");
00207         
00208         // Soft reset
00209         MAX30101::ModeConfiguration_u modeConf;
00210         modeConf.all = 0;
00211         modeConf.bits.reset = 1;
00212         hr.setModeConfiguration(modeConf);
00213         wait(0.01);
00214         
00215         // Configure FIFO
00216         MAX30101::FIFO_Configuration_u fifoConf;
00217         hr.getFIFOConfiguration(fifoConf);
00218 //        pc.printf("FIFO Configuration: 0x%02x\r\n", fifoConf.all);
00219           
00220         // Set LED power
00221         hr.setLEDPulseAmplitude(MAX30101::LED1_PA, 0x0C);
00222         hr.setLEDPulseAmplitude(MAX30101::ProxModeLED_PA, 0x19);
00223 //        pc.printf("LED set\r\n");
00224         
00225         MAX30101::SpO2Configuration_u spo2Conf;
00226         hr.getSpO2Configuration(spo2Conf);
00227         spo2Conf.bits.led_pw = MAX30101::PW_1;
00228         spo2Conf.bits.spo2_sr = MAX30101::SR_100_Hz;
00229         hr.setSpO2Configuration(spo2Conf);
00230         hr.getSpO2Configuration(spo2Conf);
00231 //        pc.printf("SpO2 Configuration: 0x%02x\r\n", spo2Conf.all);
00232         
00233         // Proximity settings
00234         hr.setProxIntThreshold(0x14);
00235         
00236         // Enable HR mode
00237         modeConf.all = 0;
00238         modeConf.bits.mode = MAX30101::HeartRateMode;
00239         hr.setModeConfiguration(modeConf);
00240 //        printf("Mode set\r\n");
00241     }
00242     
00243     if (interruptStatus.bits.prox_int == 0x1) {
00244 //        printf("Proximity Triggered, entered HR Mode.");
00245     }
00246     
00247     if (interruptStatus.bits.ppg_rdy == 0x1) {
00248 //        printf("PPG Ready.\r\n");
00249         mask_ppg = 1;
00250     }
00251     
00252     if (interruptStatus.bits.a_full == 0x1) {
00253 //        printf("FIFO Almost Full.\r\n");
00254         uint8_t data[FIFO_DATA_MAX];
00255         uint16_t readBytes = 0;
00256         hr.readFIFO(MAX30101::OneLedChannel, data, readBytes);
00257         
00258         for (uint16_t i = 0; i < readBytes; i += 3) {
00259             uint8_t sample[4] = {0};
00260             sample[0] = data[i + 2];
00261             sample[1] = data[i + 1];
00262             sample[2] = data[i];
00263             
00264         printf("%u\r\n", *(uint32_t *) sample);
00265         }
00266     }
00267     
00268     interruptStatus.all = 0xFF;
00269     if (mask_ppg == 1) {
00270         interruptStatus.bits.ppg_rdy = 0;
00271     }
00272     hr.enableInterrupts(interruptStatus);
00273 }
00274 
00275 void interruptHandler() {
00276     evqueue.call(interruptHandlerQueued);
00277 }
00278 
00279 // main() runs in its own thread in the OS
00280 int main() {
00281 //    printf("Hello world.\r\n");
00282     
00283     t.start(callback(&evqueue, &EventQueue::dispatch_forever));
00284       accel.accel_config();
00285     /* Register callbacks to application functions */
00286     kw40z_device.attach_buttonLeft(&ButtonLeft);
00287     kw40z_device.attach_buttonRight(&ButtonRight);
00288     kw40z_device.attach_buttonDown(&ButtonDown);
00289     kw40z_device.attach_buttonUp(&ButtonUp);
00290     kw40z_device.attach_passkey(&PassKey);
00291     kw40z_device.attach_alert(&AlertReceived);
00292 
00293     pc.printf("hello\n\r");
00294     
00295     /* Turn on the backlight of the OLED Display */
00296     oled.DimScreenON();
00297     
00298     /* Fills the screen with solid black */         
00299     
00300          
00301     uint8_t prevLinkState = 0; 
00302     uint8_t currLinkState = 0;
00303     
00304     
00305     pwr1v8 = 1;
00306     pwr3v3b = 1;
00307     pwr15v = 0;
00308     
00309     maximInterrupt.fall(interruptHandler);
00310     maximInterrupt.enable_irq();
00311     
00312     MAX30101::InterruptBitField_u interruptStatus;
00313     interruptStatus.all = 0xFF;
00314     hr.enableInterrupts(interruptStatus);
00315     
00316     
00317      txThread.start(txTask); /*Start transmitting Sensor Tag Data */
00318     
00319     while (true) 
00320     {
00321         // blueLed = !kw40z_device.GetAdvertisementMode(); /*Indicate BLE Advertisment Mode*/   
00322         Thread::wait(50);
00323     }
00324      
00325     return 0;
00326 }
00327 void txTask(void){
00328    
00329    while (true) 
00330    {
00331         UpdateSensorData();
00332         
00333         /*Notify Hexiwear App that it is running Sensor Tag mode*/
00334         kw40z_device.SendSetApplicationMode(GUI_CURRENT_APP_SENSOR_TAG);
00335                 
00336         /*The following is sending dummy data over BLE. Replace with real data*/
00337     
00338         /*Send Battery Level for 20% */ 
00339         kw40z_device.SendBatteryLevel(StepNumber);
00340                
00341         /*Send Ambient Light Level at 50% */ 
00342         //kw40z_device.SendAmbientLight(light);
00343         
00344         /*Send Humidity at 90% */
00345         //kw40z_device.SendHumidity(humidity);
00346         
00347         /*Send Temperature at 25 degrees Celsius */
00348         //kw40z_device.SendTemperature(temperature);
00349 
00350         /*Send Pressure at 100kPA */ 
00351         //kw40z_device.SendPressure(pressure);
00352         
00353         /*Send Mag,Accel,Gyro Data. */
00354        // kw40z_device.SendGyro(x,y,z);
00355        // kw40z_device.SendAccel(z,x,y);
00356        // kw40z_device.SendMag(y,z,x);
00357 
00358         Thread::wait(10);                 
00359     }
00360 }
00361 
00362 void UpdateSensorData(void)
00363 {    
00364         accel.acquire_accel_data_g(accel_data);
00365       //printf("Accelerometer \tX-Axis %4.2f \tY-Axis %4.2f \tZ-Axis %4.2f \tRMS %4.2f\n\r",accel_data[0],accel_data[1],accel_data[2],accel_rms);
00366       ax = Filter(0);
00367       ay = Filter(1);
00368       az = Filter(2);  
00369       wait(0.02);           
00370       accel_rms = sqrt((ax*ax)+(ay*ay)+(az*az)/3);
00371       //printf("Accelerometer \tX-Axis %4.2f \tY-Axis %4.2f \tZ-Axis %4.2f \tRMS %4.2f\n\r",ax,ay,az,accel_rms);
00372       dot = (old_accx * ax)+(old_accy * ay)+(old_accz * az);
00373       old_acc = abs(sqrt(old_accx*old_accx+old_accy*old_accy+old_accz*old_accz));
00374       new_acc = abs(sqrt(ax*ax+ay*ay+az*az));
00375       //printf("\nOld Acceleration: %4.2f\n\r",old_acc);
00376       //printf("New Acceleration: %4.2f\n\r",new_acc);
00377       dot /= (old_acc * new_acc);
00378       //printf("\nDot: %4.2f\n\r",dot);
00379       //printf("Old Dot: %4.2f\n\r",old_dot);
00380       
00381        oled_text_properties_t textProperties = {0};
00382       oled.GetTextProperties(&textProperties); 
00383       
00384       /* Set text properties to white and right aligned for the dynamic text */
00385       textProperties.fontColor = COLOR_BLUE;
00386       textProperties.alignParam = OLED_TEXT_ALIGN_LEFT;
00387       oled.SetTextProperties(&textProperties);  
00388       
00389       /* Display Legends */
00390       //strcpy((char *) text1,"Steps: ");
00391       //oled.Label((uint8_t *)text1,3,45);      
00392       StepNum = StepNumber;
00393       if(abs(dot - old_dot) >= 0.05 && abs(dot - old_dot) <= 0.10) 
00394       {
00395             StepNumber += 1;
00396         
00397       }
00398       //printf("%4.2f\n\r",dot);
00399       old_accx = ax;
00400       old_accy = ay;
00401       old_accz = az;
00402       old_dot = dot;
00403       
00404         Thread::wait(250);
00405 }
00406 
00407 
00408 void StartHaptic(void)  {
00409     hapticTimer.start(50);
00410     haptic = 1;
00411 }
00412 
00413 void StopHaptic(void const *n) {
00414     haptic = 0;
00415     hapticTimer.stop();
00416 }
00417