Exemple #1
0
// *************************************************************************************************
// @fn          reset_altitude_measurement
// @brief       Reset altitude measurement.
// @param       none
// @return      none
// *************************************************************************************************
void reset_altitude_measurement(void)
{
    // Menu item is not visible
    sAlt.state 		= MENU_ITEM_NOT_VISIBLE;

    // Clear timeout counter
    sAlt.timeout	= 0;

    // Set default altitude value
    sAlt.altitude		= 0;

    // Pressure sensor ok?
    if (ps_ok)
    {
        // Initialise pressure table
        init_pressure_table();

        // Do single conversion
        start_altitude_measurement();
        stop_altitude_measurement();

        // Apply calibration offset and recalculate pressure table
        if (sAlt.altitude_offset != 0)
        {
            sAlt.altitude += sAlt.altitude_offset;
            update_pressure_table(sAlt.altitude, sAlt.pressure, sAlt.temperature);
        }
    }
}
Exemple #2
0
// *************************************************************************************************
// @fn          reset_altitude_measurement
// @brief       Reset altitude measurement.
// @param       none
// @return      none
// *************************************************************************************************
void reset_altitude_measurement(void)
{
   // Set default values
   sAlt.on = 0;
   sAlt.altitude = 0;
   sAlt.temperature_C = 0;
   sAlt.temperature_C_offset = 0;

   // Pressure sensor ok?
   if (ps_ok)
   {
      // Initialise pressure table
      init_pressure_table();

      // Do single conversion
      start_altitude_measurement();
      stop_altitude_measurement();

      // Apply calibration offset and recalculate pressure table
      if (sAlt.altitude_offset != 0)
      {
         sAlt.altitude += sAlt.altitude_offset;
         update_pressure_table(sAlt.altitude, sAlt.pressure, sAlt.temperature_K);
      }
   }
}
Exemple #3
0
// *************************************************************************************************
// @fn          altitude_accumulator_start
// @brief       Initialises the altitude accumulator function
// @param       none
// @return      none
// *************************************************************************************************
void altitude_accumulator_start (void)
{
    s32 temp;

    alt_accum__accumtotal = 0;		// So far total upwards vertical accumulation is zero
    alt_accum_direction = 1;		// start off by assuming we're heading uphill

    // Now let's get 4 altitude readings, then average them, to obtain our current altitude
    start_altitude_measurement();
    stop_altitude_measurement();
    temp = sAlt.altitude;				// first reading
    /* start_altitude_measurement();
       stop_altitude_measurement();
       temp += sAlt.altitude;			// second reading
       start_altitude_measurement();
       stop_altitude_measurement();
       temp += sAlt.altitude;			// third reading
       start_altitude_measurement();
       stop_altitude_measurement();
       temp += sAlt.altitude;			// fourth reading
       temp = temp >> 2;				// divide result by 4 = our current altitude */

    alt_accum_startpoint = temp;		// the altitude the user zeroed the accumulator at
    alt_accum_lastpeakdip = temp;		// altitude of the last dip (in this case, as we assume we're going uphill)
    alt_accum_prevalt = temp;		// previous altitude value
    alt_accum_max = temp;			// maximum altitude we've encountered so far
}
// *************************************************************************************************
// @fn          reset_altitude_measurement
// @brief       Reset altitude measurement.
// @param       none
// @return      none
// *************************************************************************************************
void reset_altitude_measurement(void)
{
    // Show altitude
    PressDisplay = DISPLAY_DEFAULT_VIEW;
    // Offset for Ambient pressure
    AmbientPressureOffset = AMBIENT_PRESSURE_OFFSET_DEFAULT;
    
    // Menu item is not visible
    sAlt.state      = MENU_ITEM_NOT_VISIBLE;

    // Clear timeout counter
    sAlt.timeout    = 0;
    
    // Set default altitude value
    sAlt.altitude       = 0;
        
    // Pressure sensor ok?
    if (ps_ok)
    {
        // Initialise pressure table
        init_pressure_table();
        
        // Do single conversion
        start_altitude_measurement();
        stop_altitude_measurement();    

        // Apply calibration offset and recalculate pressure table
        if (sAlt.altitude_offset != 0)
        {
            sAlt.altitude += sAlt.altitude_offset;
            update_pressure_table(sAlt.altitude, sAlt.pressure, sAlt.temperature);
        }
    }
}
Exemple #5
0
// *************************************************************************************************
// @fn          reset_altitude_measurement
// @brief       Reset altitude measurement.
// @param       none
// @return      none
// *************************************************************************************************
void reset_altitude_measurement(void)
{
	sAlt.state = MENU_ITEM_NOT_VISIBLE;
	sAlt.timeout = 0;
	sAlt.altitude = 0;
	sAlt.mode = ALTITUDE_REGULAR;

	// Pressure sensor ok?
	if (ps_ok)
	{
		// Do single conversion
		start_altitude_measurement();
		stop_altitude_measurement();
	}
}
Exemple #6
0
// *************************************************************************************************
// @fn          reset_altitude_measurement
// @brief       Reset altitude measurement.
// @param       none
// @return      none
// *************************************************************************************************
void reset_altitude_measurement(void)
{

    // Clear timeout counter
    sAlt.timeout = 0;
    // Set default altitude value
    
    // Pressure sensor ok?
    if (ps_ok)
    {
        // Initialise pressure table
        init_pressure_table();

        // Do single conversion
        start_altitude_measurement();
        stop_altitude_measurement();
        
        sAlt.accu_threshold = CONFIG_MOD_ALTITUDE_ACCU_THRESHOLD;
        
        sAlt.altitude_calib =  sAlt.raw_altitude;
        sAlt.altitude_offset = sAlt.raw_altitude - sAlt.altitude_calib;
        
        sAlt.raw_minAltitude = sAlt.raw_altitude;
        sAlt.raw_maxAltitude = sAlt.raw_altitude;
     
        oldAccuAltitude = sAlt.raw_altitude;
        sAlt.accuClimbDown = 0;
        sAlt.accuClimbUp = 0;
        
        
        sAlt.minAltitude = sAlt.raw_minAltitude - sAlt.altitude_offset;
        sAlt.maxAltitude = sAlt.raw_maxAltitude - sAlt.altitude_offset;
        sAlt.altitude = sAlt.raw_altitude - sAlt.altitude_offset;

        sAlt.first_pressure = sAlt.pressure;
        sAlt.climb = 0;
        for (sAlt.history_pos = 0; sAlt.history_pos < ALT_HISTORY_LEN; sAlt.history_pos++) {
                sAlt.history[sAlt.history_pos] = 0;
        }
        sAlt.history_pos = 0;
}
}
__interrupt void TIMER0_A0_ISR(void)
{
    static u8 button_lock_counter = 0;

    // Disable IE
    TA0CCTL0 &= ~CCIE;
    // Reset IRQ flag
    TA0CCTL0 &= ~CCIFG;
    // Add 1 sec to TACCR0 register (IRQ will be asserted at 0x7FFF and 0xFFFF = 1 sec intervals)
    TA0CCR0 += 32768;
    // Enable IE
    TA0CCTL0 |= CCIE;

    // Add 1 second to global time
    clock_tick();

    // Set clock update flag
    display.flag.update_time = 1;

    // While SimpliciTI stack operates or BlueRobin searches, freeze system state
    if (is_rf() || is_bluerobin_searching())
    {
        // SimpliciTI automatic timeout
        if (sRFsmpl.timeout == 0)
        {
            simpliciti_flag |= SIMPLICITI_TRIGGER_STOP;
        }
        else
        {
            sRFsmpl.timeout--;
        }

        // switch message after received packet
        if (sRFsmpl.mode == SIMPLICITI_SYNC)
        {
            if (sRFsmpl.display_sync_done == 0)
            {
                display_chars(LCD_SEG_L2_5_0, (u8 *) "  SYNC", SEG_ON);
            }
            else
            {
                sRFsmpl.display_sync_done--;
            }
        }
        // Exit from LPM3 on RETI
        _BIC_SR_IRQ(LPM3_bits);
        return;
    }

    // -------------------------------------------------------------------
    // Service modules that require 1/min processing
    if (sTime.drawFlag >= 2)
    {
        // Measure battery voltage to keep track of remaining battery life
        request.flag.voltage_measurement = 1;

        // Check if alarm needs to be turned on
        check_alarm();
    }

    // -------------------------------------------------------------------
    // Service active modules that require 1/s processing

    // Generate alarm signal
    if (sAlarm.state == ALARM_ON)
    {
        // Decrement alarm duration counter
        if (sAlarm.duration-- > 0)
        {
            request.flag.buzzer = 1;
        }
        else
        {
            sAlarm.duration = ALARM_ON_DURATION;
            stop_alarm();
        }
    }

    // Do a temperature measurement each second while menu item is active
    if (is_temp_measurement())
        request.flag.temperature_measurement = 1;

    // Do a pressure measurement each second while menu item is active
    if (is_altitude_measurement())
    {
        // Countdown altitude measurement timeout while menu item is active
        sAlt.timeout--;

        // Stop measurement when timeout has elapsed
        if (sAlt.timeout == 0)
        {
            stop_altitude_measurement();
            // Show ---- m/ft
            display_chars(LCD_SEG_L1_3_0, (u8 *) "----", SEG_ON);
            // Clear up/down arrow
            display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
            display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
        }

        // In case we missed the IRQ due to debouncing, get data now
        if ((PS_INT_IN & PS_INT_PIN) == PS_INT_PIN)
            request.flag.altitude_measurement = 1;
    }

    // Count down timeout
    if (is_acceleration_measurement())
    {
        // Countdown acceleration measurement timeout
        sAccel.timeout--;

        // Stop measurement when timeout has elapsed
        if (sAccel.timeout == 0)
        {
            as_stop();
            // Show ----
            display_chars(LCD_SEG_L1_3_0, (u8 *) "----", SEG_ON);
            // Clear up/down arrow
            display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
            display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
            display_symbol(LCD_SEG_L1_DP1, SEG_OFF);
        }

        // If DRDY is (still) high, request data again
        if ((AS_INT_IN & AS_INT_PIN) == AS_INT_PIN)
            request.flag.acceleration_measurement = 1;
    }

    // If BlueRobin transmitter is connected, get data from API
    if (is_bluerobin())
        get_bluerobin_data();

    // If battery is low, decrement display counter
    if (sys.flag.low_battery)
    {
        if (sBatt.lobatt_display-- == 0)
        {
            message.flag.prepare = 1;
            message.flag.type_lobatt = 1;
            sBatt.lobatt_display = BATTERY_LOW_MESSAGE_CYCLE;
        }
    }

    // If a message has to be displayed, set display flag
    if (message.all_flags)
    {
        if (message.flag.prepare)
        {
            message.flag.prepare = 0;
            message.flag.show = 1;
        }
        else if (message.flag.erase)    // message cycle is over, so erase it
        {
            message.flag.erase = 0;
            display.flag.full_update = 1;
        }
    }

    // -------------------------------------------------------------------
    // Check idle timeout, set timeout flag
    if (sys.flag.idle_timeout_enabled)
    {
        if (sTime.system_time - sTime.last_activity > INACTIVITY_TIME)
            sys.flag.idle_timeout = 1;  //setFlag(sysFlag_g, SYS_TIMEOUT_IDLE);
    }

    // -------------------------------------------------------------------
    // Turn the Backlight off after timeout
    if (sButton.backlight_status == 1)
    {
        if (sButton.backlight_timeout > BACKLIGHT_TIME_ON)
        {
            //turn off Backlight
            P2OUT &= ~BUTTON_BACKLIGHT_PIN;
            P2DIR &= ~BUTTON_BACKLIGHT_PIN;
            sButton.backlight_timeout = 0;
            sButton.backlight_status = 0;
        }
        else
        {
            sButton.backlight_timeout++;
        }
    }

    // -------------------------------------------------------------------
    // Detect continuous button high states

    // Trying to lock/unlock buttons?
    if (BUTTON_NUM_IS_PRESSED && BUTTON_DOWN_IS_PRESSED)
    {
        if (button_lock_counter++ > LEFT_BUTTON_LONG_TIME)
        {
            // Toggle lock / unlock buttons flag
            sys.flag.lock_buttons = ~sys.flag.lock_buttons;

            // Show "buttons are locked/unlocked" message synchronously with next second tick
            message.flag.prepare = 1;
            if (sys.flag.lock_buttons)
                message.flag.type_locked = 1;
            else
                message.flag.type_unlocked = 1;

            // Reset button lock counter
            button_lock_counter = 0;
        }
    }
    else                        // Trying to create a long button press?
    {
        // Reset button lock counter
        button_lock_counter = 0;

        if (BUTTON_STAR_IS_PRESSED)
        {
            sButton.star_timeout++;

            // Check if button was held low for some seconds
            if (sButton.star_timeout > LEFT_BUTTON_LONG_TIME)
            {
                button.flag.star_long = 1;
                button.flag.star_not_long = 0;
                sButton.star_timeout = 0;
                // Return interrupt edge to normal value
                BUTTONS_IES &= ~BUTTON_STAR_PIN;
            }
        }
        else                    // there was a button press not long enough
        {
            sButton.star_timeout = 0;
        }

        if (BUTTON_NUM_IS_PRESSED)
        {
            sButton.num_timeout++;

            // Check if button was held low for some seconds
            if (sButton.num_timeout > LEFT_BUTTON_LONG_TIME)
            {
                button.flag.num_long = 1;
                button.flag.num_not_long = 0;
                sButton.num_timeout = 0;
                // Return interrupt edge to normal value
                BUTTONS_IES &= ~BUTTON_NUM_PIN;
            }
        }
        else                    // there was a button press not long enough
        {
            sButton.num_timeout = 0;
        }
    }

    // Exit from LPM3 on RETI
    _BIC_SR_IRQ(LPM3_bits);
}
Exemple #8
0
// *************************************************************************************************
// @fn          display_altitude
// @brief       Display routine. Supports display in meters and feet. 
// @param       u8 line                 LINE1
//                              u8 update               DISPLAY_LINE_UPDATE_FULL, DISPLAY_LINE_UPDATE_PARTIAL, DISPLAY_LINE_CLEAR
// @return      none
// *************************************************************************************************
void display_altitude(u8 line, u8 update)
{
   u8 *str;
   s16 ft;

   // Start measurement
   start_altitude_measurement();

   // redraw whole screen
   if (update == DISPLAY_LINE_UPDATE_FULL)
   {
      if (sys.flag.use_metric_units)
      {
         // Display "m" symbol
         display_symbol(LCD_UNIT_L1_M, SEG_ON);
      }
      else
      {
         // Display "ft" symbol
         display_symbol(LCD_UNIT_L1_FT, SEG_ON);
      }

      // Display altitude
      display_altitude(LINE1, DISPLAY_LINE_UPDATE_PARTIAL);
   }
   else if (update == DISPLAY_LINE_UPDATE_PARTIAL)
   {
      if (sys.flag.use_metric_units)
      {
         // Display altitude in xxxx m format, allow 3 leading blank digits
         if (sAlt.altitude >= 0)
         {
            str = int_to_array(sAlt.altitude, 4, 3);
            display_symbol(LCD_SYMB_ARROW_UP, SEG_ON);
            display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
         }
         else
         {
            str = int_to_array(sAlt.altitude * (-1), 4, 3);
            display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
            display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON);
         }
      }
      else
      {
         // Convert from meters to feet
         ft = convert_m_to_ft(sAlt.altitude);

         // Limit to 9999ft (3047m)
         if (ft > 9999)
            ft = 9999;

         // Display altitude in xxxx ft format, allow 3 leading blank digits
         if (ft >= 0)
         {
            str = int_to_array(ft, 4, 3);
            display_symbol(LCD_SYMB_ARROW_UP, SEG_ON);
            display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
         }
         else
         {
            str = int_to_array(ft * (-1), 4, 3);
            display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
            display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON);
         }
      }
      display_chars(LCD_SEG_L1_3_0, str, SEG_ON);
   }
   else if (update == DISPLAY_LINE_CLEAR)
   {
      // Stop measurement
      stop_altitude_measurement();

      // Clean up function-specific segments before leaving function
      display_symbol(LCD_UNIT_L1_M, SEG_OFF);
      display_symbol(LCD_UNIT_L1_FT, SEG_OFF);
      display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
      display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
   }
}
// *************************************************************************************************
// @fn          start_simpliciti_sync
// @brief       Start SimpliciTI (sync mode).
// @param       none
// @return      none
// *************************************************************************************************
void start_simpliciti_sync(void)
{
    // Clear LINE1
    clear_line(LINE1);
    fptr_lcd_function_line1(LINE1, DISPLAY_LINE_CLEAR);

    // Stop acceleration sensor
    as_stop();

    // Get updated altitude
    start_altitude_measurement();
    stop_altitude_measurement();

    // Get updated temperature
    temperature_measurement(FILTER_OFF);

    // Turn on beeper icon to show activity
    display_symbol(LCD_ICON_BEEPER1, SEG_ON_BLINK_ON);
    display_symbol(LCD_ICON_BEEPER2, SEG_ON_BLINK_ON);
    display_symbol(LCD_ICON_BEEPER3, SEG_ON_BLINK_ON);

    // Debounce button event
    Timer0_A4_Delay(CONV_MS_TO_TICKS(BUTTONS_DEBOUNCE_TIME_OUT));

    // Prepare radio for RF communication
    open_radio();

    // Set SimpliciTI mode
    sRFsmpl.mode = SIMPLICITI_SYNC;

    // Set SimpliciTI timeout to save battery power
    sRFsmpl.timeout = SIMPLICITI_TIMEOUT;

    // Start SimpliciTI stack. Try to link to access point.
    // Exit with timeout or by a button DOWN press.
    if (simpliciti_link())
    {
        // Enter sync routine. This will send ready-to-receive packets at regular intervals to the
        // access point.
        // The access point replies with a command (NOP if no other command is set)
        simpliciti_main_sync();
    }

    // Set SimpliciTI state to OFF
    sRFsmpl.mode = SIMPLICITI_OFF;

    // Powerdown radio
    close_radio();

    // Clear last button events
    Timer0_A4_Delay(CONV_MS_TO_TICKS(BUTTONS_DEBOUNCE_TIME_OUT));
    BUTTONS_IFG = 0x00;
    button.all_flags = 0;

    // Clear icons
    display_symbol(LCD_ICON_BEEPER1, SEG_OFF_BLINK_OFF);
    display_symbol(LCD_ICON_BEEPER2, SEG_OFF_BLINK_OFF);
    display_symbol(LCD_ICON_BEEPER3, SEG_OFF_BLINK_OFF);

    // Force full display update
    display.flag.full_update = 1;
}
Exemple #10
0
__interrupt void TIMER0_A0_ISR(void)
#endif
{
	static u8 button_lock_counter = 0;
	static u8 button_beep_counter = 0;
	
	// Disable IE 
	TA0CCTL0 &= ~CCIE;
	// Reset IRQ flag  
	TA0CCTL0 &= ~CCIFG;  
	// Add 1 sec to TACCR0 register (IRQ will be asserted at 0x7FFF and 0xFFFF = 1 sec intervals)
	TA0CCR0 += 32768;
	// Enable IE 
	TA0CCTL0 |= CCIE;
	
	// Add 1 second to global time
	clock_tick();
	
	// Set clock update flag
	display.flag.update_time = 1;
	
	// While SimpliciTI stack operates or BlueRobin searches, freeze system state
	//pfs
	#ifdef ELIMINATE_BLUEROBIN
	if (is_rf())
	#else
	if (is_rf() || is_bluerobin_searching()) 
	#endif
	{
		// SimpliciTI automatic timeout
		if (sRFsmpl.timeout == 0) 
		{
			simpliciti_flag |= SIMPLICITI_TRIGGER_STOP;
		}
		else
		{
			sRFsmpl.timeout--;
		}
		
		// Exit from LPM3 on RETI
		_BIC_SR_IRQ(LPM3_bits);     
		return;
	}
	
	// -------------------------------------------------------------------
	// Service modules that require 1/min processing
	if (sTime.drawFlag >= 2) 
	{
		#ifdef CONFIG_BATTERY
		// Measure battery voltage to keep track of remaining battery life
		request.flag.voltage_measurement = 1;
		#endif
		
		#ifdef CONFIG_ALARM
		// If the chime is enabled, we beep here
		if (sTime.minute == 0) {
			if (sAlarm.hourly == ALARM_ENABLED) {
				request.flag.alarm_buzzer = 1;
			}
            #if (CONFIG_DST > 0)
            if ((sTime.hour == 1) &&
                (dst_state == 0) &&
                dst_isDateInDST(sDate.month, sDate.day))
            {
                // spring forward
                sTime.hour++;
                dst_state = 1;
            }
            if ((sTime.hour == 2) &&
                (dst_state != 0) &&
                (!dst_isDateInDST(sDate.month, sDate.day)))
            {
                // fall back
                sTime.hour--;
                dst_state = 0;
            }
            #endif
		}
		// Check if alarm needs to be turned on
		check_alarm();
		#endif
		#ifdef CONFIG_ALTI_ACCUMULATOR
		// Check if we need to do an altitude accumulation
		if (alt_accum_enable)
			request.flag.altitude_accumulator = 1;
		#endif
	}

	// -------------------------------------------------------------------
	// Service active modules that require 1/s processing
#ifdef CONFIG_EGGTIMER
	if (sEggtimer.state == EGGTIMER_RUN) {
		eggtimer_tick(); // Subtract 1 second from eggtimer's count
	}

	if (sEggtimer.state == EGGTIMER_ALARM) { // no "else if" intentional
		// Decrement alarm duration counter
		if (sEggtimer.duration-- > 0)
		{
			request.flag.eggtimer_buzzer = 1;
		}
		else
		{
			stop_eggtimer_alarm(); // Set state to Stop and reset duration
		}
	}
#endif
	#ifdef CONFIG_ALARM
	// Generate alarm signal
	if (sAlarm.state == ALARM_ON) 
	{
		// Decrement alarm duration counter
		if (sAlarm.duration-- > 0)
		{
			request.flag.alarm_buzzer = 1;
		}
		else
		{
			sAlarm.duration = ALARM_ON_DURATION;
			stop_alarm();
		}
	}
	#endif
	
#ifdef CONFIG_PROUT
        if (is_prout()) prout_tick();
#endif
		
#ifdef CONFIG_STRENGTH
        // One more second gone by.
        if(is_strength())
	{
		strength_tick();
	}            
#endif

	// Do a temperature measurement each second while menu item is active
	if (is_temp_measurement()) request.flag.temperature_measurement = 1;
	
	// Do a pressure measurement each second while menu item is active
#ifdef CONFIG_ALTITUDE
	if (is_altitude_measurement()) 
	{
		// Countdown altitude measurement timeout while menu item is active
		sAlt.timeout--;

		// Stop measurement when timeout has elapsed
		if (sAlt.timeout == 0)	
		{
			stop_altitude_measurement();
			// Show ---- m/ft
			display_chars(LCD_SEG_L1_3_0, (u8*)"----", SEG_ON);
			// Clear up/down arrow
			display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
			display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
		}
		
		// In case we missed the IRQ due to debouncing, get data now
		if ((PS_INT_IN & PS_INT_PIN) == PS_INT_PIN) request.flag.altitude_measurement = 1;
	}	
#endif

#ifdef FEATURE_PROVIDE_ACCEL
	// Count down timeout
	if (is_acceleration_measurement()) 
	{
		// Countdown acceleration measurement timeout 
		sAccel.timeout--;

		// Stop measurement when timeout has elapsed
		if (sAccel.timeout == 0) as_stop();	
		
		// If DRDY is (still) high, request data again
		if ((AS_INT_IN & AS_INT_PIN) == AS_INT_PIN) request.flag.acceleration_measurement = 1; 
	}	
#endif

	//pfs
#ifndef ELIMINATE_BLUEROBIN
	// If BlueRobin transmitter is connected, get data from API
	if (is_bluerobin()) get_bluerobin_data();
#endif
	
	#ifdef CONFIG_BATTERY
	// If battery is low, decrement display counter
	if (sys.flag.low_battery)
	{
		if (sBatt.lobatt_display-- == 0) 
		{
			message.flag.prepare = 1;
			message.flag.type_lobatt = 1;
			sBatt.lobatt_display = BATTERY_LOW_MESSAGE_CYCLE;
		}
	}
	#endif
	
	// If a message has to be displayed, set display flag
	if (message.all_flags)
	{
		if (message.flag.prepare)
		{
			message.flag.prepare = 0;
			message.flag.show    = 1;
		}
		else if (message.flag.erase) // message cycle is over, so erase it
		{
			message.flag.erase       = 0;
			message.flag.block_line1 = 0;
			message.flag.block_line2 = 0;
			display.flag.full_update = 1;
		}	
	}
	
	// -------------------------------------------------------------------
	// Check idle timeout, set timeout flag
	if (sys.flag.idle_timeout_enabled)
	{
		if (sTime.system_time - sTime.last_activity > INACTIVITY_TIME) sys.flag.idle_timeout = 1; //setFlag(sysFlag_g, SYS_TIMEOUT_IDLE);
	}
	
	// -------------------------------------------------------------------
	// Turn the Backlight off after timeout
	if (sButton.backlight_status == 1)
	{
		if (sButton.backlight_timeout > BACKLIGHT_TIME_ON)
		{
			//turn off Backlight
			P2OUT &= ~BUTTON_BACKLIGHT_PIN;
			P2DIR &= ~BUTTON_BACKLIGHT_PIN;
			sButton.backlight_timeout = 0;
			sButton.backlight_status = 0;
		}
		else
		{
			sButton.backlight_timeout++;
		}
	}
	// -------------------------------------------------------------------
	// Detect continuous button high states

	if (BUTTON_STAR_IS_PRESSED && BUTTON_UP_IS_PRESSED)
	{
		if (button_beep_counter++ > LEFT_BUTTON_LONG_TIME)
		{
			// Toggle no_beep buttons flag
			sys.flag.no_beep = ~sys.flag.no_beep;
	
			// Show "beep / nobeep" message synchronously with next second tick
			message.flag.prepare = 1;
			if (sys.flag.no_beep)	message.flag.type_no_beep_on   = 1;
			else					message.flag.type_no_beep_off  = 1;
			
			// Reset button beep counter
			button_beep_counter = 0;
		}
	} else if (BUTTON_NUM_IS_PRESSED && BUTTON_DOWN_IS_PRESSED) // Trying to lock/unlock buttons?
	{
		if (button_lock_counter++ > LEFT_BUTTON_LONG_TIME)
		{
			// Toggle lock / unlock buttons flag
			sys.flag.lock_buttons = ~sys.flag.lock_buttons;
	
			// Show "buttons are locked/unlocked" message synchronously with next second tick
			message.flag.prepare = 1;
			if (sys.flag.lock_buttons)	message.flag.type_locked   = 1;
			else						message.flag.type_unlocked = 1;
			
			// Reset button lock counter
			button_lock_counter = 0;
		}
	}
	else // Trying to create a long button press?
	{
		// Reset button lock counter
		button_lock_counter = 0;
		
		if (BUTTON_STAR_IS_PRESSED) 	
		{
			sButton.star_timeout++;
			
			// Check if button was held low for some seconds
			if (sButton.star_timeout > LEFT_BUTTON_LONG_TIME) 
			{
				button.flag.star_long = 1;
				sButton.star_timeout = 0;
			}
		}
		else
		{
			sButton.star_timeout = 0;
		}
	
		if (BUTTON_NUM_IS_PRESSED) 	
		{
			sButton.num_timeout++;
		
			// Check if button was held low for some seconds
			if (sButton.num_timeout > LEFT_BUTTON_LONG_TIME) 
			{
				button.flag.num_long = 1;
				sButton.num_timeout = 0;
			}
		}
		else
		{
			sButton.num_timeout = 0;
		}
	}
	
	// Exit from LPM3 on RETI
	_BIC_SR_IRQ(LPM3_bits);               
}
Exemple #11
0
// *************************************************************************************************
// @fn          display_altitude
// @brief       Display routine. Supports display in meters and feet.
// @param       u8 line			LINE1
//		u8 update		DISPLAY_LINE_UPDATE_FULL, DISPLAY_LINE_UPDATE_PARTIAL, DISPLAY_LINE_CLEAR
// @return      none
// *************************************************************************************************
void display_altitude(u8 line, u8 update)
{
	if (update == DISPLAY_LINE_UPDATE_FULL)
	{
		sAlt.state = MENU_ITEM_VISIBLE;
		start_altitude_measurement();

		u8 m, ft;
#ifdef CONFIG_ALTITUDE_UNIT_SETTABLE
		if (sys.flag.use_metric_units) {
		       m = SEG_ON; ft = SEG_OFF;
		} else {
		       m = SEG_OFF; ft = SEG_ON;
		}
#elif defined(CONFIG_ALTITUDE_UNIT_METERS)
		m = SEG_ON; ft = SEG_OFF;
#elif defined(CONFIG_ALTITUDE_UNIT_FEET)
		m = SEG_OFF; ft = SEG_ON;
#endif
	       // Display "m" or "ft" symbol
	       display_symbol(LCD_UNIT_L1_M, m);
	       display_symbol(LCD_UNIT_L1_FT, ft);
	}
	if (update == DISPLAY_LINE_UPDATE_FULL || update == DISPLAY_LINE_UPDATE_PARTIAL) {
		// Update display only while measurement is active
		if (sAlt.timeout > 0) {
			u8 *str;
			if (sAlt.mode == ALTITUDE_SKYDIVING && sAlt.altitude > 1000) {
				u16 altitude = (sAlt.altitude + 50) / 100;
				str = _itoa(altitude, 3, 1);
				display_chars(LCD_SEG_L1_3_1, str, SEG_ON);
				display_chars(LCD_SEG_L1_0, NULL, SEG_OFF);
				display_symbol(LCD_SEG_L1_DP1, SEG_ON);
				display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
			} else {
				// Display altitude in xxxx m format, allow 3 leading blank digits
				if (sAlt.altitude >= 0) {
					str = _itoa(sAlt.altitude, 4, 3);
					display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
				} else {
					str = _itoa(-sAlt.altitude, 4, 3);
					display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON);
				}

				display_chars(LCD_SEG_L1_3_0, str, SEG_ON);
				display_symbol(LCD_SEG_L1_DP1, SEG_OFF);
			}
		}
	} else if (update == DISPLAY_LINE_CLEAR) {
		// Disable pressure measurement
		sAlt.state = MENU_ITEM_NOT_VISIBLE;

		// Stop measurement
		stop_altitude_measurement();

		// Clean up function-specific segments before leaving function
		display_symbol(LCD_UNIT_L1_M, SEG_OFF);
		display_symbol(LCD_UNIT_L1_FT, SEG_OFF);
		display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
		display_symbol(LCD_SEG_L1_DP1, SEG_OFF);
	}
}
Exemple #12
0
void read_altitude(void)
{
	// Start measurement
	start_altitude_measurement();
	stop_altitude_measurement();
}
__interrupt void TIMER0_A0_ISR(void)
{
	static u8 button_lock_counter = 0;
	
	// Disable IE 
	TA0CCTL0 &= ~CCIE;
	// Reset IRQ flag  
	TA0CCTL0 &= ~CCIFG;  
	// Add 1 sec to TACCR0 register (IRQ will be asserted at 0x7FFF and 0xFFFF = 1 sec intervals)
	TA0CCR0 += 32768;
	// Enable IE 
	TA0CCTL0 |= CCIE;
	
	// Add 1 second to global time
	clock_tick();

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// Count down and up
	if (sCountup.mode == COUNTUP_MODE_ON)
	{
		countup_tick();

		if (sCountdown.mode == COUNTDOWN_MODE_ON)
		{
			// Countdown acceleration measurement timeout
			sAccel.timeout--;

			// Stop measurement when timeout has elapsed
			if (sAccel.timeout == 0) as_stop();

			// If DRDY is (still) high, request data again
			if ((AS_INT_IN & AS_INT_PIN) == AS_INT_PIN) request.flag.acceleration_measurement = 1;

			// sAccel.xyz[0] = xaxis, sAccel.xyz[0] = yaxis, sAccel.xyz[0] = zaxis

			if ((sAccel.xyz[0] < sCountdown.thresholdlow[0] || sAccel.xyz[0] > sCountdown.thresholdhigh[0]) &&
				(sAccel.xyz[1] < sCountdown.thresholdlow[1] || sAccel.xyz[1] > sCountdown.thresholdhigh[1]))
			{
			// UNDER THRESHOLD VALUES
				if (sCountdown.speed == 1)
				{
					// Clear timer interrupt enable
					TA0CCTL2 &= ~CCIE;

					countdown_tick();
				}
				if (sCountdown.speed == 2)
				{
					// Recovery loop - set back to default as below threshold
					if (sCountdown.exceedcount[0] != sCountdown.exceeddefault[0])
					{
						sCountdown.exceedcount[0] = sCountdown.exceeddefault[0];
					}

					// Recovery loop - reduce recovery value if under threshold
					if (sCountdown.recoverycount != 0)
					{
						sCountdown.recoverycount--;
					}
					// Set speed to 1 if recovery is back to 0
					else
					{
						sCountdown.speed = 1;
						sCountdown.recoverycount = sCountdown.recoverydefault;
						countdown_tick();
					}
				}
				if (sCountdown.speed == 3)
				{
					// Recovery loop - set back to default as below threshold
					if (sCountdown.exceedcount[1] != sCountdown.exceeddefault[1])
					{
						sCountdown.exceedcount[1] = sCountdown.exceeddefault[1];
					}

					// Recovery loop - reduce recovery value if under threshold
					if (sCountdown.recoverycount != 0)
					{
						sCountdown.recoverycount--;
					}
					// Set speed to 1 if recovery is back to 0
					else
					{
						sCountdown.speed = 1;
						sCountdown.recoverycount = sCountdown.recoverydefault;
						countdown_tick();
					}
				}
			}
			// OVER THRESHOLD VALUES
			else
			{

				sCountdown.recoverycount = sCountdown.recoverydefault;

				if (sCountdown.speed == 1)
				{
					// Increase countdown speed
					sCountdown.speed = 2;

					// Init CCR register with current time
					TA0CCR2 = TA0R;

					// Load CCR register with next capture time
					TA0CCR2 += sCountdown.tickspeed[0];

					// Reset IRQ flag
					TA0CCTL2 &= ~CCIFG;

					// Enable timer interrupt
					TA0CCTL2 |= CCIE;

					countdown_tick();
				}
				if (sCountdown.speed == 2)
				{
					// Counting down from exceed2 limit
					if (sCountdown.exceedcount[0] != 0)
					{
						sCountdown.exceedcount[0]--;
					}
					// Speed up if equal to 0
					else
					{
						sCountdown.exceedcount[0] = sCountdown.exceeddefault[0];

						// Increase countdown speed
						sCountdown.speed = 3;
					}
				}
				if (sCountdown.speed == 3)
				{
					// Counting down from exceed3 limit
					if (sCountdown.exceedcount[1] != 0)
					{
						sCountdown.exceedcount[1]--;
					}
					// Speed up if equal to 0
					else
					{
						countdown_droptozero();
					}
				}
			}
		}
	}
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	// Set clock update flag
	display.flag.update_time = 1;
	
	// While SimpliciTI stack operates or BlueRobin searches, freeze system state
	if (is_rf() || is_bluerobin_searching()) 
	{
		// SimpliciTI automatic timeout
		if (sRFsmpl.timeout == 0) 
		{
			simpliciti_flag |= SIMPLICITI_TRIGGER_STOP;
		}
		else
		{
			sRFsmpl.timeout--;
		}
		
		// Exit from LPM3 on RETI
		_BIC_SR_IRQ(LPM3_bits);     
		return;
	}
	
	// -------------------------------------------------------------------
	// Service modules that require 1/min processing
	if (sTime.drawFlag >= 2) 
	{
		// Measure battery voltage to keep track of remaining battery life
		request.flag.voltage_measurement = 1;
		
		// Check if alarm needs to be turned on
		check_alarm();
	}

	// -------------------------------------------------------------------
	// Service active modules that require 1/s processing
	
	// Generate alarm signal
	if (sAlarm.state == ALARM_ON) 
	{
		// Decrement alarm duration counter
		if (sAlarm.duration-- > 0)
		{
			request.flag.buzzer = 1;
		}
		else
		{
			sAlarm.duration = ALARM_ON_DURATION;
			stop_alarm();
		}
	}

	// Do a temperature measurement each second while menu item is active
	if (is_temp_measurement()) request.flag.temperature_measurement = 1;
	
	// Do a pressure measurement each second while menu item is active
	if (is_altitude_measurement()) 
	{
		// Countdown altitude measurement timeout while menu item is active
		sAlt.timeout--;

		// Stop measurement when timeout has elapsed
		if (sAlt.timeout == 0)	
		{
			stop_altitude_measurement();
			// Show ---- m/ft
			display_chars(LCD_SEG_L1_3_0, (u8*)"----", SEG_ON);
			// Clear up/down arrow
			display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
			display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
		}
		
		// In case we missed the IRQ due to debouncing, get data now
		if ((PS_INT_IN & PS_INT_PIN) == PS_INT_PIN) request.flag.altitude_measurement = 1;
	}	

	// Count down timeout
	if (is_acceleration_measurement()) 
	{
		// Countdown acceleration measurement timeout 
		sAccel.timeout--;

		// Stop measurement when timeout has elapsed
		if (sAccel.timeout == 0) as_stop();	
		
		// If DRDY is (still) high, request data again
		if ((AS_INT_IN & AS_INT_PIN) == AS_INT_PIN) request.flag.acceleration_measurement = 1; 
	}	

	// If BlueRobin transmitter is connected, get data from API
	if (is_bluerobin()) get_bluerobin_data();
	
	// If battery is low, decrement display counter
	if (sys.flag.low_battery)
	{
		if (sBatt.lobatt_display-- == 0) 
		{
			message.flag.prepare = 1;
			message.flag.type_lobatt = 1;
			sBatt.lobatt_display = BATTERY_LOW_MESSAGE_CYCLE;
		}
	}
	
	// If a message has to be displayed, set display flag
	if (message.all_flags)
	{
		if (message.flag.prepare)
		{
			message.flag.prepare = 0;
			message.flag.show    = 1;
		}
		else if (message.flag.erase) // message cycle is over, so erase it
		{
			message.flag.erase       = 0;
			display.flag.full_update = 1;
		}	
	}
	
	// -------------------------------------------------------------------
	// Check idle timeout, set timeout flag
	if (sys.flag.idle_timeout_enabled)
	{
		if (sTime.system_time - sTime.last_activity > INACTIVITY_TIME) sys.flag.idle_timeout = 1; //setFlag(sysFlag_g, SYS_TIMEOUT_IDLE);
	}
	
	// -------------------------------------------------------------------
	// Detect continuous button high states
	
	// Trying to lock/unlock buttons?
	if (BUTTON_NUM_IS_PRESSED && BUTTON_DOWN_IS_PRESSED)
	{
		if (button_lock_counter++ > LEFT_BUTTON_LONG_TIME)
		{
			// Toggle lock / unlock buttons flag
			sys.flag.lock_buttons = ~sys.flag.lock_buttons;
	
			// Show "buttons are locked/unlocked" message synchronously with next second tick
			message.flag.prepare = 1;
			if (sys.flag.lock_buttons)	message.flag.type_locked   = 1;
			else						message.flag.type_unlocked = 1;
			
			// Reset button lock counter
			button_lock_counter = 0;
		}
	}
	else // Trying to create a long button press?
	{
		// Reset button lock counter
		button_lock_counter = 0;
		
		if (BUTTON_UP_IS_PRESSED)
		{
			sButton.up_timeout++;
			
			// Check if button was held low for some seconds
			if (sButton.up_timeout > LEFT_BUTTON_LONG_TIME)
			{
				button.flag.up_long = 1;
				sButton.up_timeout = 0;
			}
		}
		else
		{
			sButton.up_timeout = 0;
		}
	
		if (BUTTON_DOWN_IS_PRESSED)
		{
			sButton.down_timeout++;
		
			// Check if button was held low for some seconds
			if (sButton.down_timeout > LEFT_BUTTON_LONG_TIME)
			{
				button.flag.down_long = 1;
				sButton.down_timeout = 0;
			}
		}
		else
		{
			sButton.down_timeout = 0;
		}

		if (BUTTON_NUM_IS_PRESSED)
		{
			sButton.num_timeout++;

			// Check if button was held low for some seconds
			if (sButton.num_timeout > LEFT_BUTTON_LONG_TIME)
			{
				button.flag.num_long = 1;
				sButton.num_timeout = 0;
			}
		}
		else
		{
			sButton.num_timeout = 0;
		}
	}
	
	// Exit from LPM3 on RETI
	_BIC_SR_IRQ(LPM3_bits);               
}
// *************************************************************************************************
// @fn          display_altitude
// @brief       Display routine. Supports display in meters and feet.
// @param       u8 line                 LINE1
//                              u8 update               DISPLAY_LINE_UPDATE_FULL,
// DISPLAY_LINE_UPDATE_PARTIAL, DISPLAY_LINE_CLEAR
// @return      none
// *************************************************************************************************
void display_altitude(u8 line, u8 update)
{
    u8 *str;
    s16 ft;

    // redraw whole screen
    if (update == DISPLAY_LINE_UPDATE_FULL)
    {
        // Enable pressure measurement
        sAlt.state = MENU_ITEM_VISIBLE;

        // Start measurement
        start_altitude_measurement();


        // Display altitude
        display_altitude(LINE1, DISPLAY_LINE_UPDATE_PARTIAL);
    }
    else if (update == DISPLAY_LINE_UPDATE_PARTIAL)
    {
        // Update display only while measurement is active
        if (sAlt.timeout > 0)
        {
          if (sAlt.display == DISPLAY_DEFAULT_VIEW)
          {
            display_symbol(LCD_UNIT_L1_PER_H, SEG_OFF);
            display_symbol(LCD_SYMB_AM, SEG_OFF);            
            if (sys.flag.use_metric_units)
            {
               // Display "m" symbol
               display_symbol(LCD_UNIT_L1_M, SEG_ON);
             }
            else
             {
              // Display "ft" symbol
              display_symbol(LCD_UNIT_L1_FT, SEG_ON);
              }        
            if (sys.flag.use_metric_units)
            {
                // Display altitude in xxxx m format, allow 3 leading blank digits
                if (sAlt.altitude >= 0)
                {
                    str = int_to_array(sAlt.altitude, 4, 3);
                    display_symbol(LCD_SYMB_ARROW_UP, SEG_ON);
                    display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
                }
                else
                {
                    str = int_to_array((-1)*sAlt.altitude, 4, 3);
                    //const u8 neg_txt[3] ="NEG";
                    //str = (u8 *)neg_txt;
                    display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
                    display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON);
                }
            }
            else
            {
                // Convert from meters to feet
                ft = convert_m_to_ft(sAlt.altitude);

                // Limit to 9999ft (3047m)
                if (ft > 9999)
                    ft = 9999;

                // Display altitude in xxxx ft format, allow 3 leading blank digits
                if (ft >= 0)
                {
                    str = int_to_array(ft, 4, 3);
                    display_symbol(LCD_SYMB_ARROW_UP, SEG_ON);
                    display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
                }
                else
                {
                    str = int_to_array(ft * (-1), 4, 3);
                    display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
                    display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON);
                }
            }
  
            display_symbol(LCD_ICON_RECORD, SEG_OFF_BLINK_OFF);
            display_chars(LCD_SEG_L1_3_0, str, SEG_ON);
          }
          else if (sAlt.display == DISPLAY_ALTERNATIVE_VIEW)
          {
            // Display Pressure in hPa
            
            u16 PressureToDisp = (u16) (((float)sAlt.pressure + 100.00 * (float) sAlt.pressure_offset) / 100.00 + 0.5);
            str = int_to_array(PressureToDisp, 4, 3);
            
            display_symbol(LCD_SYMB_AM, SEG_OFF);            
                    
            display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
            display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
        
            display_symbol(LCD_UNIT_L1_M, SEG_OFF);
            display_symbol(LCD_UNIT_L1_FT, SEG_OFF);
            display_symbol(LCD_UNIT_L1_PER_H, SEG_ON_BLINK_OFF);
            
            display_chars(LCD_SEG_L1_3_0, str, SEG_ON);
          }
          else if (sAlt.display == DISPLAY_ALTERNATIVE_VIEW1)
          {
            // Display Pressure in mmHg
            u16 PressureToDisp = (u16) (3.0 * ((float)sAlt.pressure + 100.00 * (float)sAlt.pressure_offset) / 400.00  + 0.5);            
            str = int_to_array(PressureToDisp, 4, 3);
            
//            str = int_to_array(sAlt.pressure_delta, 4, 3);            
            
            display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
            display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
        
            display_symbol(LCD_UNIT_L1_M, SEG_OFF);
            display_symbol(LCD_UNIT_L1_FT, SEG_OFF);
            display_symbol(LCD_UNIT_L1_PER_H, SEG_OFF);
            display_symbol(LCD_ICON_RECORD, SEG_OFF_BLINK_OFF);
            
            display_symbol(LCD_SYMB_AM, SEG_ON);            
              
            display_chars(LCD_SEG_L1_3_0, str, SEG_ON);
            
          }
          else if (sAlt.display == DISPLAY_ALTERNATIVE_VIEW2)
          {   
            display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
            display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);              
            display_symbol(LCD_SYMB_AM, SEG_OFF);            
            display_symbol(LCD_UNIT_L1_M, SEG_OFF);
            display_symbol(LCD_UNIT_L1_FT, SEG_OFF);            
            display_symbol(LCD_UNIT_L1_PER_H, SEG_OFF);
            display_symbol(LCD_ICON_RECORD, SEG_ON_BLINK_ON);
            
            s16 dp = sAlt.pressure_delta;            
            if (dp > 250)
            {
              // unstable high pressure
              display_chars(LCD_SEG_L1_3_0, (u8 *) "UN H", SEG_ON);
            }
            else if ((dp >= 50) && (dp <= 250))
            {
              // stable good weather
              display_chars(LCD_SEG_L1_3_0, (u8 *) " SUN", SEG_ON);
            }
            else if ((dp >= -50) && (dp < 50))
            {
              // stable              
              display_chars(LCD_SEG_L1_3_0, (u8 *) "STAB", SEG_ON);
            }
            else if ((dp > -250) && (dp < -50))
            {
              // stable rainy
              display_chars(LCD_SEG_L1_3_0, (u8 *) "RAIN", SEG_ON);
            }
            else 
            {
              // unstable low
              display_chars(LCD_SEG_L1_3_0, (u8 *) "UN L", SEG_ON);
            }
 
            
            /*
            u32 Temp = (u32)((float) sAlt.pressure_sum / ((float) sAlt.pressure_counter * 100.0) + 0.5);
            str = int_to_array(Temp, 4, 3);
            display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
            display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);              
            display_symbol(LCD_SYMB_AM, SEG_OFF);            
            display_symbol(LCD_UNIT_L1_M, SEG_OFF);
            display_symbol(LCD_UNIT_L1_FT, SEG_OFF);
            display_symbol(LCD_UNIT_L1_PER_H, SEG_ON_BLINK_ON); 
            display_chars(LCD_SEG_L1_3_0, str, SEG_ON);            
            */
          }
          else
          {                
            if (sAlt.pressure_delta >= 0)
            {
              str = int_to_array(sAlt.pressure_delta, 4, 3);           
              display_symbol(LCD_SYMB_ARROW_UP, SEG_ON);
              display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
            }
            else
            {
              str = int_to_array(sAlt.pressure_delta * (-1), 4, 3);                        
              display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
              display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON);              
            }
            display_symbol(LCD_ICON_RECORD, SEG_OFF_BLINK_OFF);
            display_symbol(LCD_SYMB_AM, SEG_OFF);            
            display_symbol(LCD_UNIT_L1_M, SEG_OFF);
            display_symbol(LCD_UNIT_L1_FT, SEG_OFF);
            display_symbol(LCD_UNIT_L1_PER_H, SEG_ON); 
            display_chars(LCD_SEG_L1_3_0, str, SEG_ON);
          }          
            
        }
    }
    else if (update == DISPLAY_LINE_CLEAR)
    {
        // Disable pressure measurement
        sAlt.state = MENU_ITEM_NOT_VISIBLE;

        // Stop measurement
        stop_altitude_measurement();

        // Clean up function-specific segments before leaving function
        display_symbol(LCD_UNIT_L1_M, SEG_OFF);
        display_symbol(LCD_UNIT_L1_FT, SEG_OFF);
        display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
        display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
        display_symbol(LCD_UNIT_L1_PER_H, SEG_OFF_BLINK_OFF);    
        display_symbol(LCD_SYMB_AM, SEG_OFF);         
        display_symbol(LCD_ICON_RECORD, SEG_OFF_BLINK_OFF);
            
        sAlt.display = DISPLAY_DEFAULT_VIEW;
    }
}
Exemple #15
0
void display_altitude(u8 line, u8 update)
{
    u8 * str;
#ifndef CONFIG_METRIC_ONLY
    s16 ft;
#endif

    // redraw whole screen
    if (update == DISPLAY_LINE_UPDATE_FULL)
    {
        // Enable pressure measurement
        sAlt.state = MENU_ITEM_VISIBLE;

        // Start measurement
        start_altitude_measurement();
#ifdef CONFIG_ALTI_ACCUMULATOR
        display_chars(LCD_SEG_L1_3_0, (u8*)"ALT ", SEG_ON);
#endif
#ifdef CONFIG_METRIC_ONLY
        display_symbol(LCD_UNIT_L1_M, SEG_ON);
#else
        if (sys.flag.use_metric_units)
        {
            // Display "m" symbol
            display_symbol(LCD_UNIT_L1_M, SEG_ON);
        }
        else
        {
            // Display "ft" symbol
            display_symbol(LCD_UNIT_L1_FT, SEG_ON);
        }
#endif
        // Display altitude
        display_altitude(LINE1, DISPLAY_LINE_UPDATE_PARTIAL);
    }
    else if (update == DISPLAY_LINE_UPDATE_PARTIAL)
    {
        // Update display only while measurement is active
        if (sAlt.timeout > 0)
        {
#ifndef CONFIG_METRIC_ONLY
            if (sys.flag.use_metric_units)
            {
#endif
                // Display altitude in xxxx m format, allow 3 leading blank digits
                if (sAlt.altitude >= 0)
                {
#ifdef CONFIG_ALTI_ACCUMULATOR
                    str = _itoa(sAlt.altitude, 5, 4);
#else
                    str = _itoa(sAlt.altitude, 4, 3);
#endif
                    display_symbol(LCD_SYMB_ARROW_UP, SEG_ON);
                    display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
                }
                else
                {
#ifdef CONFIG_ALTI_ACCUMULATOR
                    str = _itoa(sAlt.altitude*(-1), 4, 3);
#else
                    str = _itoa(sAlt.altitude*(-1), 5, 4);
#endif
                    display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
                    display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON);
                }
#ifndef CONFIG_METRIC_ONLY
            }
            else
            {
                // Convert from meters to feet
                ft = convert_m_to_ft(sAlt.altitude);
#ifndef CONFIG_ALTI_ACCUMULATOR
                // Limit to 9999ft (3047m)
                if (ft > 9999) ft = 9999;
#endif
                // Display altitude in xxxx ft format, allow 3 leading blank digits
                if (ft >= 0)
                {
#ifdef CONFIG_ALTI_ACCUMULATOR
                    str = _itoa(ft, 4, 3);
#else
                    str = _itoa(ft, 5, 4);
#endif
                    display_symbol(LCD_SYMB_ARROW_UP, SEG_ON);
                    display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
                }
                else
                {
#ifdef CONFIG_ALTI_ACCUMULATOR
                    str = _itoa(ft*(-1), 4, 3);
#else
                    str = _itoa(ft*(-1), 5, 4);
#endif
                    display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
                    display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON);
                }
            }
#endif
#ifdef CONFIG_ALTI_ACCUMULATOR
            // display altitude on bottom line (5 digits)
            clear_line(LINE2);
            display_chars(LCD_SEG_L2_4_0, str, SEG_ON);
#else
            display_chars(LCD_SEG_L1_3_0, str, SEG_ON);
#endif
        }
    }
    else if (update == DISPLAY_LINE_CLEAR)
    {
        // Disable pressure measurement
        sAlt.state = MENU_ITEM_NOT_VISIBLE;

        // Stop measurement
        stop_altitude_measurement();

        // Clean up function-specific segments before leaving function
#ifdef CONFIG_ALTI_ACCUMULATOR
        // clear off the altitude display from the second line
        clear_line(LINE2);
        // should really try to get the date displayed here again too
#endif
        display_symbol(LCD_UNIT_L1_M, SEG_OFF);
        display_symbol(LCD_UNIT_L1_FT, SEG_OFF);
        display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
        display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
    }
}
Exemple #16
0
__interrupt void RTC_A_ISR(void)
#endif
{
	sTime.second++;
	if (sTime.second == 60) sTime.second = 0;
	
	static u8 button_lock_counter = 0; //gibbons TODO: need to put these just in the 1-sec interrupt section?
	static u8 button_beep_counter = 0;
	
#ifdef CONFIG_CW
	u8 CW_Message[] = "NOON\0";
#endif
	
	switch (RTCIV) {
		case RTC_RT0PSIFG: // Interval timer (16384Hz - 128Hz interrupts (binary powers) )
			// gibbons TODO: put stopwatch 1/100 sec interrupt here?
			break;
			
		case RTC_RT1PSIFG: // Interval timer (64Hz - 0.5Hz interrupts (binary powers) )
			break;
			
		case RTC_RTCRDYIFG: // RTC registers ready and safe to read (Use this for 1-sec update)
			
			// Add 1 second to stored (global) time, update sTime.drawFlag appropriately
			clock_tick();
			
			// Set clock update flag
			display.flag.update_time = 1;
			
			// While SimpliciTI stack operates or BlueRobin searches, freeze system state
			//pfs
#ifdef ELIMINATE_BLUEROBIN
			if (is_rf())
#else
			if (is_rf() || is_bluerobin_searching()) 
#endif
			{
				// SimpliciTI automatic timeout
				if (sRFsmpl.timeout == 0) 
				{
					simpliciti_flag |= SIMPLICITI_TRIGGER_STOP;
				}
				else
				{
					sRFsmpl.timeout--;
				}
				
				// Exit from LPM3 on RETI
				_BIC_SR_IRQ(LPM3_bits);     
				return;
			}
			
			// -------------------------------------------------------------------
			// Service modules that require 1/min processing
			if (sTime.drawFlag >= 2) 
			{
				// Measure battery voltage to keep track of remaining battery life
				request.flag.voltage_measurement = 1;
				
				// Check if alarm needs to be turned on
				//check_alarm(); //gibbons TODO: remove
			}

			// -------------------------------------------------------------------
			// Service active modules that require 1/s processing
			
#ifdef CONFIG_EGGTIMER
			if (sEggtimer.state == EGGTIMER_RUN) {
				eggtimer_tick(); // Subtract 1 second from eggtimer's count
			}
			
			if (sEggtimer.state == EGGTIMER_ALARM) { // no "else if" intentional
				// Decrement alarm duration counter
				if (sEggtimer.duration-- > 0)
				{
					request.flag.eggtimer_buzzer = 1;
				}
				else
				{
					stop_eggtimer_alarm(); // Set state to Stop and reset duration
				}
			}
#endif
			
			// Generate alarm signal
			if (sAlarm.state == ALARM_ON) 
			{
				// Decrement alarm duration counter
				if (sAlarm.duration-- > 0)
				{
					request.flag.alarm_buzzer = 1;
				}
				else
				{
					stop_alarm();
				}
			}

#ifdef CONFIG_PROUT
			if (is_prout()) prout_tick();
#endif

#ifdef CONFIG_VARIO
			if(is_vario()) vario_tick();
#endif

#ifdef CONFIG_STRENGTH
			// One more second gone by.
			if(is_strength())
			{
				strength_tick();
			}            
#endif

			// Do a temperature measurement each second while menu item is active
			if (is_temp_measurement()) request.flag.temperature_measurement = 1;
			
			// Do a pressure measurement each second while menu item is active
#ifdef CONFIG_ALTITUDE
			if (is_altitude_measurement()) 
			{
				// Countdown altitude measurement timeout while menu item is active
				sAlt.timeout--;

				// Stop measurement when timeout has elapsed
				if (sAlt.timeout == 0)	
				{
					stop_altitude_measurement();
					// Show ---- m/ft
					display_chars(LCD_SEG_L1_3_0, (u8*)"----", SEG_ON);
					// Clear up/down arrow
					display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
					display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
				}
				
				// In case we missed the IRQ due to debouncing, get data now
				if ((PS_INT_IN & PS_INT_PIN) == PS_INT_PIN) request.flag.altitude_measurement = 1;
			}	
#endif

#ifdef FEATURE_PROVIDE_ACCEL
			// Count down timeout
			if (is_acceleration_measurement()) 
			{
				// Countdown acceleration measurement timeout 
				sAccel.timeout--;

				// Stop measurement when timeout has elapsed
				if (sAccel.timeout == 0) as_stop();	
				
				// If DRDY is (still) high, request data again
				if ((AS_INT_IN & AS_INT_PIN) == AS_INT_PIN) request.flag.acceleration_measurement = 1; 
			}	
#endif

			//pfs
#ifndef ELIMINATE_BLUEROBIN
			// If BlueRobin transmitter is connected, get data from API
			if (is_bluerobin()) get_bluerobin_data();
#endif
			
			// If battery is low, decrement display counter
			if (sys.flag.low_battery)
			{
				if (sBatt.lobatt_display-- == 0) 
				{
					message.flag.prepare = 1;
					message.flag.type_lobatt = 1;
					sBatt.lobatt_display = BATTERY_LOW_MESSAGE_CYCLE;
				}
			}
			
			// If a message has to be displayed, set display flag
			if (message.all_flags)
			{
				if (message.flag.prepare)
				{
					message.flag.prepare = 0;
					message.flag.show    = 1;
				}
				else if (message.flag.erase) // message cycle is over, so erase it
				{
					message.flag.erase       = 0;
					message.flag.block_line1 = 0;
					message.flag.block_line2 = 0;
					display.flag.full_update = 1;
				}	
			}
			
			// -------------------------------------------------------------------
			// Check idle timeout, set timeout flag
			if (sys.flag.idle_timeout_enabled)
			{
			    if (sTime.last_activity > 0) {
				if (--sTime.last_activity == 0) sys.flag.idle_timeout = 1; //setFlag(sysFlag_g, SYS_TIMEOUT_IDLE);
			    }
			}
			
			// -------------------------------------------------------------------
			// Detect continuous button high states

			if (BUTTON_STAR_IS_PRESSED && BUTTON_UP_IS_PRESSED)
			{
				if (button_beep_counter++ > LEFT_BUTTON_LONG_TIME)
				{
					// Toggle no_beep buttons flag
					sys.flag.no_beep = ~sys.flag.no_beep;
			
					// Show "beep / nobeep" message synchronously with next second tick
					message.flag.prepare = 1;
					if (sys.flag.no_beep)	message.flag.type_no_beep_on   = 1;
					else					message.flag.type_no_beep_off  = 1;
					
					// Reset button beep counter
					button_beep_counter = 0;
				}
			} else if (BUTTON_NUM_IS_PRESSED && BUTTON_DOWN_IS_PRESSED) // Trying to lock/unlock buttons?
			{
				if (button_lock_counter++ > LEFT_BUTTON_LONG_TIME)
				{
					// Toggle lock / unlock buttons flag
					sys.flag.lock_buttons = ~sys.flag.lock_buttons;
			
					// Show "buttons are locked/unlocked" message synchronously with next second tick
					message.flag.prepare = 1;
					if (sys.flag.lock_buttons)	message.flag.type_locked   = 1;
					else						message.flag.type_unlocked = 1;
					
					// Reset button lock counter
					button_lock_counter = 0;
				}
			}
			else // Trying to create a long button press?
			{
				// Reset button lock counter
				button_lock_counter = 0;
				
				if (BUTTON_STAR_IS_PRESSED) 	
				{
					sButton.star_timeout++;
					
					// Check if button was held low for some seconds
					if (sButton.star_timeout > LEFT_BUTTON_LONG_TIME) 
					{
						button.flag.star_long = 1;
						sButton.star_timeout = 0;
					}
				}
				else
				{
					sButton.star_timeout = 0;
				}
			
				if (BUTTON_NUM_IS_PRESSED) 	
				{
					sButton.num_timeout++;
				
					// Check if button was held low for some seconds
					if (sButton.num_timeout > LEFT_BUTTON_LONG_TIME) 
					{
						button.flag.num_long = 1;
						sButton.num_timeout = 0;
					}
				}
				else
				{
					sButton.num_timeout = 0;
				}
			}
			
			
			// Exit from LPM3 on RETI
			_BIC_SR_IRQ(LPM3_bits); //gibbons TODO: move this to other interrupts from the RTC?
			
			break;
			
		case RTC_RTCTEVIFG: // Interval alarm event (min or hour changed, or rollover to midnight or noon) (choose one)
			// Minute, hour, noon, or midnight rollover beep (same beep as button press, at least for now)
#ifdef CONFIG_TIMECHIME
#ifdef CONFIG_CW
			CW_Send_String(CW_Message);
#else
			start_buzzer(1, CONV_MS_TO_TICKS(20), CONV_MS_TO_TICKS(150));
#endif
			if (RTC_Toggle_12Hr) RTCCTL01 ^= 0x0100; // Toggle Time EVent between noon and midnight
#endif
			break;
			
		case RTC_RTCAIFG: // User-configurable alarm event
			// Indicate that alarm is on
			sAlarm.state = ALARM_ON;
			
			break;
	}

	//gibbons: TODO: Remove this old code? (Associated with Timer0_A0 1-sec ISR)
	// Disable IE 
	//TA0CCTL0 &= ~CCIE;
	// Reset IRQ flag  
	//TA0CCTL0 &= ~CCIFG;  
	// Add 1 sec to TACCR0 register (IRQ will be asserted at 0x7FFF and 0xFFFF = 1 sec intervals)
	//TA0CCR0 += 32768; //gibbons TODO: Should this perhaps be (32768 - 1) ?
	// Enable IE 
	//TA0CCTL0 |= CCIE;
}
Exemple #17
0
// *************************************************************************************************
// @fn          altitude_accumulator_periodic
// @brief       Is called periodically, reads altitude and accumulates upwards vertical
// @param       none
// @return      none
//
// This function is called once a minute. It reads the current altitude, then uses that to accumulate
// upwards altitude only (it does not measure or accumulate downwards altitude - only altitude gains.
// It functions as follows. Current direction (either up or down) is given in alt_accum_direction.
//
// If we're currently going up, then alt_accum_lastpeakdip contains the altitude of the last dip (valley)
// we encountered and we're rising up above that. If the current altimeter value is greater than the
// previous altimeter reading alt_accum_prevalt, then update alt_accum_prevalt with the current altitude
// and we're done. If however we've dropped below the previous value, then if we've exceeded our
// "direction change threshold" ALT_ACCUM_DIR_THRESHOLD, then it appears we've peaked and have started
// heading downhill. So add (alt_accum_prevalt - alt_accum_lastpeakdip) to alt_accum__accumtotal to
// collect that recently-finished uphill into our accumulated uphill total. Then reverse course:
// set alt_accum_lastpeakdip equal to alt_accum_prevalt so that lastpeakdip contains the altitude of the
// top of that recently-crossed hill (it's now a peak altitude rather than a dip (valley) altitude),
// change the alt_accum_direction flag to downhill, and as usual set the alt_accum_prevalt to our current
// altitude.
//
// On the other hand, if our current altitude is only slightly less than the previous altitude, then
// do nothing - not even update our "previous" altitude. When we're going uphill, only 2 things matter to
// us: either we've gone uphill some more, or we've gone downhill enough to trigger the change-or-direction
// threshold.
//
// If we're going downhill (direction flag alt_accum_direction says downhill), there's little to do except
// keep updating alt_accum_prevalt with the current altitude if we've dropped lower, and watch for a
// change of direction to an uphill. Much the same as the uphill case, but we don't accumulate downhills
// once the change of direction occurs.
//
// In addition, independently of all this, we also update alt_accum_max with the highest altitude
// we've found.
//
// All measurements are recorded & stored in metres.
//
// Yes it's a bit convoluted. That's OK. The basic thing to understand is that a "simple" accumulator
// simply adds altitude every time we take an altimeter reading. However every reading has an error, so
// adding a bunch of readings results in a lot of error. For that reason we have this more complicated
// system whereby we look for peaks and dips, and only add to the accumulator when we find the next peak.
// In that way we obtain the best accumulator accuracy possible. It does make for a more complicated
// system though.
//
// *************************************************************************************************
void altitude_accumulator_periodic (void)
{
    s32 currentalt;					// our current altitude

    // First a quick sanity check. If we're not supposed to be running, something's wrong, so just exit
    if (alt_accum_enable==0) return;

    // First thing we need to know is our current altitude. Take 4 measurements & average them.
    start_altitude_measurement();
    stop_altitude_measurement();
    currentalt = sAlt.altitude;			// first reading

    // Now it's comparisions time. First we'll quickly update the maximum altitude tracker
    if (currentalt > alt_accum_max)
        alt_accum_max = currentalt;		// update max altitude if we're at a new high

    // Now our convoluted altitude accumulator, looking for peaks and valleys, etc.
    if (alt_accum_direction) {
        // Execute here if we're supposedly going upwards
        if (currentalt >= alt_accum_prevalt) {
            // Execute here if we're still going upwards - current alt is greater than previous alt
            alt_accum_prevalt = currentalt;	// just update our "previous" value for next time
            return;								// and that's it - we're done
        }
        else {
            // Execute here if our current altitude is below our previous - have we crested the hill and
            // started to descend? If we've exceeded the threshold altitude drop we need to deal with that.
            if ((alt_accum_prevalt - currentalt) >= ALT_ACCUM_DIR_THRESHOLD) {
                // Execute here if we've descended enough off the hillcrest to exceed the threshold - we've just
                // gone through a change of direction, so we need to accumulate the previously gained altitude,
                // then set things up for going downhill now.
                alt_accum__accumtotal += alt_accum_prevalt - alt_accum_lastpeakdip;	// accumulate the vertical from that last hill climb
                alt_accum_lastpeakdip = alt_accum_prevalt;				// peakdip is now a peak elevation
                alt_accum_direction = 0;						// indicate we're tracking downhill now
                return;
            }
            else	// we've dropped a little, but not enough to trigger any action yet
                return;
        }
    }
    else {
        // Execute here if we're supposedly going downwards
        if (currentalt <= alt_accum_prevalt) {
            // Execute here if we're still going downwards - current alt is less than previous alt
            alt_accum_prevalt = currentalt;		// just update our "previous" value for next time
            return;					// and that's it - we're done
        }
        else {
            // Execute here if our current altitude is above our previous - have we bottomed the valley and
            // started to ascend? If we've exceeded the threshold altitude increase we need to deal with that.
            if ((currentalt - alt_accum_prevalt) >= ALT_ACCUM_DIR_THRESHOLD) {
                // Execute here if we've ascended enough above the valley floor to exceed the threshold - we've just
                // gone through a change of direction, so we need to set things up for going uphill now.
                alt_accum_lastpeakdip = alt_accum_prevalt;	// peakdip is now a dip (valley) elevation
                alt_accum_direction = 1;			// indicate we're tracking uphill now
                return;
            }
            else	// we've ascended a little, but not enough to trigger any action yet
                return;
        }
    }
}
Exemple #18
0
// *************************************************************************************************
// @fn          test_mode
// @brief       Manual test mode. Activated by holding buttons STAR and UP simultaneously. 
//				Cancelled by any other button press.
// @param      	none
// @return      none
// *************************************************************************************************
void test_mode(void)
{
	u8 test_step, start_next_test;
	u8 * str;
	u8 i;
	
	// Disable timer - no need for a clock tick
	Timer0_Stop();
	
	// Disable LCD charge pump while in standby mode 
	// This reduces current consumption by ca. 5?A to ca. 10?A
	LCDBVCTL = 0;
	
	// Show welcome screen 
	display_chars(LCD_SEG_L1_3_0, (u8*)"0430", SEG_ON);
	display_chars(LCD_SEG_L2_4_0, (u8*)"CC430", SEG_ON);
	display_symbol(LCD_SEG_L1_COL, SEG_ON);
	display_symbol(LCD_ICON_HEART, SEG_ON);
	display_symbol(LCD_ICON_STOPWATCH, SEG_ON);
	display_symbol(LCD_ICON_RECORD, SEG_ON);
	display_symbol(LCD_ICON_ALARM, SEG_ON);
	display_symbol(LCD_ICON_BEEPER1, SEG_ON);
	display_symbol(LCD_ICON_BEEPER2, SEG_ON);
	display_symbol(LCD_ICON_BEEPER3, SEG_ON);
	display_symbol(LCD_SYMB_ARROW_UP, SEG_ON);
	display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON);
	display_symbol(LCD_SYMB_AM, SEG_ON);

	// Hold watchdog
	WDTCTL = WDTPW + WDTHOLD;

	// Wait for button press 
	_BIS_SR(LPM3_bits + GIE); 
	__no_operation();

	// Clear display
	display_all_off();
	
