Software

Code done by 1/21/10

The code below shows how we changed the alarm function of the watch to check if the current time is within the window AND the current heart rate is above 65 bpm (our REM heart rate level for testing). With this updated code the alarm should sound while both of those are true.

// Global Variable section
struct alarm sAlarm;
struct window sWindow;
u8 REMRATE = 65;

// Extern section

// @fn          clearalarmData
// @brief       Resets alarmData to 06:30
// @param       none
// @return      none

void reset_alarm(void) 
{
// Default alarm time 06:30
sAlarm.hour   = 06;
sAlarm.minute = 30;

// Alarm is initially off	
sAlarm.duration = ALARM_ON_DURATION;
sAlarm.state 	= ALARM_DISABLED;
      
// Default window time 06:25
sWindow.hour   = 06;
sWindow.minute = 25;

// Window is initially off	
sWindow.state = WINDOW_OFF;
}

// @fn          check_alarm
// @brief       Check if current time matches alarm time
// @param       none
// @return      none

void check_alarm(void) 
{
// Return if alarm is not enabled
if (sAlarm.state != ALARM_ENABLED) return;

// Compare current time and alarm time
// Start with minutes - only 1/60 probability to match
if (sTime.minute == sAlarm.minute)
{
	if (sTime.hour == sAlarm.hour)
	{
		// Indicate that alarm is on
		sAlarm.state = ALARM_ON;
	}
}
// Compare current time and window time
// Start with minutes - only 1/60 probability to match
if (sTime.minute == sWindow.minute)
{
	if (sTime.hour == sWindow.hour)
	{
		// Indicate that time is within window
		sWindow.state = WINDOW_ON;
	}
}
      // Return if window is not enabled
if (sWindow.state != WINDOW_ON) return;

      // Stores the current heart rate
u8 heartrate = BRRX_GetHeartRate_u8();
      
      // Checks if heart rate is at or above the rem level
      if (heartrate >= REMRATE)
      sAlarm.state = ALARM_ON;
}
// Init value index
select = 0;	
	
// Loop values until all are set or user breaks	set
while(1) 
{
	// Idle timeout: exit without saving 
	if (sys.flag.idle_timeout) break;
	
	// M1 (short): save, then exit 
	if (button.flag.m1) 
	{
		// Store local variables in global alarm time
		sAlarm.hour = hours;
		sAlarm.minute = minutes;
                      // Sets window to 5 minutes before alarm time (this is temporary for testing purposes)
                      sWindow.hour = hours;
                      sWindow.minute = minutes - 5;
		// Set display update flag
		display.flag.line1_full_update = 1;
		break;
	}

	switch (select)
	{
		case 0:		// Set hour
                                      set_value(&hours, 2, 0, 0, 23, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L1_3_2, display_hours1);
                                      select = 1;
                                      break;

		case 1:		// Set minutes
                                      set_value(&minutes, 2, 0, 0, 59, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L1_1_0, display_value1);
                                      select = 0;
                                      break;
	}
}

Code added or changed by 1/25/10

The code below shows how we implemented a user definable window begin and end time. We also changed some of the display code below to allow the user to view both the window start time and the alarm time simultaneously on the top and bottom lines of the LCD screen.

void mx_alarm(u8 line)
{
u8 select;
s32 hours;
s32 minutes;
      s32 window_hours;
      s32 window_minutes;
u8 * str;

// Clear display
clear_display_all();
// Keep global values in case new values are discarded
hours 		= sAlarm.hour;
minutes 	= sAlarm.minute;
      window_hours    = sWindow.hour;
      window_minutes  = sWindow.minute;
// Display HH:MM (LINE1) (This displays the alarm time)
str = itoa(hours, 2, 0);
display_chars(LCD_SEG_L1_3_2, str, SEG_ON);
display_symbol(LCD_SEG_L1_COL, SEG_ON);

str = itoa(minutes, 2, 0);
display_chars(LCD_SEG_L1_1_0, str, SEG_ON);

// Display "ALARM" (LINE2)
//display_chars(LCD_SEG_L2_4_0, (u8 *)"ALARM", SEG_ON);
      
      // Display HH:MM (LINE2) (This displays the window time)
      str = itoa(window_hours, 2, 0);
      display_chars(LCD_SEG_L2_3_2, str, SEG_ON);
display_symbol(LCD_SEG_L2_COL0, SEG_ON);

str = itoa(window_minutes, 2, 0);
display_chars(LCD_SEG_L2_1_0, str, SEG_ON);
     
// Init value index
select = 0;	
	
// Loop values until all are set or user breaks	set
while(1) 
{
	// Idle timeout: exit without saving 
	if (sys.flag.idle_timeout) break;
	
	// M1 (short): save, then exit 
	if (button.flag.m1) 
	{
		// Store local variables in global alarm time and window time
		sAlarm.hour = hours;
		sAlarm.minute = minutes;
                      sWindow.hour = window_hours;
                      sWindow.minute = window_minutes;
                      // Sets window to 5 minutes before alarm time (this is temporary for testing purposes)
                      // sWindow.hour = hours;
                      // sWindow.minute = minutes - 5;
                      
		// Set display update flag
		display.flag.line1_full_update = 1;
                      display.flag.line2_full_update = 1;
		break;
	}
	switch (select)
	{
		case 0:		// Set hour
                                      set_value(&hours, 2, 0, 0, 23, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L1_3_2, display_hours1);
                                      select = 1;
                                      break;
		case 1:		// Set minutes
                                      set_value(&minutes, 2, 0, 0, 59, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L1_1_0, display_value1);
                                      select = 2;
                                      break;
                      
		case 2:		// Set window_hour
                                      set_value(&window_hours, 2, 0, 0, 23, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L2_3_2, display_hours1);
                                      select = 3;
                                      break;
		case 3:		// Set window_minutes
                                      set_value(&window_minutes, 2, 0, 0, 59, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L2_1_0, display_value1);
                                      select = 0;
                                      break;
	}
}

// Clear button flag
button.all_flags = 0;

// Indicate to display function that new value is available
display.flag.update_alarm = 1;
}

