Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 1914 → Rev 1920

/Transportables_Koptertool/branch/test2/GPL_PKT_V3_6_7f_FC090b/osd/.directory
0,0 → 1,3
[Dolphin]
Timestamp=2013,3,11,20,48,32
ViewMode=1
/Transportables_Koptertool/branch/test2/GPL_PKT_V3_6_7f_FC090b/osd/osd.c
0,0 → 1,2725
/*****************************************************************************
* Copyright (C) 2008 Thomas Kaiser, thomas@ft-fanpage.de *
* Copyright (C) 2009 Peter "woggle" Mack, mac@denich.net *
* Copyright (C) 2011 Christian "Cebra" Brandtner, brandtner@brandtner.net *
* Copyright (C) 2011 Harald Bongartz *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
* Credits to: *
* Holger Buss & Ingo Busker from mikrokopter.de for the MK project + SVN *
* http://www.mikrokopter.de *
* Gregor "killagreg" Stobrawa for his version of the MK code *
* Thomas Kaiser "thkais" for the original project. See *
* http://www.ft-fanpage.de/mikrokopter/ *
* http://forum.mikrokopter.de/topic-4061-1.html *
* Claas Anders "CaScAdE" Rathje for providing the font and his C-OSD code *
* http://www.mylifesucks.de/oss/c-osd/ *
* Harald Bongartz "HaraldB" for providing his Ideas and Code for usibility*
*****************************************************************************/
 
//############################################################################
//# HISTORY osd.c
//#
//# 10.03.2013 OG
//# - fix: doppelte Degree-Anzeige in OSD_Element_CompassDegree()
//# - add: neuer Screen "MK-Status"
//# - add: 7 neue OSD-Flags
//# - chg: Screen-Refresh Zeit via timer2 (einstellbar durch define OSD_REFRESH_TIME)
//# - chg: mit define OSD_DEBUG_SCREEN kann ein zusaetzlicher Screen verwendet werden zum testen/entwickeln
//# - del: entfernt CFG2_HEIGHT_LIMIT in OSD_Element_AltitudeControl() (bis bessere Loesung gefunden ist)
//#
//# 08.03.2013 OG
//# - del: OSD_Screen_Element() und cleanup in osd.h
//# - add: OSD_Element_UpDown() (steigend/sinken via Pfeilen)
//# - chg: OSD_Element_UpDown() in Screen "General" und "Navigation" hinzugefuegt (rechts neben der Hoehenanzeige)
//# - chg: Screen "General" die Sat-Warnung wurde auf OSD_Element_Flag(OSD_FLAG_S0) geaendert
//# - chg: Anzeige von Flag 'nicht genug GPS-Sateliten' (OSD_FLAG_S0) auf "S!" geändert
//#
//# 07.03.2013 OG
//# - Hinweis bzgl. LowBatt-Anzeige in den Screens "General" und "Navigation":
//# Es gibt zwei unabhängige LowBatt-Warnungen.
//# 1. die PKT LowBatt-Warnung: sie arbeitet mit der im PKT hinterlegten
//# LowBatt Spannung und stellt den Spannungswert inkl. der Einheit "V"
//# invers dar wenn der Warnwert erreicht wurde (inkl. lautem PKT-Peepen)
//# 2. die MK-LowBatt Warnung: hierbeit wird das Flag "BA" angezeigt wenn
//# der MK eine LowBatt Warnung sendet
//# Dadurch hat man nun zwei verschiedene LowBatt Warnungen die man auf Wunsch
//# verschieden einstellen kann. Bei mir ist die PKT-LowBatt etwas niedriger
//# eingestellt als die MK-Warnung und bedeutet "es ist aller hoechste Zeit zu landen".
//# Die Spannung der MK-LowBat ist ein wenig hoeher eingestellt und
//# zeigt mir "es ist bald Zeit zu landen".
//# - del: Kommunikation zu FC - siehe Kommentare in osd()
//# - chg: Kommunikation zu NC - siehe Kommentare in osd()
//# - add: neuer Screen "Navigation"
//# - chg: Layout Screen "Statistics" - Einheiten um zwei Pixel nach rechts verschoben
//# - chg: Layout von Screen "General" modifiziert (u.a. xoffs,yoffs Pixelverschiebungen)
//# - add: OSD_FLAG_BA in Screen "General"
//# - add: die OSD_Element_xyz() Funktionen in osd.h aufgenommen
//# - chg: an verschiedenen Stellen die Char-Drawmode defines MNORMAL, MINVERS, usw. eingebaut
//# - del: Kompatibilitaetscode fuer "3D-Lage" ueber Hauptmenue entfernt
//# - chg: die Funktionen OSD_Element_Switch() und OSD_Element_SwitchLabel() heissen
//# nun OSD_Element_Flag() und OSD_Element_Flag_Label()
//# - chg: die defines OSD_SWITCH_xy heissen jetzt OSD_FLAG_xy
//# - fix: letzte GPS-Koordinaten werden jetzt permanent Config.LastLatitude, Config.LastLongitude gespeichert
//#
//# 03.03.2013 OG
//# - add: delay in Mainloop von osd() um springende Werte abzudaempfen (TEST)
//# - add: Startverzoegerung der Screens bis NaviData sich etwas stabilisiert hat (TEST)
//# - add: OSD Startup Message "connecting MK..."
//# - add: 'Emergency Landing' (EL) Anzeige in Screen "General"
//# - del: OUT1/OUT2 Anzeige in Screen "General"
//# - add: RC-Quality in Screen "General"
//# - add: func: draw_symbol_rc() (alternative RC-Quality Symbol)
//# - fix: Hoehenanzeige fuer Screens "OSD0" und "OSD1"
//# - fix: OSD_Element_SwitchLabel() angepasst fuer x=0 und y=0
//# - add: OSD_Element_Switch/Label() erweitert um OSD_SWITCH_FS
//# - fix: Screen-Redraw nach OSD_Timeout() und anderen Fehlermeldungen
//# - chg: messages.c: STATS_ITEM_0 bis STATS_ITEM_6 angepasst (1 char kuerzer)
//# - chg: Layout von OSD_Info() - mehr background-clear und etwas kleiner
//#
//# 02.03.2013 OG
//# - chg: keine internal func in Screen's wegen warnings bei anderen
//# - del: Screen "OSD3"
//# - fix: Hoehenanzeige in Screen "General" (Minuszeichen)
//# - add: MK LowBat Warning in Screen "General"
//# - add: neues Degree Symbol (als func) in Screen General (kleiner als das Char 0x1E)
//# - add: weitere Flags in OSD_Element_Flag()
//#
//# 01.03.2013 OG
//# - Reskrukturierung Code (+ neuer OSD-Screens und einiges mehr)
//############################################################################
 
 
//############################################################################
//# HINWEISE:
//#
//# 1. define: OSD_DEMO
//# mit define OSD_DEMO wird ein Demo-Modus bei den neuen Screens einge-
//# schaltet - damit werden u.a. alle Flag's angezeigt fuer Scree-Fotos
//#
//# 2. define: OSD_DEBUG_SCREEN
//# mit diesem define wird ein zusaetzlicher Screen "Debug" einkompiliert
//# fuer Test / Experimente / Debug von OSD-Elementen
//#
//# 3. Informationen zum Display
//# DOG: 128 x 64 Pixel with 6x8 Font => 21 x 8
//############################################################################
 
 
#include "../cpu.h"
#include <avr/io.h>
#include <inttypes.h>
#include <stdlib.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
 
#include "../main.h"
#include "../osd/osd.h"
#include "../lcd/lcd.h"
#include "../timer/timer.h"
#include "../uart/usart.h"
#include "../eeprom/eeprom.h"
#include "../messages.h"
#include "../parameter.h"
#include "../sound/pwmsine8bit.h"
#include "../mk-data-structs.h"
 
 
//#define OSD_DEMO // zeigt Demo-Daten in den OSD-Screens (sofern vom Screen unterstuetzt)
//#define OSD_DEBUG_SCREEN // zusaetzlichen Debug-Screen aktivieren
 
#define OSD_REFRESH_TIME 45 // Screen Refresh; ein Wert von 100 entspricht ca. 1 Sekunde (Steuerung via timer2)
 
#define COSD_WASFLYING 4
#define TIMEOUT 200 // 2 sec
 
 
// Hier Höhenanzeigefehler Korrigieren
#define AltimeterAdjust 1.5
 
 
// global definitions and global vars
NaviData_t *naviData;
mk_param_struct_t *mk_param_struct;
uint8_t Flags_ExtraConfig;
uint8_t Flags_GlobalConfig;
uint8_t Flags_GlobalConfig3;
unsigned char Element;
uint16_t heading_home;
uint8_t drawmode;
 
// flags from last round to check for changes
uint8_t old_FCFlags = 0;
uint8_t old_AngleNick = 0;
uint8_t old_AngleRoll = 0;
uint16_t old_hh = 0;
 
// stats for after flight
int16_t max_Altimeter = 0;
uint16_t max_GroundSpeed = 0;
int16_t max_Distance = 0;
uint8_t min_UBat = 255;
uint16_t max_FlyingTime = 0;
uint16_t max_Current = 0;
uint16_t max_Capacity = 0;
 
// cache old vars for blinking attribute, checkup is faster than full
// attribute write each time
volatile uint8_t last_UBat = 255;
volatile uint8_t last_RC_Quality = 255;
 
volatile uint16_t ftimer = 0;
volatile uint8_t OSD_active;
 
uint8_t Vario_Beep_Up = 0;
uint8_t Vario_Beep_Down = 0;
uint8_t Vario_Beep_Up_Interval = 9;
uint8_t Vario_Beep_Down_Interval = 6;
uint8_t Vario_Threshold = 0;
uint8_t Vario_Threshold_Value = 7;
uint8_t OldWP = 0;
uint8_t NextWP = 0;
 
 
 
//char* rose = "-+-N-+-O-+-S-+-W-+-N-+-O-+-S-+-W-+-N-+-O-+-S-+-W";
const char rose[48] PROGMEM = {
0x0e, 0x0f, 0x0e, 'N', 0x0e, 0x0f, 0x0e, 'O', 0x0e, 0x0f, 0x0e, 'S',
0x0e, 0x0f, 0x0e, 'W', 0x0e, 0x0f, 0x0e, 'N', 0x0e, 0x0f, 0x0e, 'O',
0x0e, 0x0f, 0x0e, 'S', 0x0e, 0x0f, 0x0e, 'W', 0x0e, 0x0f, 0x0e, 'N',
0x0e, 0x0f, 0x0e, 'O', 0x0e, 0x0f, 0x0e, 'S', 0x0e, 0x0f, 0x0e, 'W',
};
 
// the center is char 19 (north), we add the current heading in 8th
// which would be 22.5 degrees, but float would bloat up the code
// and *10 / 225 would take ages... so we take the uncorrect way
 
const char str_NE[] PROGMEM = "NE";
const char str_E[] PROGMEM = "E ";
const char str_SE[] PROGMEM = "SE";
const char str_S[] PROGMEM = "S ";
const char str_SW[] PROGMEM = "SW";
const char str_W[] PROGMEM = "W ";
const char str_NW[] PROGMEM = "NW";
const char str_N[] PROGMEM = "N ";
const char *directions_p[8] PROGMEM = {
str_NE,
str_E,
str_SE,
str_S,
str_SW,
str_W,
str_NW,
str_N
};
 
 
#define MAX_CELL_VOLTAGE 43 // max cell voltage for LiPO
#define MIN_CELL_VOLTAGE 32 // min cell voltage for LiPO
 
// Flags
GPS_Pos_t last5pos[7];
uint8_t COSD_FLAGS2 = 0;
volatile uint8_t error = 0;
uint8_t cells = 0;
uint8_t BattLowVoltageWarning = 0;
uint8_t CellIsChecked = 0;
uint8_t AkkuWarnThreshold = 0;
uint16_t duration = 0;
 
 
 
//###########################################################
//###########################################################
 
//--------------------------------------------------------------
//--------------------------------------------------------------
void variobeep(int16_t vario)
{
{ //start Beep
 
if (vario >0 ) // MK steigt
{
Vario_Beep_Down = 0; // Down Beep freischalten
Vario_Threshold++;
 
if ((Vario_Beep_Up == 0) && (Vario_Threshold >= Vario_Threshold_Value))
{
// set_beep ( 100, 0xffff, BeepNormal);
duration = 52 -vario;
// if (duration =0); duration = 1;
 
// write_ndigit_number_u (0,6,duration,5,0);
 
playTone(300+vario*2,duration,Config.Volume);
// playTone(300,duration,volume);
Vario_Threshold = Vario_Threshold_Value; // auf Maximalwert begrenzen
}
Vario_Beep_Up++; // Interval hochzählen in dem nicht gepiept wird
if (Vario_Beep_Up == Vario_Beep_Up_Interval) Vario_Beep_Up = 0;
}
 
if (vario <0) // MK fällt
{
Vario_Beep_Up = 0; // Up Beep freischalten
Vario_Threshold++;
if ((Vario_Beep_Down == 0) && (Vario_Threshold >= Vario_Threshold_Value))
{
duration = 50 -vario;
// write_ndigit_number_u (0,7,duration,5,0);
// if (duration < vario) ; duration = 0;
// playTone(300,50,volume);
 
 
playTone(300+vario*2,duration,Config.Volume);
Vario_Threshold = Vario_Threshold_Value; // auf Maximalwert begrenzen
}
Vario_Beep_Down++; // Interval hochzählen in dem nicht gepiept wird
if (Vario_Beep_Down == Vario_Beep_Down_Interval) Vario_Beep_Down = 0;
}
 
if (vario == 0) Vario_Threshold = 0; //Startverzögerung löschen
} // end Beep
 
}
 
 
//--------------------------------------------------------------
// Diese Funktion Beept unabhaengig von der Einstellung Config.OSD_VarioBeep
// Aufruf ggf. mit: if( Config.OSD_VarioBeep ) Beep_Vario();
//
// Ansonten:
// -> hier noch aufräumen in Zusammenhang mit func variobeep()
//--------------------------------------------------------------
void Beep_Vario(void)
{
if ( (naviData->FCStatusFlags & FC_STATUS_MOTOR_RUN) && (naviData->FCStatusFlags2 & FC_STATUS2_ALTITUDE_CONTROL))
{ //start Beep
if (naviData->Variometer <0) // MK fällt
{
Vario_Beep_Up = 0; // Up Beep freischalten
Vario_Threshold++;
if ((Vario_Beep_Down == 0) && (Vario_Threshold >= Vario_Threshold_Value))
{
 
if (!Config.HWSound) set_beep ( 300, 0xffff, BeepNormal);
else variobeep(naviData->Variometer);
 
Vario_Threshold = Vario_Threshold_Value; // auf Maximalwert begrenzen
}
Vario_Beep_Down++; // Interval hochzählen in dem nicht gepiept wird
if (Vario_Beep_Down == Vario_Beep_Down_Interval) Vario_Beep_Down = 0;
}
 
if (naviData->Variometer == 0) Vario_Threshold = 0; //Startverzögerung löschen
 
if (naviData->Variometer >0 ) // MK steigt
{
Vario_Beep_Down = 0; // Down Beep freischalten
Vario_Threshold++;
 
if ((Vario_Beep_Up == 0) && (Vario_Threshold >= Vario_Threshold_Value))
{
if (!Config.HWSound) set_beep ( 100, 0xffff, BeepNormal);
else variobeep(naviData->Variometer);
Vario_Threshold = Vario_Threshold_Value; // auf Maximalwert begrenzen
}
Vario_Beep_Up++; // Interval hochzählen in dem nicht gepiept wird
if (Vario_Beep_Up == Vario_Beep_Up_Interval) Vario_Beep_Up = 0;
}
} // end Beep
}
 
 
 
