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 Hexiwear_zeta

main.cpp

Committer:
asong
Date:
2018-05-10
Revision:
22:3de592f8e696
Parent:
21:76237b62466b

File content as of revision 22:3de592f8e696:

/**********************************************************************
HexiHeart
Texas State University Senior Project - Fall 2017/Spring 2018 

Team Zeta:
Alex Song           - https://www.linkedin.com/in/alex-song-a12632134/
Jasmine Rounsaville - https://www.linkedin.com/in/jasmine-rounsaville/
Issam Hichami       - https://www.linkedin.com/in/issam-hichami-06878aa3/
Neil Baker          - https://www.linkedin.com/in/neil-baker-41602a23/
You can find more about Team Zeta here: https://os.mbed.com/teams/Hexiwear_zeta/

******Basic Program layout********
Declarations
Up Button routines
Down Button routines
Right Button routines
Left Button routines 
Main()
Main display screen routines
Function and interrupt routines
Display data screen update routines

**************   Versions  ****************
V2.17 - Added heart rate measurement to the main screen when any of the heart
rate features are enabled. Fixed some WDT resets with certain heart rate 
vibrations.

v2.16 - Cast rolling average calculations as float to reduce rounding error. 
removed two screens from diagnostic because we don't use them.
Changed FAP to AFP in two locations.  

v2.15 - added display screens 41 and 42 back in. 

v2.14 - Retasked hr_led Ticker to turn off heart rate zone LEDs thereby preventing the 
system from having to spend half its time in a wait state. added HR screen #7 to  
screens that get refreshed with new data twice a second. Reduced WDT back to 2 seconds.  
Increased rolling average to 10 samples. removed 0.05s wait during HR read.

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.

v2.11 - 4/1/18 - Added Send_Alert(0) to turn off alerts by sending amb_light=0, 
added WDT and added WDT testing screens, changed fall Min_Movement_duration 
from 60s to 10s, added subtle vibration after impact for diagnostic purposes.

v2.10 - Adding BLE pairing code, spoofing amb light sensor data for alert status 
light=10 =>Panic Alert, 20=Fall+asked for help, 30=Fall+No response, 40=?...

v2.09 - 3/25/18 - Added final fall mode (full sequential fall algorithm), including alert screen 
and dismiss alert screen.  Added FAP (Fall Alert Protection) to main screen. fixed "aggressive Haptic" problem by using a Ticker to 
turn off Haptic instead of RTOS timer.

v2.08 - Fixed impact detect functionality, all fall detect parameters are now adjustable, 
added motion detect function, incorporated new heat index calc, increased font by 20% for time/date. 
Added SW and power resetting to initialize sensors in known state.

v2.07 - 2/18/18 - Added fall mode option to test fall/impact separately, Added global 
interrupt disable prevent button interrupts while refreshing screen, this caused haptic 
timer to stop working right.

v1.0 - 11/12/17
This version has basic menu layout and screen timeout feature.  The menu
are just placeholders (for the most part) and will be either adjusted or
replaced with graphic images.
***********************************************************************/

#include "mbed.h"
#include "Hexi_KW40Z.h"         // Button and BLE fuctions
#include "FXOS8700.h"           // Freescale/NXP FXOS8700CQ - 3D Accelorometer & Mag
#include "FXAS21002.h"          // Freescale/NXP FXAS21002CQ - 3-Axis Gyroscope
//#include "MPL3115A2.h"          // Freescale/NXP MPL3115A2 - pressure sensor 
#include "HTU21D.h"             // Non-Freescale/NXP - HTU21D - combo temperature and Humidity
#include "W25Q64FV.h"           // Non-Freescale/NXP - W25Q64FVSSIG - 8MB/64Mbit Serial Flash memory
#include "MAX30101.h"           // Non-Freescale MAX30101 - Optical Heart rate sensor 
//#include "TSL2561.h"            // Non-Freescale/NXP TSL2561 - light sensor
#include "Hexi_Battery/hexi_battery.h"  // Battery status
#include "Hexi_OLED_SSD1351.h"  // OLED fuctions
#include "OLED_types.h"         // Text attributs
#include "string.h"
#include "OpenSans_Font.h"
#include "images.h"


/* General  Definitions */
#define SW_Ver          2.17    // 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 MAX_AVE_NUM     10.0f       // maximum averaging depth of rolling average for batt, temp and humid
#define Debug           1       // If "Debug" is defined, our code will compile for debug.  Comment out for Production code.

#define FXOS8700_I2C_ADDRESS_ (0x1E<<1) //I2C address, pins SA0,SA1=0 
#define FXAS21002_I2C_ADDRESS_ 0x40      //I2C address
//#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
#define ENTER_ABOVE     50
#define EXIT_BELOW      75
#define EXIT_ABOVE      100
#define VIB_OPT_2       75      // Haptic vibration pattern option for heart rate functions
#define HR_LED_on_time  0.5 //how long should zone LED stay on for?
#define HR_LED_period   1.0 //how often should zone LED blink?
/* 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);
void Haptic_Off_(void); // added by NRB
void StartHaptic(int x);
void StopHaptic(void const *n);
void error_screen(void);  // display error screen 
void update_display(void);// Screen lables refreshed
void update_display_date(void);  // Screen data(only)refreshed 
void Screen_timer1(void);
void Decrement_Age();
void Set_Max_Bpm();
void Set_Zone_Boundaries();
void Increment_Age();
void Increment_Target_Zone();
void Decrement_Target_Zone();
void Increment_HR_Vibr_Pref();
void Decrement_HR_Vibr_Pref();
void Determine_Current_Zone();
void Heart_Rate_Vibrations();
void Increment_Heart_Rate();
void Decrement_Heart_Rate();
void Enable_Heart_Rate();
void Disable_Heart_Rate();
void Led_Zone_Indicator();
void Led_Zone_Indicator_off(); // turns off LEDs after 0.5 seconds instead of using a wait command
void Heat_Index_Calculation();
void fall_config(uint8_t);         //function call to setup fall detecting modes
void accel_sensor_config(uint8_t); 
void gyro_sensor_config(uint8_t); 
void light_config(uint8_t); 
void press_config(uint8_t); 
void fall_detect(void);         // Interupt routine
void fall_detect_debug(void);   // Interupt routine
void fall_det_end(void);        // Interupt routine
void fall_det_end_debug(void);  // Interupt routine
void chkfall(void);             // Routine used with Ticker 
void interupt_off(void);
void clear_fall(void);          // Routine used with Ticker
void impact_detect(void);       // Interupt routine
void impact_detect_debug(void); // Interupt routine
void motion_detect();           // Interupt routine
void motion_detect_debug();     // Interupt routine
void chkmotion(void);           // Routine used with Ticker
void chk_help_needed(void);     // Routine used with Ticker
void txTask(void);
void PassKey(void);
void MAX30101_test_config(uint8_t);
void Send_Alert(uint8_t);       // function to store and send alert
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?
char display_buff[30];      //Buffer for conversion to char to display
char text[20];              // Text Buffer for dynamic value displayed
bool BLE_On = 1;            // Initialize as BLE on
char pass [20];              // Passcode
bool Led_Zones = 1;
bool HR_Enable = 0;
bool OLED_ON = 1;           // Turn OLED power on/off
bool Fall_Alert = 1;        // Initialize as no active alert
bool Panic_Alert = 0;       // Initialize as no active alert
uint8_t Fall_Alert_Mode = 5;   // Initialize with fall alert mode on
bool Heart_Rate_Mode = 0;   // Initialize with Heart rate off
float Accel_Mag=0.0;        // Vector magnitude calculated from sensor data
float Accel_Data[3];        // Accel Data from sensor
float Accel_Data_Event[3];  // Accel Data from sensor at interupt
float Fall_Event_Data[7];   // Fall event Data ff-value, ff-time, impact-value, 4byte timestamp
float Gyro_Mag=0.0;         // Vector magnitude calculated from sensor data
float Gyro_Data[3];             // Gyro data from sensor
float Fall_Thresh=0.5;          // Initialize Free-Fall detect Threshold as being <= 0.5g
float Fall_Impact_Max_Wait_Time=2.0;// maximum wait time from end of fall detect to impact detect 
float Impact_Thresh=3.0;        // Initialize Impact detect Threshold
float Movement_Thresh=50.0;     // Initialize Movement detect Threshold
float Min_Movement_Time=5.0;    // Initialize Movement minimum movement time to 5 sec
float Min_Movement_duration=10.0;    // Initialize Movement min-movement testing duration to 60 sec
float Do_You_Need_Help_Time=10.0; // Time to dismiss "Do you need Help" screen
uint8_t Reset_Count = 0;
uint8_t Current_Zone = 1;
uint8_t Prev_Zone = 1;
uint8_t Heart_Rate = 0;
uint8_t rand_stage;
uint8_t *HR_return;
uint8_t Age = 25;            // Initialize age
uint8_t Max_Bpm = 220 - Age;      // Initialize Max BPM
uint8_t Screen_Num = 0;      // Initialize to main screen
uint8_t Error_Num = 0;         // Error num for debug
uint8_t HR_Vibration = 2;       //Choose Heart Rate Vibration Options
uint8_t Target_Zone = 2;        //Initialize Target Heart Rate Zone to Zone 3
uint8_t HR_Zone1[2] = {Max_Bpm * .50, Max_Bpm * .60};       //Heart Rate Zone 1
uint8_t HR_Zone2[2] = {HR_Zone1[1] + 1, Max_Bpm * .70};       //Heart Rate Zone 2
uint8_t HR_Zone3[2] = {HR_Zone2[1] + 1, Max_Bpm * .80};       //Heart Rate Zone 3
uint8_t HR_Zone4[2] = {HR_Zone3[1] + 1, Max_Bpm};       //Heart Rate Zone 4
uint8_t heat_index;                  // used in Heat index calc
int hi_calc;                    // used in Heat index calc
int adjustment;                 // used in Heat index calc
bool randomized = 0; //Initialize to 0, since srand has not been called
int simulation_stage = 0;
uint32_t hr_data[100];
// slow changing variables
int sample_ftemp = 0;               // used in Heat index calc
int sample_humid = 0;               // used in Heat index calc
uint8_t batt_per_level = 0;         //
float Ave_Num  = 0.0; 


// Pointers for screen images 
const uint8_t *Hexi_Heart_ = Hexi_Heart_bmp;
//const uint8_t *NB_Linkedin = NB_Linkedin_bmp;  
//const uint8_t *AS_Linkedin = NB_Linkedin_bmp;  
//const uint8_t *IR_Linkedin = NB_Linkedin_bmp;
//const uint8_t *IH_Linkedin = NB_Linkedin_bmp;


// ***************** Define pins *****************************
//W25Q64FVSSIG - 8MB/64Mbit Serial Flash memory (SPI1)(MOSI,SCLK,POWER,CS,RST,DC)
//W25Q64FV(PinName mosi, PinName miso, PinName sclk, PinName cs, int frequency=10000000);
//MKW40Z (SPI1)
SSD1351 oled(PTB22,PTB21,PTC13,PTB20,PTE6, PTD15); // SSD1351 OLED Driver SPI2(MOSI,SCLK,POWER,CS,RST,DC)
FXAS21002 gyro(PTC11,PTC10); // Gyroscope (I2C1 data bus(SDA, SCL))
FXOS8700 accel(PTC11, PTC10); // Accelorometer (I2C1 data bus(SDA, SCL))
FXOS8700 mag(PTC11, PTC10);   // Mag (same chip as Accel) (I2C1 data bus(SDA, SCL))
//MAX30101 heart(PTB1, PTB0); //Heart Rate Chip (I2C0 data bus(SDA, SCL))
HTU21D temphumid(PTB1,PTB0); // HTU21D Sensor (I2C0 data bus(SDA, SCL))
//TSL2561 - (PTB1, PTB0); //Amb light sensor (I2C0 data bus(SDA, SCL))

// initialize I2C bus for FXOS8700, FXAS-Gyro, MPL-Pressure
    I2C i2c_bus1(PTC11, PTC10);  // (SDA, SCL)
// initialize I2C bus for MAX30101, HTU21D, TSL2561
    I2C i2c_bus0(PTB1, PTB0);   // (SDA, SCL)
    
// initialize SPI bus for W25Q64FVSSIG, (and MKW40Z if needed)
//    SPI spi_bus1(PTD6, PTD7, PTD5);  // (MOSI, MISO, SCLK) CS=PTD4?(low=select)

DigitalOut RED_Led(LED1);
DigitalOut GRN_Led(LED2);
DigitalOut BLU_Led(LED3);
DigitalOut haptic(PTB9);
DigitalOut Led_clk1(PTA12);
DigitalOut Led_clk2(PTA13);
DigitalOut Led_clk3(PTA14);

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 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 


/* Instantiate the Hexi KW40Z Driver (UART TX, UART RX) */
KW40Z kw40z_device(PTE24, PTE25);

/* Define timer for haptic feedback */
RtosTimer hapticTimer(StopHaptic, osTimerOnce);

/*Create a Thread to handle sending BLE Sensor Data */ 
//Thread txThread;

//***************** Interrups *****************
InterruptIn Accel_INT1(PTC1);       // Accel sensor's interupt 1
InterruptIn Accel_INT2(PTD13);      // Accel sensor's interupt 2
InterruptIn Gyro_INT1(PTD1);        // Gyro sensor's interupt 1
InterruptIn Gyro_INT2(PTC18);       // Gyro sensor's interupt 2
//InterruptIn Amb_Light_INT1(PTC0);  // TSL2561- Light sensor's interupt
//InterruptIn HR_INT1(PTB18);        // MAX30101 - Heart rate sensor's interupt
//InterruptIn Pressure_INT1(PTD12);  // MPL3115A2 pressure sensor's interupt 1
//InterruptIn Pressure_INT2(PTD10);  // MPL3115A2 pressure sensor's interupt 2

//***************** Tickers and Timers *****************
Ticker Screen_Timer;// use ticker to turn off OLED
Timer f_time;       // Timer used to measure fall 
Ticker chk_fall;    // Ticker used to check on active fall
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()
Purpose: Ticker interupt routine used to dim the OLED screen 3s before turning screen off
Inputs: Screen_Timer Ticker
******************************************************************************/
void timout_timer(){ // turn off display mode
        HexiwearBattery battery;
        battery.sensorOn();  
    if (battery.isBatteryCharging() || (uint8_t)battery.readLevelPercent() > 99) {
        oled.DimScreenOFF();
        Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED while fully charged
    } //end if
    else {
    Screen_Timer.attach(&Screen_timer1,(3));// Dim display for 3 seconds befor turning off display
    oled.DimScreenON(); //Dim display if 3 seconds from turning off
    }//end else
}// end Screen_timer1()

/*****************************************************************************
Name: Screen_timer1(()
Purpose: Ticker interupt routine used to turn off the OLED screen after ~13s to save power
Inputs: Screen_Timer Ticker
******************************************************************************/
void Screen_timer1(){ // turn off display mode
#ifdef Debug    // in debug keep screens on for demo  
        HexiwearBattery battery;
        battery.sensorOn();  
                              
        if (battery.isBatteryCharging() || batt_per_level > 99) {
           Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED while fully charged
           oled.DimScreenOFF();
        } //end if
    else {
#endif        
   /* Turn on the backlight of the OLED Display */
    //oled.DimScreenON(); just dim display for debug
     OLED_PWR = 0;  // Turn off OLED power supply
     OLED_ON = 0;  // set flag to off
     Screen_Timer.detach();  // detach Ticker
#ifdef Debug    // in debug keep screens on for demo  
     } // endelse
#endif   
}//end timout_timer routine


/*****************************************************************************
Name: ButtonUp()
Purpose: Routine called when MK46 recieves a ButtonUP interrupt from KW40
Inputs: Uses global Screen_Num value and other status varibles
Returns: None
******************************************************************************/
void ButtonUp(void)
{
    Screen_Timer.attach(&timout_timer,(SCRN_TIME));//Is this sufficient to reset/restart ticker timer for OLED?
    oled.DimScreenOFF();
    if (OLED_ON == 0) {
        OLED_ON = 1; // Scree was off, set to On
        update_display();
    } else {
        switch(Screen_Num) {
            case 0: {// We're in Main Screen
                // do nothing, wrong button
                break;
            }
            case 1: {// Panic Alert option
                StartHaptic();
                Screen_Num = 5;  //Change to screen 5
#ifdef Debug    // in debug show debug/diagnostic screens                         
                Screen_Num = 26;  //Change to screen 20
#endif

                update_display();
                break;
            }
            case 2: {// Fall Alert option
                StartHaptic();
                Screen_Num = 71;  //Change to screen 71
                update_display();
                break;
            }
            case 3: {// Heart Rate Monitoring option
                StartHaptic();
                Screen_Num = 2;  //Change to screen 2
                update_display();
                break;
            }
            case 4: {// Alert History option
                StartHaptic();
                Screen_Num = 3; //Change to screen 3
                update_display();
                break;
            }
            case 5: {// About HexiHeart
                StartHaptic();
                Screen_Num = 3; //Change to screen 3, skip 4
                update_display();
                break;
            }
            case 6: {// Panic Alert
                StartHaptic();
                Screen_Num = 51; 
                Panic_Alert = 1;
                Send_Alert(10); // send/store alert type zero
                update_display();
                break;
            }
            case 7: {// Heart Rate Zone
                StartHaptic();
                maxInit();
                maxEnable();
                hr_led.attach(&Led_Zone_Indicator, HR_LED_period); // blink every second
                hr_ticker.attach(&processHeartRate, 5); 
                break;
            }
            case 8: {// Alert History
                StartHaptic();
                //Increment  alert index
                break;
            }
            case 9: {// HexiHeart About info1
                    StartHaptic();
                    Screen_Num = 11;  //Change to screen 11
                    update_display();
                    break;
                }    
            case 10: {// HexiHeart About info2
                    StartHaptic();
                    Screen_Num = 9;  //Change to screen 9
                    update_display();
                    break;
                }    
            case 11: {// HexiHeart About info3
                    StartHaptic();
                    Screen_Num = 10;  //Change to screen 9
                    update_display();
                    break;
                } 
            case 20: {// Diagnostic/Debug Screens
                StartHaptic();
                Screen_Num = 5;  //Change to screen 5
                update_display();
                break;
            }
            case 21: {// Fall Diagnostic
                StartHaptic();
                Screen_Num = 49;  //Change to screen 49
                update_display();
                break;
            }
            case 22: {// Fall Debug
                StartHaptic();
                Screen_Num = 21;  //Change to screen 21
                update_display();
                break;
            }
            case 23: {// Heart Rate Diagnostic - not used 
                StartHaptic();
                Screen_Num = 22;  //Change to screen 22
                update_display();
                break;
            }
            case 24: {// Heart Rate Debug - not used
                StartHaptic();
                Screen_Num = 23;  //Change to screen 23
                update_display();
                break;
            }
            case 25: {// Heat Index Diagnostic
                StartHaptic();
                Screen_Num = 21;  //Change to screen 24
                update_display();
                break;
            }
            case 26: {//Heart Rate Config Option
                StartHaptic();
                Screen_Num = 20;
                update_display();
                break;
            }
            case 27: {//Incrementing Age
                Increment_Age();
                Set_Zone_Boundaries();
                update_display();
                break;
            }
            case 28: {//Changing Heart Rate Vibration Preferences
                Increment_HR_Vibr_Pref();
                update_display();
                break;
            }
            case 30: {//Change Target Heart Rate Zone Preference
                Increment_Target_Zone();
                update_display();
                break;
            }
            case 31: { //Manually Increment Heart Rate by 1
                //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, HR_LED_period);
                Heart_Rate_Mode = 1;
                break;
            }
            case 33:{//Start heart rate simulation
                StartHaptic();
                if(maxim == 0)
                {
                    simulation_stage = 0;
                    Heart_Rate_Mode = 1;
                    hr_led.attach(&Led_Zone_Indicator, HR_LED_period);
                    hr_simulation.attach(&HR_Simulation, 5.0);                  
                }
                update_display();
                break;
            }
            
            case 41: {//Fall mode 0,1,2,3,4,5
            // 0=nothing, 1=fall_only, 2=impact only, 3=motion_only, 4=all, 5=main sequence
                StartHaptic();
                Fall_Alert_Mode++;
                if(Fall_Alert_Mode > 5){
                Fall_Alert_Mode = 0;
                }//endif
                update_display();
                __disable_irq();    // Disable all Interrupts
                fall_config(10);  // reset accel sensor
                //gyro_sensor_config(10);  // reset gyro sensor  
                wait(0.1);
                //gyro_sensor_config(Fall_Alert_Mode);  // leave gyro sensor active
                fall_config(Fall_Alert_Mode);
                wait(0.1);
                __enable_irq();     // Enable all Interrupts
                wait(0.3);
                update_display();
                break;
            }    
            case 42: {// F-Th adj
                StartHaptic();
                Fall_Thresh = Fall_Thresh + 0.05f;
                if(Fall_Thresh > 0.9f){
                Fall_Thresh = 0.9;
                }//endif
                update_display();
                break;
            }
            case 43: {// I-Th adj
                StartHaptic();
                Impact_Thresh = Impact_Thresh + 0.1f;
                if(Impact_Thresh > 3.9f){
                Impact_Thresh = 3.9;
                }//endif
                update_display();
                break;
            }
            case 44: {// M-Th adj
                StartHaptic();
                Movement_Thresh = Movement_Thresh + 5.0f;
                if(Movement_Thresh > 300.0f){
                Movement_Thresh = 300.0;
                }//endif
                update_display();
                break;
            }
            case 45: {// Min_Movement_Time adj
                StartHaptic();
                Min_Movement_Time = Min_Movement_Time + 0.1f;
                if(Min_Movement_Time > 2.4f){
                Min_Movement_Time = 2.4;
                }//endif
                update_display();
                break;
            }
            case 46: {// Min_Movement_duration adj
                StartHaptic();
                Min_Movement_duration = Min_Movement_duration + 5.0f;
                if(Min_Movement_duration > 300.0f){
                Min_Movement_duration = 300.0;
                }//endif
                update_display();
                break;
            }      
            case 49: {// WDT debug test screen
                StartHaptic();
                Screen_Num = 25;  //Change to screen 25
                update_display();
                break;
            }
            case 71: {// BLE
                StartHaptic();
                Screen_Num = 1; //Change to screen 1
                update_display();
                break;
            }
            case 72: {// BlueTooth on/off
                // do nothing, wrong button or change to another screen number if you're making more BLE type screens
                break;
            }
            default: {
                break;
            }
        }// end case switch
    }// end if
}// end ButtonUp


