Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2136 - 1
/*****************************************************************************
2
 *   Copyright (C) 2008 Thomas Kaiser, thomas@ft-fanpage.de                  *
3
 *   Copyright (C) 2009 Peter "woggle" Mack, mac@denich.net                  *
4
 *   Copyright (C) 2011 Christian "Cebra" Brandtner, brandtner@brandtner.net *
5
 *   Copyright (C) 2011 Harald Bongartz                                      *
6
 *                                                                           *
7
 *   This program is free software; you can redistribute it and/or modify    *
8
 *   it under the terms of the GNU General Public License as published by    *
9
 *   the Free Software Foundation; either version 2 of the License.          *
10
 *                                                                           *
11
 *   This program is distributed in the hope that it will be useful,         *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
14
 *   GNU General Public License for more details.                            *
15
 *                                                                           *
16
 *   You should have received a copy of the GNU General Public License       *
17
 *   along with this program; if not, write to the                           *
18
 *   Free Software Foundation, Inc.,                                         *
19
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.               *
20
 *                                                                           *
21
 *                                                                           *
22
 *   Credits to:                                                             *
23
 *   Holger Buss & Ingo Busker from mikrokopter.de for the MK project + SVN  *
24
 *                          http://www.mikrokopter.de                        *
25
 *   Gregor "killagreg" Stobrawa for his version of the MK code              *
26
 *   Thomas Kaiser "thkais" for the original project. See                    *
27
 *                          http://www.ft-fanpage.de/mikrokopter/            *
28
 *                          http://forum.mikrokopter.de/topic-4061-1.html    *
29
 *   Claas Anders "CaScAdE" Rathje for providing the font and his C-OSD code *
30
 *                          http://www.mylifesucks.de/oss/c-osd/             *
31
 *   Harald Bongartz "HaraldB" for providing his Ideas and Code for usibility*
32
 *   Oliver Gemesi   "olli42" for additions und changes in OSDScreen         *
33
 *****************************************************************************/
34
 
35
 
36
//--------------------
37
// Debug
38
//--------------------
39
//#define DEBUG_OSD_TIME            // mit dem NC-Simulator koennen keine brauchbaren Zeit/Datum Daten ermittelt werden
40
                                    //  am Anfang von osd() wird mit dieser Einstellung eine gueltige Fake-Zeit/Date gesetzt
41
//#define DEBUG_OSD_STAT_MOTORRUN   // erzwingt Statistik Aufzeichnung auch wenn die Motoren nicht laufen
42
 
43
//############################################################################
44
//# HISTORY  osd.c
45
//#
46
//# 05.04.2015 Cebra
47
//# - chg: SendOutData( 'h', ADDRESS_ANY, 2, &mkdisplayCmd, 1, 0x00,1) ergänzt um 2. Parameter wegen Fehlfunktion mit NC 2.09h
48
//#
49
//# 21.06.2014 OG
50
//# - chg: osd() - bei auftreten von mk_timeout wieder OSD_MK_Connect(MK_CONNECT)
51
//#        aktiviert -> dadurch wird u.a. wieder auf die NC umgeschaltet falls
52
//#        etwas anderes (z.B. ein anderes PKT) auf die FC umgeschaltet hat
53
//# - add: draw_icon_mk()
54
//#
55
//# 18.06.2014 OG
56
//# - add: MKLiPoCells_Init(), MKLiPoCells_Check()
57
//# - chg: define ORIENTATION_H, ORIENTATION_V verschoben nach osd.h
58
//#
59
//# 02.06.2014 OG
60
//# - fix: Beep_Waypoint() Target-Reach Beep auch bei Single-WP's (WP-Listen
61
//#        die nur aus einem WP bestehen)
62
//#
63
//# 01.06.2014 OG
64
//# Beginn von Auslagerungen von Code alter OSD-Screens nach osdold_screens.c/h
65
//# - add: include "../osd/osdold_screens.h"
66
//# - add: include "../osd/osdold_messages.h"
67
//# - chg: osd() - Check bzgl. NC-Hardware entfernt da das bereits durch das
68
//#        aufrufende Menue erledigt wird
69
//# - add: OSD_Screen_MKDisplay() um Beep_Waypoint() ergaenzt
70
//# - chg: OSD_Screen_Waypoints() umgestellt auf Beep_Waypoint()
71
//# - add: Beep_Waypoint()
72
//#
73
//# 31.05.2014 OG
74
//# - chg: OSD_Screen_MKDisplay() - umgestellt auf PKT_KeylineUpDown()
75
//#
76
//# 26.05.2014 OG
77
//# - add: etliche Aenderungen/Erweiterung am Screen "Waypoints" (auch neues Layout)
78
//#
79
//# 24.05.2014 OG
80
//# - fix: OSD_Screen_Waypoints(), OSD_Screen_MKDisplay() - Anzeige des akt. WP-Index
81
//# - chg: OSD_Screen_3DLage() - optisches Facelift
82
//# - fix: OSD_Screen_3DLage() - es wurden ggf. Kreise gezeichnet die ungueltig
83
//#        und in undefinierten Speicher gingen - wurde korrigiert
84
//# - chg: OSD0,1,2 angepasst an OSD_Element_CompassDirection() mit xoffs,yoffs
85
//# - chg: OSD_Element_CompassDirection() - erweitert um xoffs,yoffs
86
//#
87
//# 20.05.2014 OG
88
//# - chg: OSD_Element_Flag_Label() - Anpassung zur Rahmenbestimmung eines Flags
89
//#
90
//# 19.05.2014 OG
91
//# - fix: osd() - Tastensteuerung bei MK-Empfangsverlust
92
//# - chg: osd() - wenn MK-Setting nicht ermittelt werden konnte dann exit
93
//# - add: OSD_Screen_MKDisplay() - Anzeige von akt. Waypoint und Anzahl der Waypoints
94
//# - chg: OSD_Popup_MKSetting() - gibt true/false fuer Ok zurueck und Beep bei Fehler
95
//# - chg: OSD_Popup_MKSetting() - timeout von 15 auf 9 reduziert
96
//# - chg: OSD_Popup_MKSetting(), OSD_Popup_MKError() - Layout, Multi-Sprachenunterstuetzung
97
//#
98
//# 02.05.2014 OG
99
//# - del: Popup_Draw() (jetzt in lcd.c)
100
//#
101
//# 02.05.2014 OG
102
//# - chg: kleine Aenderung an Codereihenfolge von MkError_Save() wegen Compiler-Warning
103
//#
104
//# 28.04.2014 OG
105
//# Anmerkung OSD-MK-Display: wenn der MK-Display Modus eingeschaltet wird, dann werden die Display Daten
106
//# angefordert und die BL-Daten etwas reduziert. Hin und wieder kann es passieren das ein Tastendruck im
107
//# OSD-MK-Display-Modus nicht durch kommt (aber nicht allzu stoerend) - kann evtl. verbessert werden wenn
108
//# auch die OSD-Daten reduziert werden (waere jedoch einiges mehr Aufwand).
109
//# - Unterstuetzung von MK-Display (nur NC-Modus) im OSD
110
//#   (einschalten mit langem Druck dritte Taste von links, abschalten ebenso)
111
//# - Info-Anzeige bzgl. langem Tastendruck fuer MK-Display erweitert und deutsche Uebersetzung von "long press"
112
//# - Umstrukturierung von osd.c fuer MK-Display
113
//# - Aenderungen/Erweiterungen an verschiedenen weiteren Funktionen wie OSD_MK_GetData() fuer MK-Display
114
//# - add: OSD_MK_ShowTimeout() - neues Design/Layout
115
//# - del: OSD_Timeout() (ersetzt durch OSD_MK_ShowTimeout())
116
//# - chg: verschiedene Aenderungen an Timings
117
//# - add: neuer Timer fuer MK-Display: timer_get_displaydata
118
//# - fix: es gab bei einem Datenpaket-Timer einen Konflikt mit 'timer' - ein neuer Timer wurde aktiviert (timer_mk_timeout)
119
//#
120
//# 22.04.2014 OG
121
//# - add: OSD_Element_HomeCircleX() - soll das alte OSD_Element_HomeCircle() ersetzen, wenn
122
//#        die alten OSD-Screens endgueltig rausfliegen
123
//# - chg: Aenderung Anzeige OSD_Screen_UserGPS() (abgerundete Ecken und Code Einsparung)
124
//# - chg: Aenderung Anzeige OSD_Screen_MKStatus() (abgerundete Ecken und Code Einsparung)
125
//# - chg: Aenderung Anzeige OSD_Screen_Electric() (abgerundete Ecken und Code Einsparung)
126
//#
127
//# 01.03.2014 OG
128
//# - chg: OSD_Popup_MKError() auf lcdx_printp_center() umgestellt
129
//#
130
//# 16.02.2014 OG
131
//# - chg: OSD_Popup_MKSetting() umgestellt auf MK_Setting_load()
132
//#
133
//# 13.02.2014 OG
134
//# - chg: OSD_MK_GetData() prueft mit MKVersion_Cmp() auf NC-Version v0.30g
135
//#        ob GPS-Zeit-Datenpakete ('t') von der NC angefordert werden koennen
136
//#
137
//# 12.02.2014 OG
138
//# - chg: define MKVERSIONnnn rund um OSD_MK_UTCTime() entfernt
139
//#        -> TODO OG: auf neue MKVersion bzgl. Versionsprüfung anpassen!
140
//#        -> keine Unterstuetzung mehr durch zu alte NC-Versionen
141
//# - del: die includes zu den alten parameter... entfernt
142
//#
143
//# 10.02.2014 OG
144
//# - chg: OSD_Popup_MKSetting() umgestellt auf MKVersion_Setting_print()
145
//#
146
//# 08.02.2014 OG
147
//# - chg: OSD_Popup_MKSetting() umgestellt auf neue MKVersion Struktur
148
//#
149
//# 04.02.2014 OG
150
//# - fix: OSD_Element_BattLevel2() Aufruf von writex_ndigit_number_u_100th()
151
//#
152
//# 03.02.2014 OG
153
//# - chg: OSD_Element_BattLevel2() unterstuetzt Config.OSD_ShowCellU zur Anzeige
154
//#        der MK-Spannung als Einzelzelle (kalk. auf Basis der ermittelten Zellenzahl)
155
//#
156
//# 29.01.2014 OG
157
//# - add: neue MK-Errorcodes 32,33,34
158
//# - add: #include "mk/mkbase.h"
159
//#
160
//# 24.01.2014 OG
161
//# - chg: OSD_Popup_MKSetting(): MK-Settings wird beim Start vom OSD wieder angezeigt
162
//#        auch wenn die falsche FC-Revision vorhanden ist mit folgender Regel:
163
//#        a) wenn falsche FC-Settings-Revision dann nur die Nummer
164
//#        b) wenn richtige FC-Revision dann mit Nummer und Namen
165
//#
166
//# 06.01.2014 Cebra
167
//# - add: MK-Settingsname wird bei falscher FC Version nicht angezeigt
168
//#
169
//# 07.07.2013 OG
170
//# - add: OSD-Screens koennen vom Benutzer an-/ausgeschaltet werden (osd(), ScreenCtrl_Push())
171
//# - chg: OSD-Screen Namen jetzt in messages.c
172
//# - fix: MK-Error Check prueft ob die Fehlernummer gueltig ist
173
//# - del: alten Screen Electric (der ohne Nachkomma bei den Stroemen)
174
//#
175
//# 03.07.2013 OG
176
//# - chg: OSD_Popup_MKSetting() - zentrierte Anzeige des Setting-Namens
177
//# - chg: OSD_Popup_MKSetting() - timing
178
//# - chg: osd() - Screen-Umschaltung beschleunigt
179
//# - chg: timinigs bei OSD_MK_Connect(), osd() (werden Verbindungsfehler reduziert?)
180
//#
181
//# 02.07.2013 OG
182
//# - chg: CheckMKLipo() - MK-Unterspannungs-Beep nur wenn Motoren laufen
183
//# - del: unbenutzte Variablen
184
//#
185
//# 30.06.2013 OG
186
//# - add: grafische Akku-Anzeige auch fuer Screen Navigation und ElectricN
187
//#
188
//# 30.06.2013 OG
189
//# - add: Screen General: das Batt-Symbol zeigt grafisch den Fuellstand
190
//#        des MK-Lipos
191
//# - add: Mittelwert fuer Gesamtstrom
192
//# - add: calc_avg() - Mittelwertberechnung
193
//# - chg: Benamung Statistik-Var's von mid_* auf avg_* geaendert
194
//# - add: USE_OSD_PKTHOOK in osd() - aktuell noch nicht klar ob PKT_Hook()
195
//#        die Kommunikation stoert
196
//#
197
//# 27.06.2013 OG
198
//# - chg: numerische Winkelanzeige im Screen "Navigation" von -180 bis 180 Grad
199
//#        0 Grad = vorderer Ausleger zeigt zur Startposition
200
//# - fix: Homesicht des MK's (Winkelanzeige, Grafik)
201
//#        ab nun: keine Benutzereinstellung mehr dafuer
202
//#        es gilt: 0 Grad bzw. Strich nach unten -> der vordere Ausleger des MK
203
//#                 zeigt auf seine Startposition
204
//#
205
//# 19.06.2013 OG
206
//# - fix: redundante PKT-Error 40 eliminiert durch merken via old_PKTErrorcode
207
//#        -> hilft wenn der MK ausgeschaltet wird waehrend man in der PKT-OSD-Anzeige ist
208
//# - fix: last_FlyTime in osd()
209
//#
210
//# 18.06.2013 OG
211
//# - chg: OSD_Timeout() erweitert um Errorlogging (Code 40 = "PKT RX lost")
212
//# - add: Fehlerliste "PKT RX lost" (Code: 40)
213
//#
214
//# 15.06.2013 OG
215
//# - chg: Anzeige OSD_Popup_MKSetting() kann durch Benutzer via Setup an/ausgeschaltet werden
216
//#
217
//# 15.06.2013 OG
218
//# - chg: OSD_Popup_MKSetting() optimiert, Layout, fix
219
//# - chg: PKT_CtrlHook erstmal wieder disabled in osd() (evtl. Probleme mit Timings?)
220
//#
221
//# 13.06.2013 cebra
222
//# - add: Settings Popup beim Start des OSD-Screens
223
//#
224
//# 11.06.2013 OG
225
//# - add: Mittelwertberechnung BL-Strom [MK_GetData()]
226
//# - chg: Config.OSD_ScreenMode wird vor PKT_CtrlHook() gesetzt [osd()]
227
//#
228
//# 27.05.2013 OG
229
//# - fix: OSD_MK_UTCTime() (neue "t" Version) Problem wegen cast fuer Sekunden
230
//#
231
//# 19.05.2013 OG
232
//# - chg: osd() erweitert um PKT_CtrlHook() um u.a. PKT-Updates zu ermoeglichen
233
//#
234
//# 16.05.2013 OG
235
//# - add: USE_OSD_SCREEN_NAVIGATION, USE_OSD_SCREEN_ELECTRIC, USE_OSD_SCREEN_ELECTRIC_N,
236
//#        USE_OSD_SCREEN_MKSTATUS, USE_OSD_SCREEN_USERGPS, USE_OSD_SCREEN_3DLAGE,
237
//#        USE_OSD_SCREEN_STATISTIC
238
//# - add: OSD_Screen_ElectricN() - zeigt BL-Stroeme mit Nachkomma an
239
//# - del: define SHOW_OSD_BLCURRENT_10TH (ersetzt durch neue Screen-Variante)
240
//# - chg: osd() umgestellt auf OSD Screen Controler; Anpassungen dafuer an allen Screens
241
//# - add: Funktionen fuer Screen Controler (Screen_*())
242
//#
243
//# 15.05.2013 OG
244
//# - chg: OSD_Screen_Electric() zeigt BL-Strom mit Nachkomma an
245
//#         (einstellbar via define SHOW_OSD_BLCURRENT_10TH bzgl. neue/alte Anzeige)
246
//# - add: define DEBUG_OSD_STAT_MOTORRUN erzwingt Statistik Aufzeichnung auch wenn
247
//#        die Motoren nicht laufen
248
//# - fix: osd() Statistik-Ende Zeit wird nach Landung gesetzt
249
//# - chg: diverse Aufraeumarbeiten
250
//# - chg: OSD_Screen_Statistics() umgetsellt auf calc_BLmax(()
251
//# - add: calc_BLmax() ermittelt max. BL Current & Temp
252
//# - del: draw_symbol_degree(), draw_symbol_rc() - wurden ersetzt durch
253
//#        Zeichen im font 8x6 (SYMBOL_SMALLDEGREE, SYMBOL_RCQUALITY)
254
//#
255
//# 14.05.2013 OG
256
//# - add: OSD_MK_Connect() vereinheitlicht MK-Verbindungsinitialisierung
257
//#        und MK-Abo-Renew
258
//# - chg: OSD_MK_UTCTime() atomisiert via ATOMIC_BLOCK()
259
//# - chg: OSD_Screen_Debug_RX() verschiedene Optimierungen und Beschreibungen
260
//#
261
//# 14.05.2013 OG
262
//# - chg: OSD_MK_UTCTime() wird mittels define jetzt mit neuem oder mit altem
263
//#        Algorithmus einkompiliert.
264
//#        ALT bei: defined MKVERSION088n || defined MKVERSION090b || defined MKVERSION090e
265
//#        NEU bei: alles andere (also neuer): die neue Zeit/Datumsermittlung
266
//#
267
//# 13.05.2013 OG
268
//# - fix: an allen Stellen mit naviData->CompassHeading ein Modulo 360 ergaenzt
269
//#        um Winkelangaben der FC geradezuziehen falls der Kopter beim Mixersetup
270
//#        'verdreht' wurde (Problem von helitron im Forum - Winkelanzeige > 360 Grad)
271
//#        Ist ggf. ab Firmware NC 0.30h nicht mehr notwendig da Holger das
272
//#        korrigieren wollte (muesste noch geprueft werden)
273
//#
274
//# 11.05.2013 OG
275
//# - add: OSD_MK_UTCTime_NEW() - ab NC 0.30g (Alpha, noch nicht im Einsatz)
276
//#
277
//# 05.05.2013 OG
278
//# - chg: OSD_Popup_Info() & OSD_Popup_MKError() wurden vereinheitlicht
279
//#        mittels Popup_Draw()
280
//# - chg: Anzeigezeiten der Popup's etwas verkuerzt
281
//#
282
//# 03.05.2013 OG
283
//# - fix: OSD_MK_GetData() - griff beim lesen der BL's auf naviData fuer
284
//#        die Statistik - relevante naviData-Werte werden nun vor dem
285
//#        wechseln auf BL-Data gemerkt
286
//# - chg: Erfassung der Statistik Start/Ende-Zeit verbessert
287
//# - chg: bei Aufrufen von writex_datetime_time()/writex_datetime_time() den
288
//#        Parameter 'timeoffset' entfernt
289
//# - add: define DEBUG_OSD_TIME um eine Fake-Zeit/Datum bei Gebrauch des
290
//#        NC-Simulators zu setzen
291
//#
292
//# 29.04.2013 OG
293
//# - chg: Plausibilitaetscheck in OSD_MK_UTCTime() bzgl. des Datums
294
//#
295
//# 28.04.2013 OG
296
//# - chg: die alten OSD-Screens angepasst auf define USE_FONT_BIG
297
//#
298
//# 24.04.2013 OG
299
//# - chg: directions_p[] geaendert auf Kompatibilitaet mit Atmel Studio 6
300
//#
301
//# 21.04.2013 OG
302
//# - chg: define AltimeterAdjust nach osd.h verschoben
303
//#
304
//# 14.04.2013 OG
305
//# - add: weitere Statistik-Aufzeichnungen
306
//# - fix: MK_GetData() - Statistik-Aufzeichnung nur fuer wirklich vorhandene BL's
307
//#
308
//# 04.04.2013 OG
309
//# - fix: 3 warnings
310
//#
311
//# 04.04.2013 OG
312
//# - chg: MK-Errortext-Anzeige umgestellt auf naviData->Errorcode
313
//#        weniger Datenkomminkation mit dem MK und schnelleres Ansprechverhalten
314
//#
315
//# 03.04.2013 OG
316
//# - chg: defines OSD_DEMO, OSD_SCREEN_DEBUG, OSD_SCREEN_OLD
317
//#        umbenannt nach: USE_OSD_DEMO, USE_OSD_SCREEN_DEBUG, USE_OSD_SCREEN_OLD
318
//#        und verschoben nach: main.h
319
//#
320
//# 28.03.2013 OG
321
//# - fix: MKErr_Log_Init() - es fehlte Multiplikation mit MAX_MKERR_LOG
322
//# - chg: Code Formatierungen
323
//#
324
//# 28.03.2013 CB
325
//# - add: replace OSD_Statistic, GPS_User, MKErr_Log in EEProm structure variable
326
//#
327
//# 28.03.2013 OG
328
//# - fix: abo_timer wieder aktiviert fuer 'o' und 'k'
329
//#
330
//# 28.03.2013 OG
331
//# - chg: osd_statistic_t - erweitert um diverse Werte und Timestamps (werden apeter implementiert)
332
//# - add: mkerror_t MKErr_Log[MAX_MKERR_LOG] - Vorbereitung um MK-Errors zu loggen
333
//#
334
//# 27.03.2013 OG
335
//# - add: Datum / Zeit vom MK lesen
336
//# - chg: Kommunikation mit dem MK optimiert
337
//# - chg: auf neue messages.c angepasst
338
//# - struct von den Statistiken auf PKTdatetime PKTdatetime_t
339
//# - verschiedene andere Aenderungen
340
//#
341
//# 22.03.2013 OG
342
//# erhebliche Aenderungen / Ergaenzungen - hier nur das Wichtigste
343
//# - neue Funktion "User GPS" (UGPS) - mit langem Druck auf Taste KEY_ENTER werden die aktuellen GPS-Daten abgespeichert
344
//#     * gespeichert wird nur wenn wenn der MK GPS-Ok meldet
345
//#     * wenn Ok erfolgt ein bestaetigungs Beep; wenn nicht Ok erfolgt ein Error-Beep
346
//# - neuer Screen "User GPS" - Anzeige der letzten der 3 UGPS-Koordinaten (intern wird mehr gespeichert)
347
//# - Anzeige von MK-Error Messages als Popup mit einstellbarer Anzeigezeit (kann mit Taste abgebrochen werden)
348
//#     * kann getestet werden z.B. durch Ausschalten der Funke (= "RC Signal lost")
349
//#     * siehe: http://www.mikrokopter.de/ucwiki/ErrorCodes
350
//# - OSD-Info ist nun ein Popup - autom. ausblenden nach einstellbarer Zeit; im Hintergrund werden weiterhin MK-Daten empfangen und ausgewertet
351
//# - neuer Debug-Screen "Debug RXPackages" - zeigt die Anzahl empfangener Datenpakete der verschiedenen Bereiche (um z.B. Timings einzustellen)
352
//# - erweiterte Kommunikation mit dem MK fuer BL-Daten und Error-Messages
353
//# - Timings der MK-Datenkommunikation weitreichend einstellbar durch defines
354
//# - Datenstrukturen fuer OSD-Statistiken und BL-Statistiken
355
//# - neue timer: timer_get_erdata, timer_get_bldata, timer_osd_refresh, timer_pkt_uptime
356
//# - mit dem define OSD_SCREEN_OLD koennen ggf. die alten OSD-Screens ausgeblendet werden (spart ein paar KByte's)
357
//# - verschiedene Optimierungen
358
//#
359
//# 12.03.2013 OG
360
//# - add: Get_BL_Data() - BL-Ctrl via NC auslesen (BETA) (siehe dort auch Kommentare im func-Header)
361
//# - add: neuer Screen "Electric"
362
//# - chg: Layout von Screen "Navigation" - Pixelverschiebungen
363
//# - chg: Layout von Screen "MK-Status" - Pixelverschiebungen und Anzeige 'Strom' ersetzt durch 'entn. Kapazitaet'
364
//# - add: in osd() LiPO-Cell Erkennung hinzugefuegt (fuer Screen "Electric")
365
//#
366
//# 10.03.2013 OG
367
//# - fix: doppelte Degree-Anzeige in OSD_Element_CompassDegree()
368
//# - add: neuer Screen "MK-Status"
369
//# - add: 7 neue OSD-Flags
370
//# - chg: Screen-Refresh Zeit via timer2 (einstellbar durch define TIME_OSD_REFRESH)
371
//# - chg: mit define OSD_DEBUG_SCREEN kann ein zusaetzlicher Screen verwendet werden zum testen/entwickeln
372
//# - del: entfernt CFG2_HEIGHT_LIMIT in OSD_Element_AltitudeControl() (bis bessere Loesung gefunden ist)
373
//#
374
//# 08.03.2013 OG
375
//# - del: OSD_Screen_Element() und cleanup in osd.h
376
//# - add: OSD_Element_UpDown() (steigend/sinken via Pfeilen)
377
//# - chg: OSD_Element_UpDown() in Screen "General" und "Navigation" hinzugefuegt (rechts neben der Hoehenanzeige)
378
//# - chg: Screen "General" die Sat-Warnung wurde auf OSD_Element_Flag(OSD_FLAG_S0) geaendert
379
//# - chg: Anzeige von Flag 'nicht genug GPS-Sateliten' (OSD_FLAG_S0) auf "S!" geändert
380
//#
381
//# 07.03.2013 OG
382
//# - Hinweis bzgl. LowBatt-Anzeige in den Screens "General" und "Navigation":
383
//#      Es gibt zwei unabhängige LowBatt-Warnungen.
384
//#      1. die PKT LowBatt-Warnung: sie arbeitet mit der im PKT hinterlegten
385
//#         LowBatt Spannung und stellt den Spannungswert inkl. der Einheit "V"
386
//#         invers dar wenn der Warnwert erreicht wurde (inkl. lautem PKT-Peepen)
387
//#      2. die MK-LowBatt Warnung: hierbeit wird das Flag "BA" angezeigt wenn
388
//#         der MK eine LowBatt Warnung sendet
389
//#      Dadurch hat man nun zwei verschiedene LowBatt Warnungen die man auf Wunsch
390
//#      verschieden einstellen kann. Bei mir ist die PKT-LowBatt etwas niedriger
391
//#      eingestellt als die MK-Warnung und bedeutet "es ist aller hoechste Zeit zu landen".
392
//#      Die Spannung der MK-LowBat ist ein wenig hoeher eingestellt und
393
//#      zeigt mir "es ist bald Zeit zu landen".
394
//# - del: Kommunikation zu FC - siehe Kommentare in osd()
395
//# - chg: Kommunikation zu NC - siehe Kommentare in osd()
396
//# - add: neuer Screen "Navigation"
397
//# - chg: Layout Screen "Statistics" - Einheiten um zwei Pixel nach rechts verschoben
398
//# - chg: Layout von Screen "General" modifiziert (u.a. xoffs,yoffs Pixelverschiebungen)
399
//# - add: OSD_FLAG_BA in Screen "General"
400
//# - add: die OSD_Element_xyz() Funktionen in osd.h aufgenommen
401
//# - chg: an verschiedenen Stellen die Char-Drawmode defines MNORMAL, MINVERS, usw. eingebaut
402
//# - del: Kompatibilitaetscode fuer "3D-Lage" ueber Hauptmenue entfernt
403
//# - chg: die Funktionen OSD_Element_Switch() und OSD_Element_SwitchLabel() heissen
404
//#        nun OSD_Element_Flag() und OSD_Element_Flag_Label()
405
//# - chg: die defines OSD_SWITCH_xy heissen jetzt OSD_FLAG_xy
406
//# - fix: letzte GPS-Koordinaten werden jetzt permanent Config.LastLatitude, Config.LastLongitude gespeichert
407
//#
408
//# 03.03.2013 OG
409
//# - add: delay in Mainloop von osd() um springende Werte abzudaempfen (TEST)
410
//# - add: Startverzoegerung der Screens bis NaviData sich etwas stabilisiert hat (TEST)
411
//# - add: OSD Startup Message "connecting MK..."
412
//# - add: 'Emergency Landing' (EL) Anzeige in Screen "General"
413
//# - del: OUT1/OUT2 Anzeige in Screen "General"
414
//# - add: RC-Quality in Screen "General"
415
//# - add: func: draw_symbol_rc() (alternative RC-Quality Symbol)
416
//# - fix: Hoehenanzeige fuer Screens "OSD0" und "OSD1"
417
//# - fix: OSD_Element_SwitchLabel() angepasst fuer x=0 und y=0
418
//# - add: OSD_Element_Switch/Label() erweitert um OSD_SWITCH_FS
419
//# - fix: Screen-Redraw nach OSD_MK_TIMEOUT() und anderen Fehlermeldungen
420
//# - chg: messages.c: STATS_ITEM_0 bis STATS_ITEM_6 angepasst (1 char kuerzer)
421
//# - chg: Layout von OSD_Info() - mehr background-clear und etwas kleiner
422
//#
423
//# 02.03.2013 OG
424
//# - chg: keine internal func in Screen's wegen warnings bei anderen
425
//# - del: Screen "OSD3"
426
//# - fix: Hoehenanzeige in Screen "General" (Minuszeichen)
427
//# - add: MK LowBat Warning in Screen "General"
428
//# - add: neues Degree Symbol (als func) in Screen General (kleiner als das Char 0x1E)
429
//# - add: weitere Flags in OSD_Element_Flag()
430
//#
431
//# 01.03.2013 OG
432
//# - Reskrukturierung Code (+ neuer OSD-Screens und einiges mehr)
433
//############################################################################
434
 
435
 
436
//############################################################################
437
//# HINWEISE:
438
//#
439
//# 1. define: USE_OSD_DEMO  (main.h)
440
//#    mit define OSD_DEMO wird ein Demo-Modus bei den neuen Screens einge-
441
//#    schaltet - damit werden u.a. alle Flag's angezeigt fuer Scree-Fotos
442
//#
443
//# 2. define: USE_OSD_SCREEN_DEBUG  (main.h)
444
//#    mit diesem define wird ein zusaetzlicher Screen "Debug" einkompiliert
445
//#    fuer Test / Experimente / Debug von OSD-Elementen
446
//#
447
//# 3. define: USE_OSD_SCREEN_OLD  (main.h)
448
//#    ein-/ ausschalten der alten OSD-Screens OSD0, OSD1, OSD2 (spart ca. 3 KByte)
449
//#
450
//# 4. Timings der MK-Datenkommunikation
451
//#    die Timings sind weitreichend enstellbar ueber die define im Abschnitt 'Timings'
452
//#    der Debug-Screen 'Debug RXPackages' informiert ueber die Anzahl eingegangener
453
//#    Datenpakete der verschiedenen Bereiche (OSD, BL-Daten, Error-Message)
454
//#
455
//# 5. Informationen zum Display
456
//#    DOG: 128 x 64 Pixel with 6x8 Font => 21 x 8
457
//#
458
//# 6. MK-Kommunikationsprotokoll Referenz
459
//#    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
460
//############################################################################
461
 