//--------------------------------------------------------------
// Quelle Mikrokopter FC-Software Holger + Ingo
//--------------------------------------------------------------
void CheckMKLipo(void)
{
if(Config.MK_LowBat < 50) // automatische Zellenerkennung
{
if (CellIsChecked <= 2) //Nur beim Start 1x prüfen
{
// up to 6s LiPo, less than 2s is technical impossible
for(cells = 2; cells < 7; cells++)
{
if(naviData->UBat < cells * MAX_CELL_VOLTAGE) break;
}
BattLowVoltageWarning = cells * Config.MK_LowBat;
CellIsChecked++;
}
}
else BattLowVoltageWarning = Config.MK_LowBat;
 
if (naviData->UBat < BattLowVoltageWarning)
{
if (AkkuWarnThreshold <= 4) AkkuWarnThreshold++;
else
{ //Beeper ein
set_beep ( 1000, 0x0020, BeepSevere);
// BeepTime = 3000;
// BeepMuster = 0x0020;
}
}
}
 
 
//--------------------------------------------------------------
// convert the <heading> gotton from NC into an index
uint8_t heading_conv (uint16_t heading)
{
if (heading > 23 && heading < 68)
return 0; //direction = "NE";
else if (heading > 67 && heading < 113)
return 1; //direction = "E ";
else if (heading > 112 && heading < 158)
return 2; //direction = "SE";
else if (heading > 157 && heading < 203)
return 3; //direction = "S ";
else if (heading > 202 && heading < 248)
return 4; //direction = "SW";
else if (heading > 247 && heading < 293)
return 5; //direction = "W ";
else if (heading > 292 && heading < 338)
return 6; //direction = "NW";
 
return 7; //direction = "N ";
}
 
 
//--------------------------------------------------------------
// draw a compass rose at <x>/<y> for <heading>
void draw_compass (uint8_t x, uint8_t y, uint16_t heading)
{
uint8_t front = 19 + (heading / 22);
for (uint8_t i = 0; i < 9; i++)
lcd_putc (x++, y, pgm_read_byte(&rose[front - 4 + i]), 0);
}
 
 
//--------------------------------------------------------------
// variometer
// x, y in Pixel!
//--------------------------------------------------------------
void draw_variometer (uint8_t x, uint8_t y, uint8_t width, uint8_t hight, int16_t variometer)
{
lcd_rect (x, y - ((hight) / 2), width, hight, 1);
lcd_frect (x + 1, y - ((hight) / 2) + 1, width - 2, hight - 2, 0);
lcd_line (x, y, x + width, y, 1);
 
if (variometer > 0) // steigend
{
switch (variometer / 5)
{
case 0:
lcd_line (x + 4, y - 1, x + 6, y - 1, 1); // 1 > 4
break;
 
case 1:
lcd_line (x + 4, y - 1, x + 6, y - 1, 1); // 1 > 4
lcd_frect (x + 3, y - 3, 4, 1, 1); // 5 > 9
break;
 
case 2:
lcd_line (x + 4, y - 1, x + 6, y - 1, 1); // 1 > 4
lcd_frect (x + 3, y - 3, 4, 1, 1); // 5 > 9
lcd_frect (x + 2, y - 5, 6, 1, 1); // 10 > 14
break;
 
default:
lcd_line (x + 4, y - 1, x + 6, y - 1, 1); // 1 > 4
lcd_frect (x + 3, y - 3, 4, 1, 1); // 5 > 9
lcd_frect (x + 2, y - 5, 6, 1, 1); // 10 > 14
lcd_frect (x + 1, y - 6, 8, 1, 1); // 15 >
break;
}
}
else if (variometer < 0) // fallend
{
switch ((variometer) / -5)
{
case 0:
lcd_line (x + 4, y + 1, x + 6, y + 1, 1); // - 1 > - 4
break;
 
case 1:
lcd_line (x + 4, y + 1, x + 6, y + 1, 1); // - 1 > - 4
lcd_frect (x + 3, y + 2, 4, 1, 1); // - 5 > - 9
break;
 
case 2:
lcd_line (x + 4, y + 1, x + 6, y + 1, 1); // - 1 > - 4
lcd_frect (x + 3, y + 2, 4, 1, 1); // - 5 > - 9
lcd_frect (x + 2, y + 4, 6, 1, 1); // -10 > -14
break;
 
default:
lcd_line (x + 4, y + 1, x + 6, y + 1, 1); // - 1 > - 4
lcd_frect (x + 3, y + 2, 4, 1, 1); // - 5 > - 9
lcd_frect (x + 2, y + 4, 6, 1, 1); // -10 > -14
lcd_frect (x + 1, y + 5, 8, 1, 1); // -15 >
break;
}
}
}
 
 
//--------------------------------------------------------------
// variometer 2
//
// x, y in Pixel
// x, y top, left
//--------------------------------------------------------------
/*
void draw_variometer2( uint8_t x, uint8_t y, uint8_t width, uint8_t hight, int16_t variometer)
{
uint8_t max = 5; // max: 5 m/sec == 100%
 
lcd_rect (x, y, width, hight, 1);
lcd_frect(x + 1, y + 1, width - 2, hight - 2, 0);
lcd_line (x, y + ((hight) / 2), x + width, y + ((hight) / 2), 1);
 
}
*/
 
 
//--------------------------------------------------------------
// Home symbol
// draw Homesymbol at <x>/<y>
//--------------------------------------------------------------
void draw_homesymbol (uint8_t x, uint8_t y)
{
x *= 6;
y *= 8;
y += 7;
 
lcd_plot (x,y-4,1);
lcd_line (x+1,y-1,x+1,y-5,1);
lcd_plot (x+2,y-6,1);
lcd_plot (x+3,y-7,1);
lcd_plot (x+4,y-6,1);
lcd_line (x+5,y-1,x+5,y-5,1);
lcd_plot (x+6,y-4,1);
lcd_plot (x+3,y-1,1);
lcd_plot (x+3,y-2,1);
lcd_line (x+1,y,x+5,y,1);
 
}
 
//--------------------------------------------------------------
// Target symbol
// draw Targetsymbol at <x>/<y>
//--------------------------------------------------------------
void draw_targetsymbol (uint8_t x, uint8_t y)
{
x *= 6;
y *= 8;
y += 7;
 
lcd_circle (x+3, y-3, 4, 1);
lcd_line (x,y-3,x+6,y-3,1);
lcd_line (x+3,y,x+3,y-6,1);
lcd_circle (x+3, y-3, 2, 1);
}
 
 
//--------------------------------------------------------------
// Degree symbol
// draw Degreesymbol at <x>/<y>
//
// Ein etwas kleineres Degeree als Char 0x1E
//--------------------------------------------------------------
void draw_symbol_degree (uint8_t x, uint8_t y, int8_t xoffs, int8_t yoffs)
{
x *= 6;
y *= 8;
lcd_rect (x+1+xoffs, y+yoffs, 2, 2, 1);
}
 
 
//--------------------------------------------------------------
// RC symbol
// alternatives Symbol fuer RC-Quality
//--------------------------------------------------------------
void draw_symbol_rc (uint8_t x, uint8_t y)
{
x *= 6;
y *= 8;
y += 1;
x += 1;
lcd_plot ( x+3, y+4, 1);
lcd_line ( x+2, y+2, x+4, y+2, 1);
lcd_line ( x+1, y+0, x+5, y+0, 1);
}
 
 
//--------------------------------------------------------------
void print_position (void)
{
lcd_cls ();
lcd_puts_at(0, 0, strGet(START_LASTPOS1), 2); // Breitengr Längengr
lcd_puts_at(12, 7, strGet(ENDE), 0);
uint8_t ij =0;
 
for(ij=0;ij<6;ij++)
{
uint32_t lon = last5pos[ij].Latitude;
write_ndigit_number_u (1, ij+1, (uint16_t)(lon/10000000), 2, 0,0);
lcd_printp_at (3, ij+1, PSTR("."), 0);
write_ndigit_number_u (4, ij+1, (uint16_t)((lon/1000) % 10000), 4, 1,0);
write_ndigit_number_u (8, ij+1, (uint16_t)((lon/10) % 100), 2, 1,0);
 
uint32_t lat = last5pos[ij].Longitude;
write_ndigit_number_u (12, ij+1, (uint16_t)(lat/10000000), 2, 0,0);
lcd_printp_at (14, ij+1, PSTR("."), 0);
write_ndigit_number_u (15, ij+1, (uint16_t)((lat/1000) % 10000), 4, 1,0);
write_ndigit_number_u (19, ij+1, (uint16_t)((lat/10) % 100), 2, 1,0);
}
 
while (!get_key_press (1 << KEY_ESC))
timer = TIMEOUT;
 
get_key_press(KEY_ALL);
lcd_cls();
}
 
 
//--------------------------------------------------------------
void Show_LastPosition(void)
{
lcd_puts_at(0, 2, strGet(OSD_POS1), 0);
lcd_puts_at(0, 3, strGet(OSD_POS2), 0);
lcd_puts_at(0, 5, strGet(START_LASTPOS1), 0);
uint32_t lon = last5pos[0].Latitude;
write_ndigit_number_u (1, 6, (uint16_t)(lon/10000000), 2, 0,0);
lcd_printp_at (3, 6, PSTR("."), 0);
write_ndigit_number_u (4, 6, (uint16_t)((lon/1000) % 10000), 4, 1,0);
write_ndigit_number_u (8, 6, (uint16_t)((lon/10) % 100), 2, 1,0);
 
uint32_t lat = last5pos[0].Longitude;
write_ndigit_number_u (12, 6, (uint16_t)(lat/10000000), 2, 0,0);
lcd_printp_at (14, 6, PSTR("."), 0);
write_ndigit_number_u (15, 6, (uint16_t)((lat/1000) % 10000), 4, 1,0);
write_ndigit_number_u (19, 6, (uint16_t)((lat/10) % 100), 2, 1,0);
 
}
 
 
//--------------------------------------------------------------
void OSD_Timeout(uint8_t flag)
{
 
// uint8_t flag;
uint8_t tmp_dat;
// flag = 0;
timer = TIMEOUT;
// disable OSD Data from NC
// RS232_request_mk_data (1, 'o', 0);
// tmp_dat = 0;
// SendOutData ('o', ADDRESS_NC, 1, &tmp_dat, 1);
 
mode = 0;
rxd_buffer_locked = FALSE;
 
 
// Bei Verbindungsverlusst werden hier die letzten bekannten Koordinaten ausgegeben!!!
if( flag )
{
// Falls Spannungswarnung an war Beeper aus//
 
set_beep ( 0, 0, BeepOff);
 
lcd_cls ();
WriteLastPosition(last5pos[0].Longitude,last5pos[0].Latitude); // im EEprom speichern
lcd_puts_at(0, 0, strGet(OSD_ERROR), 2); // ERROR: Datenverlust
lcd_puts_at(0, 2, strGet(OSD_POS1), 0); // Letzte bekannte
lcd_puts_at(0, 3, strGet(OSD_POS2), 0); // Position gespeichert.
lcd_puts_at(0, 5, strGet(START_LASTPOS1), 0); // Breitengr Längengr
// lcd_puts_at(12, 7, strGet(ENDE), 0);
// lcd_puts_at(19, 7, strGet(OK), 0);
// if (OSD_RCErrorbeep==true)
// {
set_beep ( 250, 0x0040, BeepNormal);
// }
 
uint32_t lon = last5pos[0].Latitude;
write_ndigit_number_u (1, 6, (uint16_t)(lon/10000000), 2, 0,0);
lcd_printp_at (3, 6, PSTR("."), 0);
write_ndigit_number_u (4, 6, (uint16_t)((lon/1000) % 10000), 4, 1,0);
write_ndigit_number_u (8, 6, (uint16_t)((lon/10) % 100), 2, 1,0);
 
uint32_t lat = last5pos[0].Longitude;
write_ndigit_number_u (12, 6, (uint16_t)(lat/10000000), 2, 0,0);
lcd_printp_at (14, 6, PSTR("."), 0);
write_ndigit_number_u (15, 6, (uint16_t)((lat/1000) % 10000), 4, 1,0);
write_ndigit_number_u (19, 6, (uint16_t)((lat/10) % 100), 2, 1,0);
 
// while (!get_key_press (1 << KEY_ENTER));
// _delay_ms(1000);
timer = TIMEOUT;
// lcd_cls();
// return;
}
else
{
lcd_puts_at(0, 0, strGet(OSD_ERROR), 2);
Show_LastPosition();
if (Config.OSD_RCErrorbeep==true) set_beep ( 200, 0x0080, BeepNormal);
// _delay_ms(2000);
}
 
rxd_buffer_locked = FALSE; // 07.03.2013 OG: fix
// es gab Probleme mit dem Empfang gueltiger NC-Daten, die zu unschoenen Starteffekten bei den
// OSD-Screens gefuehrt haben. Mit rxd_buffer_locked = FALSE vor SwitchToNC() ist das PKT wieder im 'Takt'
 
SwitchToNC();
 
mode = 'O';
 
// disable debug...
// RS232_request_mk_data (0, 'd', 0);
tmp_dat = 0;
SendOutData ('d', ADDRESS_ANY, 1, &tmp_dat, 1);
 
// request OSD Data from NC every 100ms
// RS232_request_mk_data (1, 'o', 100);
tmp_dat = 10;
SendOutData ('o', ADDRESS_NC, 1, &tmp_dat, 1);
 
//_delay_ms(100);
//rxd_buffer_locked = FALSE;
}
 
 
 
 
//-----------------------------------------------------------
//
void lcd_o_circle (uint16_t x, uint16_t y, int16_t breite, uint8_t mode, int8_t xoffs, int8_t yoffs)
{
breite *= 6;
int16_t radius = breite / 2;
x += 2;
x *= 6;
x += 2;
y += 1;
y *= 8;
y += 3;
 
// 04.03.2012 OG: chg: x-radius von -3 auf -2 (runder auf dem display)
//lcd_ellipse (x, y, radius - 3, radius - 5, mode);
lcd_ellipse( x+xoffs, y+yoffs, radius - 2, radius - 5, mode);
}
 
 
//-----------------------------------------------------------
// lcd_o_circ_line( x, y, breite, deg, rOffset, mode)
//
// x, y : in Chars
// breite : in Chars
// deg : in Pixel
// rOffset: Beeinflusst den Schluss der Linie zum Huellkreis
// 0 = Standard
// >0 naeher zum Huellkreis
// <0 entfernter vom Huellkreis
// mode : siehe: lcd_ellipse_line()
//-----------------------------------------------------------
void lcd_o_circ_line( uint16_t x, uint16_t y, uint8_t breite, uint16_t deg, int8_t rOffset, uint8_t mode, int8_t xoffs, int8_t yoffs)
{
breite *= 6;
int16_t radius = breite / 3;
x += 2;
x *= 6;
x += 2;
y += 1;
y *= 8;
y += 3;
 
// 04.03.2013 OG: der Radius kann mit rOffset >0 vergroessert werden um zum Kreis aufzuschliessen
lcd_ellipse_line( x+xoffs, y+yoffs, radius+rOffset, radius+rOffset, deg, mode);
}
 
 
//--------------------------------------------------------------
void draw_icon_home(uint8_t x, uint8_t y)
{
//lcd_plot( x+0, y+0, 1); // Referenz 0,0
lcd_rect( x+0, y+5, 10, 8, 1); // Mitte
lcd_line( x+5, y+0, x+0, y+5, 1); // Dach Links
lcd_line( x+5, y+0, x+10, y+5, 1); // Dach Rechts
lcd_rect( x+4, y+10, 2, 3, 1); // Tuere
}
 
 
//--------------------------------------------------------------
void draw_icon_sat(uint8_t x, uint8_t y)
{
//lcd_plot( x+0, y+0, 1); // Referenz 0,0
lcd_rect( x+0, y+2, 4, 2, 1); // linker Fluegel
lcd_rect( x+8, y+2, 4, 2, 1); // rechter Fluegel
lcd_rect( x+4, y+0, 4, 6, 1); // Mitte, oben
lcd_line( x+6, y+7, x+2, y+11, 1); // Strahl Links
lcd_line( x+6, y+7, x+10, y+11, 1); // Strahl Rechts
lcd_line( x+1, y+12, x+11, y+12, 1); // Strahl Unten
}
 
 
//--------------------------------------------------------------
void draw_icon_battery(uint8_t x, uint8_t y)
{
//lcd_plot( x+0, y+0, 1); // Referenz 0,0
lcd_rect( x+2, y+0, 2, 2, 1); // der kleine Knubbel oben
lcd_rect( x+0, y+2, 6, 15, 1); // body
}
 
 
 
