// ************************************************************************************************* // @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) { // 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); } } }
// ************************************************************************************************* // @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); } } }
// ************************************************************************************************* // @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); } } }
// ************************************************************************************************* // @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(); } }
// ************************************************************************************************* // @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; } }
// ************************************************************************************************* // @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 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; } } }
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); } }
// ************************************************************************************************* // @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; }
// ************************************************************************************************* // @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); } }
void read_altitude(void) { // Start measurement start_altitude_measurement(); stop_altitude_measurement(); }
// ************************************************************************************************* // @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; } }
// ************************************************************************************************* // @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); } }