/*****************************************************************************
Name: ButtonDown()
Purpose: Routine called when MK46 recieves a ButtonDown interrupt from KW40
Inputs: Uses global Screen_Num value and other status varibles
Returns: None
******************************************************************************/
void ButtonDown(void)
{
    Screen_Timer.attach(&timout_timer,(SCRN_TIME));//Is this sufficient to reset/restart ticker timer for OLED?
    oled.DimScreenOFF();
    if (OLED_ON == 0) {
        OLED_ON = 1; // Screen was off, set to On
        update_display();
    } else {

        switch(Screen_Num) {
            case 0: {// We're in Main Screen
                // do nothing, wrong button
                break;
            }
            case 1: {// Panic Alert option
                StartHaptic();
                Screen_Num = 71;  //Change to screen 71
                update_display();
                break;
            }
            case 2: {// Fall Alert option
                StartHaptic();
                Screen_Num = 3;  //Change to screen 3
                update_display();
                break;
            }
            case 3: {// Heart Rate Monitoring option
                StartHaptic();
                Screen_Num = 5;  //Change to screen 5, skip 4
                update_display();
                break;
            }
            case 4: {// Alert History option
                StartHaptic();
                Screen_Num = 5;  //Change to screen 5
                update_display();
                break;
            }
            case 5: {// About HexiHeart option
                StartHaptic();
                Screen_Num = 26;  //Change to screen 1
#ifdef Debug    // in debug show debug/diagnostic screens                         
                Screen_Num = 20;  //Change to screen 20
#endif
                update_display();
                break;
            }
            case 6: {// Panic Alert
                // do nothing, wrong button
                break;
            }
            case 7: {// Heart Rate Zone
                StartHaptic();
                maxDeinit();              
                break;
            }
            case 8: {// Alert History
                StartHaptic();
                //decriment alert index
                break;
            }
            case 9: {// HexiHeart About info1
                    StartHaptic();
                    Screen_Num = 10;  //Change to screen 10
                    update_display();
                    break;
                }
            case 10: {// HexiHeart About info2
                    StartHaptic();
                    Screen_Num = 11;  //Change to screen 11
                    update_display();
                    break;
                }
            case 11: {// HexiHeart About info3
                    StartHaptic();
                    Screen_Num = 9;  //Change to screen 9
                    update_display();
                    break;
                }            
            case 20: {// Diagnostic/Debug Screens
                StartHaptic();
                Screen_Num = 26;  //Change to screen 1
                update_display();
                break;
            }
            case 21: {// Fall Diagnostic
                StartHaptic();
                Screen_Num = 22;  //Change to screen 22
                update_display();
                break;
            }
            case 22: {// Fall Debug
                StartHaptic();
                Screen_Num = 25;  //Change to screen 23
                update_display();
                break;
            }
            case 23: {// Heart Rate Diagnostic - not used
                StartHaptic();
                Screen_Num = 24;  //Change to screen 24
                update_display();
                break;
            }
            case 24: {// Heart Rate Debug - not used
                StartHaptic();
                Screen_Num = 25;  //Change to screen 25
                update_display();
                break;
            }
            case 25: {// Heat Index Diagnostic
                StartHaptic();
                Screen_Num = 49;  //Change to screen 49
                update_display();
                break;
            }
            case 26: {//Heart Rate Configs
                StartHaptic();
                Screen_Num = 1;
                update_display();
                break;
            }
            case 27: { //Decrement Age
                Decrement_Age();
                Set_Zone_Boundaries();
                update_display();
                break;

            }
            case 28: { //Changing Heart Rate Vibration Preference
                /*
                    StartHaptic();
                    if(HR_Vibration == 1) {
                        HR_Vibration = 3;
                    } else {
                        HR_Vibration -= 1;
                    }
                */
                Decrement_HR_Vibr_Pref();
                update_display();
                break;
            }
            case 30: {//Change Target Heart Rate Zone Preference
                Decrement_Target_Zone();
                update_display();
                break;
            }
            case 31: { //Manually decrement heart rate by 1
                if(maxim == 0)
                {
                    Decrement_Heart_Rate();
                   // Determine_Current_Zone();
                   update_display();
                }
                
                break;
            }
            case 32: {//End HR led used for manual demonstration
                 hr_led.detach();
                 Heart_Rate_Mode = 0;
                 RED_Led = LED_OFF; 
                 GRN_Led = LED_OFF;
                 BLU_Led = LED_OFF;
                break;
            }
            case 33: {//End HR Simulation early
                StartHaptic();
                if(maxim == 0)
                {
                    Heart_Rate_Mode = 0;
                    hr_simulation.detach();
                    simulation_stage = 0;
                    hr_led.detach();
                    RED_Led = LED_OFF; 
                    GRN_Led = LED_OFF;
                    BLU_Led = LED_OFF;
                }
                update_display();
                break;
            }
            case 41: {//Fall mode 0,1,2,3,4,5
            // 0=nothing, 1=fall_only, 2=impact only, 3=motion_only, 4=all, 5=main sequence
                StartHaptic();
                Fall_Alert_Mode--;
                if(Fall_Alert_Mode > 5){// should be 0xff if decr from zero
                Fall_Alert_Mode = 5;
                }  //endif
                update_display();
                __disable_irq();    // Disable all Interrupts
                fall_config(10);  // reset accel sensor
                //gyro_sensor_config(10);  // reset gyro sensor  
                wait(0.1);
                //gyro_sensor_config(Fall_Alert_Mode);  // leave gyro sensor active
                fall_config(Fall_Alert_Mode);
                wait(0.1);
                __enable_irq();     // Enable all Interrupts
                wait(0.2);
                update_display();
                break;
            }
            case 42: {// F-Th adj
                StartHaptic();
                Fall_Thresh = Fall_Thresh - 0.05f;
                if(Fall_Thresh < 0.1f){
                Fall_Thresh = 0.1;
                }//endif
                update_display();
                break;
            }
            case 43: {// I-Th adj
                StartHaptic();
                Impact_Thresh = Impact_Thresh - 0.1f;
                if(Impact_Thresh < 0.9f){
                Impact_Thresh = 0.9;
                }//endif
                update_display();
                break;
            }
            case 44: {// M-Th adj
                StartHaptic();
                Movement_Thresh = Movement_Thresh - 5.0f;
                if(Movement_Thresh < 5.0f){
                Movement_Thresh = 5.0;
                }//endif
                update_display();
                break;
            }
            case 45: {// Min_Movement_Time adj
                StartHaptic();
                Min_Movement_Time = Min_Movement_Time - 0.1f;
                if(Min_Movement_Time < 0.5f){
                Min_Movement_Time = 0.5;
                }//endif
                update_display();
                break;
            }
            case 46: {// Min_Movement_duration adj
                StartHaptic();
                Min_Movement_duration = Min_Movement_duration - 5.0f;
                if(Min_Movement_duration < 5.0f){
                Min_Movement_duration = 5.0;
                }//endif
                update_display();
                break;
            }
            case 49: {// WDT diagnostic test screen
                StartHaptic();
                Screen_Num = 21;  //Change to screen 21
                update_display();
                break;
            }
            case 71: {// BLE
                StartHaptic();
                Screen_Num = 2; //Change to screen 2
                update_display();
                break;
            }
            case 72: {// BlueTooth on/off
                // do nothing, wrong button or change to another screen number if you're making more BLE type screens
                break;
            }
            
            default: {
                break;
            }
        }//end case switch
    }//end if
}// end ButtonDown()


/*****************************************************************************
Name: ButtonRight()
Purpose: Routine called when MK46 recieves a ButtonRight interrupt from KW40
Inputs: Uses global Screen_Num value and other status varibles
Returns: None
******************************************************************************/
void ButtonRight(void)
{
    Reset_Count = 0;
    Screen_Timer.attach(&timout_timer,(SCRN_TIME));//Is this sufficient to reset/restart ticker timer for OLED?
    oled.DimScreenOFF();
    if (OLED_ON == 0) {
        OLED_ON = 1; // Screen was off, set to On
        update_display();
    } else {
        switch(Screen_Num) {
            case 0: {// We're in Main Screen
                StartHaptic();
                Screen_Num = 1;  //Change to screen 1
                update_display();
                break;
            }
            case 1: {// Panic Alert option
                StartHaptic();
                Screen_Num = 6;  //Change to screen 6
                update_display();
                break;
            }
            case 2: {// Fall Alert option
                StartHaptic();
                if(Fall_Alert == 1){
                    Fall_Alert = 0;
                    fall_config(0); // configure sensors for standby
                    }
                else{     
                    //Accel_INT1.fall(&fall_detect); // Accel sensor's int#1 calls interupt routine
                    Fall_Alert = 1;
                    fall_config(Fall_Alert_Mode); // configure sensors for current fall mode
                    }
                update_display();
                break;
            }
            case 3: {// Heart Rate Monitoring option
                StartHaptic();
                Screen_Num = 7;  //Change to screen 7
                update_display();
                break;
            }
            case 4: {// Alert History option
                StartHaptic();
                Screen_Num = 8;  //Change to screen 8
                update_display();
                break;
            }
            case 5: {// About HexiHeart option
                StartHaptic();
                Screen_Num = 9;  //Change to screen 9
                update_display();
                break;
            }

            case 6: {// Panic Alert
                // do nothing, wrong button
                break;
            }
            case 7: {// Heart Rate Zone
                StartHaptic();
                Screen_Num = 31;
                update_display();
                break;
            }
            case 20: {// Diagnostic/Debug Screens
                StartHaptic();
                Screen_Num = 21;  //Change to screen 21
                update_display();
                break;
            }
            case 22: {// Fall Debug
                StartHaptic();
                Screen_Num = 41;  //Change to screen 41
                update_display();
                break;
            }
            case 26: {//Change to Heart Rate Config Screen
                StartHaptic();
                Screen_Num = 27;
                update_display();
                break;
            }
            case 27: {//Change to Heart Rate Vibration Preferences
                StartHaptic();
                Screen_Num = 28;
                update_display();
                break;
            }
            case 28: {//Change to Heart Rate Zone Boundary Info
                StartHaptic();
                Screen_Num = 29;
                update_display();
                break;
            }
            case 29: {//Change Target Heart Rate Zone Preference
                StartHaptic();
                Screen_Num = 30;
                update_display();
                break;
            }
            case 30: {//Change to Heart Rate Config Screen
                StartHaptic();
                Screen_Num = 27;
                update_display();
                break;
            }
            case 31: {
                StartHaptic();
                Screen_Num = 32;
                update_display();
                break;
            }
            case 32: {
                StartHaptic();
                Screen_Num = 33;
                update_display();
                break;
            }
            case 33: {
                StartHaptic();
                Screen_Num = 7;
                update_display();
                break;
            } 
            case 41: {// Fall-Mode adj
                StartHaptic();
                Screen_Num = 42;  //Change to screen 42
                update_display();
                break;
            }       
            case 42: {// F-Th adj
                StartHaptic();
                Screen_Num = 43;  //Change to screen 43
                update_display();
                break;
            }
            case 43: {// I-Th adj
                StartHaptic();
                Screen_Num = 44;  //Change to screen 44
                update_display();
                break;
            }
            case 44: {// M-Th adj
                StartHaptic();
                Screen_Num = 45;  //Change to screen 44
                update_display();
                break;
            }
            case 45: {// Min_time adj
                StartHaptic();
                Screen_Num = 46;  //Change to screen 44
                update_display();
                break;
            }
            case 46: {// Time_dur adj
                    //do nothing for now
                break;
            }         
            case 47: {// Fall-Detected screen "are you ok?"
                StartHaptic();
                Send_Alert(20); // send/store alert type 20
                Screen_Num = 48;  //Change to screen 48 (send alert screen)
                update_display();
                break;
            }     
            case 49: {// start WDT test
                StartHaptic();
                Screen_Num = 50;  //Change to screen 50
                update_display();
                break;
            }     
             case 71: {// BLE
                StartHaptic();
                Screen_Num = 72;  //Change to screen 72
                update_display();
                break;
            }
             case 72: {// BlueTooth on/off
                StartHaptic();
                BLE_On = !BLE_On;
                kw40z_device.ToggleAdvertisementMode();
                update_display();
                break;
            }           
            
            default: {
                break;
            }
        }//end case switch
    }//end if
}//end ButtonRight


/*****************************************************************************
Name: ButtonLeft()
Purpose: Routine called when MK46 recieves a ButtonLeft interrupt from KW40
Inputs: Uses global Screen_Num value and other status varibles
Returns: None
******************************************************************************/
void ButtonLeft(void)
{
    Screen_Timer.attach(&timout_timer,(SCRN_TIME));//Is this sufficient to reset/restart ticker timer for OLED?
    oled.DimScreenOFF();
    if (OLED_ON == 0) {
        OLED_ON = 1; // Screen was off, set to On
        update_display();
    } else {
        switch(Screen_Num) {
            case 0: {// We're in Main Screen
                Reset_Count++;
                if(Reset_Count >= 8){
                    __disable_irq();    // Disable all Interrupts
                    oled_text_properties_t textProperties = {0};  // Need these to change font color
                    oled.GetTextProperties(&textProperties);      // Need these to change font color
                    textProperties.font = OpenSans_12x18_Regular;  //  Max Width of Character  = 12px, Max Height of Character = 18px 
                    textProperties.fontColor = COLOR_WHITE;
                    oled.SetTextProperties(&textProperties); 
                    wait_ms(100);
                    oled.FillScreen(COLOR_BLACK); // Clear screen
                    wait_ms(100);
                    oled.Label((uint8_t *)"Hidden",20,20); // Display "Back" at x,y
                    oled.Label((uint8_t *)" Reset ",20,40); // Display "Back" at x,y
                    oled.Label((uint8_t *)"Feature",20,60); // Display "Back" at x,y
                    wait_ms(500);// display for 100ms
                    NVIC_SystemReset(); // software reset
                    wait(3.0);// should never get here
                    }//end if
                break;
            }
            case 1: {// Panic Alert option
                StartHaptic();
                Screen_Num = 0;  //Change to screen 0
                update_display();
                break;
            }
            case 2: {// Fall Alert option
                StartHaptic();
                Screen_Num = 0;  //Change to screen 0
                update_display();
                break;
            }
            case 3: {// Heart Rate Monitoring option
                StartHaptic();
                Screen_Num = 0;  //Change to screen 0
                update_display();
                break;
            }
            case 4: {// Alert History option
                StartHaptic();
                Screen_Num = 0;  //Change to screen 0
                update_display();
                break;
            }
            case 5: {// About HexiHeart option
                StartHaptic();
                Screen_Num = 0;  //Change to screen 0
                update_display();
                break;
            }
            case 6: {// Panic Alert
                StartHaptic();
                Screen_Num = 1;  //Change to screen 1
                update_display();
                break;
            }
            case 7: {// Heart Rate Zone
                StartHaptic();
                Screen_Num = 3;  //Change to screen 3
                update_display();
                break;
            }
            case 8: {// Alert History
                StartHaptic();
                Screen_Num = 4;  //Change to screen 4
                update_display();
                break;
            }
            case 9: {// About HexiHeart info1
                    StartHaptic();
                    Screen_Num = 5;  //Change to screen 5
                    update_display();
                    break;
                }
            case 10: {// HexiHeart About info2
                    StartHaptic();
                    Screen_Num = 5;  //Change to screen 5
                    update_display();
                    break;
                }
            case 11: {// HexiHeart About info3
                    StartHaptic();
                    Screen_Num = 5;  //Change to screen 5
                    update_display();
                    break;
                }            
            case 20: {// Diagnostic/Debug Screens
                StartHaptic();
                Screen_Num = 0;  //Change to screen 0
                update_display();
                break;
            }
            case 21: {// Fall Diagnostic
                StartHaptic();
                Screen_Num = 20;  //Change to screen 20
                update_display();
                break;
            }
            case 22: {// Fall Debug
                StartHaptic();
                Screen_Num = 20;  //Change to screen 20
                update_display();
                break;
            }
            case 23: {// Heart Rate Diagnostic
                StartHaptic();
                Screen_Num = 20;  //Change to screen 20
                update_display();
                break;
            }
            case 24: {// Heart Rate Debug
                StartHaptic();
                Screen_Num = 20;  //Change to screen 20
                update_display();
                break;
            }
            case 25: {// Heat Index Diagnostic
                StartHaptic();
                Screen_Num = 20;  //Change to screen 20
                update_display();
                break;
            }
            case 26: {//Heart Rate Config Option
                StartHaptic();
                Screen_Num = 0;
                update_display();
                break;
            }
            case 27: {//Enter Age
                StartHaptic();
                Screen_Num = 26;
                update_display();
                break;
            }
            case 28: {//Heart Rate Vibration Preference Screen
                StartHaptic();
                Screen_Num = 27;
                update_display();
                break;
            }
            case 29: {//Heart Rate Zone Boundary Info
                StartHaptic();
                Screen_Num = 28;
                update_display();
                break;
            }
            case 30: {//Change Target Heart Rate Zone Preference
                StartHaptic();
                Screen_Num = 29;
                update_display();
                break;
            }
            case 31: {
                StartHaptic();
                Screen_Num = 7;
                update_display();
                break;
            }
            case 32: {
                StartHaptic();
                Screen_Num = 31;
                update_display();
                break;
            }
            case 33: {
                StartHaptic();
                Screen_Num = 32;
                update_display();
                break;
            }
            case 41: {// Fall mode screen
                StartHaptic();
                Screen_Num = 22;
                update_display();
                break;
            }    
            case 42: {// F-Th adj
                StartHaptic();
                Screen_Num = 41;  //Change to screen 41
                update_display();
                break;
            }
            case 43: {// I-Th adj
                StartHaptic();
                Screen_Num = 42;  //Change to screen 42
                update_display();
                break;
            }
            case 44: {// M-Th adj
                StartHaptic();
                Screen_Num = 43;  //Change to screen 43
                update_display();
                break;
            }    
            case 45: {// M-time adj
                StartHaptic();
                Screen_Num = 44;  //Change to screen 44
                update_display();
                break;
            }   
            case 46: {// M-dur adj
                StartHaptic();
                Screen_Num = 45;  //Change to screen 45
                update_display();
                break;
            }         
            case 47: {// Fall-detected screen
                StartHaptic();
                Led_clk1 = 0;  // Turn off LED1, on docking station
                Led_clk2 = 0;  // Turn off LED2, on docking station
                Screen_Num = 0;  //Change to screen 0
                update_display();
                break;
            }      
            case 48: {// Sending Fall-Alert screen
                StartHaptic();
                Led_clk1 = 0;  // Turn off LED1, on docking station
                Led_clk2 = 0;  // Turn off LED2, on docking station
                // stop/dismiss alert
                Send_Alert(0);
                Screen_Num = 0;  //Change to screen 0
                update_display();
                break;
            }       
            case 51: {// Sending Panic Alert
                StartHaptic();
                Screen_Num = 6;  //Change to screen 6
                Panic_Alert = 0;
                Send_Alert(0); // send/store alert type zero
                update_display();
                break;
            }              
             case 71: {// BLE
                StartHaptic();
                Screen_Num = 0;  //Change to screen 0
                update_display();
                break;
            }

            case 72: {// BlueTooth on/off
                StartHaptic();
                Screen_Num = 71;  //Change to screen 71
                update_display();
                break;
            }
           
            default: {
                break;
            }
        }// end case switch
    }// end if
}// end ButtonLeft