//##############################################################
//# OSD-ELEMENTS
//##############################################################
 
//--------------------------------------------------------------
// OSD_Element_Flag_Label( xC, yC, item, lOn, xoffs, yoffs)
//
// xC, yC : x,y in Characters
// item : OSD_FLAG_AH, OSD_FLAG_PH, usw.
// lOn : true / false
// xoffs,yoffs : x,y Pixelverschiebung
//--------------------------------------------------------------
void OSD_Element_Flag_Label( uint8_t xC, uint8_t yC, uint8_t item, uint8_t lOn, int8_t xoffs, int8_t yoffs)
{
int8_t x = (xC*6)-2;
int8_t y = (yC*8)-1;
uint8_t w = 14;
uint8_t h = 8;
 
const char *labels[OSD_FLAG_COUNT] =
{
PSTR("AH"), // OSD_FLAG_AH Altitue Hold
PSTR("PH"), // OSD_FLAG_PH Position Hold
PSTR("CF"), // OSD_FLAG_CF Care Free
PSTR("CH"), // OSD_FLAG_CH Coming Home
PSTR("o1"), // OSD_FLAG_O1 Out1
PSTR("o2"), // OSD_FLAG_O2 Out2
PSTR("BA"), // OSD_FLAG_BA LowBat warning (MK)
PSTR("CA"), // OSD_FLAG_CA Calibrate
PSTR("ST"), // OSD_FLAG_ST Start
PSTR("MR"), // OSD_FLAG_MR Motor Run
PSTR("FY"), // OSD_FLAG_FY Fly
PSTR("EL"), // OSD_FLAG_EL Emergency Landing
PSTR("FS"), // OSD_FLAG_FS RX Failsave Active
PSTR("GP"), // OSD_FLAG_GP GPS Ok
PSTR("S!"), // OSD_FLAG_S0 GPS-Sat not ok (GPS NOT ok)
PSTR("TU"), // OSD_FLAG_TU Vario Trim Up
PSTR("TD"), // OSD_FLAG_TD Vario Trim Down
PSTR("FR"), // OSD_FLAG_FR Free
PSTR("RL"), // OSD_FLAG_RL Range Limit
PSTR("SL"), // OSD_FLAG_SL No Serial Link
PSTR("TR"), // OSD_FLAG_TR Target Reached
PSTR("MC") // OSD_FLAG_MC Manual Control
};
 
//lcd_plot( x-2, y-2, 1); // Referenz
if( yC==0 ) { y = 0; h = 7; }
if( xC==0 ) { x = 0; w = 12; }
if( lOn )
{
lcd_frect( x+xoffs, y+yoffs, w, h, 1); // Filler
lcdx_printp_at( xC, yC, labels[item], MINVERS, xoffs,yoffs); // Label
}
else
{
lcd_frect( x+xoffs, y+yoffs, w, h, 0); // clear
}
}
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
void OSD_Element_Flag( uint8_t xC, uint8_t yC, uint8_t item, int8_t xoffs, int8_t yoffs)
{
uint8_t lOn = 0;
 
// FC_StatusFlags 0.88
switch( item )
{
// Altitue Hold
case OSD_FLAG_AH : lOn = (naviData->FCStatusFlags2 & FC_STATUS2_ALTITUDE_CONTROL);
break;
 
// Position Hold
case OSD_FLAG_PH : lOn = (naviData->NCFlags & NC_FLAG_PH);
break;
 
// Coming Home
case OSD_FLAG_CH : lOn = (naviData->NCFlags & NC_FLAG_CH);
break;
 
// Care Free
case OSD_FLAG_CF : lOn = (naviData->FCStatusFlags2 & FC_STATUS2_CAREFREE);
break;
 
// Out1
case OSD_FLAG_O1 : lOn = (naviData->FCStatusFlags2 & FC_STATUS2_OUT1_ACTIVE);
break;
 
// Out2
case OSD_FLAG_O2 : lOn = (naviData->FCStatusFlags2 & FC_STATUS2_OUT2_ACTIVE);
break;
 
// LowBat warning (MK)
case OSD_FLAG_BA : lOn = (naviData->FCStatusFlags & FC_STATUS_LOWBAT);
break;
 
// Calibrate
case OSD_FLAG_CA : lOn = (naviData->FCStatusFlags & FC_STATUS_CALIBRATE);
break;
 
// Start
case OSD_FLAG_ST : lOn = (naviData->FCStatusFlags & FC_STATUS_START);
break;
 
// Motor Run
case OSD_FLAG_MR : lOn = (naviData->FCStatusFlags & FC_STATUS_MOTOR_RUN);
break;
 
// Fly
case OSD_FLAG_FY : lOn = (naviData->FCStatusFlags & FC_STATUS_FLY);
break;
 
// Emergency Landing
case OSD_FLAG_EL : lOn = (naviData->FCStatusFlags & FC_STATUS_EMERGENCY_LANDING);
break;
 
// RC Failsave Active
case OSD_FLAG_FS : lOn = (naviData->FCStatusFlags2 & FC_STATUS2_RC_FAILSAVE_ACTIVE);
break;
// GPS ok
case OSD_FLAG_GP : lOn = (naviData->NCFlags & NC_FLAG_GPS_OK);
break;
 
// GPS-Sat not ok (GPS NOT ok)
case OSD_FLAG_S0 : lOn = !(naviData->NCFlags & NC_FLAG_GPS_OK);
break;
 
// Vario Trim Up
case OSD_FLAG_TU : lOn = (naviData->FCStatusFlags & FC_STATUS_VARIO_TRIM_UP);
break;
// Vario Trim Down
case OSD_FLAG_TD : lOn = (naviData->FCStatusFlags & FC_STATUS_VARIO_TRIM_DOWN);
break;
 
// Free
case OSD_FLAG_FR : lOn = (naviData->NCFlags & NC_FLAG_FREE);
break;
 
// Range Limit
case OSD_FLAG_RL : lOn = (naviData->NCFlags & NC_FLAG_RANGE_LIMIT);
break;
 
// No Serial Link
case OSD_FLAG_SL : lOn = (naviData->NCFlags & NC_FLAG_NOSERIALLINK);
break;
 
// Target Reached
case OSD_FLAG_TR : lOn = (naviData->NCFlags & NC_FLAG_TARGET_REACHED);
break;
 
// Manual Control
case OSD_FLAG_MC : lOn = (naviData->NCFlags & NC_FLAG_MANUAL_CONTROL);
break;
 
}
OSD_Element_Flag_Label( xC, yC, item, lOn, xoffs,yoffs);
}
 
 
//--------------------------------------------------------------
// OSD_Element_AltitudeControl( x, y)
//--------------------------------------------------------------
void OSD_Element_AltitudeControl( uint8_t x, uint8_t y )
{
//---------------------------------------------------------
// 10.03.2013 OG:
// CFG2_HEIGHT_LIMIT im Augenblick nicht unterstuetzt
// Siehe Anmerkungen in osd()
//---------------------------------------------------------
/*
if (Flags_ExtraConfig & CFG2_HEIGHT_LIMIT)
{
if (naviData->FCStatusFlags2 & FC_STATUS2_ALTITUDE_CONTROL)
lcd_puts_at (x, y, strGet(OSD_ALTI_1), 0); // Höhe begr.
else
lcd_puts_at (x, y, strGet(OSD_ALTI_0), 0); // Höhe aus
}
else
{
if (naviData->FCStatusFlags2 & FC_STATUS2_ALTITUDE_CONTROL)
lcd_puts_at (x, y, strGet(OSD_VARIO_1), 0); // Vario Höhe
else
lcd_puts_at (x, y, strGet(OSD_VARIO_0), 0); // Vario aus
}
*/
 
if (naviData->FCStatusFlags2 & FC_STATUS2_ALTITUDE_CONTROL)
lcd_puts_at (x, y, strGet(OSD_VARIO_1), 0); // Vario Höhe
else
lcd_puts_at (x, y, strGet(OSD_VARIO_0), 0); // Vario aus
 
}
 
 
//--------------------------------------------------------------
// Anzeige von Steigen / Sinken
//--------------------------------------------------------------
void OSD_Element_UpDown( uint8_t x, uint8_t y, int8_t xoffs, int8_t yoffs)
{
x = (x*6) + xoffs;
y = (y*8) + yoffs;
 
lcd_frect( x, y, 6, 7, 0); // clear
if( naviData->Variometer > 2 ) // steigen mehr als 0.2 m/sec (ein guter Wert muss noch in der Praxis ermittelt werden)
{
lcd_line( x+2, y+0, x+0, y+2, 1);
lcd_line( x+2, y+0, x+4, y+2, 1);
}
else if( naviData->Variometer < -2 ) // sinken mehr als 0.2 m/sec
{
lcd_line( x+2, y+6, x+0, y+4, 1);
lcd_line( x+2, y+6, x+4, y+4, 1);
}
 
}
 
 
//--------------------------------------------------------------
// OSD_Element_Altitude( x, y, nStyle)
// nStyle entspricht dem ehemaligen 'Mode'
//--------------------------------------------------------------
void OSD_Element_Altitude( uint8_t x, uint8_t y, uint8_t nStyle )
{
switch( nStyle )
{
case 0 :
case 1 : //note:lephisto:according to several sources it's /30
if (naviData->Altimeter > (300 / AltimeterAdjust) || naviData->Altimeter < (-300 / AltimeterAdjust)) // above 10m only write full meters
write_ndigit_number_s (x, y, naviData->Altimeter / (30 / AltimeterAdjust), 4, 0,MNORMAL);
else // up to 10m write meters.dm
write_ndigit_number_s_10th (x, y, naviData->Altimeter / (3 / AltimeterAdjust), 3, 0,MNORMAL);
 
lcd_printp_at (x+4, y, PSTR("m"), MNORMAL);
lcd_putc (x+5, y, 0x09, 0); // Hoehensymbol
break;
 
case 2 : //note:lephisto:according to several sources it's /30
if (naviData->Altimeter > (300 / AltimeterAdjust) || naviData->Altimeter < (-300 / AltimeterAdjust)) // above 10m only write full meters
write_ndigit_number_s (x+4, y, naviData->Altimeter / (30 / AltimeterAdjust), 4, 0,MBIG);
else // up to 10m write meters.dm
write_ndigit_number_s_10th (x+4, y, naviData->Altimeter / (3 / AltimeterAdjust), 3, 0,MBIG);
lcd_putc( x+8, y, 'm', MBIG);
lcd_printp_at (x, y, PSTR("Höhe"), MNORMAL);
break;
}
}
 
 
//--------------------------------------------------------------
// fuer: Config.OSD_LipoBar==1
//--------------------------------------------------------------
void OSD_Element_BatteryLevel_Bar( uint8_t x, uint8_t y )
{
uint16_t Balken = 0;
 
drawmode = (naviData->UBat < BattLowVoltageWarning ? 2 : 0);
if( cells > 0 ) // LipobargraphAnzeige nur wenn Anzahl der Lipozellen bekannt sind
{
write_ndigit_number_u (x+6, y, cells, 1, 0, drawmode);
lcd_printp_at (x+7, y, PSTR("S"), drawmode);
 
if( cells==3 )
{
lcd_rect(x*6, y*8, 28, 7, 1); // Rahmen
Balken = ((naviData->UBat-(cells*MIN_CELL_VOLTAGE))*10)/12;
if((Balken > 0) && (Balken <28)) lcd_frect((x*6)+1, (y*8)+1, Balken, 5, 1); // Fuellung
if(Balken <= 26) lcd_frect(Balken+(x*6)+1, (y*8)+1, 26-Balken, 5, 0); // loeschen
}
 
if( cells==4 ||cells==5 )
{
lcd_rect(x*6, y*8, 30, 7, 1); // Rahmen
if (cells == 4) Balken = ((naviData->UBat-(cells*MIN_CELL_VOLTAGE))*10)/15;
if (cells == 5) Balken = ((naviData->UBat-(cells*MIN_CELL_VOLTAGE))*10)/19;
if ((Balken > 0) && (Balken <=29)) lcd_frect((x*6)+1, (y*8)+1, Balken, 5, 1); // Fuellung
if (Balken <= 27) lcd_frect(Balken+(x*6)+1, (y*8)+1, 28-Balken, 5, 0); // loeschen
}
 
} // end if: cells > 0 (TODO: Anzeige fuer cells==0 implementieren)
}
 
 
 