462
#include "../cpu.h"
463
#include <avr/io.h>
464
#include <inttypes.h>
465
#include <stdlib.h>
466
#include <avr/pgmspace.h>
467
#include <util/delay.h>
468
#include <string.h>
469
#include <util/atomic.h>
470
 
471
#include "../main.h"
472
#include "../lcd/lcd.h"
473
#include "../timer/timer.h"
474
#include "../uart/usart.h"
475
#include "../eeprom/eeprom.h"
476
#include "../messages.h"
477
#include "../sound/pwmsine8bit.h"
478
#include "../mk-data-structs.h"
479
#include "../pkt/pkt.h"
480
#include "../osd/osd.h"
481
#include "../utils/xutils.h"
482
#include "../mk/mkbase.h"
483
#include "../osd/osdold_messages.h"
484
#include "../osd/osdold_screens.h"
485
 
486
 
487
//--------------------
488
// Funktionen ein-/ausbinden
489
//--------------------
490
// -> siehe main.h
491
 
492
 
493
//--------------------
494
// Timings
495
//--------------------
496
#define TIME_OSD_REFRESH      45  // Screen Refresh (Steuerung via 'timer_osd_refresh') (n*10 = ms; 100 entspricht 1 Sekunde)
497
#define TIME_POPUP_INFO       400 // 4 Sekunden Popup-Info zeigen (kann mit Taste abgebrochen werden)
498
#define TIME_POPUP_MKERROR    700 // 7 Sekunden Popup-MK-Error zeigen (kann mit Taste abgebrochen werden)
499
 
500
#define TXINTERVAL_OSDDATA    10  // Intervall mit der der MK OSD-Daten senden soll (n*10 = ms)
501
 
502
#define TIME_GET_BLDATA       35  // Zeitintervall in der BL-Daten vom MK geholt werden (Steuerung via 'timer_get_bldata') (n*10 = ms; 100 entspricht 1 Sekunde)
503
#define TIME_READ_BLDATA      20  // fuer n Zeit werden BL-Daten vom MK gelesen (Steuerung via timer) (n*10 = ms; 100 entspricht 1 Sekunde))
504
#define TXINTERVAL_BLDATA     7   // Intervall mit der der MK BL-Daten senden soll (n*10 = ms)
505
 
506
#define TIME_GET_TIDATA     12000 // alles 120 Sekunden Zeit/Datum vom MK lesen (die Zwischenzeit wird von einem PKT-Timer uebernommen)
507
 
508
#define TIME_GET_DISPLAYDATA  20  // fuer n Zeit werden BL-Daten vom MK gelesen (Steuerung via timer) (n*10 = ms; 100 entspricht 1 Sekunde))
509
 
510
 
511
//#define MK_TIMEOUT          300 // MK-Verbindungsfehler wenn fuer n Zeit keine gueltigen Daten hereinkommen (3 sec)
512
#define MK_TIMEOUT            400 // MK-Verbindungsfehler wenn fuer n Zeit keine gueltigen Daten hereinkommen (4 sec)
513
 
514
 
515
//--------------------
516
// weiteres
517
//--------------------
518
#define OSD_POPUP_NONE      0
519
#define OSD_POPUP_INFO      1
520
#define OSD_POPUP_MKERROR   2
521
 
522
#define MK_CONNECT          1
523
#define MK_ABORENEW         2
524
 
525
 
526
 
527
// global definitions and global vars
528
NaviData_t          *naviData;
529
uint16_t            heading_home;
530
uint8_t             drawmode;
531
uint8_t             OSDScreenRefresh;
532
 
533
 
534
// flags from last round to check for changes
535
uint8_t  old_AngleNick      = 0;
536
uint8_t  old_AngleRoll      = 0;
537
uint16_t old_hh             = 0;
538
 
539
 
540
// aktuell nicht benoetigt - siehe Kommentar in osd.c
541
//mk_param_struct_t     *mk_param_struct;
542
//uint8_t           Flags_ExtraConfig;
543
//uint8_t           Flags_GlobalConfig;
544
//uint8_t           Flags_GlobalConfig3;
545
 
546
 
547
// cache old vars for blinking attribute, checkup is faster than full
548
// attribute write each time
549
 
550
volatile uint8_t OSD_active         = 0;
551
 
552
uint8_t Vario_Beep_Up               = 0;
553
uint8_t Vario_Beep_Down             = 0;
554
uint8_t Vario_Beep_Up_Interval      = 9;
555
uint8_t Vario_Beep_Down_Interval    = 6;
556
uint8_t Vario_Threshold             = 0;
557
uint8_t Vario_Threshold_Value       = 7;
558
uint8_t OldWP                       = 0;
559
uint8_t NextWP                      = 0;
560
 
561
uint8_t WP_old                      = 0;    // Screen: "Waypoints"
562
uint8_t WP_last                     = false;    // Screen: "Waypoints"
563
 
564
 
565
 
566
#define MAX_CELL_VOLTAGE    43  // max cell voltage for LiPO
567
#define MIN_CELL_VOLTAGE    32  // min cell voltage for LiPO
568
 
569
// Flags
570
volatile uint8_t error                  = 0;
571
uint8_t         cells                   = 0;
572
uint8_t         BattLowVoltageWarning   = 0;
573
uint8_t         CellIsChecked           = 0;
574
uint8_t         AkkuWarnThreshold       = 0;
575
uint16_t        duration                = 0;
576
 
577
 
578
//-----------------------------------------------------------
579
// Buffer
580
//-----------------------------------------------------------
581
BLData_t        blData[OSD_MAX_MOTORS];         // speichert gelesene BL-Datenpakete
582
pkt_gpspos_t    GPS_Current;                    // aktuelle GPS-Position
583
u8              old_PKTErrorcode;               // speichert den letzen Errorcode vom PKT damit dieser nicht wiederholt gespeichert wird
584
u8              old_MKErrorcode;                // speichert den letzen Errorcode vom MK damit dieser nicht wiederholt angezeigt wird
585
 
586
 
587
//-----------------------------------------------------------
588
// OSD Daten
589
//-----------------------------------------------------------
590
NaviData_t      osdData;                        // Buffer
591
 
592
//-----------------------------------------------------------
593
// MK-DISPLAY
594
//-----------------------------------------------------------
595
uint8_t         mkdisplayMode   = false;
596
uint8_t         mkdisplayCmd    = 0xff;
597
char            mkdisplayData[81];              // Buffer (80 +1 fuer term. Char)
598
 
599
 
600
//---------------------
601
// DEBUG
602
//---------------------
603
#ifdef USE_OSD_SCREEN_DEBUG
604
uint16_t        readCounterOSD;                 // Anzahl gelesener Datenpakete von NC Modus 'o' (Request OSD-Data)
605
uint16_t        readCounterTIME;                // Anzahl gelesener Datenpakete von NC (Time)
606
uint16_t        readCounterDISPLAY;
607
uint16_t        readCounterBL[OSD_MAX_MOTORS];  // Anzahl gelesener Datenpakete pro BL via NC Modus 'k' (BL Ctrl Status)
608
#endif  // USE_OSD_SCREEN_DEBUG
609
 
610
 
611
//---------------------
612
// Strings & Co.
613
//---------------------
614
static const char mkerror00[] PROGMEM = "No Error";
615
static const char mkerror01[] PROGMEM = "FC not compatible";
616
static const char mkerror02[] PROGMEM = "MK3Mag not compati.";
617
static const char mkerror03[] PROGMEM = "no FC communication";
618
static const char mkerror04[] PROGMEM = "no MK3Mag communic.";
619
static const char mkerror05[] PROGMEM = "no GPS communication";
620
static const char mkerror06[] PROGMEM = "bad compass value";
621
static const char mkerror07[] PROGMEM = "RC Signal lost";
622
static const char mkerror08[] PROGMEM = "FC spi rx error";
623
static const char mkerror09[] PROGMEM = "no NC communication";
624
static const char mkerror10[] PROGMEM = "FC Nick Gyro";
625
static const char mkerror11[] PROGMEM = "FC Roll Gyro";
626
static const char mkerror12[] PROGMEM = "FC Yaw Gyro";
627
static const char mkerror13[] PROGMEM = "FC Nick ACC";
628
static const char mkerror14[] PROGMEM = "FC Roll ACC";
629
static const char mkerror15[] PROGMEM = "FC Z-ACC";
630
static const char mkerror16[] PROGMEM = "Pressure sensor";
631
static const char mkerror17[] PROGMEM = "FC I2C";
632
static const char mkerror18[] PROGMEM = "Bl Missing";
633
static const char mkerror19[] PROGMEM = "Mixer Error";
634
static const char mkerror20[] PROGMEM = "Carefree Error";
635
static const char mkerror21[] PROGMEM = "GPS lost";
636
static const char mkerror22[] PROGMEM = "Magnet Error";
637
static const char mkerror23[] PROGMEM = "Motor restart";
638
static const char mkerror24[] PROGMEM = "BL Limitation";
639
static const char mkerror25[] PROGMEM = "Waypoint range";
640
static const char mkerror26[] PROGMEM = "No SD-Card";
641
static const char mkerror27[] PROGMEM = "SD Logging aborted";
642
static const char mkerror28[] PROGMEM = "Flying range!";
643
static const char mkerror29[] PROGMEM = "Max Altitude";
644
static const char mkerror30[] PROGMEM = "No GPS Fix";
645
static const char mkerror31[] PROGMEM = "compass not calibr.";
646
static const char mkerror32[] PROGMEM = "BL selftest";
647
static const char mkerror33[] PROGMEM = "no ext. compass";
648
static const char mkerror34[] PROGMEM = "compass sensor";
649
 
650
#define MAX_MKERROR_NUM        34   // maximale Error-Nummer vom MK (verwendet in osd())
651
 
652
static const char mkerror35[] PROGMEM = "";  // free for MK
653
static const char mkerror36[] PROGMEM = "";  // free for MK
654
static const char mkerror37[] PROGMEM = "";  // free for MK
655
static const char mkerror38[] PROGMEM = "";  // free for MK
656
static const char mkerror39[] PROGMEM = "";  // free for MK
657
 
658
static const char pkterror40[] PROGMEM = "PKT RX lost";
659
 
660
 
661
//---------------------------------------
662
// wenn die Liste erweitert wird,
663
// MAX_MKERROR_NUM in osd.h anpassen!
664
//---------------------------------------
665
const char * const mkerrortext[] PROGMEM=
666
{
667
    mkerror00,
668
    mkerror01,
669
    mkerror02,
670
    mkerror03,
671
    mkerror04,
672
    mkerror05,
673
    mkerror06,
674
    mkerror07,
675
    mkerror08,
676
    mkerror09,
677
    mkerror10,
678
    mkerror11,
679
    mkerror12,
680
    mkerror13,
681
    mkerror14,
682
    mkerror15,
683
    mkerror16,
684
    mkerror17,
685
    mkerror18,
686
    mkerror19,
687
    mkerror20,
688
    mkerror21,
689
    mkerror22,
690
    mkerror23,
691
    mkerror24,
692
    mkerror25,
693
    mkerror26,
694
    mkerror27,
695
    mkerror28,
696
    mkerror29,
697
    mkerror30,
698
    mkerror31,
699
    mkerror32,
700
    mkerror33,
701
    mkerror34,
702
    mkerror35,
703
    mkerror36,
704
    mkerror37,
705
    mkerror38,
706
    mkerror39,
707
    pkterror40
708
};
709
 
710
 
711
//char* rose = "-+-N-+-O-+-S-+-W-+-N-+-O-+-S-+-W-+-N-+-O-+-S-+-W";
712
const char rose[48] PROGMEM = {
713
    0x0e, 0x0f, 0x0e, 'N', 0x0e, 0x0f, 0x0e, 'O', 0x0e, 0x0f, 0x0e, 'S',
714
    0x0e, 0x0f, 0x0e, 'W', 0x0e, 0x0f, 0x0e, 'N', 0x0e, 0x0f, 0x0e, 'O',
715
    0x0e, 0x0f, 0x0e, 'S', 0x0e, 0x0f, 0x0e, 'W', 0x0e, 0x0f, 0x0e, 'N',
716
    0x0e, 0x0f, 0x0e, 'O', 0x0e, 0x0f, 0x0e, 'S', 0x0e, 0x0f, 0x0e, 'W',
717
};
718
 
719
 
720
// the center is char 19 (north), we add the current heading in 8th
721
// which would be 22.5 degrees, but float would bloat up the code
722
// and *10 / 225 would take ages... so we take the uncorrect way
723
static const char str_NE[] PROGMEM = "NE";
724
static const char str_E[]  PROGMEM = "E ";
725
static const char str_SE[] PROGMEM = "SE";
726
static const char str_S[]  PROGMEM = "S ";
727
static const char str_SW[] PROGMEM = "SW";
728
static const char str_W[]  PROGMEM = "W ";
729
static const char str_NW[] PROGMEM = "NW";
730
static const char str_N[]  PROGMEM = "N ";
731
 
732
const char * const directions_p[] PROGMEM=
733
{
734
    str_NE,
735
    str_E,
736
    str_SE,
737
    str_S,
738
    str_SW,
739
    str_W,
740
    str_NW,
741
    str_N
742
};
743
 
744
 
745
//###########################################################
746
//# OSD Screen Controler
747
//###########################################################
748
 
749
#define SCREENCTRL_MAX  15  // Anzahl max. zu verwaltender Screens
750
 
751
//---------------------------
752
// typedef: einzelner Screen
753
//---------------------------
754
typedef struct
755
{
756
    const char *screenname;
757
    void (*screen)(void);
758
}  screen_t;
759
 
760
 
761
//---------------------------
762
// typedef: Screenliste
763
//---------------------------
764
typedef struct
765
{
766
    uint8_t     active;
767
    uint8_t     count;
768
    screen_t    screen[SCREENCTRL_MAX];
769
}  screenlist_t;
770
 
771
screenlist_t osdscreens;
772
 
773
 
774
//--------------------------------------------------------------
775
// ScreenCtrl_Init()
776
//
777
// initialisiert die Screenliste - muss vor dem ersten
778
// ScreenCtrl_Push() aufgerufen werden
779
//--------------------------------------------------------------
780
void ScreenCtrl_Init( void )
781
{
782
    osdscreens.active = 0;
783
    osdscreens.count  = 0;
784
}
785
 
786
 
787
//--------------------------------------------------------------
788
// ScreenCtrl_Push( *screenname, *screenfunc)
789
//
790
// fuegt einen Screen der Screenliste hinzu (siehe osd())
791
//--------------------------------------------------------------
792
void ScreenCtrl_Push( uint8_t screenid, const char *screenname, void (*screenfunc)(void))
793
{
794
    if( osdscreens.count < SCREENCTRL_MAX )
795
    {
796
        // wenn screenid = 0 dann immer anzeigen (Screen ist nicht vom Benutzer auswaehlbar)
797
        if( (screenid==0) || ((Config.OSD_UseScreen & (1 << screenid)) != 0) )
798
        {
799
            osdscreens.screen[osdscreens.count].screenname = screenname;
800
            osdscreens.screen[osdscreens.count].screen     = screenfunc;
801
            osdscreens.count++;
802
        }
803
    }
804
}
805
 
806
 
807
//--------------------------------------------------------------
808
// ScreenCtrl_Set( screennum)
809
//
810
// aktiviert einen bestimmten Screen aus der Screenliste
811
//--------------------------------------------------------------
812
void ScreenCtrl_Set( uint8_t screennum )
813
{
814
    osdscreens.active = 0;
815
    if( screennum < osdscreens.count )
816
    {
817
        osdscreens.active = screennum;
818
    }
819
}
820
 
821
 
822
//--------------------------------------------------------------
823
// num = ScreenCtrl_GetNum()
824
//
825
// gibt die Nummer des aktuell aktivierten Screens zurueck
826
//--------------------------------------------------------------
827
uint8_t ScreenCtrl_GetNum( void )
828
{
829
    return osdscreens.active;
830
}
831
 
832
 
833
//--------------------------------------------------------------
834
// name = ScreenCtrl_GetName()
835
//
836
// gibt den Namen des aktuell aktivierten Screens zurueck
837
// Rueckgabe ist ein Pointer auf einen String im PROGMEM
838
//--------------------------------------------------------------
839
const char * ScreenCtrl_GetName( void )
840
{
841
    return osdscreens.screen[osdscreens.active].screenname;
842
}
843
 
844
 
845
//--------------------------------------------------------------
846
// ScreenCtrl_Next()
847
//
848
// zum naechsten Screen wechseln
849
//--------------------------------------------------------------
850
void ScreenCtrl_Next( void )
851
{
852
    osdscreens.active++;
853
    if( osdscreens.active >= osdscreens.count )
854
    {
855
        osdscreens.active = 0;
856
    }
857
    OSDScreenRefresh = OSD_SCREEN_REDRAW;
858
}
859
 
860
 
861
//--------------------------------------------------------------
862
// ScreenCtrl_Previous()
863
//
864
// zum vorherigen Screen wechseln
865
//--------------------------------------------------------------
866
void ScreenCtrl_Previous( void )
867
{
868
    if( osdscreens.active == 0 )
869
    {
870
        osdscreens.active = osdscreens.count-1;
871
    }
872
    else
873
    {
874
        osdscreens.active--;
875
    }
876
    OSDScreenRefresh = OSD_SCREEN_REDRAW;
877
}
878
 
879
 
880
//--------------------------------------------------------------
881
// ScreenCtrl_Show()
882
//
883
// ruft den aktuell Screen auf
884
//--------------------------------------------------------------
885
void ScreenCtrl_Show( void )
886
{
887
    osdscreens.screen[osdscreens.active].screen();
888
}
889
 
890
 
891
//###########################################################
892
//###########################################################
893
 
894
//--------------------------------------------------------------
895
//--------------------------------------------------------------
896
void calc_BLmax( osd_BLmax_t *blmax )
897
{
898
    uint8_t i;
899
 
900
    memset( blmax, 0, sizeof(osd_BLmax_t) );
901
 
902
    for( i=0; i<Config.OSD_Statistic.BL_Count; i++)
903
    {
904
        if( Config.OSD_Statistic.BL[i].max_Current > blmax->max_BL_Current )
905
        {
906
            blmax->max_BL_Current        = Config.OSD_Statistic.BL[i].max_Current;
907
            blmax->max_BL_Current_Index = i;
908
        }
909
 
910
        if( Config.OSD_Statistic.BL[i].max_Temp > blmax->max_BL_Temp )
911
        {
912
            blmax->max_BL_Temp    = Config.OSD_Statistic.BL[i].max_Temp;
913
            blmax->max_BL_Temp_Index = i;
914
        }
915
 
916
    }
917
}
918
 
919
 
920
 
921
//--------------------------------------------------------------
922
// STAT_Init()
923
//
924
// initialisiert die Statistic Werte neu
925
//--------------------------------------------------------------
926
void STAT_Init(void)
927
{
928
    // init: statistic
929
    memset( &Config.OSD_Statistic, 0, sizeof(osd_statistic_t) );
930
 
931
    Config.OSD_Statistic.min_UBat       = 255;
932
    Config.OSD_Statistic.min_RCQuality  = 255;
933
    Config.OSD_Statistic.min_AngleNick  = 126;
934
    Config.OSD_Statistic.min_AngleRoll  = 126;
935
}
936
 
937
 
938
 
939
//--------------------------------------------------------------
940
// MKErr_Log_Init()
941
//
942
// initialisiert die MK Errorcodes neu
943
//--------------------------------------------------------------
944
void MKErr_Log_Init(void)
945
{
946
        // init: MK Errorlog
947
        memset( &Config.MKErr_Log, 0, sizeof(mkerror_t)*MAX_MKERR_LOG );
948
 
949
}
950
 
951
 
952
 
953
//--------------------------------------------------------------
954
//--------------------------------------------------------------
955
void MkError_Save( uint8_t Errorcode )
956
{
957
    uint8_t i;
958
 
959
    for( i=MAX_MKERR_LOG-1; i>0; i--)
960
    {
961
        Config.MKErr_Log[i] = Config.MKErr_Log[i-1];
962
    }
963
 
964
    Config.MKErr_Log[0].Errorcode = Errorcode;
965
    memcpy( &Config.MKErr_Log[0].set_Time, (char *)&UTCTime, sizeof(PKTdatetime_t) );       // sichern...
966
}
967
 
968
 
969
 
970
//--------------------------------------------------------------
971
// OSD_MK_Connect()
972
//
973
// Verbindung zum MK herstellen oder ABO-Renew
974
//
975
// modus: MK_CONNECT oder MK_ABORENEW
976
//--------------------------------------------------------------
977
void OSD_MK_Connect( uint8_t modus )
978
{
979
    uint8_t tx_interval;
980
 
981
    if( modus == MK_CONNECT )
982
    {
983
        SwitchToNC();
984
 
985
        // switch off: 3d data => kompatibel mit SmartOSD????
986
        //tx_interval   = 0;
987
        //SendOutData ('c', ADDRESS_ANY, 1, &tx_interval, 1);
988
        //_delay_ms(25);
989
 
990
        tx_interval = 0;
991
        SendOutData( 'd', ADDRESS_ANY, 1, &tx_interval, 1);     // switch off: debug
992
 
993
        timer = 3; while( timer > 0 );                          // short delay
994
    }
995
 
996
    tx_interval = TXINTERVAL_OSDDATA;                           // switch on: sending osd-data
997
    SendOutData( 'o', ADDRESS_NC, 1,  &tx_interval, 1);         //   request: OSD Data from NC every ..ms
998
 
999
    timer = 3; while( timer > 0 );                              // short delay
1000
 
1001
                                                                // switch on: sending bl-data
1002
    tx_interval = TXINTERVAL_BLDATA;                            //   5 => 50 ms (send packet every n*10 ms)
1003
    SendOutData( 'k', ADDRESS_ANY, 1, &tx_interval, 1);         //   request: BL Ctrl Status
1004
 
1005
    mode      = 'O';
1006
    abo_timer = ABO_TIMEOUT;
1007
 
1008
    rxd_buffer_locked = FALSE;
1009
}
1010
 
1011
 
1012
 
1013
//--------------------------------------------------------------
1014
//--------------------------------------------------------------
1015
void OSD_MK_ShowTimeout( void )
1016
{
1017
    if( old_PKTErrorcode != 40 )
1018
    {
1019
        MkError_Save( 40 );                                         // Logge: "PKT RX lost"
1020
        old_PKTErrorcode = 40;
1021
    }
1022
 
1023
    lcd_cls ();
1024
 
1025
    lcd_frect_round( 0, 0, 127,10, 1, R1);                          // Rect: Invers (Titel)
1026
    lcdx_printp_center( 0, strGet(OSD_ERROR), MINVERS, 1,2);        // "FEHLER: Datenverlust!"
1027
 
1028
    lcdx_printp_at(3, 1, strGet(START_LASTPOS) , MNORMAL, 0,6);     // "Letzte Position"
1029
    lcdx_printp_at(3, 2, strGet(START_LASTPOS3), MNORMAL, 0,6);     // "Google Eingabe"
1030
 
1031
    //----
1032
    lcd_frect( 0, (4*7)+5, 127, 7, 1);                              // Rect: Invers
1033
    lcdx_printp_at(1, 3, strGet(START_LASTPOS1), MINVERS, 0,9);     // "Breitengr  Längengr"
1034
 
1035
    writex_gpspos(  1, 4, Config.LastLatitude , MNORMAL,  0,11);    // Anzeige: Breitengrad
1036
    writex_gpspos( 12, 4, Config.LastLongitude, MNORMAL, -1,11);    // Anzeige: Laengengrad
1037
 
1038
    lcd_rect( 0, (3*8)+8, 127, (2*8)+4, 1);                         // Rahmen
1039
 
1040
    lcd_printp_at(12, 7, strGet(ENDE)      , MNORMAL);              // Keyline: "Ende"
1041
 
1042
    set_beep ( 0, 0, BeepOff);                                      // Falls Spannungswarnung an war Beeper aus (ist das notwendig?)
1043
}
1044
 
1045
 
1046
 
1047
/***************************************************************************************************************************************
1048
 
1049
//--------------------------------------------------------------
1050
// OSD_MK_UTCTime()
1051
// Fuer: defined MKVERSION088n || defined MKVERSION090b || defined MKVERSION090e
1052
// -> erstmal keine Unterstuetzung mehr...
1053
//--------------------------------------------------------------
1054
 
1055
//--------------------------------------------------------------
1056
// OSD_MK_UTCTime()
1057
//
1058
// ALTE Funktion fuer FC < 0.90h (und dementsprechend NC < 0.30h)
1059
//
1060
// Setzt die PKT globale UTCTime mithilfe des MK.
1061
//
1062
// Foraussetzung:
1063
// - der NC-Modus muss aktiv sein (SwitchToNC)
1064
// - aktuell nur fuer osd.c
1065
//
1066
// Rueckgabe:
1067
//  true = ok, UTCTime gespeichert
1068
//  false = Zeit/Datum nicht gelesen
1069
//
1070
// Hack:
1071
// Gelesen wird die Seite 3 des NC-Display's. Dort wird Zeit
1072
// und Datum an den entsprechnenden Positionen via Zeichen an-
1073
// gezeigt. Die Zeichen werden ausgelesen und in die interne UTCTime
1074
// gespeichert.
1075
//
1076
// HINWEIS:
1077
// Ab NC > v0.30b (evtl. v0.30c) wird die NC ein neues Datenpaket
1078
// senden ("T") mit strukturierten Informationen zu Datum/Zeit.
1079
// Das wurde von Holger eingebaut.
1080
// Wird spaeter auch im PKT implementiert.
1081
//--------------------------------------------------------------
1082
int OSD_MK_UTCTime( uint8_t readtime )
1083
{
1084
    uint32_t sec;
1085
    uint32_t min;
1086
    uint32_t hour;
1087
    uint16_t year;
1088
    uint8_t  month;
1089
    uint8_t  day;
1090
    uint8_t  page;
1091
    uint8_t  ok = false;
1092
 
1093
 
1094
    mode = 'L';                         // read: MK-Display Page
1095
    page = 3;                           // anfordern von Seite 3 (der NC)
1096
    SendOutData ('l', ADDRESS_ANY, 1, &page, 1);    // request: MK-Display Page 3
1097
 
1098
    rxd_buffer_locked = FALSE;
1099
 
1100
    timer = readtime;                   // fuer max. n*10 millisec versuchen Daten zu lesen
1101
    while( timer>0 && !ok );            // lese Daten-Pakete fuer die angegebene Zeit oder gelesen
1102
    {
1103
        if( rxd_buffer_locked )
1104
        {
1105
            Decode64();
1106
 
1107
            #ifdef USE_OSD_SCREEN_DEBUG
1108
            readCounterTIME++;
1109
            #endif
1110
 
1111
            sec  = (uint32_t)(pRxData[66+7+2] - '0') + 10 * (uint32_t)(pRxData[66+6+2] - '0');          // seconds: sec
1112
            min  = (uint32_t)(pRxData[66+4+2] - '0') + 10 * (uint32_t)(pRxData[66+3+2] - '0');          // seconds: min
1113
            hour = (uint32_t)(pRxData[66+1+2] - '0') + 10 * (uint32_t)(pRxData[66+0+2] - '0');          // seconds: hour
1114
            sec += (min * 60) + (hour * 3600);
1115
 
1116
            year =  (uint16_t)(pRxData[46+9+2] - '0') + 10   * (uint16_t)(pRxData[46+8+2] - '0');       // year
1117
            year += 100 * (uint16_t)(pRxData[46+7+2] - '0') + 1000 * (uint16_t)(pRxData[46+6+2] - '0'); // year
1118
 
1119
            day   = (uint8_t)(pRxData[46+4+2] - '0') + 10 * (uint8_t)(pRxData[46+3+2] - '0');           // day
1120
 
1121
            month = (uint8_t)(pRxData[46+1+2] - '0') + 10 * (uint8_t)(pRxData[46+0+2] - '0');           // month
1122
 
1123
            // in der globalen UTCTime speichern (hoffentlich funkt kein timer dazwischen)
1124
            if( year > 2000 && year < 2200 )        // plausibilitaets check
1125
            {
1126
                ATOMIC_BLOCK(ATOMIC_FORCEON)
1127
                {
1128
                    UTCTime.seconds = sec;
1129
                    UTCTime.day     = day;
1130
                    UTCTime.month   = month;
1131
                    UTCTime.year    = year;
1132
                }
1133
            }
1134
            ok = true;
1135
        }
1136
    }
1137
 
1138
    return ok;              // wenn erfolgreich gelesen dann true (kein timeout)
1139
}
1140
***************************************************************************************************************************************/
1141
 
1142
 
1143
 
1144
//--------------------------------------------------------------
1145
// OSD_MK_UTCTime()
1146
//
1147
// NEUE Ermittlung der Zeit vom MK
1148
// ab NC v0.30g (bzw. NC 0.30h fuer FC 0.90h)
1149
//
1150
// TODO OG: auf neue MKVersion bzgl. Versionsprüfung anpassen!
1151
//--------------------------------------------------------------
1152
int OSD_MK_UTCTime( uint8_t readtime )
1153
{
1154
    DateTime_t  *rx_DateTime;
1155
    uint8_t     tx_interval;
1156
    uint8_t     ok = false;
1157
 
1158
    mode = 'T';                                         // read: MK-Display Page
1159
    tx_interval = 1;                                    //
1160
    SendOutData ('t', ADDRESS_NC, 1, &tx_interval, 1);  // request: DateTime
1161
 
1162
    rxd_buffer_locked = FALSE;
1163
 
1164
    timer = readtime;                                   // fuer max. n*10 millisec versuchen Daten zu lesen
1165
    while( timer>0 && !ok );                            // lese Daten-Pakete fuer die angegebene Zeit oder gelesen
1166
    {
1167
        if( rxd_buffer_locked )
1168
        {
1169
            Decode64();
1170
            rx_DateTime = (DateTime_t *) (pRxData);
1171
 
1172
            #ifdef USE_OSD_SCREEN_DEBUG
1173
            readCounterTIME++;
1174
            #endif
1175
 
1176
            if( rx_DateTime->Year > 2000 && rx_DateTime->Year < 2200 )      // Plausibilitaets Check
1177
            {
1178
                ATOMIC_BLOCK(ATOMIC_FORCEON)
1179
                {
1180
                    UTCTime.seconds = ((uint32_t)(rx_DateTime->Hour))*3600 + ((uint32_t)(rx_DateTime->Min))*60 + (uint32_t)(rx_DateTime->Sec);
1181
                    UTCTime.day     = rx_DateTime->Day;
1182
                    UTCTime.month   = rx_DateTime->Month;
1183
                    UTCTime.year    = rx_DateTime->Year;
1184
                }
1185
            }
1186
 
1187
            ok = true;
1188
        }
1189
    }
1190
 
1191
    return ok;              // wenn erfolgreich gelesen dann true (kein timeout)
1192
}
1193
 
1194
 
1195
 