Code added or changed by 1/27/10

This code shows the implementation of our average algorithm.

      void calc_avg(void) 
      {
      // Makes sure that the watch is picking up a heart rate before it calculates the average
      if (BRRX_GetHeartRate_u8() > 0)
      {
              // Calculates the current average heart rate
        sum = sum + BRRX_GetHeartRate_u8();
              data_num++;
        average = sum / data_num;
      }
      }
void check_alarm(void) 
{
// Return if alarm is not enabled
if (sAlarm.state != ALARM_ENABLED) return;

// Compare current time and alarm time
// Start with minutes - only 1/60 probability to match
if (sTime.minute == sAlarm.minute)
{
	if (sTime.hour == sAlarm.hour)
	{
		// Indicate that alarm is on
		sAlarm.state = ALARM_ON;
	}
              else
              {
                      // Calculates the current average heart rate
                      calc_avg();  
              }
}
      else
      {
              // Calculates the current average heart rate
              calc_avg();
      }
      
// Compare current time and window time
// Start with minutes - only 1/60 probability to match
if (sTime.minute == sWindow.minute)
{
	if (sTime.hour == sWindow.hour)
	{
		// Indicate that time is within window
		sWindow.state = WINDOW_ON;
	}
}
      // Return if window is not enabled
if (sWindow.state != WINDOW_ON) return;

      // Stores the current heart rate
u8 heartrate = BRRX_GetHeartRate_u8();
      
      // Checks if heart rate is above the average
      if (heartrate > average)
      sAlarm.state = ALARM_ON;
}

We had to find optimal spots in the code to reset the global variable that are used in the calc_avg() function back to zero. This way you can set the alarm again and the previous average will not affect your new average.

void stop_alarm(void) 
{
// Indicate that alarm is enabled, but not active
sAlarm.state = ALARM_ENABLED;

// Stop buzzer
stop_buzzer();
      
      // Resets the values for calculating the average heart rate
      average = 0;
      sum = 0;
      data_num = 0;
}
void sx_alarm(u8 line)
{
// S1: Alarm on, off
if(button.flag.s1)
{
	// Toggle alarm state
	if (sAlarm.state == ALARM_DISABLED)		
	{
		sAlarm.state = ALARM_ENABLED;
                      
                      // Resets the values for calculating the average heart rate
                      average = 0;
                      sum = 0;
                      data_num = 0;
		
		// Show "  on" message 
		message.flag.prepare = 1;
		message.flag.type_alarm_on = 1;
		
//			// Set alarm icon
//			display_symbol(LCD_ICON_ALARM, SEG_ON_BLINK_OFF);
	}
	else if (sAlarm.state == ALARM_ENABLED)	
	{
		sAlarm.state = ALARM_DISABLED;
                      
                      // Resets the values for calculating the average heart rate
                      average = 0;
                      sum = 0;
                      data_num = 0;
		// Show "  off" message 
		message.flag.prepare = 1;
		message.flag.type_alarm_off = 1;
		
//			// Clear alarm icon
//			display_symbol(LCD_ICON_ALARM, SEG_ON_BLINK_ON);
	}
}
}
 
Back to top
projects/realeasymorning/code.txt · Last modified: 2010/01/28 00:32 by lespaul
 
 
chimeric.de = chi`s home Creative Commons License Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0