//--------------------------------------------------------------
// fuer die neuen OSD-Screens
//--------------------------------------------------------------
void OSD_Element_BattLevel2( uint8_t x, uint8_t y, int8_t xoffs, int8_t yoffs )
{
drawmode = (naviData->UBat < BattLowVoltageWarning ? MINVERS : MNORMAL);
writex_ndigit_number_u_10th( x, y, naviData->UBat, 3, 0, drawmode, xoffs,yoffs);
lcdx_printp_at( x+4, y, PSTR("V"), drawmode, xoffs+1,yoffs); // Einheit
lcd_line( (x+4)*6, y*8, (x+4)*6, y*8+7, (drawmode==MINVERS ? 1 : 0) ); // filler zwischen Spannung und "V"
}
 
 
//--------------------------------------------------------------
// fuer: Config.OSD_LipoBar==0
// nStyle entspricht dem ehemaligen 'Mode'
//--------------------------------------------------------------
void OSD_Element_BatteryLevel_Text( uint8_t x, uint8_t y, uint8_t nStyle )
{
if( nStyle <= 1)
drawmode = (naviData->UBat < BattLowVoltageWarning ? 2 : 0); // Normal-Schrift
else
drawmode = (naviData->UBat < BattLowVoltageWarning ? 4 : 3); // Fett-Schrift
 
if( nStyle <= 1)
{
write_ndigit_number_u_10th (x, y, naviData->UBat, 3, 0, drawmode);
lcd_printp_at (x+4, y, PSTR("V"), drawmode);
}
else
{
write_ndigit_number_u_10th (x-2, y, naviData->UBat, 3, 0, drawmode);
lcd_printp_at (x+2, y, PSTR("V"), drawmode);
}
}
 
 
//--------------------------------------------------------------
// nStyle entspricht dem ehemaligen 'Mode'
//--------------------------------------------------------------
void OSD_Element_BatteryLevel( uint8_t x, uint8_t y, uint8_t nStyle )
{
if( Config.OSD_LipoBar )
OSD_Element_BatteryLevel_Bar( x, y);
else
OSD_Element_BatteryLevel_Text( x, y, nStyle);
}
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
void OSD_Element_Capacity( uint8_t x, uint8_t y )
{
drawmode = (naviData->UsedCapacity > Config.OSD_mAh_Warning ? 2 : 0);
write_ndigit_number_u (x, y, naviData->UsedCapacity, 5, 0, drawmode);
lcd_printp_at (x+5, y, PSTR("mAh"), drawmode);
// BeepTime = 3000;
// BeepMuster = 0x0020;
}
 
 
//--------------------------------------------------------------
// OSD_Element_CareFree( x, y)
//--------------------------------------------------------------
void OSD_Element_CareFree( uint8_t x, uint8_t y )
{
lcd_puts_at (x, y, strGet( naviData->FCStatusFlags2 & FC_STATUS2_CAREFREE ? OSD_CARE_FREE_1 : OSD_CARE_FREE_0 ), 0);
}
 
 
//--------------------------------------------------------------
// OSD_Element_CompassDegree( x, y, nStyle)
// nStyle entspricht dem ehemaligen 'Mode'
//--------------------------------------------------------------
void OSD_Element_CompassDegree( uint8_t x, uint8_t y, uint8_t nStyle )
{
switch( nStyle )
{
case 0 :
case 1 : write_ndigit_number_u (x, y, naviData->CompassHeading, 3, 0,MNORMAL);
x += 3;
break;
case 2 : write_ndigit_number_u (x, y, naviData->CompassHeading, 3, 0,MBIG);
x += 8;
break;
}
lcd_putc( x, y, 0x1E, MNORMAL); // degree symbol
}
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
void OSD_Element_CompassDirection( uint8_t x, uint8_t y )
{
lcd_printp_at (x, y, (const char *) (pgm_read_word ( &(directions_p[heading_conv(naviData->CompassHeading)]))), 0);
}
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
void OSD_Element_CompassRose( uint8_t x, uint8_t y )
{
draw_compass (x, y, naviData->CompassHeading);
}
 
//--------------------------------------------------------------
//--------------------------------------------------------------
void OSD_Element_Current( uint8_t x, uint8_t y )
{
write_ndigit_number_u_10th (x, y, naviData->Current, 3, 0,0);
lcd_printp_at (x+4, y, PSTR("A"), 0);
}
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
void OSD_Element_FlyingTime( uint8_t x, uint8_t y )
{
write_time (x, y, naviData->FlyingTime);
lcd_printp_at (x+5, y, PSTR("m"), 0);
}
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
void OSD_Element_GroundSpeed( uint8_t x, uint8_t y )
{
write_ndigit_number_u (x, y, (uint16_t) (((uint32_t) naviData->GroundSpeed * (uint32_t) 9) / (uint32_t) 250), 3, 0,0);
lcd_printp_at (x+3, y, PSTR("Kmh"), 0);
}
 
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
void OSD_Element_HomeCircle( uint8_t x, uint8_t y, uint8_t breite, int8_t rOffset, int8_t xoffs, int8_t yoffs )
{
lcd_o_circle( x, y, breite, 1, xoffs,yoffs);
 
if (Config.OSD_HomeMKView==1)
heading_home = (naviData->HomePositionDeviation.Bearing + 360 - naviData->CompassHeading) % 360;
else
heading_home = (naviData->CompassHeading- naviData->HomePositionDeviation.Bearing + 360 ) % 360;
 
lcd_o_circ_line( x, y, breite, old_hh , rOffset, 0, xoffs,yoffs);
lcd_o_circ_line( x, y, breite, heading_home, rOffset, 1, xoffs,yoffs);
old_hh = heading_home;
}
 
 
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
void OSD_Element_HomeDegree( uint8_t x, uint8_t y )
{
write_ndigit_number_u (x, y, heading_home, 3, 0,0);
lcd_putc (x+3, y, 0x1e, 0); // degree symbol
}
 
 
//--------------------------------------------------------------
// OSD_Element_HomeDistance( x, y, nStyle)
//--------------------------------------------------------------
void OSD_Element_HomeDistance( uint8_t x, uint8_t y, uint8_t nStyle )
{
switch( nStyle )
{
case 0 :
case 1 : write_ndigit_number_u (x, y, naviData->HomePositionDeviation.Distance / 10, 3, 0,0);
lcd_putc (x+3, y, 'm', 0);
draw_homesymbol(x+4, y);
break;
case 2 : lcd_printp_at (x, y, PSTR("Home"), 0);
write_ndigit_number_u (x+5, y, naviData->HomePositionDeviation.Distance / 10, 3, 0,0);
lcd_printp_at (x+8, y, PSTR("m -"), 0);
break;
}
}
 
 
//--------------------------------------------------------------
// OSD_Element_LEDOutput( x, y, bitmask)
//
// bitmask: LED1 = FC_STATUS2_OUT1_ACTIVE
// LED2 = FC_STATUS2_OUT2_ACTIVE
//--------------------------------------------------------------
void OSD_Element_LEDOutput( uint8_t x, uint8_t y, uint8_t bitmask )
{
uint8_t lOn;
lOn = (naviData->FCStatusFlags2 & bitmask ? 1 : 0); // Bit gesetzt?
lOn = (Config.OSD_InvertOut ? !lOn : lOn); // Invertieren?
lOn = (lOn ? 1 : 0); // auf 0 oder 1 setzen (hmm, geht auch besser...).
lcd_fcircle (x * 6 + 5, y * 8 + 3, Config.OSD_LEDform, lOn);
lcd_circle (x * 6 + 5, y * 8 + 3, 3, 1);
 
/*
if (!Config.OSD_InvertOut)
{
if (naviData->FCStatusFlags2 & FC_STATUS2_OUT1_ACTIVE)
{
lcd_fcircle (x * 6 + 5, y * 8 + 3, Config.OSD_LEDform, 0);
lcd_circle (x * 6 + 5, y * 8 + 3, 3, 1);
}
else
{
lcd_fcircle (x * 6 + 5, y * 8 + 3, Config.OSD_LEDform, 1);
lcd_circle (x * 6 + 5, y * 8 + 3, 3, 1);
}
}
else
{
if (naviData->FCStatusFlags2 & FC_STATUS2_OUT1_ACTIVE)
{
lcd_fcircle (x * 6 + 5, y * 8 + 3,Config.OSD_LEDform, 1);
lcd_circle (x * 6 + 5, y * 8 + 3, 3, 1);
}
else
{
lcd_fcircle (x * 6 + 5, y * 8 + 3, Config.OSD_LEDform, 0);
lcd_circle (x * 6 + 5, y * 8 + 3, 3, 1);
}
}
break;
*/
}
 
 
//--------------------------------------------------------------
// OSD_Element_LED1Output( x, y)
//--------------------------------------------------------------
void OSD_Element_LED1Output( uint8_t x, uint8_t y )
{
OSD_Element_LEDOutput( x, y, FC_STATUS2_OUT1_ACTIVE );
}
 
 
//--------------------------------------------------------------
// OSD_Element_LED2Output( x, y)
//--------------------------------------------------------------
void OSD_Element_LED2Output( uint8_t x, uint8_t y )
{
OSD_Element_LEDOutput( x, y, FC_STATUS2_OUT2_ACTIVE );
}
 
 
//--------------------------------------------------------------
// OSD_Element_Manuell( x, y)
//--------------------------------------------------------------
void OSD_Element_Manuell( uint8_t x, uint8_t y )
{
if (naviData->NCFlags & NC_FLAG_MANUAL_CONTROL)
lcd_putc (x, y, 'M', 0); // rc transmitter
else
lcd_putc (x, y, 'X', 0); // clear
}
 
 
//--------------------------------------------------------------
// OSD_Element_NaviMode( x, y)
//--------------------------------------------------------------
void OSD_Element_NaviMode( uint8_t x, uint8_t y )
{
if (naviData->NCFlags & NC_FLAG_FREE)
lcd_puts_at (x, y, strGet(OSD_NAVI_MODE_0), 0); // Navi aus
else if (naviData->NCFlags & NC_FLAG_PH)
lcd_puts_at (x, y, strGet(OSD_NAVI_MODE_1), 0); // Pos. Hold
else if (naviData->NCFlags & NC_FLAG_CH)
lcd_puts_at (x, y, strGet(OSD_NAVI_MODE_2), 0); // Coming Home
}
 
 
//--------------------------------------------------------------
// OSD_Element_RCIntensity( x, y)
//--------------------------------------------------------------
void OSD_Element_RCIntensity( uint8_t x, uint8_t y )
{
write_ndigit_number_u (x, y, naviData->RC_Quality, 3, 0,0);
lcd_printp_at (x+3, y, PSTR("\x1F"), 0); // RC-transmitter
if (naviData->NCFlags & NC_FLAG_NOSERIALLINK)
{
lcd_printpns_at(x+3, y, PSTR(" "), 0); // Clear
}
else
{
lcd_printpns_at(x+3, y, PSTR("PC"), 0);
}
}
 
 
//--------------------------------------------------------------
// OSD_Element_SatsInUse( x, y, nStyle)
//
// nStyle == 0: "00s"
// nStyle == 1: wie 0
// nStyle == 2: "00 Sat"
//
// nStyle entspricht dem ehemaligen 'Mode'
//--------------------------------------------------------------
void OSD_Element_SatsInUse( uint8_t x, uint8_t y, uint8_t nStyle )
{
drawmode = (naviData->NCFlags & NC_FLAG_GPS_OK ? 0 : 2);
switch( nStyle )
{
case 0 :
case 1 : write_ndigit_number_u (x, y, naviData->SatsInUse, 2, 0, drawmode);
lcd_putc (x+2, y, 0x08, drawmode);
break;
case 2 : write_ndigit_number_u (x, y, naviData->SatsInUse, 2, 0, drawmode);
lcd_printp_at (x+2, y, PSTR(" Sat"), drawmode);
break;
}
}
 
 
//--------------------------------------------------------------
// OSD_Element_StatusFlags( x, y)
//--------------------------------------------------------------
void OSD_Element_StatusFlags( uint8_t x, uint8_t y )
{
// FC_StatusFlags 0.88
// #define FC_STATUS_MOTOR_RUN 0x01
// #define FC_STATUS_FLY 0x02
// #define FC_STATUS_CALIBRATE 0x04
// #define FC_STATUS_START 0x08
// #define FC_STATUS_EMERGENCY_LANDING 0x10
// #define FC_STATUS_LOWBAT 0x20
// #define FC_STATUS_VARIO_TRIM_UP 0x40
// #define FC_STATUS_VARIO_TRIM_DOWN 0x80
 
if (naviData->FCStatusFlags & FC_STATUS_CALIBRATE)
lcd_puts_at (x, y, strGet(OSD_FLAGS_1), 0); // Calibrate
else if (naviData->FCStatusFlags & FC_STATUS_START)
lcd_puts_at (x, y, strGet(OSD_FLAGS_2), 0); // Start
else if (naviData->FCStatusFlags & FC_STATUS_MOTOR_RUN)
lcd_puts_at (x, y, strGet(OSD_FLAGS_3), 0); // Run
else if (naviData->FCStatusFlags & FC_STATUS_FLY)
lcd_puts_at (x, y, strGet(OSD_FLAGS_4), 0); // Fly
else if (naviData->FCStatusFlags & FC_STATUS_EMERGENCY_LANDING)
lcd_puts_at (x, y, strGet(OSD_FLAGS_5), 0); // Landing
else if (naviData->FCStatusFlags & FC_STATUS_LOWBAT)
lcd_puts_at (x, y, strGet(OSD_FLAGS_6), 0); // LowBat
else
// lcd_printp_at (x, y, PSTR(" "), 0); // Clear
lcd_puts_at (x, y, strGet(OSD_FLAGS_0), 0); // Clear
}
 
 
//--------------------------------------------------------------
// OSD_Element_Variometer( x, y)
//--------------------------------------------------------------
void OSD_Element_Variometer( uint8_t x, uint8_t y )
{
x *= 6;
y *= 8;
y += 7;
draw_variometer (x, y, 10, 14, naviData->Variometer);
}
 
 
//--------------------------------------------------------------
// OSD_Element_Target( x, y, nStyle)
//
// nStyle entspricht dem ehemaligen 'Mode'
// nStyle = 0,1: "000m"
// nStyle = 2,3: "Ziel 000m -"
//--------------------------------------------------------------
void OSD_Element_Target( uint8_t x, uint8_t y, uint8_t nStyle )
{
if( nStyle <= 1 )
{
write_ndigit_number_u (x, y, naviData->TargetPositionDeviation.Distance / 10, 3, 0,0);
lcd_putc (x+3, y, 'm', 0);
draw_targetsymbol(x+4,y);
}
else
{
lcd_printp_at (x, y, PSTR("Ziel"), 0);
write_ndigit_number_u (x+5, y, naviData->TargetPositionDeviation.Distance / 10, 3, 0,0);
lcd_printp_at (x+8, y, PSTR("m -"), 0);
}
}
 
 
//--------------------------------------------------------------
// TODO:
// - pruefen ob beep hier an richtiger Stelle ist
//--------------------------------------------------------------
void OSD_Element_VarioWert( uint8_t x, uint8_t y )
{
uint8_t FC_Fallspeed;
FC_Fallspeed = (unsigned int)naviData->Variometer;
FC_Fallspeed = 255-FC_Fallspeed;
 
drawmode = ( (naviData->Variometer < 0) && (FC_Fallspeed > Config.OSD_Fallspeed) ? 2 : 0);
 
if( Config.OSD_VarioBeep )
Beep_Vario(); // Beep ???
 
if( drawmode == 2 )
{
if( !Config.HWSound )
set_beep ( 1000, 0x0060, BeepNormal); // muss ein Beep hier hin????
else
variobeep(naviData->Variometer); // muss ein Beep hier hin????
}
 
write_ndigit_number_s_10th (x, y, naviData->Variometer, 3,0, drawmode);
lcd_printpns_at(x+4, y, PSTR("ms"), drawmode);
}
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
void OSD_Element_WayPoint( uint8_t x, uint8_t y )
{
if (!OldWP == naviData->WaypointIndex)
{
// BeepTime = 500;
// BeepMuster = 0x0080;
OldWP = naviData->WaypointIndex;
NextWP = true;
}
if ((NextWP==true)&& naviData->NCFlags & NC_FLAG_TARGET_REACHED)
{
set_beep ( 500, 0x0080, BeepNormal);
NextWP = false;
}
write_ndigit_number_u (x+2, y, naviData->WaypointIndex , 2, 0,0);
 
lcd_printp_at (x, y, PSTR("WP"), 0);
}
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
void OSD_Element_TargetDegree( uint8_t x, uint8_t y )
{
write_ndigit_number_u (x, y, naviData->TargetPositionDeviation.Bearing/ 10, 3, 0,0);
lcd_putc (x+3, y, 0x1e, 0); // degree symbol
}
 
 
 