/*****************************************************************************
Name: ButtonSlide()
Purpose: Routine called when MK46 recieves a ButtonSlide interrupt from KW40, which
we never get.
Inputs: None
Returns: None
******************************************************************************/
void ButtonSlide(void)  // What is this Slide button???
{
    Screen_Timer.attach(&timout_timer,(SCRN_TIME));//Is this sufficient to reset/restart ticker timer for OLED?
    oled.DimScreenOFF();
    if (OLED_ON == 0) {
        OLED_ON = 1; // Screen was off, set to On
    }
    StartHaptic();
    oled.FillScreen(COLOR_BLACK); // Clear screen
    strcpy((char *) text_1,"Slide Button");
    oled.Label((uint8_t *)text_1,0,40);
}// end ButtonSlide

int main()
{
//__STATIC_INLINE void __set_PMCTRL(0b01000000);// set K64 SMC_PMCTRL register to VLPR (Very low power run) mode
 //   SMC->PMCTRL = (uint8_t)((SYSTEM_SMC_PMCTRL_VALUE) & (SMC_PMCTRL_RUNM_MASK)); // Enable VLPR mode    
 //   SMC->PMCTRL = (0b01000000);// set K64 SMC_PMCTRL register to VLPR (Very low power run) mode << did nothing for battery time
    
//set_time(1256729737);  // Set RTC time to Wed, 28 Oct 2009 11:35:37
//set_time((Year-1970)*365*24*3600+(days of this year)*24*3600+(hr)*3600 + (min)*60 + (Sec) - fudge factor);  // Set RTC time to Mon, 19 Feb 2018 10:00
//set_time(48*365*24*3600 + 61*24*3600 + 10*3600-4);  // Set RTC time to Mon, 19 Feb 2018 10:00
//set_time((2018-1970)*365.25f*24*3600 + (31+28+1-1)*24*3600 + (16)*3600 + (5)*60+ (1) + 38);  // Set RTC time to 3/01/2018 16:04:20
//set_time((2018-1970)*365.25f*24*3600 + (31+28+26-1)*24*3600 + (10)*3600 + (0)*60+ (0) + 28);  // Set RTC time to 3/26/2018 9:59:31
 //   set_time((2018-1970)*365.25f*24*3600 + (31+28+31+18-1)*24*3600 + (10)*3600 + (0)*60+ (0) + 29);  // Set RTC time to 4/18/2018 9:59:31
    set_time((2018-1970)*365.25f*24*3600 + (31+28+31+30+10-1)*24*3600 + (13)*3600 + (15)*60+ (0) + 29);  // Set RTC time to 5/10/2018 9:59:31
    RED_Led = LED_OFF;
    GRN_Led = LED_OFF;
    BLU_Led = LED_OFF;
    Led_clk1 = 0;       // LEDs on docking station default to off, need to turn on with a 1
    Led_clk2 = 0;       // LEDs on docking station default to off, need to turn on with a 1
    Led_clk3 = 0;       // LEDs on docking station default to off, need to turn on with a 1
    
// *****************  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
    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
//    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?
        
    oled.FillScreen(COLOR_BLACK); // Clear screen 
    fall_config(10);            // SW reset accell and gyro sensor 
 //   gyro_sensor_config(10);     // SW reset gyro sensor 
    press_config(0);            // put pressure sensor into 2uA standby, we're not using it
 //   MAX30101_test_config(10);   // SW reset HR sensor << power is off
    oled.FillScreen(COLOR_BLACK); // Clear screen 
    
// *****************  Local variables  ***********************
//   float accel_data[3]; float accel_rms=0.0;
    int i;
 
// **************  configure sensor modules  ******************

    //accel.accel_config();   // original configure accel sensor  
    fall_config(Fall_Alert_Mode); // configure sensor (I2C1) for current fall mode
    //Fall_Alert_Mode: 0=none, 1=fall_only, 2=impact only, 3=motion_only, 4=all three, 5=full sequencial
    //gyro.gyro_config();    // original configure gyro sensor
    //gyro_sensor_config(Fall_Alert_Mode);  // configure gyro sensor (I2C1) 0=standby, 1=active, 2=interupt set up (now setup in fall_config())
    //mag.mag_config();     // we don't need mag 
    //light_config(0);      // config TSL2561 ambient light sensor (I2C0) for lowest power - cycling PowerEn should have reset it to state
    //Configure HTU21(Temp/Hum)? No need, it seems to draw 0.02uA when not being activly read over data bus

//   need to configure MAX30101 at some point
   // MAX30101_test_config(0);


// ***** Register callbacks/interupts to application functions *********
    kw40z_device.attach_buttonUp(&ButtonUp);
    kw40z_device.attach_buttonDown(&ButtonDown);
    kw40z_device.attach_buttonLeft(&ButtonLeft);
    kw40z_device.attach_buttonRight(&ButtonRight);
 //   kw40z_device.attach_buttonSlide(&ButtonSlide);
 //   kw40z_device.attach_alert(&TimeSet);
     //kw40z_device.attach_alertIn(&TimeSet);
     kw40z_device.attach_passkey(&PassKey);

// ***** attaching interupts to functions *********
    //Accel_INT1.fall(&fall_detect); // Accel sensor's int#1 (PTC1) calls interupt routine (now setup in fall_config())
    //Accel_INT2.fall(&impact_detect); //Accel sensor's int#2 (PTD13) calls interupt routine(now setup in fall_config())
    //Gyro_INT1.fall(&motion_detect); // Gyro sensor's int#1 (PTD1) calls interupt routine (now setup in fall_config())
    //Gyro_INT2.fall(&motion_detect); // Gyro sensor's int#2 (PTC18) calls interupt routine (not used)
    //HR_INT1.fall(&some_HR_read_function_yet_to_be_named); // MAX30101 - Heart rate sensor's interupt (PTB18)


    
// **** Get OLED Class Default Text Properties ****************
    oled_text_properties_t textProperties = {0};
    oled.GetTextProperties(&textProperties);

// *********Set text color and screen alignment  **************
    //textProperties.font = OpenSans_12x18_Regular;  //  Max Width of Character  = 12px, Max Height of Character = 18px 
    //textProperties.font = OpenSans_10x15_Regular;  //  <-This is default Font, Max Width of Character  = 10px, Max Height of Character = 15px 
    textProperties.fontColor = COLOR_WHITE;
    textProperties.alignParam = OLED_TEXT_ALIGN_LEFT;
    oled.SetTextProperties(&textProperties);

// **************  Display spash screen  **********************
/*
    oled.FillScreen(COLOR_BLACK); // Clear screen
    oled.DrawImage(Hexi_Heart_,0,0);  // my Hexi_Heart image is offset for some reason
    wait(0.5);  // wait 0.5 seconds
*/
    oled.FillScreen(COLOR_BLACK); // Clear screen
    
    textProperties.font = OpenSans_12x18_Regular;  //  Max Width of Character  = 12px, Max Height of Character = 18px 
    oled.SetTextProperties(&textProperties); 
    oled.Label((uint8_t *)"Hexi",18,5); // Display white "Hexi" at x,y
    textProperties.fontColor = COLOR_RED;
    oled.SetTextProperties(&textProperties);
    oled.Label((uint8_t *)"Heart",47,5); // Display red "Heart" at x,y
    textProperties.font = OpenSans_10x15_Regular;  //  Max Width of Character  = 10px, Max Height of Character = 15px 
    oled.SetTextProperties(&textProperties);

    strcpy((char *) text_1,"This is a");
    oled.Label((uint8_t *)text_1,19,25);  // text_1 at x,y
    strcpy((char *) text_1,"Demo Proj");
    oled.Label((uint8_t *)text_1,15,40);  // text_1 at x,y
    strcpy((char *) text_1,"SW_Ver:");
    oled.Label((uint8_t *)text_1,10,70);  // text_1 at x,y
    textProperties.fontColor = COLOR_MAGENTA;
    oled.SetTextProperties(&textProperties);
    sprintf(text_1,"%2.2f  ",SW_Ver);
    oled.Label((uint8_t *)text_1,60,70);// text_1 at x,y
    StartHaptic(); 
    
    textProperties.fontColor = COLOR_WHITE;
    oled.SetTextProperties(&textProperties);
    wait(2);  // wait 3 seconds
    
   // txThread.start(txTask); /*Start transmitting Sensor Tag Data */
    oled.DimScreenOFF();
    update_display(); // Displays current screen (screen 0)
    UpDate_Ave(); // Update slow changing measurements once every 30 seconds
    Screen_Timer.attach(&timout_timer,(SCRN_TIME)); //start ticker timer for turning off LCD
    WDT_Timer.attach(&WDT_Timeout,(WDT_TIME));      //attach/start WDT
//  ******************* Main Loop *************************
    while (true) {
            i=0;
    while (i<20)// used for "Heart beat flash and updated any displayed data)
    {
    Thread::wait(500);          // wait 0.5 sec each loop
    CLRWDT();

    if(OLED_PWR==1){
    update_display_date();     // refresh display data twice a second w/o updating entire display 
        }// end if
          
    i++;
    }// end 10 second while(i<20) loop 
    if(maxim==0){// don't use red LED while heart rate zone routine is active
    RED_Led = LED_ON;    // Used only for diagnostic of wait command
    }
    Led_clk3 = 1;         // Used only for diagnostic of wait command
    wait(0.01);          // BLIP led 1/10 sec each loop
    if(maxim==0){// don't use red LED while heart rate zone routine is active
    RED_Led = LED_OFF;    // Used only for diagnostic of wait command
    }
    Led_clk3 = 0; 
    
    Thread::wait(490);    // keep up the pace, at 0.5 sec (0.01s+0.49s) update date 
    
    CLRWDT();
    UpDate_Ave(); // Update slow changing measurements once every 10.5 seconds 
    } // end of while(true)

}
//  ************** end of main()

void update_display(void)
{
    OLED_PWR = 1;  // make sure OLED power supply is on
    oled_text_properties_t textProperties = {0};  // Need these to change font color
    oled.GetTextProperties(&textProperties);      // Need these to change font color
    __disable_irq();    // Disable all Interrupts
    switch(Screen_Num) {
        case 0: {// Main Screen
            HexiwearBattery battery;
            battery.sensorOn();  
            oled.FillScreen(COLOR_BLACK); // Clear screen
            
            if (battery.isBatteryCharging()) {
            textProperties.fontColor = COLOR_GREEN;
            oled.SetTextProperties(&textProperties);  
  //          sprintf(text_1, "%s", "chrg");           
            sprintf(text_1, "%i%%+", batt_per_level);
            Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED while fully charged
            oled.DimScreenOFF();
            } else {
            sprintf(text_1, "%i%%", batt_per_level);
            }
            oled.TextBox((uint8_t *)text_1,60,0,35,15); //show level value of battery in a 35px by 15px text box at x=60, y=0
        
        textProperties.fontColor = COLOR_WHITE;
        oled.SetTextProperties(&textProperties);
            
            oled.Label((uint8_t *)"Batt",35,0); // Display "Batt" at x,y
//            oled.Label((uint8_t *)"Date",35,20); // Display "Date" at x,y
//           oled.Label((uint8_t *)"Time",35,40); // Display "Time" at x,y
//            oled.Label((uint8_t *)"H.I.",10,80); // Display "H.I." at x,y

            oled.Label((uint8_t *)"BT",40,80);  //Display "BT" at x,y
            oled.Label((uint8_t *)"Menu",60,80);  //Display "Menu" at x,y
            
            textProperties.fontColor = COLOR_GRAY;
            if(BLE_On == 1){
               textProperties.fontColor = COLOR_BLUE; // If BLE on make "BT" blue!
               }
            oled.SetTextProperties(&textProperties);
            
            oled.Label((uint8_t *)"BT",40,80);  //Display "BT" at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);  
            
            textProperties.fontColor = COLOR_GRAY;
            if(Fall_Alert == 1){
                textProperties.fontColor = COLOR_GREEN; // is Fall protection on?
            }
            if(Fall_Alert == 1 && Led_clk1 == 1){
                textProperties.fontColor = COLOR_YELLOW; // is Fall detected? 
            }       
            if(Fall_Alert == 1 && Led_clk1 == 1 && Led_clk2 == 1){
                textProperties.fontColor = COLOR_RED; // is impact detected? 
            }       
            oled.SetTextProperties(&textProperties); 
            oled.Label((uint8_t *)"AFP",3,0);  //Display "FAP" at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
           
// added real time and date information            
            char buffer[32];
            time_t seconds = time(NULL);
            strftime(buffer,32, "%a,%d %m %Y.%H:%M:%S\r", localtime(&seconds)); //format local time and store in buffer
            
            textProperties.font = OpenSans_12x18_Regular;  //  Max Width of Character  = 12px, Max Height of Character = 18px 
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);        
            
            sprintf(text_1,"%c%c/%c%c/%c%c%c%c ",buffer[7],buffer[8],buffer[4],buffer[5],buffer[10],buffer[11],buffer[12],buffer[13]);
            oled.Label((uint8_t *)text_1,15,25);// Date at x,y
            sprintf(text_1,"%c%c:%c%c:%c%c ",buffer[15],buffer[16],buffer[18],buffer[19],buffer[21],buffer[22]);
            oled.Label((uint8_t *)text_1,25,40);// Time at x,y
            
            textProperties.font = OpenSans_10x15_Regular;  //  Max Width of Character  = 10px, Max Height of Character = 15px 
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
                      
            Heat_Index_Calculation();
            sprintf(text,"%i",heat_index);
            oled.Label((uint8_t *)text,3,80);// HI at x,y
            //oled.TextBox((uint8_t *)text,3,80); //show HI in a 15px by 15px text box at x=3, y=80
            strcpy((char *) text,"F");
            oled.Label((uint8_t *)text,25,80); // was "dF" at 18,80
            
            if(Heart_Rate_Mode == 1) {
                sprintf(text,"%i",Heart_Rate);
                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 *)text,35,60); 
                textProperties.fontColor = COLOR_WHITE;
                oled.SetTextProperties(&textProperties);
            }
            break;
        }
        case 1: {// Panic Alert option
            oled.FillScreen(COLOR_BLACK); // Clear screen
            oled.Label((uint8_t *)"Panic Alert",18,5); // Display 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 *)"Back",10,80); // Display "Back" at x,y
            oled.Label((uint8_t *)"Enter",60,80);  //Display "enter" at x,y
            break;
        }
        case 2: {// Fall Alert option
            oled.FillScreen(COLOR_BLACK); // Clear screen
            oled.Label((uint8_t *)"Fall Alert",20,5); // Display at x,y
            oled.Label((uint8_t *)"Protection",15,20);  
            oled.Label((uint8_t *)"AFP",15,40); 
            if (Fall_Alert == 1){  
           
            textProperties.fontColor = COLOR_GREEN; 
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)" On ",42,40);   
            }
            else {               
            textProperties.fontColor = COLOR_GRAY;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)" Off ",40,40);  
        
                } 
            textProperties.fontColor = COLOR_WHITE; 
            oled.SetTextProperties(&textProperties);
            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 *)"Toggle",59,80);  //Display "Toggle" at x,y
            break;
        }
        case 3: {// Heart Rate Monitoring option
            oled.FillScreen(COLOR_BLACK); // Clear screen
            oled.Label((uint8_t *)"Heart Rate",18,5); // Display 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 *)"Back",10,80); // Display "Back" at x,y
            oled.Label((uint8_t *)"Enter",60,80);  //Display at x,y
            break;
        }
        case 4: {// Alert History option
            oled.FillScreen(COLOR_BLACK); // Clear screen
            oled.Label((uint8_t *)"Alert History",10,5); // Display 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 *)"Back",10,80); // Display "Back" at x,y
            oled.Label((uint8_t *)"Enter",60,80);  //Display at x,y
            break;
        }
        case 5: {// About HexiHeart Screen

            oled.FillScreen(COLOR_BLACK); // Clear screen
            oled.Label((uint8_t *)"Hexi",20,20); // Display white "Hexi" at x,y
            textProperties.fontColor = COLOR_RED;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"Heart",45,20); // Display red "Heart" at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            strcpy((char *) text_1,"About");
            oled.Label((uint8_t *)text_1,30,5);  // text_1 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 *)"Back",10,80); // Display "Back" at x,y
            oled.Label((uint8_t *)"Enter",60,80);  //Display at x,y
            break;
        }

        case 6: {// Panic Alert
            oled.FillScreen(COLOR_BLACK); // Clear screen
            oled.Label((uint8_t *)"Send ",20,10); // Display at x,y
            oled.Label((uint8_t *)"Panic Alert",15,40); // Display at x,y
            oled.Label((uint8_t *)"-->",80,15); // "*" at x,y
            oled.Label((uint8_t *)"Back",10,80); // Display "Back" at x,y
            break;
        }
         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:",10,25); // Display at x,y
            sprintf(display_buff, "%u", Heart_Rate);
            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,43,25); // Display at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            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
            oled.Label((uint8_t *)display_buff,43,45); // Display at x,y
            textProperties.fontColor = COLOR_WHITE;
            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 *)"Menu",10,80); // Display "Back" at x,y
            oled.Label((uint8_t *)"Next",60,80); // Display "Next" at x,y
            break;
        }
        case 8: {// Alert History
            oled.FillScreen(COLOR_BLACK); // Clear screen
            oled.Label((uint8_t *)"Alert History",5,5); // Display at x,y
            oled.Label((uint8_t *)"Date - Time",20,40); // Display at x,y
            oled.Label((uint8_t *)"Alert Type:",20,60); // Display 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 *)"Back",10,80); // Display "Back" at x,y
            break;
        }
        
        case 9: {// About HexiHeart info1
                    oled.FillScreen(COLOR_BLACK); // Clear screen
                    oled.Label((uint8_t *)"Hexi",20,1); // Display white "Hexi" at x,y
                    textProperties.fontColor = COLOR_RED;
                    oled.SetTextProperties(&textProperties);  
                    oled.Label((uint8_t *)"Heart",45,0); // Display red "Heart" at x,y  
                    textProperties.fontColor = COLOR_WHITE;
                    oled.SetTextProperties(&textProperties);  
                    oled.Label((uint8_t *)"Senior Proj",5,15); //
                    oled.Label((uint8_t *)"Team Zeta E2.7",5,30); //
                    oled.Label((uint8_t *)"Texas State Univ",0,45); //        
                    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                  
                        break;
                }
                        
            case 10: {// About HexiHeart info2
                    oled.FillScreen(COLOR_BLACK); // Clear screen
                    oled.Label((uint8_t *)"Hexi",20,0); // Display white "Hexi" at x,y
                    textProperties.fontColor = COLOR_RED;
                    oled.SetTextProperties(&textProperties);  
                    oled.Label((uint8_t *)"Heart",45,0); // Display red "Heart" at x,y  
                    textProperties.fontColor = COLOR_WHITE;
                    oled.SetTextProperties(&textProperties);  
  //                  oled.Label((uint8_t *)"E2.7 Team Zeta",2,12); //
                    oled.Label((uint8_t *)"Alex Song",5,12); //
                    oled.Label((uint8_t *)"Jasmine ",5,24); // Jasmine Rounsaville is to long
                    oled.Label((uint8_t *)"Rounsaville",15,37); // Jasmine Rounsaville is to long
                    oled.Label((uint8_t *)"Issam Hichami",5,51); // 
                    oled.Label((uint8_t *)"Neil Baker",5,64); //           

                    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                  
                        break;
                }
                    
            case 11: {// About HexiHeart info3
                    oled.FillScreen(COLOR_BLACK); // Clear screen
                    
                    textProperties.font = OpenSans_12x18_Regular;  //  Max Width of Character  = 12px, Max Height of Character = 18px 
                    oled.SetTextProperties(&textProperties); 
                    oled.Label((uint8_t *)"Hexi",17,5); // Display white "Hexi" at x,y
                    textProperties.fontColor = COLOR_RED;
                    oled.SetTextProperties(&textProperties);
                    oled.Label((uint8_t *)"Heart",46,5); // Display red "Heart" at x,y
                    textProperties.font = OpenSans_10x15_Regular;  //  Max Width of Character  = 10px, Max Height of Character = 15px 
                    oled.SetTextProperties(&textProperties);

                    strcpy((char *) text_1,"This is a");
                    oled.Label((uint8_t *)text_1,19,25);  // text_1 at x,y
                    strcpy((char *) text_1,"Demo Proj");
                    oled.Label((uint8_t *)text_1,15,40);  // text_1 at x,y
                    strcpy((char *) text_1,"SW_Ver:");
                    oled.Label((uint8_t *)text_1,10,65);  // text_1 at x,y
                    textProperties.fontColor = COLOR_MAGENTA;
                    oled.SetTextProperties(&textProperties);
                    sprintf(text_1,"%2.2f  ",SW_Ver);
                    oled.Label((uint8_t *)text_1,60,65);// text_1 at x,y
                    textProperties.fontColor = COLOR_WHITE;
                    oled.SetTextProperties(&textProperties);                
                    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                  
                        break;
                }       
        
