The HexiHeart is a demo project product that takes advantage of many of the onboard Hexiwear sensors and capabilities to create a multifunctional fitness and safety watch.
Dependencies: FXAS21002 FXOS8700 Hexi_KW40Z Hexi_OLED_SSD1351 MAXIM W25Q64FVSSIG HTU21D MPL3115A2 TSL2561
Fork of HexiHeart_Alex by
Diff: main.cpp
- Revision:
- 14:c3b080cdf36b
- Parent:
- 13:37cd579208e9
- Child:
- 15:330794a9f347
--- a/main.cpp Mon Apr 09 13:31:46 2018 +0000 +++ b/main.cpp Wed Apr 11 01:46:49 2018 +0000 @@ -20,6 +20,9 @@ Display data screen update routines ************** Versions **************** +v2.13 - Added heart rate measurement, heart rate simulation, +improved heart rate leds, and optimized heart rate functionalities + v2.12 - Added hidden reset feature (push left button 9+ times, on screen zero, to reset), added line that might put K64 into low power run mode, added dimming feature to display, changed humid/temp and battery measurement to a rolling average. Made new screen for sending panic alert. @@ -66,13 +69,20 @@ #include "images.h" -//*************** Definitions -#define SW_Ver 2.12 // For displaying software version +/* General Definitions */ +#define SW_Ver 2.13 // For displaying software version #define LED_ON 0 #define LED_OFF 1 #define SCRN_TIME 10.0 // Set OLED screen turn off time to 10.0 seconds -#define WDT_TIME 2.0 // Set Watch Dog timer to 1.5 seconds (1.5s reset in certain subroutines) +#define WDT_TIME 5.0 // Set Watch Dog timer to 1.5 seconds (1.5s reset in certain subroutines) #define Debug 1 // If "Debug" is defined, our code will compile for debug. Comment out for Production code. + +#define FXOS8700_I2C_ADDRESS_ (0x1E<<1) //pins SA0,SA1=0 +#define FXAS21002_I2C_ADDRESS_ 0x40 // +//#define TSL2561_I2C_ADDRESS_ (0x29 << 1) // Address select line is grounded +//#define MPL3115A2_I2C_ADDRESS_ ? // + +/*Heart Rate Definitions */ #define HIGHEST_ZONE 4 // Highest heart rate zone #define LOWEST_ZONE 1 #define ENTER_BELOW 25 @@ -80,10 +90,44 @@ #define EXIT_BELOW 75 #define EXIT_ABOVE 100 #define VIB_OPT_2 75 // Haptic vibration pattern option for heart rate functions -#define FXOS8700_I2C_ADDRESS_ (0x1E<<1) //pins SA0,SA1=0 -#define FXAS21002_I2C_ADDRESS_ 0x40 // -//#define TSL2561_I2C_ADDRESS_ (0x29 << 1) // Address select line is grounded -//#define MPL3115A2_I2C_ADDRESS_ ? // +/* I2C Address */ +#define HR_W_ADDR 0xAE +#define HR_R_ADDR 0xAF + +/* Status */ +#define REG_INT_MSB 0x00 /* Interrupt Status 1 */ +#define REG_INT_LSB 0x01 /* Interrupt Status 2 */ +#define REG_INT_ENB_MSB 0x02 /* Interrupt Enable 1 */ +#define REG_INT_ENB_LSB 0x03 /* Interrupt Enable 2 */ +/* FIFO */ +#define REG_FIFO_WR_PTR 0x04 /* FIFO Write Pointer */ +#define REG_OVF_COUNTER 0x05 /* Overflow Counter */ +#define REG_FIFO_RD_PTR 0x06 /* FIFO Read Pointer */ +#define REG_FIFO_DATA 0x07 /* FIFO Data Register */ +/* Configuration */ +#define REG_FIFO_CONFIG 0x08 /* FIFO Configuration */ +#define REG_MODE_CONFIG 0x09 /* Mode Configuration */ +#define REG_SPO2_CONFIG 0x0A /* SpO2 Configuration */ +/* reserved 0x0B */ +#define REG_LED1_PA 0x0C /* RED LED Pulse Amplitude 1 */ +#define REG_LED2_PA 0x0D /* IR LED Pulse Amplitude 2 */ +#define REG_LED3_PA 0x0E /* GREEN LED Pulse Amplitude 3 */ +/* reserved 0x0F */ +#define REG_PILOT_PA 0x10 /* Proximity LED Pulse Amplitude */ +#define REG_SLOT_MSB 0x11 /* Multi-LED Mode Control Registers 2, 1 */ +#define REG_SLOT_LSB 0x12 /* Multi-LED Mode Control Registers 4, 3 */ +/* DIE Temperature */ +#define REG_TEMP_INT 0x1F /* Die Temperature Integer */ +#define REG_TEMP_FRAC 0x20 /* Die Temperature Fraction */ +#define REG_TEMP_EN 0x21 /* Die Temperature Config */ +/* Proximity Function */ +#define REG_PROX_INT_THR 0x30 /* Proximity Interrupt Threshold */ +/* Part ID */ +#define REG_REV_ID 0xFE /* Revision ID */ +#define REG_PART_ID 0xFF /* Part ID: 0x15 */ +/* Depth of FIFO */ +#define FIFO_DEPTH 32 +/* End of heart rate definitions */ void StartHaptic(void); @@ -135,6 +179,33 @@ void WDT_Timeout(void); // WDT Routine used reset void CLRWDT(void); // function to clear WDT void UpDate_Ave(void); // function used to update slow changing measurments +void HR_Simulation(void); // Step through a constrained random heart rate simulation to demo zones +void readRegs(int, uint8_t *, int); //I2c read for maxim chip +void writeRegs(uint8_t, int); //I2c write for maxim chip +/* Functions for setting maxim chip values */ +void setIntEnable(uint16_t); +void setFIFO_WR_PTR(uint8_t); +void setOVF_COUNTER(uint8_t); +void setFIFO_RD_PTR(uint8_t); +void setFIFO_DATA(uint8_t); +void setFIFO_CONFIG(uint8_t); +void setMODE_CONFIG(uint8_t); +void setSPO2_CONFIG(uint8_t); +void setLED1_PA(uint8_t); +void setLED2_PA(uint8_t); +void setLED3_PA(uint8_t); +void setPILOT_PA(uint8_t); +void setSLOT(uint16_t); +void setPROX_INT_THR(uint8_t); +void clearFIFO(void); +uint32_t readFIFO(void); //Read from the maxim chips fifo +void maxReset(void); //Reset maxim chip +void maxInit(void); //Initialize the maxim chip with necessary values +uint16_t getIntEnable(void); +void maxEnable(void); //Begin the maxim chip light measurements +void maxDeinit(void); //Turn off the maxim chip +uint32_t isPeak(uint32_t *); //Calculate the peak of a sample from the maxim chip +void processHeartRate(void); //Calculate the heart rate measurement // ***************** Global variables *********************** char text_1[20]; // Text buffer - Do we need more? @@ -166,7 +237,6 @@ uint8_t Current_Zone = 1; uint8_t Prev_Zone = 1; uint8_t Heart_Rate = 100; -uint8_t HR_buff[250]; uint8_t *HR_return; uint8_t Age = 50; // Initialize age uint8_t Max_Bpm = 220 - Age; // Initialize Max BPM @@ -186,7 +256,9 @@ int sample_humid = 0; // used in Heat index calc uint8_t batt_per_level = 0; // uint8_t Ave_Num = 0; - +bool randomized = 0; //Initialize to 0, since srand has not been called +int simulation_stage = 0; +uint32_t hr_data[100]; // Pointers for screen images const uint8_t *Hexi_Heart_ = Hexi_Heart_bmp; //const uint8_t *NB_Linkedin = NB_Linkedin_bmp; @@ -225,7 +297,7 @@ DigitalOut OLED_PWR(PTC13); // this pin turns on/off 15V supply to OLED display DigitalOut PowerEN (PTB12); // 3V3B Power Enable for HTU21D (Temp/Hum sensor) and Light sensor Sensor supply -DigitalOut HR_PWR(PTA29); // this pin turns on/off power to heart rate sensor +DigitalOut maxim(PTA29); // this pin turns on/off power to heart rate sensor //DigitalIn Sw1(PTA12); //Switch 'T1' on docking station AND Led_clk1!! //DigitalIn Sw2(PTA13); //Switch 'T2' on docking station AND Led_clk2!! DigitalIn Sw3(PTA15); //Switch 'T3' on docking station @@ -257,6 +329,10 @@ Ticker chk_motion; // Ticker used to check on post fall motion Ticker Haptic_Timer; Ticker WDT_Timer; +Ticker hr_led; +Ticker hr_simulation; +Ticker hr_ticker; +Ticker hr_measure_ticker; /***************************************************************************** Name: timout_timer() @@ -365,13 +441,11 @@ break; } case 7: {// Heart Rate Zone - StartHaptic(50); - Enable_Heart_Rate(); - //heart.enable(); - //HR_Enable = 1; - //while(HR_Enable == 1) - // heart.readRawData(HR_buff, HR_return); - //update_display(); + StartHaptic(); + maxInit(); + maxEnable(); + hr_led.attach(&Led_Zone_Indicator, 1); + hr_ticker.attach(&processHeartRate, 5); break; } case 8: {// Alert History @@ -456,8 +530,26 @@ break; } case 31: { //Manually Increment Heart Rate by 1 - Increment_Heart_Rate(); - Determine_Current_Zone(); + //StartHaptic(); + if(maxim == 0) + { + Increment_Heart_Rate(); + // Determine_Current_Zone(); + update_display(); + } + break; + } + case 32: {//Turn on HR led blinking for manual demonstration + hr_led.attach(&Led_Zone_Indicator, 1); + break; + } + case 33:{//Start heart rate simulation + StartHaptic(); + if(maxim == 0) + { + hr_led.attach(&Led_Zone_Indicator, 1); + hr_simulation.attach(&HR_Simulation, 5.0); + } update_display(); break; } @@ -609,8 +701,8 @@ break; } case 7: {// Heart Rate Zone - StartHaptic(100); - Disable_Heart_Rate(); + StartHaptic(); + maxDeinit(); break; } case 8: {// Alert History @@ -704,8 +796,27 @@ break; } case 31: { //Manually decrement heart rate by 1 - Decrement_Heart_Rate(); - Determine_Current_Zone(); + if(maxim == 0) + { + Decrement_Heart_Rate(); + // Determine_Current_Zone(); + update_display(); + } + + break; + } + case 32: {//End HR led used for manual demonstration + hr_led.detach(); + break; + } + case 33: {//End HR Simulation early + StartHaptic(); + if(maxim == 0) + { + hr_simulation.detach(); + simulation_stage = 0; + hr_led.detach(); + } update_display(); break; } @@ -912,18 +1023,17 @@ update_display(); break; } - case 31: { + case 32: { StartHaptic(); - Screen_Num = 32; + Screen_Num = 33; update_display(); break; } - case 32: { + case 33: { StartHaptic(); Screen_Num = 7; update_display(); - break; - } + } case 41: {// Fall-Mode adj StartHaptic(); Screen_Num = 42; //Change to screen 42 @@ -1173,6 +1283,12 @@ update_display(); break; } + case 33: { + StartHaptic(); + Screen_Num = 32; + update_display(); + break; + } case 41: {// Fall mode screen StartHaptic(); Screen_Num = 22; @@ -1298,11 +1414,11 @@ // ***************** Reset sensors *********************** OLED_PWR = 0; // Turn off OLED power supply PowerEN = 1; // Turn off (=1)HTU21(Temp/Hum) and TSL2561(Light) sensors to reset them - HR_PWR = 0; // Turn off (=0) Heart rate sensor 1.8V and HRM(3.3V) supply to reset + maxim = 0; // Turn off (=0) Heart rate sensor 1.8V and HRM(3.3V) supply to reset wait(0.2); // how long should we wait for sensors to power down? PowerEN = 0; // Turn on (=0) HTU21(Temp/Hum) and TSL2561(Light) sensors to reset them - HR_PWR = 1; // Turn on (=1)Heart rate sensor +// maxim = 1; // Turn on (=1)Heart rate sensor OLED_PWR = 1; // Turn on OLED power supply wait(0.2); // how long should we wait for sensors to power up? @@ -1597,18 +1713,20 @@ oled.Label((uint8_t *)"Back",10,80); // Display "Back" at x,y break; } - case 7: {// Heart Rate Zone + case 7: {// Heart Rate Zone oled.FillScreen(COLOR_BLACK); // Clear screen + textProperties.fontColor = COLOR_WHITE; + oled.SetTextProperties(&textProperties); oled.Label((uint8_t *)"Heart Rate",18,5); // Display at x,y - oled.Label((uint8_t *)"HR:",15,25); // Display at x,y + oled.Label((uint8_t *)"HR:",10,25); // Display at x,y sprintf(display_buff, "%u", Heart_Rate); textProperties.fontColor = COLOR_RED; //Change font to red oled.SetTextProperties(&textProperties);//Implement color change oled.Label((uint8_t *)display_buff,43,25); // Display at x,y textProperties.fontColor = COLOR_WHITE; oled.SetTextProperties(&textProperties); - oled.Label((uint8_t *)"Age: ",15,45); // Display at x,y + oled.Label((uint8_t *)"Age: ",10,45); // Display at x,y textProperties.fontColor = COLOR_GREEN; oled.SetTextProperties(&textProperties); //implements the color change sprintf(display_buff, "%u", Age); //Convert int to char array for displaying user age @@ -1617,13 +1735,8 @@ oled.SetTextProperties(&textProperties); oled.Label((uint8_t *)"On",80,15); // "+" at x,y oled.Label((uint8_t *)"Off",78,60); // "-" at x,y - oled.Label((uint8_t *)"Back",10,80); // Display "Back" at x,y + oled.Label((uint8_t *)"Menu",10,80); // Display "Back" at x,y oled.Label((uint8_t *)"Next",60,80); // Display "Next" at x,y - - //heart.enable(); - //sprintf(display_buff, "%u", heart.getRevisionID()); //Convert int to char array for displaying user age - //oled.Label((uint8_t *)display_buff,45,25); // Display at x,y - //update_display(); break; } case 8: {// Alert History @@ -2050,12 +2163,9 @@ } case 31: { oled.FillScreen(COLOR_BLACK); - Heart_Rate_Vibrations(); oled.Label((uint8_t *)"Enter HR", 10, 5);// Display at x,y oled.Label((uint8_t *)"Back",10,80); // Display "Back" at x,y oled.Label((uint8_t *)"Next",60,80); //Display "Next" at x,y - oled.Label((uint8_t *)"+",85,15); // "+" at x,y - oled.Label((uint8_t *)"-",85,60); // "-" at x,y oled.Label((uint8_t *)"HR:", 10, 25); sprintf(display_buff, "%u", Heart_Rate); // Convert int to char to display textProperties.fontColor = COLOR_RED; //Change font to red @@ -2099,8 +2209,6 @@ oled.Label((uint8_t *)display_buff, 71, 60); textProperties.fontColor = COLOR_WHITE; //Change font to white oled.SetTextProperties(&textProperties);//Implement color change - CLRWDT(); - Led_Zone_Indicator(); break; } case 32: { @@ -2145,37 +2253,33 @@ oled.Label((uint8_t *)"Next",60,80); //Display "Next" at x,y break; } - case 41: { //Fall mode + case 33: {//Heart rate simulator oled.FillScreen(COLOR_BLACK); - oled.Label((uint8_t *)"Adj Fall Mode", 10, 5); - sprintf(display_buff, "%u", Fall_Alert_Mode); //Convert int to char array for displaying mode - oled.Label((uint8_t *)"Mode:", 5, 30); - oled.Label((uint8_t *)"+",85,15); // "*" at x,y - oled.Label((uint8_t *)"-",85,60); // "*" at x,y + textProperties.fontColor = COLOR_WHITE; + oled.Label((uint8_t *)"HR Simulation", 10, 5);// Display at x,y + oled.Label((uint8_t *)"HR: ", 10, 40);// Display at x,y oled.Label((uint8_t *)"Back",10,80); // Display "Back" at x,y oled.Label((uint8_t *)"Next",60,80); //Display "Next" at x,y - textProperties.fontColor = COLOR_GREEN; - oled.SetTextProperties(&textProperties); - oled.Label((uint8_t *)display_buff,43,30); // Display at x,y + oled.Label((uint8_t *)"On",75,25); // "*" at x,y + oled.Label((uint8_t *)"Off",75,55); // "*" at x,y + sprintf(display_buff, "%u", Heart_Rate); // Convert int to char to display + if(Current_Zone == 1) { + textProperties.fontColor = COLOR_YELLOW; + oled.SetTextProperties(&textProperties); + } else if(Current_Zone == 2) { + textProperties.fontColor = COLOR_BLUE; + oled.SetTextProperties(&textProperties); + } else if(Current_Zone == 3) { + textProperties.fontColor = COLOR_GREEN; + oled.SetTextProperties(&textProperties); + } else if(Current_Zone == 4) { + textProperties.fontColor = COLOR_RED; + oled.SetTextProperties(&textProperties); + } + oled.Label((uint8_t *)display_buff, 35, 40);// Display at x,y textProperties.fontColor = COLOR_WHITE; oled.SetTextProperties(&textProperties); - break; - } - case 42: { //Fall Thresh - oled.FillScreen(COLOR_BLACK); - oled.Label((uint8_t *)"Adj F-Th", 10, 5); - sprintf(display_buff, "%2.2f g", Fall_Thresh); //Convert int to char array for displaying mode - oled.Label((uint8_t *)"F_Th:", 5, 30); - oled.Label((uint8_t *)"+",85,15); // "*" at x,y - oled.Label((uint8_t *)"-",85,60); // "*" at x,y - oled.Label((uint8_t *)"Back",10,80); // Display "Back" at x,y - oled.Label((uint8_t *)"Next",60,80); //Display "Next" at x,y - textProperties.fontColor = COLOR_GREEN; - oled.SetTextProperties(&textProperties); - oled.Label((uint8_t *)display_buff,43,30); // Display at x,y - textProperties.fontColor = COLOR_WHITE; - oled.SetTextProperties(&textProperties); - break; + break; } case 43: { //Impact Thresh oled.FillScreen(COLOR_BLACK); @@ -3979,17 +4083,23 @@ case 10: {// reset - char d[2]; - d[0] = 0x09; // Mod_conf reg - SHDN, reset, modes - d[1] = 0b01000000; //resets IC - if(i2c_bus0.write(0xaf, d, 2) ==1){ - oled.Label((uint8_t *)"MAX_W_Err10a",5,1); // Display "error" at x,y - wait(2.0); // wait 0 seconds - }//end if - else { - // oled.Label((uint8_t *)"MAX_Reset",20,30); // Display "reset" at x,y + if(maxim == 0) + { } - wait(0.01); // wait 0.01 seconds + else + { + char d[2]; + d[0] = 0x09; // Mod_conf reg - SHDN, reset, modes + d[1] = 0b01000000; //resets IC + if(i2c_bus0.write(0xaf, d, 2) ==1){ + oled.Label((uint8_t *)"MAX_W_Err10a",5,1); // Display "error" at x,y + wait(2.0); // wait 0 seconds + }//end if + else { + // oled.Label((uint8_t *)"MAX_Reset",20,30); // Display "reset" at x,y + } + wait(0.01); // wait 0.01 seconds + } break; }// end of case 10 @@ -4286,4 +4396,316 @@ if(Ave_Num>4){ Ave_Num = 4;//set limit } - }// end UpDate_Ave \ No newline at end of file +}// end UpDate_Ave +void HR_Simulation(void) +{ + if(randomized == 0) + { + srand(hi_calc); + randomized = 1; + } + if(simulation_stage == 0) + { + Heart_Rate = HR_Zone1[0] + rand() %( HR_Zone1[1] - HR_Zone1[0] + 1); + + } + else if(simulation_stage == 1) + { + Heart_Rate = HR_Zone2[0] + rand() %( HR_Zone2[1] - HR_Zone2[0] + 1); + + } + else if(simulation_stage == 2) + { + Heart_Rate = HR_Zone3[0] + rand() %( HR_Zone3[1] - HR_Zone3[0] + 1); + + } + else if(simulation_stage == 3) + { + Heart_Rate = HR_Zone4[0] + rand() %( HR_Zone4[1] - HR_Zone4[0] + 1); + + } + else if(simulation_stage == 4) + { + Heart_Rate = HR_Zone3[0] + rand() %( HR_Zone3[1] - HR_Zone3[0] + 1); + + } + else + { + simulation_stage = -1; + } + simulation_stage++; + Determine_Current_Zone(); + update_display(); +} + +void readRegs(int addr, uint8_t * data, int len) +{ + char temp[1] = {addr}; + i2c_bus0.write(HR_W_ADDR, temp, 1, true); + i2c_bus0.read(HR_R_ADDR, (char*)data, len); + +} + +void writeRegs(uint8_t * data, int len) +{ + i2c_bus0.write(HR_W_ADDR, (char*)data, len); +} + +void setIntEnable(uint16_t mask) +{ + uint8_t res[3]; + res[0] = REG_INT_ENB_MSB; + res[1] = (mask >> 8) & 0xFF; + res[2] = (mask & 0xFF); + writeRegs(res, 3); +} + + +void setFIFO_WR_PTR(uint8_t data) +{ + uint8_t res[2]; + res[0] = REG_FIFO_WR_PTR; + res[1] = data; + writeRegs(res, 2); +} + +void setOVF_COUNTER(uint8_t data) +{ + uint8_t res[2]; + res[0] = REG_OVF_COUNTER; + res[1] = data; + writeRegs(res, 2); +} + +uint8_t getFIFO_RD_PTR(void) +{ + uint8_t data; + readRegs(REG_FIFO_RD_PTR, &data, 1); + return (data); +} + +void setSLOT(uint16_t data) +{ + uint8_t res[3]; + res[0] = REG_SLOT_MSB; + res[1] = (data >> 8) & 0xFF; + res[2] = data & 0xFF; + writeRegs(res, 3); +} + +void setFIFO_RD_PTR(uint8_t data) +{ + uint8_t res[2]; + res[0] = REG_FIFO_RD_PTR; + res[1] = data; + writeRegs(res, 2); +} + +void setFIFO_DATA(uint8_t data) +{ + uint8_t res[2]; + res[0] = REG_FIFO_DATA; + res[1] = data; + writeRegs(res, 2); +} + +void setFIFO_CONFIG(uint8_t data) +{ + uint8_t res[2]; + res[0] = REG_FIFO_CONFIG; + res[1] = data; + writeRegs(res, 2); +} + + +void setMODE_CONFIG(uint8_t data) +{ + uint8_t res[2]; + res[0] = REG_MODE_CONFIG; + res[1] = data; + writeRegs (res, 2); +} + +void setSPO2_CONFIG(uint8_t data) +{ + uint8_t res[2] ; + res[0] = REG_SPO2_CONFIG ; + res[1] = data ; + writeRegs(res, 2) ; +} + +void setLED1_PA(uint8_t data) +{ + uint8_t res[2] ; + res[0] = REG_LED1_PA ; + res[1] = data ; + writeRegs(res, 2) ; +} + +void setLED2_PA(uint8_t data) +{ + uint8_t res[2] ; + res[0] = REG_LED2_PA ; + res[1] = data ; + writeRegs(res, 2) ; +} + +void setLED3_PA(uint8_t data) +{ + uint8_t res[2] ; + res[0] = REG_LED3_PA ; + res[1] = data ; + writeRegs(res, 2) ; +} + +void setPILOT_PA(uint8_t data) +{ + uint8_t res[2] ; + res[0] = REG_PILOT_PA ; + res[1] = data ; + writeRegs(res, 2) ; +} + + + + +void setPROX_INT_THR(uint8_t data) +{ + uint8_t res[2] ; + res[0] = REG_PROX_INT_THR ; + res[1] = data ; + writeRegs(res, 2) ; +} + +void clearFIFO(void) +{ + uint8_t res[5] ; + res[0] = REG_FIFO_WR_PTR ; + res[1] = 0x00 ; /* FIFO_WR_PTR */ + res[2] = 0x00 ; /* OVF_COUNTER */ + res[3] = 0x00 ; /* FIFO_RD_PTR */ + res[4] = 0x00 ; /* FIFO_DATA (do we need to clear this?) */ + writeRegs(res, 5) ; +} + +/* + * readFIFO(void) + * FIFO data is always a 3-bytes data + * byte1[1:0] : FIFO_DATA[17]-FIFO_DATA[16] + * byte2[7:0] : FIFO_DATA[15]-FIFO_DATA[8] + * byte3[7:0] : FIFO_DATA[7]-FIFO_DATA[0] + * The data is left aligned, so FIFO_DATA[17] + * is always MSB, although the data length + * can be 18-bit ~ 15-bit + */ +uint32_t readFIFO(void) +{ + uint32_t data = 0 ; + uint8_t res[3] ; + readRegs(REG_FIFO_DATA, res, 3) ; + data = + ((res[0] & 0x03)<<16) + | (res[1] << 8) + | res[2] ; + return( data ) ; +} + +void maxReset(void) +{ + uint8_t res[2] ; + res[0] = REG_MODE_CONFIG ; + res[1] = 0x40 ; /* reset */ + writeRegs(res, 2) ; +} + +void maxInit(void) +{ + maxim = 1; + maxReset(); + wait(0.05); + setLED1_PA(0xFF); + setLED2_PA(0x33); + setLED3_PA(0xFF); + setPILOT_PA(0x19); + wait(0.05); + setSLOT(0x0300); + setFIFO_CONFIG(0x06); + setSPO2_CONFIG(0x42); + wait(0.05); + setPROX_INT_THR(0x14); + clearFIFO(); + wait(0.05); +} + +void maxEnable(void) +{ + setIntEnable(0x8000); + setMODE_CONFIG(0x07); + Enable_Heart_Rate(); +} + +void maxDeinit(void) +{ + maxim = 0; + hr_ticker.detach(); + hr_measure_ticker.detach(); + Disable_Heart_Rate(); + hr_led.detach(); +} + +void processHeartRate(void) +{ + + uint32_t peak; + + for(int i = 0; i < 100; i++) + { + hr_data[i] = readFIFO(); + if(i % 3 == 1) + wait(0.05); + } + + + peak = isPeak(hr_data); + + uint8_t hr = (uint8_t)((60 * peak * 50)/ 100); + if(hr >= HR_Zone1[0] && hr <= HR_Zone4[1]) + { + Heart_Rate = hr; + update_display(); + } + Determine_Current_Zone(); + + +} + +uint32_t isPeak(uint32_t hr_array[]) +{ + uint32_t peaks[100]; + uint32_t numPeaks = 0; + uint32_t index = 0; + uint32_t currentPeak = 0; + + for(int i = 1; i < 100; i++) + { + if((hr_array[i] > hr_array[i + 1]) && (hr_array[i] > hr_array[i - 1])) + { + peaks[index] = hr_array[i]; + numPeaks++; + index++; + } + } + if(numPeaks > 0) + { + currentPeak = peaks[0]; + for(int i = 0; i < numPeaks; i++) + { + if(currentPeak < peaks[i]) + { + currentPeak = peaks[i]; + } + } + } + + return currentPeak; +} \ No newline at end of file