//##############################################################
//# OSD-SCREENS
//##############################################################
 
//--------------------------------------------------------------
// OSD-Screen "General"
//
// nMode: 0 = update values
// 1 = redraw labels and update values
//--------------------------------------------------------------
const char * OSD_Screen_General( uint8_t nMode )
{
const char *ScreenName = PSTR("General");
 
//-----------------------------------------
// REDRAW
// statische Screen Elemente die nicht
// jedesmal neu gezeichnet werden muessen
//-----------------------------------------
if( nMode == OSD_SCREEN_REDRAW )
{
// Display: 128 x 64 with 6x8 Font => 21 x 8
 
// Linien: Horizontal
lcd_line (0, 28, 127, 28, 1); // mitte
lcd_line (0, 51, 127, 51, 1); // unten
// Linien: Vertikal
lcd_line (65, 0, 65, 50, 1); // mitte
//-----------------------------------------
// Block: Oben - Links
//-----------------------------------------
draw_icon_battery(0,4);
//lcdx_printp_at( 6, 0, PSTR("V") , MNORMAL, 1,0); // Spannung (Volt)
lcdx_printp_at( 7, 2, PSTR(" mA"), MNORMAL, 0,2);
 
//-----------------------------------------
// Block: Oben - Rechts
//-----------------------------------------
lcdx_printp_at( 12, 0, PSTR("Alt:") , MNORMAL, 0,0);
lcdx_printp_at( 12, 1, PSTR("Dir:") , MNORMAL, 0,1);
draw_symbol_degree( 20, 1, 1,1);
lcdx_printp_at( 12, 2, PSTR(" I:") , MNORMAL, 0,2);
lcdx_printp_at( 20, 2, PSTR("A") , MNORMAL, 2,2);
 
//-----------------------------------------
// Block: Unten - Links
//-----------------------------------------
draw_icon_sat(0,33);
lcdx_printp_at( 6, 5, PSTR(" kmh"), MNORMAL, 0,1);
 
//-----------------------------------------
// Block: Unten - Rechts
//-----------------------------------------
draw_icon_home( 70, 32);
lcdx_printp_at( 20, 4, PSTR("m"), MNORMAL, 2,0);
draw_symbol_degree( 20, 5, 1,1);
//lcd_putc( 20, 5, 0x1E, 0); // alternativ: degree symbol
//-----------------------------------------
// unterste Zeile
//-----------------------------------------
draw_symbol_rc(20,7); // RC-transmitter
}
//-----------------
// Batt Level (Volt)
//-----------------
OSD_Element_BattLevel2( 2, 0, 0,0 );
 
//-----------------
// LowBat Warnung MK
//-----------------
OSD_Element_Flag( 8, 0, OSD_FLAG_BA, 0,0 );
 
//-----------------
// Flugzeit
//-----------------
writex_time(2, 1, naviData->FlyingTime, MNORMAL, 0,1);
 
//-----------------
// entnommene Kapazitaet (mAh)
//-----------------
drawmode = (naviData->UsedCapacity > Config.OSD_mAh_Warning ? MINVERS : MNORMAL);
writex_ndigit_number_u( 2, 2, naviData->UsedCapacity, 5, 0, drawmode, 0,2);
//-----------------
// Höhe
//-----------------
if (naviData->Altimeter > (300 / AltimeterAdjust) || naviData->Altimeter < (-300 / AltimeterAdjust)) // above 10m only write full meters
write_ndigit_number_s ( 16, 0, naviData->Altimeter / (30 / AltimeterAdjust), 4, 0, MNORMAL);
else // up to 10m write meters.dm
write_ndigit_number_s_10th( 16, 0, naviData->Altimeter / (3 / AltimeterAdjust), 3, 0, MNORMAL);
 
//-----------------
// steigen / sinken
//-----------------
OSD_Element_UpDown( 20, 0, 2,0);
 
//-----------------
// Compass Degree
//-----------------
writex_ndigit_number_u (17, 1, naviData->CompassHeading, 3, 0,MNORMAL, 0,1);
 
//-----------------
// Strom
//-----------------
//write_ndigit_number_u_10th( 16, 2, naviData->Current, 3, 0,0); // alternativ mit Nachkomma
writex_ndigit_number_u( 17, 2, naviData->Current/10, 3, 0,MNORMAL, 0,2);
 
//-----------------
// Sat Anzahl
//-----------------
write_ndigit_number_u (4, 4, naviData->SatsInUse, 2, 0,MNORMAL);
 
//-----------------
// Sat Warnung "!"
//-----------------
/*
if( naviData->NCFlags & NC_FLAG_GPS_OK )
lcd_printp_at( 9, 4, PSTR(" "), MNORMAL);
else
lcd_printp_at( 9, 4, PSTR("!"), MNORMAL);
*/
OSD_Element_Flag( 8, 4, OSD_FLAG_S0, -1,0 ); // Sat Warnung (GPS not ok)
 
//-----------------
// Geschwindigkeit
//-----------------
writex_ndigit_number_u( 3, 5, (uint16_t) (((uint32_t) naviData->GroundSpeed * (uint32_t) 9) / (uint32_t) 250), 3, 0,MNORMAL, 0,1);
 
//-----------------
// Home Distance
//-----------------
write_ndigit_number_u( 17, 4, naviData->HomePositionDeviation.Distance / 10, 3, 0,MNORMAL);
 
//-----------------
// Home Winkel
//-----------------
writex_ndigit_number_u( 16, 5, heading_home, 4, 0,MNORMAL, 0,1);
 
//-----------------
// Flags
//-----------------
OSD_Element_Flag( 1, 7, OSD_FLAG_CF, 0,0 ); // Care Free
OSD_Element_Flag( 4, 7, OSD_FLAG_AH, 0,0 ); // Altitude Hold
OSD_Element_Flag( 7, 7, OSD_FLAG_PH, 0,0 ); // Position Hold
OSD_Element_Flag( 10, 7, OSD_FLAG_CH, 0,0 ); // Coming Home
OSD_Element_Flag( 13, 7, OSD_FLAG_EL, 0,0 ); // Emergency Landing
 
//-----------------
// RC-Quality (MK)
//-----------------
write_ndigit_number_u( 17, 7, naviData->RC_Quality, 3, 0,MNORMAL);
 
#ifdef OSD_DEMO
//-----------------
// Flags
//-----------------
OSD_Element_Flag_Label( 8, 0, OSD_FLAG_BA, true, 0,0 ); // DEMO: Batterie Warnung
OSD_Element_Flag_Label( 8, 4, OSD_FLAG_S0, true, -1,0 ); // DEMO: Sat Warnung (GPS not ok)
 
OSD_Element_Flag_Label( 1, 7, OSD_FLAG_CF, true, 0,0 ); // DEMO
OSD_Element_Flag_Label( 4, 7, OSD_FLAG_AH, true, 0,0 ); // DEMO
OSD_Element_Flag_Label( 7, 7, OSD_FLAG_PH, true, 0,0 ); // DEMO
OSD_Element_Flag_Label( 10, 7, OSD_FLAG_CH, true, 0,0 ); // DEMO
OSD_Element_Flag_Label( 13, 7, OSD_FLAG_EL, true, 0,0 ); // DEMO
#endif
 
 
return( ScreenName );
}
 
 
//--------------------------------------------------------------
// OSD-Screen "Navigation"
//
// nMode: 0 = update values
// 1 = redraw labels and update values
//--------------------------------------------------------------
const char * OSD_Screen_Navigation( uint8_t nMode )
{
const char *ScreenName = PSTR("Navigation");
int8_t xoffs, yoffs;
 
//-----------------------------------------
// REDRAW
// statische Screen Elemente die nicht
// jedesmal neu gezeichnet werden muessen
//-----------------------------------------
if( nMode == OSD_SCREEN_REDRAW )
{
// do things here for static screen elements like labels and so....
lcd_line ((6*6-4), 0, (6*6-4), 9, 1); // Linie Vertikal links
lcd_line ((15*6+3), 0, (15*6+3), 9, 1); // Linie Vertikal rechts
lcd_line (0, 10, 127, 10, 1); // Linie Horizontal
 
lcdx_printp_at( 0, 2, PSTR("Alt:"), MNORMAL, 0,2); // Hoehe
lcdx_printp_at( 0, 5, PSTR("Home:"), MNORMAL, 0,3); // Home Distance
}
 
 
//-----------------
// Oben: Batt Level (Volt)
//-----------------
OSD_Element_BattLevel2( 0, 0, 0,0 );
 
//-----------------
// Oben: Kompass Rose
//-----------------
OSD_Element_CompassRose( 6, 0);
 
//-----------------
// Oben: Flugzeit
//-----------------
write_time(16, 0, naviData->FlyingTime);
 
//-----------------
// Hoehe
//-----------------
xoffs = 0;
yoffs = 3;
drawmode = MNORMAL;
if (naviData->Altimeter > (300 / AltimeterAdjust) || naviData->Altimeter < (-300 / AltimeterAdjust)) // above 10m only write full meters
writex_ndigit_number_s ( 0, 3, naviData->Altimeter / (30 / AltimeterAdjust), 4, 0, drawmode, xoffs,yoffs);
else // up to 10m write meters.dm
writex_ndigit_number_s_10th( 0, 3, naviData->Altimeter / (3 / AltimeterAdjust), 3, 0, drawmode, xoffs,yoffs);
 
//-----------------
// Steigen / Sinken
//-----------------
OSD_Element_UpDown( 4, 3, 1,yoffs);
 
//-----------------
// Home Distance
//-----------------
yoffs = 3;
writex_ndigit_number_u( 0, 6, naviData->HomePositionDeviation.Distance / 10, 4, 0,MNORMAL, 0,yoffs+1);
lcdx_printp_at( 4, 6, PSTR("m"), MNORMAL, 2,yoffs+1); // Home
//-----------------
// Home Circle
//-----------------
xoffs = 0;
yoffs = 3;
OSD_Element_HomeCircle( 8, 3, 9, 4, xoffs,yoffs); // Home Circle
lcd_frect( (9*6)-3+xoffs, (4*8)-2+yoffs, (3*6)+4, (1*8)+2, 0); // inner clear
lcd_rect ( (9*6)-4+xoffs, (4*8)-3+yoffs, (3*6)+6, (1*8)+4, 1); // inner rect
lcd_frect ( 61+xoffs, 57+yoffs, 2, 2, 1); // bottom mini rect
writex_ndigit_number_u( 9, 4, heading_home, 3, 0,MNORMAL, xoffs,yoffs); // Degree (Winkel)
 
//-----------------
// Variometer
//-----------------
//void draw_variometer (uint8_t x, uint8_t y, uint8_t width, uint8_t hight, int16_t variometer)
//draw_variometer( 95, 38, 7, 30, naviData->Variometer);
//draw_variometer( 94, 38, 7, 21, naviData->Variometer);
//draw_variometer2( 94, 28, 7, 21, naviData->Variometer);
 
//-----------------
// Flags
//-----------------
OSD_Element_Flag( 16, 2, OSD_FLAG_BA, -3, 0); // MK Batt Warning
OSD_Element_Flag( 19, 2, OSD_FLAG_CF, 0, 0); // Carefree
OSD_Element_Flag( 19, 4, OSD_FLAG_AH, 0,-3); // Altitude Hold
OSD_Element_Flag( 19, 6, OSD_FLAG_PH, 0,-6); // Position Hold
OSD_Element_Flag( 19, 7, OSD_FLAG_CH, 0,-1); // Coming Home
OSD_Element_Flag( 16, 7, OSD_FLAG_S0, -3,-1); // GPS-Sat not ok (GPS NOT ok)
 
 
#ifdef OSD_DEMO
//-----------------
// Flags
//-----------------
OSD_Element_Flag_Label( 16, 2, OSD_FLAG_BA, true, -3,0); // DEMO
OSD_Element_Flag_Label( 19, 2, OSD_FLAG_CF, true, 0,0); // DEMO
OSD_Element_Flag_Label( 19, 4, OSD_FLAG_AH, true, 0,-3); // DEMO
OSD_Element_Flag_Label( 19, 6, OSD_FLAG_PH, true, 0,-6); // DEMO
OSD_Element_Flag_Label( 19, 7, OSD_FLAG_CH, true, 0,-1); // DEMO
 
OSD_Element_Flag_Label( 16, 7, OSD_FLAG_S0, true, -3,-1); // DEMO
#endif
 
 
return( ScreenName );
}
 
 
 
 
//--------------------------------------------------------------
// OSD-Screen "Status"
//
// nMode: 0 = update values
// 1 = redraw labels and update values
//--------------------------------------------------------------
const char * OSD_Screen_MKStatus( uint8_t nMode )
{
const char *ScreenName = PSTR("MK-Status");
int8_t xoffs;
 
//-----------------------------------------
// REDRAW
// statische Screen Elemente die nicht
// jedesmal neu gezeichnet werden muessen
//-----------------------------------------
if( nMode == OSD_SCREEN_REDRAW )
{
// do things here for static screen elements like labels and so....
lcd_line ((6*6-3), 0, (6*6-3), 9, 1); // Linie Vertikal links
lcd_line ((15*6+3), 0, (15*6+3), 9, 1); // Linie Vertikal rechts
lcd_line (0, 10, 127, 10, 1); // Linie Horizontal
 
//lcdx_printp_at( 8, 0, PSTR("Status"), MNORMAL, -3,0); // oben, mitte Text
lcdx_printp_at( 13, 0, PSTR("A"), MNORMAL, -4,0); // oben, mitte "A"
}
 
 
//-----------------
// Oben: Batt Level (Volt)
//-----------------
OSD_Element_BattLevel2( 0, 0, 0,0 );
 
//-----------------
// Strom
//-----------------
writex_ndigit_number_u_10th( 7, 0, naviData->Current, 4, 0,MNORMAL, 1,0); // Strom mit Nachkomma
 
//-----------------
// Oben: Flugzeit
//-----------------
write_time(16, 0, naviData->FlyingTime);
//-----------------
// Flags
//-----------------
xoffs = -7;
OSD_Element_Flag( 19, 2, OSD_FLAG_CF, 0+xoffs, 0); // Carefree
OSD_Element_Flag( 19, 4, OSD_FLAG_AH, 0+xoffs,-3); // Altitude Hold
OSD_Element_Flag( 19, 6, OSD_FLAG_PH, 0+xoffs,-6); // Position Hold
OSD_Element_Flag( 19, 7, OSD_FLAG_CH, 0+xoffs,-1); // Coming Home
 
xoffs -= 4;
OSD_Element_Flag( 16, 2, OSD_FLAG_BA, -3+xoffs, 0); // MK Batt Warning
OSD_Element_Flag( 16, 4, OSD_FLAG_EL, -3+xoffs,-3); // Emergency Landing
OSD_Element_Flag( 16, 6, OSD_FLAG_RL, -3+xoffs,-6); // Range Limit
OSD_Element_Flag( 16, 7, OSD_FLAG_S0, -3+xoffs,-1); // GPS-Sat not ok (GPS NOT ok)
 
xoffs -= 4;
OSD_Element_Flag( 12, 2, OSD_FLAG_CA, 0+xoffs, 0); // Calibrate
OSD_Element_Flag( 12, 4, OSD_FLAG_ST, 0+xoffs,-3); // Start
OSD_Element_Flag( 12, 6, OSD_FLAG_MR, 0+xoffs,-6); // Motor Run
OSD_Element_Flag( 12, 7, OSD_FLAG_FY, 0+xoffs,-1); // Fly
 
xoffs -= 4;
OSD_Element_Flag( 9, 2, OSD_FLAG_O1, -2+xoffs, 0); // Out1
OSD_Element_Flag( 9, 4, OSD_FLAG_O2, -2+xoffs,-3); // Out2
OSD_Element_Flag( 9, 6, OSD_FLAG_TR, -2+xoffs,-6); // Target Reached
OSD_Element_Flag( 9, 7, OSD_FLAG_MC, -2+xoffs,-1); // Manual Control
 
xoffs -= 4;
OSD_Element_Flag( 6, 2, OSD_FLAG_TU, -4+xoffs, 0); // Vario Trim Up
OSD_Element_Flag( 6, 4, OSD_FLAG_TD, -4+xoffs,-3); // Vario Trim Down
OSD_Element_Flag( 6, 6, OSD_FLAG_FR, -4+xoffs,-6); // Free
OSD_Element_Flag( 6, 7, OSD_FLAG_SL, -4+xoffs,-1); // No Serial Link
 
 
#ifdef OSD_DEMO
//-----------------
// Flags
//-----------------
/*
PSTR("AH"), // OSD_FLAG_AH Altitue Hold
PSTR("PH"), // OSD_FLAG_PH Position Hold
PSTR("CF"), // OSD_FLAG_CF Care Free
PSTR("CH"), // OSD_FLAG_CH Coming Home
PSTR("o1"), // OSD_FLAG_O1 Out1
PSTR("o2"), // OSD_FLAG_O2 Out2
PSTR("BA"), // OSD_FLAG_BA LowBat warning (MK)
PSTR("CA"), // OSD_FLAG_CA Calibrate
PSTR("ST"), // OSD_FLAG_ST Start
PSTR("MR"), // OSD_FLAG_MR Motor Run
PSTR("FY"), // OSD_FLAG_FY Fly
PSTR("EL"), // OSD_FLAG_EL Emergency Landing
PSTR("FS"), // OSD_FLAG_FS RX Failsave Active
PSTR("GP"), // OSD_FLAG_GP GPS Ok
PSTR("S!") // OSD_FLAG_S0 GPS-Sat not ok (GPS NOT ok)
PSTR("TU"), // OSD_FLAG_TU Vario Trim Up
PSTR("TD"), // OSD_FLAG_TD Vario Trim Down
PSTR("FR"), // OSD_FLAG_FR Free
PSTR("RL"), // OSD_FLAG_RL Range Limit
PSTR("SL"), // OSD_FLAG_SL No Serial Link
PSTR("TR"), // OSD_FLAG_TR Target Reached
PSTR("MC") // OSD_FLAG_MC Manual Control
*/
xoffs = -7;
OSD_Element_Flag_Label( 19, 2, OSD_FLAG_CF, true, 0+xoffs, 0); // DEMO: Carefree
OSD_Element_Flag_Label( 19, 4, OSD_FLAG_AH, true, 0+xoffs,-3); // DEMO: Altitude Hold
OSD_Element_Flag_Label( 19, 6, OSD_FLAG_PH, true, 0+xoffs,-6); // DEMO: Position Hold
OSD_Element_Flag_Label( 19, 7, OSD_FLAG_CH, true, 0+xoffs,-1); // DEMO: Coming Home
 
xoffs -= 4;
OSD_Element_Flag_Label( 16, 2, OSD_FLAG_BA, true, -3+xoffs, 0); // DEMO: MK Batt Warning
OSD_Element_Flag_Label( 16, 4, OSD_FLAG_EL, true, -3+xoffs,-3); // DEMO: Emergency Landing
OSD_Element_Flag_Label( 16, 6, OSD_FLAG_RL, true, -3+xoffs,-6); // DEMO: Range Limit
OSD_Element_Flag_Label( 16, 7, OSD_FLAG_S0, true, -3+xoffs,-1); // DEMO: GPS-Sat not ok (GPS NOT ok)
 
xoffs -= 4;
OSD_Element_Flag_Label( 12, 2, OSD_FLAG_CA, true, 0+xoffs, 0); // DEMO: Calibrate
OSD_Element_Flag_Label( 12, 4, OSD_FLAG_ST, true, 0+xoffs,-3); // DEMO: Start
OSD_Element_Flag_Label( 12, 6, OSD_FLAG_MR, true, 0+xoffs,-6); // DEMO: Motor Run
OSD_Element_Flag_Label( 12, 7, OSD_FLAG_FY, true, 0+xoffs,-1); // DEMO: Fly
 
xoffs -= 4;
OSD_Element_Flag_Label( 9, 2, OSD_FLAG_O1, true, -2+xoffs, 0); // DEMO: Out1
OSD_Element_Flag_Label( 9, 4, OSD_FLAG_O2, true, -2+xoffs,-3); // DEMO: Out2
OSD_Element_Flag_Label( 9, 6, OSD_FLAG_TR, true, -2+xoffs,-6); // DEMO: Target Reached
OSD_Element_Flag_Label( 9, 7, OSD_FLAG_MC, true, -2+xoffs,-1); // DEMO: Manual Control
 
xoffs -= 4;
OSD_Element_Flag_Label( 6, 2, OSD_FLAG_TU, true, -4+xoffs, 0); // DEMO: Vario Trim Up
OSD_Element_Flag_Label( 6, 4, OSD_FLAG_TD, true, -4+xoffs,-3); // DEMO: Vario Trim Down
OSD_Element_Flag_Label( 6, 6, OSD_FLAG_FR, true, -4+xoffs,-6); // DEMO: Free
OSD_Element_Flag_Label( 6, 7, OSD_FLAG_SL, true, -4+xoffs,-1); // DEMO: No Serial Link
 
#endif
 
 
return( ScreenName );
}
 
 
 