#ifdef Debug  // if this is non-production/debug version - do this
        case 20: {// Diagnostic/Debug Screens
            oled.FillScreen(COLOR_BLACK); // Clear screen
            textProperties.fontColor = COLOR_RED;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"Diagnostics",18,5); // Display at x,y
            oled.Label((uint8_t *)"Enter",60,80);  //Display at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            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

            break;
        }
        case 21: {// Fall Alert Diagnostic Screen
            if(Fall_Alert_Mode == 0){
                fall_config(11); // turn accel sensor to active to take reading
            }
            oled.FillScreen(COLOR_BLACK); // Clear screen
            textProperties.fontColor = COLOR_RED;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"Fall-Diag",25,5); // Display at x,y
       //     oled.Label((uint8_t *)"Diagnostic",25,5); // Display at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            gyro.acquire_gyro_data_dps(Gyro_Data);
            Gyro_Mag = (abs(Gyro_Data[0])+abs(Gyro_Data[1])+abs(Gyro_Data[2]));
            accel.acquire_accel_data_g(Accel_Data);
            if(Fall_Alert_Mode == 0){
                fall_config(12); // turn accel sensor to standby
            }
            Accel_Mag = 2*sqrt(((Accel_Data[0]*Accel_Data[0])+(Accel_Data[1]*Accel_Data[1])+(Accel_Data[2]*Accel_Data[2])));     
            sprintf(text_1," Accel:%2.2f g  ",Accel_Mag);
            oled.Label((uint8_t *)text_1,5,40);// text_1 at x,y
            sprintf(text_1," Gyro:%4.0f D/S  ",Gyro_Mag);
            oled.Label((uint8_t *)text_1,5,60);// text_1 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 *)"Back",10,80); // Display "Back" at x,y
            break;
        }
        case 22: {// Fall Alert Debug Screen
            oled.FillScreen(COLOR_BLACK); // Clear screen
            textProperties.fontColor = COLOR_RED;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"Fall Debug",15,5); // Display at x,y
            textProperties.fontColor = COLOR_GREEN;
            oled.SetTextProperties(&textProperties);
            sprintf(text_1," %i ",Fall_Alert_Mode);
            oled.Label((uint8_t *)text_1,36,20);// text_1 at x,y
            textProperties.fontColor = COLOR_GRAY;
            if(Fall_Alert_Mode == 1 || Fall_Alert_Mode >= 4){
                textProperties.fontColor = COLOR_GREEN;
            }
            oled.SetTextProperties(&textProperties);
            sprintf(text_1," %1.2f g  ",Fall_Thresh);
            oled.Label((uint8_t *)text_1,35,35);// text_1 at x,y
            textProperties.fontColor = COLOR_GRAY;
            if(Fall_Alert_Mode == 2 || Fall_Alert_Mode >= 4){
                textProperties.fontColor = COLOR_GREEN;
            }
            oled.SetTextProperties(&textProperties);
            sprintf(text_1," %2.2f g  ",Impact_Thresh);
            oled.Label((uint8_t *)text_1,35,50);// text_1 at x,y
            textProperties.fontColor = COLOR_GRAY;
            if(Fall_Alert_Mode == 3 || Fall_Alert_Mode >= 4){
                textProperties.fontColor = COLOR_GREEN;
            }
            oled.SetTextProperties(&textProperties);
            sprintf(text_1," %3.0f D/S  ",Movement_Thresh);
            oled.Label((uint8_t *)text_1,35,65);// text_1 at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"Mode:",5,20); // "*" at x,y
            oled.Label((uint8_t *)"F-Th:",5,35); // "*" at x,y
            oled.Label((uint8_t *)"I-Th:",5,50); // "*" at x,y
            oled.Label((uint8_t *)"M-Th:",5,65); // "*" 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 *)"Back",10,80); // Display "Back" at x,y
            oled.Label((uint8_t *)"Enter",60,80);  //Display at x,y
            break;
        }
        case 23: {// Heart Rate Diagnostic Screen
            oled.FillScreen(COLOR_BLACK); // Clear screen
            textProperties.fontColor = COLOR_RED;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"H.R. Diagnostic",5,5); // Display at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            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 *)" Enter ",59,80);  //Display at x,y
            break;
        }
        case 24: {// Heart Rate Debug Screen
            oled.FillScreen(COLOR_BLACK); // Clear screen
            textProperties.fontColor = COLOR_RED;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"H.R. Debug",10,5); // Display at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            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 *)" Enter ",59,80);  //Display at x,y
            break;
        }
        case 25: {// Heat Index Diagnostic Screen
            oled.FillScreen(COLOR_BLACK); // Clear screen
            textProperties.fontColor = COLOR_RED;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"H.I. Diagnostic",5,5); // Display at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            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 *)" Enter ",59,80);  //Display at x,y

            Heat_Index_Calculation();
            
            oled_text_properties_t textProperties = {0};
            oled.GetTextProperties(&textProperties);
      
            strcpy((char *) text,"Temp.");
            oled.Label((uint8_t *)text,5,40); 
            strcpy((char *) text,"Humidity");
            oled.Label((uint8_t *)text,5,57);   
            strcpy((char *) text,"H.I.");
            oled.Label((uint8_t *)text,5,23);        
      
        /* Set text properties to white and right aligned for the dynamic text */
            textProperties.fontColor = COLOR_GREEN;
            textProperties.alignParam = OLED_TEXT_ALIGN_RIGHT;
            oled.SetTextProperties(&textProperties);  
            
        /* Format the value */
            sprintf(text,"%i",sample_ftemp);
        
        /* Display temp reading in 15px by 15px textbox at(x=55, y=40) */
            oled.TextBox((uint8_t *)text,55,40,15,15); //Increase textbox for more digits
        
        /* Display Units */
            strcpy((char *) text,"dF");
            oled.Label((uint8_t *)text,71,40);       
      
        /* Format the value */
            sprintf(text,"%i",sample_humid);
        
        /* Display Hum reading in 15px by 15px textbox at(x=55, y=57) */
            oled.TextBox((uint8_t *)text,55,57,15,15); //Increase textbox for more digits
        
        /* Display Units */
            strcpy((char *) text,"%");
            oled.Label((uint8_t *)text,71,57); 
        
         /* Set text properties to white and right aligned for the dynamic text */
            textProperties.fontColor = COLOR_BLUE;
            textProperties.alignParam = OLED_TEXT_ALIGN_RIGHT;
            oled.SetTextProperties(&textProperties);        
      
        /* Format the value */
            sprintf(text,"%i",heat_index);
        
        /* Display HI reading in 15px by 15px textbox at(x=55, y=23) */
            oled.TextBox((uint8_t *)text,55,23,15,15); //Increase textbox for more digits
        
        /* Display Units */
            strcpy((char *) text,"dF");
            oled.Label((uint8_t *)text,71,23);
            
            break;
        }
        case 26: {//Heart Rate Config Option
            oled.FillScreen(COLOR_BLACK); // Clear screen
            oled.Label((uint8_t *)"HR Config",18,5); // Display 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 *)"Back",10,80); // Display "Back" at x,y
            oled.Label((uint8_t *)"Enter",60,80);  //Display "enter" at x,y
            break;
        }
        case 27: { //Enter Age Screen
            oled.FillScreen(COLOR_BLACK);
            oled.Label((uint8_t *)"Input Age", 10, 5);
            sprintf(display_buff, "%u", Age); //Convert int to char array for displaying user age
            oled.Label((uint8_t *)"Age:", 10, 30);
            oled.Label((uint8_t *)"+",85,15); // "*" at x,y
            oled.Label((uint8_t *)"-",85,60); // "*" at x,y
            oled.Label((uint8_t *)"Menu",10,80); // Display "Menu" 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);
            oled.Label((uint8_t *)"Max bpm:",10,50);
            textProperties.fontColor = COLOR_RED;
            oled.SetTextProperties(&textProperties); //implements the color change
            sprintf(display_buff, "%u", Max_Bpm); //Convert int to char array for displaying user max bpm
            oled.Label((uint8_t *)display_buff, 65, 50);
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            break;
        }
        case 28: {//Choose Heart Rate Vibration Option
            oled.FillScreen(COLOR_BLACK);
            oled.Label((uint8_t *)"Vibrate Pref", 10, 10);
            oled.Label((uint8_t *)"Option:", 10, 25);
            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
            sprintf(display_buff, "%u", HR_Vibration); //Convert int to char array for displaying user preference
            textProperties.fontColor = COLOR_GREEN; //Change font to green
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)display_buff,55,25); // Display at x,y
            if(HR_Vibration == 1) {
                textProperties.fontColor = COLOR_RED; //Change font to red
                oled.SetTextProperties(&textProperties); //Implement color change
                oled.Label((uint8_t *)"All On",10,45); // Display at x,y
            } else if(HR_Vibration == 2) {
                textProperties.fontColor = COLOR_RED; //Change font to red
                oled.SetTextProperties(&textProperties);//Implement color change
                oled.Label((uint8_t *)"Only Entering",10,38);// Display at x,y
                oled.Label((uint8_t *)"And Exiting",10,53);// Display at x,y
                oled.Label((uint8_t *)"Target Zone",10,68);// Display at x,y

            } else if(HR_Vibration == 3) {
                textProperties.fontColor = COLOR_RED; //Change font to red
                oled.SetTextProperties(&textProperties); //Implement color change
                oled.Label((uint8_t *)"All Off",10,45);// Display at x,y
            }
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            break;
        }
        case 29: { //Zone Boundary Info
            oled.FillScreen(COLOR_BLACK);
            textProperties.fontColor = COLOR_WHITE; //Change font to yellow
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)"HR Zone Info", 10, 5);// Display at x,y
            textProperties.fontColor = COLOR_YELLOW; //Change font to yellow
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)"Z1:", 10, 20);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone1[0]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 30, 20);// Display at x,y
            oled.Label((uint8_t *)"-", 52, 20);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone1[1]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 60, 20);// Display at x,y
            textProperties.fontColor = COLOR_BLUE; //Change font to blue
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)"Z2:", 10, 35);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone2[0]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 30, 35);// Display at x,y
            oled.Label((uint8_t *)"-", 52, 35);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone2[1]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 60, 35);// Display at x,y
            textProperties.fontColor = COLOR_GREEN; //Change font to green
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)"Z3:", 10, 50);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone3[0]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 30, 50);// Display at x,y
            oled.Label((uint8_t *)"-", 52, 50);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone3[1]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 60, 50);// Display at x,y
            textProperties.fontColor = COLOR_RED; //Change font to red
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)"Z4:", 10, 65);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone4[0]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 30, 65);// Display at x,y
            oled.Label((uint8_t *)"-", 52, 65);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone4[1]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 60, 65);// Display at x,y
            textProperties.fontColor = COLOR_WHITE; //Change font to white
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)"Back",10,80); // Display "Back" at x,y
            oled.Label((uint8_t *)"Next",60,80);  //Display "Next" at x,y
            break;
        }
        case 30: { //Enter Target Heart Rate Zone Preference
            oled.FillScreen(COLOR_BLACK);
            oled.Label((uint8_t *)"Zone Pref", 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 *)"Target:", 10, 25);// Display at x,y
            sprintf(display_buff, "%u", Target_Zone); // Convert int to char to display
            if(Target_Zone == 1) {
                textProperties.fontColor = COLOR_YELLOW; //Change font to yellow
                oled.SetTextProperties(&textProperties);//Implement color change
            } else if(Target_Zone == 2) {
                textProperties.fontColor = COLOR_BLUE; //Change font to blue
                oled.SetTextProperties(&textProperties);//Implement color change
            } else if(Target_Zone == 3) {
                textProperties.fontColor = COLOR_GREEN; //Change font to green
                oled.SetTextProperties(&textProperties);//Implement color change
            } else if(Target_Zone == 4) {
                textProperties.fontColor = COLOR_RED; //Change font to red
                oled.SetTextProperties(&textProperties);//Implement color change
            }
            oled.Label((uint8_t *)display_buff, 55, 25);// Display at x,y
            textProperties.fontColor = COLOR_WHITE; //Change font to white
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)"Bounds:", 10, 45);// Display at x,y
            if(Target_Zone == 1) {
                textProperties.fontColor = COLOR_YELLOW; //Change font to yellow
                oled.SetTextProperties(&textProperties);//Implement color change
                sprintf(display_buff, "%u", HR_Zone1[0]); // Convert int to char to display
                oled.Label((uint8_t *)display_buff, 10, 60);// Display at x,y
                oled.Label((uint8_t *)"-", 32, 60);// Display at x,y
                sprintf(display_buff, "%u", HR_Zone1[1]); // Convert int to char to display
                oled.Label((uint8_t *)display_buff, 40, 60);// Display at x,y
            } else if(Target_Zone == 2) {
                textProperties.fontColor = COLOR_BLUE; //Change font to blue
                oled.SetTextProperties(&textProperties);//Implement color change
                sprintf(display_buff, "%u", HR_Zone2[0]); // Convert int to char to display
                oled.Label((uint8_t *)display_buff, 10, 60);// Display at x,y
                oled.Label((uint8_t *)"-", 32, 60);// Display at x,y
                sprintf(display_buff, "%u", HR_Zone2[1]); // Convert int to char to display
                oled.Label((uint8_t *)display_buff, 40, 60);// Display at x,y
            } else if(Target_Zone == 3) {
                textProperties.fontColor = COLOR_GREEN; //Change font to green
                oled.SetTextProperties(&textProperties);//Implement color change
                sprintf(display_buff, "%u", HR_Zone3[0]); // Convert int to char to display
                oled.Label((uint8_t *)display_buff, 10, 60); // Display at x,y
                oled.Label((uint8_t *)"-", 32, 60); // Display at x,y
                sprintf(display_buff, "%u", HR_Zone3[1]); // Convert int to char to display
                oled.Label((uint8_t *)display_buff, 40, 60);// Display at x,y
            } else if(Target_Zone == 4) {
                textProperties.fontColor = COLOR_RED; //Change font to red
                oled.SetTextProperties(&textProperties);//Implement color change
                sprintf(display_buff, "%u", HR_Zone4[0]); // Convert int to char to display
                oled.Label((uint8_t *)display_buff, 10, 60); // Display at x,y
                oled.Label((uint8_t *)"-", 32, 60); // Display at x,y
                sprintf(display_buff, "%u", HR_Zone4[1]); // Convert int to char to display
                oled.Label((uint8_t *)display_buff, 40, 60); // Display at x,y
            }
            textProperties.fontColor = COLOR_WHITE; //Change font to white
            oled.SetTextProperties(&textProperties);//Implement color change
            break;
        }
        case 31: {
            oled.FillScreen(COLOR_BLACK);
            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 *)"HR:", 10, 25);
            sprintf(display_buff, "%u", Heart_Rate); // Convert int to char to display
            textProperties.fontColor = COLOR_RED; //Change font to red
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)display_buff, 40, 25);
            textProperties.fontColor = COLOR_WHITE; //Change font to white
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)"Cur Zone:", 10, 45);
            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);
            }
            sprintf(display_buff, "%u", Current_Zone); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 71, 45);
            textProperties.fontColor = COLOR_WHITE; //Change font to white
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)"Prev Zone:", 10, 60);
            if(Prev_Zone == 1) {
                textProperties.fontColor = COLOR_YELLOW;
                oled.SetTextProperties(&textProperties);
            } else if(Prev_Zone == 2) {
                textProperties.fontColor = COLOR_BLUE;
                oled.SetTextProperties(&textProperties);
            } else if(Prev_Zone == 3) {
                textProperties.fontColor = COLOR_GREEN;
                oled.SetTextProperties(&textProperties);
            } else if(Prev_Zone == 4) {
                textProperties.fontColor = COLOR_RED;
                oled.SetTextProperties(&textProperties);
            }
            sprintf(display_buff, "%u", Prev_Zone); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 71, 60);
            textProperties.fontColor = COLOR_WHITE; //Change font to white
            oled.SetTextProperties(&textProperties);//Implement color change
            break;
        }
        case 32: {
            //Zone Boundary Info
            oled.FillScreen(COLOR_BLACK);
            oled.Label((uint8_t *)"HR Zone Info", 10, 5);// Display at x,y
            textProperties.fontColor = COLOR_YELLOW; //Change font to yellow
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)"Z1:", 10, 20);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone1[0]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 30, 20);// Display at x,y
            oled.Label((uint8_t *)"-", 52, 20);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone1[1]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 60, 20);// Display at x,y
            textProperties.fontColor = COLOR_BLUE; //Change font to blue
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)"Z2:", 10, 35);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone2[0]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 30, 35);// Display at x,y
            oled.Label((uint8_t *)"-", 52, 35);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone2[1]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 60, 35);// Display at x,y
            textProperties.fontColor = COLOR_GREEN; //Change font to green
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)"Z3:", 10, 50);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone3[0]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 30, 50);// Display at x,y
            oled.Label((uint8_t *)"-", 52, 50);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone3[1]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 60, 50);// Display at x,y
            textProperties.fontColor = COLOR_RED; //Change font to red
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)"Z4:", 10, 65);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone4[0]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 30, 65);// Display at x,y
            oled.Label((uint8_t *)"-", 52, 65);// Display at x,y
            sprintf(display_buff, "%u", HR_Zone4[1]); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 60, 65);// Display at x,y
            textProperties.fontColor = COLOR_WHITE; //Change font to white
            oled.SetTextProperties(&textProperties);//Implement color change
            oled.Label((uint8_t *)"Back",10,80); // Display "Back" at x,y
            oled.Label((uint8_t *)"Next",60,80);  //Display "Next" at x,y
            break;
        }  
        case 33: {//Heart rate simulator
            oled.FillScreen(COLOR_BLACK);
            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
            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 41: { //Fall mode
            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
            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;
        }
        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;
        }
        
        case 43: { //Impact Thresh
            oled.FillScreen(COLOR_BLACK);
            oled.Label((uint8_t *)"Adj I-Th", 10, 5);
            sprintf(display_buff, "%2.2f g", Impact_Thresh); //Convert int to char array for displaying mode
            oled.Label((uint8_t *)"I_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;
        }
        case 44: { //Motion Thresh
            oled.FillScreen(COLOR_BLACK);
            oled.Label((uint8_t *)"Adj M-Th", 10, 5);
            sprintf(display_buff, "%4.0f D/S", Movement_Thresh); //Convert int to char array for displaying mode
            oled.Label((uint8_t *)"M_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;
        }//end case 44
        case 45: { //Min_Movement_Time
            oled.FillScreen(COLOR_BLACK);
            oled.Label((uint8_t *)"Adj MinM_Tim", 10, 5);
            sprintf(display_buff, "%1.2fSec", Min_Movement_Time); //Convert int to char array for displaying mode
            oled.Label((uint8_t *)"m_Tm:", 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;
        }//end case 45
        case 46: { //Min_Movement_Time
            oled.FillScreen(COLOR_BLACK);
            oled.Label((uint8_t *)"Adj MinM_Dur", 10, 5);
            sprintf(display_buff, "%2.1fSec", Min_Movement_duration); //Convert int to char array for displaying mode
            oled.Label((uint8_t *)"mDur:", 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;
        }//end case 46   
        
        case 47: { //Post fall "are you OK?" screen
            oled.FillScreen(COLOR_BLACK);
            textProperties.fontColor = COLOR_RED;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"Fall Detected!", 5, 5);
            textProperties.font = OpenSans_12x18_Regular;  //  Max Width of Character  = 12px, Max Height of Character = 18px 
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties); 
            oled.Label((uint8_t *)"Do you need", 5, 20);
            oled.Label((uint8_t *)"Help?", 10, 35);
            //oled.Label((uint8_t *)"+",85,15); // "*" at x,y
            //oled.Label((uint8_t *)"-",85,60); // "*" at x,y
            oled.Label((uint8_t *)"No",10,75); // Display "Back" at x,y
            oled.Label((uint8_t *)"YES!",60,75);  //Display "Next" at x,y
            textProperties.font = OpenSans_10x15_Regular;  //  Max Width of Character  = 10px, Max Height of Character = 15px 
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            break;
        }//end case 47   
        
        case 48: { //Sending Fall alert screen
            oled.FillScreen(COLOR_BLACK);
            textProperties.fontColor = COLOR_RED;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"Fall Detected!", 5, 5);
            textProperties.font = OpenSans_12x18_Regular;  //  Max Width of Character  = 12px, Max Height of Character = 18px 
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties); 
            oled.Label((uint8_t *)"Sending", 20, 40);
            oled.Label((uint8_t *)"Alert", 25, 55);
            oled.Label((uint8_t *)"Dismiss?",5,75); // Display "Back" at x,y
            //oled.Label((uint8_t *)"YES!",60,80);  //Display "Next" at x,y
            textProperties.font = OpenSans_10x15_Regular;  //  Max Width of Character  = 10px, Max Height of Character = 15px 
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            break;
        }//end case 48
        
        case 49: { //Testing WDT diagnostic screen
            oled.FillScreen(COLOR_BLACK); // Clear screen
            textProperties.fontColor = COLOR_RED;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"WDT Test",15,5); // Display at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);        
            oled.Label((uint8_t *)"This will",16,25); // Display at x,y
            oled.Label((uint8_t *)"Cause a",17,40); // Display at x,y
            oled.Label((uint8_t *)"SW Reset",15,55); // Display 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 *)"Back",10,80); // Display "Back" at x,y
            oled.Label((uint8_t *)"Enter",60,80);  //Display at x,y
            break;
        }//end case 49
        
        case 50: { //WDT timeout screen
            CLRWDT();
            oled.FillScreen(COLOR_BLACK); // Clear screen
            textProperties.fontColor = COLOR_RED;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"WDT Test",15,5); // Display at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);        
            oled.Label((uint8_t *)"Reset in",17,25); // Display at x,y
            
            sprintf(display_buff, "%2.1f Sec", WDT_TIME); //Convert int to char array for displaying mode
            oled.Label((uint8_t *)display_buff,18,40); // Display 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 *)"Back",10,80); // Display "Back" at x,y
            //oled.Label((uint8_t *)"Enter",60,80);  //Display at x,y
            haptic = 0;
            wait(WDT_TIME+1.0);
            break;
        }//end case 50
        
        case 51: { //Sending panic alert screen
            oled.FillScreen(COLOR_BLACK);
            textProperties.fontColor = COLOR_RED;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"Panic Alert!", 5, 5);
            textProperties.font = OpenSans_12x18_Regular;  //  Max Width of Character  = 12px, Max Height of Character = 18px 
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties); 
            oled.Label((uint8_t *)"Sending", 20, 40);
            oled.Label((uint8_t *)"Alert", 25, 55);
            oled.Label((uint8_t *)"Dismiss?",5,75); // Display "Back" at x,y
            //oled.Label((uint8_t *)"YES!",60,80);  //Display "Next" at x,y
            textProperties.font = OpenSans_10x15_Regular;  //  Max Width of Character  = 10px, Max Height of Character = 15px 
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            break;
        }//end case 51