#ifdef USE_LCD_CHARGE_PUMP
	// Charge pump voltage generated internally, internal bias (V2-V4) generation
	// This ensures that the contrast and LCD control is constant for the whole battery lifetime
	LCDBVCTL = LCDCPEN | VLCD_2_72;
#endif
	
	// Renenable timer
	Timer0_Start();
	
	// Debounce button press
	Timer0_A4_Delay(CONV_MS_TO_TICKS(100));
		
	while(1)
	{
		// Check button event
		if (BUTTON_STAR_IS_PRESSED && BUTTON_UP_IS_PRESSED)
		{
			// Start with test #0
			test_step = 0;
			start_next_test = 1;
			while(1)
			{
				if (start_next_test)
				{
					// Clean up previous test display
					display_all_off();
					
					start_next_test = 0;

					switch (test_step)
					{
						case 0: // All LCD segments on
								display_all_on(); 
								// Wait until buttons are off
								while (BUTTON_STAR_IS_PRESSED && BUTTON_UP_IS_PRESSED);
								break;
						case 1:	// Altitude measurement
#ifdef CONFIG_ALTITUDE
								display_altitude(LINE1, DISPLAY_LINE_UPDATE_FULL);
								for (i=0; i<2; i++)
								{
									while((PS_INT_IN & PS_INT_PIN) == 0); 
									do_altitude_measurement(FILTER_OFF);
									display_altitude(LINE1, DISPLAY_LINE_UPDATE_PARTIAL);
								}
								stop_altitude_measurement();	
#endif
								break;
						case 2: // Temperature measurement
								display_temperature(LINE1, DISPLAY_LINE_UPDATE_FULL);
								for (i=0; i<4; i++)
								{
									Timer0_A4_Delay(CONV_MS_TO_TICKS(250));
									temperature_measurement(FILTER_OFF);
									display_temperature(LINE1, DISPLAY_LINE_UPDATE_PARTIAL);
								}
								break;
						case 3: // Acceleration measurement
								as_start();
								for (i=0; i<4; i++)
								{
									Timer0_A4_Delay(CONV_MS_TO_TICKS(250));
									as_get_data(sAccel.xyz);
									str = itoa( sAccel.xyz[0], 3, 0);
									display_chars(LCD_SEG_L1_2_0, str, SEG_ON);
									str = itoa( sAccel.xyz[2], 3, 0);
									display_chars(LCD_SEG_L2_2_0, str, SEG_ON);
								}
								as_stop();
								break;
						//pfs
						#ifndef ELIMINATE_BLUEROBIN
						case 4:	// BlueRobin test
								button.flag.up = 1;
								sx_bluerobin(LINE1);
								Timer0_A4_Delay(CONV_MS_TO_TICKS(100));
								get_bluerobin_data();
								display_heartrate(LINE1, DISPLAY_LINE_UPDATE_FULL);
								stop_bluerobin();
								break;
						#endif
					}
					
					// Debounce button
					Timer0_A4_Delay(CONV_MS_TO_TICKS(200));
				}
				
				// Check button event
				if (BUTTON_STAR_IS_PRESSED) 
				{
					test_step = 1;
					start_next_test = 1;
				}
				else if (BUTTON_NUM_IS_PRESSED) 
				{
					test_step = 2;
					start_next_test = 1;
				}
				else if (BUTTON_UP_IS_PRESSED) 
				{
					test_step = 3;
					start_next_test = 1;
				}
				else if (BUTTON_DOWN_IS_PRESSED) 
				{
					test_step = 4;
					start_next_test = 1;
				}
				else if (BUTTON_BACKLIGHT_IS_PRESSED) 
				{
					// Wait until button has been released (avoid restart)
					while (BUTTON_BACKLIGHT_IS_PRESSED);

					// Disable LCD and LCD charge pump
					LCDBCTL0 &= ~BIT0;
					LCDBVCTL  = 0;
					
					// Debounce button press
					Timer0_A4_Delay(CONV_MS_TO_TICKS(500));

					// Disable timer - no need for a clock tick
					Timer0_Stop();
					
					// Hold watchdog
					WDTCTL = WDTPW + WDTHOLD;
					
					// Sleep until button is pressed (ca. 4?A current consumption)
					_BIS_SR(LPM4_bits + GIE);
					__no_operation();
				
					// Force watchdog reset for a clean restart 
					WDTCTL = 1; 
				}
				
#ifdef USE_WATCHDOG		
				// Service watchdog
				WDTCTL = WDTPW + WDTIS__512K + WDTSSEL__ACLK + WDTCNTCL;
#endif
				// To LPM3
				_BIS_SR(LPM3_bits + GIE);  
				__no_operation();
			}
		}
		else
		{
			// Debounce button
			Timer0_A4_Delay(CONV_MS_TO_TICKS(100));
			button.all_flags = 0;
			break;
		}
	}
}
Exemple #19
0
// *************************************************************************************************
// @fn          display_alt_accumulator
// @brief       Display altitude accumulator routine. Supports display in meters and feet.
// @param       u8 line			LINE1
//				u8 update		DISPLAY_LINE_UPDATE_FULL, DISPLAY_LINE_UPDATE_PARTIAL, DISPLAY_LINE_CLEAR
// @return      none
// *************************************************************************************************
void display_alt_accumulator (u8 line, u8 update)
{
    s32 temp;
    u8 * str;


    // show our altitude accumulator numbers on the second line
    if ( (update==DISPLAY_LINE_UPDATE_FULL) || (update==DISPLAY_LINE_UPDATE_PARTIAL) )
    {
        // Show "ALtA" on top line
        display_chars(LCD_SEG_L1_3_0, (u8*)"ALTA", SEG_ON);

        // if the altitude accumulator is currently disabled, we've got nothing else to display so exit
        if (alt_accum_enable == 0) {
            clear_line(LINE2);
            display_chars(LCD_SEG_L2_4_0, (u8*)" OFF ", SEG_ON);	// display "OFF" on bottom line
            return;
        }

        // Otherwise the accumulator is running, so display on the second line whatever alt_accum_displaycode
        // says to display, in metres or feet as appropriate.
        if (alt_accum_displaycode>2) alt_accum_displaycode=0;		// sanity check

        // light up "m" or "ft" display symbol as appropriate
        if (sys.flag.use_metric_units)
            display_symbol(LCD_UNIT_L1_M, SEG_ON);			// metres symbol
        else
            display_symbol(LCD_UNIT_L1_FT, SEG_ON);			// or feet symbol

        if (alt_accum_displaycode==0)
        {
            // Display current altitude relative to the accumulator's starting point
            // "DIFF" means difference between starting elevation & current elevation
            display_chars(LCD_SEG_L1_3_0, (u8*)"DIFF", SEG_ON);		// top line display message

            start_altitude_measurement();
            stop_altitude_measurement();					// grab our current altitude

            temp = sAlt.altitude - alt_accum_startpoint;	// difference between starting altitude & current altitude
            if (sys.flag.use_metric_units==0) temp = (temp*328)/100;	// convert to feet if necessary

            clear_line(LINE2);						// clear the bottom line of the display
            if (temp < 0) {							// if altitude is a negative number...
                display_char(LCD_SEG_L2_4, '-', SEG_ON);		// display - (negative sign) character at start of second line
                temp = 0 - temp;					// make altitude a positive number again so we can display it
                if (temp>9999) temp = 9999;				// we can only display 4 digits for a negative number
                str = _itoa(temp, 4, 3);					// 4 digits, up to 3 leading blank digits
                display_chars(LCD_SEG_L2_3_0, str, SEG_ON);		// display altitude difference on bottom line (4 digits)
                return;
            }
            else								// otherwise altitude difference is a positive number
            {
                str = _itoa(temp, 5, 4);					// 5 digits, up to 4 leading blank digits
                display_chars(LCD_SEG_L2_4_0, str, SEG_ON);		// display altitude difference on bottom line (5 digits)
                return;
            }
        }

        else if (alt_accum_displaycode==1)
        {
            // Display total accumulated elevation gain. Remember we might currently be going uphill
            // so we need to check for, and include, any current elevation gain
            display_chars(LCD_SEG_L1_3_0, (u8*)"ACCA", SEG_ON);		// top line display message
            clear_line(LINE2);						// clear the bottom line of the display

            if (alt_accum__accumtotal<0) alt_accum__accumtotal = 0;	// accumulated total should never be negative!
            temp = alt_accum__accumtotal;				// local copy of accumulated total

            // Now we need to add on any vertical gained recently, that hasn't yet been included in alt_accum__accumtotal
            // This only happens if we're currently going uphill, and we've above our last valley / dip elevation
            if (alt_accum_direction && (sAlt.altitude>alt_accum_lastpeakdip))	// if we're going up, and we're higher than our last dip (valley) altitude
                temp += sAlt.altitude - alt_accum_lastpeakdip;			// then add the vertical we've gained so far above that last dip / valley point

            // display the result
            str = _itoa(temp, 5, 4);					// 5 digits, up to 4 leading blank digits
            display_chars(LCD_SEG_L2_4_0, str, SEG_ON);		// display peak altitude on bottom line (5 digits)
            return;
        }

        else
        {
            // Display maximum altitude found so far
            display_chars(LCD_SEG_L1_3_0, (u8*)"PEAK", SEG_ON);	// top line display message
            clear_line(LINE2);					// clear the bottom line of the display

            temp = alt_accum_max;					// local copy of peak altitude
            if (temp < 0) temp = 0;					// I can't be bothered displaying a negative number! So make it zero if it is.
            str = _itoa(temp, 5, 4);					// 5 digits, up to 4 leading blank digits
            display_chars(LCD_SEG_L2_4_0, str, SEG_ON);		// display peak altitude on bottom line (5 digits)
            return;
        }
    }


    // clear out - we're finished
    else if (update == DISPLAY_LINE_CLEAR)
    {
        clear_line(LINE2);			// clear off the altitude display from the second line
        // should really try to get the date displayed here again

        // Clean up function-specific segments before leaving function
        display_symbol(LCD_UNIT_L1_M, SEG_OFF);
        display_symbol(LCD_UNIT_L1_FT, SEG_OFF);
        display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
    }
}
// *************************************************************************************************
// @fn          display_altitude
// @brief       Display routine. Supports display in meters and feet. 
// @param       u8 line         LINE1
//              u8 update       DISPLAY_LINE_UPDATE_FULL, DISPLAY_LINE_UPDATE_PARTIAL, DISPLAY_LINE_CLEAR
// @return      none
// *************************************************************************************************
void display_altitude(u8 line, u8 update)
{
    u8 * str;
    s16 ft;
    
    // redraw whole screen
    if (update == DISPLAY_LINE_UPDATE_FULL) 
    {
        // Enable pressure measurement
        sAlt.state = MENU_ITEM_VISIBLE;

        // Start measurement
        start_altitude_measurement();
        
        // Display altitude
        display_altitude(LINE1, DISPLAY_LINE_UPDATE_PARTIAL);
    }
    else if (update == DISPLAY_LINE_UPDATE_PARTIAL)
    {
        // Update display only while measurement is active
        if (sAlt.timeout > 0)
        {
            // Altitude view
            if (PressDisplay == DISPLAY_DEFAULT_VIEW)
            {
                display_symbol(LCD_SEG_L1_DP1, SEG_OFF);
                if (sys.flag.use_metric_units)
                {
                    // Display "m" symbol
                    display_symbol(LCD_UNIT_L1_M, SEG_ON);
                    // Display altitude in xxxx m format, allow 3 leading blank digits
                    if (sAlt.altitude >= 0)
                    {
                        str = itoa(sAlt.altitude, 4, 3);
                        display_symbol(LCD_SYMB_ARROW_UP, SEG_ON);
                        display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
                    }
                    else
                    {
                        str = itoa(sAlt.altitude*(-1), 4, 3);
                        display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
                        display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON);
                    }
                }
                else
                {
                    // Display "ft" symbol
                    display_symbol(LCD_UNIT_L1_FT, SEG_ON);                 
                    
                    // Convert from meters to feet
                    ft = convert_m_to_ft(sAlt.altitude);
                    
                    // Limit to 9999ft (3047m)
                    if (ft > 9999) ft = 9999;
                    
                    // Display altitude in xxxx ft format, allow 3 leading blank digits
                    if (ft >= 0)
                    {
                        str = itoa(ft, 4, 3);
                        display_symbol(LCD_SYMB_ARROW_UP, SEG_ON);
                        display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
                    }
                    else
                    {
                        str = itoa(ft*(-1), 4, 3);
                        display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
                        display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON);
                    }               
                }
            }
            // Pressure view, unit: milliBar = hectoPascal
            else if (PressDisplay == DISPLAY_ALTERNATIVE_VIEW)
            {
                display_symbol(LCD_SEG_L1_DP1, SEG_OFF);
                display_symbol(LCD_UNIT_L1_M, SEG_OFF);
                display_symbol(LCD_UNIT_L1_FT, SEG_OFF);
                display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
                display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
                str = itoa(AmbientPressure, 4, 3);
            }
            // Pressure view, unit: PSI (Pound-force per square inch absolute) 1mbar = 0.01450377 PSI
            else  // DISPLAY_ALTERNATIVE_VIEW_2
            {
                str = itoa((u32)AmbientPressure * 10000L / 6895L, 4, 3);
                display_symbol(LCD_SEG_L1_DP1, SEG_ON);
            }
            display_chars(LCD_SEG_L1_3_0, str, SEG_ON);
        }
    }
    else if (update == DISPLAY_LINE_CLEAR)
    {
        // Disable pressure measurement
        sAlt.state = MENU_ITEM_NOT_VISIBLE;

        // Stop measurement
        stop_altitude_measurement();
        
        // Clean up function-specific segments before leaving function
        display_symbol(LCD_SEG_L1_DP1, SEG_OFF);
        display_symbol(LCD_UNIT_L1_M, SEG_OFF);
        display_symbol(LCD_UNIT_L1_FT, SEG_OFF);
        display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF);
        display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF);
    }
}