//##############################################################
#ifdef OSD_DEBUG_SCREEN
//##############################################################
 
//**************************************************************
//* OSD_DEBUG_SCREEN - Experimental-Code usw.
//* - nicht fuer die Oeffentlichkeit bestimmt
//* - gesteuert ueber define OSD_DEBUG_SCREEN
//**************************************************************
 
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// NOTIZEN
//
// 1. Thema: Motorwerte abfragen
//
// ja, auf die gleiche Weise wie man an die Config Parameter kommt.
//
// SwitchToFC();
// SendOutData( 'u', ADDRESS_FC, BL-Adresse, &tmp_dat, 1);
//
// Die Daten kommen dann in der Form:
// typedef struct
// {
// uint8_t Version; // the version of the BL (0 = old)
// uint8_t SetPoint; // written by attitude controller
// uint8_t SetPointLowerBits; // for higher Resolution of new BLs
// uint8_t State; // 7 bit for I2C error counter, highest bit indicates if motor is present
// uint8_t ReadMode; // select data to read
// // the following bytes must be exactly in that order!
// uint8_t Current; // in 0.1 A steps, read back from BL
// uint8_t MaxPWM; // read back from BL -> is less than 255 if BL is in current limit, not running (250) or starting (40)
// int8_t Temperature; // old BL-Ctrl will return a 255 here, the new version the temp. in ?C
// } __attribute__((packed)) MotorData_t;
//
//
// kennst Du die Seite?:http://www.mikrokopter.de/ucwiki/en/SerialProtocol?highlight=%28%28----%28-*%29%28\r%29%3F\n%29%28.*%29CategoryCoding%29#en.2BAC8-SerialCommands.Flight-Ctrl
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
uint8_t xload_setting( uint8_t setting )
{
mode = 'Q'; // Settings
uint8_t timeout = 50;
rxd_buffer_locked = FALSE;
 
while (!rxd_buffer_locked && timeout)
{
SendOutData ('q', ADDRESS_FC, 1, &setting, 1);
// _delay_ms(50);
timer = 20;
while (timer > 0);
timeout--;
}
 
if (timeout != 0)
{
Decode64 ();
setting = *pRxData;
mk_param_struct = (mk_param_struct_t *) (pRxData + 1) ;
}
else
{ // timeout occured
// lcd_printp_at (0, 2, PSTR("Fehler: keine Daten"), 0);
lcd_puts_at(0, 2, strGet(OSD_ERROR), 0);
timer = 100;
while (timer > 0);
setting = 255;
}
return setting;
}
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
const char * OSD_Screen_Debug( uint8_t nMode )
{
const char *ScreenName = PSTR("Debug");
static s16 min_debug = 0;
static s16 max_debug = 0;
static uint16_t debug_count = 0;
 
//-----------------------------------------
// REDRAW
// statische Screen Elemente die nicht
// jedesmal neu gezeichnet werden muessen
//-----------------------------------------
if( nMode == OSD_SCREEN_REDRAW )
{
// do things here for static screen elements like labels and so....
min_debug = 0;
max_debug = 0;
}
 
lcd_printp_at( 0, 0, PSTR("Debug"), 0);
 
 
debug_count++;
 
if( naviData->Variometer < min_debug ) min_debug = naviData->Variometer;
if( naviData->Variometer > max_debug ) max_debug = naviData->Variometer;
 
write_ndigit_number_s ( 8, 1, (naviData->Variometer), 12, 0,MNORMAL); // s16 Variometer;
write_ndigit_number_s ( 8, 2, (min_debug), 12, 0,MNORMAL); // s16 Variometer;
write_ndigit_number_s ( 8, 3, (max_debug), 12, 0,MNORMAL); // s16 Variometer;
 
write_ndigit_number_u ( 8, 5, (debug_count), 12, 0,MNORMAL); //
//write_ndigit_number_u ( 8, 6, (timer), 12, 0,MNORMAL); //
 
//draw_variometer2( 6, 19, 7, 21, naviData->Variometer);
 
return( ScreenName );
}
//##############################################################
#endif // OSD_DEBUG_SCREEN
//##############################################################
 
 
 