#endif  // end of non-production/debug version code

        case 71: {// BLE
            oled.FillScreen(COLOR_BLACK); // Clear screen
            textProperties.fontColor = COLOR_BLUE;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"BLUETOOTH",15,5); // Display at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"Enter",60,80);  //Display 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 *)"Back",10,80); // Display "Back" at x,y
            break;
        }

        case 72: {// BlueTooth on/off
           oled.FillScreen(COLOR_BLACK); // Clear screen
            textProperties.fontColor = COLOR_BLUE;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)"BLUETOOTH",10,5); // Display at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            if (BLE_On == 1) {
                
                /* Display PAIR CODE in a 90px by 18px textbox at x=0,y=25 */
                strcpy((char *) text,"PAIR CODE");
                oled.TextBox((uint8_t *)text,10,25,80,18);

                /* Display Bond Pass Key in a 90px by 18px textbox at x=0,y=40 */
                sprintf(text,"%d", kw40z_device.GetPassKey());
                oled.TextBox((uint8_t *)text,10,45,80,18);
            } else {
                oled.Label((uint8_t *)" Off ",40,45);
            }
  //          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 *)"Toggle",59,80);  //Display "Toggle" at x,y
            break;
        }


        default: {
            Error_Num=1;
            error_screen(); // Clear screen
            break;
        }
    }//end of switch
    __enable_irq();     // Enable all Interrupts
}// end upday_display()

void error_screen(void)
{
    oled.FillScreen(COLOR_RED); // Clear screen
    oled.Label((uint8_t *)"Error! ",30,30); // Display error at x,y
    sprintf(text_1," %i  ",Error_Num);
    oled.Label((uint8_t *)text_1,30,60); // Display error at x,y
    wait(3);  // wait 3 seconds
    oled.FillScreen(COLOR_BLACK); // Clear screen
}

/*****************************************************************************
Name: StartHaptic
Purpose: Cause the HexiHeart device to vibrate for a predetermined amount of
         time
Inputs: None
Returns: None
******************************************************************************/
void StartHaptic(void)
{
    Haptic_Timer.attach(&Haptic_Off_,(0.05));
   // hapticTimer.start(30);  // was originaly 50, then 30 
    /* this 30 value seems to not work after Neil added a global 
    __disable_irq() and __enable_irq() for the update_display() functions on 2/18/18
    */
    haptic = 1;
}
void Haptic_Off_(void)
{
    haptic = 0;
    }

/*****************************************************************************
Name: StartHaptic
Purpose: Cause the HexiHeart device to vibrate for x amount of time
Inputs: An int representing the duration of the vibration
Returns: None
******************************************************************************/

void StartHaptic(int x)
{   
    hapticTimer.start(x);
    haptic = 1;
}

void StopHaptic(void const *n)
{
    haptic = 0;
    hapticTimer.stop();
}

/*****************************************************************************
Name: Increment_Age
Purpose: Increment the user's age by 1
Inputs: None
Returns: None
******************************************************************************/
void Increment_Age()
{
    StartHaptic();
    if(Age < 100) {
        Age += 1;
        Screen_Num = 27;
    } else {
        Age = 1;
    }
}

/*****************************************************************************
Name: Decrement_Age
Purpose: Decrement the user's age by 1
Inputs: None
Returns: None
******************************************************************************/
void Decrement_Age()
{
    StartHaptic();
    if(Age == 1) {
        Age = 100;
    } else {
        Age -= 1;
        Screen_Num = 27;
    }
}

/*****************************************************************************
Name: Set_Max_Bpm
Purpose: Calculates the user's maximum heart rate based on their age
Inputs: None
Returns: None
******************************************************************************/
void Set_Max_Bpm()
{
    Max_Bpm = 220 - Age;
}

/*****************************************************************************
Name: Set_Zone_Boundaries
Purpose: Calculates the user's heart rate zones' boundaries based on the user's
         maximum heart rate
Inputs: None
Returns: None
******************************************************************************/
void Set_Zone_Boundaries()
{
    Set_Max_Bpm();
    HR_Zone1[0] = Max_Bpm * .50;   //Set Heart Rate Zone 1
    HR_Zone1[1] = Max_Bpm * .60;   //Set Heart Rate Zone 1
    HR_Zone2[0] = HR_Zone1[1] + 1;   //Set Heart Rate Zone 2
    HR_Zone2[1] = Max_Bpm * .70;   //Set Heart Rate Zone 2
    HR_Zone3[0] = HR_Zone2[1] + 1;   //Set Heart Rate Zone 3
    HR_Zone3[1] = Max_Bpm * .80;   //Set Heart Rate Zone 3
    HR_Zone4[0] = HR_Zone3[1] + 1;   //Set Heart Rate Zone 4
    HR_Zone4[1] = Max_Bpm;   //Set Heart Rate Zone 4
}

/*****************************************************************************
Name: Increment_Target_Zone
Purpose: Imcrements the user's target heart rate zone preference by 1
Inputs: None
Returns: None
******************************************************************************/
void Increment_Target_Zone()
{
    StartHaptic();
    if(Target_Zone == 4) {
        Target_Zone = 1;
    } else {
        Target_Zone += 1;
    }
}

/*****************************************************************************
Name: Decrement_Target_Zone
Purpose: Decrements the user's target heart rate zone preference by 1
Inputs: None
Returns: None
******************************************************************************/
void Decrement_Target_Zone()
{
    StartHaptic();
    if(Target_Zone == 1) {
        Target_Zone = 4;
    } else {
        Target_Zone -= 1;
    }
}

/*****************************************************************************
Name: Increment_HR_Vibr_Pref
Purpose: Increment the user's heart rate vibration preference by 1
Inputs: None
Returns: None
******************************************************************************/
void Increment_HR_Vibr_Pref()
{
    StartHaptic();
    if(HR_Vibration == 3) {
        HR_Vibration = 1;
    } else {
        HR_Vibration += 1;
    }
}

/*****************************************************************************
Name: Decrement_HR_Vibr_Pref
Purpose: Decrement the user's heart rate vibration preference by 1
Inputs: None
Returns: None
******************************************************************************/
void Decrement_HR_Vibr_Pref()
{
    StartHaptic();
    if(HR_Vibration == 1) {
        HR_Vibration = 3;
    } else {
        HR_Vibration -= 1;
    }
}

/*****************************************************************************
Name: Enable_Heart_Rate
Purpose: Turn on the HexiHeart heart rate function
Inputs: None
Returns: None
******************************************************************************/
void Enable_Heart_Rate()
{
    Heart_Rate_Mode = true;
}

/*****************************************************************************
Name: Disable_Heart_Rate
Purpose: Turn off the HexiHeart heart rate function
Inputs: None
Returns: None
******************************************************************************/
void Disable_Heart_Rate()
{
    Heart_Rate_Mode = false;  
}

/*****************************************************************************
Name: Determine_Current_Zone
Purpose: Determines which zone the heart rate is in and assigns the curent
         zone and previous zone
Inputs: None
Returns: None
******************************************************************************/
void Determine_Current_Zone()
{
    Prev_Zone = Current_Zone;

    if(Heart_Rate >= HR_Zone1[0] && Heart_Rate <= HR_Zone1[1]) {
        Current_Zone = 1;
    } else if(Heart_Rate >= HR_Zone2[0] && Heart_Rate <= HR_Zone2[1]) {
        Current_Zone = 2;
    } else if(Heart_Rate >= HR_Zone3[0] && Heart_Rate <= HR_Zone3[1]) {
        Current_Zone = 3;
    } else if(Heart_Rate >= HR_Zone4[0] && Heart_Rate <= HR_Zone4[1]) {
        Current_Zone = 4;
    } else {
        //error reading, don't change anything
    }
    Heart_Rate_Vibrations();


}
/*****************************************************************************
Name: Run_Heart_Vibrations
Purpose: Performs the HexiHeart heart rate function
Inputs: None
Returns: None
******************************************************************************/
void Heart_Rate_Vibrations()
{
    
        if(HR_Vibration == 1) {
            //All Pre-loaded vibrations enabled
            if(Current_Zone == Prev_Zone) {
                // Do nothing if no zone change
            } else if(Current_Zone == Target_Zone) { //Changed to target zone
                if(Target_Zone == LOWEST_ZONE || Prev_Zone > Target_Zone) { //must have entered from above
                    CLRWDT();
                    haptic = 1;
                    wait(0.5);
                    haptic = 0;
                    wait(0.5);
                    CLRWDT();
                    haptic = 1;
                    wait(0.5);
                    haptic = 0;
                } else if(Target_Zone == HIGHEST_ZONE || Prev_Zone < Target_Zone) { //must have entered from below
                    CLRWDT();
                    haptic = 1;
                    wait(0.5);
                    haptic = 0;
                }
            } else if(Current_Zone != Target_Zone && Prev_Zone == Target_Zone) {
                if(Target_Zone == HIGHEST_ZONE || Current_Zone < Target_Zone) { //must have exited below
                    CLRWDT();
                    haptic  = 1;
                    wait(1);
                    haptic = 0;
                } else if(Target_Zone == LOWEST_ZONE || Current_Zone > Target_Zone) { //must have exited above
                    haptic = 1;
                    CLRWDT();
                    wait(1);
                    haptic = 0;
                    wait(1);
                    CLRWDT();
                    haptic = 1;
                    wait(1);
                    haptic = 0;
                }
            }
        } else if(HR_Vibration == 2) {
            //Only Entering and Exiting target zone
            if(Current_Zone == Prev_Zone) {
                //do nothing
            } else if(Current_Zone == Target_Zone) {
                CLRWDT();
                haptic = 1;
                wait(0.2);
                haptic = 0;
                wait(0.2);
                CLRWDT();
                haptic = 1;
                wait(0.2);
                haptic = 0;
            } else if(Current_Zone != Target_Zone && Prev_Zone == Target_Zone) {
                haptic = 1;
                CLRWDT();
                wait(1);
                haptic = 0; 
            }

        } else  if(HR_Vibration == 3) {
            //No Vibrations

        } else {
            //Error, can only be choices 1-3
            error_screen();
        }
    
}

/*****************************************************************************
Name: Increment_Heart_Rate
Purpose: Manually increment the the heart rate measurement by 1 for testing
         purposes
Inputs: None
Returns: None
******************************************************************************/
void Increment_Heart_Rate()
{
    //StartHaptic();
    if(Heart_Rate == HR_Zone4[1]) {
        Heart_Rate = HR_Zone1[0];
    } else {
        Heart_Rate += 1;
    }
    Determine_Current_Zone();
}

/*****************************************************************************
Name: Decrement_Heart_Rate
Purpose: Manually decrement the the heart rate measurement by 1 for testing
         purposes
Inputs: None
Returns: None
******************************************************************************/
void Decrement_Heart_Rate()
{
    //StartHaptic();
    if(Heart_Rate == HR_Zone1[0]) {
        Heart_Rate = HR_Zone4[1];
    } else {
        Heart_Rate -= 1;
    }
    Determine_Current_Zone();
} 

/*****************************************************************************
Name: Led_Zone_Indicator()
Purpose: Ticker interupt routine called every 1.0 Seconds in order to Blink LED to indicate current Heart Rate zone
Inputs: hr_led Ticker
******************************************************************************/
void Led_Zone_Indicator()
{
    CLRWDT();// Reset watchdog timer before we do this long opperation
  if(Led_Zones == true)
  {
    if(Current_Zone == 1)
    {
        BLU_Led = LED_OFF;
        RED_Led = LED_ON;
        GRN_Led = LED_ON;
        hr_led.attach(&Led_Zone_Indicator_off, HR_LED_on_time); // in 0.5 seconds turn off LED
        //wait(0.5);
        //RED_Led = LED_OFF;
        // GRN_Led = LED_OFF;
    }  
    else if(Current_Zone == 2)
    {
        if(Prev_Zone == 1)
        {
            RED_Led = LED_OFF;
            GRN_Led = LED_OFF;
        }
        else if(Prev_Zone == 3)
        {
            GRN_Led = LED_OFF;
        }
        BLU_Led = LED_ON;
        hr_led.attach(&Led_Zone_Indicator_off, HR_LED_on_time); // in 0.5 seconds turn off LED
       // wait(0.5);  
       // BLU_Led = LED_OFF; 
    }
    else if(Current_Zone == 3)
    {
        if(Prev_Zone == 2)
        {
            BLU_Led = LED_OFF;
        }
        else if(Prev_Zone == 4)
        {
            RED_Led = LED_OFF;
        }
        GRN_Led = LED_ON;
        hr_led.attach(&Led_Zone_Indicator_off, HR_LED_on_time); // in 0.5 seconds turn off LED
      //  wait(0.5);  
     //   GRN_Led = LED_OFF; 
    }
    else if(Current_Zone == 4)
    {
        GRN_Led = LED_OFF;
        RED_Led = LED_ON;
        hr_led.attach(&Led_Zone_Indicator_off, HR_LED_on_time); // in 0.5 seconds turn off LED
       // wait(0.5);  
       // RED_Led = LED_OFF; 
    }
  }  
}//end of Led_Zone_Indicator 

/*****************************************************************************
Name: Led_Zone_Indicator_off()
Purpose: Ticker interupt routine called every 0.5 Seconds after LEDs turned on to turn them back
off.  This avoids the 0.5 wait every second, freeing up the system.
Inputs: hr_led Ticker
******************************************************************************/
 //turns off LEDs after 0.5 seconds instead of using a wait command
void Led_Zone_Indicator_off(){
    RED_Led = LED_OFF; 
    GRN_Led = LED_OFF;
    BLU_Led = LED_OFF;
    hr_led.attach(&Led_Zone_Indicator, HR_LED_period); // blink every second
    }//end void Led_Zone_Indicator_off()

/*****************************************************************************
Name: Heat_Index_Calculation()
Purpose: Calculates the heat index using the temperature and humidity sensors
Inputs: None
Returns: None
******************************************************************************/
void Heat_Index_Calculation(){
    //sample_ftemp = temphumid.sample_ftemp(); // sampling is now done in rolling UpDate_Ave() function
 
    //sample_humid = temphumid.sample_humid(); // sampling is now done in rolling UpDate_Ave() function 
            
    hi_calc = -42.379 +
           2.04901523 * sample_ftemp +
           10.14333127 * sample_humid -
           0.22475541 * sample_ftemp * sample_humid -
           0.00683783 * sample_ftemp * sample_ftemp -
           0.05481717 * sample_humid * sample_humid +
           0.00122874 * sample_ftemp * sample_ftemp * sample_humid +
           0.00085282 * sample_ftemp * sample_humid * sample_humid -
           0.00000199 * sample_ftemp * sample_ftemp * sample_humid * sample_humid;
           
        if (sample_humid < 13 && sample_ftemp > 80 && sample_ftemp < 112){
                adjustment = ((13 - sample_humid) / 4) * sqrt((17-abs(sample_ftemp-95.0))/17);
                heat_index = hi_calc - adjustment;
                }
                
        else if (sample_humid > 85 && sample_ftemp > 80 && sample_ftemp < 87){
                adjustment = ((sample_humid - 85) / 10) * ((87 - sample_ftemp)/5);
                heat_index = hi_calc + adjustment;
                }
                
        else if (hi_calc < 80){
                heat_index = 0.5 * (sample_ftemp + 61.0 + ((sample_ftemp - 68.0) * 1.2) + (sample_humid * 0.094));
                }
 
        else {heat_index = hi_calc;}               
}

/*****************************************************************************
Name: fall_detect_debug()
Purpose: Debug Interupt routine called when accelerometer IC has detected a 
free-fall (accel <= 0.5g)
Inputs: interupt1 of accel sensor
******************************************************************************/
void fall_detect_debug(){// fall detect interupt routine
if(Fall_Alert == 1){
 accel.acquire_accel_data_g(Accel_Data_Event);
// for now just turn on display and give haptic feedback
    Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED
        oled.DimScreenOFF(); 
        if (OLED_ON == 0) {
        OLED_ON = 1; // Scree was off, set to On  
        update_display();      
         }  // endif        
        if (Screen_Num != 21){
            Screen_Num = 21;  //Change to screen 21 (Fall diag screen)
            update_display();
        }  // endif      
         
//__disable_irq();    // Disable all Interrupts
//    oled.Label((uint8_t *)" Fall Detected ",05,70); // Display at x,y 

    Accel_Mag = 2*sqrt(((Accel_Data_Event[0]*Accel_Data_Event[0])+(Accel_Data_Event[1]*Accel_Data_Event[1])+(Accel_Data_Event[2]*Accel_Data_Event[2])));
    sprintf(text_1,"Free-Fall:%2.2fg",Accel_Mag);
    oled.Label((uint8_t *)text_1,2,5);// text_1 at x,y

    BLU_Led = LED_ON;  // LEDs default to on, need to turn off
    Led_clk1 = 1;  // Turn on LED1, on docking station
    StartHaptic();
 //   haptic = 1;
    Accel_INT1.rise(&fall_det_end_debug); // reset accel sensor's int#1 to active high and proper int routine
//__enable_irq();     // Enable all Interrupts
}// end if     
}//end fall_detect_debug interupt routine

/*****************************************************************************
Name: fall_det_end_debug()
Purpose: Debug interupt routine called when accelerometer IC has detected that the 
free-fall acceleration has ended (accel now >0.5g)
Inputs: interupt1 of accel sensor
******************************************************************************/
void fall_det_end_debug(){
    haptic = 0;         // Turn off Haptic
    BLU_Led = LED_OFF;  // Turn off HexiHeart Blue LED
    Led_clk1 = 0;       // Turn off LED1, on docking station
    fall_config(21);    // reads interrupts to clear old interupt
 //   oled.Label((uint8_t *)"                         ",05,70); // clear display at x,y
    Accel_INT1.fall(&fall_detect_debug); // reset accel sensor's int#1 to active low and proper int routine
}    //end fall_det_end_debug interupt routine