1196
//--------------------------------------------------------------
1197
//--------------------------------------------------------------
1198
int32_t calc_avg( int32_t avg, int32_t nvalue, int32_t count, int32_t factor)
1199
{
1200
    avg = avg + (( ( nvalue * factor) - avg) / count);
1201
    return avg;
1202
}
1203
 
1204
 
1205
 
1206
//--------------------------------------------------------------
1207
// OSD_MK_GetData()
1208
//
1209
// Holt Daten der BL-Ctrl via NC.
1210
//
1211
// Die Werte der BL's 1-12 kommen in mehr oder weniger beliebiger
1212
// Reihenfolge an. Die Daten fuer vorhandene BL's werden oefter
1213
// gesendet als die von nicht vorhandenen BL's.
1214
//
1215
// Diese Funktioen liest fuer die Zeit BL_READ_TIME die BL-Daten
1216
// vom MK ein und ordnet diese der PKT-internen Speichstruktur zu.
1217
//
1218
// Hierbei ist nicht gewaehrleistet, dass die Daten von jedem BL
1219
// in einem festen Zeitrahmen ermittelt werden. Die Folge ist
1220
// ein 'zufaelliger' Aufbau der Anzeige der BL-Daten und auch
1221
// eine nicht exakt bestimmbare Refreshtime der Werte.
1222
//
1223
// Optimieren kann man ggf. die Refreshzeit aller BL-Werte durch
1224
// tx_intervall fuer Kommando "k" und durch BL_READ_TIME.
1225
// Brauchbare Startwerte sind (noch experimentell):
1226
//   tx_interval  = 5 (fuer "k")    =  50 ms
1227
//   BL_READ_TIME = 25              = 250 ms
1228
//
1229
// Wenn dieses Verhalten verbessert werden soll muss ggf.
1230
// die ISR() (usart.c) fuer Kommando "k" angepasst werden um
1231
// in einem Schwung mehrere gesendete BL-Pakete aufeinmal
1232
// aufzunehmen und als Paket zur Verfuegung zu stellen.
1233
//--------------------------------------------------------------
1234
void OSD_MK_GetData( void )
1235
{
1236
    BLData_t    *rx_blData;
1237
    uint8_t     blIndex;
1238
    uint8_t     FCStatusFlags;
1239
    uint8_t     v;
1240
    uint8_t     skipBL = false;
1241
 
1242
    FCStatusFlags = naviData->FCStatusFlags;                // save naviData->FCStatusFlags for use with BL-Data
1243
 
1244
 
1245
    //######################################
1246
    //# ZEIT/DATUM
1247
    //######################################
1248
    // lese UTC-Time vom MK
1249
    //--------------------------------------
1250
    if( timer_get_tidata == 0 )
1251
    {
1252
        //--------------------------------------------------
1253
        // das 'T' Datenpaket der NC fuer OSD_MK_UTCTime()
1254
        // gibt es erst ab NC v0.30g (!)
1255
        //
1256
        // --> Versionspruefung der NC-Firmware
1257
        //--------------------------------------------------
1258
 
1259
        v = MKVersion_Cmp( MKVersion.NCVer,  0,30,'g' );        // pruefe auf NC-Version >= "0.30g"
1260
 
1261
        if( v && (v >= GIVEN_VERSION) )                         // wenn aktuelle NC-Version >= "0.30g"...
1262
        {
1263
            if( !OSD_MK_UTCTime(20) )
1264
                timer_get_tidata = 50;                          // erfolglos: versuche es nach einer 1/2 Sekunde erneut
1265
            else
1266
                timer_get_tidata = TIME_GET_TIDATA;             // alle 60 Sekunden refresh - den Rest uebernimmt ein Timer des PKT
1267
        }
1268
    }
1269
 
1270
 
1271
 
1272
    //######################################
1273
    //# MK-DISPLAY
1274
    //######################################
1275
    // switch to: (h)
1276
    //--------------------------------------
1277
    //if( timer_get_displaydata == 0 )
1278
    if( mkdisplayMode && timer_get_displaydata == 0 )
1279
    {
1280
        mode              = 'H';
1281
        rxd_buffer_locked = FALSE;
1282
 
1283
/*
1284
        if( mkdisplayCmd != 0xff )
1285
        {
1286
            if( mkdisplayCmd == 0 ) mkdisplayCmd = 0xff;
1287
            SendOutData( 'h', ADDRESS_ANY, 1, &mkdisplayCmd, 1);
1288
        }
1289
*/
1290
        if( mkdisplayCmd == 0 ) mkdisplayCmd = 0xff;
1291
 
1292
        SendOutData( 'h', ADDRESS_ANY, 2, &mkdisplayCmd, 1, 0x00 ,1); // 05.04.2015 Cebra, 2.er Parameter wg NC 2.09i
1293
 
1294
        mkdisplayCmd = 0xff;        // 0xff = aktuelle Seite
1295
 
1296
        timer = 20; while( (timer>0) && !rxd_buffer_locked );                               //
1297
 
1298
        if( rxd_buffer_locked )
1299
        {
1300
            Decode64();
1301
            memcpy( mkdisplayData, (const void *)&rxd_buffer[3+ 0], 80 );       // sichern...
1302
 
1303
            #ifdef USE_OSD_SCREEN_DEBUG
1304
                readCounterDISPLAY++;
1305
            #endif  // USE_OSD_SCREEN_DEBUG
1306
        }
1307
 
1308
        timer_get_displaydata = TIME_GET_DISPLAYDATA;                 // n*10 ms
1309
        skipBL                = true;
1310
    }  // end: if( mkdisplayMode && timer_get_displaydata == 0 )
1311
 
1312
 
1313
 
1314
    //######################################
1315
    //# BL-Daten
1316
    //######################################
1317
    // switch to: 'BL Ctrl Status' (k)
1318
    //--------------------------------------
1319
    if( !skipBL && timer_get_bldata == 0 )
1320
    {
1321
        mode        = 'K';                                  // read: BL Ctrl Status
1322
        rxd_buffer_locked = FALSE;
1323
 
1324
        timer = TIME_READ_BLDATA;                           // fuer x Zeit werden BL-Daten gelesen
1325
        while( timer>0 )                                    // lese Daten-Pakete fuer die angegebene Zeit
1326
        {
1327
            if( rxd_buffer_locked )
1328
            {
1329
                Decode64 ();
1330
                rx_blData = (BLData_t *) (pRxData);
1331
 
1332
                // die BL-Daten kommen in beliebiger Reihenfolge an
1333
                // Hier werden sie entsprechend ihres Index gesichert
1334
                blIndex = rx_blData->Index;
1335
                if( blIndex >= 0 && blIndex < OSD_MAX_MOTORS )
1336
                {
1337
                    memcpy( &blData[blIndex], rx_blData, sizeof(BLData_t));  // sichern...
1338
 
1339
                    #ifdef USE_OSD_SCREEN_DEBUG
1340
                        readCounterBL[blIndex]++;
1341
                    #endif  // USE_OSD_SCREEN_DEBUG
1342
 
1343
                    // Statistiken
1344
                    if( (blData[blIndex].Status & 0xf0) && (FCStatusFlags & FC_STATUS_MOTOR_RUN) )  // nur wenn BL/Motor vorhanden und Motoren laufen
1345
                    {
1346
                        // BL Statistik: Anzahl empf. Datenpakete (fuer Mittelwert)
1347
                        Config.OSD_Statistic.BL[blIndex].count++;
1348
 
1349
                        // int32_t calc_avg( int32_t avg, int32_t value, int32_t count, int32_t factor)
1350
                        Config.OSD_Statistic.BL[blIndex].avg_Current = (uint16_t) calc_avg( (int32_t)Config.OSD_Statistic.BL[blIndex].avg_Current,
1351
                                                                                            (int32_t)blData[blIndex].Current,
1352
                                                                                            (int32_t)Config.OSD_Statistic.BL[blIndex].count,
1353
                                                                                            100);
1354
 
1355
                        // ALT
1356
                        // BL Statistik: Mittelwert: Strom (*100 um Rundungsfehler zu reduzieren)
1357
                        //avg = (int32_t)Config.OSD_Statistic.BL[blIndex].avg_Current;
1358
                        //avg = avg + (( ( (int32_t)blData[blIndex].Current * 100) - avg) / (int32_t)Config.OSD_Statistic.BL[blIndex].count);
1359
                        //Config.OSD_Statistic.BL[blIndex].avg_Current = (uint16_t)avg;
1360
 
1361
                        // BL Statistik:  Max: Strom
1362
                        if( blData[blIndex].Current     > Config.OSD_Statistic.BL[blIndex].max_Current) Config.OSD_Statistic.BL[blIndex].max_Current = blData[blIndex].Current;
1363
 
1364
                        // BL Statistik:  Max: Temperatur
1365
                        if( blData[blIndex].Temperature > Config.OSD_Statistic.BL[blIndex].max_Temp)    Config.OSD_Statistic.BL[blIndex].max_Temp    = blData[blIndex].Temperature;
1366
                        if( blIndex+1                   > Config.OSD_Statistic.BL_Count )               Config.OSD_Statistic.BL_Count                = blIndex+1;
1367
                    }
1368
                }
1369
                rxd_buffer_locked = FALSE;
1370
            }
1371
        }
1372
        timer_get_bldata = TIME_GET_BLDATA;                 // n*10 ms
1373
    }  // end: if( timer_get_bldata == 0 )
1374
 
1375
 
1376
 
1377
    //--------------------------------------
1378
    // back to: OSD-Data
1379
    //--------------------------------------
1380
    mode                = 'O';                          // read: OSD-Data
1381
    rxd_buffer_locked   = FALSE;                        // ready to receive new data
1382
    timer_mk_timeout    = MK_TIMEOUT;                   // reset osd MK_TIMEOUT timer
1383
}
1384
 
1385
 
1386
 
1387
//--------------------------------------------------------------
1388
//--------------------------------------------------------------
1389
void variobeep(int16_t vario)
1390
{
1391
#ifdef USE_SOUND
1392
  { //start Beep
1393
 
1394
    if (vario >0 )          // MK steigt
1395
      {
1396
       Vario_Beep_Down = 0;                 // Down Beep freischalten
1397
       Vario_Threshold++;
1398
 
1399
       if ((Vario_Beep_Up == 0) && (Vario_Threshold >= Vario_Threshold_Value))
1400
        {
1401
//         set_beep ( 100, 0xffff, BeepNormal);
1402
         duration = 52 -vario;
1403
//         if (duration =0); duration = 1;
1404
 
1405
//         write_ndigit_number_u (0,6,duration,5,0);
1406
 
1407
         playTone(300+vario*2,duration,Config.Volume);
1408
 
1409
//         playTone(300,duration,volume);
1410
         Vario_Threshold = Vario_Threshold_Value;     // auf Maximalwert begrenzen
1411
        }
1412
       Vario_Beep_Up++;                 // Interval hochzählen in dem nicht gepiept wird
1413
       if (Vario_Beep_Up == Vario_Beep_Up_Interval) Vario_Beep_Up = 0;
1414
      }
1415
 
1416
    if (vario <0)          // MK fällt
1417
      {
1418
       Vario_Beep_Up = 0;                 // Up Beep freischalten
1419
       Vario_Threshold++;
1420
       if ((Vario_Beep_Down == 0) && (Vario_Threshold >= Vario_Threshold_Value))
1421
        {
1422
         duration = 50 -vario;
1423
//         write_ndigit_number_u (0,7,duration,5,0);
1424
//         if (duration < vario) ; duration = 0;
1425
//         playTone(300,50,volume);
1426
 
1427
 
1428
         playTone(300+vario*2,duration,Config.Volume);
1429
 
1430
         Vario_Threshold = Vario_Threshold_Value;     // auf Maximalwert begrenzen
1431
        }
1432
       Vario_Beep_Down++;                 // Interval hochzählen in dem nicht gepiept wird
1433
       if (Vario_Beep_Down == Vario_Beep_Down_Interval) Vario_Beep_Down = 0;
1434
      }
1435
 
1436
    if (vario == 0) Vario_Threshold = 0;  //Startverzögerung löschen
1437
  }  // end Beep
1438
#endif
1439
}
1440
 
1441
 
1442
//--------------------------------------------------------------
1443
// Diese Funktion Beept unabhaengig von der Einstellung Config.OSD_VarioBeep
1444
// Aufruf ggf. mit: if( Config.OSD_VarioBeep ) Beep_Vario();
1445
//
1446
// Ansonten:
1447
// -> hier noch aufräumen in Zusammenhang mit func variobeep()
1448
//--------------------------------------------------------------
1449
void Beep_Vario(void)
1450
{
1451
    if ( (naviData->FCStatusFlags & FC_STATUS_MOTOR_RUN) && (naviData->FCStatusFlags2 & FC_STATUS2_ALTITUDE_CONTROL))
1452
    { //start Beep
1453
      if (naviData->Variometer <0)          // MK fällt
1454
        {
1455
         Vario_Beep_Up = 0;                 // Up Beep freischalten
1456
         Vario_Threshold++;
1457
         if ((Vario_Beep_Down == 0) && (Vario_Threshold >= Vario_Threshold_Value))
1458
          {
1459
 
1460
          if (!Config.HWSound) set_beep ( 300, 0xffff, BeepNormal);
1461
               else  variobeep(naviData->Variometer);
1462
 
1463
           Vario_Threshold = Vario_Threshold_Value;     // auf Maximalwert begrenzen
1464
          }
1465
         Vario_Beep_Down++;                 // Interval hochzählen in dem nicht gepiept wird
1466
         if (Vario_Beep_Down == Vario_Beep_Down_Interval) Vario_Beep_Down = 0;
1467
        }
1468
 
1469
      if (naviData->Variometer == 0) Vario_Threshold = 0;  //Startverzögerung löschen
1470
 
1471
      if (naviData->Variometer >0 )          // MK steigt
1472
        {
1473
         Vario_Beep_Down = 0;                 // Down Beep freischalten
1474
         Vario_Threshold++;
1475
 
1476
         if ((Vario_Beep_Up == 0) && (Vario_Threshold >= Vario_Threshold_Value))
1477
          {
1478
           if (!Config.HWSound) set_beep ( 100, 0xffff, BeepNormal);
1479
           else  variobeep(naviData->Variometer);
1480
           Vario_Threshold = Vario_Threshold_Value;     // auf Maximalwert begrenzen
1481
          }
1482
         Vario_Beep_Up++;                 // Interval hochzählen in dem nicht gepiept wird
1483
         if (Vario_Beep_Up == Vario_Beep_Up_Interval) Vario_Beep_Up = 0;
1484
        }
1485
    }  // end Beep
1486
}
1487
 
1488
 
1489
 
1490
//--------------------------------------------------------------
1491
// Quelle Mikrokopter FC-Software Holger + Ingo
1492
//--------------------------------------------------------------
1493
void CheckMKLipo( void )
1494
{
1495
    if( Config.MK_LowBat < 50 )     // automatische Zellenerkennung
1496
    {
1497
       if( CellIsChecked <= 2 )     // nur beim Start 1x prüfen
1498
       {
1499
            // up to 6s LiPo, less than 2s is technical impossible
1500
            for( cells = 2; cells < 7; cells++)
1501
            {
1502
                if( naviData->UBat < cells * MAX_CELL_VOLTAGE)
1503
                    break;
1504
            }
1505
            BattLowVoltageWarning = cells * Config.MK_LowBat;
1506
            CellIsChecked++;
1507
       }
1508
    }
1509
    else BattLowVoltageWarning = Config.MK_LowBat;
1510
 
1511
    if( naviData->UBat < BattLowVoltageWarning)
1512
    {
1513
        if( AkkuWarnThreshold <= 4)
1514
        {
1515
            AkkuWarnThreshold++;
1516
        }
1517
        else if( naviData->FCStatusFlags & FC_STATUS_MOTOR_RUN )
1518
        {
1519
            // MK-Unterspannungs-Beep nur wenn Motoren laufen
1520
            set_beep ( 1000, 0x0020, BeepSevere);
1521
        }
1522
    }
1523
}
1524
 
1525
 
1526
//--------------------------------------------------------------
1527
//--------------------------------------------------------------
1528
void calc_heading_home(void)
1529
{
1530
    int16_t degree;
1531
 
1532
    //---------------------------------------
1533
    // warum modulo 360:
1534
    //
1535
    // die NC kann unter gewissen Umstaenden Winkel > 360 Grad
1536
    // senden -> fragt H&I warum
1537
    //---------------------------------------
1538
    degree = ((naviData->CompassHeading % 360) - (naviData->HomePositionDeviation.Bearing % 360));
1539
 
1540
    if( degree < 0 )
1541
        heading_home = (int16_t)(360 + degree);
1542
    else
1543
        heading_home = (int16_t)degree;
1544
}
1545
 
1546
 
1547
//--------------------------------------------------------------
1548
// convert the <heading> gotton from NC into an index
1549
uint8_t heading_conv (uint16_t heading)
1550
{
1551
    if (heading > 23 && heading < 68)
1552
        return 0;       //direction = "NE";
1553
    else if (heading > 67 && heading < 113)
1554
        return 1;       //direction = "E ";
1555
    else if (heading > 112 && heading < 158)
1556
        return 2;       //direction = "SE";
1557
    else if (heading > 157 && heading < 203)
1558
        return 3;       //direction = "S ";
1559
    else if (heading > 202 && heading < 248)
1560
        return 4;       //direction = "SW";
1561
    else if (heading > 247 && heading < 293)
1562
        return 5;       //direction = "W ";
1563
    else if (heading > 292 && heading < 338)
1564
        return 6;       //direction = "NW";
1565
 
1566
    return 7;   //direction = "N ";
1567
}
1568
 
1569
 
1570
//--------------------------------------------------------------
1571
// draw a compass rose at <x>/<y> for <heading>
1572
void draw_compass (uint8_t x, uint8_t y, uint16_t heading, int8_t xoffs, int8_t yoffs)
1573
{
1574
 
1575
    uint8_t front = 19 + (heading / 22);
1576
    for (uint8_t i = 0; i < 9; i++)
1577
        lcdx_putc (x++, y, pgm_read_byte(&rose[front - 4 + i]), MNORMAL, xoffs,yoffs);
1578
}
1579
 
1580
 
1581
//--------------------------------------------------------------
1582
// variometer
1583
// x, y in Pixel!
1584
//--------------------------------------------------------------
1585
void draw_variometer (uint8_t x, uint8_t y, uint8_t width, uint8_t hight, int16_t variometer)
1586
{
1587
    lcd_rect (x, y - ((hight) / 2), width, hight, 1);
1588
    lcd_frect (x + 1, y - ((hight) / 2) + 1, width - 2, hight - 2, 0);
1589
    lcd_line (x, y, x + width, y, 1);
1590
 
1591
    if (variometer > 0)  // steigend
1592
    {
1593
        switch (variometer / 5)
1594
        {
1595
            case 0:
1596
                lcd_line  (x + 4, y - 1, x + 6, y - 1, 1);  //  1 >  4
1597
            break;
1598
 
1599
            case 1:
1600
                lcd_line  (x + 4, y - 1, x + 6, y - 1, 1);  //  1 >  4
1601
                lcd_frect (x + 3, y - 3, 4, 1, 1);          //  5 >  9
1602
            break;
1603
 
1604
            case 2:
1605
                lcd_line  (x + 4, y - 1, x + 6, y - 1, 1);  //  1 >  4
1606
                lcd_frect (x + 3, y - 3, 4, 1, 1);          //  5 >  9
1607
                lcd_frect (x + 2, y - 5, 6, 1, 1);          // 10 > 14
1608
            break;
1609
 
1610
            default:
1611
                lcd_line  (x + 4, y - 1, x + 6, y - 1, 1);  //  1 >  4
1612
                lcd_frect (x + 3, y - 3, 4, 1, 1);          //  5 >  9
1613
                lcd_frect (x + 2, y - 5, 6, 1, 1);          // 10 > 14
1614
                lcd_frect (x + 1, y - 6, 8, 1, 1);          // 15 >
1615
            break;
1616
        }
1617
    }
1618
    else if (variometer < 0)  // fallend
1619
    {
1620
        switch ((variometer) / -5)
1621
        {
1622
            case 0:
1623
                lcd_line  (x + 4, y + 1, x + 6, y + 1, 1);  // - 1 > - 4
1624
            break;
1625
 
1626
            case 1:
1627
                lcd_line  (x + 4, y + 1, x + 6, y + 1, 1);  // - 1 > - 4
1628
                lcd_frect (x + 3, y + 2, 4, 1, 1);          // - 5 > - 9
1629
            break;
1630
 
1631
            case 2:
1632
                lcd_line  (x + 4, y + 1, x + 6, y + 1, 1);  // - 1 > - 4
1633
                lcd_frect (x + 3, y + 2, 4, 1, 1);          // - 5 > - 9
1634
                lcd_frect (x + 2, y + 4, 6, 1, 1);          // -10 > -14
1635
            break;
1636
 
1637
            default:
1638
                lcd_line  (x + 4, y + 1, x + 6, y + 1, 1);  // - 1 > - 4
1639
                lcd_frect (x + 3, y + 2, 4, 1, 1);          // - 5 > - 9
1640
                lcd_frect (x + 2, y + 4, 6, 1, 1);          // -10 > -14
1641
                lcd_frect (x + 1, y + 5, 8, 1, 1);          // -15 >
1642
            break;
1643
        }
1644
    }
1645
}
1646
 
1647
 
1648
//--------------------------------------------------------------
1649
// variometer 2
1650
//
1651
// x, y in Pixel
1652
// x, y top, left
1653
//--------------------------------------------------------------
1654
/*
1655
void draw_variometer2( uint8_t x, uint8_t y, uint8_t width, uint8_t hight, int16_t variometer)
1656
{
1657
    uint8_t max = 5;    // max: 5 m/sec == 100%
1658
 
1659
    lcd_rect (x, y, width, hight, 1);
1660
    lcd_frect(x + 1, y + 1, width - 2, hight - 2, 0);
1661
    lcd_line (x, y + ((hight) / 2), x + width, y + ((hight) / 2), 1);
1662
 
1663
}
1664
*/
1665
 
1666
 
1667
//--------------------------------------------------------------
1668
// Home symbol
1669
// draw Homesymbol at <x>/<y>
1670
//--------------------------------------------------------------
1671
void draw_homesymbol (uint8_t x, uint8_t y)
1672
{
1673
        x *= 6;
1674
        y *= 8;
1675
        y += 7;
1676
 
1677
        lcd_plot (x,y-4,1);
1678
        lcd_line (x+1,y-1,x+1,y-5,1);
1679
        lcd_plot (x+2,y-6,1);
1680
        lcd_plot (x+3,y-7,1);
1681
        lcd_plot (x+4,y-6,1);
1682
        lcd_line (x+5,y-1,x+5,y-5,1);
1683
        lcd_plot (x+6,y-4,1);
1684
        lcd_plot (x+3,y-1,1);
1685
        lcd_plot (x+3,y-2,1);
1686
        lcd_line (x+1,y,x+5,y,1);
1687
 
1688
}
1689
 
1690
 
1691
//--------------------------------------------------------------
1692
// Target symbol
1693
// draw Targetsymbol at <x>/<y>
1694
//--------------------------------------------------------------
1695
void draw_targetsymbol (uint8_t x, uint8_t y)
1696
{
1697
        x *= 6;
1698
        y *= 8;
1699
        y += 7;
1700
 
1701
        lcd_circle (x+3, y-3, 4, 1);
1702
        lcd_line (x,y-3,x+6,y-3,1);
1703
        lcd_line (x+3,y,x+3,y-6,1);
1704
        lcd_circle (x+3, y-3, 2, 1);
1705
}
1706
 
1707
 
1708
//-----------------------------------------------------------
1709
//-----------------------------------------------------------
1710
void writex_altimeter( uint8_t x, uint8_t y, s32 Altimeter, uint8_t mode, int8_t xoffs, int8_t yoffs )
1711
{
1712
    if (Altimeter > (300 / AltimeterAdjust) || Altimeter < (-300 / AltimeterAdjust))    // above 10m only write full meters
1713
        writex_ndigit_number_s ( x, y, (Altimeter / (30 / AltimeterAdjust)), 4, 0, mode, xoffs,yoffs);
1714
    else                                                                                                    // up to 10m write meters.dm
1715
        writex_ndigit_number_s_10th( x, y, (Altimeter / (3 / AltimeterAdjust)), 3, 0, mode, xoffs,yoffs);
1716
}
1717
 
1718
 
1719
 
1720
//-----------------------------------------------------------
1721
//--------------------------------------------------------------
1722
void lcd_o_circle (uint16_t x, uint16_t y, int16_t breite, uint8_t mode, int8_t xoffs, int8_t yoffs)
1723
{
1724
    breite *= 6;
1725
    int16_t radius = breite / 2;
1726
    x += 2;
1727
    x *= 6;
1728
    x += 2;
1729
    y += 1;
1730
    y *= 8;
1731
    y += 3;
1732
 
1733
    // 04.03.2012 OG: chg: x-radius von -3 auf -2 (runder auf dem display)
1734
    //lcd_ellipse (x, y, radius - 3, radius - 5, mode);
1735
    lcd_ellipse( x+xoffs, y+yoffs, radius - 2, radius - 5, mode);
1736
}
1737
 
1738
 
1739
//-----------------------------------------------------------
1740
// lcd_o_circ_line( x, y, breite, deg, rOffset, mode)
1741
//
1742
// x, y   : in Chars
1743
// breite : in Chars
1744
// deg    : in Pixel
1745
// rOffset: Beeinflusst den Schluss der Linie zum Huellkreis
1746
//          0 = Standard
1747
//          >0 naeher zum Huellkreis
1748
//          <0 entfernter vom Huellkreis
1749
// mode   : siehe: lcd_ellipse_line()
1750
//-----------------------------------------------------------
1751
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)
1752
{
1753
    breite *= 6;
1754
    int16_t radius = breite / 3;
1755
    x += 2;
1756
    x *= 6;
1757
    x += 2;
1758
    y += 1;
1759
    y *= 8;
1760
    y += 3;
1761
 
1762
    // 04.03.2013 OG: der Radius kann mit rOffset >0 vergroessert werden um zum Kreis aufzuschliessen
1763
    lcd_ellipse_line( x+xoffs, y+yoffs, radius+rOffset, radius+rOffset, deg, mode);
1764
}
1765
 
1766
 
1767
 
1768
 
1769
 
1770
 
1771
 
1772
 
1773
 
1774
 
1775
 
1776
//-----------------------------------------------------------
1777
//--------------------------------------------------------------
1778
void lcdx_o_circle( uint8_t x, uint8_t y, int8_t width, uint8_t mode)
1779
{
1780
    int8_t radius = width / 2;
1781
 
1782
    // 04.03.2012 OG: chg: x-radius von -3 auf -2 (runder auf dem display)
1783
    //lcd_ellipse (x, y, radius - 3, radius - 5, mode);
1784
    lcd_ellipse( x, y, radius - 2, radius - 5, mode);
1785
}
1786
 
1787
 
1788
 
1789
//-----------------------------------------------------------
1790
// lcd_o_circ_line( x, y, breite, deg, rOffset, mode)
1791
//
1792
// x, y   : in Chars
1793
// breite : in Chars
1794
// deg    : in Pixel
1795
// rOffset: Beeinflusst den Schluss der Linie zum Huellkreis
1796
//          0 = Standard
1797
//          >0 naeher zum Huellkreis
1798
//          <0 entfernter vom Huellkreis
1799
// mode   : siehe: lcd_ellipse_line()
1800
//-----------------------------------------------------------
1801
void lcdx_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)
1802
{
1803
    breite *= 6;
1804
    int16_t radius = breite / 3;
1805
    x += 2;
1806
    x *= 6;
1807
    x += 2;
1808
    y += 1;
1809
    y *= 8;
1810
    y += 3;
1811
 
1812
    // 04.03.2013 OG: der Radius kann mit rOffset >0 vergroessert werden um zum Kreis aufzuschliessen
1813
    lcd_ellipse_line( x+xoffs, y+yoffs, radius+rOffset, radius+rOffset, deg, mode);
1814
}
1815
 
1816
 
1817
 
1818
//--------------------------------------------------------------
1819
// PARAMETER:
1820
//   x,y : in Pixel
1821
//--------------------------------------------------------------
1822
void draw_icon_mk( uint8_t x, uint8_t y)
1823
{
1824
  //lcd_plot( x+0, y+0, 1);             // Referenz 0,0
1825
 
1826
    lcd_line( x+5, y+0, x+0, y+5, 1);   // Dach oben Links
1827
    lcd_line( x+5, y+0, x+10, y+5, 1);  // Dach oben Rechts
1828
 
1829
    lcd_line( x+5, y+10, x+0, y+5, 1);  // Dach unten Links
1830
    lcd_line( x+5, y+10, x+10, y+5, 1); // Dach unten Rechts
1831
 
1832
    lcd_line( x+4, y+5, x+6, y+5, 1);   // Innenkreuz Horizontal
1833
    lcd_line( x+5, y+4, x+5, y+6, 1);   // Innenkreuz Vertikal
1834
}
1835
 
1836
 
1837
 
1838
//--------------------------------------------------------------
1839
// Variante: rund
1840
//
1841
// PARAMETER:
1842
//   x,y : in Pixel
1843
//--------------------------------------------------------------
1844
void draw_icon_target_round( uint8_t x, uint8_t y)
1845
{
1846
  //lcd_plot( x+0, y+0, 1);             // Referenz 0,0
1847
 
1848
    lcd_ellipse( x+5, y+5, 5+1, 5, 1);  // Aussenkreis
1849
 
1850
  //lcd_line( x+2, y+5, x+8, y+5, 1);   // Innenkreuz Horizontal (laenger)
1851
    lcd_line( x+3, y+5, x+7, y+5, 1);   // Innenkreuz Horizontal (kuerzer)
1852
 
1853
    lcd_line( x+5, y+3, x+5, y+7, 1);   // Innenkreuz Vertikal
1854
}
1855
 
1856
 
1857
 
1858
//--------------------------------------------------------------
1859
// Variante: eckig
1860
//
1861
// PARAMETER:
1862
//   x,y : in Pixel
1863
//--------------------------------------------------------------
1864
void draw_icon_target_diamond( uint8_t x, uint8_t y)
1865
{
1866
  //lcd_plot( x+0, y+0, 1);             // Referenz 0,0
1867
 
1868
    lcd_line( x+5, y+0, x+0, y+5, 1);   // Dach oben Links
1869
    lcd_line( x+5, y+0, x+10, y+5, 1);  // Dach oben Rechts
1870
 
1871
    lcd_line( x+5, y+10, x+0, y+5, 1);  // Dach unten Links
1872
    lcd_line( x+5, y+10, x+10, y+5, 1); // Dach unten Rechts
1873
 
1874
    lcd_line( x+4, y+5, x+6, y+5, 1);   // Innenkreuz Horizontal
1875
    lcd_line( x+5, y+4, x+5, y+6, 1);   // Innenkreuz Vertikal
1876
}
1877
 
1878
 
1879
 