//--------------------------------------------------------------
// ehemals: OSD_ALTITUDE,Config.OSD_ScreenMode == 0
//--------------------------------------------------------------
const char * OSD_Screen_OSD0( uint8_t nMode )
{
const char *ScreenName = PSTR("OSD0");
//uint8_t xoffs;
 
//-----------------------------------------
// REDRAW static screen elements
//-----------------------------------------
if( nMode == OSD_SCREEN_REDRAW )
{
// do things here for static screen elements like labels and so....
}
 
OSD_Element_AltitudeControl ( 0, 3);
OSD_Element_Altitude ( 11, 3, 0);
OSD_Element_BatteryLevel ( 0, 7, 0);
OSD_Element_Capacity ( 13, 7);
OSD_Element_Current ( 8, 7);
OSD_Element_CareFree ( 0, 5);
OSD_Element_CompassDegree ( 13, 0, 0);
OSD_Element_CompassDirection( 18, 0);
OSD_Element_CompassRose ( 12, 1);
OSD_Element_FlyingTime ( 0, 1);
OSD_Element_GroundSpeed ( 0, 0);
OSD_Element_HomeCircle ( 16, 4, 5, 0, 0,0);
OSD_Element_HomeDegree ( 12, 4);
OSD_Element_HomeDistance ( 10, 5, 0);
OSD_Element_Target ( 10, 6, 0);
//OSD_Element_TargetDegree ( x, y);
OSD_Element_WayPoint ( 5, 6);
OSD_Element_LED1Output ( 0, 6);
OSD_Element_LED2Output ( 3, 6);
//OSD_Element_Manuell ( x, y);
OSD_Element_NaviMode ( 0, 4);
//OSD_Element_RCIntensity ( x, y);
OSD_Element_VarioWert ( 12, 2);
OSD_Element_SatsInUse ( 18, 2, 0);
OSD_Element_StatusFlags ( 0, 2);
OSD_Element_Variometer ( 9, 0);
 
return( ScreenName );
}
 
 
 
 
//--------------------------------------------------------------
// ehemals: OSD_ALTITUDE,Config.OSD_ScreenMode == 1
//--------------------------------------------------------------
const char * OSD_Screen_OSD1( uint8_t nMode )
{
const char *ScreenName = PSTR("OSD1");
//uint8_t xoffs;
 
//-----------------------------------------
// REDRAW static screen elements
//-----------------------------------------
if( nMode == OSD_SCREEN_REDRAW )
{
// do things here for static screen elements like labels and so....
}
 
//OSD_Element_AltitudeControl( x, y);
OSD_Element_Altitude ( 1, 1, 1);
OSD_Element_BatteryLevel ( 0, 7, 1);
OSD_Element_Capacity ( 13, 7);
OSD_Element_Current ( 8, 7);
//OSD_Element_CareFree ( x, y);
OSD_Element_CompassDegree ( 13, 0, 1);
OSD_Element_CompassDirection( 18, 0);
OSD_Element_CompassRose ( 12, 1);
OSD_Element_FlyingTime ( 7, 6);
OSD_Element_GroundSpeed ( 0, 0);
OSD_Element_HomeCircle ( 1, 3, 7, 0, 0,0);
OSD_Element_HomeDegree ( 8, 3);
OSD_Element_HomeDistance ( 7, 2, 1);
//OSD_Element_Target ( x, y, 1);
//OSD_Element_TargetDegree ( x, y);
//OSD_Element_WayPoint ( x, y);
//OSD_Element_LED1Output ( x, y);
//OSD_Element_LED2Output ( x, y);
//OSD_Element_Manuell ( x, y);
OSD_Element_NaviMode ( 8, 5);
OSD_Element_RCIntensity ( 15, 6);
OSD_Element_VarioWert ( 15, 2);
OSD_Element_SatsInUse ( 8, 4, 1);
//OSD_Element_StatusFlags ( x, y);
OSD_Element_Variometer ( 9, 0);
 
return( ScreenName );
}
 
 
//--------------------------------------------------------------
// ehemals: OSD_ALTITUDE,Config.OSD_ScreenMode == 2
//--------------------------------------------------------------
const char * OSD_Screen_OSD2( uint8_t nMode )
{
const char *ScreenName = PSTR("OSD2");
//uint8_t xoffs;
 
//-----------------------------------------
// REDRAW static screen elements
//-----------------------------------------
if( nMode == OSD_SCREEN_REDRAW )
{
// do things here for static screen elements like labels and so....
}
OSD_Element_AltitudeControl ( 0, 1);
OSD_Element_Altitude ( 0, 4, 2);
OSD_Element_BatteryLevel ( 13, 7, 2);
OSD_Element_Capacity ( 0, 7);
OSD_Element_Current ( 8, 7);
OSD_Element_CareFree ( 0, 3);
OSD_Element_CompassDegree ( 12, 3, 2);
//OSD_Element_CompassDirection( x, y);
//OSD_Element_CompassRose ( x, y);
OSD_Element_FlyingTime ( 15, 5);
//OSD_Element_GroundSpeed ( x, y);
OSD_Element_HomeCircle ( 16, 0, 5, 0, 0,0);
OSD_Element_HomeDegree ( 11, 5);
OSD_Element_HomeDistance ( 0, 5, 2);
OSD_Element_Target ( 0, 6, 2);
OSD_Element_TargetDegree ( 11, 6);
//OSD_Element_WayPoint ( x, y);
OSD_Element_LED1Output ( 12, 2);
OSD_Element_LED2Output ( 14, 2);
//OSD_Element_Manuell ( x, y);
OSD_Element_NaviMode ( 0, 2);
//OSD_Element_RCIntensity ( x, y);
OSD_Element_VarioWert ( 15, 4);
OSD_Element_SatsInUse ( 10, 0, 2);
OSD_Element_StatusFlags ( 0, 0);
//OSD_Element_Variometer ( x, y);
 
return( ScreenName );
}
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
const char * OSD_Screen_3DLage( uint8_t nMode )
{
const char *ScreenName = PSTR("3D Lage");
uint16_t head_home;
uint8_t Nick;
uint8_t Roll;
 
//-----------------------------------------
// REDRAW static screen elements
//-----------------------------------------
if( nMode == OSD_SCREEN_REDRAW )
{
// do things here for static screen elements like labels and so....
}
 
head_home = (naviData->HomePositionDeviation.Bearing + 360 - naviData->CompassHeading) % 360;
 
//lcd_cls ();
 
lcd_line(26,32,100,32,1); // horizontal //
lcd_line(63,0,63,63,1); // vertical //
//lcd_puts_at(12, 7, strGet(KEYLINE5), 0);
 
// 45' Angel
lcd_line(61,11,65,11,1); // -- //
lcd_line(40,30,40,34,1); // | //
lcd_line(86,30,86,34,1); // | //
lcd_line(61,53,65,53,1); // -- //
 
lcd_puts_at(9, 0, strGet(OSD_3D_V), 0); // V
lcd_puts_at(3, 3, strGet(OSD_3D_L), 0); // L
lcd_puts_at(17, 3, strGet(OSD_3D_R), 0); // R
lcd_puts_at(9, 7, strGet(OSD_3D_H), 0); // H
 
lcd_puts_at(0, 0, strGet(OSD_3D_NICK), 0); // Ni
write_ndigit_number_s (2, 0, naviData->AngleNick, 3, 0,0);
lcd_putc (5, 0, 0x1e, 0); // degree symbol
 
lcd_puts_at(0, 7, strGet(OSD_3D_ROLL), 0); // Ro
write_ndigit_number_s (2, 7, naviData->AngleRoll, 3, 0,0);
lcd_putc (5, 7, 0x1e, 0); // degree symbol
 
lcd_puts_at(13, 0, strGet(OSD_3D_COMPASS), 0);
//write_ndigit_number_s (15, 0,head_home, 3, 0);
write_ndigit_number_u (15, 0, naviData->CompassHeading, 3, 0,0);
lcd_putc (18, 0, 0x1e, 0); // degree symbol
lcd_printp_at (19, 0, (const char *) (pgm_read_word ( &(directions_p[heading_conv(naviData->CompassHeading)]))), 0);
 
Nick = ((-naviData->AngleNick/2)+32);
Roll = ((-naviData->AngleRoll/2)+63);
 
lcd_ellipse ( old_AngleRoll, old_AngleNick, 9, 8, 0);
lcd_ellipse_line( old_AngleRoll, old_AngleNick, 8, 7, old_hh, 0);
 
lcd_ellipse ( Roll, Nick, 9, 8, 1);
lcd_ellipse_line( Roll, Nick, 8, 7, head_home, 1);
 
// remember last values (3DL)
old_hh = head_home;
old_AngleNick = Nick;
old_AngleRoll = Roll;
return( ScreenName );
}
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
const char * OSD_Screen_Statistics( uint8_t nMode )
{
const char *ScreenName = PSTR("Statistics");
uint8_t line = 0;
 
//-----------------------------------------
// REDRAW static screen elements
//-----------------------------------------
/*
if( nMode == OSD_SCREEN_REDRAW )
{
// do things here for static screen elements like labels and so....
}
*/
//---------------------------
// max Altitude
lcd_puts_at (0, line, strGet(STATS_ITEM_0), MNORMAL);
write_ndigit_number_s (14, line, max_Altimeter / (30 / AltimeterAdjust), 4, 0,MNORMAL);
lcdx_putc (18, line, 'm', MNORMAL, 2,0);
//---------------------------
// max Speed
// max_GroundSpeed = 1;
lcd_puts_at (0, ++line, strGet(STATS_ITEM_1), MNORMAL);
write_ndigit_number_u (15, line, (uint16_t) (((uint32_t) max_GroundSpeed * (uint32_t) 9) / (uint32_t) 250), 3, 0,MNORMAL);
lcdx_printp_at(18, line, PSTR("kmh"), MNORMAL, 2,0);
 
//---------------------------
// max Distance
// max_Distance = 64512;
lcd_puts_at (0, ++line, strGet(STATS_ITEM_2), MNORMAL);
write_ndigit_number_u (14, line, max_Distance / 10, 4, 0,MNORMAL);
lcdx_putc (18, line, 'm', MNORMAL, 2,0);
//---------------------------
// max time
// max_FlyingTime = 3600;
lcd_puts_at (0, ++line, strGet(STATS_ITEM_4), MNORMAL);
write_time (13, line, max_FlyingTime);
 
//---------------------------
// min voltage
lcd_puts_at (0, ++line, strGet(STATS_ITEM_3), MNORMAL);
if( min_UBat==255 )
lcd_printp_at(14, line, PSTR(" 0"), MNORMAL);
else
write_ndigit_number_u_10th (14, line, min_UBat, 3, 0,MNORMAL);
lcdx_putc (18, line, 'V', MNORMAL, 2,0);
 
//---------------------------
// max Current
// max_Current = 1000;
lcd_puts_at (0, ++line, strGet(STATS_ITEM_5), MNORMAL);
write_ndigit_number_u_10th (13, line, max_Current, 4, 0,MNORMAL);
lcdx_putc (18, line, 'A', MNORMAL, 2,0);
 
//---------------------------
// Used Capacity
lcd_puts_at (0, ++line, strGet(STATS_ITEM_6), MNORMAL);
write_ndigit_number_u (14, line, max_Capacity, 4, 0,MNORMAL);
lcdx_printp_at(18, line, PSTR("mAh"), MNORMAL, 2,0);
return( ScreenName );
}
 
//--------------------------------------------------------------
//--------------------------------------------------------------
void print_statistics (void)
{
lcd_cls ();
lcd_puts_at(12, 7, strGet(ENDE), 0);
 
OSD_Screen_Statistics( OSD_SCREEN_REDRAW );
 
while (!get_key_press (1 << KEY_ESC))
timer = TIMEOUT;
 
COSD_FLAGS2 &= ~COSD_WASFLYING;
get_key_press(KEY_ALL);
lcd_cls();
}
 
 
//-----------------------------------------------------------
//-----------------------------------------------------------
void OSD_Info( uint8_t ScreenNum, const char *ScreenName)
{
lcd_frect( 0, 36, 127, 10, 0); // clear
lcd_frect( 0, 34, 4, 4, 0); // clear links
lcd_frect( 0, 40, 127, 24, 1); // Box
lcd_frect( 10, 36, 108, 4, 1); // Filler oben
lcd_fcircle( 8, 39, 7, 1); // Links
lcd_fcircle( 121, 41, 5, 1); // Rechts
 
lcd_line ( 4, 51, 122, 51, 0); // Linie mitte
 
//-----------------------
// ScreenNummer: ScreenName
//-----------------------
write_ndigit_number_s ( 1, 5, ScreenNum, 2, 1,2);
lcd_printp_at( 3, 5, PSTR(":"), 2);
lcd_printp_at( 5, 5, ScreenName, 2);
 
//-----------------------
// Key's
//-----------------------
lcd_puts_at(0, 7, strGet(KEYLINE3), 2);
lcd_printp_at (17, 7, PSTR("Info"), 2);
do
{
timer = TIMEOUT;
_delay_ms(50);
} while ( !( (get_key_press (1 << KEY_ENTER)) || (get_key_press (1 << KEY_ESC)) || (get_key_press (1 << KEY_PLUS)) || (get_key_press (1 << KEY_MINUS)) ) );
}
 
 
 
//##############################################################
//# OSD MAIN LOOP
//##############################################################
 
