You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

471 lines
14 KiB

// *************************************************************************************************
//
// Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
//
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the
// distribution.
//
// Neither the name of Texas Instruments Incorporated nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// *************************************************************************************************
// Altitude measurement functions.
// *************************************************************************************************
// *************************************************************************************************
// Include section
// system
#include "project.h"
#ifdef FEATURE_ALTITUDE
// driver
#include "altitude.h"
#include "display.h"
#include "vti_ps.h"
#include "ports.h"
#include "timer.h"
// logic
#include "user.h"
#ifdef CONFIG_VARIO
# include "vario.h"
#endif
// *************************************************************************************************
// Prototypes section
// *************************************************************************************************
// Defines section
// *************************************************************************************************
// Global Variable section
struct alt sAlt;
// *************************************************************************************************
// Extern section
// Global flag for pressure sensor initialisation status
extern u8 ps_ok;
// *************************************************************************************************
// @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);
}
}
}
#ifndef CONFIG_METRIC_ONLY
// *************************************************************************************************
// @fn conv_m_to_ft
// @brief Convert meters to feet
// @param u16 m Meters
// @return u16 Feet
// *************************************************************************************************
s16 convert_m_to_ft(s16 m)
{
return (((s32)328*m)/100);
}
// *************************************************************************************************
// @fn conv_ft_to_m
// @brief Convert feet to meters
// @param u16 ft Feet
// @return u16 Meters
// *************************************************************************************************
s16 convert_ft_to_m(s16 ft)
{
return (((s32)ft*61)/200);
}
#endif
// *************************************************************************************************
// @fn is_altitude_measurement
// @brief Altitude measurement check
// @param none
// @return u8 1=Measurement ongoing, 0=measurement off
// *************************************************************************************************
u8 is_altitude_measurement(void)
{
return ((sAlt.state == MENU_ITEM_VISIBLE) && (sAlt.timeout > 0));
}
// *************************************************************************************************
// @fn start_altitude_measurement
// @brief Start altitude measurement
// @param none
// @return none
// *************************************************************************************************
void start_altitude_measurement(void)
{
// Show warning if pressure sensor was not initialised properly
if (!ps_ok)
{
display_chars(LCD_SEG_L1_2_0, (u8*)"ERR", SEG_ON);
return;
}
// Start altitude measurement if timeout has elapsed
if (sAlt.timeout == 0)
{
// Enable DRDY IRQ on rising edge
PS_INT_IFG &= ~PS_INT_PIN;
PS_INT_IE |= PS_INT_PIN;
// Start pressure sensor
ps_start();
// Set timeout counter only if sensor status was OK
sAlt.timeout = ALTITUDE_MEASUREMENT_TIMEOUT;
// Get updated altitude
while((PS_INT_IN & PS_INT_PIN) == 0);
do_altitude_measurement(FILTER_OFF);
}
}
// *************************************************************************************************
// @fn stop_altitude_measurement
// @brief Stop altitude measurement
// @param none
// @return none
// *************************************************************************************************
void stop_altitude_measurement(void)
{
// Return if pressure sensor was not initialised properly
if (!ps_ok) return;
// Stop pressure sensor
ps_stop();
// Disable DRDY IRQ
PS_INT_IE &= ~PS_INT_PIN;
PS_INT_IFG &= ~PS_INT_PIN;
// Clear timeout counter
sAlt.timeout = 0;
}
// *************************************************************************************************
// @fn do_altitude_measurement
// @brief Perform single altitude measurement
// @param none
// @return none
// *************************************************************************************************
void do_altitude_measurement(u8 filter)
{
volatile u32 pressure;
// If sensor is not ready, skip data read
if ((PS_INT_IN & PS_INT_PIN) == 0) return;
// Get temperature (format is *10?K) from sensor
sAlt.temperature = ps_get_temp();
// Get pressure (format is 1Pa) from sensor
pressure = ps_get_pa();
// Store measured pressure value
if (filter == FILTER_OFF) //sAlt.pressure == 0)
{
sAlt.pressure = pressure;
}
else
{
// Filter current pressure
#ifdef FIXEDPOINT
pressure = (u32)(((pressure * 2) + (sAlt.pressure * 8))/10);
#else
pressure = (u32)((pressure * 0.2) + (sAlt.pressure * 0.8));
#endif
// Store average pressure
sAlt.pressure = pressure;
}
// Convert pressure (Pa) and temperature (?K) to altitude (m).
#ifdef FIXEDPOINT
sAlt.altitude = conv_pa_to_altitude(sAlt.pressure, sAlt.temperature);
#else
sAlt.altitude = conv_pa_to_meter(sAlt.pressure, sAlt.temperature);
#endif
#ifdef CONFIG_VARIO
// Stash a copy to the vario after filtering. If doing so before, there
// is just too much unnecessary fluctuation, up to +/- 7Pa seen.
vario_p_write( pressure );
#endif
}
// *************************************************************************************************
// @fn sx_altitude
// @brief Altitude direct function. Sx restarts altitude measurement.
// @param u8 line LINE1, LINE2
// @return none
// *************************************************************************************************
void sx_altitude(u8 line)
{
// Function can be empty
// Restarting of altitude measurement will be done by subsequent full display update
}
// *************************************************************************************************
// @fn mx_altitude
// @brief Mx button handler to set the altitude offset.
// @param u8 line LINE1
// @return none
// *************************************************************************************************
void mx_altitude(u8 line)
{
s32 altitude;
s32 limit_high, limit_low;
// Clear display
clear_display_all();
// Set lower and upper limits for offset correction
#ifdef CONFIG_METRIC_ONLY
display_symbol(LCD_UNIT_L1_M, SEG_ON);
// Convert global variable to local variable
altitude = sAlt.altitude;
// Limits for set_value function
limit_low = -100;
limit_high = 4000;
#else
if (sys.flag.use_metric_units)
{
// Display "m" symbol
display_symbol(LCD_UNIT_L1_M, SEG_ON);
// Convert global variable to local variable
altitude = sAlt.altitude;
// Limits for set_value function
limit_low = -100;
limit_high = 4000;
}
else // English units
{
// Display "ft" symbol
display_symbol(LCD_UNIT_L1_FT, SEG_ON);
// Convert altitude in meters to feet
altitude = sAlt.altitude;
// Convert from meters to feet
altitude = convert_m_to_ft(altitude);
// Limits for set_value function
limit_low = -500;
limit_high = 9999;
}
#endif
// Loop values until all are set or user breaks set
while(1)
{
// Idle timeout: exit without saving
if (sys.flag.idle_timeout) break;
// Button STAR (short): save, then exit
if (button.flag.star)
{
// When using English units, convert ft back to m before updating pressure table
#ifndef CONFIG_METRIC_ONLY
if (!sys.flag.use_metric_units) altitude = convert_ft_to_m((s16)altitude);
#endif
// Update pressure table
update_pressure_table((s16)altitude, sAlt.pressure, sAlt.temperature);
// Set display update flag
display.flag.line1_full_update = 1;
break;
}
// Set current altitude - offset is set when leaving function
set_value(&altitude, 4, 3, limit_low, limit_high, SETVALUE_DISPLAY_VALUE + SETVALUE_FAST_MODE + SETVALUE_DISPLAY_ARROWS, LCD_SEG_L1_3_0, display_value1);
}
// Clear button flags
button.all_flags = 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
// *************************************************************************************************
#ifdef CONFIG_ALTITUDE
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_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)
{
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);
}
#ifndef CONFIG_METRIC_ONLY
}
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 = 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);
}
}
#endif
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);
}
}
#endif // CONFIG_ALTITUDE
#endif // FEATURE_ALTITUDE