1880
//--------------------------------------------------------------
1881
// PARAMETER:
1882
//   x,y : in Pixel
1883
//--------------------------------------------------------------
1884
void draw_icon_home( uint8_t x, uint8_t y)
1885
{
1886
    //lcd_plot( x+0, y+0, 1);           // Referenz 0,0
1887
    lcd_rect( x+0, y+5, 10, 8, 1);      // Mitte
1888
    lcd_line( x+5, y+0, x+0, y+5, 1);   // Dach Links
1889
    lcd_line( x+5, y+0, x+10, y+5, 1);  // Dach Rechts
1890
    lcd_rect( x+4, y+10, 2, 3, 1);      // Tuere
1891
 
1892
}
1893
 
1894
 
1895
 
1896
//--------------------------------------------------------------
1897
// PARAMETER:
1898
//   x,y : in Pixel
1899
//--------------------------------------------------------------
1900
void draw_icon_sat( uint8_t x, uint8_t y)
1901
{
1902
    //lcd_plot( x+0, y+0, 1);            // Referenz 0,0
1903
    lcd_rect( x+0, y+2, 4, 2, 1);        // linker Fluegel
1904
    lcd_rect( x+8, y+2, 4, 2, 1);        // rechter Fluegel
1905
    lcd_rect( x+4, y+0, 4, 6, 1);        // Mitte, oben
1906
    lcd_line( x+6, y+7, x+2, y+11, 1);   // Strahl Links
1907
    lcd_line( x+6, y+7, x+10, y+11, 1);  // Strahl Rechts
1908
    lcd_line( x+1, y+12, x+11, y+12, 1); // Strahl Unten
1909
}
1910
 
1911
 
1912
 
1913
//--------------------------------------------------------------
1914
// PARAMETER:
1915
//   x,y : in Pixel
1916
//--------------------------------------------------------------
1917
void draw_icon_satmini( uint8_t x, uint8_t y)
1918
{
1919
    //lcd_plot( x+0, y+0, 1);            // Referenz 0,0
1920
 
1921
    //lcd_line( x+3, y+3, x+0, y+6, 1);   // Strahl Links
1922
 
1923
    lcd_line( x+2, y+0, x+4, y+0, 1);   //
1924
    lcd_line( x+0, y+1, x+6, y+1, 1);   //
1925
    lcd_line( x+2, y+2, x+4, y+2, 1);   //
1926
    lcd_plot( x+3, y+1, 0);             //
1927
 
1928
    lcd_line( x+3, y+3, x+1, y+5, 1);   // Strahl Links
1929
    lcd_line( x+3, y+3, x+5, y+5, 1);   // Strahl Rechts
1930
    lcd_line( x+0, y+6, x+6, y+6, 1);   // Strahl Unten
1931
}
1932
 
1933
 
1934
 
1935
//--------------------------------------------------------------
1936
// PARAMETER:
1937
//   x,y : in Pixel
1938
//--------------------------------------------------------------
1939
void draw_icon_satmini2( uint8_t x, uint8_t y)
1940
{
1941
    //lcd_plot( x+0, y+0, 1);            // Referenz 0,0
1942
 
1943
    //lcd_line( x+3, y+3, x+0, y+6, 1);   // Strahl Links
1944
 
1945
    lcd_line( x+2, y-1, x+4, y-1, 1);   //
1946
  //lcd_line( x+2, y+0, x+4, y+0, 1);   //
1947
    lcd_line( x+0, y+0, x+6, y+0, 1);   //
1948
    lcd_line( x+0, y+1, x+6, y+1, 1);   //
1949
    lcd_line( x+2, y+2, x+4, y+2, 1);   //
1950
    lcd_plot( x+3, y+0, 0);             //
1951
    lcd_plot( x+3, y+1, 0);             //
1952
 
1953
    lcd_line( x+3, y+3, x+1, y+5, 1);   // Strahl Links
1954
    lcd_line( x+3, y+3, x+5, y+5, 1);   // Strahl Rechts
1955
    lcd_line( x+0, y+6, x+6, y+6, 1);   // Strahl Unten
1956
}
1957
 
1958
 
1959
//--------------------------------------------------------------
1960
// PARAMETER:
1961
//   x,y : in Pixel
1962
//--------------------------------------------------------------
1963
void draw_icon_battery( uint8_t x, uint8_t y)
1964
{
1965
    //lcd_plot( x+0, y+0, 1);           // Referenz 0,0
1966
    lcd_rect( x+2, y+0, 2, 2,  1);      // der kleine Knubbel oben
1967
    lcd_rect( x+0, y+2, 6, 15, 1);      // body
1968
}
1969
 
1970
 
1971
 
1972
//--------------------------------------------------------------
1973
// RC symbol
1974
// alternatives Symbol fuer RC-Quality
1975
//--------------------------------------------------------------
1976
void draw_symbol_rc( uint8_t x, uint8_t y)
1977
{
1978
    x *= 6;
1979
    y *= 8;
1980
    y += 1;
1981
    x += 1;
1982
 
1983
    lcd_plot( x+3, y+4, 1);
1984
    lcd_line( x+2, y+2, x+4, y+2, 1);
1985
    lcd_line( x+1, y+0, x+5, y+0, 1);
1986
}
1987
 
1988
 
1989
 
1990
 
1991
//##############################################################
1992
//# spezielle Beeps
1993
//##############################################################
1994
 
1995
//--------------------------------------------------------------
1996
// Beep_Waypoint()
1997
//
1998
// Beep bei Waypoint Wechsel und wenn die WP-Liste abgearbeitet
1999
// ist
2000
//--------------------------------------------------------------
2001
void Beep_Waypoint( void )
2002
{
2003
    //-----------------
2004
    // BEEP: WP erreicht
2005
    //-----------------
2006
    if( naviData->WaypointIndex > WP_old )
2007
    {
2008
        set_beep( 30, 0xffff, BeepNormal );                         // kurzer Bestaetigungs-Beep
2009
    }
2010
 
2011
    if(    (naviData->WaypointIndex == naviData->WaypointNumber)
2012
        && (naviData->NCFlags & NC_FLAG_TARGET_REACHED)
2013
        && (!WP_last)
2014
      )
2015
    {
2016
        set_beep( 400, 0xffff, BeepNormal );                        // langer Bestaetigungs-Beep
2017
        WP_last = true;
2018
    }
2019
 
2020
    if( naviData->WaypointIndex != WP_old )
2021
    {
2022
        WP_old = naviData->WaypointIndex;
2023
    }
2024
 
2025
    if(     (naviData->WaypointIndex != naviData->WaypointNumber)   // wenn aktueller WP != WP-Anzahl -> WP_last abschalten
2026
        || !(naviData->NCFlags & NC_FLAG_TARGET_REACHED)            // wenn kein TR mehr an ist -> WP_last abschalten
2027
      )
2028
    {
2029
        WP_last = false;
2030
    }
2031
 
2032
 
2033
    // alter Code zur Orientierung
2034
    //if( OldWP != naviData->WaypointIndex )
2035
    //{
2036
    //    OldWP = naviData->WaypointIndex;
2037
    //    NextWP = true;
2038
    //}
2039
    //
2040
    //if( (NextWP==true) && (naviData->NCFlags & NC_FLAG_TARGET_REACHED) )
2041
    //{
2042
    //    set_beep( 25, 0xffff, BeepNormal );                       // kurzer Bestaetigungs-Beep
2043
    //    NextWP = false;
2044
    //}
2045
}
2046
 
2047
 
2048
 
2049
//##############################################################
2050
//# OSD-ELEMENTS
2051
//##############################################################
2052
 
2053
//--------------------------------------------------------------
2054
// OSD_Element_Flag_Label( xC, yC, item, lOn, xoffs, yoffs)
2055
//
2056
// xC, yC       : x,y in Characters
2057
// item         : OSD_FLAG_AH, OSD_FLAG_PH, usw.
2058
// lOn          : true / false
2059
// xoffs,yoffs  : x,y Pixelverschiebung
2060
//--------------------------------------------------------------
2061
void OSD_Element_Flag_Label( uint8_t xC, uint8_t yC, uint8_t item, uint8_t lOn, int8_t xoffs, int8_t yoffs)
2062
{
2063
    int8_t  x = (xC*6)-2;
2064
    int8_t  y = (yC*8)-1;
2065
    uint8_t w = 14;
2066
    uint8_t h = 8;
2067
 
2068
    const char *labels[OSD_FLAG_COUNT] =
2069
    {
2070
        PSTR("AH"),  // OSD_FLAG_AH  Altitue Hold
2071
        PSTR("PH"),  // OSD_FLAG_PH  Position Hold
2072
        PSTR("CF"),  // OSD_FLAG_CF  Care Free
2073
        PSTR("CH"),  // OSD_FLAG_CH  Coming Home
2074
        PSTR("o1"),  // OSD_FLAG_O1  Out1
2075
        PSTR("o2"),  // OSD_FLAG_O2  Out2
2076
        PSTR("BA"),  // OSD_FLAG_BA  LowBat warning (MK)
2077
        PSTR("CA"),  // OSD_FLAG_CA  Calibrate
2078
        PSTR("ST"),  // OSD_FLAG_ST  Start
2079
        PSTR("MR"),  // OSD_FLAG_MR  Motor Run
2080
        PSTR("FY"),  // OSD_FLAG_FY  Fly
2081
        PSTR("EL"),  // OSD_FLAG_EL  Emergency Landing
2082
        PSTR("FS"),  // OSD_FLAG_FS  RX Failsave Active
2083
        PSTR("GP"),  // OSD_FLAG_GP  GPS Ok
2084
        PSTR("S!"),  // OSD_FLAG_S0  GPS-Sat not ok (GPS NOT ok)
2085
        PSTR("TU"),  // OSD_FLAG_TU  Vario Trim Up
2086
        PSTR("TD"),  // OSD_FLAG_TD  Vario Trim Down
2087
        PSTR("FR"),  // OSD_FLAG_FR  Free
2088
        PSTR("RL"),  // OSD_FLAG_RL  Range Limit
2089
        PSTR("SL"),  // OSD_FLAG_SL  No Serial Link
2090
        PSTR("TR"),  // OSD_FLAG_TR  Target Reached
2091
        PSTR("MC")   // OSD_FLAG_MC  Manual Control
2092
    };
2093
 
2094
    //lcd_plot( x-2, y-2, 1);                       // Referenz
2095
 
2096
    if( yC==0 && yoffs<=0 ) { y = 0;  h = 7;  }
2097
    if( xC==0 && xoffs<=0 ) { x = 0;  w = 12; }
2098
 
2099
    if( lOn )
2100
    {
2101
        lcd_frect( x+xoffs, y+yoffs, w, h, 1);                          // Filler
2102
        lcdx_printp_at(  xC, yC, labels[item], MINVERS, xoffs,yoffs);   // Label
2103
    }
2104
    else
2105
    {
2106
        lcd_frect( x+xoffs, y+yoffs, w, h, 0);                          // clear
2107
    }
2108
}
2109
 
2110
 
2111
//--------------------------------------------------------------
2112
//--------------------------------------------------------------
2113
void OSD_Element_Flag( uint8_t xC, uint8_t yC, uint8_t item, int8_t xoffs, int8_t yoffs)
2114
{
2115
    uint8_t lOn = 0;
2116
 
2117
    // FC_StatusFlags 0.88
2118
    switch( item )
2119
    {
2120
        // Altitue Hold
2121
        case OSD_FLAG_AH :  lOn = (naviData->FCStatusFlags2 & FC_STATUS2_ALTITUDE_CONTROL);
2122
                                break;
2123
 
2124
        // Position Hold
2125
        case OSD_FLAG_PH :  lOn = (naviData->NCFlags & NC_FLAG_PH);
2126
                                break;
2127
 
2128
        // Coming Home
2129
        case OSD_FLAG_CH :  lOn = (naviData->NCFlags & NC_FLAG_CH);
2130
                                break;
2131
 
2132
        // Care Free
2133
        case OSD_FLAG_CF :  lOn = (naviData->FCStatusFlags2 & FC_STATUS2_CAREFREE);
2134
                                break;
2135
 
2136
        // Out1
2137
        case OSD_FLAG_O1 :  lOn = (naviData->FCStatusFlags2 & FC_STATUS2_OUT1_ACTIVE);
2138
                                break;
2139
 
2140
        // Out2
2141
        case OSD_FLAG_O2 :  lOn = (naviData->FCStatusFlags2 & FC_STATUS2_OUT2_ACTIVE);
2142
                                break;
2143
 
2144
        //  LowBat warning (MK)
2145
        case OSD_FLAG_BA :  lOn = (naviData->FCStatusFlags & FC_STATUS_LOWBAT);
2146
                                break;
2147
 
2148
        //  Calibrate
2149
        case OSD_FLAG_CA :  lOn = (naviData->FCStatusFlags & FC_STATUS_CALIBRATE);
2150
                                break;
2151
 
2152
        //  Start
2153
        case OSD_FLAG_ST :  lOn = (naviData->FCStatusFlags & FC_STATUS_START);
2154
                                break;
2155
 
2156
        //  Motor Run
2157
        case OSD_FLAG_MR :  lOn = (naviData->FCStatusFlags & FC_STATUS_MOTOR_RUN);
2158
                                break;
2159
 
2160
        //  Fly
2161
        case OSD_FLAG_FY :  lOn = (naviData->FCStatusFlags & FC_STATUS_FLY);
2162
                                break;
2163
 
2164
        //  Emergency Landing
2165
        case OSD_FLAG_EL :  lOn = (naviData->FCStatusFlags & FC_STATUS_EMERGENCY_LANDING);
2166
                                break;
2167
 
2168
        //  RC Failsave Active
2169
        case OSD_FLAG_FS :  lOn = (naviData->FCStatusFlags2 & FC_STATUS2_RC_FAILSAVE_ACTIVE);
2170
                                break;
2171
 
2172
        //  GPS ok
2173
        case OSD_FLAG_GP :  lOn = (naviData->NCFlags & NC_FLAG_GPS_OK);
2174
                                break;
2175
 
2176
        //  GPS-Sat not ok (GPS NOT ok)
2177
        case OSD_FLAG_S0 :  lOn = !(naviData->NCFlags & NC_FLAG_GPS_OK);
2178
                                break;
2179
 
2180
        //  Vario Trim Up
2181
        case OSD_FLAG_TU :  lOn = (naviData->FCStatusFlags & FC_STATUS_VARIO_TRIM_UP);
2182
                                break;
2183
 
2184
        //  Vario Trim Down
2185
        case OSD_FLAG_TD :  lOn = (naviData->FCStatusFlags & FC_STATUS_VARIO_TRIM_DOWN);
2186
                                break;
2187
 
2188
        //  Free
2189
        case OSD_FLAG_FR :  lOn = (naviData->NCFlags & NC_FLAG_FREE);
2190
                                break;
2191
 
2192
        //  Range Limit
2193
        case OSD_FLAG_RL :  lOn = (naviData->NCFlags & NC_FLAG_RANGE_LIMIT);
2194
                                break;
2195
 
2196
        //  No Serial Link
2197
        case OSD_FLAG_SL :  lOn = (naviData->NCFlags & NC_FLAG_NOSERIALLINK);
2198
                                break;
2199
 
2200
        //  Target Reached
2201
        case OSD_FLAG_TR :  lOn = (naviData->NCFlags & NC_FLAG_TARGET_REACHED);
2202
                                break;
2203
 
2204
        //  Manual Control
2205
        case OSD_FLAG_MC :  lOn = (naviData->NCFlags & NC_FLAG_MANUAL_CONTROL);
2206
                                break;
2207
 
2208
    }
2209
 
2210
    OSD_Element_Flag_Label( xC, yC, item, lOn, xoffs,yoffs);
2211
}
2212
 
2213
 
2214
//--------------------------------------------------------------
2215
// Anzeige von Steigen / Sinken
2216
//--------------------------------------------------------------
2217
void OSD_Element_UpDown( uint8_t x, uint8_t y, int8_t xoffs, int8_t yoffs)
2218
{
2219
    x = (x*6) + xoffs;
2220
    y = (y*8) + yoffs;
2221
 
2222
    lcd_frect( x, y, 6, 7, 0);              // clear
2223
 
2224
    if( naviData->Variometer > 2 )          // steigen mehr als 0.2 m/sec (ein guter Wert muss noch in der Praxis ermittelt werden)
2225
    {
2226
        lcd_line( x+2, y+0, x+0, y+2, 1);
2227
        lcd_line( x+2, y+0, x+4, y+2, 1);
2228
    }
2229
    else if( naviData->Variometer < -2 )    // sinken  mehr als 0.2 m/sec
2230
    {
2231
        lcd_line( x+2, y+6, x+0, y+4, 1);
2232
        lcd_line( x+2, y+6, x+4, y+4, 1);
2233
    }
2234
 
2235
}
2236
 
2237
 
2238
//--------------------------------------------------------------
2239
// OSD_Element_Altitude( x, y, nStyle)
2240
// nStyle entspricht dem ehemaligen 'Mode'
2241
//--------------------------------------------------------------
2242
void OSD_Element_Altitude( uint8_t x, uint8_t y, uint8_t nStyle )
2243
{
2244
 
2245
#ifdef USE_FONT_BIG
2246
 
2247
    switch( nStyle )
2248
    {
2249
        case 0 :
2250
        case 1 :    //note:lephisto:according to several sources it's /30
2251
                    if (naviData->Altimeter > (300 / AltimeterAdjust) || naviData->Altimeter < (-300 / AltimeterAdjust))    // above 10m only write full meters
2252
                             write_ndigit_number_s (x, y, naviData->Altimeter / (30 / AltimeterAdjust), 4, 0,MNORMAL);
2253
                    else    // up to 10m write meters.dm
2254
                             write_ndigit_number_s_10th (x, y, naviData->Altimeter / (3 / AltimeterAdjust), 3, 0,MNORMAL);
2255
 
2256
                    lcd_printp_at (x+4, y, PSTR("m"), MNORMAL);
2257
                    lcd_putc (x+5, y, 0x09, 0);  // Hoehensymbol
2258
                    break;
2259
 
2260
        case 2 :    //note:lephisto:according to several sources it's /30
2261
                    if (naviData->Altimeter > (300 / AltimeterAdjust) || naviData->Altimeter < (-300 / AltimeterAdjust))        // above 10m only write full meters
2262
                        write_ndigit_number_s (x+4, y, naviData->Altimeter / (30 / AltimeterAdjust), 4, 0,MBIG);
2263
                    else        // up to 10m write meters.dm
2264
                        write_ndigit_number_s_10th (x+4, y, naviData->Altimeter / (3 / AltimeterAdjust), 3, 0,MBIG);
2265
                    lcd_putc( x+8, y, 'm', MBIG);
2266
                    lcd_printp_at (x, y, PSTR("Höhe"), MNORMAL);
2267
                    break;
2268
    }
2269
 
2270
#else
2271
 
2272
    if( nStyle == 2 )
2273
    {
2274
        lcd_printp_at (x, y, PSTR("Höhe"), MNORMAL);
2275
        x += 4;
2276
    }
2277
    else
2278
    {
2279
        lcd_putc (x+5, y, 0x09, 0);  // Hoehensymbol
2280
    }
2281
 
2282
    if (naviData->Altimeter > (300 / AltimeterAdjust) || naviData->Altimeter < (-300 / AltimeterAdjust))    // above 10m only write full meters
2283
        write_ndigit_number_s (x, y, naviData->Altimeter / (30 / AltimeterAdjust), 4, 0,MNORMAL);
2284
    else    // up to 10m write meters.dm
2285
        write_ndigit_number_s_10th (x, y, naviData->Altimeter / (3 / AltimeterAdjust), 3, 0,MNORMAL);
2286
 
2287
    lcd_printp_at (x+4, y, PSTR("m"), MNORMAL);
2288
 
2289
#endif
2290
 
2291
}
2292
 
2293
 
2294
//--------------------------------------------------------------
2295
// fuer: Config.OSD_LipoBar==1
2296
//--------------------------------------------------------------
2297
void OSD_Element_BatteryLevel_Bar( uint8_t x, uint8_t y )
2298
{
2299
    uint16_t Balken = 0;
2300
 
2301
    drawmode = (naviData->UBat < BattLowVoltageWarning ? 2 : 0);
2302
 
2303
    if( cells > 0 )  // LipobargraphAnzeige nur wenn Anzahl der Lipozellen bekannt sind
2304
    {
2305
        write_ndigit_number_u (x+6, y, cells, 1, 0, drawmode);
2306
        lcd_printp_at (x+7, y, PSTR("S"), drawmode);
2307
 
2308
        if( cells==3 )
2309
        {
2310
            lcd_rect(x*6, y*8, 28, 7, 1);  // Rahmen
2311
            Balken = ((naviData->UBat-(cells*MIN_CELL_VOLTAGE))*10)/12;
2312
            if((Balken > 0) && (Balken <28)) lcd_frect((x*6)+1, (y*8)+1, Balken, 5, 1);     // Fuellung
2313
            if(Balken <= 26) lcd_frect(Balken+(x*6)+1, (y*8)+1, 26-Balken, 5, 0);           // loeschen
2314
        }
2315
 
2316
        if( cells==4 ||cells==5 )
2317
        {
2318
           lcd_rect(x*6, y*8, 30, 7, 1);  // Rahmen
2319
           if (cells == 4) Balken = ((naviData->UBat-(cells*MIN_CELL_VOLTAGE))*10)/15;
2320
           if (cells == 5) Balken = ((naviData->UBat-(cells*MIN_CELL_VOLTAGE))*10)/19;
2321
           if ((Balken > 0) && (Balken <=29)) lcd_frect((x*6)+1, (y*8)+1, Balken, 5, 1);    // Fuellung
2322
           if (Balken <= 27) lcd_frect(Balken+(x*6)+1, (y*8)+1, 28-Balken, 5, 0);           // loeschen
2323
        }
2324
 
2325
      } // end if: cells > 0   (TODO: Anzeige fuer cells==0 implementieren)
2326
}
2327
 
2328
 
2329
 
2330
//--------------------------------------------------------------
2331
// fuer die neuen OSD-Screens
2332
//--------------------------------------------------------------
2333
void OSD_Element_BattLevel2( uint8_t x, uint8_t y, int8_t xoffs, int8_t yoffs )
2334
{
2335
    drawmode = (naviData->UBat < BattLowVoltageWarning ? MINVERS : MNORMAL);
2336
 
2337
    if( Config.OSD_ShowCellU )
2338
    {
2339
        // kalk. Einzelzellen Spannungsanzeige
2340
        writex_ndigit_number_u_100th( x, y, (uint16_t)((naviData->UBat*10)/cells), 3, 0, drawmode, xoffs,yoffs);
2341
        lcdx_printp_at( x+4, y, PSTR("v"), drawmode, xoffs+1,yoffs);                    // Einheit (Einzelzellenanzeige ca., berechnet)
2342
    }
2343
    else
2344
    {
2345
        // Gesamtspannungsanzeige
2346
        writex_ndigit_number_u_10th( x, y, naviData->UBat, 3, 0, drawmode, xoffs,yoffs);
2347
        lcdx_printp_at( x+4, y, PSTR("V"), drawmode, xoffs+1,yoffs);                    // Einheit (Gesamtspannung)
2348
    }
2349
 
2350
    lcd_line( (x+4)*6, y*8, (x+4)*6, y*8+7, (drawmode==MINVERS ? 1 : 0) );              // filler zwischen Spannung und "V"
2351
 
2352
}
2353
 
2354
 
2355
//--------------------------------------------------------------
2356
// fuer: Config.OSD_LipoBar==0
2357
// nStyle entspricht dem ehemaligen 'Mode'
2358
//--------------------------------------------------------------
2359
void OSD_Element_BatteryLevel_Text( uint8_t x, uint8_t y, uint8_t nStyle )
2360
{
2361
#ifdef USE_FONT_BIG
2362
    if( nStyle <= 1)
2363
        drawmode = (naviData->UBat < BattLowVoltageWarning ? 2 : 0);  // Normal-Schrift
2364
    else
2365
        drawmode = (naviData->UBat < BattLowVoltageWarning ? 4 : 3);  // Fett-Schrift
2366
 
2367
    if( nStyle <= 1)
2368
    {
2369
        write_ndigit_number_u_10th (x, y, naviData->UBat, 3, 0, drawmode);
2370
        lcd_printp_at (x+4, y, PSTR("V"), drawmode);
2371
    }
2372
    else
2373
    {
2374
        write_ndigit_number_u_10th (x-2, y, naviData->UBat, 3, 0, drawmode);
2375
        lcd_printp_at (x+2, y, PSTR("V"), drawmode);
2376
    }
2377
#else
2378
    drawmode = (naviData->UBat < BattLowVoltageWarning ? 2 : 0);  // Normal-Schrift
2379
 
2380
    if( nStyle == 2)
2381
        x += 3;
2382
    write_ndigit_number_u_10th (x, y, naviData->UBat, 3, 0, drawmode);
2383
    lcd_printp_at (x+4, y, PSTR("V"), drawmode);
2384
#endif
2385
}
2386
 
2387
 
2388
//--------------------------------------------------------------
2389
// OSD_Element_Battery_Bar( x, y, length, width, orientation)
2390
//
2391
// neue Variante (OG 06/2013)
2392
//
2393
// Parameter:
2394
//  length     : Gesamtlaenge des Bar's
2395
//  width      : Breite in Pixel (fest)
2396
//  orientation: ORIENTATION_V - Vertikal (x,y oberer,linker Punkt)
2397
//               ORIENTATION_H
2398
//--------------------------------------------------------------
2399
void OSD_Element_Battery_Bar( uint8_t x, uint8_t y, uint8_t length, uint8_t width, uint8_t orientation)
2400
{
2401
    uint8_t bat_umax;
2402
    uint8_t bat_umin;
2403
    uint8_t bat_uact;
2404
    int8_t  bat_p;
2405
 
2406
    // die Min/Max Spannungswerte sind jetzt erstmal fest vorgegeben bzw. berechnet, eine individuelle
2407
    // Anpassung waere moeglich aber wenn besser ist es, wenn der User das nicht machen muesste...
2408
    bat_umax = cells * 42;
2409
    //bat_umin = cells * 32;
2410
    bat_umin = cells * 34;          // 3.4 Volt pro Zelle Minimum
2411
 
2412
    bat_uact = naviData->UBat;
2413
 
2414
    bat_p = length * (bat_uact-bat_umin) / (bat_umax-bat_umin);
2415
 
2416
    if( bat_p < 0 )      bat_p = 0;
2417
    if( bat_p > length ) bat_p = length;
2418
 
2419
    if( width == 1 )     width = 0;     // eine kleine Eigenart von frect um es zu ueberreden eine Linie zu zeichnen
2420
 
2421
    if( orientation == ORIENTATION_V )
2422
    {
2423
        lcd_frect( x, y             , width, length-bat_p, 0);  // clear: vertical
2424
        lcd_frect( x, y+length-bat_p, width,        bat_p, 1);  // draw: vertical
2425
    }
2426
    else
2427
    {
2428
        lcd_frect( x+bat_p, y, length-bat_p, width,  0);    // clear:
2429
        lcd_frect( x      , y, bat_p       , width,  1);    // draw:
2430
    }
2431
}
2432
 
2433
 
2434
//--------------------------------------------------------------
2435
// nStyle entspricht dem ehemaligen 'Mode'
2436
//--------------------------------------------------------------
2437
void OSD_Element_BatteryLevel( uint8_t x, uint8_t y, uint8_t nStyle )
2438
{
2439
    if( Config.OSD_LipoBar )
2440
        OSD_Element_BatteryLevel_Bar( x, y);
2441
    else
2442
        OSD_Element_BatteryLevel_Text( x, y, nStyle);
2443
}
2444
 
2445
 
2446
//--------------------------------------------------------------
2447
//--------------------------------------------------------------
2448
void OSD_Element_Capacity( uint8_t x, uint8_t y )
2449
{
2450
    drawmode = (naviData->UsedCapacity > Config.OSD_mAh_Warning ? 2 : 0);
2451
 
2452
    write_ndigit_number_u (x, y, naviData->UsedCapacity, 5, 0, drawmode);
2453
    lcd_printp_at (x+5, y, PSTR("mAh"), drawmode);
2454
    // BeepTime = 3000;
2455
    // BeepMuster = 0x0020;
2456
}
2457
 
2458
 
2459
 
2460
//--------------------------------------------------------------
2461
// OSD_Element_CompassDegree( x, y, nStyle)
2462
// nStyle entspricht dem ehemaligen 'Mode'
2463
//--------------------------------------------------------------
2464
void OSD_Element_CompassDegree( uint8_t x, uint8_t y, uint8_t nStyle )
2465
{
2466
    switch( nStyle )
2467
    {
2468
        case 0 :
2469
        case 1 : write_ndigit_number_u (x, y, (naviData->CompassHeading)%360, 3, 0,MNORMAL);
2470
                 x += 3;
2471
                 break;
2472
 
2473
        case 2 :
2474
                 #ifdef USE_FONT_BIG
2475
                    write_ndigit_number_u (x, y, (naviData->CompassHeading)%360, 3, 0,MBIG);
2476
                 #else
2477
                    write_ndigit_number_u (x+5, y, (naviData->CompassHeading)%360, 3, 0,MNORMAL);
2478
                 #endif
2479
 
2480
                 x += 8;
2481
                 break;
2482
    }
2483
    lcd_putc( x, y, 0x1E, MNORMAL);     // degree symbol
2484
}
2485
 
2486
 
2487
//--------------------------------------------------------------
2488
//--------------------------------------------------------------
2489
void OSD_Element_CompassDirection( uint8_t x, uint8_t y, int8_t xoffs, int8_t yoffs )
2490
{
2491
    lcdx_printp_at (x, y, (const char *) (pgm_read_word ( &(directions_p[heading_conv((naviData->CompassHeading)%360)]))), MNORMAL, xoffs,yoffs);
2492
}
2493
 
2494
 
2495
//--------------------------------------------------------------
2496
//--------------------------------------------------------------
2497
void OSD_Element_CompassRose( uint8_t x, uint8_t y )
2498
{
2499
    draw_compass (x, y, (naviData->CompassHeading)%360, 0,0);
2500
}
2501
 
2502
//--------------------------------------------------------------
2503
//--------------------------------------------------------------
2504
void OSD_Element_Current( uint8_t x, uint8_t y )
2505
{
2506
    write_ndigit_number_u_10th (x, y, naviData->Current, 3, 0,0);
2507
    lcd_printp_at (x+4, y, PSTR("A"), 0);
2508
}
2509
 
2510
 
2511
//--------------------------------------------------------------
2512
//--------------------------------------------------------------
2513
void OSD_Element_FlyingTime( uint8_t x, uint8_t y )
2514
{
2515
    write_time (x, y, naviData->FlyingTime);
2516
    lcd_printp_at (x+5, y, PSTR("m"), 0);
2517
}
2518
 
2519
 
2520
//--------------------------------------------------------------
2521
//--------------------------------------------------------------
2522
void OSD_Element_GroundSpeed( uint8_t x, uint8_t y )
2523
{
2524
    write_ndigit_number_u (x, y, (uint16_t) (((uint32_t) naviData->GroundSpeed * (uint32_t) 9) / (uint32_t) 250), 3, 0,0);
2525
    lcd_printp_at (x+3, y, PSTR("Kmh"), 0);
2526
}
2527
 