//--------------------------------------------------------------
// OSD MAIN LOOP
//--------------------------------------------------------------
void osd( uint8_t ShowMode )
{
uint8_t flag;
uint8_t tmp_dat;
uint8_t ScreenRefresh;
uint8_t MAX_OSD_Screens;
//uint8_t status; // FC Kommunikation
const char *ScreenName = PSTR("");
 
lcd_cls();
 
//----------------------------------------
// NC Hardware needed
//----------------------------------------
if( hardware == FC )
{
lcd_puts_at(0, 3, strGet(ONLY_NC), 0); // Nur mit NC
timer = 100;
while (timer > 0);
return;
}
 
/*
//-----------------------------------------------------------------------------------------------
// 07.03.2013 OG: del
// Dieser Teil hat immer wieder Probleme bereitet bei der Verbindung des PKT-OSD zum MK da
// Timeouts zustande kamen. Eine Recherche im Code ergab, dass die Nutzdaten die
// hierueber bezogen werden sich lediglich auf Flags_ExtraConfig beschraenkten (CFG2_HEIGHT_LIMIT).
// Siehe dazu untere Kommentare.
//
// Der negative Effekt moeglicher Timeouts und Verzoegerungen sind es aktuell nicht Wert
// CFG2_HEIGHT_LIMIT zu unterstuetzen. Dieses Feature ist erstmal raus.
//
// Falls gewuenscht wird, dass CFG2_HEIGHT_LIMIT wieder in das PKT-OSD kommt muss
// es zuverlaessig an anderer Stelle implementiert werden - und zwar nicht in osd.c
// weil es eine statische FC-Information ist (ggf. beim Verbindungsaufbau PKT <-> MK).
//
// Hat auch aktuell Auswirkung auf den Code OSD_Element_AltitudeControl()
//
lcd_printp_at( 0, 3, PSTR("connecting MK..."), 0);
 
SwitchToFC();
 
status = load_setting(0xff);
if( status == 255 )
{
lcd_puts_at(0, 0, strGet(NO_SETTINGS), 0); // Keine Settings
_delay_ms(2000);
}
Flags_ExtraConfig = mk_param_struct->ExtraConfig; // OG: wird in osd.c nur verwendet von: OSD_Element_AltitudeControl()
Flags_GlobalConfig = mk_param_struct->GlobalConfig; // OG: wird nicht in osd.c verwendet
Flags_GlobalConfig3 = mk_param_struct->GlobalConfig3; // OG: wird nicht in osd.c verwendet
*/
 
rxd_buffer_locked = FALSE; // 07.03.2013 OG: fix
// es gab Probleme mit dem Empfang gueltiger NC-Daten, die zu unschoenen Starteffekten bei den
// OSD-Screens gefuehrt haben. Mit rxd_buffer_locked = FALSE vor SwitchToNC() ist das PKT wieder im 'Takt'
SwitchToNC();
 
mode = 'O';
 
// disable debug...
// RS232_request_mk_data (0, 'd', 0);
tmp_dat = 0;
SendOutData ('d', ADDRESS_ANY, 1, &tmp_dat, 1);
 
// request OSD Data from NC every 100ms
// RS232_request_mk_data (1, 'o', 100);
tmp_dat = 10;
OSD_active = true; // benoetigt für Navidata Ausgabe an SV2
SendOutData( 'o', ADDRESS_NC, 1, &tmp_dat, 1);
 
//-------------------------
// Clear statistics
//-------------------------
max_Altimeter = 0;
max_GroundSpeed = 0;
max_Distance = 0;
min_UBat = 255;
max_FlyingTime = 0;
CellIsChecked = 0;
cells = 0;
AkkuWarnThreshold = 0;
OldWP = 0;
NextWP = false;
 
//-------------------------
//-------------------------
MAX_OSD_Screens = 8;
 
#ifdef OSD_DEBUG_SCREEN
MAX_OSD_Screens += 1;
#endif
if( Config.OSD_ScreenMode >= MAX_OSD_Screens ) Config.OSD_ScreenMode = 0;
 
 
//-------------------------
// Timer & Flags
//-------------------------
ScreenRefresh = OSD_SCREEN_REDRAW;
flag = 0;
timer = TIMEOUT;
abo_timer = ABO_TIMEOUT;
timer2 = OSD_REFRESH_TIME;
 
do
{
if( rxd_buffer_locked )
{
timer = TIMEOUT;
Decode64 ();
naviData = (NaviData_t *) pRxData;
 
 
//----------------------------------
// Winkel zu Home
//----------------------------------
if( Config.OSD_HomeMKView == 1 )
heading_home = (naviData->HomePositionDeviation.Bearing + 360 - naviData->CompassHeading) % 360;
else
heading_home = (naviData->CompassHeading - naviData->HomePositionDeviation.Bearing + 360 ) % 360;
 
 
//----------------------------------
// speichere letzte GPS-Positionen
//----------------------------------
GPS_Pos_t currpos;
currpos.Latitude = naviData->CurrentPosition.Latitude;
currpos.Longitude = naviData->CurrentPosition.Longitude;
 
if((currpos.Latitude != last5pos[0].Latitude)&&(currpos.Longitude != last5pos[0].Longitude))
{
last5pos[6] = last5pos[5];
last5pos[5] = last5pos[4];
last5pos[4] = last5pos[3];
last5pos[3] = last5pos[2];
last5pos[2] = last5pos[1];
last5pos[1] = last5pos[0];
last5pos[0] = currpos;
}
 
// 07.03.2013 OG: Speichere permanent letzte Position in Config
// wurde vorher nur in OSD_TimeOut() gemacht
Config.LastLatitude = currpos.Latitude; // speichere letzte Position in Config
Config.LastLongitude = currpos.Longitude; // speichere letzte Position in Config
 
flag = 1;
 
if (naviData->FCStatusFlags & FC_STATUS_MOTOR_RUN)
{ // should be engines running
// motors are on, assume we were/are flying
COSD_FLAGS2 |= COSD_WASFLYING;
}
 
 
//----------------------------------
// remember statistics (only when engines running)
//----------------------------------
if( naviData->FCStatusFlags & FC_STATUS_MOTOR_RUN )
{
if (naviData->Altimeter > max_Altimeter) max_Altimeter = naviData->Altimeter;
if (naviData->GroundSpeed > max_GroundSpeed) max_GroundSpeed = naviData->GroundSpeed;
if (naviData->HomePositionDeviation.Distance > max_Distance) max_Distance = naviData->HomePositionDeviation.Distance;
if (naviData->FlyingTime > max_FlyingTime) max_FlyingTime = naviData->FlyingTime;
if (naviData->UBat < min_UBat) min_UBat = naviData->UBat;
if (naviData->Current > max_Current) max_Current = naviData->Current;
if (naviData->UsedCapacity > max_Capacity) max_Capacity = naviData->UsedCapacity;
}
 
//----------------------------------
// OSD-Screens
//----------------------------------
if( ScreenRefresh == OSD_SCREEN_REDRAW ) lcd_cls();
 
if( timer2 == 0 || ScreenRefresh == OSD_SCREEN_REDRAW)
{
if( Config.OSD_ScreenMode == 0) ScreenName = OSD_Screen_General( ScreenRefresh );
else if( Config.OSD_ScreenMode == 1) ScreenName = OSD_Screen_Navigation( ScreenRefresh );
else if( Config.OSD_ScreenMode == 2) ScreenName = OSD_Screen_MKStatus( ScreenRefresh );
else if( Config.OSD_ScreenMode == 3) ScreenName = OSD_Screen_OSD0( ScreenRefresh );
else if( Config.OSD_ScreenMode == 4) ScreenName = OSD_Screen_OSD1( ScreenRefresh );
else if( Config.OSD_ScreenMode == 5) ScreenName = OSD_Screen_OSD2( ScreenRefresh );
else if( Config.OSD_ScreenMode == 6) ScreenName = OSD_Screen_3DLage( ScreenRefresh );
else if( Config.OSD_ScreenMode == 7) ScreenName = OSD_Screen_Statistics( ScreenRefresh );
 
#ifdef OSD_DEBUG_SCREEN
else if( Config.OSD_ScreenMode == (MAX_OSD_Screens-1) ) ScreenName = OSD_Screen_Debug( ScreenRefresh );
#endif
}
ScreenRefresh = OSD_SCREEN_REFRESH;
if( timer2 == 0 ) timer2 = OSD_REFRESH_TIME;
 
//-----------------------
// Key-Handler
//-----------------------
 
//if (get_key_press (1 << KEY_PLUS))
//{
// print_position ();
//}
if( get_key_press (1 << KEY_ENTER) ) // info
{
OSD_Info( Config.OSD_ScreenMode, ScreenName);
ScreenRefresh = OSD_SCREEN_REDRAW;
}
if (get_key_press (1 << KEY_MINUS)) // previous screen
{
if( Config.OSD_ScreenMode == 0 )
Config.OSD_ScreenMode = MAX_OSD_Screens-1;
else
Config.OSD_ScreenMode--;
ScreenRefresh = OSD_SCREEN_REDRAW;
}
 
if (get_key_press (1 << KEY_PLUS)) // next Screen
{
Config.OSD_ScreenMode++;
Config.OSD_ScreenMode = ( Config.OSD_ScreenMode >= MAX_OSD_Screens ? 0 : Config.OSD_ScreenMode );
ScreenRefresh = OSD_SCREEN_REDRAW;
}
 
 
//-----------------------
// Akku Warnung
//-----------------------
CheckMKLipo();
 
// if (naviData->UBat > MK_LowBat) //bei kurzzeitigen Schwankungen Beeper erst wieder aus wenn UBat 0,2 V höher als Warnschwelle
// { //Beeper aus
// BeepTime = 0;
// BeepMuster = 0xFFFF;
// }
// Akku Warnung Ende
 
 
//-----------------------
// remember last values
//-----------------------
last_RC_Quality = naviData->RC_Quality;
last_UBat = naviData->UBat;
old_FCFlags = naviData->FCStatusFlags;
 
rxd_buffer_locked = FALSE;
 
 
//-----------------------
// abo_timer
//-----------------------
if (!abo_timer)
{ // renew abo every 3 sec
// request OSD Data from NC every 100ms
// RS232_request_mk_data (1, 'o', 100);
tmp_dat = 10;
SendOutData ('o', ADDRESS_NC, 1, &tmp_dat, 1);
abo_timer = ABO_TIMEOUT;
}
} //if (rxd_buffer_locked)
if (!timer)
{
OSD_Timeout(flag);
flag = 0;
ScreenRefresh = OSD_SCREEN_REDRAW;
}
} while (!get_key_press (1 << KEY_ESC));
OSD_active = false;
}
Property changes:
Added: svn:mime-type
+text/plain
\ No newline at end of property
/Transportables_Koptertool/branch/test2/GPL_PKT_V3_6_7f_FC090b/osd/osd.h
0,0 → 1,111
/*****************************************************************************
* Copyright (C) 2008 Thomas Kaiser, thomas@ft-fanpage.de *
* Copyright (C) 2009 Peter "woggle" Mack, mac@denich.net *
* Copyright (C) 2011 Christian "Cebra" Brandtner, brandtner@brandtner.net *
* Copyright (C) 2011 Harald Bongartz *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
* Credits to: *
* Holger Buss & Ingo Busker from mikrokopter.de for the MK project + SVN *
* http://www.mikrokopter.de *
* Gregor "killagreg" Stobrawa for his version of the MK code *
* Thomas Kaiser "thkais" for the original project. See *
* http://www.ft-fanpage.de/mikrokopter/ *
* http://forum.mikrokopter.de/topic-4061-1.html *
* Claas Anders "CaScAdE" Rathje for providing the font and his C-OSD code *
* http://www.mylifesucks.de/oss/c-osd/ *
* Harald Bongartz "HaraldB" for providing his Ideas and Code for usibility*
*****************************************************************************/
 
 
#ifndef _OSD_H
#define _OSD_H
 
 
#define OSD_SCREEN_REFRESH 0 // Screen: Werte anzeigen
#define OSD_SCREEN_REDRAW 1 // Screen: Labels und statischer Elemente neu zeichen, Werte anzeigen
 
 
// Flags
#define OSD_FLAG_AH 0 // Altitue Hold
#define OSD_FLAG_PH 1 // Position Hold
#define OSD_FLAG_CF 2 // Care Free
#define OSD_FLAG_CH 3 // Coming Home
#define OSD_FLAG_O1 4 // Out1 (LED 1)
#define OSD_FLAG_O2 5 // Out2 (LED 2)
#define OSD_FLAG_BA 6 // LowBat warning (MK)
#define OSD_FLAG_CA 7 // Calibrate
#define OSD_FLAG_ST 8 // Start
#define OSD_FLAG_MR 9 // Motor Run
#define OSD_FLAG_FY 10 // Fly
#define OSD_FLAG_EL 11 // Emergency Landing
#define OSD_FLAG_FS 12 // RS Failsave Active
#define OSD_FLAG_GP 13 // GPS ok
#define OSD_FLAG_S0 14 // GPS-Sat not ok (GPS NOT ok)
#define OSD_FLAG_TU 15 // Vario Trim Up
#define OSD_FLAG_TD 16 // Vario Trim Down
#define OSD_FLAG_FR 17 // Free
#define OSD_FLAG_RL 18 // Range Limit
#define OSD_FLAG_SL 19 // No Serial Link
#define OSD_FLAG_TR 20 // Target Reached
#define OSD_FLAG_MC 21 // Manual Control
 
#define OSD_FLAG_COUNT 22
 
 
void osd (uint8_t ShowMode);
void vario_beep_output (void);
void OSD_Timeout(uint8_t flag);
void CheckMKLipo(void);
extern volatile uint8_t OSD_active;
extern volatile uint8_t error;
 
void OSD_Element_Flag_Label( uint8_t xC, uint8_t yC, uint8_t item, uint8_t lOn, int8_t xoffs, int8_t yoffs);
void OSD_Element_Flag( uint8_t xC, uint8_t yC, uint8_t item, int8_t xoffs, int8_t yoffs);
void OSD_Element_AltitudeControl( uint8_t x, uint8_t y );
void OSD_Element_Altitude( uint8_t x, uint8_t y, uint8_t nStyle );
void OSD_Element_BattLevel2( uint8_t x, uint8_t y, int8_t xoffs, int8_t yoffs );
void OSD_Element_BatteryLevel_Bar( uint8_t x, uint8_t y );
void OSD_Element_BatteryLevel_Text( uint8_t x, uint8_t y, uint8_t nStyle );
void OSD_Element_BatteryLevel( uint8_t x, uint8_t y, uint8_t nStyle );
void OSD_Element_Capacity( uint8_t x, uint8_t y );
void OSD_Element_CareFree( uint8_t x, uint8_t y );
void OSD_Element_CompassDegree( uint8_t x, uint8_t y, uint8_t nStyle );
void OSD_Element_CompassDirection( uint8_t x, uint8_t y );
void OSD_Element_CompassRose( uint8_t x, uint8_t y );
void OSD_Element_Current( uint8_t x, uint8_t y );
void OSD_Element_FlyingTime( uint8_t x, uint8_t y );
void OSD_Element_GroundSpeed( uint8_t x, uint8_t y );
void OSD_Element_HomeCircle( uint8_t x, uint8_t y, uint8_t breite, int8_t rOffset, int8_t xoffs, int8_t yoffs );
void OSD_Element_HomeDegree( uint8_t x, uint8_t y );
void OSD_Element_HomeDistance( uint8_t x, uint8_t y, uint8_t nStyle );
void OSD_Element_LEDOutput( uint8_t x, uint8_t y, uint8_t bitmask );
void OSD_Element_LED1Output( uint8_t x, uint8_t y );
void OSD_Element_LED2Output( uint8_t x, uint8_t y );
void OSD_Element_Manuell( uint8_t x, uint8_t y );
void OSD_Element_NaviMode( uint8_t x, uint8_t y );
void OSD_Element_RCIntensity( uint8_t x, uint8_t y );
void OSD_Element_SatsInUse( uint8_t x, uint8_t y, uint8_t nStyle );
void OSD_Element_StatusFlags( uint8_t x, uint8_t y );
void OSD_Element_Variometer( uint8_t x, uint8_t y );
void OSD_Element_Target( uint8_t x, uint8_t y, uint8_t nStyle );
void OSD_Element_VarioWert( uint8_t x, uint8_t y );
void OSD_Element_WayPoint( uint8_t x, uint8_t y );
void OSD_Element_TargetDegree( uint8_t x, uint8_t y );
void OSD_Element_UpDown( uint8_t x, uint8_t y, int8_t xoffs, int8_t yoffs);
 
#endif
Property changes:
Added: svn:mime-type
+text/plain
\ No newline at end of property