/*****************************************************************************
Name: impact_detect_debug()
Purpose: Debug Interupt routine called when accelerometer IC has detected a vector
magnitude acceleration >= 3.0g
Inputs: interupt2 of accel sensor
******************************************************************************/
void impact_detect_debug(){
 if(Fall_Alert == 1){
    accel.acquire_accel_data_g(Accel_Data_Event);
    haptic = 1;
    Led_clk2 = 1;  // Turn LED2 on docking station on

    Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED
    oled.DimScreenOFF();
        if (OLED_ON == 0) {
        OLED_ON = 1; // Screen was off, set to On  
        update_display();      
         }  // endif 
         
        if (Screen_Num != 21){
            Screen_Num = 21;  //Change to screen 21 (Fall diag screen)
            update_display();
        }  // endif    
        accel.acquire_accel_data_g(Accel_Data);
        Accel_Mag = 2*sqrt(((Accel_Data_Event[0]*Accel_Data_Event[0])+(Accel_Data_Event[1]*Accel_Data_Event[1])+(Accel_Data_Event[2]*Accel_Data_Event[2])));
        sprintf(text_1,"Impact:%2.2fg",Accel_Mag);
        oled.Label((uint8_t *)text_1,3,20);// text_1 at x,y
        wait(0.1);
        Led_clk2 = 0;  // Turn LED2 off docking station on
        haptic = 0;
 }// end if     
}//end impact_detect_debug interupt routine

/*****************************************************************************
Name: motion_detect_debug()
Purpose: Debug Interupt routine called when gyro IC has detected motion >= 50 deg/sec
in order to see if fall-impact resulted in motion-less person.
Inputs: interupt1 of gyro sensor
******************************************************************************/
void motion_detect_debug(){
 float Gyro_Data_Event[3]; // store right away to see what it was
 if(Fall_Alert == 1 && Fall_Alert_Mode > 2){// only service interupt if automatic fall detect is selected by user
    gyro.acquire_gyro_data_dps(Gyro_Data_Event);
    Gyro_Mag = (abs(Gyro_Data_Event[0])+abs(Gyro_Data_Event[1])+abs(Gyro_Data_Event[2]));
    haptic = 1;
    Led_clk3 = 1;  // Turn on LED3, on docking station

    Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED
    oled.DimScreenOFF();
        if (OLED_ON == 0) {
        OLED_ON = 1; // Screen was off, set to On  
        update_display();      
         }  // endif 
         
        if (Screen_Num != 21){
            Screen_Num = 21;  //Change to screen 21 (Fall diag screen)
            update_display();
        }  // endif         
        sprintf(text_1,"Motion:%4.0f d/s",Gyro_Mag);
        oled.Label((uint8_t *)text_1,3,20);// text_1 at x,y
        gyro_sensor_config(13); // reset motion counter
        wait(0.1);
        Led_clk3 = 0;  // Turn LED3 off docking station on
        haptic = 0;
 }// end if     
}//end motion_detect_debug interupt routine

//********** Full sequential fall interup routines below *********************
/*****************************************************************************
Name: fall_detect()
Purpose: Interupt routine called when accelerometer IC has detected a 
free-fall (accel <= 0.5g)
Inputs: interupt1 of accel sensor
******************************************************************************/
void fall_detect(){// fall detect interupt routine
if(Fall_Alert == 1 && Led_clk2 == 0){// are we looking for falls? Have we already det impact?
 accel.acquire_accel_data_g(Accel_Data_Event);
    f_time.reset(); 
    f_time.start(); //start measuring fall time
    for (int i=0; i<7; i++){
        Fall_Event_Data[i] = 0; // clear any old information
    }//end for loop

//    Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED
    //time_t seconds = time(NULL);
    //store time into Fall_Event_Data buffer
    Fall_Event_Data[0] = 2*sqrt(((Accel_Data_Event[0]*Accel_Data_Event[0])+(Accel_Data_Event[1]*Accel_Data_Event[1])+(Accel_Data_Event[2]*Accel_Data_Event[2])));
    Led_clk1 = 1;  // Turn on LED1, on docking station
    //Led_clk2 = 0;  // Turn off LED2, on docking station
    Accel_INT1.rise(&fall_det_end); // look for end of fall by reseting accel sensor's int#1 to active high
 //   Accel_INT1.fall(&fall_detect); // Accel sensor's int#1 calls interupt routine
    Accel_INT2.fall(&impact_detect); //Start looking for vector impacts
 //   Gyro_INT1.fall(&motion_detect); // Gyro sensor's int#1 (PTD1) calls interupt routine
    chk_fall.attach(&chkfall,(0.5)); //initialize ticker to check for end of fall every half second
 
}// end if     
}//end fall_detect interupt routine


/*****************************************************************************
Name: chkfall()
Purpose: Ticker interupt routine called every 0.5 Seconds (after a free-fall has been detected)
to check to see if we've missed the interupt indicating the free-fall event is over.
Inputs: chk_fall Ticker
******************************************************************************/
void chkfall(){// Ticker fall-end detect routine to see if we missed interupt
    if(Accel_INT1 == 0){//fall still active
        accel.acquire_accel_data_g(Accel_Data_Event);
        Accel_Mag = 2*sqrt(((Accel_Data_Event[0]*Accel_Data_Event[0])+(Accel_Data_Event[1]*Accel_Data_Event[1])+(Accel_Data_Event[2]*Accel_Data_Event[2])));
        if (Accel_Mag < Fall_Event_Data[0]){
            Fall_Event_Data[0] = Accel_Mag;// if fall is less than previous re-store value
        }//endif  
    }//endif
    else{//fall interupt off
        f_time.stop(); // stop fall timer
        chk_fall.detach(); //stop ticker, interupt caught end of fall
        chk_fall.attach(&clear_fall,(2.0)); //initialize ticker to check no impact in 2 seconds
        Accel_INT1.fall(NULL); // turn off accel sensor's int#1
    }//end else
    
}//end chkfall ticker interupt routine

/*****************************************************************************
Name: interupt_off()
Purpose: Interupts are supposed to be turned off by using "Int_name.fall(NULL);", but
that doesn't seem to work. 
******************************************************************************/
void interupt_off(){// turn off an interupt by substituting this one
// Do nothing 
}//end interupt_off  routine


/*****************************************************************************
Name: fall_det_end()
Purpose: Interupt routine called when accelerometer IC has detected that the 
free-fall acceleration has ended (accel now >0.5g)
Inputs: interupt1 of accel sensor
******************************************************************************/
void fall_det_end(){    // accel detected end of free-fall
    f_time.stop();      // stop fall timer
    chk_fall.detach();  //stop ticker, interupt caught end of fall
    chk_fall.attach(&clear_fall,(Fall_Impact_Max_Wait_Time)); //initialize ticker to check no impact in 2 seconds
   // fall_config(21);    // reads interrupts to clear old interupt
    Accel_INT1.fall(NULL); // Turn off accel sensor's int#1 
}    //end fall_det_end interupt routine


/*****************************************************************************
Name: clear_fall()
Purpose: Ticker interupt routine called to clear/cancel fall detection routine if 
no impact was detected withing 2.0 seconds after the free-fall event
Inputs: chk_fall Ticker
******************************************************************************/
void clear_fall(){// Ticker routine to clear_fall detect routine if no impact in 2.0 seconds after free-fall event is over
    if(Led_clk2 == 1){// have we detected an impact?
     chk_fall.detach(); //just stop ticker
    }//endif
    else{
     Accel_INT1.fall(&fall_detect); // reset accel sensor's int#1 to active low and reset for next fall
     Accel_INT2.fall(NULL); //Stop looking for vector impacts, 
     Led_clk1 = 0;       // Turn off LED1, on docking station
    }//end else
}//end clear_fall ticker interupt routine


/*****************************************************************************
Name: impact_detect()
Purpose: Interupt routine called when accelerometer IC has detected a vector
magnitude acceleration >= 3.0g
Inputs: interupt2 of accel sensor
******************************************************************************/
void impact_detect(){// we may detect multiple impacts, this needs to work from last impact detected
 if(Fall_Alert == 1){
    f_time.stop(); // stop fall timer
    accel.acquire_accel_data_g(Accel_Data_Event);
    chk_fall.detach();  //detach/stop ticker, impact was detected
    wait(0.1);
    Fall_Event_Data[1] = f_time;// store free-fall time
    Led_clk2 = 1;  // Turn on LED2, on docking station
    gyro_sensor_config(13); // reset motion counter
    Gyro_INT1.fall(&motion_detect);     // Start looking for motion
    chk_motion.attach(&chkmotion,(Min_Movement_duration)); //initialize ticker to check for motion during Min_Movement_duration
 }  // endif    
    Accel_Mag = 2*sqrt(((Accel_Data_Event[0]*Accel_Data_Event[0])+(Accel_Data_Event[1]*Accel_Data_Event[1])+(Accel_Data_Event[2]*Accel_Data_Event[2])));
    if(Accel_Mag>Fall_Event_Data[2]){
        Fall_Event_Data[2] = Accel_Mag; // if impact accel is higher than last measured, update   
    }//endif
    haptic = 1;// vibrate a little
    wait_ms(50);
    haptic = 0;
    //wait(0.1);
    //Led_clk3 = 1;  // Turn on LED3, on docking station  - we're looking for motion  
}//end impact_detect interupt routine

/*****************************************************************************
Name: motion_detect()
Purpose: Interupt routine called when gyro IC has detected motion >= 50 deg/sec
in order to see if fall-impact resulted in motion-less person.
Inputs: interupt1 of gyro sensor
******************************************************************************/
void motion_detect(){// 2 seconds of motion was detected
 chk_motion.detach(); //stop ticker, we've detected motion        
    Accel_INT1.fall(&fall_detect);   // Accel sensor's int#1 calls interupt routine
    Accel_INT2.fall(NULL);    //Reset for next event
    Gyro_INT1.fall(NULL);     //Reset for next event
        //wait(0.1);
        Led_clk1 = 0;  // Turn off LED1, on docking station
        Led_clk2 = 0;  // Turn off LED2, on docking station

}//end motion_detect interupt routine


/*****************************************************************************
Name: chkmotion()
Purpose: Ticker interupt routine called when 60sec window has elapsed without 
2seconds of motion being detected.
Inputs: chk_motion Ticker
******************************************************************************/
void chkmotion(){// if we got here we didn't detect motion
    //
    chk_motion.detach(); //stop ticker
    Screen_Num = 47;  //Change to screen 47 (Fall diag screen)
    Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED
        if (OLED_ON == 0) {
        OLED_ON = 1; // Screen was off, set to On          
         }  // endif 
         oled.DimScreenOFF();
        update_display(); //
        chk_motion.attach(&chk_help_needed,(Do_You_Need_Help_Time)); //initialize ticker to send automatic alert 
        CLRWDT();
        haptic = 1;
        wait(0.2);// aggressive hapic
        haptic = 0;
        wait(0.2);
        haptic = 1;
        wait(0.2);// aggressive hapic
        CLRWDT();
        haptic = 0;
        wait(0.2);
        haptic = 1;
        wait(0.2);// aggressive hapic
        haptic = 0;
        
    }//end of chkmotion ticker interupt routine
    
/*****************************************************************************
Name: chk_help_needed()
Purpose: Ticker interupt routine called when X sec window has elapsed without 
user dimissing "Are you OK" screen, sends automatic alert. 
Inputs: chk_motion Ticker
******************************************************************************/    
void chk_help_needed(){// Were they able to dismiss on their own?
    //
    chk_motion.detach(); //stop ticker
    if (Screen_Num == 47){// are we still on screen 47?
        Screen_Num = 48;  //Change to screen 48 and send alert
        Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED to keep it on 
        if (OLED_ON == 0) {
        OLED_ON = 1; // Screen was off, set to On        
        }  // endif 
        oled.DimScreenOFF();
        update_display();
        oled_text_properties_t textProperties = {0};
        oled.GetTextProperties(&textProperties);
        textProperties.fontColor = COLOR_RED;
        oled.SetTextProperties(&textProperties);
        oled.Label((uint8_t *)"No response!", 5, 20);
        textProperties.fontColor = COLOR_WHITE;
        oled.SetTextProperties(&textProperties);
        Send_Alert(30); // send alert type two 
        CLRWDT();    
        haptic = 1;
        wait(0.5);// very aggressive hapic
        haptic = 0;
        wait(0.2);
        haptic = 1;
        CLRWDT();
        wait(0.5);// very aggressive hapic
        haptic = 0;
        wait(0.2);
        haptic = 1;
        CLRWDT();
        wait(0.5);// very aggressive hapic
        haptic = 0;
    }  // endif   

    }//end of chkmotion ticker interupt routine
    
    
/*****************************************************************************
Name: Send_Alert()
Purpose: routine used to store and send alert
Inputs: int value from 0 to 256
10=Panic, 20=Fall+asked for help, 30=Fall+No response, 40=?...
Returns: None
******************************************************************************/
void Send_Alert(uint8_t Num){
    
    // store alert
    
    
    // ************ transmit alert
     /*Notify Hexiwear App that it is running Sensor Tag mode*/
        kw40z_device.SendSetApplicationMode(GUI_CURRENT_APP_SENSOR_TAG);
               
        /*Send Ambient Light Level at with aler number */ 
        //10=Panic, 20=Fall+asked for help, 30=Fall+No response, 40=?...
        kw40z_device.SendAmbientLight(Num);
    
    }//end Send_Alert routine

/*****************************************************************************
Name: fall_config()
Purpose: routine used to set accelerometer and gyro sensors' internal registers for chip
level interrupts
Inputs: int value from 0 to 256
Returns: None
******************************************************************************/
void fall_config(uint8_t Num){ // this is more than just accel config
// use case switches here to configure for 
switch(Num) {           
                case 0: {// put in standby
                    accel_sensor_config(0); // set accel sensor to standby
                    /*For lowest accel power ~2uA in standby mode */
                    gyro_sensor_config(0); // set gyro sensor to standby
                    /*For lowest gyro power ~2.8uA in standby mode */
                    Accel_INT1.fall(NULL); // Turn off Accel sensor's int#1
                    Accel_INT2.fall(NULL); // Turn off Accel sensor's int#2
                    Gyro_INT1.fall(NULL); // Turn off Gyro sensor's int#1 
                    break;      
                }// end of case 0
                
                case 1: {// configure for free-fall int only
                    accel_sensor_config(1); // set accel sensor for free-fall
                    gyro_sensor_config(0); // set gyro sensor to standby
                    Accel_INT1.fall(NULL); // Turn off Accel sensor's int#1
                    Accel_INT2.fall(NULL); // Turn off Accel sensor's int#2
                    Gyro_INT1.fall(NULL); // Turn off Gyro sensor's int#1 
                    
                    Accel_INT1.fall(&fall_detect_debug); // Accel sensor's int#1 calls interupt routine
                    break;
                }// end of case 1
                
                case 2: {// configure for vector impact only
                    accel_sensor_config(2); // set accel sensor vector impact only
                    gyro_sensor_config(0); // set gyro sensor to standby
                    Accel_INT1.fall(NULL); // Turn off Accel sensor's int#1
                   // Accel_INT2.fall(NULL); // Turn off Accel sensor's int#2
                    Gyro_INT1.fall(NULL); // Turn off Gyro sensor's int#1
                    Accel_INT2.fall(&impact_detect_debug); //Accel sensor's int#2 calls interupt routine
                    
                    break;
                }// end of case 2    
     
                case 3: {// configure for motion int only
                    accel_sensor_config(0); // set accel sensor vector impact only
                    gyro_sensor_config(3); // set gyro sensor to standby
                    Accel_INT1.fall(NULL); // Turn off Accel sensor's int#1
                    Accel_INT2.fall(NULL); // Turn off Accel sensor's int#2
                    Gyro_INT1.fall(&motion_detect_debug); // Gyro sensor's int#1 (PTD1) calls interupt routine
                    break;
                }// end of case 3           
                                            
                 case 4: {// configure FFMT for free-fall event AND config for vector impact   
                    accel_sensor_config(4); // set accel sensor Free-fall and vector impact
                    gyro_sensor_config(3); // set gyro sensor motion
                    Accel_INT1.fall(&fall_detect_debug); // Accel sensor's int#1 calls interupt routine
                    Accel_INT2.fall(&impact_detect_debug); //Accel sensor's int#2 calls interupt routine
                    Gyro_INT1.fall(&motion_detect_debug); // Gyro sensor's int#1 (PTD1) calls interupt routine
                    break;
                }// end of case 4
                
                case 5: {// configure for sequential free-fall, vector impact then motion  
                    accel_sensor_config(4); // set accel sensor Free-fall and vector impact
                    gyro_sensor_config(3); // set gyro sensor motion
                    Accel_INT1.fall(&fall_detect); // Accel sensor's int#1 calls interupt routine
                    Accel_INT2.fall(NULL); //Accel sensor's int#2 calls interupt routine
                    Gyro_INT1.fall(NULL); // Gyro sensor's int#1 (PTD1) calls interupt routine
                    break;
                }// end of case 4
                       
                case 10: {// reset IC 
                    accel_sensor_config(10); // reset accel sensor 
                    gyro_sensor_config(10); // reset gyro sensor 
                    break;
                }// end case 10      
                
                case 11: {// wake both sensors for simple data read, they were in stanby
                    accel_sensor_config(11); // set accel sensor active for read
                    gyro_sensor_config(11); // set accel sensor active for read
                    break;
                }// end of case 11 
                
                case 12: {// put into standby for low power
                    accel_sensor_config(12); // set accel sensor to standby
                    gyro_sensor_config(12); // set gyro sensor to standby
                    break;
                }// end of case 112             
                
                case 20: {// read INT_Source to clear VECM int, shouldn't have to do this
            // This was not working for me but it was due to me using the wrong FXOS8700_I2C_ADDRESS_
                    char d[2];//, data_byte_[1]; 
                    d[0] = 0x0c;  // 0x0c is INT_Source Reg
                    i2c_bus1.write(FXOS8700_I2C_ADDRESS_,d,1,true); // "true" is needed to prevent stop
                    wait(0.01);
                    if(i2c_bus1.read(FXOS8700_I2C_ADDRESS_,d,1) == 1){ // read Who am I Reg for debug
                    sprintf(text_1," INT_Read_Err ");
                    oled.Label((uint8_t *)text_1,5,50); // Display error at x,y 
                    wait(1);  // wait 1 seconds
                    }//endif
                    break;
                }// end of case 20 
                
                   case 21: {// read A_FFMT_SRC reg to clear FFMT int, shouldn't have to do this
            // This was not working for me but it was due to me using the wrong FXOS8700_I2C_ADDRESS_
                    char d[2];//, data_byte_[1]; 
                    d[0] = 0x16;  // 0x16 is A_FFMT_SRC Reg
                    i2c_bus1.write(FXOS8700_I2C_ADDRESS_,d,1,true); // "true" is needed to prevent stop
                    wait(0.01);
                    if(i2c_bus1.read(FXOS8700_I2C_ADDRESS_,d,1) == 1){ // read Who am I Reg for debug
                    sprintf(text_1," INT_Read_Err ");
                    oled.Label((uint8_t *)text_1,5,50); // Display error at x,y 
                    wait(1);  // wait 1 seconds
                    }//endif
                    break;
                }// end of case 21 
                
                default: {
                    oled.Label((uint8_t *)" Mode? ",30,60); // Display "mode" at x,y
                    // unknown config
                    break;
                } 
}// end switch                

}// end Fall_config


/*****************************************************************************
Name: accel_sensor_config()
Purpose: Used to set accelerometer IC's internal registers to set up chip level
interrupts
Inputs: int value from 0 to 256
Returns: None
******************************************************************************/
      