2528
 
2529
 
2530
//--------------------------------------------------------------
2531
//--------------------------------------------------------------
2532
void OSD_Element_HomeCircle( uint8_t x, uint8_t y, uint8_t breite, int8_t rOffset, int8_t xoffs, int8_t yoffs )
2533
{
2534
    calc_heading_home();
2535
 
2536
    lcd_o_circle( x, y, breite, 1, xoffs,yoffs);
2537
    lcd_o_circ_line( x, y, breite, (old_hh       + 180), rOffset, 0, xoffs,yoffs);
2538
    lcd_o_circ_line( x, y, breite, (heading_home + 180), rOffset, 1, xoffs,yoffs);
2539
 
2540
    old_hh = heading_home;
2541
}
2542
 
2543
 
2544
 
2545
//--------------------------------------------------------------
2546
// NEU! 22.04.2014 OG
2547
// soll das alte OSD_Element_HomeCircle() komplett ersetzen wenn
2548
// die alten OSD-Screens endgueltig rausfliegen
2549
//--------------------------------------------------------------
2550
void OSD_Element_HomeCircleX( uint8_t px, uint8_t py, uint8_t rx, int8_t ry )
2551
{
2552
    calc_heading_home();
2553
    lcd_ellipse_line( px, py, rx, ry, (old_hh       + 180), 0);
2554
    lcd_ellipse_line( px, py, rx, ry, (heading_home + 180), 1);
2555
    lcd_ellipse( px, py, rx, ry, 1);
2556
    old_hh = heading_home;
2557
}
2558
 
2559
 
2560
 
2561
//--------------------------------------------------------------
2562
//--------------------------------------------------------------
2563
void OSD_Element_HomeDegree( uint8_t x, uint8_t y )
2564
{
2565
    write_ndigit_number_u (x, y, heading_home, 3, 0,0);
2566
    lcd_putc (x+3, y, 0x1e, 0); // degree symbol
2567
}
2568
 
2569
 
2570
//--------------------------------------------------------------
2571
// OSD_Element_HomeDistance( x, y, nStyle)
2572
//--------------------------------------------------------------
2573
void OSD_Element_HomeDistance( uint8_t x, uint8_t y, uint8_t nStyle )
2574
{
2575
    switch( nStyle )
2576
    {
2577
        case 0 :
2578
        case 1 : write_ndigit_number_u (x, y, naviData->HomePositionDeviation.Distance / 10, 3, 0,0);
2579
                 lcd_putc (x+3, y, 'm', 0);
2580
                 draw_homesymbol(x+4, y);
2581
                 break;
2582
 
2583
        case 2 : lcd_printp_at (x, y, PSTR("Home"), 0);
2584
                 write_ndigit_number_u (x+5, y, naviData->HomePositionDeviation.Distance / 10, 3, 0,0);
2585
                 lcd_printp_at (x+8, y, PSTR("m -"), 0);
2586
                 break;
2587
    }
2588
}
2589
 
2590
 
2591
//--------------------------------------------------------------
2592
// OSD_Element_LEDOutput( x, y, bitmask)
2593
//
2594
// bitmask: LED1 = FC_STATUS2_OUT1_ACTIVE
2595
//          LED2 = FC_STATUS2_OUT2_ACTIVE
2596
//--------------------------------------------------------------
2597
void OSD_Element_LEDOutput( uint8_t x, uint8_t y, uint8_t bitmask )
2598
{
2599
    uint8_t lOn;
2600
 
2601
    lOn = (naviData->FCStatusFlags2 & bitmask ? 1 : 0);   // Bit gesetzt?
2602
    lOn = (Config.OSD_InvertOut ? !lOn : lOn);            // Invertieren?
2603
    lOn = (lOn ? 1 : 0);                                  // auf 0 oder 1 setzen
2604
 
2605
    lcd_fcircle (x * 6 + 5, y * 8 + 3, Config.OSD_LEDform, lOn);
2606
    lcd_circle  (x * 6 + 5, y * 8 + 3, 3, 1);
2607
}
2608
 
2609
 
2610
//--------------------------------------------------------------
2611
// OSD_Element_LED1Output( x, y)
2612
//--------------------------------------------------------------
2613
void OSD_Element_LED1Output( uint8_t x, uint8_t y )
2614
{
2615
    OSD_Element_LEDOutput( x, y, FC_STATUS2_OUT1_ACTIVE );
2616
}
2617
 
2618
 
2619
//--------------------------------------------------------------
2620
// OSD_Element_LED2Output( x, y)
2621
//--------------------------------------------------------------
2622
void OSD_Element_LED2Output( uint8_t x, uint8_t y )
2623
{
2624
    OSD_Element_LEDOutput( x, y, FC_STATUS2_OUT2_ACTIVE );
2625
}
2626
 
2627
 
2628
//--------------------------------------------------------------
2629
// OSD_Element_Manuell( x, y)
2630
//--------------------------------------------------------------
2631
void OSD_Element_Manuell( uint8_t x, uint8_t y )
2632
{
2633
    if (naviData->NCFlags & NC_FLAG_MANUAL_CONTROL)
2634
        lcd_putc (x, y, 'M', 0); // rc transmitter
2635
    else
2636
        lcd_putc (x, y, 'X', 0); // clear
2637
}
2638
 
2639
 
2640
 
2641
//--------------------------------------------------------------
2642
// OSD_Element_RCIntensity( x, y)
2643
//--------------------------------------------------------------
2644
void OSD_Element_RCIntensity( uint8_t x, uint8_t y )
2645
{
2646
    write_ndigit_number_u (x, y, naviData->RC_Quality, 3, 0,0);
2647
    //lcd_printp_at (x+3, y, PSTR("\x1F"), 0);        // RC-transmitter
2648
    if (naviData->NCFlags & NC_FLAG_NOSERIALLINK)
2649
    {
2650
        lcd_printpns_at(x+3, y, PSTR("  "), 0);     // Clear
2651
    }
2652
    else
2653
    {
2654
        lcd_printpns_at(x+3, y, PSTR("PC"), 0);
2655
    }
2656
}
2657
 
2658
 
2659
//--------------------------------------------------------------
2660
// OSD_Element_SatsInUse( x, y, nStyle)
2661
//
2662
// nStyle == 0: "00s"
2663
// nStyle == 1: wie 0
2664
// nStyle == 2: "00 Sat"
2665
//
2666
// nStyle entspricht dem ehemaligen 'Mode'
2667
//--------------------------------------------------------------
2668
void OSD_Element_SatsInUse( uint8_t x, uint8_t y, uint8_t  nStyle )
2669
{
2670
    drawmode = (naviData->NCFlags & NC_FLAG_GPS_OK ? 0 : 2);
2671
 
2672
    switch( nStyle )
2673
    {
2674
        case 0 :
2675
        case 1 : write_ndigit_number_u (x, y, naviData->SatsInUse, 2, 0, drawmode);
2676
                 lcd_putc (x+2, y, 0x08, drawmode);
2677
                 break;
2678
 
2679
        case 2 : write_ndigit_number_u (x, y, naviData->SatsInUse, 2, 0, drawmode);
2680
                 lcd_printp_at (x+2, y, PSTR(" Sat"), drawmode);
2681
                 break;
2682
    }
2683
}
2684
 
2685
 
2686
 
2687
//--------------------------------------------------------------
2688
// OSD_Element_Variometer( x, y)
2689
//--------------------------------------------------------------
2690
void OSD_Element_Variometer( uint8_t x, uint8_t y )
2691
{
2692
    x *= 6;
2693
    y *= 8;
2694
    y += 7;
2695
 
2696
    draw_variometer (x, y, 10, 14, naviData->Variometer);
2697
}
2698
 
2699
 
2700
//--------------------------------------------------------------
2701
// OSD_Element_Target( x, y, nStyle)
2702
//
2703
// nStyle entspricht dem ehemaligen 'Mode'
2704
// nStyle = 0,1: "000m"
2705
// nStyle = 2,3: "Ziel 000m -"
2706
//--------------------------------------------------------------
2707
void OSD_Element_Target( uint8_t x, uint8_t y, uint8_t nStyle )
2708
{
2709
    if( nStyle <= 1 )
2710
    {
2711
        write_ndigit_number_u (x, y, naviData->TargetPositionDeviation.Distance / 10, 3, 0,0);
2712
        lcd_putc (x+3, y, 'm', 0);
2713
        draw_targetsymbol(x+4,y);
2714
    }
2715
    else
2716
    {
2717
        lcd_printp_at (x, y, PSTR("Ziel"), 0);
2718
        write_ndigit_number_u (x+5, y, naviData->TargetPositionDeviation.Distance / 10, 3, 0,0);
2719
        lcd_printp_at (x+8, y, PSTR("m -"), 0);
2720
    }
2721
}
2722
 
2723
 
2724
//--------------------------------------------------------------
2725
// TODO:
2726
// - pruefen ob beep hier an richtiger Stelle ist
2727
//--------------------------------------------------------------
2728
void OSD_Element_VarioWert( uint8_t x, uint8_t y )
2729
{
2730
    uint8_t FC_Fallspeed;
2731
 
2732
    FC_Fallspeed = (unsigned int)naviData->Variometer;
2733
    FC_Fallspeed = 255-FC_Fallspeed;
2734
 
2735
    drawmode = ( (naviData->Variometer < 0) && (FC_Fallspeed > Config.OSD_Fallspeed) ? 2 : 0);
2736
 
2737
 
2738
    if( Config.OSD_VarioBeep )
2739
        Beep_Vario();                               // Beep ???
2740
 
2741
    if( drawmode == 2 )
2742
    {
2743
        if( !Config.HWSound )
2744
            set_beep ( 1000, 0x0060, BeepNormal);   // muss ein Beep hier hin????
2745
        else
2746
            variobeep(naviData->Variometer);        // muss ein Beep hier hin????
2747
    }
2748
 
2749
    write_ndigit_number_s_10th (x, y, naviData->Variometer, 3,0, drawmode);
2750
    lcd_printpns_at(x+4, y, PSTR("ms"), drawmode);
2751
}
2752
 
2753
 
2754
//--------------------------------------------------------------
2755
//--------------------------------------------------------------
2756
void OSD_Element_WayPoint( uint8_t x, uint8_t y )
2757
{
2758
    if (!OldWP == naviData->WaypointIndex)
2759
    {
2760
        // BeepTime = 500;
2761
        // BeepMuster = 0x0080;
2762
        OldWP = naviData->WaypointIndex;
2763
        NextWP = true;
2764
    }
2765
 
2766
    if ((NextWP==true)&& naviData->NCFlags & NC_FLAG_TARGET_REACHED)
2767
    {
2768
        set_beep ( 500, 0x0080, BeepNormal);
2769
        NextWP = false;
2770
    }
2771
 
2772
    write_ndigit_number_u (x+2, y, naviData->WaypointIndex , 2, 0,0);
2773
 
2774
    lcd_printp_at (x, y, PSTR("WP"), 0);
2775
}
2776
 
2777
 
2778
//--------------------------------------------------------------
2779
//--------------------------------------------------------------
2780
void OSD_Element_TargetDegree( uint8_t x, uint8_t y )
2781
{
2782
    write_ndigit_number_u (x, y, naviData->TargetPositionDeviation.Bearing/ 10, 3, 0,0);
2783
    lcd_putc (x+3, y, 0x1e, 0);     // degree symbol
2784
}
2785
 
2786
 
2787
 
2788
//##############################################################
2789
//# OSD-SCREENS
2790
//##############################################################
2791
 
2792
//--------------------------------------------------------------
2793
// OSD-Screen "General"
2794
//
2795
// OSDScreenRefresh:    0 = update values
2796
//                  1 = redraw labels and update values
2797
//--------------------------------------------------------------
2798
void OSD_Screen_General( void )
2799
{
2800
    //-----------------------------------------
2801
    // REDRAW
2802
    // statische Screen Elemente die nicht
2803
    // jedesmal neu gezeichnet werden muessen
2804
    //-----------------------------------------
2805
    if( OSDScreenRefresh == OSD_SCREEN_REDRAW )
2806
    {
2807
        // Display: 128 x 64 with 6x8 Font => 21 x 8
2808
 
2809
        // Linien: Horizontal
2810
        lcd_line (0, 28, 127, 28, 1);  // mitte
2811
        lcd_line (0, 51, 127, 51, 1);  // unten
2812
 
2813
        // Linien: Vertikal
2814
        lcd_line (65, 0, 65, 50, 1);   // mitte
2815
 
2816
        //-----------------------------------------
2817
        // Block: Oben - Links
2818
        //-----------------------------------------
2819
        draw_icon_battery(0,4);
2820
        lcdx_printp_at( 7, 2, PSTR(" mA"), MNORMAL, 0,2);
2821
 
2822
        //-----------------------------------------
2823
        // Block: Oben - Rechts
2824
        //-----------------------------------------
2825
        lcdx_printp_at( 12, 0, PSTR("Alt:") , MNORMAL, 0,0);
2826
        lcdx_printp_at( 12, 1, PSTR("Dir:") , MNORMAL, 0,1);
2827
        lcdx_putc( 20, 1, SYMBOL_SMALLDEGREE, MNORMAL, 1,1);
2828
        lcdx_printp_at( 12, 2, PSTR("  I:") , MNORMAL, 0,2);
2829
        lcdx_putc( 20, 2, 'A', MNORMAL, 2,2);
2830
 
2831
        //-----------------------------------------
2832
        // Block: Unten - Links
2833
        //-----------------------------------------
2834
        draw_icon_sat(0,33);
2835
        lcdx_printp_at( 6, 5, PSTR(" kmh"), MNORMAL, 0,1);
2836
 
2837
        //-----------------------------------------
2838
        // Block: Unten - Rechts
2839
        //-----------------------------------------
2840
        draw_icon_home( 70, 32);
2841
        lcdx_putc( 20, 4, 'm', MNORMAL, 2,0);
2842
        lcdx_putc( 20, 5, SYMBOL_SMALLDEGREE, MNORMAL, 1,1);
2843
 
2844
        //-----------------------------------------
2845
        // unterste Zeile
2846
        //-----------------------------------------
2847
        draw_symbol_rc( 20, 7);         // RC-transmitter
2848
        //lcdx_putc( 20, 7, SYMBOL_RCQUALITY, MNORMAL, 2,0);
2849
    }
2850
 
2851
    //-----------------
2852
    // Batt Level (Graph)
2853
    //-----------------
2854
    OSD_Element_Battery_Bar( 2, 8, 11, 2, ORIENTATION_V);
2855
 
2856
    //-----------------
2857
    // Batt Level (Volt)
2858
    //-----------------
2859
    OSD_Element_BattLevel2( 2, 0, 0,0 );
2860
 
2861
    //-----------------
2862
    // LowBat Warnung MK
2863
    //-----------------
2864
    OSD_Element_Flag( 8, 0, OSD_FLAG_BA, 0,0 );
2865
 
2866
    //-----------------
2867
    // Flugzeit
2868
    //-----------------
2869
    writex_time(2, 1, naviData->FlyingTime, MNORMAL, 0,1);
2870
 
2871
    //-----------------
2872
    // entnommene Kapazitaet (mAh)
2873
    //-----------------
2874
    drawmode = (naviData->UsedCapacity > Config.OSD_mAh_Warning ? MINVERS : MNORMAL);
2875
    writex_ndigit_number_u( 2, 2, naviData->UsedCapacity, 5, 0, drawmode, 0,2);
2876
 
2877
    //-----------------
2878
    // Höhe
2879
    //-----------------
2880
    writex_altimeter( 16, 0, naviData->Altimeter, MNORMAL, 0,0 );
2881
/*
2882
    if (naviData->Altimeter > (300 / AltimeterAdjust) || naviData->Altimeter < (-300 / AltimeterAdjust))    // above 10m only write full meters
2883
        write_ndigit_number_s ( 16, 0, naviData->Altimeter / (30 / AltimeterAdjust), 4, 0, MNORMAL);
2884
    else                                                                                                    // up to 10m write meters.dm
2885
        write_ndigit_number_s_10th( 16, 0, naviData->Altimeter / (3 / AltimeterAdjust), 3, 0, MNORMAL);
2886
*/
2887
 
2888
    //-----------------
2889
    // steigen / sinken
2890
    //-----------------
2891
    OSD_Element_UpDown( 20, 0, 2,0);
2892
 
2893
    //-----------------
2894
    // Compass Degree
2895
    //-----------------
2896
    writex_ndigit_number_u (17, 1, (naviData->CompassHeading)%360, 3, 0,MNORMAL, 0,1);
2897
 
2898
    //-----------------
2899
    // Strom
2900
    //-----------------
2901
    //write_ndigit_number_u_10th( 16, 2, naviData->Current, 3, 0,0);  // alternativ mit Nachkomma
2902
    writex_ndigit_number_u( 17, 2, naviData->Current/10, 3, 0,MNORMAL, 0,2);
2903
 
2904
    //-----------------
2905
    // Sat Anzahl
2906
    //-----------------
2907
    write_ndigit_number_u (4, 4, naviData->SatsInUse, 2, 0,MNORMAL);
2908
 
2909
    //-----------------
2910
    // Sat Warnung "!"
2911
    //-----------------
2912
    /*
2913
    if( naviData->NCFlags & NC_FLAG_GPS_OK )
2914
        lcd_printp_at( 9, 4, PSTR(" "), MNORMAL);
2915
    else
2916
        lcd_printp_at( 9, 4, PSTR("!"), MNORMAL);
2917
    */
2918
    OSD_Element_Flag(  8, 4, OSD_FLAG_S0, -1,0 );  // Sat Warnung (GPS not ok)
2919
 
2920
    //-----------------
2921
    // Geschwindigkeit
2922
    //-----------------
2923
    writex_ndigit_number_u( 3, 5, (uint16_t) (((uint32_t) naviData->GroundSpeed * (uint32_t) 9) / (uint32_t) 250), 3, 0,MNORMAL, 0,1);
2924
 
2925
    //-----------------
2926
    // Home Distance
2927
    //-----------------
2928
    write_ndigit_number_u( 17, 4, naviData->HomePositionDeviation.Distance / 10, 3, 0,MNORMAL);
2929
 
2930
    //-----------------
2931
    // Home Winkel
2932
    //-----------------
2933
    writex_ndigit_number_u( 16, 5, heading_home, 4, 0,MNORMAL, 0,1);
2934
 
2935
    //-----------------
2936
    // Flags
2937
    //-----------------
2938
    OSD_Element_Flag(  1, 7, OSD_FLAG_CF, 0,0 );  // Care Free
2939
    OSD_Element_Flag(  4, 7, OSD_FLAG_AH, 0,0 );  // Altitude Hold
2940
    OSD_Element_Flag(  7, 7, OSD_FLAG_PH, 0,0 );  // Position Hold
2941
    OSD_Element_Flag( 10, 7, OSD_FLAG_CH, 0,0 );  // Coming Home
2942
    OSD_Element_Flag( 13, 7, OSD_FLAG_EL, 0,0 );  // Emergency Landing
2943
 
2944
    //-----------------
2945
    // RC-Quality (MK)
2946
    //-----------------
2947
    write_ndigit_number_u( 17, 7, naviData->RC_Quality, 3, 0,MNORMAL);
2948
 
2949
    #ifdef USE_OSD_DEMO
2950
        //-----------------
2951
        // Flags
2952
        //-----------------
2953
        OSD_Element_Flag_Label(  8, 0, OSD_FLAG_BA, true, 0,0 );    // DEMO: Batterie Warnung
2954
        OSD_Element_Flag_Label(  8, 4, OSD_FLAG_S0, true, -1,0 );   // DEMO: Sat Warnung (GPS not ok)
2955
 
2956
        OSD_Element_Flag_Label(  1, 7, OSD_FLAG_CF, true, 0,0 );    // DEMO
2957
        OSD_Element_Flag_Label(  4, 7, OSD_FLAG_AH, true, 0,0 );    // DEMO
2958
        OSD_Element_Flag_Label(  7, 7, OSD_FLAG_PH, true, 0,0 );    // DEMO
2959
        OSD_Element_Flag_Label( 10, 7, OSD_FLAG_CH, true, 0,0 );    // DEMO
2960
        OSD_Element_Flag_Label( 13, 7, OSD_FLAG_EL, true, 0,0 );    // DEMO
2961
    #endif
2962
}
2963
 
2964
 
2965
 
2966
//--------------------------------------------------------------
2967
// OSD-Screen "Navigation"
2968
//
2969
// OSDScreenRefresh:    0 = update values
2970
//                  1 = redraw labels and update values
2971
//--------------------------------------------------------------
2972
#ifdef USE_OSD_SCREEN_NAVIGATION
2973
void OSD_Screen_Navigation( void )
2974
{
2975
    int8_t xoffs, yoffs;
2976
    int16_t degree;
2977
    uint8_t minus;
2978
 
2979
    //-----------------------------------------
2980
    // REDRAW
2981
    // statische Screen Elemente die nicht
2982
    // jedesmal neu gezeichnet werden muessen
2983
    //-----------------------------------------
2984
    if( OSDScreenRefresh == OSD_SCREEN_REDRAW )
2985
    {
2986
        // do things here for static screen elements like labels and so....
2987
 
2988
        lcd_line(  (6*6-3),  0,  (6*6-3), 11, 1);                   // Linie Vertikal links
2989
        lcd_line( (15*6+5),  0, (15*6+5), 11, 1);                   // Linie Vertikal rechts
2990
        lcd_line(        0, 12,      127, 12, 1);                   // Linie Horizontal
2991
 
2992
        lcdx_printp_at( 0, 2, PSTR("Alt:"), MNORMAL, 0,2);          // Hoehe
2993
        lcdx_printp_at( 0, 5, PSTR("Home:"), MNORMAL, 0,3);         // Home Distance
2994
    }
2995
 
2996
 
2997
    //-----------------
2998
    // Oben: Batt Level (Volt)
2999
    //-----------------
3000
    OSD_Element_BattLevel2( 0, 0, 0,0 );
3001
 
3002
    //-----------------
3003
    // Oben: Batt Level Bar
3004
    //-----------------
3005
    //OSD_Element_Battery_Bar( x, y, length, width, orientation)
3006
    OSD_Element_Battery_Bar( 0, 9, 30, 1, ORIENTATION_H);
3007
 
3008
    //-----------------
3009
    // Oben: Kompass Rose
3010
    //-----------------
3011
    draw_compass( 6, 0, (naviData->CompassHeading)%360, 2,0);
3012
 
3013
    //-----------------
3014
    // Oben: Flugzeit
3015
    //-----------------
3016
    writex_time(16, 0, naviData->FlyingTime, MNORMAL, 2,0);
3017
 
3018
    //-----------------
3019
    // Hoehe
3020
    //-----------------
3021
    xoffs = 0;
3022
    yoffs = 3;
3023
    writex_altimeter( 0, 3, naviData->Altimeter, MNORMAL, xoffs,yoffs );
3024
 
3025
    //-----------------
3026
    // Steigen / Sinken
3027
    //-----------------
3028
    OSD_Element_UpDown( 4, 3, 1,yoffs);
3029
 
3030
    //-----------------
3031
    // Home Distance
3032
    //-----------------
3033
    yoffs = 3;
3034
    writex_ndigit_number_u( 0, 6, naviData->HomePositionDeviation.Distance / 10, 4, 0,MNORMAL, 0,yoffs+1);
3035
    lcdx_printp_at( 4, 6, PSTR("m"), MNORMAL, 2,yoffs+1);       // Home
3036
 
3037
    //-----------------
3038
    // Home Circle
3039
    //-----------------
3040
 
3041
//void OSD_Element_HomeCircleX( uint8_t px, uint8_t py, uint8_t rx, int8_t ry )
3042
 
3043
    xoffs = 2;
3044
    yoffs = 3;
3045
 
3046
    //OSD_Element_HomeCircleX( 64, 38, 25, 22 );                            // entspricht dem ehemaligem Huellkreis
3047
    OSD_Element_HomeCircleX( 64, 38, 26, 22 );                              // leicht erweiterter Huellkreis
3048
 
3049
    lcd_frect( (9*6)-3+xoffs, (4*8)-2+yoffs, (3*6)+4, (1*8)+2, 0);          // inner clear
3050
    lcd_rect ( (9*6)-4+xoffs, (4*8)-3+yoffs, (3*6)+6, (1*8)+4, 1);          // inner rect
3051
    lcd_frect(  61+xoffs, 57+yoffs, 2, 2, 1);                               // bottom mini rect
3052
 
3053
    degree  = (int16_t)heading_home;
3054
    minus   = false;
3055
    if( degree >= 180 ) degree = 360 - degree;
3056
    else                minus = true;
3057
 
3058
    writex_ndigit_number_u( 9, 4, degree, 3, 0,MNORMAL, xoffs+1,yoffs);         // Degree (Winkel)
3059
 
3060
    if( minus && degree != 0 )
3061
        lcd_line( (9*6)-2+xoffs, (4*8)+3+yoffs, (9*6)-1+xoffs, (4*8)+3+yoffs, 1);
3062
 
3063
 
3064
    //-----------------
3065
    // Variometer
3066
    //-----------------
3067
    // OG: Variometer wird erstmal nicht angezeigt weil es den Screen zu voll macht
3068
    //     wenn doch muessen erst grafische Anpassungen an den Variometer-Code gemacht
3069
    //     werden
3070
    //void draw_variometer (uint8_t x, uint8_t y, uint8_t width, uint8_t hight, int16_t variometer)
3071
    //draw_variometer( 95, 38,  7, 30, naviData->Variometer);
3072
    //draw_variometer( 94, 38,  7, 21, naviData->Variometer);
3073
    //draw_variometer2( 94, 28,  7, 21, naviData->Variometer);
3074
 
3075
    //-----------------
3076
    // Flags
3077
    //-----------------
3078
    OSD_Element_Flag(  16, 2, OSD_FLAG_BA, -3, 0);  // MK Batt Warning
3079
    OSD_Element_Flag(  19, 2, OSD_FLAG_CF,  0, 0);  // Carefree
3080
    OSD_Element_Flag(  19, 4, OSD_FLAG_AH,  0,-3);  // Altitude Hold
3081
    OSD_Element_Flag(  19, 6, OSD_FLAG_PH,  0,-6);  // Position Hold
3082
    OSD_Element_Flag(  19, 7, OSD_FLAG_CH,  0,-1);  // Coming Home
3083
    OSD_Element_Flag(  16, 7, OSD_FLAG_S0, -3,-1);  // GPS-Sat not ok (GPS NOT ok)
3084
 
3085
 
3086
    #ifdef USE_OSD_DEMO
3087
        //-----------------
3088
        // Flags
3089
        //-----------------
3090
        OSD_Element_Flag_Label(  16, 2, OSD_FLAG_BA, true, -3,0);   // DEMO
3091
 
3092
        OSD_Element_Flag_Label(  19, 2, OSD_FLAG_CF, true, 0,0);    // DEMO
3093
        OSD_Element_Flag_Label(  19, 4, OSD_FLAG_AH, true, 0,-3);   // DEMO
3094
        OSD_Element_Flag_Label(  19, 6, OSD_FLAG_PH, true, 0,-6);   // DEMO
3095
        OSD_Element_Flag_Label(  19, 7, OSD_FLAG_CH, true, 0,-1);   // DEMO
3096
 
3097
        OSD_Element_Flag_Label(  16, 7, OSD_FLAG_S0, true, -3,-1);  // DEMO
3098
    #endif
3099
}
3100
#endif // USE_OSD_SCREEN_NAVIGATION
3101
 
3102
 
3103
 
3104
 