void accel_sensor_config(uint8_t Num){ 
// use case switches here to configure for 
switch(Num) {           
                case 0: {// put in standby
                  char d[2]; 
                    d[0] = FXOS8700_CTRL_REG1;                     //Puts device in Standby mode
                    d[1] = 0x00; 
                    i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2);                            
                    /*For lowest power ~8uA, set ODR-12.5Hz,(low-pwr accel mode) or 2uA in standby mode */
                    break;      
                }// end of case 0
                
                case 1: {// configure for free-fall int only
                    char d[2]; 
                    d[0] = 0x2a;                                       //0x2a Config reg1
                    d[1] = 0x00;                                    //Put device in Standby mode
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc1a err",30,05); // Display "error" at x,y                  
                        wait(3.0); // display for 3 seconds
                    }//end if
                    
                    d[0] = 0x0e;                                    //XYZ_DATA_CFG (set full-scall range)
                    d[1] = 0b00000001;                              //Set data to default range of +/-2g for full range (2x0.488mg/LSB), High-pass filter off
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc1b err",30,05); // Display "error" at x,y      
                        wait(3.0); // display for 3 seconds
                    }//end if
 /*
                    d[0] = 0x0a;                                    //TRIG_CFG (address of FIFO trigger config reg)
                    d[1] = 0b00000100;                              //Trigger on freefall
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)" Step2 error ",30,05); // Display "error" at x,y      
                        wait(3.0); // display for 3 seconds
                    }//end if
 */                   
                    d[0] = 0x15;                                    //A_FFMT_CFG (address of Free fall trigger config reg), write in Standby only
                    d[1] = 0b00111000;                              //set to freefall, and look at all axis.
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc1c err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if
                       
                    d[0] = 0x17;                                    //A_FFMT_THS (address of Free fall threshold reg), write in Active or Standby
  //                  d[1] = 0b00001000;                                //set freefall threshold to about 756mg for now                   
                    d[1] = (uint8_t)(1000*Fall_Thresh/63);            //set freefall threshold - Resolution is 63mg/LSB, 0b111_1111 is maximum value
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc1d err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if  
                     
                    d[0] = 0x18;                                    //A_FFMT_COUNT (address of Free fall debounce counter), write in Active or Standby
                    d[1] = 0b00000110;                              //with ODR at 100Hz, should equal 60mS debounce time or 120mS in Sleep
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc1e err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if 
                           
                    d[0] = 0x2b;                                    //CTRL_REG2 (address of control reg), write in Standby only
 //                   d[1] = 0b00001101;                              //Turns Auto-Sleep mode on and low-noise, low power
                    d[1] = 0b00001001;                              //Turns Auto-Sleep mode off (b/c it wasn't waking on int) and low-noise, low power
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc1f err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if    
                    
                    d[0] = 0x2c;                                    //CTRL_REG3 (address of Int control reg), write in Standby only
                    d[1] = 0b00001000;                              //FFMT will wake chip from sleep, int are active high
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc1g err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if    
                        
                    d[0] = 0x2d;                                    //CTRL_REG4 (address of Int enable reg), write in Standby only
                    d[1] = 0b10000100;                              // FFMT int enabled and for debug I'm using a sleep int
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc1h err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if            
                    
                    d[0] = 0x2e;                                    //CTRL_REG5 (Int routing reg), write in Standby only
                    d[1] = 0b00000100;                              // Make FFMT int output on pin INT1(PTC1)
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc1i err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if                  
                    
                    d[0] = 0x29;                                    //ASLP_Count (counter used to go to sleep reg), write in Standby only
                    d[1] = 0b00001010;                              // 10*320mS=3.2S of no inturrupts to go to sleep
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc1j err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if    
                    
                    d[0] = 0x2a;                         //0x2a Config reg1, write in Standby only except for bit[0]
                    d[1] = 0b00011001;                    //Auto-Sleep mode on set to 50Hz, ODR set to 100Hz Puts device back into Active mode 
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc1k err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if  
                                     
                    break;
                }// end of case 1
                
                case 2: {// configure for vector impact only
                    char d[2]; 
                    
                    d[0] = FXOS8700_CTRL_REG1;                      //Config reg1 0x2a
                    d[1] = 0x00;                                    //Put device in Standby mode
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc2a err",30,05); // Display "error" at x,y                  
                        wait(3.0); // display for 3 seconds
                    }//end if
 
                    d[0] = 0x0e;                                    //XYZ_DATA_CFG (set full-scall range)
                    d[1] = 0b00000001;                              //Set data to +/-4g for full range (0.488mg/LSB), High-pass filter off
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc2b err",30,05); // Display "error" at x,y      
                        wait(3.0); // display for 3 seconds
                    }//end if
 /*
                    d[0] = 0x0a;                                    //TRIG_CFG (address of FIFO trigger config reg)
                    d[1] = 0b00000110;                              //Trigger on freefall and on Vector
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)" Step2 error ",30,05); // Display "error" at x,y      
                        wait(3.0); // display for 3 seconds
                    }//end if
 */                                      
                    d[0] = 0x5f;                                    //A_VECM_CFG (address of Vector config reg), write in Standby only
                    d[1] = 0b00111000;                              //Use reference values, don't update ref, enable.
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc2c err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if
                       
                    d[0] = 0x60;                                    //A_VECM_MSB (address of Vector threshold reg), write in Active or Standby
 //                   d[1] = 0b00000111;                                //set impact threshold to less than 1g for now                   
                    d[1] = (uint8_t)((1000*Impact_Thresh/0.488f)/256);        //set MSB Impact threshold - Resolution is 0.488mg/LSB so 0.5g=1024.6 => MSB=0b00000100 LSB=0b00000000 
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc2d err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if  
           
                    d[0] = 0x61;                                    //A_VECM_LSB (address of Vector threshold reg), write in Active or Standby
//                    d[1] = 0b00000011;                                //set impact threshold to less than 1g for now                   
                    d[1] = (uint8_t)(1000*Impact_Thresh/0.488f);
                    d[1] = (uint8_t)(d[1]%256);  //set MSB Impact threshold - Resolution 0.488mg/LSB so 0.5g=1024.6 => MSB=0b00000100 LSB=0b00000000 
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc2e err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if              
                     
                    d[0] = 0x62;                                    //A_VECM_COUNT (address of Vector debounce counter), write in Active or Standby
                    d[1] = 0b00000110;                              //with ODR at 100Hz, should equal ??mS debounce time or ??mS in Sleep
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc2f err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if 
                           
                   // Registers 0x63 - 0x68 are vector reference values which I'm leaving set to 0 because we want absolute measurements    
                                  
                    d[0] = 0x2b;                                    //CTRL_REG2 (address of control reg), write in Standby only
 //                   d[1] = 0b00001101;                              //Turns Auto-Sleep mode on and low-noise, low power
                    d[1] = 0b00001001;                              //Turns Auto-Sleep mode off (b/c it wasn't waking on int) and low-noise, low power
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc2g err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if    
                    
                    d[0] = 0x2c;                                    //CTRL_REG3 (address of Int control reg), write in Standby only
                    d[1] = 0b00000100;                              //Vector will wake chip from sleep, int are active high
  //                  d[1] = 0b00001000;                              //FFMT will wake chip from sleep, int are active high
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc2h err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if    
                        
                    d[0] = 0x2d;                                    //CTRL_REG4 (address of Int enable reg), write in Standby only
                    d[1] = 0b10000010;                              // Vector int enabled
 //                   d[1] = 0b00000100;                              // FFMT int enabled 
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc2i err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if            
                    //wait(0.2);  // people have had a problem here and needed a delay
                    
                    d[0] = 0x2e;                                    //CTRL_REG5 (Int routing reg), write in Standby only
                    d[1] = 0b00000100;                              // Make FFMT int output on pin INT1(PTC1) and Vector on INT2(PTD13)
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc2j err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if                  
                    
                    d[0] = 0x29;                                    //ASLP_Count (counter used to go to sleep reg), write in Standby only
                    d[1] = 0b00001010;                              // 10*320mS=3.2S of no inturrupts to go to sleep
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc2k err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if    
                    
                    d[0] = FXOS8700_CTRL_REG1;                     //CTRL_REG1, write in Standby only except for bit[0]
                    d[1] = 0b00011001;                              //Auto-Sleep mode on set to 50Hz, ODR set to 100Hz Puts device back into Active mode 
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc2L err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if  
                    break;
                }// end of case 2    
     
                case 3: {// configure for motion int only
                    char d[2]; 
                    d[0] = 0x2a;                                      //0x2a Config reg1
                    d[1] = 0x00;                                    //Put device in Standby mode
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc3a err",30,05); // Display "error" at x,y                  
                        wait(3.0); // display for 3 seconds
                    }//end if
                    
                    d[0] = 0x0e;                                    //XYZ_DATA_CFG (set full-scall range)
                    d[1] = 0b00000001;                              //Set data to default range of +/-2g for full range (2x0.488mg/LSB), High-pass filter off
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc3b err",30,05); // Display "error" at x,y      
                        wait(3.0); // display for 3 seconds
                    }//end if
                    
                    d[0] = 0x2a;                         //0x2a Config reg1, write in Standby only except for bit[0]
                    d[1] = 0b00011001;                    //Auto-Sleep mode on set to 50Hz, ODR set to 100Hz Puts device back into Active mode 
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc3c err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if  
                    break;
                }// end of case 3           
                                            
                 case 4: {// configure FFMT for free-fall event AND config for vector impact   
                    char d[2];       
                    d[0] = 0x2a;                                    //0x2a Config reg1,  
                    d[1] = 0x00;                                    //Put device in Standby mode
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc4a err",30,05); // Display "error" at x,y                  
                        wait(3.0); // display for 3 seconds
                    }//end if 
 
                    d[0] = 0x0e;                                    //XYZ_DATA_CFG (set full-scall range)
                    d[1] = 0b00000001;                              //Set data to +/-4g for full range (0.488mg/LSB), High-pass filter off
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc4b err",30,05); // Display "error" at x,y      
                        wait(3.0); // display for 3 seconds
                    }//end if
 /*
                    d[0] = 0x0a;                                    //TRIG_CFG (address of FIFO trigger config reg)
                    d[1] = 0b00000110;                              //Trigger on freefall and on Vector
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)" Step2 error ",30,05); // Display "error" at x,y      
                        wait(3.0); // display for 3 seconds
                    }//end if
  */                  
                    d[0] = 0x15;                                    //A_FFMT_CFG (address of Free fall trigger config reg), write in Standby only
                    d[1] = 0b00111000;                              //set to freefall, and look at all axis.
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc4c err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if
                       
                    d[0] = 0x17;                                    //A_FFMT_THS (address of Free fall threshold reg), write in Active or Standby
 //                   d[1] = 0b00001000;                                //set freefall threshold to about 756mg for now                   
                   d[1] = (uint8_t)(1000*Fall_Thresh/63);            //set freefall threshold - Resolution is 63mg/LSB, 0b111_1111 is maximum value
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc4d err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if  
                     
                    d[0] = 0x18;                                    //A_FFMT_COUNT (address of Free fall debounce counter), write in Active or Standby
                    d[1] = 0b00000110;                              //with ODR at 100Hz, should equal 60mS debounce time or 120mS in Sleep
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc4e err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if 
                                             
                    d[0] = 0x5f;                                    //A_VECM_CFG (address of Vector config reg), write in Standby only
                    d[1] = 0b00111000;                              //Use reference values, don't update ref, enable.
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc4f err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if
                       
                    d[0] = 0x60;                                    //A_VECM_MSB (address of Vector threshold reg), write in Active or Standby
 //                   d[1] = 0b00000111;                                //set impact threshold to less than 1g for now                   
                    d[1] = (uint8_t)((1000*Impact_Thresh/0.488f)/256);        //set MSB Impact threshold - Resolution is 0.488mg/LSB so 0.5g=1024.6 => MSB=0b00000100 LSB=0b00000000 
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc4g err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if  
           
                    d[0] = 0x61;                                    //A_VECM_LSB (address of Vector threshold reg), write in Active or Standby
//                    d[1] = 0b00000011;                                //set impact threshold to less than 1g for now                   
                    d[1] = (uint8_t)(1000*Impact_Thresh/0.488f);
                    d[1] = (uint8_t)(d[1]%256);  //set MSB Impact threshold - Resolution 0.488mg/LSB so 0.5g=1024.6 => MSB=0b00000100 LSB=0b00000000 
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc4h err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if             
                     
                    d[0] = 0x62;                                    //A_VECM_COUNT (address of Vector debounce counter), write in Active or Standby
                    d[1] = 0b00000100;                              //with ODR at 100Hz, 0x04 should equal 40mS debounce time or 80mS in 50Hz Sleep
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc4i err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if 
                           
                   // Registers 0x63 - 0x68 are vector reference values which I'm leaving set to 0 because we want absolute measurements    
                                  
                    d[0] = 0x2b;                                    //CTRL_REG2 (address of control reg), write in Standby only
 //                   d[1] = 0b00001101;                              //Turns Auto-Sleep mode on and low-noise, low power
                    d[1] = 0b00001001;                              //Turns Auto-Sleep mode off (b/c it wasn't waking on int) and low-noise, low power
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc4jerr",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if    
                    
                    d[0] = 0x2c;                                    //CTRL_REG3 (address of Int control reg), write in Standby only
                    d[1] = 0b00001100;                              //FFMT or Vector will wake chip from sleep, int are active high
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc4k err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if    
                        
                    d[0] = 0x2d;                                    //CTRL_REG4 (address of Int enable reg), write in Standby only
                    d[1] = 0b10000110;                              // FFMT and Vector int enabled
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc4L err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if            
                   // wait(0.2);  // people have had a problem here and needed a delay
                    
                    d[0] = 0x2e;                                    //CTRL_REG5 (Int routing reg), write in Standby only
                    d[1] = 0b00000100;                              // Make FFMT int output on pin INT1(PTC1) and Vector on INT2(PTD13)
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc4m err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if                  
                    
                    d[0] = 0x29;                                    //ASLP_Count (counter used to go to sleep reg), write in Standby only
                    d[1] = 0b00001010;                              // 10*320mS=3.2S of no inturrupts to go to sleep
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc4n err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if                  
                    
                    d[0] = 0x2a;                          //0x2a Config reg1, write in Standby only except for bit[0]
                    d[1] = 0b00011001;                    //Auto-Sleep mode on set to 50Hz, ODR set to 100Hz Puts device back into Active mode 
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"Acc4o err",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if   
                    break;
                }// end of case 4
                       
                case 10: {// reset IC 
                  char d[2]; 
                    d[0] = 0x2a;                          //0x2a Config reg1
                    d[1] = 0x00;                                    //Put device in Standby mode
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)" Step10a err",30,05); // Display "error" at x,y                  
                        wait(3.0); // display for 3 seconds
                    }//end if
                       
                    d[0] = 0x2b;                                //CTRL_REG2 
                    d[1] = 0b01000000;                          // set bit to force reset of FXOS8700 
                    if(i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)" Reset error ",30,05); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if    
                   // oled.Label((uint8_t *)"Acc_Reset",20,60); // Display "reset" at x,y
                    break;
                }// end case 10      
                
                case 11: {// wake for simple data read, was in stanby
                  char d[2];
                    d[0] = FXOS8700_CTRL_REG1;                     //Puts device in Standby mode just in case
                    d[1] = 0x00; 
                    i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2); 
                      
                    d[0] = 0x0e;                                    //XYZ_DATA_CFG (set full-scall range)
                    d[1] = 0b00000001;                              //Set data to +/-4g for full range (0.488mg/LSB), High-pass filter off
                    i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d,2);  
                                               
                    /*For lowest power ~8uA, set ODR-12.5Hz,(low-pwr accel mode) or 2uA in standby mode */        
                    d[0] = 0x2a;                          //0x2a Config reg1, write in Standby only except for bit[0]
                    d[1] = 0b00011001;                    //Auto-Sleep mode on set to 50Hz, ODR set to 100Hz Puts device back into Active mode 
                    i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d, 2);
                    break;
                }// end of case 11 
                
                case 12: {// put into standby for low power
                  char d[2]; 
                    d[0] = FXOS8700_CTRL_REG1;                     //Puts device in Standby mode
                    d[1] = 0x00; 
                    i2c_bus1.write(FXOS8700_I2C_ADDRESS_, d, 2);                       
                    /*For lowest power ~8uA, set ODR-12.5Hz,(low-pwr accel mode) or 2uA in standby mode */
                    break;
                }// end of case 11             
                
                case 20: {// read INT_Source to clear VECM int, shouldn't have to do this
            // This was not working for me but it was due to me using the wrong FXOS8700_I2C_ADDRESS_
                    char d[2];//, data_byte_[1]; 
                    d[0] = 0x0c;  // 0x0c is INT_Source Reg
                    i2c_bus1.write(FXOS8700_I2C_ADDRESS_,d,1,true); // "true" is needed to prevent stop
                    wait(0.01);
                    if(i2c_bus1.read(FXOS8700_I2C_ADDRESS_,d,1) == 1){ // read Who am I Reg for debug
                    sprintf(text_1," INT_Read_Err ");
                    oled.Label((uint8_t *)text_1,5,50); // Display error at x,y 
                    wait(1);  // wait 1 seconds
                    }//endif
                    break;
                }// end of case 20 
                
                   case 21: {// read A_FFMT_SRC reg to clear FFMT int, shouldn't have to do this
            // This was not working for me but it was due to me using the wrong FXOS8700_I2C_ADDRESS_
                    char d[2];//, data_byte_[1]; 
                    d[0] = 0x16;  // 0x16 is A_FFMT_SRC Reg
                    i2c_bus1.write(FXOS8700_I2C_ADDRESS_,d,1,true); // "true" is needed to prevent stop
                    wait(0.01);
                    if(i2c_bus1.read(FXOS8700_I2C_ADDRESS_,d,1) == 1){ // read Who am I Reg for debug
                    sprintf(text_1," INT_Read_Err ");
                    oled.Label((uint8_t *)text_1,5,50); // Display error at x,y 
                    wait(1);  // wait 1 seconds
                    }//endif
                    break;
                }// end of case 21 
                
                default: {
                    oled.Label((uint8_t *)" Mode? ",30,60); // Display "mode" at x,y
                    // unknown config
                    break;
                } 
}// end switch                

}// end accel_sensor_cconfig

/*****************************************************************************
Name: gyro_sensor_config()
Purpose: Used to set gyro IC's internal registers for chip level
interrupts and power modes
Inputs: int value from 0 to 256
Returns: None
******************************************************************************/

void gyro_sensor_config(uint8_t Num){ 
// use case switches here to configure for 
switch(Num) {                     
                case 0: {// put in standby
                    /*For lowest power ~2.8uA in standby mode */
                    char d[2];
                    d[0] = FXAS21002_CTRL_REG1;                       //CTRL_REG1=0x13
                    d[1] = 0b00001100;                                //puts device in standby mode and leaves ODR set to 100Hz
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"gyr_err0a",20,45); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if 
                    break;    
                }// end of case 0  
                
                case 1: {// Fall_Alert mode=1, put in active mode se we can read gyro measurments
                    char d[2];
                    d[0] = FXAS21002_CTRL_REG1;                       //CTRL_REG1=0x13
                    d[1] = 0x00;                                      //Puts device in standby mode  
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"gyr_err1a",20,45); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if   
                    d[0] = FXAS21002_CTRL_REG0;                       //CTRL_REG0=0x0d
                    d[1] = 0x00;                                       //sets FS =+/- 2000 dps
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"gyr_err1b",20,45); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if  
                    d[0] = FXAS21002_CTRL_REG1;                       //CTRL_REG1=0x13
                    d[1] = 0x0e;                                       //0x0e puts device in active mode with ODR = 100Hz
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"gyr_err1c",20,45); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if  
                    break;
                }// end of case 1
                
                case 3: {// Fall_Alert mode 3,  set up interupt, put in active mode
                    char d[2];
                    d[0] = FXAS21002_CTRL_REG1;                       //CTRL_REG1=0x13
                    d[1] = 0x00;                                      //0x08 puts device in standby mode  
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"gyr_err3",20,45); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if   
                    
                    // set RT_CFG reg 0x0e - Rate int config
                    d[0] = 0x0e;                                        //set RT_CFG reg 0x0e - Rate int config
                    d[1] = 0b00000111;                                      // enable x,y,z axis 
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"gyr_err3a",20,45); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if 
                      
                    // set RT_THS reg 0x10 - Rate Threshold value
                    d[0] = 0x10;                                        //set RT_THS reg 0x10 - Rate Threshold config
    //                d[1] = 0b00000111;                                   // bit7=couter mode(1=clr,0=dec), rate Tresh(dps)=(THS+1)*Sensitivity(dps/LSB
                    // Sensitivity(dps/LSB), we should have mdps/LSB=62.50 or a full range of +/- 2000 dps
                    // Movement_Thresh 50 dps=(THS+1)*256*Sensitivity(dps/LSB) => THS = Movement_Thresh/(16.0f)-1
                    // We specified that 50 dps was the magnitude some of all 3 axis so THS is 1/3 of that
                    d[1] = (uint8_t)((Movement_Thresh/(3*16.0f))-1);  // Movement_Thresh 50 dps setting Tresh(dps)=(THS+1)*256*Sensitivity(dps/LSB)
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"gyr_err3b",20,45); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if 
                    
                    // set RT_COUNT reg 0x11 - Rate Threshold counter
                    d[0] = 0x11;                                    //set RT_COUNT reg 0x11 - Rate Threshold counter
                    //  d[1] = 0b10000000;                            // debounce count value (Count=10, ODR=100Hz => 100mS)
                    d[1] = (uint8_t)(Min_Movement_Time/0.01f);      // debounce count value (at ODR=100Hz, each count = 10mS) 2.55s=255
                    // need to calculate and store this value
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                    oled.Label((uint8_t *)"gyr_err3c",20,45); // Display "error" at x,y 
                    wait(3.0); // display for 3 seconds
                    }//end if                   
                    
                    // set CTRL_REG2 reg 0x14 - Int config
                    d[0] = 0x14;                                        //set CTRL_REG2 reg 0x14 - Int config
                    d[1] = 0b01110000;                                  // enable RT &FIFO interupts, int=act_low, push/pull
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                    oled.Label((uint8_t *)"gyr_err3d",20,45); // Display "error" at x,y 
                    wait(3.0); // display for 3 seconds
                    }//end if                         
                    
                    // set CTRL_REG3 reg 0x15 - Auto inc config, external power, FSR <=don't need?
                    d[0] = 0x15;                                       //CTRL_REG3 reg 0x15
                    d[1] = 0x00;                                       //Auto inc config, external power, FSR
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"gyr_err3e",20,45); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if  
             
                    d[0] = FXAS21002_CTRL_REG0;                       //CTRL_REG0=0x0d
                    d[1] = 0x00;                                       //sets FS=0,mdps/LSB=62.50 => +/- 2000 dps
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"gyr_err3f",20,45); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if  
                    d[0] = FXAS21002_CTRL_REG1;                       //CTRL_REG1 0x13 - Op mode, ODR selection, reset
                    d[1] = 0b00001110;                                //0x0e puts device in active mode and sets ODR to 100Hz
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"gyr_err3g",20,45); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if  
                    break;
                }// end of case 3

                case 10: {// reset Gyro IC 
                  char d[2];    
                    d[0] = FXAS21002_CTRL_REG1;                       //CTRL_REG1 0x13 - Op mode, ODR selection, reset
                    d[1] = 0b01000000;                                //resets IC
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"gyr_err10a",20,45); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if   
                   // oled.Label((uint8_t *)"G_Reset ",30,45); // Display "reset" at x,y
                    break;
                }// end case 10  

                case 11: {//  set sensor to active to read gyro measurments
                    char d[2];
                    d[0] = FXAS21002_CTRL_REG1;                       //CTRL_REG1=0x13
                    d[1] = 0b00001110;                                //0x0e puts device in active mode with ODR = 100Hz
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"gyr_err11a",20,45); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if  
                    break;
                }// end of case 11

                case 12: {// put in standby
                    /*For lowest power ~2.8uA in standby mode */
                    char d[2];
                    d[0] = FXAS21002_CTRL_REG1;                       //CTRL_REG1=0x13
                    d[1] = 0b00001100;                                //puts device in standby mode and leaves ODR set to 100Hz
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"gyr_err12a",20,45); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if 
                    break;    
                }// end of case 12  
                
                case 13: {// put in standby then back to active, to clear counter
                    /*For lowest power ~2.8uA in standby mode */
                    char d[2];
                    d[0] = FXAS21002_CTRL_REG1;                       //CTRL_REG1=0x13
                    d[1] = 0b00001100;                                //puts device in standby mode and leaves ODR set to 100Hz
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"gyr_err12a",20,45); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if 
                    d[1] = 0b00001110;                                //0x0e puts device in active mode with ODR = 100Hz
                    if(i2c_bus1.write(FXAS21002_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"gyr_err11a",20,45); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if  
                    
                    break;    
                }// end of case 13 

                default: {
                    oled.Label((uint8_t *)"Gyro_Mode?",20,45); // Display "mode" at x,y
                    // unknown config
                    break;
                } 
    }// end switch    
}// end gyro_sensor_config

/*****************************************************************************
Name: press_config()
Purpose: Used to set pressure sensor's internal registers for power modes
Inputs: int value from 0 to 256
Returns: None
******************************************************************************/

void press_config(uint8_t Num){
// use case switches here to configure
switch(Num) {                     
                case 0: {// put in standby (AKA powered down) mode
                    //For lowest power ~2.8uA in standby mode, sensor should default to this after reset 
                    char d[2];
                    d[0] = 0x26;                                      //CTRL_REG1=0x26
                    d[1] = 0x00;                                      //Puts device in powered down mode
                    if(i2c_bus1.write(0xC0, d,2) ==1){                 // 0xc0 is MPL3115A2 address
                        oled.Label((uint8_t *)"press_err0a",20,30);     // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if 
                    break;    
                }// end of case 0  
                 
                default: {
                    oled.Label((uint8_t *)"PRESS_Mode?",20,45); // Display "mode" at x,y
                    // unknown config
                    break;
                } 
    }// end switch    
}// end press_config

/*****************************************************************************
Name: MAX30101_test_config()
Purpose: Used to test operation of the MAX30101 heart-rate sensor
Inputs: int value from 0 to 256
Returns: None
******************************************************************************/
void MAX30101_test_config(uint8_t Num){
// use case switches here to configure
switch(Num) {                     
                case 0: {// test 
                    char d[2] = {0xfe, 0x07};
                    if(i2c_bus0.read(0xae, d, 2) == 1){ // read RevID value 0-255
                        sprintf(text_1,"M_R_Er %i %i",d[0],d[1]);
                        oled.Label((uint8_t *)text_1,5,16); // Display error at x,y 
                    }//end if
                    else{
                        sprintf(text_1,"M_R_data %i %i",d[0],d[1]);
                        oled.Label((uint8_t *)text_1,5,16); // Display good data at x,y
                        }
                    wait(1);  // wait 1 seconds
                    d[0] = 0x09;  //  Mod_conf reg - SHDN, reset, modes
                    d[1] = 0b00000111;   //  set mode to red, green and/or IR LEDs
                    if(i2c_bus0.write(0xaf, d, 1) ==1){; // "true" is needed to prevent stop, MAX30101 address is 0xae but left shifted
                        oled.Label((uint8_t *)"MAX_W_err0a",5,30);     // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if 
                    wait(5); // wait 5 seconds
                    
                    /*
                    d[0] = 0xfe;                                      //lets try to read revID value 0-255
                    d[1] = 0x00;                                      //Puts device in powered down mode
                    if(i2c_bus0.write(0xae<<1, d,2) ==1){             // MAX30101 address is 0xae but left shifted
                        oled.Label((uint8_t *)"Max_err0a",20,30); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if 
                    */
                    break;    
                }// end of case 0  
               
               
                case 10: {// reset
                    if(maxim == 0)
                    {
                    }
                    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  
                
                default: {
                    oled.Label((uint8_t *)"MAX_Mode?",20,45); // Display "mode" at x,y
                    // unknown config
                    break;
                } 
    }// end switch    
}// end light_config

/*****************************************************************************
Name: light_config()
Purpose: Used to set ambient light sensor's internal registers for power modes
Inputs: int value from 0 to 256
Returns: None
******************************************************************************/
/*
void light_config(uint8_t Num){
// use case switches here to configure
switch(Num) {                     
                case 0: {// put in standby (AKA powered down) mode
                    //For lowest power ~2.8uA in standby mode, sensor should default to this after reset 
                    char d[2];
                    d[0] = TSL2561_CONTROL;                                      //CTRL_REG0=0x00
                    d[1] = 0x00;                                      //Puts device in powered down mode
                    if(i2c_bus0.write(TSL2561_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"light_err0a",20,30); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if 
                    break;    
                }// end of case 0  
                
                case 1: {// put in active
                    char d[2];
                    d[0] = TSL2561_CONTROL;                                      //CTRL_REG=0x00
                    d[1] = 0x03;                                      //Puts device in powered up mode
                    if(i2c_bus0.write(TSL2561_I2C_ADDRESS_, d,2) ==1){
                        oled.Label((uint8_t *)"light_err0a",20,30); // Display "error" at x,y 
                        wait(3.0); // display for 3 seconds
                    }//end if 
                    break;    
                }// end of case 1  
                
                default: {
                    oled.Label((uint8_t *)"LGHT_Mode?",20,45); // Display "mode" at x,y
                    // unknown config
                    break;
                } 
    }// end switch    
}// end light_config
*/

/*****************************************************************************
Name: update_display_date
Purpose: Updating display data without updating any data labels.  This keeps
measurements and time values current while reducing screen flicker.
******************************************************************************/
void update_display_date(void)
{
    oled_text_properties_t textProperties = {0};  // Need these to change font color
    oled.GetTextProperties(&textProperties);      // Need these to change font color
    __disable_irq();    // Disable all Interrupts
    
        switch(Screen_Num) {
    case 0: {// Main Screen
            HexiwearBattery battery;
            battery.sensorOn();  
            if (battery.isBatteryCharging()) {
            textProperties.fontColor = COLOR_GREEN;
            oled.SetTextProperties(&textProperties);  
                     
            sprintf(text_1, "%i%%+", batt_per_level);
  //          Screen_Timer.attach(&timout_timer,(SCRN_TIME));// Reset/restart ticker timer for OLED while fully charged
            } else {
            sprintf(text_1, "%i%%", batt_per_level);
            }
            oled.TextBox((uint8_t *)text_1,60,0,35,15); //show level value of battery in a 35px by 15px text box at x=60, y=0

            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);  
           
// added real time and date information            
            char buffer[32];
            time_t seconds = time(NULL);
            strftime(buffer,32, "%a,%d %m %Y.%H:%M:%S\r", localtime(&seconds));
//        sprintf(text_1,"%c%c/%c%c/%c%c%c%c ",buffer[7],buffer[8],buffer[4],buffer[5],buffer[10],buffer[11],buffer[12],buffer[13]);
//        oled.Label((uint8_t *)text_1,20,20);// Date at x,y
            sprintf(text_1,"%c%c:%c%c:%c%c ",buffer[15],buffer[16],buffer[18],buffer[19],buffer[21],buffer[22]);

    
            textProperties.font = OpenSans_12x18_Regular;  //  Max Width of Character  = 12px, Max Height of Character = 18px 
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties); 
            oled.Label((uint8_t *)text_1,25,40);// Time at x,y
            textProperties.font = OpenSans_10x15_Regular;  //  Max Width of Character  = 10px, Max Height of Character = 15px 
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            
            Heat_Index_Calculation();
            sprintf(text,"%i",heat_index);
            //oled.TextBox((uint8_t *)text,3,80,15,15); //show HI in a 15px by 15px text box at x=3, y=80
            oled.Label((uint8_t *)text,3,80);// HI at x,y
            
            textProperties.fontColor = COLOR_GRAY;
            if(Fall_Alert == 1){
                textProperties.fontColor = COLOR_GREEN; // is Fall protection on?
            }
            if(Fall_Alert == 1 && Led_clk1 == 1){
                textProperties.fontColor = COLOR_YELLOW; // is Fall detected? 
            }       
            if(Fall_Alert == 1 && Led_clk1 == 1 && Led_clk2 == 1){
                textProperties.fontColor = COLOR_RED; // is impact detected? 
            }       
            oled.SetTextProperties(&textProperties); 
            oled.Label((uint8_t *)"AFP",3,0);  //Display "AFP" at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            if(Heart_Rate_Mode == 1) {
                sprintf(text,"%i  ",Heart_Rate);
                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 *)text,35,60);
                textProperties.fontColor = COLOR_WHITE;
                oled.SetTextProperties(&textProperties);
               
            }
            
            break;
        }// end case 0
        
        case 7: {// Heart Rate Zone
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            sprintf(display_buff, "%u  ", Heart_Rate);
             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,43,25); // 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
            oled.Label((uint8_t *)display_buff,43,45); // Display at x,y
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);

            break;
        }// end case 7
                     
            case 21: {// Fall Alert Diagnostic Screen
            if(Fall_Alert_Mode == 0){
                fall_config(11); // turn accel sensor to active mode to take a reading, may take 80mS to 300mS
            }
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            gyro.acquire_gyro_data_dps(Gyro_Data);
            Gyro_Mag = (abs(Gyro_Data[0])+abs(Gyro_Data[1])+abs(Gyro_Data[2]));
            sprintf(text_1," %4.0f D/S  ",Gyro_Mag);
            oled.Label((uint8_t *)text_1,37,60);// text_1 at x,y
            
            accel.acquire_accel_data_g(Accel_Data);
            if(Fall_Alert_Mode == 0){
                fall_config(12); // turn accel sensor back to standby
            }
            Accel_Mag = 2*sqrt(((Accel_Data[0]*Accel_Data[0])+(Accel_Data[1]*Accel_Data[1])+(Accel_Data[2]*Accel_Data[2])));
            sprintf(text_1," %2.2f g  ",Accel_Mag);
            oled.Label((uint8_t *)text_1,39,40);// text_1 at x,y
            if(Accel_Mag > Fall_Thresh + 0.05f && Led_clk2 == 1){// are we stuck in limbo?
            fall_det_end(); 
            }
            break;
        }//end case 21 
        case 31: {
            sprintf(display_buff, "%u   ", Heart_Rate); // Convert int to char to display
            textProperties.fontColor = COLOR_RED;
            oled.SetTextProperties(&textProperties);
            oled.Label((uint8_t *)display_buff, 40, 25);
            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);
            }
            sprintf(display_buff, "%u", Current_Zone); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 71, 45);
            if(Prev_Zone == 1) {
                textProperties.fontColor = COLOR_YELLOW;
                oled.SetTextProperties(&textProperties);
            } else if(Prev_Zone == 2) {
                textProperties.fontColor = COLOR_BLUE;
                oled.SetTextProperties(&textProperties);
            } else if(Prev_Zone == 3) {
                textProperties.fontColor = COLOR_GREEN;
                oled.SetTextProperties(&textProperties);
            } else if(Prev_Zone == 4) {
                textProperties.fontColor = COLOR_RED;
                oled.SetTextProperties(&textProperties);
            }
            sprintf(display_buff, "%u", Prev_Zone); // Convert int to char to display
            oled.Label((uint8_t *)display_buff, 71, 60);
            textProperties.fontColor = COLOR_WHITE; //Change font to white
            oled.SetTextProperties(&textProperties);//Implement color change
            break;   
        }   
        case 33: {
            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 72: {// BlueTooth on/off
            textProperties.fontColor = COLOR_WHITE;
            oled.SetTextProperties(&textProperties);
            if (BLE_On == 1) {
                /* re-Display Bond Pass Key in a 90px by 18px textbox at x=0,y=40 */
                sprintf(text,"%d", kw40z_device.GetPassKey());
                oled.TextBox((uint8_t *)text,10,45,80,18);
            } else {
                // do nothing, don't update when not active
            }

            break;
        }// end case 72
            default: {
                    // do nothing for other screens
             break;
                } 
    }// end switch   
    __enable_irq();     // Enable all Interrupts 
}// end of update_display_date


/*****************************************************************************
Name: txTask()
Purpose: HexiHeart Connecction
Inputs: None
Returns: None
******************************************************************************/

void txTask(void)// we're not really using this because we arn't always transmitting
{
    while (true) {
        // update sensor data
        
        /*Notify Hexiwear App that it is running Sensor Tag mode*/
        kw40z_device.SendSetApplicationMode(GUI_CURRENT_APP_SENSOR_TAG);
        
        /* send sensor data
        
        //Send Battery Level 
        kw40z_device.SendBatteryLevel(battery);
               
        //Send Ambient Light Level 
        kw40z_device.SendAmbientLight(light);
        
        //Send Humidity 
        kw40z_device.SendHumidity(humidity);
        
        //Send Temperature  
        kw40z_device.SendTemperature(temperature);

        //Send Pressure 
        kw40z_device.SendPressure(pressure);
        
        //Send Mag,Accel,Gyro Data. 
        kw40z_device.SendGyro(x,y,z);
        kw40z_device.SendAccel(z,x,y);
        kw40z_device.SendMag(y,z,x);
        
        */  
        Thread::wait(1000);  
    }// end while
}// end TxTask


/*****************************************************************************
Name: WDT_Timeout()
Purpose: Interrupt routine used by Watch Dog timer Ticker. 
Note that there are a few ways to implement a WDT. The best would be an external 
circuit that resets the K46 if it became unresponsive. The next best would be using 
the internal WDT that is built into microprocessor. And lastly there is this 
method, using a Ticker/timer.
Inputs: None
Returns: None
******************************************************************************/
void WDT_Timeout(){ // turn off display mode
    Screen_Timer.attach(&timout_timer,(SCRN_TIME));//Is this sufficient to reset/restart ticker timer for OLED?
    if (OLED_ON == 0) {
        OLED_ON = 1; // Screen was off, set to On
    }
    oled.DimScreenOFF();
    __disable_irq();    // Disable all Interrupts
    oled_text_properties_t textProperties = {0};  // Need these to change font color
    oled.GetTextProperties(&textProperties);      // Need these to change font color
    oled.FillScreen(COLOR_BLACK); // Clear screen
    textProperties.font = OpenSans_12x18_Regular;  //  Max Width of Character  = 12px, Max Height of Character = 18px 
    textProperties.fontColor = COLOR_WHITE;
    oled.SetTextProperties(&textProperties); 
    oled.Label((uint8_t *)"WatchDog",10,30); // Display "Back" at x,y
    oled.Label((uint8_t *)" Reset!",20,55); // Display "Back" at x,y
    wait(0.1);// display for 100ms

    NVIC_SystemReset(); // software reset
}//end WDT_Timeout routine


/*****************************************************************************
Name: CLRWDT()
Purpose: Routine to clear/reset Watch Dog timer Ticker
Inputs: None
Returns: None
******************************************************************************/
void CLRWDT(){ // turn off display mode
    WDT_Timer.attach(&WDT_Timeout,(WDT_TIME));//re-attach/reset WDT
}//end WDT_Timeout routine


/*****************************************************************************
Name: PassKey()
Purpose: Interrupt routine called when MK46 recieves Passkey from KW40
Inputs: None
Returns: None
******************************************************************************/
void PassKey(void)// 
{
    Screen_Timer.attach(&timout_timer,(SCRN_TIME));//Is this sufficient to reset/restart ticker timer for OLED?
    if (OLED_ON == 0) {
        OLED_ON = 1; // Scree was off, set to On
    }
    oled.DimScreenOFF();
        Screen_Num = 72;  //Change to screen BLE screen 72
        StartHaptic();
        update_display();
}// PassKey

/*****************************************************************************
Name: UpDate_Ave()
Purpose: Routine called to update rolling average of slow changing sensor readings
Inputs: Temp/humid sensor readings and battery measurement
Returns: updated global variables
******************************************************************************/
void UpDate_Ave(void)//
{
    //int i = 4; // used in rolling average
    HexiwearBattery battery;
    battery.sensorOn();  
    if(Ave_Num == 0.0f){  
    // this is first measurement since reboot         
    batt_per_level = (uint8_t)battery.readLevelPercent();
    sample_ftemp = temphumid.sample_ftemp();
    sample_humid = temphumid.sample_humid();
    }//end if
    else{
    // updated measurments on a rolling average basis: 1/4 new measurement to 3/4 running average
    batt_per_level = (uint8_t)((Ave_Num-1)*batt_per_level/Ave_Num + battery.readLevelPercent()/Ave_Num); // do calculation as a float but return an uint8
    sample_ftemp = (int)(Ave_Num-1)*sample_ftemp/Ave_Num + temphumid.sample_ftemp()/Ave_Num;      
    sample_humid = (int)(Ave_Num-1)*sample_humid/Ave_Num + temphumid.sample_humid()/Ave_Num;      
        }//end else
    Ave_Num = Ave_Num + 1;
    if(Ave_Num > MAX_AVE_NUM){
        Ave_Num = MAX_AVE_NUM;  //set limit 
        }    
}// 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 if(simulation_stage == 5)
    {
        Heart_Rate = HR_Zone2[0] + rand() %( HR_Zone2[1] - HR_Zone2[0] + 1);
    }
    else if(simulation_stage == 6)
    {
        Heart_Rate = HR_Zone1[0] + rand() %( HR_Zone1[1] - HR_Zone1[0] + 1);
    }
    else 
    {
        rand_stage = rand() % 4 + 1;
        if(rand_stage == 1)
        {
            Heart_Rate = HR_Zone1[0] + rand() %( HR_Zone1[1] - HR_Zone1[0] + 1);
        }
        else if(rand_stage == 2)
        {
            Heart_Rate = HR_Zone2[0] + rand() %( HR_Zone2[1] - HR_Zone2[0] + 1);
        }
        else if(rand_stage == 3)
        {
            Heart_Rate = HR_Zone3[0] + rand() %( HR_Zone3[1] - HR_Zone3[0] + 1);    
        }
        else if(rand_stage == 4)
        {
            Heart_Rate = HR_Zone4[0] + rand() %( HR_Zone4[1] - HR_Zone4[0] + 1);
        }
    }
    simulation_stage++;
    Determine_Current_Zone();  
    //update_display();  // I don't think we should update display, let update_data() do that
}

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();
    RED_Led = LED_OFF; 
    GRN_Led = LED_OFF;
    BLU_Led = LED_OFF;
}

void processHeartRate(void)
{
    
    uint32_t peak;
 
    for(int i = 0; i < 100; i++)
    {
        hr_data[i] = readFIFO();
    }
  
    
    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;

    }
    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;
}