3105
//--------------------------------------------------------------
3106
// OSD-Screen "OSD_Screen_Waypoints_OLD"
3107
//
3108
// alte, alternative Variante - wenn sich die neue Variante
3109
// durchsetzt kann das hier geloescht werden
3110
//--------------------------------------------------------------
3111
#ifdef USE_OSD_SCREEN_WAYPOINTS
3112
/*
3113
void OSD_Screen_Waypoints_OLD( void )
3114
{
3115
    int8_t xoffs, yoffs;
3116
 
3117
    //-----------------------------------------
3118
    // REDRAW
3119
    // statische Screen Elemente die nicht
3120
    // jedesmal neu gezeichnet werden muessen
3121
    //-----------------------------------------
3122
    if( OSDScreenRefresh == OSD_SCREEN_REDRAW )
3123
    {
3124
        // do things here for static screen elements like labels and so....
3125
 
3126
        lcd_line(  (6*6-3),  0,  (6*6-3), 11, 1);                       // Linie Vertikal links
3127
        lcd_line( (15*6+5),  0, (15*6+5), 11, 1);                       // Linie Vertikal rechts
3128
        //lcd_line(        0, 12,      127, 12, 1);                     // Linie Horizontal
3129
 
3130
        lcd_rect_round( 0, 12, 127, 63-19+7, 1, R2);                    // Rahmen
3131
 
3132
        lcd_line(        0, 12+25,      127, 12+25, 1);                 // Trennlinie in der Mitte
3133
 
3134
        draw_icon_home( 7, 18);
3135
        draw_icon_target_round( 7, 45);
3136
        //draw_icon_target_diamond( 7, 45);                             // Alternative fuer draw_icon_target_round()
3137
    }
3138
 
3139
 
3140
    //-----------------
3141
    // Oben: Batt Level (Volt)
3142
    //-----------------
3143
    OSD_Element_BattLevel2( 0, 0, 0,0 );
3144
 
3145
    //-----------------
3146
    // Oben: Batt Level Bar
3147
    //-----------------
3148
    //OSD_Element_Battery_Bar( x, y, length, width, orientation)
3149
    OSD_Element_Battery_Bar( 0, 9, 30, 1, ORIENTATION_H);
3150
 
3151
    //-----------------
3152
    // Oben: Kompass Rose
3153
    //-----------------
3154
    //draw_compass( 6, 0, (naviData->CompassHeading)%360, 2,0);
3155
 
3156
    //-----------------
3157
    // Oben: Flugzeit
3158
    //-----------------
3159
    writex_time(16, 0, naviData->FlyingTime, MNORMAL, 2,0);
3160
 
3161
    //-----------------
3162
    // Home: Hoehe
3163
    //-----------------
3164
    xoffs = 6;
3165
    yoffs = 0;
3166
    writex_altimeter( 7, 2, naviData->Altimeter, MNORMAL, xoffs,yoffs );
3167
    lcdx_printp_at( 3, 2, PSTR("Al:"), MNORMAL, xoffs+2,yoffs);
3168
 
3169
    //-----------------
3170
    // Home: Steigen / Sinken
3171
    //-----------------
3172
    OSD_Element_UpDown( 13, 2, -2,yoffs);
3173
 
3174
    //-----------------
3175
    // Home: Distance
3176
    //-----------------
3177
    yoffs = 2;
3178
    lcdx_printp_at( 3, 3, PSTR("Ho:"), MNORMAL, xoffs+2,yoffs);
3179
    writex_ndigit_number_u( 7, 3, naviData->HomePositionDeviation.Distance / 10, 4, 0,MNORMAL, xoffs,yoffs);
3180
    lcdx_printp_at(11, 3, PSTR("m"), MNORMAL, xoffs+4,yoffs);       // Home
3181
 
3182
    //-----------------
3183
    // Home: Circle
3184
    //-----------------
3185
    xoffs = 2;
3186
    yoffs = 3;
3187
 
3188
  //OSD_Element_HomeCircleX( px, py, rx, ry )
3189
  //OSD_Element_HomeCircleX( 64, 38, 26, 22 );                              // leicht erweiterter Huellkreis
3190
    OSD_Element_HomeCircleX( 112, 24, 10, 8 );                              // leicht erweiterter Huellkreis
3191
 
3192
  //lcd_frect(  112-1, 33, 2, 1, 1);                               // bottom mini rect
3193
    lcd_frect(  112-1, 33, 2, 0, 1);                               // bottom mini rect
3194
    lcd_frect(  112-0, 33, 0, 1, 1);                               // bottom mini rect
3195
 
3196
 
3197
    //-----------------
3198
    // WP: Waypoint-Index und Anzahl der Waypoint's
3199
    //-----------------
3200
    xoffs = 6;
3201
    yoffs = 2;
3202
    lcdx_printp_at( 3, 5, PSTR("WP:"), MNORMAL, xoffs+2,yoffs);
3203
 
3204
    uint8_t wpindex = naviData->WaypointIndex;
3205
    if( naviData->WaypointNumber==0 ) wpindex = 0;
3206
 
3207
    lcdx_printf_at_P( 7, 5, MNORMAL, xoffs,yoffs, PSTR("%2d/%2d"), wpindex, naviData->WaypointNumber );
3208
 
3209
 
3210
    //-----------------
3211
    // Sat Anzahl
3212
    //-----------------
3213
    writex_ndigit_number_u( 17, 5, naviData->SatsInUse, 2, 0,MNORMAL,  0,2);
3214
    draw_icon_satmini( 117, 42);
3215
 
3216
 
3217
    //-----------------
3218
    // WP: Distance
3219
    //-----------------
3220
    yoffs = 4;
3221
    lcdx_printp_at( 3, 6, PSTR("Di:"), MNORMAL, xoffs+2,yoffs);
3222
    writex_ndigit_number_u( 7, 6, naviData->TargetPositionDeviation.Distance / 10, 4, 0,MNORMAL, xoffs,yoffs);
3223
    lcdx_printp_at( 11, 6, PSTR("m"), MNORMAL, xoffs+4,yoffs);       //
3224
 
3225
    //-----------------
3226
    // WP: Hoehe
3227
    // Anmerkung OG: macht nicht so wirklich Sinn denke ich
3228
    //-----------------
3229
  //writex_ndigit_number_u( 14, 6, naviData->TargetPosition.Altitude / 1000, 4, 0,MNORMAL, xoffs,yoffs);
3230
  //lcdx_printp_at( 18, 6, PSTR("m"), MNORMAL, xoffs+4,yoffs);       //
3231
 
3232
 
3233
    //-----------------
3234
    // Oben: Flags
3235
    //-----------------
3236
    // Variante 1: PH, CH, CF
3237
  //OSD_Element_Flag(  7, 0, OSD_FLAG_PH, -2,1);  // Position Hold
3238
  //OSD_Element_Flag(  9, 0, OSD_FLAG_CH,  5,1);  // Coming Home
3239
  //OSD_Element_Flag( 12, 0, OSD_FLAG_CF,  6,1);  // Carefree
3240
 
3241
    // Variante 2: CF, CH, TR
3242
    OSD_Element_Flag(  7, 0, OSD_FLAG_CF, -2,1);  // Carefree
3243
    OSD_Element_Flag(  9, 0, OSD_FLAG_CH,  5,1);  // Coming Home
3244
    OSD_Element_Flag( 12, 0, OSD_FLAG_TR,  6,1);  // Target Reached
3245
 
3246
 
3247
    // Variante: TR neben Waypoint-Anzahl
3248
  //OSD_Element_Flag( 13, 5, OSD_FLAG_TR,  6,2);  // Target Reached
3249
 
3250
 
3251
    //-----------------
3252
    // ggf. BEEP wenn WP erreicht
3253
    //-----------------
3254
    Beep_Waypoint();
3255
}
3256
*/
3257
#endif // USE_OSD_SCREEN_WAYPOINTS
3258
 
3259
 
3260
 
3261
//--------------------------------------------------------------
3262
// OSD-Screen "Waypoints"
3263
//
3264
// aktuelle Variante!
3265
//--------------------------------------------------------------
3266
#ifdef USE_OSD_SCREEN_WAYPOINTS
3267
void OSD_Screen_Waypoints( void )
3268
{
3269
    int8_t  xoffs, yoffs;
3270
    uint8_t v;
3271
 
3272
    //-----------------------------------------
3273
    // REDRAW
3274
    // statische Screen Elemente die nicht
3275
    // jedesmal neu gezeichnet werden muessen
3276
    //-----------------------------------------
3277
    if( OSDScreenRefresh == OSD_SCREEN_REDRAW )
3278
    {
3279
        // do things here for static screen elements like labels and so....
3280
 
3281
        lcd_line(  (6*6-3),  0,  (6*6-3), 11, 1);                       // Linie Vertikal links
3282
        lcd_line( (15*6+5),  0, (15*6+5), 11, 1);                       // Linie Vertikal rechts
3283
        //lcd_line(        0, 12,      127, 12, 1);                     // Linie Horizontal
3284
 
3285
        lcd_rect_round( 0, 12, 127, 63-19+7, 1, R2);                    // Rahmen
3286
 
3287
        lcd_line(       0, 12+25, (15*6+5), 12+25, 1);                  // Trennlinie in der Mitte
3288
        lcd_line( (15*6+5),  12+25, (15*6+5), 63, 1);                   // Linie Vertikal rechts, unten
3289
        lcd_plot ((15*6+5),  12+25, 0);
3290
 
3291
        draw_icon_home( 7, 18);
3292
        draw_icon_target_round( 7, 45);
3293
        //draw_icon_target_diamond( 7, 45);                             // Alternative fuer draw_icon_target_round()
3294
    }
3295
 
3296
 
3297
    //-----------------
3298
    // Oben,Links: Batt Level (Volt)
3299
    //-----------------
3300
    OSD_Element_BattLevel2( 0, 0, 0,0 );
3301
 
3302
    //-----------------
3303
    // Oben,Links: Batt Level Bar
3304
    //-----------------
3305
    //OSD_Element_Battery_Bar( x, y, length, width, orientation)
3306
    OSD_Element_Battery_Bar( 0, 9, 30, 1, ORIENTATION_H);
3307
 
3308
    //-----------------
3309
    // Oben,Rechts: Flugzeit
3310
    //-----------------
3311
    writex_time(16, 0, naviData->FlyingTime, MNORMAL, 2,0);
3312
 
3313
    //-----------------
3314
    // Oben,Mitte: Flags
3315
    //-----------------
3316
    // Variante 1: PH, CH, CF
3317
  //OSD_Element_Flag(  7, 0, OSD_FLAG_PH, -2,1);  // Position Hold
3318
  //OSD_Element_Flag(  9, 0, OSD_FLAG_CH,  5,1);  // Coming Home
3319
  //OSD_Element_Flag( 12, 0, OSD_FLAG_CF,  6,1);  // Carefree
3320
 
3321
    // Variante 2: CF, CH, TR
3322
    OSD_Element_Flag(  7, 0, OSD_FLAG_CF, -2,1);  // Carefree
3323
    OSD_Element_Flag(  9, 0, OSD_FLAG_CH,  5,1);  // Coming Home
3324
    OSD_Element_Flag( 12, 0, OSD_FLAG_TR,  6,1);  // Target Reached
3325
 
3326
 
3327
 
3328
    //-----------------
3329
    // Home: Hoehe
3330
    //-----------------
3331
    xoffs = 5;
3332
    yoffs = 0;
3333
    writex_altimeter( 7, 2, naviData->Altimeter, MNORMAL, xoffs,yoffs );
3334
    lcdx_printp_at( 3, 2, PSTR("Al:"), MNORMAL, xoffs+3,yoffs);
3335
 
3336
    //-----------------
3337
    // Home: Steigen / Sinken
3338
    //-----------------
3339
    OSD_Element_UpDown( 13, 2, -3,yoffs);
3340
 
3341
    //-----------------
3342
    // Home: Distance
3343
    //-----------------
3344
    yoffs = 2;
3345
    lcdx_printp_at( 3, 3, PSTR("Ho:"), MNORMAL, xoffs+3,yoffs);
3346
    writex_ndigit_number_u( 7, 3, naviData->HomePositionDeviation.Distance / 10, 4, 0,MNORMAL, xoffs,yoffs);
3347
    lcdx_printp_at(11, 3, PSTR("m"), MNORMAL, xoffs+4,yoffs);       // Home
3348
 
3349
    //-----------------
3350
    // Home: Circle
3351
    //-----------------
3352
    // orginal
3353
    //OSD_Element_HomeCircleX( 110, 25, 11, 9 );                     // leicht erweiterter Huellkreis
3354
    //lcd_frect(  112-3, 35, 2, 1, 1);                               // bottom mini rect
3355
 
3356
    // 1 pixel weiter links
3357
    OSD_Element_HomeCircleX( 109, 25, 11, 9 );                     // leicht erweiterter Huellkreis
3358
    lcd_frect(  112-4, 35, 2, 1, 1);                               // bottom mini rect
3359
 
3360
    // etwas groesser
3361
    //OSD_Element_HomeCircleX( 109, 26, 12, 10 );                     // leicht erweiterter Huellkreis
3362
    //lcd_frect(  112-4, 37, 2, 1, 1);                               // bottom mini rect
3363
 
3364
    //-----------------
3365
    // Home: Sat Anzahl
3366
    //-----------------
3367
    //yoffs = -2; // alternativ
3368
    yoffs = 0;
3369
    //naviData->SatsInUse = 10;
3370
    writex_ndigit_number_u( 17, 5, naviData->SatsInUse, 2, 0,MNORMAL,  -1,2+yoffs);
3371
    draw_icon_satmini( 115, 42+yoffs);
3372
 
3373
 
3374
 
3375
    //-----------------
3376
    // WP: Waypoint-Index und Anzahl der Waypoint's
3377
    //-----------------
3378
    xoffs = 5;
3379
    yoffs = 2;
3380
    lcdx_printp_at( 3, 5, PSTR("WP:"), MNORMAL, xoffs+3,yoffs);
3381
 
3382
    v = naviData->WaypointIndex;
3383
    if( naviData->WaypointNumber==0 ) v = 0;
3384
 
3385
    lcdx_printf_at_P( 7, 5, MNORMAL, xoffs,yoffs, PSTR("%2d/%2d"), v, naviData->WaypointNumber );
3386
 
3387
 
3388
    //-----------------
3389
    // WP: Countdown Target-Holdtime
3390
    //-----------------
3391
    xoffs = 6;
3392
    yoffs = 2;
3393
 
3394
    v = naviData->TargetHoldTime;
3395
    if( v > 0 )
3396
    {
3397
        lcdx_printf_at_P( 12, 5, MINVERS, xoffs+2,yoffs, PSTR("%2d"), v );
3398
        lcd_line(        (12*6)+xoffs+2, (5*8)+yoffs-1, (12*6)+xoffs+2+11, (5*8)+yoffs-1, 1);
3399
        lcd_line(        (12*6)+xoffs+1, (5*8)+yoffs-1, (12*6)+xoffs+1, (5*8)+yoffs+7, 1);
3400
    }
3401
    else
3402
    {
3403
        lcd_frect( (12*6)+xoffs+1, (5*8)+yoffs-1,  (2*8)-3, 8, 0);
3404
    }
3405
 
3406
 
3407
    //-----------------
3408
    // WP: Distance
3409
    //-----------------
3410
    xoffs = 5;
3411
    yoffs = 4;
3412
    lcdx_printp_at( 3, 6, PSTR("Di:"), MNORMAL, xoffs+3,yoffs);
3413
    writex_ndigit_number_u( 7, 6, naviData->TargetPositionDeviation.Distance / 10, 4, 0,MNORMAL, xoffs,yoffs);
3414
    lcdx_printp_at( 11, 6, PSTR("m"), MNORMAL, xoffs+4,yoffs);       //
3415
 
3416
    //-----------------
3417
    // WP: Hoehe
3418
    // Anmerkung OG: macht nicht so wirklich Sinn denke ich
3419
    //-----------------
3420
  //writex_ndigit_number_u( 14, 6, naviData->TargetPosition.Altitude / 1000, 4, 0,MNORMAL, xoffs,yoffs);
3421
  //lcdx_printp_at( 18, 6, PSTR("m"), MNORMAL, xoffs+4,yoffs);       //
3422
 
3423
 
3424
 
3425
 
3426
    //-----------------
3427
    // ggf. BEEP wenn WP erreicht
3428
    //-----------------
3429
    Beep_Waypoint();
3430
}
3431
#endif // USE_OSD_SCREEN_WAYPOINTS
3432
 
3433
 
3434
 
3435
//--------------------------------------------------------------
3436
// OSD-Screen "User GPS"
3437
//
3438
// OSDScreenRefresh:    OSD_SCREEN_REFESH = update values
3439
//                  OSD_SCREEN_REDRAW = redraw labels and update values
3440
//--------------------------------------------------------------
3441
#ifdef USE_OSD_SCREEN_USERGPS
3442
void OSD_Screen_UserGPS( void )
3443
{
3444
    uint8_t y, i;
3445
    int8_t      yoffs;
3446
    uint8_t show_gps_altitude = 0;  // 1=GPS-Höhe anzeigen; 0=barymetrische Höhe anzeigen
3447
 
3448
 
3449
    //-----------------------------------------
3450
    // REDRAW
3451
    // statische Screen Elemente die nicht
3452
    // jedesmal neu gezeichnet werden muessen
3453
    //-----------------------------------------
3454
    if( OSDScreenRefresh == OSD_SCREEN_REDRAW )
3455
    {
3456
        // do things here for static screen elements like labels and so....
3457
        lcd_line(  (6*6-3), 0, (6*6-3), 9, 1);                      // Linie vertikal oben, links
3458
        lcd_line( (15*6+3), 0, (15*6+3), 9, 1);                     // Linie vertikal oben, rechts
3459
        lcd_rect_round( 0, 9, 127, 63-9, 1, R2);                    // Rahmen
3460
        lcdx_printp_at( 6, 0, PSTR("UGPS"), MNORMAL, 2,0);
3461
    }
3462
 
3463
 
3464
    //-----------------
3465
    // Oben: Batt Level (Volt)
3466
    //-----------------
3467
    OSD_Element_BattLevel2( 0, 0, 0,0 );
3468
 
3469
    //-----------------
3470
    // Oben: Sat Ok
3471
    //-----------------
3472
    OSD_Element_Flag(  12, 0, OSD_FLAG_S0, 5,0);    // GPS-Sat not ok (GPS NOT ok)
3473
 
3474
    //-----------------
3475
    // Oben: Flugzeit
3476
    //-----------------
3477
    writex_time( 16, 0, naviData->FlyingTime, MNORMAL, 2,0);
3478
 
3479
    //-----------------
3480
    // die letzen 3 User-GPS Daten anzeigen
3481
    //-----------------
3482
    yoffs = -4;
3483
    for(i=0; i<3; i++)
3484
    {
3485
        y = (i*2)+2;
3486
        lcd_frect( 0, (y*8)+yoffs-1, 127, 7, 1);                                // inverser Hintergrund
3487
 
3488
        writex_ndigit_number_u( 0, y+0, (i+1), 1, 0 , MINVERS, 4,yoffs);        // Index
3489
        writex_datetime_time(   4, y+0, Config.GPS_User[i].timestamp, MINVERS, 0,yoffs);
3490
 
3491
        //writex_time(    3, y+0, GPS_User[i].time_pkt, MINVERS, 0,yoffs);
3492
        //lcdx_printp_at( 12, y+0, PSTR("Alt:")     , MINVERS, 0,yoffs);
3493
        lcdx_printp_at( 20, y+0, PSTR("m")          , MINVERS, 0,yoffs);
3494
 
3495
        if( show_gps_altitude )                                                 // GPS-Hoehe oder barymetrische Hoehe?
3496
        {
3497
            // GPS Hoehe
3498
            //lcdx_printp_at( 10, y+0, PSTR("G"), MINVERS, 2,yoffs);
3499
            //lcd_frect( (12*6)-4, (y*8)+3+yoffs, 1, 1, 0);
3500
            writex_ndigit_number_s( 16, y+0, Config.GPS_User[i].GPSData.Altitude/1000, 4, 0, MINVERS, 0,yoffs); // GPS Hoehe in Meter
3501
        }
3502
        else
3503
        {
3504
            // barymetrische Hoehe
3505
            //lcdx_printp_at( 10, y+0, PSTR("B"), MINVERS, 2,yoffs);
3506
            //lcd_frect( (12*6)-4, (y*8)+3+yoffs, 1, 1, 0);
3507
            writex_altimeter( 16, y+0, Config.GPS_User[i].Altimeter, MINVERS, 0,yoffs );
3508
        }
3509
 
3510
        lcd_line( 1, (y*8)+yoffs+7, 125, (y*8)+yoffs+7, 0);                     // clear: Invers unterste Linie
3511
 
3512
        writex_gpspos(  1, y+1, Config.GPS_User[i].GPSData.Latitude , MNORMAL, 0,yoffs);        // GPS Lat
3513
        writex_gpspos( 12, y+1, Config.GPS_User[i].GPSData.Longitude, MNORMAL, 0,yoffs);        // GPS Long
3514
        //writex_gpspos(  1, y+1, GPS_User[i].GPSData.Latitude + 12867000, MNORMAL, 0,yoffs);   // DUMMY DATEN! DEMO!
3515
        //writex_gpspos( 12, y+1, GPS_User[i].GPSData.Longitude+ 8568000, MNORMAL, 0,yoffs);    // DUMMY DATEN! DEMO!
3516
 
3517
        yoffs++;
3518
    }
3519
}
3520
#endif // USE_OSD_SCREEN_USERGPS
3521
 
3522
 
3523
 
3524
//--------------------------------------------------------------
3525
// OSD-Screen "Status"
3526
//
3527
// OSDScreenRefresh:    0 = update values
3528
//              1 = redraw labels and update values
3529
//--------------------------------------------------------------
3530
#ifdef USE_OSD_SCREEN_MKSTATUS
3531
void OSD_Screen_MKStatus( void )
3532
{
3533
    int8_t      xoffs, yoffs;
3534
 
3535
    //-----------------------------------------
3536
    // REDRAW
3537
    // statische Screen Elemente die nicht
3538
    // jedesmal neu gezeichnet werden muessen
3539
    //-----------------------------------------
3540
    if( OSDScreenRefresh == OSD_SCREEN_REDRAW )
3541
    {
3542
        // do things here for static screen elements like labels and so....
3543
 
3544
        lcd_line(  (6*6-3), 0, (6*6-3), 9, 1);                      // Linie vertikal oben, links
3545
        lcd_line( (15*6+3), 0, (15*6+3), 9, 1);                     // Linie vertikal oben, rechts
3546
        lcd_rect_round( 0, 10, 127, 63-10, 1, R2);                  // Rahmen
3547
 
3548
        lcdx_printp_at( 12,0 , PSTR("mAh"), MNORMAL, -1,0);         // "mAh" (entnommene Kapazität)
3549
    }
3550
 
3551
 
3552
    //-----------------
3553
    // Oben: Batt Level (Volt)
3554
    //-----------------
3555
    OSD_Element_BattLevel2( 0, 0, 0,0 );
3556
 
3557
    //-----------------
3558
    // Strom
3559
    //-----------------
3560
    //writex_ndigit_number_u_10th( 7, 0, naviData->Current, 4, 0,MNORMAL, 1,0);  // Strom mit Nachkomma
3561
 
3562
    //-----------------
3563
    // entnommene Kapazitaet (mAh)
3564
    //-----------------
3565
    drawmode = (naviData->UsedCapacity > Config.OSD_mAh_Warning ? MINVERS : MNORMAL);
3566
    //writex_ndigit_number_u( 7, 0, naviData->UsedCapacity * 10, 5, 0, drawmode, -3,0);  // DEBUG
3567
    writex_ndigit_number_u( 7, 0, naviData->UsedCapacity, 5, 0, drawmode, -3,0);
3568
 
3569
    //-----------------
3570
    // Oben: Flugzeit
3571
    //-----------------
3572
    writex_time( 16, 0, naviData->FlyingTime, MNORMAL, 2,0);
3573
 
3574
    //-----------------
3575
    // Flags
3576
    //-----------------
3577
    yoffs = -2;
3578
    xoffs = -7;
3579
    OSD_Element_Flag(  19, 2, OSD_FLAG_CF,  0+xoffs, 0+yoffs);  // Carefree
3580
    OSD_Element_Flag(  19, 4, OSD_FLAG_AH,  0+xoffs,-3+yoffs);  // Altitude Hold
3581
    OSD_Element_Flag(  19, 6, OSD_FLAG_PH,  0+xoffs,-6+yoffs);  // Position Hold
3582
    OSD_Element_Flag(  19, 7, OSD_FLAG_CH,  0+xoffs,-1+yoffs);  // Coming Home
3583
 
3584
    xoffs -= 4;
3585
    OSD_Element_Flag(  16, 2, OSD_FLAG_BA, -3+xoffs, 0+yoffs);  // MK Batt Warning
3586
    OSD_Element_Flag(  16, 4, OSD_FLAG_EL, -3+xoffs,-3+yoffs);  // Emergency Landing
3587
    OSD_Element_Flag(  16, 6, OSD_FLAG_RL, -3+xoffs,-6+yoffs);  // Range Limit
3588
    OSD_Element_Flag(  16, 7, OSD_FLAG_S0, -3+xoffs,-1+yoffs);  // GPS-Sat not ok (GPS NOT ok)
3589
 
3590
    xoffs -= 4;
3591
    OSD_Element_Flag(  12, 2, OSD_FLAG_CA,  0+xoffs, 0+yoffs);  // Calibrate
3592
    OSD_Element_Flag(  12, 4, OSD_FLAG_ST,  0+xoffs,-3+yoffs);  // Start
3593
    OSD_Element_Flag(  12, 6, OSD_FLAG_MR,  0+xoffs,-6+yoffs);  // Motor Run
3594
    OSD_Element_Flag(  12, 7, OSD_FLAG_FY,  0+xoffs,-1+yoffs);  // Fly
3595
 
3596
    xoffs -= 4;
3597
    OSD_Element_Flag(   9, 2, OSD_FLAG_O1, -2+xoffs, 0+yoffs);  // Out1
3598
    OSD_Element_Flag(   9, 4, OSD_FLAG_O2, -2+xoffs,-3+yoffs);  // Out2
3599
    OSD_Element_Flag(   9, 6, OSD_FLAG_TR, -2+xoffs,-6+yoffs);  // Target Reached
3600
    OSD_Element_Flag(   9, 7, OSD_FLAG_MC, -2+xoffs,-1+yoffs);  // Manual Control
3601
 
3602
    xoffs -= 4;
3603
    OSD_Element_Flag(   6, 2, OSD_FLAG_TU, -4+xoffs, 0+yoffs);  // Vario Trim Up
3604
    OSD_Element_Flag(   6, 4, OSD_FLAG_TD, -4+xoffs,-3+yoffs);  // Vario Trim Down
3605
    OSD_Element_Flag(   6, 6, OSD_FLAG_FR, -4+xoffs,-6+yoffs);  // Free
3606
    OSD_Element_Flag(   6, 7, OSD_FLAG_SL, -4+xoffs,-1+yoffs);  // No Serial Link
3607
 
3608
 
3609
    #ifdef USE_OSD_DEMO
3610
        //-----------------
3611
        // Flags
3612
        //-----------------
3613
 /*
3614
        PSTR("AH"),  // OSD_FLAG_AH  Altitue Hold
3615
        PSTR("PH"),  // OSD_FLAG_PH  Position Hold
3616
        PSTR("CF"),  // OSD_FLAG_CF  Care Free
3617
        PSTR("CH"),  // OSD_FLAG_CH  Coming Home
3618
        PSTR("o1"),  // OSD_FLAG_O1  Out1
3619
        PSTR("o2"),  // OSD_FLAG_O2  Out2
3620
        PSTR("BA"),  // OSD_FLAG_BA  LowBat warning (MK)
3621
        PSTR("CA"),  // OSD_FLAG_CA  Calibrate
3622
        PSTR("ST"),  // OSD_FLAG_ST  Start
3623
        PSTR("MR"),  // OSD_FLAG_MR  Motor Run
3624
        PSTR("FY"),  // OSD_FLAG_FY  Fly
3625
        PSTR("EL"),  // OSD_FLAG_EL  Emergency Landing
3626
        PSTR("FS"),  // OSD_FLAG_FS  RX Failsave Active
3627
        PSTR("GP"),  // OSD_FLAG_GP  GPS Ok
3628
        PSTR("S!")   // OSD_FLAG_S0  GPS-Sat not ok (GPS NOT ok)
3629
        PSTR("TU"),  // OSD_FLAG_TU  Vario Trim Up
3630
        PSTR("TD"),  // OSD_FLAG_TD  Vario Trim Down
3631
        PSTR("FR"),  // OSD_FLAG_FR  Free
3632
        PSTR("RL"),  // OSD_FLAG_RL  Range Limit
3633
        PSTR("SL"),  // OSD_FLAG_SL  No Serial Link
3634
        PSTR("TR"),  // OSD_FLAG_TR  Target Reached
3635
        PSTR("MC")   // OSD_FLAG_MC  Manual Control
3636
*/
3637
        yoffs = -2;
3638
        xoffs = -7;
3639
        OSD_Element_Flag_Label(  19, 2, OSD_FLAG_CF, true,  0+xoffs, 0+yoffs);  // DEMO: Carefree
3640
        OSD_Element_Flag_Label(  19, 4, OSD_FLAG_AH, true,  0+xoffs,-3+yoffs);  // DEMO: Altitude Hold
3641
        OSD_Element_Flag_Label(  19, 6, OSD_FLAG_PH, true,  0+xoffs,-6+yoffs);  // DEMO: Position Hold
3642
        OSD_Element_Flag_Label(  19, 7, OSD_FLAG_CH, true,  0+xoffs,-1+yoffs);  // DEMO: Coming Home
3643
 
3644
        xoffs -= 4;
3645
        OSD_Element_Flag_Label(  16, 2, OSD_FLAG_BA, true, -3+xoffs, 0+yoffs);  // DEMO: MK Batt Warning
3646
        OSD_Element_Flag_Label(  16, 4, OSD_FLAG_EL, true, -3+xoffs,-3+yoffs);  // DEMO: Emergency Landing
3647
        OSD_Element_Flag_Label(  16, 6, OSD_FLAG_RL, true, -3+xoffs,-6+yoffs);  // DEMO: Range Limit
3648
        OSD_Element_Flag_Label(  16, 7, OSD_FLAG_S0, true, -3+xoffs,-1+yoffs);  // DEMO: GPS-Sat not ok (GPS NOT ok)
3649
 
3650
        xoffs -= 4;
3651
        OSD_Element_Flag_Label(  12, 2, OSD_FLAG_CA, true,  0+xoffs, 0+yoffs);  // DEMO: Calibrate
3652
        OSD_Element_Flag_Label(  12, 4, OSD_FLAG_ST, true,  0+xoffs,-3+yoffs);  // DEMO: Start
3653
        OSD_Element_Flag_Label(  12, 6, OSD_FLAG_MR, true,  0+xoffs,-6+yoffs);  // DEMO: Motor Run
3654
        OSD_Element_Flag_Label(  12, 7, OSD_FLAG_FY, true,  0+xoffs,-1+yoffs);  // DEMO: Fly
3655
 
3656
        xoffs -= 4;
3657
        OSD_Element_Flag_Label(   9, 2, OSD_FLAG_O1, true, -2+xoffs, 0+yoffs);  // DEMO: Out1
3658
        OSD_Element_Flag_Label(   9, 4, OSD_FLAG_O2, true, -2+xoffs,-3+yoffs);  // DEMO: Out2
3659
        OSD_Element_Flag_Label(   9, 6, OSD_FLAG_TR, true, -2+xoffs,-6+yoffs);  // DEMO: Target Reached
3660
        OSD_Element_Flag_Label(   9, 7, OSD_FLAG_MC, true, -2+xoffs,-1+yoffs);  // DEMO: Manual Control
3661
 
3662
        xoffs -= 4;
3663
        OSD_Element_Flag_Label(   6, 2, OSD_FLAG_TU, true, -4+xoffs, 0+yoffs);  // DEMO: Vario Trim Up
3664
        OSD_Element_Flag_Label(   6, 4, OSD_FLAG_TD, true, -4+xoffs,-3+yoffs);  // DEMO: Vario Trim Down
3665
        OSD_Element_Flag_Label(   6, 6, OSD_FLAG_FR, true, -4+xoffs,-6+yoffs);  // DEMO: Free
3666
        OSD_Element_Flag_Label(   6, 7, OSD_FLAG_SL, true, -4+xoffs,-1+yoffs);  // DEMO: No Serial Link
3667
 
3668
    #endif
3669
}
3670
#endif // USE_OSD_SCREEN_MKSTATUS
3671
 
3672
 
3673
 
3674
//--------------------------------------------------------------
3675
// OSD_Screen_Electric()
3676
//
3677
// Anzeige BL-Temperaturen und Stroeme
3678
//--------------------------------------------------------------
3679
#ifdef USE_OSD_SCREEN_ELECTRIC
3680
void OSD_Screen_Electric( void )
3681
{
3682
    uint8_t x, y, x0, y0;
3683
    int8_t  yoffs;
3684
 
3685
    //-----------------------------------------
3686
    // REDRAW
3687
    // statische Screen Elemente die nicht
3688
    // jedesmal neu gezeichnet werden muessen
3689
    //-----------------------------------------
3690
    if( OSDScreenRefresh == OSD_SCREEN_REDRAW )
3691
    {
3692
        // do things here for static screen elements like labels and so....
3693
        lcd_line (33, 0, 33, 19, 1);                                // Linie vertikal oben, links
3694
        lcd_line (93, 0, 93, 19, 1);                                // Linie vertikal oben, rechts
3695
 
3696
        lcd_rect_round( 0, 19, 127, 63-19, 1, R2);                  // Rahmen
3697
        lcd_line (0, 41, 127, 41, 1);                               // Linie horizontal mitte
3698
 
3699
        lcdx_printp_at( 12,0 , PSTR("mAh"), MNORMAL, -1,0);         // entnommene Kapazität
3700
        lcdx_printp_at( 12,1 , PSTR("A")  , MNORMAL, -1,2);         // aktueller Strom
3701
 
3702
        writex_ndigit_number_u( 19, 1, cells, 1, 0, MNORMAL, 2,2);  // LiPO Cells Wert
3703
        lcdx_printp_at( 20,1 , PSTR("s")          , MNORMAL, 2,2);  // LiPO Cells "s"
3704
 
3705
    } // end: if( OSDScreenRefresh == OSD_SCREEN_REDRAW )
3706
    //-----------------------------------------
3707
 
3708
 
3709
    //-----------------
3710
    // Oben: Batt Level (Volt)
3711
    //-----------------
3712
    OSD_Element_BattLevel2( 0, 0, 0,0 );
3713
 
3714
    //-----------------
3715
    // Oben: Batt Level Bar
3716
    //-----------------
3717
    //OSD_Element_Battery_Bar( x, y, length, width, orientation)
3718
    OSD_Element_Battery_Bar( 0, 9, 30, 1, ORIENTATION_H);
3719
 
3720
    //-----------------
3721
    // Oben: entnommene Kapazitaet (mAh)
3722
    //-----------------
3723
    drawmode = (naviData->UsedCapacity > Config.OSD_mAh_Warning ? MINVERS : MNORMAL);
3724
    writex_ndigit_number_u( 7, 0, naviData->UsedCapacity, 5, 0, drawmode, -3,0);
3725
 
3726
    //-----------------
3727
    // Oben: Flugzeit
3728
    //-----------------
3729
    //writex_time(16, 0, naviData->FlyingTime+900, MNORMAL, 2,0);  // DEBUG
3730
    writex_time( 16, 0, naviData->FlyingTime, MNORMAL, 2,0);
3731
 
3732
    //-----------------
3733
    // Strom
3734
    //-----------------
3735
    writex_ndigit_number_u_10th( 7, 1, naviData->Current, 4, 0,MNORMAL, -3,2);  // Strom mit Nachkomma
3736
 
3737
    //-----------------
3738
    // BL 1-8 Temp & Strom
3739
    //-----------------
3740
    x0 = 1;
3741
    y0 = 4;
3742
    for( y=0; y<2; y++)                                 // 2 Zeilen (mit je 4 BL's/Motoren)
3743
    {
3744
        if( y==0 )  yoffs = -9;
3745
        else        yoffs = -3;
3746
 
3747
        for( x=0; x<4; x++)                             // und 4 BL's/Motoren pro Zeile
3748
        {
3749
            if( blData[y*4+x].Status & 0xf0 )           // BL/Motor vorhanden?
3750
            {
3751
                if( blData[y*4+x].Temperature != 0 )    // Anzeige nur wenn Temp != 0 wegen BL-Ctrl v1 die keine Temperatur senden
3752
                {
3753
                    writex_ndigit_number_u( (x*5)+x0,   (y*2)+y0+0, ( blData[y*4+x].Temperature ), 3, 0,MNORMAL, 0,yoffs);  // Temperatur
3754
                    lcdx_putc             ( (x*5)+3+x0, (y*2)+y0+0, SYMBOL_SMALLDEGREE                 ,MNORMAL, 1,yoffs);
3755
                }
3756
 
3757
                // Variante: mit Nachkommastellen
3758
                writex_ndigit_number_u_10th (   (x*5)+x0, (y*2)+y0+1, ( blData[y*4+x].Current), 3, 0, MNORMAL, 0,yoffs);        // Strom
3759
            }
3760
        }
3761
    }
3762
 
3763
    #ifdef USE_OSD_DEMO
3764
        OSD_Element_Flag_Label(  19, 1, OSD_FLAG_BA, true, 0,1);    // DEMO
3765
    #endif
3766
}
3767
#endif  // USE_OSD_SCREEN_ELECTRIC_N
3768
 
3769
 
3770
 
3771
 
3772
//--------------------------------------------------------------
3773
// OSD_Screen_Statistics()
3774
//--------------------------------------------------------------
3775
#ifdef USE_OSD_SCREEN_STATISTIC
3776
void OSD_Screen_Statistics( void )
3777
{
3778
    osd_BLmax_t blmax;
3779
    uint8_t line = 0;
3780
 
3781
 
3782
    // max. der BL's ermitteln
3783
    calc_BLmax( &blmax );
3784
 
3785
 
3786
    //---------------------------
3787
    // max Altitude
3788
    lcd_printp_at (0, line, strGet(STATS_ITEM_0), MNORMAL);
3789
    write_ndigit_number_s (14, line, Config.OSD_Statistic.max_Altimeter / (30 / AltimeterAdjust), 4, 0,MNORMAL);
3790
    lcdx_putc (18, line, 'm', MNORMAL, 2,0);
3791
 
3792
    //---------------------------
3793
    // max Speed
3794
    // max_GroundSpeed = 1;
3795
    lcd_printp_at (0, ++line, strGet(STATS_ITEM_1), MNORMAL);
3796
    write_ndigit_number_u (15, line, (uint16_t) (((uint32_t) Config.OSD_Statistic.max_GroundSpeed * (uint32_t) 9) / (uint32_t) 250), 3, 0,MNORMAL);
3797
    lcdx_printp_at(18, line, PSTR("kmh"), MNORMAL, 2,0);
3798
 
3799
    //---------------------------
3800
    // max Distance
3801
    // max_Distance = 64512;
3802
    lcd_printp_at (0, ++line, strGet(STATS_ITEM_2), MNORMAL);
3803
    write_ndigit_number_u (14, line, Config.OSD_Statistic.max_Distance / 10, 4, 0,MNORMAL);
3804
    lcdx_putc (18, line, 'm', MNORMAL, 2,0);
3805
 
3806
    //---------------------------
3807
    // min voltage
3808
    lcd_printp_at (0, ++line, strGet(STATS_ITEM_3), MNORMAL);
3809
    if( Config.OSD_Statistic.min_UBat==255 )
3810
        lcd_printp_at(14, line, PSTR("   0"), MNORMAL);
3811
    else
3812
        write_ndigit_number_u_10th (14, line, Config.OSD_Statistic.min_UBat, 3, 0,MNORMAL);
3813
    lcdx_putc (18, line, 'V', MNORMAL, 2,0);
3814
 
3815
    //---------------------------
3816
    // Used Capacity
3817
    lcd_printp_at (0, ++line, strGet(STATS_ITEM_6), MNORMAL);
3818
    write_ndigit_number_u (14, line, Config.OSD_Statistic.max_Capacity, 4, 0,MNORMAL);
3819
    lcdx_printp_at(18, line, PSTR("mAh"), MNORMAL, 2,0);
3820
 
3821
 
3822
    //---------------------------
3823
    // max Current
3824
    // max_Current = 1000;
3825
    lcd_printp_at (0, ++line, strGet(STATS_ITEM_5), MNORMAL);
3826
    write_ndigit_number_u_10th (13, line, Config.OSD_Statistic.max_Current, 4, 0,MNORMAL);
3827
    lcdx_putc (18, line, 'A', MNORMAL, 2,0);
3828
 
3829
 
3830
    //---------------------------
3831
    // max BL-Current
3832
    line++;
3833
    lcd_printp_at( 0, line, PSTR("max BL  Curr:"), MNORMAL);
3834
    write_ndigit_number_u( 6, line, blmax.max_BL_Current_Index+1, 1, 0,MNORMAL);
3835
    write_ndigit_number_u_10th (14, line, blmax.max_BL_Current, 3, 0,MNORMAL);
3836
    lcdx_putc (18, line, 'A', MNORMAL, 2,0);
3837
 
3838
    //---------------------------
3839
    // max BL-Temp
3840
    line++;
3841
    lcd_printp_at( 0, line, PSTR("max BL  Temp:"), MNORMAL);
3842
    write_ndigit_number_u( 6, line, blmax.max_BL_Temp_Index+1, 1, 0,MNORMAL);
3843
    write_ndigit_number_u (14, line, blmax.max_BL_Temp, 4, 0,MNORMAL);
3844
    lcdx_printp_at( 18, line, PSTR("\013C"), MNORMAL, 2,0);
3845
}
3846
#endif // USE_OSD_SCREEN_STATISTIC
3847
 
3848
 
3849
 
3850
//--------------------------------------------------------------
3851
// OSD_Screen_3DLage()
3852
//--------------------------------------------------------------
3853
#ifdef USE_OSD_SCREEN_3DLAGE
3854
void OSD_Screen_3DLage( void )
3855
{
3856
    uint16_t head_home;
3857
    uint8_t  Nick;
3858
    uint8_t  Roll;
3859
 
3860
    //-----------------------------------------
3861
    // REDRAW
3862
    // statische Screen Elemente die nicht
3863
    // jedesmal neu gezeichnet werden muessen
3864
    //-----------------------------------------
3865
    if( OSDScreenRefresh == OSD_SCREEN_REDRAW )
3866
    {
3867
        // do things here for static screen elements like labels and so....
3868
        lcd_rect_round( 0, 0, 127, 63-0, 1, R2);                    // Rahmen
3869
    }
3870
 
3871
 
3872
    head_home = (naviData->HomePositionDeviation.Bearing + 360 - naviData->CompassHeading) % 360;
3873
 
3874
    lcd_line(26,32,100,32,1);  // horizontal //
3875
    lcd_line(63,0,63,63,1);    //  vertical  //
3876
 
3877
    // 45' Angel
3878
    lcd_line(61,11,65,11,1);   //    --    //
3879
    lcd_line(40,30,40,34,1);   //  |       //
3880
    lcd_line(86,30,86,34,1);   //       |  //
3881
    lcd_line(61,53,65,53,1);   //    --    //
3882
 
3883
    lcdx_printp_at( 9, 0, strGet(OSD_3D_V), MNORMAL, 0,4);      // V
3884
    lcdx_printp_at( 3, 3, strGet(OSD_3D_L), MNORMAL, 0,0);      // L
3885
    lcdx_printp_at(17, 3, strGet(OSD_3D_R), MNORMAL, 0,0);      // R
3886
    lcdx_printp_at( 9, 7, strGet(OSD_3D_H), MNORMAL, 0,-3);     // H
3887
 
3888
    // Oben, Links: Ni
3889
    lcdx_printp_at(0, 0, strGet(OSD_3D_NICK), MNORMAL, 5,4);                    // Ni
3890
    writex_ndigit_number_s (2, 0, naviData->AngleNick, 3, 0, MNORMAL, 7,4);
3891
    lcdx_putc (5, 0, SYMBOL_SMALLDEGREE, MNORMAL, 7,4);
3892
 
3893
    // Unten, Links: Ro
3894
    lcdx_printp_at(0, 7, strGet(OSD_3D_ROLL), MNORMAL, 5,-3);                   // Ro
3895
    writex_ndigit_number_s (2, 7, naviData->AngleRoll, 3, 0, MNORMAL, 7,-3);
3896
    lcdx_putc (5, 7, SYMBOL_SMALLDEGREE, MNORMAL, 7,-3);
3897
 
3898
    // Oben, Rechts: Ko
3899
    //lcdx_printp_at(13, 0, strGet(OSD_3D_COMPASS), MNORMAL, -4,3);             // Ko
3900
    writex_ndigit_number_u (15, 0, (naviData->CompassHeading)%360, 3, 0, MNORMAL, -4,4);
3901
    lcdx_putc (18, 0, SYMBOL_SMALLDEGREE, MNORMAL, -4,4);
3902
    OSD_Element_CompassDirection( 19, 0,  -2,4 );
3903
 
3904
    Roll = ((-naviData->AngleRoll/2)+63);
3905
    Nick = ((-naviData->AngleNick/2)+32);
3906
 
3907
    if( Roll <     (9+1) ) Roll =     (9+1);    // nicht ausserhalb des Screens zeichnen!
3908
    if( Roll > 127-(9+1) ) Roll = 127-(9+1);    // nicht ausserhalb des Screens zeichnen!
3909
 
3910
    if( Nick <     (8+1) ) Nick =     (8+1);    // nicht ausserhalb des Screens zeichnen!
3911
    if( Nick >  63-(8+1) ) Nick =  63-(8+1);    // nicht ausserhalb des Screens zeichnen!
3912
 
3913
    if( old_AngleRoll != 0 )                    // nicht ausserhalb des Screens zeichnen!
3914
    {
3915
        lcd_ellipse     ( old_AngleRoll, old_AngleNick, 9, 8, 0);
3916
        lcd_ellipse_line( old_AngleRoll, old_AngleNick, 8, 7, old_hh, 0);
3917
    }
3918
 
3919
    lcd_ellipse     ( Roll, Nick, 9, 8, 1);
3920
    lcd_ellipse_line( Roll, Nick, 8, 7, head_home, 1);
3921
 
3922
    // remember last values (3DL)
3923
    old_hh          = head_home;
3924
    old_AngleNick   = Nick;
3925
    old_AngleRoll   = Roll;
3926
}
3927
#endif // USE_OSD_SCREEN_3DLAGE
3928
 
3929
 
3930
 
3931
 
3932
//--------------------------------------------------------------
3933
// OSD_Screen_MKDisplay()
3934
//
3935
// das ist ein Spezialscreen der ausserhalb der regulaeren
3936
// OSD-Screens aufgerufen und bedient wird!
3937
//--------------------------------------------------------------
3938
//#ifdef USE_OSD_SCREEN_MKDISPLAY
3939
void OSD_Screen_MKDisplay( void )
3940
{
3941
    uint8_t wpindex;
3942
 
3943
    //-----------------------------------------
3944
    // REDRAW
3945
    // statische Screen Elemente die nicht
3946
    // jedesmal neu gezeichnet werden muessen
3947
    //-----------------------------------------
3948
    if( OSDScreenRefresh == OSD_SCREEN_REDRAW )
3949
    {
3950
        // do things here for static screen elements like labels and so....
3951
        lcd_line(  (6*6-3),  0,  (6*6-3), 11, 1);                               // Linie Vertikal Oben: links
3952
        lcd_line( (15*6+5),  0, (15*6+5), 11, 1);                               // Linie Vertikal Oben: rechts
3953
        lcd_rect_round( 0, 2*7-2, 127, 5*7+3+3, 1, R2);                         // Rahmen unten fuer Inhalt Display
3954
 
3955
        //lcd_frect_round( 6*6+0, 0, 9*6+2, 9, 1, R1);                          // Umrahmung fuer "OSD-Displ"
3956
        //lcdx_printp_at( 7, 0, PSTR("OSD-Disp"), MINVERS,  -3,1);              // "OSD-Displ"
3957
        //lcdx_printp_at(15, 0, PSTR("l"), MINVERS,  -4,1);                     // das "l" von "OSD-Displ" (1 Pixel nach links)
3958
 
3959
        lcdx_printp_at( 2, 7, PSTR("\x18    \x19"), MNORMAL,  0,0);             // Keyline: Links / Rechts
3960
        PKT_KeylineUpDown( 18, 13,  0,0);                                       // Keyline: Down / Up
3961
 
3962
    } // end: if( OSDScreenRefresh == OSD_SCREEN_REDRAW )
3963
    //-----------------------------------------
3964
 
3965
 
3966
    //-----------------
3967
    // Oben: Waypoint-Index und Anzahl der Waypoint's
3968
    //-----------------
3969
    wpindex = naviData->WaypointIndex;
3970
    if( naviData->WaypointNumber==0 ) wpindex = 0;
3971
 
3972
    lcdx_printf_at_P( 7, 0, MNORMAL, -1,0, PSTR("WP:%2d/%2d"), wpindex, naviData->WaypointNumber );
3973
 
3974
 
3975
    //lcdx_printf_at_P(13, 0, MNORMAL, -3,1, PSTR("R:%d"), (naviData->NCFlags & NC_FLAG_TARGET_REACHED) );
3976
    //if ((NextWP==true)&& naviData->NCFlags & NC_FLAG_TARGET_REACHED)
3977
    //lcd_printf_at_P( 0, 2, MNORMAL, PSTR("WP:%d"), naviData->WaypointIndex);
3978
    //write_ndigit_number_u (x+2, y, naviData->WaypointIndex , 2, 0,0);
3979
    //lcd_printp_at (x, y, PSTR("WP"), 0);
3980
    //if ((NextWP==true)&& naviData->NCFlags & NC_FLAG_TARGET_REACHED)
3981
 
3982
 
3983
 
3984
    //-----------------
3985
    // Oben: Batt Level (Volt)
3986
    //-----------------
3987
    OSD_Element_BattLevel2( 0, 0, 0,0 );
3988
 
3989
    //-----------------
3990
    // Oben: Batt Level Bar
3991
    //-----------------
3992
    //OSD_Element_Battery_Bar( x, y, length, width, orientation)
3993
    OSD_Element_Battery_Bar( 0, 9, 30, 1, ORIENTATION_H);
3994
 
3995
    //-----------------
3996
    // Oben: Navi-Kreis
3997
    //-----------------
3998
    //OSD_Element_HomeCircleX( 64, 5, 6, 5, true );
3999
 
4000
 
4001
    //-----------------
4002
    // Oben: Flugzeit
4003
    //-----------------
4004
    writex_time(16, 0, naviData->FlyingTime, MNORMAL, 2,0);
4005
 
4006
 
4007
    //------------------------------------------
4008
    // Ausgabe auf PKT-Anzeige
4009
    // 4 Zeilen a 20 Zeichen
4010
    //------------------------------------------
4011
    mkdisplayData[80] = 0;
4012
    lcdx_print_at( 0,5, (uint8_t *) &mkdisplayData[60],  MNORMAL,  5,3);
4013
 
4014
    mkdisplayData[60] = 0;
4015
    lcdx_print_at( 0,4, (uint8_t *) &mkdisplayData[40],  MNORMAL,  5,2);
4016
 
4017
    mkdisplayData[40] = 0;
4018
    lcdx_print_at( 0,3, (uint8_t *) &mkdisplayData[20],  MNORMAL,  5,1);
4019
 
4020
    mkdisplayData[20] = 0;
4021
    lcdx_print_at( 0,2, (uint8_t *) &mkdisplayData[0],   MNORMAL,  5,0);
4022
 
4023
    Beep_Waypoint();
4024
}
4025
//#endif  // USE_OSD_SCREEN_MKDISPLAY
4026
 
4027
 
4028
 
4029
//##############################################################
4030
#ifdef USE_OSD_SCREEN_DEBUG
4031
//##############################################################
4032
 
4033
//**************************************************************
4034
//* OSD_DEBUG_SCREEN - Experimental-Code usw.
4035
//* - nicht fuer die Oeffentlichkeit bestimmt
4036
//* - gesteuert ueber define OSD_DEBUG_SCREEN
4037
//**************************************************************
4038
 
4039
//--------------------------------------------------------------
4040
// OSD_Screen_Debug()
4041
//--------------------------------------------------------------
4042
void OSD_Screen_Debug( void )
4043
{
4044
    //char buffer[80];
4045
    static uint16_t debug_count = 0;
4046
    //char buffer[30];
4047
    //uint8_t   y, i;
4048
 
4049
 
4050
    //-----------------------------------------
4051
    // REDRAW
4052
    // statische Screen Elemente die nicht
4053
    // jedesmal neu gezeichnet werden muessen
4054
    //-----------------------------------------
4055
    if( OSDScreenRefresh == OSD_SCREEN_REDRAW )
4056
    {
4057
        // do things here for static screen elements like labels and so....
4058
        lcd_printp_at( 0, 0, PSTR("Debug"), 0);
4059
        //timer_pkt_uptime = 0;
4060
    }
4061
 
4062
    debug_count++;
4063
    write_ndigit_number_u( 17, 0, (debug_count), 4, 0,MNORMAL);   //
4064
 
4065
 
4066
    // act. Current
4067
    lcd_printf_at_P( 0, 2, MNORMAL, PSTR("act  Current%3.1u A"), naviData->Current);
4068
 
4069
    // max. Current
4070
    lcd_printf_at_P( 0, 3, MNORMAL, PSTR("max  Current%3.1u A"), Config.OSD_Statistic.max_Current);
4071
 
4072
    // avg. Current
4073
    lcd_printf_at_P( 0, 4, MNORMAL, PSTR("avg  Current%3.1u A"), (uint8_t)(Config.OSD_Statistic.avg_Current/100));
4074
 
4075
    // avg. Current DEBUG
4076
    //lcd_printf_at_P( 0, 5, MNORMAL, PSTR("avgD Current%3.1u A"), (uint8_t)(Config.OSD_Statistic.avg_Altimeter/100));
4077
 
4078
    // stat. Packages
4079
    lcd_printf_at_P( 0, 6, MNORMAL, PSTR("stat Pkg's%7u"), Config.OSD_Statistic.count_osd);
4080
 
4081
 
4082
/*
4083
    // DEBUG: Heading
4084
    lcd_printf_at_P( 0, 1, MNORMAL, PSTR("NC-Errorcode:%3u"), naviData->Errorcode);
4085
 
4086
    //heading_home = (naviData->HomePositionDeviation.Bearing + 360 - naviData->CompassHeading) % 360;
4087
 
4088
    lcd_printf_at_P( 0, 3, MNORMAL, PSTR("CH:%6d%6d"), naviData->CompassHeading, naviData->CompassHeading%360);
4089
    lcd_printf_at_P( 0, 4, MNORMAL, PSTR("HD:%6d%6d"), naviData->HomePositionDeviation.Bearing, naviData->HomePositionDeviation.Bearing%360);
4090
 
4091
    //heading_home = (naviData->HomePositionDeviation.Bearing + 360 - naviData->CompassHeading) % 360;
4092
 
4093
    //heading_home = ((naviData->CompassHeading % 360) - (naviData->HomePositionDeviation.Bearing % 360)) + 180;
4094
    //heading_home = ((naviData->CompassHeading % 360) - (naviData->HomePositionDeviation.Bearing % 360));
4095
 
4096
    calc_heading_home();
4097
 
4098
    lcd_printf_at_P( 0, 6, MNORMAL, PSTR("xx:%6d"), heading_home);
4099
*/
4100
 
4101
/*
4102
    lcd_putc( 0, 3, 0x08, MNORMAL); // ASCII -   8 08 SAT Symbol
4103
    lcd_putc( 2, 3, 0x09, MNORMAL); // ASCII -   9 09 Altitude Symbol
4104
    lcd_putc( 4, 3, 0x0C, MNORMAL); // ASCII -  12 0C Enter Symbol
4105
    lcd_putc( 6, 3, 0x1F, MNORMAL); // ASCII -  31 1F Antenne
4106
    lcd_putc( 8, 3, 10, MNORMAL); // 'o'
4107
    lcd_putc(10, 3, 13, MNORMAL); // 'o'
4108
    //lcd_putc(10, 3, 0x06, MNORMAL);
4109
    //lcd_putc(12, 3, 0x07, MNORMAL);
4110
 
4111
    lcd_putc( 0, 5, 0x1E, MNORMAL);
4112
    lcd_putc( 4, 5, 0x7e, MNORMAL);
4113
    lcd_putc( 6, 5, 0x7f, MNORMAL);
4114
    lcd_putc( 8, 5, 0x18, MNORMAL);
4115
    lcd_putc(10, 5, 0x19, MNORMAL);
4116
*/
4117
 
4118
    //lcd_printp_at( 0, 1, PSTR("Free RAM:"), 0);
4119
    //writex_ndigit_number_u ( 9,  1, get_freeRam(), 9, 0,MNORMAL, 0,0);   //
4120
}
4121
 
4122
 
4123
//--------------------------------------------------------------
4124
// OSD_Screen_Debug_RX()
4125
//
4126
// Anzeige gelesener Datenpakete (fuer Feinabstimmung) und weitere
4127
// Werte wie Zeit/Datum (mit/ohne Abgleich zur NC)
4128
//
4129
// Anzeige oben 1. Zeile:
4130
//   Screenname  : "Debug-RX"
4131
//   PKT-Uptime  : Minuten, Sekunden die das PKT aktuell eingeschaltet ist
4132
//   Screen-Count: Anzahl der Aufrufe des Screens (abhaengig von der Refreshtime)
4133
//
4134
// Anzeige Zeit:
4135
//   "N" oder "O": neuer(N) oder alter(O) Zeit-Algo fuer die NC (OSD_MK_UTCTime())
4136
//   00:00:00    : Stunde, Minute, Sekunde (korrigiert mittels PKT-Einstellung bzgl. Zeitzone/Sommerzeit)
4137
//   dd.mm.yyyy  : Tag, Monat, Jahr        (korrigiert mittels PKT-Einstellung bzgl. Zeitzone/Sommerzeit)
4138
// Solange keine richtige Zeit von der NC gemeldet wird, wird die PKT-Uptime
4139
// seit einschalten des PKT angezeigt.
4140
//
4141
// Anzeige unten:
4142
//   OSD:  Anzahl gelesener OSD-Pakete der NC
4143
//   Time: Anzahl gelesener Time-Pakete der NC (Aktualisierung ca. jede Minute)
4144
//
4145
//   BL:   es werden die gelesenen Datenpakete der BL's angezeigt
4146
//         von BL1 (links oben) bis BL8 (rechts unten)
4147
//--------------------------------------------------------------
4148
void OSD_Screen_Debug_RX( void )
4149
{
4150
    static uint16_t debug_count = 0;
4151
    uint8_t y;
4152
    int8_t  yoffs;
4153
 
4154
    //uint8_t status;       // FC Kommunikation
4155
 
4156
    //-----------------------------------------
4157
    // REDRAW
4158
    // statische Screen Elemente die nicht
4159
    // jedesmal neu gezeichnet werden muessen
4160
    //-----------------------------------------
4161
    if( OSDScreenRefresh == OSD_SCREEN_REDRAW )
4162
    {
4163
        // do things here for static screen elements like labels and so....
4164
        lcd_frect(     0, 0, 1, 8, 1);                              // title spacer
4165
        lcdx_printp_at( 0, 0, PSTR("Debug-RX"), MINVERS, 1,0);      // title
4166
        lcd_line (0, 9, 127, 9, 1);                                 // Linie horizontal
4167
        lcd_line (0, 22, 127, 22, 1);                               // Linie horizontal
4168
        //lcd_line (0, 31, 127, 31, 1);                               // Linie horizontal
4169
    }
4170
 
4171
    //-----------------------
4172
    // Zeile 0
4173
    //-----------------------
4174
    writex_time( 11, 0, timer_pkt_uptime/100, MNORMAL, 0,0);
4175
    debug_count++;
4176
    write_ndigit_number_u ( 17, 0, (debug_count), 4, 0,MNORMAL);   //
4177
 
4178
 
4179
    //-----------------------
4180
    // Anzeige Zeit / Datum
4181
    //-----------------------
4182
    yoffs = 5;
4183
    writex_datetime_time(  1, 1, UTCTime, MNORMAL, 5,yoffs);    // Zeit
4184
    writex_datetime_date( 11, 1, UTCTime, MNORMAL, 0,yoffs);    // Datum
4185
 
4186
    //-----------------------
4187
    // gelesene Pakete: OSD und Zeit
4188
    //-----------------------
4189
    y = 4;
4190
    yoffs = -5;
4191
 
4192
    lcdx_printp_at( 0, y+0, PSTR("OSD:"), MNORMAL, 0,yoffs);
4193
    writex_ndigit_number_u ( 4,  y+0, ( readCounterOSD), 5, 0,MNORMAL, 0,yoffs);   //
4194
 
4195
    lcdx_printp_at( 13, y+0, PSTR("Time:"), MNORMAL, 0,yoffs);
4196
    writex_ndigit_number_u ( 18,  y+0, ( readCounterTIME), 3, 0,MNORMAL, 0,yoffs);   //
4197
 
4198
 
4199
    //----
4200
    lcdx_printp_at( 0, y+1, PSTR("Dis:"), MNORMAL, 0,yoffs);
4201
    writex_ndigit_number_u ( 4,  y+1, ( readCounterDISPLAY), 5, 0,MNORMAL, 0,yoffs);   //
4202
 
4203
 
4204
    //-----------------------
4205
    // gelesene Pakete: BL
4206
    //-----------------------
4207
    y = 6;
4208
    lcd_frect(     0, y*8-1, 8, 17, 1); // Box
4209
 
4210
    lcdx_printp_at( 0, y+0, PSTR("B"), MINVERS, 2,0);
4211
    lcdx_printp_at( 0, y+1, PSTR("L"), MINVERS, 2,0);
4212
    write_ndigit_number_u ( 2,  y+0, ( readCounterBL[0]), 4, 0,MNORMAL);   //
4213
    write_ndigit_number_u ( 7,  y+0, ( readCounterBL[1]), 4, 0,MNORMAL);   //
4214
    write_ndigit_number_u ( 12, y+0, ( readCounterBL[2]), 4, 0,MNORMAL);   //
4215
    write_ndigit_number_u ( 17, y+0, ( readCounterBL[3]), 4, 0,MNORMAL);   //
4216
 
4217
    write_ndigit_number_u ( 2,  y+1, ( readCounterBL[4]), 4, 0,MNORMAL);   //
4218
    write_ndigit_number_u ( 7,  y+1, ( readCounterBL[5]), 4, 0,MNORMAL);   //
4219
    write_ndigit_number_u ( 12, y+1, ( readCounterBL[6]), 4, 0,MNORMAL);   //
4220
    write_ndigit_number_u ( 17, y+1, ( readCounterBL[7]), 4, 0,MNORMAL);   //
4221
}
4222
 
4223
//##############################################################
4224
#endif  // USE_OSD_SCREEN_DEBUG
4225
//##############################################################
4226
 
4227
 
4228
 
4229
//-----------------------------------------------------------
4230
// ok = OSD_Popup_MKSetting()
4231
//
4232
// zeigt das aktuelle FC-Setting beim Start vom OSD an
4233
//
4234
// RUECKGABE:
4235
//   true  = Setting konnte gelesen werden
4236
//   false = Fehler
4237
//-----------------------------------------------------------
4238
uint8_t OSD_Popup_MKSetting( void )
4239
{
4240
    Popup_Draw( 3 );                                                // 3 Zeilen von unten nach oben fuer's Popup
4241
    lcdx_printp_center( 2, PSTR("PKT OSD")   , MNORMAL,  0, 0);
4242
    lcdx_printp_center( 6, PSTR("MK Setting"), MINVERS,  0,-8);
4243
 
4244
    MK_Setting_load( 0xff, 9 );                                     // 0xff == aktuelles Parameterset holen; 9 == timeout
4245
 
4246
    MKVersion_Setting_print( 7, MINVERS,  0,-4);                    // aus: mkbase.c
4247
 
4248
    if( MKVersion.mksetting == 0 )
4249
        set_beep( 500, 0xffff, BeepNormal );                        // kein Setting - langer Beep ERROR
4250
 
4251
 
4252
    clear_key_all();
4253
    timer = 300;                                                    // ca. 3 Sekunden zeigen; Abbruch mit einer Taste moeglich
4254
    while( timer > 0 && !get_key_press(0xff) );
4255
 
4256
    clear_key_all();
4257
    lcd_cls();
4258
 
4259
    return (MKVersion.mksetting != 0);
4260
}
4261
 
4262
 
4263
 
4264
//-----------------------------------------------------------
4265
//-----------------------------------------------------------
4266
void OSD_Popup_MKError( u8 mkerrorcode )
4267
{
4268
    Popup_Draw( 3 );                                                                                        // 3 Zeilen von unten nach oben fuer's Popup
4269
 
4270
    lcdx_printf_center_P( 6, MINVERS, 0,-8, PSTR("** MK-%S %02d **"), strGet(STR_ERROR), mkerrorcode );     // "MK-FEHLER" und Fehlernummer
4271
 
4272
    lcdx_printp_center( 7, (const char*) pgm_read_word(&mkerrortext[mkerrorcode]), MINVERS, 0,-4);          // MK-Fehlertext
4273
}
4274
 
4275
 
4276
 
4277
//-----------------------------------------------------------
4278
//-----------------------------------------------------------
4279
void OSD_Popup_Info( uint8_t ScreenNum, const char *ScreenName)
4280
{
4281
    Popup_Draw( 5 );                            // 5 Zeilen von unten nach oben fuer's Popup
4282
 
4283
    lcd_line( 3, 53-21, 124, 53-21, 0);         // Linie: oben
4284
    lcd_line( 3, 53, 124, 53, 0);               // Linie: unten
4285
 
4286
    //-----------------------
4287
    // ScreenNummer: ScreenName
4288
    //-----------------------
4289
    lcdx_printf_at_P( 0, 3, MINVERS, 5,-2, PSTR("%02d: %S"), ScreenNum, ScreenName );
4290
 
4291
    //-----------------------
4292
    // longpress Key's
4293
    //-----------------------
4294
    lcdx_printp_at( 0, 4, strGet(STR_LONGPRESS), MINVERS, 6,3); // "langer Tastendruck:"
4295
    lcdx_printp_at(12, 5, PSTR("Disp"), MINVERS, 0,4);
4296
    lcdx_printp_at(17, 5, PSTR("UGps"), MINVERS, 0,4);
4297
 
4298
    //-----------------------
4299
    // shortpress Key's
4300
    //-----------------------
4301
    lcd_printp_at( 0, 7, strGet(KEYLINE3), MINVERS);
4302
    lcd_printp_at(17, 7, PSTR("Info")    , MINVERS);
4303
}
4304
 
4305
 
4306
 
4307
//--------------------------------------------------------------
4308
//--------------------------------------------------------------
4309
void GPS_Pos_Save( pkt_gpspos_t *pGPS )
4310
{
4311
    pGPS->Altimeter         = naviData->Altimeter;                              // barymetrische Hoehe
4312
    pGPS->HomeDistance      = naviData->HomePositionDeviation.Distance;         // Entfernung Home
4313
 
4314
    memcpy( &pGPS->GPSData, &naviData->CurrentPosition, sizeof(GPS_Pos_t) );    // sichern...
4315
    memcpy( &pGPS->timestamp, (char *)&UTCTime, sizeof(PKTdatetime_t) );        // sichern...
4316
}
4317
 
4318
 
4319
//--------------------------------------------------------------
4320
//--------------------------------------------------------------
4321
 
4322
//--------------------------------------------------------------
4323
// GPS_User_Init()
4324
//
4325
// initialisiert die GPS Positionen neu
4326
//--------------------------------------------------------------
4327
 
4328
void GPS_User_Init( void )
4329
{
4330
    memset( Config.GPS_User, 0, sizeof(pkt_gpspos_t)*MAX_GPS_USER );
4331
}
4332
 
4333
 
4334
//--------------------------------------------------------------
4335
//--------------------------------------------------------------
4336
void GPS_User_Save( void )
4337
{
4338
    uint8_t i;
4339
 
4340
    if( naviData->NCFlags & NC_FLAG_GPS_OK )        // nur wenn MK-GPS ok ist
4341
    {
4342
        for( i=MAX_GPS_USER-1; i>0; i--)
4343
        {
4344
            Config.GPS_User[i] = Config.GPS_User[i-1];
4345
        }
4346
        GPS_Pos_Save( &Config.GPS_User[0] );
4347
 
4348
        set_beep( 160, 0xffff, BeepNormal );        // Beep Ok
4349
    }
4350
    else
4351
    {
4352
        set_beep( 600, 0x000f, BeepNormal );        // Beep Error (keine gueeltigen GPS-Daten)
4353
    }
4354
}
4355
 
4356
 
4357
 
4358
//##############################################################
4359
//##############################################################
4360
 
4361
 
4362
//--------------------------------------------------------------
4363
//--------------------------------------------------------------
4364
void MKLiPoCells_Init( void )
4365
{
4366
    CellIsChecked     = 0;
4367
    cells             = 0;
4368
}
4369
 
4370
 
4371
//--------------------------------------------------------------
4372
//--------------------------------------------------------------
4373
void MKLiPoCells_Check( void )
4374
{
4375
    if( cells == 0 )                        // Zellenzahl noch nicht ermittelt?
4376
    {
4377
        // up to 6s LiPo, less than 2s is technical impossible
4378
        for( cells = 2; cells < 7; cells++)
4379
        {
4380
            if( naviData->UBat < cells * MAX_CELL_VOLTAGE ) break;
4381
        }
4382
        Config.OSD_Statistic.LiPoCells = cells;
4383
    }
4384
}
4385
 
4386
 
4387
 
4388
//##############################################################
4389
//# OSD MAIN LOOP
4390
//##############################################################
4391
 
4392
//--------------------------------------------------------------
4393
// OSD MAIN LOOP
4394
//--------------------------------------------------------------
4395
void osd( void )
4396
{
4397
    uint8_t     osdexit     = false;
4398
    uint8_t     mktimeout   = false;
4399
    uint8_t     flying      = false;
4400
    uint8_t     popup_state = OSD_POPUP_NONE;
4401
 
4402
 
4403
    lcd_cls();
4404
 
4405
    #ifdef DEBUG_OSD_TIME
4406
      // Fake-Zeit/Datum setzen wenn der NC-Simulator verwendet wird
4407
      if( UTCTime.year < 2000 )
4408
      {
4409
          UTCTime.seconds = ((uint32_t)13*3600)+(15*60)+42;   // 13:15:42
4410
          UTCTime.day     = 01;
4411
          UTCTime.month   = 05;
4412
          UTCTime.year    = 2013;
4413
      }
4414
    #endif
4415
 
4416
 
4417
    //----------------------------------------
4418
    // Anzeige: aktuelles MK-Setting
4419
    //----------------------------------------
4420
    if( (Config.OSD_ShowMKSetting) )
4421
    {
4422
        if( !OSD_Popup_MKSetting() )
4423
            return;
4424
    }
4425
 
4426
 
4427
    /*
4428
    //-----------------------------------------------------------------------------------------------
4429
    // 07.03.2013 OG: del
4430
    //   Dieser Teil hat immer wieder Probleme bereitet bei der Verbindung des PKT-OSD zum MK da
4431
    //   MK_TIMEOUTs zustande kamen. Eine Recherche im Code ergab, dass die Nutzdaten die
4432
    //   hierueber bezogen werden sich lediglich auf Flags_ExtraConfig beschraenkten (CFG2_HEIGHT_LIMIT).
4433
    //   Siehe dazu untere Kommentare.
4434
    //
4435
    //   Der negative Effekt moeglicher MK_TIMEOUTs und Verzoegerungen sind es aktuell nicht Wert
4436
    //   CFG2_HEIGHT_LIMIT zu unterstuetzen. Dieses Feature ist erstmal raus.
4437
    //
4438
    //   Falls gewuenscht wird, dass CFG2_HEIGHT_LIMIT wieder in das PKT-OSD kommt muss
4439
    //   es zuverlaessig an anderer Stelle implementiert werden - und zwar nicht in osd.c
4440
    //   weil es eine statische FC-Information ist (ggf. beim Verbindungsaufbau PKT <-> MK).
4441
    //
4442
    //   Hat auch aktuell Auswirkung auf den Code OSD_Element_AltitudeControl()
4443
    //-----------------------------------------------------------------------------------------------
4444
    //lcd_printp_at( 0, 3, PSTR("connecting MK..."), 0);
4445
    //
4446
    //SwitchToFC();
4447
    //
4448
    //status = load_setting(0xff);
4449
    //
4450
    //if( status == 255 )
4451
    //{
4452
    //    lcd_printp_at(0, 0, PSTR("Keine Settings !!"), 0);    // Keine Settings
4453
    //    _delay_ms(2000);
4454
    //}
4455
    //Flags_ExtraConfig   = mk_param_struct->ExtraConfig;     // OG: wird in osd.c nur verwendet von: OSD_Element_AltitudeControl()
4456
    //Flags_GlobalConfig  = mk_param_struct->GlobalConfig;    // OG: wird nicht in osd.c verwendet
4457
    //Flags_GlobalConfig3 = mk_param_struct->GlobalConfig3;   // OG: wird nicht in osd.c verwendet
4458
    */
4459
 
4460
 
4461
 
4462
    //-------------------------
4463
    // MK-Display initialisieren
4464
    //-------------------------
4465
    memset( mkdisplayData, 0, 81 );
4466
    mkdisplayMode   = false;
4467
    mkdisplayCmd    = 0xff;
4468
 
4469
 
4470
    //-------------------------
4471
    // BL-DATA initialisieren
4472
    //-------------------------
4473
    memset( blData, 0, sizeof(BLData_t)*OSD_MAX_MOTORS );
4474
 
4475
 
4476
    //-------------------------
4477
    // Debug initialisieren
4478
    //-------------------------
4479
    #ifdef USE_OSD_SCREEN_DEBUG
4480
        readCounterOSD      = 0;
4481
        readCounterTIME     = 0;
4482
        readCounterDISPLAY  = 0;
4483
        memset( readCounterBL, 0, sizeof(uint16_t)*OSD_MAX_MOTORS );
4484
    #endif  // USE_OSD_SCREEN_DEBUG
4485
 
4486
 
4487
 
4488
    //-------------------------
4489
    // NC Datenkommunikation starten
4490
    //-------------------------
4491
    OSD_MK_Connect( MK_CONNECT );
4492
 
4493
    OSD_active  = true;                 // benoetigt fuer Navidata Ausgabe an SV2
4494
 
4495
 
4496
    //-------------------------
4497
    // Clear statistics
4498
    //-------------------------
4499
    //STAT_Init();
4500
 
4501
    CellIsChecked     = 0;
4502
    cells             = 0;
4503
    AkkuWarnThreshold = 0;
4504
    OldWP             = 0;
4505
    NextWP            = false;
4506
    old_PKTErrorcode  = 0;
4507
    old_MKErrorcode   = 0;
4508
 
4509
 
4510
 
4511
    //-------------------------
4512
    // Init: OSD-Screens
4513
    //-------------------------
4514
    ScreenCtrl_Init();
4515
    ScreenCtrl_Push( OSDSCREEN_GENERAL      , strGet(STR_OSDSCREEN_GENERAL)   , &OSD_Screen_General    );
4516
 
4517
    #ifdef USE_OSD_SCREEN_NAVIGATION
4518
    ScreenCtrl_Push( OSDSCREEN_NAVIGATION   , strGet(STR_OSDSCREEN_NAVIGATION), &OSD_Screen_Navigation );
4519
    #endif
4520
 
4521
    #ifdef USE_OSD_SCREEN_WAYPOINTS
4522
    ScreenCtrl_Push( OSDSCREEN_WAYPOINTS    , strGet(STR_OSDSCREEN_WAYPOINTS) , &OSD_Screen_Waypoints  );
4523
    #endif
4524
 
4525
    // *ALTERNATIVE*
4526
    //#ifdef USE_OSD_SCREEN_WAYPOINTS
4527
    //ScreenCtrl_Push( OSDSCREEN_WAYPOINTS    , strGet(STR_OSDSCREEN_WAYPOINTS) , &OSD_Screen_Waypoints0 );
4528
    //#endif
4529
 
4530
    #ifdef USE_OSD_SCREEN_ELECTRIC
4531
    ScreenCtrl_Push( OSDSCREEN_ELECTRIC     , strGet(STR_OSDSCREEN_ELECTRIC)  , &OSD_Screen_Electric   );
4532
    #endif
4533
 
4534
    #ifdef USE_OSD_SCREEN_MKSTATUS
4535
    ScreenCtrl_Push( OSDSCREEN_MKSTATUS     , strGet(STR_OSDSCREEN_MKSTATUS)  , &OSD_Screen_MKStatus   );
4536
    #endif
4537
 
4538
    #ifdef USE_OSD_SCREEN_USERGPS
4539
    ScreenCtrl_Push( OSDSCREEN_USERGPS      , strGet(STR_OSDSCREEN_USERGPS)   , &OSD_Screen_UserGPS    );
4540
    #endif
4541
 
4542
    #ifdef USE_OSD_SCREEN_3DLAGE
4543
    ScreenCtrl_Push( OSDSCREEN_3DLAGE       , strGet(STR_OSDSCREEN_3DLAGE)    , &OSD_Screen_3DLage     );
4544
    #endif
4545
 
4546
    #ifdef USE_OSD_SCREEN_STATISTIC
4547
    ScreenCtrl_Push( OSDSCREEN_STATISTICS   , strGet(STR_OSDSCREEN_STATISTIC) , &OSD_Screen_Statistics );
4548
    #endif
4549
 
4550
    #ifdef USE_OSD_SCREEN_OLD
4551
    ScreenCtrl_Push( OSDSCREEN_OSD0         , strGet(STR_OSDSCREEN_OSD0)      , &OSD_Screen_OSD0       );
4552
    ScreenCtrl_Push( OSDSCREEN_OSD1         , strGet(STR_OSDSCREEN_OSD1)      , &OSD_Screen_OSD1       );
4553
    ScreenCtrl_Push( OSDSCREEN_OSD2         , strGet(STR_OSDSCREEN_OSD2)      , &OSD_Screen_OSD2       );
4554
    #endif
4555
 
4556
    #ifdef USE_OSD_SCREEN_DEBUG
4557
    ScreenCtrl_Push( 0                      , PSTR("Debug")                   , &OSD_Screen_Debug      );
4558
    ScreenCtrl_Push( 0                      , PSTR("Debug-RX")                , &OSD_Screen_Debug_RX   );
4559
    #endif
4560
 
4561
    ScreenCtrl_Set( Config.OSD_ScreenMode );
4562
 
4563
 
4564
    //-------------------------
4565
    // Init: Timer & Flags
4566
    //-------------------------
4567
    OSDScreenRefresh      = OSD_SCREEN_REDRAW;
4568
    timer_mk_timeout      = MK_TIMEOUT;
4569
    timer_osd_refresh     = TIME_OSD_REFRESH;
4570
    timer_get_bldata      = 0;
4571
    timer_get_tidata      = 0;
4572
    timer_get_displaydata = 0;
4573
 
4574
 
4575
    //--------------------------------
4576
    // OSD Main-Loop
4577
    //--------------------------------
4578
    while( !osdexit )
4579
    {
4580
        //################################
4581
        //# Empfange/verarbeite: OSD-Daten
4582
        //################################
4583
        if( rxd_buffer_locked )                     // naviData Ok?
4584
        {
4585
            Decode64();
4586
            memcpy( &osdData, (const void *)pRxData, sizeof(NaviData_t) );       // sichern in: osdData
4587
            naviData = &osdData;
4588
 
4589
            #ifdef USE_OSD_SCREEN_DEBUG
4590
                readCounterOSD++;                   // gelesene Datenpakete
4591
            #endif
4592
 
4593
            mktimeout = false;
4594
 
4595
 
4596
            //----------------------------------
4597
            // LiPo Cell Check
4598
            //----------------------------------
4599
            if( cells == 0 )                        // Zellenzahl noch nicht ermittelt?
4600
            {
4601
                // up to 6s LiPo, less than 2s is technical impossible
4602
                for( cells = 2; cells < 7; cells++)
4603
                {
4604
                    if( naviData->UBat < cells * MAX_CELL_VOLTAGE ) break;
4605
                }
4606
                Config.OSD_Statistic.LiPoCells = cells;
4607
            }
4608
 
4609
 
4610
            //----------------------------------
4611
            // Winkel zu Home
4612
            //----------------------------------
4613
            calc_heading_home();
4614
 
4615
 
4616
            //----------------------------------
4617
            // speichere letzte GPS-Positionen
4618
            //----------------------------------
4619
            GPS_Pos_Save( &GPS_Current );
4620
            Config.LastLatitude  = GPS_Current.GPSData.Latitude;    // speichere letzte Position in Config
4621
            Config.LastLongitude = GPS_Current.GPSData.Longitude;   // speichere letzte Position in Config
4622
 
4623
 
4624
            //----------------------------------
4625
            // PKT Fehler reset
4626
            //----------------------------------
4627
            if( old_PKTErrorcode == 40 )                            // 40 = PKT Empfangsausfall ("PKT RX lost")
4628
            {
4629
                // PKT-Verbindungsfehler zuruecksetzen
4630
                // da an dieser Stelle ja bereits wieder ein gueltiges Datenpaket
4631
                // von der NaviCtrl empfangen wurde
4632
                old_PKTErrorcode = 0;
4633
                clear_key_all();
4634
            }
4635
 
4636
 
4637
            //----------------------------------
4638
            // remember statistics (only when engines running)
4639
            //----------------------------------
4640
            #ifdef DEBUG_OSD_STAT_MOTORRUN
4641
              if( true )
4642
            #else
4643
              if( naviData->FCStatusFlags & FC_STATUS_MOTOR_RUN )     // AM FLIEGEN -> Statistik aufzeichnen
4644
            #endif
4645
            {
4646
                flying = true;
4647
 
4648
                 // --- gueltige Zeit von der NC vorhanden und noch keine Start-Zeit gesetzt?
4649
                if( UTCTime.year != 0 && Config.OSD_Statistic.begin_StatTime.year == 0 )
4650
                {
4651
                    memcpy( &Config.OSD_Statistic.begin_StatTime, (char *)&UTCTime, sizeof(PKTdatetime_t) );    // Start Zeit/Datum sichern...
4652
                }
4653
 
4654
                Config.OSD_Statistic.last_FlyTime = naviData->FlyingTime;
4655
 
4656
                Config.OSD_Statistic.count_osd++;                                                               // Anzahl OSD-Statistik Pakete
4657
 
4658
                // int32_t calc_avg( int32_t avg, int32_t value, int32_t count, int32_t factor)
4659
                Config.OSD_Statistic.avg_Current = (uint16_t)calc_avg( (int32_t)Config.OSD_Statistic.avg_Current,
4660
                                                                       (int32_t)naviData->Current,
4661
                                                                       (int32_t)Config.OSD_Statistic.count_osd,
4662
                                                                       (int32_t)100 );
4663
 
4664
                if( naviData->Altimeter > Config.OSD_Statistic.max_Altimeter )      Config.OSD_Statistic.max_Altimeter      = naviData->Altimeter;
4665
                if( naviData->GroundSpeed > Config.OSD_Statistic.max_GroundSpeed )  Config.OSD_Statistic.max_GroundSpeed    = naviData->GroundSpeed;
4666
                if( naviData->HomePositionDeviation.Distance > Config.OSD_Statistic.max_Distance ) Config.OSD_Statistic.max_Distance  = naviData->HomePositionDeviation.Distance;
4667
                if( naviData->Current > Config.OSD_Statistic.max_Current )          Config.OSD_Statistic.max_Current        = naviData->Current;
4668
                if( naviData->UsedCapacity > Config.OSD_Statistic.max_Capacity )    Config.OSD_Statistic.max_Capacity       = naviData->UsedCapacity;
4669
                if( naviData->UBat < Config.OSD_Statistic.min_UBat )                Config.OSD_Statistic.min_UBat           = naviData->UBat;
4670
 
4671
                if( naviData->TopSpeed > Config.OSD_Statistic.max_TopSpeed )        Config.OSD_Statistic.max_TopSpeed       = naviData->TopSpeed;
4672
                if( naviData->RC_Quality > Config.OSD_Statistic.max_RCQuality )     Config.OSD_Statistic.max_RCQuality      = naviData->RC_Quality;
4673
                if( naviData->RC_Quality < Config.OSD_Statistic.min_RCQuality )     Config.OSD_Statistic.min_RCQuality      = naviData->RC_Quality;
4674
 
4675
                if( naviData->AngleNick < Config.OSD_Statistic.min_AngleNick )      Config.OSD_Statistic.min_AngleNick      = naviData->AngleNick;
4676
                if( naviData->AngleNick > Config.OSD_Statistic.max_AngleNick )      Config.OSD_Statistic.max_AngleNick      = naviData->AngleNick;
4677
 
4678
                if( naviData->AngleRoll < Config.OSD_Statistic.min_AngleRoll )      Config.OSD_Statistic.min_AngleRoll      = naviData->AngleRoll;
4679
                if( naviData->AngleRoll > Config.OSD_Statistic.max_AngleRoll )      Config.OSD_Statistic.max_AngleRoll      = naviData->AngleRoll;
4680
            }
4681
            else if( flying && UTCTime.year != 0 )                  // GELANDET -> Statistik beenden
4682
            {
4683
                // --- Ende Zeit/Datum Statistik sichern
4684
                memcpy( &Config.OSD_Statistic.end_StatTime, (char *)&UTCTime, sizeof(PKTdatetime_t) );          // Ende Zeit/Datum sichern...
4685
                flying = false;
4686
            }
4687
 
4688
 
4689
            //-----------------------
4690
            // Check: Akku Warnung
4691
            //-----------------------
4692
            CheckMKLipo();
4693
 
4694
 
4695
            //----------------------------------
4696
            // Show: OSD-Screens
4697
            //----------------------------------
4698
            if( popup_state == OSD_POPUP_NONE && (timer_osd_refresh == 0 || OSDScreenRefresh == OSD_SCREEN_REDRAW) )
4699
            {
4700
                if( OSDScreenRefresh == OSD_SCREEN_REDRAW )     lcd_cls();
4701
 
4702
                if( !mkdisplayMode )
4703
                    ScreenCtrl_Show();
4704
                else
4705
                    OSD_Screen_MKDisplay();
4706
 
4707
                timer_osd_refresh = TIME_OSD_REFRESH;
4708
            }
4709
            OSDScreenRefresh = OSD_SCREEN_REFRESH;
4710
 
4711
 
4712
            //----------------------------------
4713
            // Check: MK-Error
4714
            //----------------------------------
4715
            if( naviData->Errorcode != old_MKErrorcode && naviData->Errorcode <= MAX_MKERROR_NUM )
4716
            {
4717
                if( naviData->Errorcode > 0 )                   // raise Error
4718
                {
4719
                    // Fehler aufzeichnen
4720
                    MkError_Save( naviData->Errorcode );
4721
 
4722
                    // Fehler Anzeigen
4723
                    OSD_Popup_MKError( naviData->Errorcode );
4724
                    set_beep( 1000, 0x000f, BeepNormal);        // Beep Error (MK-Error vorhanden)
4725
                    timer2      = TIME_POPUP_MKERROR;
4726
                    popup_state = OSD_POPUP_MKERROR;
4727
                }
4728
                else                                            // reset Error
4729
                {
4730
                    popup_state       = OSD_POPUP_NONE;
4731
                    OSDScreenRefresh  = OSD_SCREEN_REDRAW;
4732
                }
4733
                old_MKErrorcode = naviData->Errorcode;
4734
            }
4735
 
4736
            rxd_buffer_locked   = FALSE;                    // ready to receive new data
4737
 
4738
 
4739
            //-------------------------------------------
4740
            // hole weitere Daten vom MK (BL, Time, ...)
4741
            //
4742
            // muss am Schluss stehen da naviData-Buffer
4743
            // dabei ueberschrieben wird!
4744
            //-------------------------------------------
4745
            OSD_MK_GetData();                               // holt BL-Daten und NC-Zeit
4746
 
4747
 
4748
            timer_mk_timeout = MK_TIMEOUT;
4749
 
4750
        } //end: if( rxd_buffer_locked )  // OSD-Daten
4751
 
4752
 
4753
 
4754
        //################################
4755
        //# der Rest...
4756
        //################################
4757
 
4758
        //--------------------------------
4759
        // TASTEN: MK-Timeout
4760
        //--------------------------------
4761
        if( mktimeout )
4762
        {
4763
            if( get_key_short(1 << KEY_ESC) )                   // PKT OSD EXIT
4764
            {
4765
                osdexit = true;
4766
            }
4767
        }
4768
 
4769
 
4770
        //--------------------------------
4771
        // Popup beenden
4772
        // wenn irgendeine Taste gedrückt oder Popup-Timeout
4773
        //--------------------------------
4774
        if( !mktimeout && (popup_state != OSD_POPUP_NONE) && (get_key_press(255) || !timer2) )    // get_key_press(255) == alles an Tasten abfangen was moeglich ist
4775
        {
4776
            popup_state      = OSD_POPUP_NONE;
4777
            OSDScreenRefresh = OSD_SCREEN_REDRAW;
4778
            clear_key_all();
4779
        }
4780
 
4781
 
4782
        //--------------------------------
4783
        // TASTEN: KEIN mkdisplay (OSD Modus)
4784
        //--------------------------------
4785
        if( !osdexit && !mktimeout && !mkdisplayMode )
4786
        {
4787
            if( get_key_short(1 << KEY_ESC) )                   // PKT OSD EXIT
4788
            {
4789
                osdexit = true;
4790
            }
4791
 
4792
            if( get_key_long(1 << KEY_ESC) )                   // ÊINSCHALTEN: mkdisplayMode
4793
            {
4794
                set_beep( 25, 0xffff, BeepNormal );             // kurzer Bestaetigungs-Beep
4795
                OSDScreenRefresh = OSD_SCREEN_REDRAW;
4796
                mkdisplayMode    = true;
4797
                mkdisplayCmd     = 0;                           // lesen display-Daten erzwingen
4798
            }
4799
 
4800
            if( get_key_long (1 << KEY_ENTER) )                 // User GPS-Position sichern
4801
            {
4802
                GPS_User_Save();
4803
            }
4804
 
4805
            if( get_key_short (1 << KEY_ENTER) )                // Popup: Info
4806
            {
4807
                if( popup_state == OSD_POPUP_NONE )
4808
                {
4809
                    popup_state = OSD_POPUP_INFO;
4810
                    OSD_Popup_Info( ScreenCtrl_GetNum(), ScreenCtrl_GetName() );
4811
                    timer2 = TIME_POPUP_INFO;
4812
                }
4813
            }
4814
 
4815
            if( get_key_press (1 << KEY_MINUS))                 // previous screen
4816
            {
4817
                ScreenCtrl_Previous();
4818
            }
4819
 
4820
            if( get_key_press (1 << KEY_PLUS))                  // next Screen
4821
            {
4822
                ScreenCtrl_Next();
4823
            }
4824
 
4825
        }
4826
 
4827
 
4828
 
4829
        //--------------------------------
4830
        // TASTEN: mkdisplay AKTIV
4831
        //--------------------------------
4832
        if( !osdexit && !mktimeout && mkdisplayMode )
4833
        {
4834
            /*
4835
            if(    get_key_long(1 << KEY_ENTER)                 // ABSCHALTEN mkdisplayMode: longpress ENTER, ESC, MINUS, PLUS schaltet mkdisplay aus
4836
                || get_key_long(1 << KEY_ESC)
4837
                || get_key_long(1 << KEY_MINUS)
4838
                || get_key_long(1 << KEY_PLUS) )
4839
            {
4840
            */
4841
 
4842
            if( get_key_long(1 << KEY_ESC) )                    // ABSCHALTEN mkdisplayMode: longpress ESC (Taste 3 von links)
4843
            {
4844
                set_beep( 25, 0xffff, BeepNormal );             // kurzer Bestaetigungs-Beep beim Modus-Wechsel
4845
                OSDScreenRefresh = OSD_SCREEN_REDRAW;
4846
                mkdisplayMode    = false;
4847
                clear_key_all();
4848
            }
4849
 
4850
            if( get_key_short (1 << KEY_MINUS) )   mkdisplayCmd = 0xfe; // MK-Key: rechts (next page)
4851
            if( get_key_short (1 << KEY_PLUS)  )   mkdisplayCmd = 0xfd; // MK-Key: links (previous page)
4852
            if( get_key_short (1 << KEY_ESC)   )   mkdisplayCmd = 0xfb; // MK-Key: runter
4853
            if( get_key_short (1 << KEY_ENTER) )   mkdisplayCmd = 0xf7; // MK-Key: hoch
4854
 
4855
            if( mkdisplayCmd != 0xff )                          // wenn eine MK-Display Taste gedrueckt worde sofort Daten
4856
            {                                                   // holen und darstellen um Anzeigereaktion fuer Benutzer zu verbessern
4857
                timer_get_displaydata = 0;                      // lesen erzwingen
4858
                OSD_MK_GetData();                               // Daten holen
4859
                OSD_Screen_MKDisplay();                         // MK-Display Anzeigen
4860
            }
4861
        }
4862
 
4863
 
4864
 
4865
        //-----------------------
4866
        // abo_timer
4867
        //-----------------------
4868
        if( abo_timer == 0 )
4869
        {
4870
            OSD_MK_Connect( MK_ABORENEW );
4871
        }
4872
 
4873
 
4874
        //--------------------------
4875
        // Daten Timeout vom MK?
4876
        //--------------------------
4877
        if( timer_mk_timeout == 0 )
4878
        {
4879
            if( !mktimeout ) OSD_MK_ShowTimeout();              // nur anzeigen wenn noch nicht im mktimeout-Modus
4880
            set_beep ( 200, 0x0080, BeepNormal);                // Beep
4881
            mktimeout        = true;
4882
            timer_mk_timeout = MK_TIMEOUT;
4883
            OSDScreenRefresh = OSD_SCREEN_REDRAW;
4884
            OSD_MK_Connect( MK_CONNECT );                       // 21.06.2014 OG: wieder aktviert wegen Umschaltung auf NC
4885
        }
4886
 
4887
 
4888
 
4889
        //--------------------------
4890
        // Pruefe auf PKT-Update und
4891
        // andere interne PKT-Aktionen
4892
        //--------------------------
4893
        #ifdef USE_OSD_PKTHOOK
4894
          if( PKT_CtrlHook() )  OSDScreenRefresh = OSD_SCREEN_REDRAW;    // Update vom Updatetool angefordert?
4895
        #endif
4896
 
4897
    } // END: while( !osdexit )
4898
 
4899
 
4900
 
4901
    //------------------------------------------
4902
    // PKT-OSD beenden
4903
    //------------------------------------------
4904
    Config.OSD_ScreenMode = ScreenCtrl_GetNum();                    // merken letzter Screen
4905
 
4906
 
4907
    //------------------------------------------
4908
    // ggf. Statistik Ende Zeit/Datum sichern
4909
    //------------------------------------------
4910
    if( flying && UTCTime.year != 0 )                                   // wenn noch am fliegen
4911
    {
4912
        // --- Ende Zeit/Datum Statistik sichern
4913
        memcpy( &Config.OSD_Statistic.end_StatTime, (char *)&UTCTime, sizeof(PKTdatetime_t) );  // Ende Zeit/Datum sichern...
4914
    }
4915
 
4916
 
4917
    OSD_active = false;
4918
}
4919