Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1734 - 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
 *****************************************************************************/
33
 
34
 
35
#include "cpu.h"
36
#include <avr/io.h>
37
#include <inttypes.h>
38
#include <stdlib.h>
39
#include <avr/pgmspace.h>
40
#include <util/delay.h>
41
 
42
#include "main.h"
43
#include "osd.h"
44
#include "lcd.h"
45
#include "timer.h"
46
#include "usart.h"
47
#include "eeprom.h"
48
#include "messages.h"
49
#include "parameter.h"
50
#include "mk-data-structs.h"
51
 
52
#define COSD_WASFLYING 4
53
#define TIMEOUT 200     // 2 sec
54
 
55
// global definitions and global vars
56
NaviData_t *naviData;
57
mk_param_struct_t *mk_param_struct;
58
uint16_t old_hh = 0;
59
uint8_t Flags_ExtraConfig;
60
uint8_t Flags_GlobalConfig;
61
uint8_t Flags_GlobalConfig3;
62
unsigned char Element;
63
uint16_t heading_home;
64
 
65
// Hier Höhenanzeigefehler Korrigieren
66
#define AltimeterAdjust 1.5
67
 
68
// stats for after flight
69
int16_t max_Altimeter = 0;
70
uint16_t max_GroundSpeed = 0;
71
int16_t max_Distance = 0;
72
uint8_t min_UBat = 255;
73
uint16_t max_FlyingTime = 0;
74
uint16_t max_Current = 0;
75
uint16_t max_Capacity = 0;
76
 
77
// cache old vars for blinking attribute, checkup is faster than full
78
// attribute write each time
79
volatile uint8_t last_UBat = 255;
80
volatile uint8_t last_RC_Quality = 255;
81
 
82
volatile uint16_t ftimer = 0;
83
volatile uint8_t OSD_active;
84
 
85
uint8_t Vario_Beep_Up = 0;
86
uint8_t Vario_Beep_Down = 0;
87
uint8_t Vario_Beep_Up_Interval = 9;
88
uint8_t Vario_Beep_Down_Interval = 6;
89
uint8_t Vario_Threshold = 0;
90
uint8_t Vario_Threshold_Value = 7;
91
uint8_t OldWP=0;
92
uint8_t NextWP = 0;
93
 
94
 
95
 
96
 
97
//char* rose = "-+-N-+-O-+-S-+-W-+-N-+-O-+-S-+-W-+-N-+-O-+-S-+-W";
98
const char rose[48] PROGMEM = {
99
        0x0e, 0x0f, 0x0e, 'N', 0x0e, 0x0f, 0x0e, 'O', 0x0e, 0x0f, 0x0e, 'S',
100
        0x0e, 0x0f, 0x0e, 'W', 0x0e, 0x0f, 0x0e, 'N', 0x0e, 0x0f, 0x0e, 'O',
101
        0x0e, 0x0f, 0x0e, 'S', 0x0e, 0x0f, 0x0e, 'W', 0x0e, 0x0f, 0x0e, 'N',
102
        0x0e, 0x0f, 0x0e, 'O', 0x0e, 0x0f, 0x0e, 'S', 0x0e, 0x0f, 0x0e, 'W',
103
};
104
 
105
// the center is char 19 (north), we add the current heading in 8th
106
// which would be 22.5 degrees, but float would bloat up the code
107
// and *10 / 225 would take ages... so we take the uncorrect way
108
 
109
const char str_NE[] PROGMEM = "NE";
110
const char str_E[] PROGMEM  = "E ";
111
const char str_SE[] PROGMEM = "SE";
112
const char str_S[] PROGMEM  = "S ";
113
const char str_SW[] PROGMEM = "SW";
114
const char str_W[] PROGMEM  = "W ";
115
const char str_NW[] PROGMEM = "NW";
116
const char str_N[] PROGMEM  = "N ";
117
const char *directions_p[8] PROGMEM = {
118
        str_NE,
119
        str_E,
120
        str_SE,
121
        str_S,
122
        str_SW,
123
        str_W,
124
        str_NW,
125
        str_N
126
};
127
 
128
// Positionen der Anzeigeelemente im Bildschirm
129
#define OSD_ALTITUDE_CONTROL            1
130
#define OSD_ALTITUDE                    2
131
#define OSD_BATTERY_LEVEL               3
132
#define OSD_CAPACITY                    4
133
#define OSD_CARE_FREE                   5
134
#define OSD_COMPASS_DEGREE              6
135
#define OSD_COMPASS_DIRECTION           7
136
#define OSD_COMPASS_ROSE                8
137
#define OSD_CURRENT                     9
138
#define OSD_FLYING_TIME                 10
139
#define OSD_GROUND_SPEED                11
140
#define OSD_HOME_CIRCLE                 12
141
#define OSD_HOME_DEGREE                 13
142
#define OSD_HOME_DISTANCE               14
143
#define OSD_LED1_OUTPUT                 15
144
#define OSD_LED2_OUTPUT                 16
145
#define OSD_MANUELL                     17
146
#define OSD_NAVI_MODE                   18
147
#define OSD_RC_INTENSITY                19
148
#define OSD_SATS_IN_USE                 20
149
#define OSD_STATUS_FLAGS                21
150
#define OSD_VARIOMETER                  22
151
#define OSD_TARGET                      23
152
#define OSD_VARIOWERT                   24
153
#define OSD_WAYPOINT                    25
154
#define OSD_TARGET_DEGREE               26
155
 
156
#define MAX_CELL_VOLTAGE 43 // max cell volatage for LiPO
157
#define MIN_CELL_VOLTAGE 32 // min cell volatage for LiPO
158
 
159
// Flags
160
uint8_t COSD_FLAGS2 = 0;
161
 
162
GPS_Pos_t last5pos[7];
163
uint8_t error = 0;
164
uint8_t cells,BattLowVoltageWarning,CellIsChecked = 0;
165
uint8_t AkkuWarnThreshold = 0;
166
 
167
 
168
void CheckMKLipo(void)              // Quelle Mikrokopter FC-Software Holger + Ingo
169
 
170
{
171
 
172
            if(MK_LowBat < 50) // automatische Zellenerkennung
173
              {
174
               if (CellIsChecked <= 2)   //Nur beim Start 1x prüfen
175
                {
176
                        // up to 6s LiPo, less than 2s is technical impossible
177
                        for(cells = 2; cells < 7; cells++)
178
                        {
179
                                if(naviData->UBat < cells * MAX_CELL_VOLTAGE) break;
180
                        }
181
 
182
                        BattLowVoltageWarning = cells * MK_LowBat;
183
                        CellIsChecked++;
184
                }
185
              }
186
            else BattLowVoltageWarning = MK_LowBat;
187
 
188
            if (naviData->UBat < BattLowVoltageWarning)
189
              {
190
 
191
              if (AkkuWarnThreshold <= 4) AkkuWarnThreshold++;
192
              else
193
 
194
                { //Beeper ein
195
 
196
                        set_beep ( 1000, 0x0020, BeepSevere);
197
 
198
//                       BeepTime = 3000;
199
//                       BeepMuster = 0x0020;
200
                }
201
          }
202
 
203
}
204
 
205
//--------------------------------------------------------------
206
// convert the <heading> gotton from NC into an index
207
uint8_t heading_conv (uint16_t heading)
208
{
209
        if (heading > 23 && heading < 68)
210
                return 0;               //direction = "NE";
211
        else if (heading > 67 && heading < 113)
212
                return 1;               //direction = "E ";
213
        else if (heading > 112 && heading < 158)
214
                return 2;               //direction = "SE";
215
        else if (heading > 157 && heading < 203)
216
                return 3;               //direction = "S ";
217
        else if (heading > 202 && heading < 248)
218
                return 4;               //direction = "SW";
219
        else if (heading > 247 && heading < 293)
220
                return 5;               //direction = "W ";
221
        else if (heading > 292 && heading < 338)
222
                return 6;               //direction = "NW";
223
 
224
        return 7;       //direction = "N ";
225
}
226
 
227
//--------------------------------------------------------------
228
// draw a compass rose at <x>/<y> for <heading>
229
void draw_compass (uint8_t x, uint8_t y, uint16_t heading)
230
{
231
        uint8_t front = 19 + (heading / 22);
232
        for (uint8_t i = 0; i < 9; i++)
233
                lcd_putc (x++, y, pgm_read_byte(&rose[front - 4 + i]), 0);
234
}
235
 
236
 
237
//--------------------------------------------------------------
238
// variometer
239
// draw variometer arrows at <x>/<y> according to <variometer>
240
//
241
void draw_variometer (uint8_t x, uint8_t y, uint8_t width, uint8_t hight, int16_t variometer)
242
{
243
        x *= 6;
244
        y *= 8;
245
        y += 7;
246
 
247
        lcd_rect (x, y - ((hight) / 2), width, hight, 1);
248
        lcd_frect (x + 1, y - ((hight) / 2) + 1, width - 2, hight - 2, 0);
249
        lcd_line (x, y, x + width, y, 1);
250
 
251
        if (variometer > 0)  // steigend
252
        {
253
                switch (variometer / 5)
254
                {
255
                        case 0:
256
                                lcd_line  (x + 4, y - 1, x + 6, y - 1, 1);      //  1 >  4
257
                        break;
258
 
259
                        case 1:
260
                                lcd_line  (x + 4, y - 1, x + 6, y - 1, 1);      //  1 >  4
261
                                lcd_frect (x + 3, y - 3, 4, 1, 1);                      //  5 >  9
262
                        break;
263
 
264
                        case 2:
265
                                lcd_line  (x + 4, y - 1, x + 6, y - 1, 1);      //  1 >  4
266
                                lcd_frect (x + 3, y - 3, 4, 1, 1);                      //  5 >  9
267
                                lcd_frect (x + 2, y - 5, 6, 1, 1);                      // 10 > 14
268
                        break;
269
 
270
                        default:
271
                                lcd_line  (x + 4, y - 1, x + 6, y - 1, 1);  //  1 >  4
272
                                lcd_frect (x + 3, y - 3, 4, 1, 1);                      //  5 >  9
273
                                lcd_frect (x + 2, y - 5, 6, 1, 1);                      // 10 > 14
274
                                lcd_frect (x + 1, y - 6, 8, 1, 1);                      // 15 >
275
                        break;
276
                }
277
        }
278
        else if (variometer < 0)  // fallend
279
        {
280
                switch ((variometer) / -5)
281
                {
282
                        case 0:
283
                                lcd_line  (x + 4, y + 1, x + 6, y + 1, 1);      // - 1 > - 4
284
                        break;
285
 
286
                        case 1:
287
                                lcd_line  (x + 4, y + 1, x + 6, y + 1, 1);      // - 1 > - 4
288
                                lcd_frect (x + 3, y + 2, 4, 1, 1);                      // - 5 > - 9
289
                        break;
290
 
291
                        case 2:
292
                                lcd_line  (x + 4, y + 1, x + 6, y + 1, 1);      // - 1 > - 4
293
                                lcd_frect (x + 3, y + 2, 4, 1, 1);                      // - 5 > - 9
294
                                lcd_frect (x + 2, y + 4, 6, 1, 1);                      // -10 > -14
295
                        break;
296
 
297
                        default:
298
                                lcd_line  (x + 4, y + 1, x + 6, y + 1, 1);      // - 1 > - 4
299
                                lcd_frect (x + 3, y + 2, 4, 1, 1);                      // - 5 > - 9
300
                                lcd_frect (x + 2, y + 4, 6, 1, 1);                      // -10 > -14
301
                                lcd_frect (x + 1, y + 5, 8, 1, 1);                      // -15 >
302
                        break;
303
                }
304
        }
305
}
306
//--------------------------------------------------------------
307
// Home symbol
308
// draw Homesymbol at <x>/<y>
309
//
310
void draw_homesymbol (uint8_t x, uint8_t y)
311
{
312
 
313
        x *= 6;
314
        y *= 8;
315
        y += 7;
316
 
317
        lcd_plot (x,y-4,1);
318
        lcd_line (x+1,y-1,x+1,y-5,1);
319
        lcd_plot (x+2,y-6,1);
320
        lcd_plot (x+3,y-7,1);
321
        lcd_plot (x+4,y-6,1);
322
        lcd_line (x+5,y-1,x+5,y-5,1);
323
        lcd_plot (x+6,y-4,1);
324
        lcd_plot (x+3,y-1,1);
325
        lcd_plot (x+3,y-2,1);
326
        lcd_line (x+1,y,x+5,y,1);
327
 
328
}
329
//--------------------------------------------------------------
330
// Target symbol
331
// draw Targetsymbol at <x>/<y>
332
//
333
void draw_targetsymbol (uint8_t x, uint8_t y)
334
{
335
 
336
        x *= 6;
337
        y *= 8;
338
        y += 7;
339
 
340
        lcd_circle (x+3, y-3, 4, 1);
341
        lcd_line (x,y-3,x+6,y-3,1);
342
        lcd_line (x+3,y,x+3,y-6,1);
343
        lcd_circle (x+3, y-3, 2, 1);
344
}
345
//--------------------------------------------------------------
346
void print_statistics (void)
347
{
348
        uint8_t line = 0;
349
        lcd_cls ();
350
        lcd_puts_at(12, 7, strGet(ENDE), 0);
351
 
352
        // max Altitude
353
        lcd_puts_at (0, line, strGet(STATS_ITEM_0), 0);
354
        write_ndigit_number_s (14, line, max_Altimeter / (30 / AltimeterAdjust), 4, 0,0);
355
        lcd_putc (18, line, 'm', 0);
356
//      max_GroundSpeed = 1;
357
        // max Speed
358
        lcd_puts_at (0, ++line, strGet(STATS_ITEM_1), 0);
359
        write_ndigit_number_u (15, line, (uint16_t) (((uint32_t) max_GroundSpeed * (uint32_t) 9) / (uint32_t) 250), 3, 0,0);
360
        lcd_printp_at(18, line, PSTR("kmh"), 0);
361
 
362
        // max Distance
363
//      max_Distance = 64512;
364
        lcd_puts_at (0, ++line, strGet(STATS_ITEM_2), 0);
365
        write_ndigit_number_u (15, line, max_Distance / 10, 4, 0,0);
366
        lcd_putc (19, line, 'm', 0);
367
//      max_FlyingTime = 3600;
368
        // max time
369
        lcd_puts_at (0, ++line, strGet(STATS_ITEM_4), 0);
370
        write_time (14, line, max_FlyingTime);
371
        lcd_putc (19, line, 'm', 0);
372
 
373
        // min voltage
374
        lcd_puts_at (0, ++line, strGet(STATS_ITEM_3), 0);
375
        write_ndigit_number_u_10th (14, line, min_UBat, 3, 0,0);
376
        lcd_putc (18, line, 'V', 0);
377
 
378
#if 1
379
//      max_Current = 1000;
380
        // max Current
381
        lcd_puts_at (0, ++line, strGet(STATS_ITEM_5), 0);
382
        write_ndigit_number_u_10th (14, line, max_Current, 4, 0,0);
383
        lcd_putc (19, line, 'A', 0);
384
 
385
        // Used Capacity
386
        lcd_puts_at (0, ++line, strGet(STATS_ITEM_6), 0);
387
        write_ndigit_number_u (14, line, max_Capacity, 4, 0,0);
388
        lcd_printp_at(18, line, PSTR("mAh"), 0);
389
#else
390
        // longitude
391
        lcd_puts_at (0, ++line, strGet(STATS_ITEM_7), 0);
392
        write_gps_pos (8, line, naviData->CurrentPosition.Longitude);
393
 
394
        // latitude
395
        lcd_puts_at (0, ++line, strGet(STATS_ITEM_8), 0);
396
        write_gps_pos (8, line, naviData->CurrentPosition.Latitude);
397
#endif
398
 
399
        while (!get_key_press (1 << KEY_ESC))
400
                timer = TIMEOUT;
401
 
402
        COSD_FLAGS2 &= ~COSD_WASFLYING;
403
        get_key_press(KEY_ALL);
404
        lcd_cls();
405
}
406
 
407
//--------------------------------------------------------------
408
void print_position (void)
409
{
410
        lcd_cls ();
411
        lcd_puts_at(0, 0, strGet(START_LASTPOS1), 2);   // Breitengr  Längengr
412
        lcd_puts_at(12, 7, strGet(ENDE), 0);
413
        uint8_t ij =0;
414
 
415
        for(ij=0;ij<6;ij++)
416
        {
417
                uint32_t lon = last5pos[ij].Latitude;
418
                write_ndigit_number_u (1, ij+1, (uint16_t)(lon/10000000), 2, 0,0);
419
                lcd_printp_at (3, ij+1, PSTR("."), 0);
420
                write_ndigit_number_u (4, ij+1, (uint16_t)((lon/1000) % 10000), 4, 1,0);
421
                write_ndigit_number_u (8, ij+1, (uint16_t)((lon/10) % 100), 2, 1,0);
422
 
423
                uint32_t lat = last5pos[ij].Longitude;
424
                write_ndigit_number_u (12, ij+1, (uint16_t)(lat/10000000), 2, 0,0);
425
                lcd_printp_at (14, ij+1, PSTR("."), 0);
426
                write_ndigit_number_u (15, ij+1, (uint16_t)((lat/1000) % 10000), 4, 1,0);
427
                write_ndigit_number_u (19, ij+1, (uint16_t)((lat/10) % 100), 2, 1,0);
428
        }
429
 
430
        while (!get_key_press (1 << KEY_ESC))
431
                timer = TIMEOUT;
432
 
433
        get_key_press(KEY_ALL);
434
        lcd_cls();
435
}
436
 
437
//--------------------------------------------------------------
438
void Show_LastPosition(void)
439
{
440
        lcd_puts_at(0, 2, strGet(OSD_POS1), 0);
441
        lcd_puts_at(0, 3, strGet(OSD_POS2), 0);
442
        lcd_puts_at(0, 5, strGet(START_LASTPOS1), 0);
443
        uint32_t lon = last5pos[0].Latitude;
444
        write_ndigit_number_u (1, 6, (uint16_t)(lon/10000000), 2, 0,0);
445
        lcd_printp_at (3, 6, PSTR("."), 0);
446
        write_ndigit_number_u (4, 6, (uint16_t)((lon/1000) % 10000), 4, 1,0);
447
        write_ndigit_number_u (8, 6, (uint16_t)((lon/10) % 100), 2, 1,0);
448
 
449
        uint32_t lat = last5pos[0].Longitude;
450
        write_ndigit_number_u (12, 6, (uint16_t)(lat/10000000), 2, 0,0);
451
        lcd_printp_at (14, 6, PSTR("."), 0);
452
        write_ndigit_number_u (15, 6, (uint16_t)((lat/1000) % 10000), 4, 1,0);
453
        write_ndigit_number_u (19, 6, (uint16_t)((lat/10) % 100), 2, 1,0);
454
 
455
}
456
 
457
//--------------------------------------------------------------
458
void OSD_Timeout(uint8_t flag)
459
{
460
 
461
//      uint8_t flag;
462
        uint8_t tmp_dat;
463
//      flag = 0;
464
        timer = TIMEOUT;
465
        // disable OSD Data from NC
466
//      RS232_request_mk_data (1, 'o', 0);
467
//      tmp_dat = 0;
468
//      SendOutData ('o', ADDRESS_NC, 1, &tmp_dat, 1);
469
 
470
        mode = 0;
471
        rxd_buffer_locked = FALSE;
472
 
473
 
474
        // Bei Verbindungsverlusst werden hier die letzten bekannten Koordinaten ausgegeben!!!
475
        if (flag)
476
        {
477
                // Falls Spannungswarnung an war Beeper aus//
478
 
479
                set_beep ( 0, 0, BeepOff);
480
 
481
                lcd_cls ();
482
                WriteLastPosition(last5pos[0].Longitude,last5pos[0].Latitude);  // im EEprom speichern
483
                lcd_puts_at(0, 0, strGet(OSD_ERROR), 2);                                                // ERROR: Datenverlust
484
                lcd_puts_at(0, 2, strGet(OSD_POS1), 0);                                                 // Letzte bekannte
485
                lcd_puts_at(0, 3, strGet(OSD_POS2), 0);                                                 // Position gespeichert.
486
                lcd_puts_at(0, 5, strGet(START_LASTPOS1), 0);                                   // Breitengr  Längengr
487
//              lcd_puts_at(12, 7, strGet(ENDE), 0);
488
//              lcd_puts_at(19, 7, strGet(OK), 0);
489
//              if (OSD_RCErrorbeep==true)
490
//              {
491
                set_beep ( 250, 0x0040, BeepNormal);
492
 
493
//              }
494
                error = 1;
495
 
496
                uint32_t lon = last5pos[0].Latitude;
497
                write_ndigit_number_u (1, 6, (uint16_t)(lon/10000000), 2, 0,0);
498
                lcd_printp_at (3, 6, PSTR("."), 0);
499
                write_ndigit_number_u (4, 6, (uint16_t)((lon/1000) % 10000), 4, 1,0);
500
                write_ndigit_number_u (8, 6, (uint16_t)((lon/10) % 100), 2, 1,0);
501
 
502
                uint32_t lat = last5pos[0].Longitude;
503
                write_ndigit_number_u (12, 6, (uint16_t)(lat/10000000), 2, 0,0);
504
                lcd_printp_at (14, 6, PSTR("."), 0);
505
                write_ndigit_number_u (15, 6, (uint16_t)((lat/1000) % 10000), 4, 1,0);
506
                write_ndigit_number_u (19, 6, (uint16_t)((lat/10) % 100), 2, 1,0);
507
 
508
//              while (!get_key_press (1 << KEY_ENTER));
509
//              _delay_ms(1000);
510
                timer = TIMEOUT;
511
//              lcd_cls();
512
//              return;
513
 
514
 
515
        }
516
        else
517
        {
518
                lcd_puts_at(0, 0, strGet(OSD_ERROR), 2);
519
                Show_LastPosition();
520
                if (OSD_RCErrorbeep==true) set_beep ( 200, 0x0080, BeepNormal);
521
 
522
 
523
//              _delay_ms(2000);
524
        }
525
 
526
        SwitchToNC();
527
 
528
        mode = 'O';
529
 
530
        // disable debug...
531
//      RS232_request_mk_data (0, 'd', 0);
532
        tmp_dat = 0;
533
        SendOutData ('d', ADDRESS_ANY, 1, &tmp_dat, 1);
534
 
535
        // request OSD Data from NC every 100ms
536
//      RS232_request_mk_data (1, 'o', 100);
537
        tmp_dat = 10;
538
        SendOutData ('o', ADDRESS_NC, 1, &tmp_dat, 1);
539
 
540
 
541
}
542
 
543
 
544
 
545
 
546
//-----------------------------------------------------------
547
//
548
void lcd_o_circle (int16_t x, int16_t y, int16_t breite, uint8_t mode)
549
{
550
        breite *= 6;
551
        int16_t radius = breite / 2;
552
        x += 2;
553
        x *= 6;
554
        x += 2;
555
        y += 1;
556
        y *= 8;
557
        y += 3;
558
 
559
        lcd_ellipse (x, y, radius - 3, radius - 5, mode);
560
}
561
 
562
 
563
//-----------------------------------------------------------
564
//
565
void lcd_o_circ_line (uint8_t x, uint8_t y, uint8_t breite, uint16_t deg, uint8_t mode)
566
{
567
        breite *= 6;
568
        int16_t radius = breite / 3;
569
        x += 2;
570
        x *= 6;
571
        x += 2;
572
        y += 1;
573
        y *= 8;
574
        y += 3;
575
 
576
        lcd_ellipse_line(x, y, radius, radius, deg, mode);
577
}
578
 
579
 
580
//--------------------------------------------------------------
581
void osd (uint8_t ShowMode)
582
{
583
        uint8_t flag;
584
        uint8_t tmp_dat;
585
        uint8_t OSD_Mode;
586
        uint8_t info_3D = 0;
587
        uint8_t status;
588
 
589
 
590
 
591
        // Clear statistics
592
        max_Altimeter = 0;
593
        max_GroundSpeed = 0;
594
        max_Distance = 0;
595
        min_UBat = 255;
596
        max_FlyingTime = 0;
597
        CellIsChecked = 0;
598
        cells = 0;
599
        AkkuWarnThreshold=0;
600
        OldWP=0;
601
        NextWP = false;
602
 
603
        // flags from last round to check for changes
604
        uint8_t old_FCFlags = 0;
605
 
606
        uint8_t old_AngleNick = 0;
607
        uint8_t old_AngleRoll = 0;
608
        lcd_cls();
609
        OSD_Mode = ShowMode;
610
 
611
        if (hardware == FC)
612
        {
613
                lcd_puts_at(0, 3, strGet(ONLY_NC), 0);  // Nur mit NC
614
                timer = 100;
615
                while (timer > 0);
616
 
617
                return;
618
        }
619
 
620
        SwitchToFC();
621
 
622
        status = load_setting(0xff);
623
        if(status == 255)
624
        {
625
                lcd_puts_at(0, 0, strGet(NO_SETTINGS), 0);      // Keine Setings
626
                _delay_ms(2000);
627
        }
628
        Flags_ExtraConfig = mk_param_struct->ExtraConfig;
629
        Flags_GlobalConfig = mk_param_struct->GlobalConfig;
630
        Flags_GlobalConfig3 = mk_param_struct->GlobalConfig3;
631
 
632
        SwitchToNC();
633
 
634
        mode = 'O';
635
 
636
        // disable debug...
637
        //      RS232_request_mk_data (0, 'd', 0);
638
        tmp_dat = 0;
639
        SendOutData ('d', ADDRESS_ANY, 1, &tmp_dat, 1);
640
 
641
        // request OSD Data from NC every 100ms
642
        //      RS232_request_mk_data (1, 'o', 100);
643
        tmp_dat = 10;
644
        OSD_active = true;              // benötigt für Navidata Ausgabe an SV2
645
        SendOutData ('o', ADDRESS_NC, 1, &tmp_dat, 1);
646
 
647
        flag = 0;
648
        timer = TIMEOUT;
649
        abo_timer = ABO_TIMEOUT;
650
//??    lcd_putc (10,5,0x18,1);
651
 
652
 
653
        do
654
        {
655
                if (rxd_buffer_locked)
656
                {
657
                        timer = TIMEOUT;
658
                        Decode64 ();
659
                        naviData = (NaviData_t *) pRxData;
660
 
661
                        if(error == 1)
662
                                lcd_cls();
663
 
664
                        error = 0;
665
                        GPS_Pos_t currpos;
666
                        currpos.Latitude = naviData->CurrentPosition.Latitude;
667
                        currpos.Longitude = naviData->CurrentPosition.Longitude;
668
 
669
                        if((currpos.Latitude != last5pos[0].Latitude)&&(currpos.Longitude != last5pos[0].Longitude))
670
                        {
671
                                last5pos[6] = last5pos[5];
672
                                last5pos[5] = last5pos[4];
673
                                last5pos[4] = last5pos[3];
674
                                last5pos[3] = last5pos[2];
675
                                last5pos[2] = last5pos[1];
676
                                last5pos[1] = last5pos[0];
677
                                last5pos[0] = currpos;
678
                        }
679
 
680
                        flag = 1;
681
 
682
                        if (OSD_Mode == 1)
683
                        {
684
                                if (naviData->FCStatusFlags & FC_STATUS_MOTOR_RUN)
685
                                { // should be engines running
686
                                        // motors are on, assume we were/are flying
687
                                        COSD_FLAGS2 |= COSD_WASFLYING;
688
                                }
689
                                else
690
                                {       // stats
691
                                        if ((COSD_FLAGS2 & COSD_WASFLYING) | (get_key_press (1 << KEY_ENTER)))
692
                                          {
693
                                                print_statistics ();
694
//                                              draw_homesymbol(9,5);
695
//                                              draw_targetsymbol(9,6);
696
 
697
                                          }
698
 
699
                                        if (get_key_press (1 << KEY_PLUS))
700
                                          {
701
                                                print_position ();
702
//                                              draw_homesymbol(9,5);
703
//                                              draw_targetsymbol(9,6);
704
 
705
                                          }
706
                                }
707
 
708
                                // Altitude Control
709
                                switch (OSD_ScreenMode)
710
                                  {
711
                                    case    0 :  OSD_Screen_Element (0, 3, OSD_ALTITUDE_CONTROL); break;
712
                                    case    1 :   break;
713
                                    case    2 : OSD_Screen_Element (0, 1, OSD_ALTITUDE_CONTROL);break;
714
                                    break;
715
                                  }
716
 
717
 
718
                                // Altitude
719
 
720
                                switch (OSD_ScreenMode)
721
                                  {
722
                                    case    0 :  OSD_Screen_Element (11, 3, OSD_ALTITUDE); break;
723
                                    case    1 :  OSD_Screen_Element (1, 1, OSD_ALTITUDE); break;
724
                                    case    2 :  OSD_Screen_Element (1, 4, OSD_ALTITUDE); break;
725
                                    break;
726
                                  }
727
                                // Battery level
728
                                switch (OSD_ScreenMode)
729
                                  {
730
                                    case    0 :  OSD_Screen_Element (0, 7, OSD_BATTERY_LEVEL); break;
731
                                    case    1 :  OSD_Screen_Element (0, 7, OSD_BATTERY_LEVEL); break;
732
                                    case    2 :  OSD_Screen_Element (13, 7, OSD_BATTERY_LEVEL); break;
733
                                    break;
734
                                  }
735
 
736
                                // Capacity
737
                                switch (OSD_ScreenMode)
738
                                  {
739
                                    case    0 :  OSD_Screen_Element (13, 7, OSD_CAPACITY); break;
740
                                    case    1 :  OSD_Screen_Element (13, 7, OSD_CAPACITY); break;
741
                                    case    2 :  OSD_Screen_Element (0, 7, OSD_CAPACITY); break;
742
                                    break;
743
                                  }
744
 
745
 
746
                                // Current
747
                                switch (OSD_ScreenMode)
748
                                  {
749
                                    case    0 :   OSD_Screen_Element (8, 7, OSD_CURRENT); break;
750
                                    case    1 :   OSD_Screen_Element (8, 7, OSD_CURRENT); break;
751
                                    case    2 :   OSD_Screen_Element (8, 7, OSD_CURRENT); break;
752
                                    break;
753
                                  }
754
 
755
 
756
                                // Care Free
757
                                switch (OSD_ScreenMode)
758
                                  {
759
                                    case    0 :  OSD_Screen_Element (0, 5, OSD_CARE_FREE); break;
760
                                    case    1 :  break;
761
                                    case    2 :  OSD_Screen_Element (0, 3, OSD_CARE_FREE); break;
762
                                    break;
763
                                  }
764
 
765
 
766
                                // Compass Degree
767
                                switch (OSD_ScreenMode)
768
                                  {
769
                                    case    0 :  OSD_Screen_Element (13, 0, OSD_COMPASS_DEGREE); break;
770
                                    case    1 :  OSD_Screen_Element (13, 0, OSD_COMPASS_DEGREE); break;
771
                                    case    2 :  OSD_Screen_Element (12, 3, OSD_COMPASS_DEGREE);break;
772
                                    break;
773
                                  }
774
 
775
 
776
                                // Compass Direction
777
                                switch (OSD_ScreenMode)
778
                                  {
779
                                    case    0 :  OSD_Screen_Element (18, 0, OSD_COMPASS_DIRECTION); break;
780
                                    case    1 :  OSD_Screen_Element (18, 0, OSD_COMPASS_DIRECTION); break;
781
                                    case    2 : break;
782
                                    break;
783
                                  }
784
 
785
 
786
                                // Compass Rose
787
                                switch (OSD_ScreenMode)
788
                                  {
789
                                    case    0 :  OSD_Screen_Element (12, 1, OSD_COMPASS_ROSE); break;
790
                                    case    1 :  OSD_Screen_Element (12, 1, OSD_COMPASS_ROSE); break;
791
                                    case    2 :  break;
792
                                    break;
793
                                  }
794
 
795
 
796
 
797
 
798
                                // Flying time
799
                                switch (OSD_ScreenMode)
800
                                  {
801
                                    case    0 :  OSD_Screen_Element (0, 1, OSD_FLYING_TIME); break;
802
                                    case    1 :  OSD_Screen_Element (7, 6, OSD_FLYING_TIME); break;
803
                                    case    2 :  OSD_Screen_Element (15, 5, OSD_FLYING_TIME); break;
804
                                    break;
805
                                  }
806
 
807
 
808
                                // Ground Speed
809
                                switch (OSD_ScreenMode)
810
                                  {
811
                                    case    0 :  OSD_Screen_Element (0, 0, OSD_GROUND_SPEED); break;
812
                                    case    1 :  OSD_Screen_Element (0, 0, OSD_GROUND_SPEED); break;
813
                                    case    2  : break;
814
                                    break;
815
                                  }
816
 
817
 
818
                                // Home Circle
819
                                switch (OSD_ScreenMode)
820
                                  {
821
                                    case    0 :  OSD_Screen_Element (16, 4, OSD_HOME_CIRCLE); break;
822
                                    case    1 :  OSD_Screen_Element (1, 3, OSD_HOME_CIRCLE); break;
823
                                    case    2 :  OSD_Screen_Element (16, 0, OSD_HOME_CIRCLE); break;
824
                                    break;
825
                                  }
826
 
827
 
828
                                // Home Degree
829
                                switch (OSD_ScreenMode)
830
                                  {
831
                                    case    0 :  OSD_Screen_Element (12, 4, OSD_HOME_DEGREE); break;
832
                                    case    1 :  OSD_Screen_Element (8, 3, OSD_HOME_DEGREE); break;
833
                                    case    2 :  OSD_Screen_Element (11, 5, OSD_HOME_DEGREE); break;
834
                                    break;
835
                                  }
836
 
837
 
838
                                // Home Distance
839
                                switch (OSD_ScreenMode)
840
                                  {
841
                                    case    0 :  OSD_Screen_Element (10, 5, OSD_HOME_DISTANCE); break;
842
                                    case    1 :  OSD_Screen_Element (7, 2, OSD_HOME_DISTANCE); break;
843
                                    case    2 :  OSD_Screen_Element (0, 5, OSD_HOME_DISTANCE); break;
844
                                    break;
845
                                  }
846
 
847
 
848
                                // Target Distance
849
                                switch (OSD_ScreenMode)
850
                                  {
851
                                    case    0 :  OSD_Screen_Element (10, 6, OSD_TARGET); break;
852
                                    case    1 :  break;
853
                                    case    2 :  OSD_Screen_Element (0, 6, OSD_TARGET); break;
854
                                    break;
855
                                  }
856
                                // Target Bearing
857
                                switch (OSD_ScreenMode)
858
                                  {
859
                                    case    0 :  break;
860
                                    case    1 :  break;
861
                                    case    2 :  OSD_Screen_Element (11, 6, OSD_TARGET_DEGREE); break;
862
                                    break;
863
                                  }
864
                                // Waypointnumber
865
                                switch (OSD_ScreenMode)
866
                                  {
867
                                    case    0 :  OSD_Screen_Element (5, 6, OSD_WAYPOINT); break;
868
                                    case    1 :  break;
869
                                    case    2 : break;
870
 
871
                                    break;
872
                                  }
873
 
874
                                // LED1 Output
875
                                switch (OSD_ScreenMode)
876
                                  {
877
                                    case    0 :  OSD_Screen_Element (0, 6, OSD_LED1_OUTPUT); break;
878
                                    case    1 :  break;
879
                                    case    2 :  OSD_Screen_Element (12, 2, OSD_LED1_OUTPUT); break;
880
                                    break;
881
                                  }
882
 
883
 
884
 
885
                                // LED2 Output
886
                                switch (OSD_ScreenMode)
887
                                  {
888
                                    case    0 :  OSD_Screen_Element (3, 6, OSD_LED2_OUTPUT); break;
889
                                    case    1 :  break;
890
                                    case    2 :  OSD_Screen_Element (14, 2, OSD_LED2_OUTPUT); break;
891
                                    break;
892
                                  }
893
 
894
                                // Manuell
895
                        //      OSD_Screen_Element (7, 0, OSD_MANUELL);
896
 
897
                                // Navi Mode
898
                                switch (OSD_ScreenMode)
899
                                  {
900
                                    case    0 :  OSD_Screen_Element (0, 4, OSD_NAVI_MODE); break;
901
                                    case    1 :  OSD_Screen_Element (8, 5, OSD_NAVI_MODE); break;
902
                                    case    2 :  OSD_Screen_Element (0, 2, OSD_NAVI_MODE); break;
903
                                    break;
904
                                  }
905
 
906
 
907
                                // RC Intensity
908
 
909
                                switch (OSD_ScreenMode)
910
                                  {
911
                                    case    0 :  break;
912
                                    case    1 :  OSD_Screen_Element (15, 6, OSD_RC_INTENSITY);break;
913
                                    case    2 :  break;
914
                                    break;
915
                                  }
916
                                // Variometer Wert
917
                                switch (OSD_ScreenMode)
918
                                  {
919
                                    case    0 :  OSD_Screen_Element (11, 2, OSD_VARIOWERT); break;
920
                                    case    1 :  OSD_Screen_Element (14, 2, OSD_VARIOWERT); break;
921
                                    case    2 :  OSD_Screen_Element (8, 4, OSD_VARIOWERT); break;
922
                                    break;
923
                                  }
924
 
925
 
926
                                // Sats in use
927
                                switch (OSD_ScreenMode)
928
                                  {
929
                                    case    0 :  OSD_Screen_Element (18, 2, OSD_SATS_IN_USE); break;
930
                                    case    1 :  OSD_Screen_Element (8, 4, OSD_SATS_IN_USE); break;
931
                                    case    2 :  OSD_Screen_Element (10, 0, OSD_SATS_IN_USE); break;
932
                                    break;
933
                                  }
934
 
935
 
936
                                // Status Flags
937
                                switch (OSD_ScreenMode)
938
                                  {
939
                                    case    0 : OSD_Screen_Element (0, 2, OSD_STATUS_FLAGS); break;
940
                                    case    1 : break;
941
                                    case    2 : OSD_Screen_Element (0, 0, OSD_STATUS_FLAGS); break;
942
                                    break;
943
                                  }
944
 
945
 
946
                                // Variometer Grafik
947
                                switch (OSD_ScreenMode)
948
                                  {
949
                                    case    0 : OSD_Screen_Element (9, 0, OSD_VARIOMETER); break;
950
                                    case    1 : OSD_Screen_Element (9, 0, OSD_VARIOMETER); break;
951
                                    case    2 : break;
952
                                    break;
953
                                  }
954
 
955
 
956
 
957
                                // Akku Warnung
958
                                CheckMKLipo();
959
 
960
//                              if (naviData->UBat > MK_LowBat)  //bei kurzzeitigen Schwankungen Beeper erst wieder aus wenn UBat 0,2 V höher als Warnschwelle
961
//                              { //Beeper aus
962
//                                      BeepTime = 0;
963
//                                      BeepMuster = 0xFFFF;
964
//                              }
965
//                               Akku Warnung Ende
966
 
967
                                // remember statistics (only when engines running)
968
                                if (naviData->FCStatusFlags & FC_STATUS_MOTOR_RUN)
969
                                {
970
                                        if (naviData->Altimeter > max_Altimeter) max_Altimeter = naviData->Altimeter;
971
                                        if (naviData->GroundSpeed > max_GroundSpeed) max_GroundSpeed = naviData->GroundSpeed;
972
                                        if (naviData->HomePositionDeviation.Distance > max_Distance) max_Distance = naviData->HomePositionDeviation.Distance;
973
                                        if (naviData->UBat < min_UBat) min_UBat = naviData->UBat;
974
                                        if (naviData->FlyingTime > max_FlyingTime) max_FlyingTime = naviData->FlyingTime;
975
                                        if (naviData->Current > max_Current) max_Current = naviData->Current;
976
                                        if (naviData->UsedCapacity > max_Capacity) max_Capacity = naviData->UsedCapacity;
977
                                }
978
 
979
                                // remember last values
980
                                last_RC_Quality = naviData->RC_Quality;
981
                                last_UBat = naviData->UBat;
982
                                old_FCFlags = naviData->FCStatusFlags;
983
 
984
                                rxd_buffer_locked = FALSE;
985
                        }
986
        // 3D Lage anzeige beginnt hier -----------------------------------
987
                        else if (OSD_Mode == 3)
988
                        {
989
                                uint16_t head_home = (naviData->HomePositionDeviation.Bearing + 360 - naviData->CompassHeading) % 360;
990
 
991
                                lcd_cls ();
992
 
993
                                lcd_line(26,32,100,32,1);  // horizontal //
994
                                lcd_line(63,0,63,63,1);    //  vertical  //
995
                                lcd_puts_at(12, 7, strGet(KEYLINE5), 0);
996
 
997
                                // 45' Angel
998
                                lcd_line(61,11,65,11,1);   //    --    //
999
                                lcd_line(40,30,40,34,1);   //  |       //
1000
                                lcd_line(86,30,86,34,1);   //       |  //
1001
                                lcd_line(61,53,65,53,1);   //    --    //
1002
 
1003
                                if (info_3D == 1)
1004
                                {
1005
                                        lcd_puts_at(9, 0, strGet(OSD_3D_V), 0);  // V
1006
                                        lcd_puts_at(3, 3, strGet(OSD_3D_L), 0);  // L
1007
                                        lcd_puts_at(17, 3, strGet(OSD_3D_R), 0); // R
1008
                                        lcd_puts_at(9, 7, strGet(OSD_3D_H), 0);  // H
1009
 
1010
                                        lcd_puts_at(0, 0, strGet(OSD_3D_NICK), 0);      // Ni
1011
                                        write_ndigit_number_s (2, 0, naviData->AngleNick, 3, 0,0);
1012
                                        lcd_putc (5, 0, 0x1e, 0);       // degree symbol
1013
 
1014
                                        lcd_puts_at(0, 7, strGet(OSD_3D_ROLL), 0);      // Ro
1015
                                        write_ndigit_number_s (2, 7, naviData->AngleRoll, 3, 0,0);
1016
                                        lcd_putc (5, 7, 0x1e, 0);       // degree symbol
1017
 
1018
                                        lcd_puts_at(13, 0, strGet(OSD_3D_COMPASS), 0);
1019
//                                      write_ndigit_number_s (15, 0,head_home, 3, 0);
1020
                                        write_ndigit_number_u (15, 0, naviData->CompassHeading, 3, 0,0);
1021
                                        lcd_putc (18, 0, 0x1e, 0);      // degree symbol
1022
                                        lcd_printp_at (19, 0, (const char *) (pgm_read_word ( &(directions_p[heading_conv(naviData->CompassHeading)]))), 0);
1023
                                }
1024
 
1025
                                if (get_key_press (1 << KEY_ENTER))
1026
                                {
1027
                                        info_3D++;
1028
                                        if (info_3D > 1)
1029
                                                info_3D = 0;
1030
                                }
1031
 
1032
                                uint8_t Nick = ((-naviData->AngleNick/2)+32);
1033
                                uint8_t Roll = ((-naviData->AngleRoll/2)+63);
1034
 
1035
                                lcd_ellipse(old_AngleRoll,old_AngleNick, 9, 8, 0);
1036
                                lcd_ellipse_line (old_AngleRoll, old_AngleNick, 8, 7, old_hh, 0);
1037
 
1038
                                lcd_ellipse(Roll, Nick, 9, 8, 1);
1039
                                lcd_ellipse_line (Roll, Nick, 8, 7, head_home, 1);
1040
 
1041
                                old_hh = head_home;
1042
                                old_AngleNick = Nick;
1043
                                old_AngleRoll = Roll;
1044
                                // remember last values
1045
                                last_RC_Quality = naviData->RC_Quality;
1046
                                last_UBat = naviData->UBat;
1047
                                old_FCFlags = naviData->FCStatusFlags;
1048
                                rxd_buffer_locked = FALSE;
1049
                        }
1050
 
1051
                        if (!abo_timer)
1052
                        {       // renew abo every 3 sec
1053
                                // request OSD Data from NC every 100ms
1054
                                //      RS232_request_mk_data (1, 'o', 100);
1055
                                tmp_dat = 10;
1056
                                SendOutData ('o', ADDRESS_NC, 1, &tmp_dat, 1);
1057
 
1058
                                abo_timer = ABO_TIMEOUT;
1059
                        }
1060
                }
1061
                if (!timer)
1062
                {
1063
                        OSD_Timeout(flag);
1064
                        flag = 0;
1065
                        error = 1;
1066
 
1067
                }
1068
        }
1069
 
1070
        while (!get_key_press (1 << KEY_ESC));
1071
        OSD_active = false;
1072
 
1073
}
1074
 
1075
 
1076
//-----------------------------------------------------------
1077
//
1078
void OSD_Screen_Element (uint8_t x, uint8_t y, uint8_t Element)
1079
{
1080
  uint8_t FC_Fallspeed;
1081
  uint16_t Balken = 0;
1082
 
1083
        switch (Element)
1084
        {
1085
        case OSD_ALTITUDE_CONTROL:
1086
                if (Flags_ExtraConfig & CFG2_HEIGHT_LIMIT)
1087
                {
1088
                        if (naviData->FCStatusFlags2 & FC_STATUS2_ALTITUDE_CONTROL)
1089
                                lcd_puts_at (x, y, strGet(OSD_ALTI_1), 0);      // Höhe begr.
1090
                        else
1091
                                lcd_puts_at (x, y, strGet(OSD_ALTI_0), 0);      // Höhe aus
1092
                }
1093
                else
1094
                {
1095
                        if (naviData->FCStatusFlags2 & FC_STATUS2_ALTITUDE_CONTROL)
1096
                                lcd_puts_at (x, y, strGet(OSD_VARIO_1), 0);     // Vario Höhe
1097
                        else
1098
                                lcd_puts_at (x, y, strGet(OSD_VARIO_0), 0);     // Vario aus
1099
                }
1100
                break;
1101
 
1102
        case OSD_ALTITUDE:
1103
                //note:lephisto:according to several sources it's /30
1104
                if (naviData->Altimeter > (300 / AltimeterAdjust) || naviData->Altimeter < (-300 / AltimeterAdjust))    // above 10m only write full meters
1105
                        write_ndigit_number_s (x, y, naviData->Altimeter / (30 / AltimeterAdjust), 4, 0,0);
1106
                else    // up to 10m write meters.dm
1107
                        write_ndigit_number_s_10th (x, y, naviData->Altimeter / (3 / AltimeterAdjust), 3, 0,0);
1108
 
1109
                lcd_printp_at (x+4, y, PSTR("m"), 0);
1110
                lcd_putc (x+5, y, 0x09, 0);
1111
 
1112
                break;
1113
 
1114
        case OSD_BATTERY_LEVEL:
1115
 
1116
          {
1117
                    if ((OSD_LipoBar==1) &&(cells>0))  // LipobargraphAnzeige nur wenn Anzahl der Lipozellen bekannt sind
1118
                      {
1119
                        {
1120
                        if (naviData->UBat < BattLowVoltageWarning)
1121
 
1122
                          {
1123
                            write_ndigit_number_u (x+6, y, cells, 1, 0,2);
1124
                            lcd_printp_at (x+7, y, PSTR("S"), 2);
1125
                          }
1126
                        else
1127
                          {
1128
                            write_ndigit_number_u (x+6, y, cells, 1, 0,0);
1129
                            lcd_printp_at (x+7, y, PSTR("S"), 0);
1130
                          }
1131
                        }
1132
 
1133
                        if (cells==3)
1134
 
1135
                          {
1136
 
1137
                            lcd_rect(x*6, y*8, 28, 7, 1);  // Rahmen
1138
                            Balken = ((naviData->UBat-(cells*MIN_CELL_VOLTAGE))*10)/12;
1139
                            if ((Balken > 0) && (Balken <28)) lcd_frect((x*6)+1, (y*8)+1, Balken, 5, 1);  // Füllung
1140
                            if (Balken <= 26) lcd_frect(Balken+(x*6)+1, (y*8)+1, 26-Balken, 5, 0);  // löschen
1141
                          }
1142
 
1143
                        if (cells==4 ||cells==5 )
1144
                          {
1145
                             lcd_rect(x*6, y*8, 30, 7, 1);  // Rahmen
1146
                             if (cells == 4) Balken = ((naviData->UBat-(cells*MIN_CELL_VOLTAGE))*10)/15;
1147
                             if (cells == 5) Balken = ((naviData->UBat-(cells*MIN_CELL_VOLTAGE))*10)/19;
1148
                             if ((Balken > 0) && (Balken <=29)) lcd_frect((x*6)+1, (y*8)+1, Balken, 5, 1);  // Füllung
1149
                             if (Balken <= 27) lcd_frect(Balken+(x*6)+1, (y*8)+1, 28-Balken, 5, 0);  // löschen
1150
                          }
1151
 
1152
                      }
1153
                    if (OSD_LipoBar==0 )
1154
                      { // nur Textanzeige
1155
 
1156
                        switch (OSD_ScreenMode)
1157
                                    {
1158
                              case   0 :
1159
                              case   1 :
1160
                                        {
1161
                                          if (naviData->UBat < BattLowVoltageWarning)
1162
                                            {
1163
                                             write_ndigit_number_u_10th (x, y, naviData->UBat, 3, 0,2);
1164
                                             lcd_printp_at (x+4, y, PSTR("V"), 2);
1165
                                            }
1166
                                          else
1167
                                           {
1168
                                            write_ndigit_number_u_10th (x, y, naviData->UBat , 3, 0,0);
1169
                                            lcd_printp_at (x+4, y, PSTR("V"), 0);
1170
                                         }
1171
                                          break;
1172
                                           }
1173
                              case 2 :
1174
                                        {
1175
                                          if (naviData->UBat < BattLowVoltageWarning)
1176
                                            {
1177
                                             write_ndigit_number_u_10th (x-2, y, naviData->UBat, 3, 0,4);
1178
                                             lcd_putc_jeti (x+2, y, 'V', 2);
1179
                                            }
1180
                                          else
1181
                                           {
1182
                                            write_ndigit_number_u_10th (x-2, y, naviData->UBat , 3, 0,3);
1183
                                            lcd_putc_jeti (x+2, y, 'V', 0);
1184
                                         }
1185
                                          break;
1186
                                         }
1187
                           //break;
1188
                                    }
1189
                      }
1190
          }
1191
                break;
1192
 
1193
        case OSD_CAPACITY:
1194
                if (naviData->UsedCapacity > OSD_mAh_Warning)
1195
                  {
1196
                    write_ndigit_number_u (x, y, naviData->UsedCapacity, 5, 0,2);
1197
                    lcd_printp_at (x+5, y, PSTR("mAh"), 2);
1198
//                    BeepTime = 3000;
1199
//                    BeepMuster = 0x0020;
1200
                  }
1201
                else
1202
                  {
1203
                    write_ndigit_number_u (x, y, naviData->UsedCapacity, 5, 0,0);
1204
                    lcd_printp_at (x+5, y, PSTR("mAh"), 0);
1205
                  }
1206
 
1207
                break;
1208
 
1209
        case OSD_CARE_FREE:
1210
                if (naviData->FCStatusFlags2 & FC_STATUS2_CAREFREE)
1211
                        lcd_puts_at (x, y, strGet(OSD_CARE_FREE_1), 0);
1212
                else
1213
                        lcd_puts_at (x, y, strGet(OSD_CARE_FREE_0), 0); // Clear
1214
                break;
1215
 
1216
        case OSD_COMPASS_DEGREE:
1217
 
1218
 
1219
                switch (OSD_ScreenMode)
1220
                            {
1221
                              case    0: case 1 :
1222
                                        {
1223
                                          write_ndigit_number_u (x, y, naviData->CompassHeading, 3, 0,0);
1224
                                          lcd_putc (x+3, y, 0x1E, 0);     // degree symbol
1225
                                          break;
1226
                                        }
1227
                              case    2 :
1228
                                          {
1229
                                            write_ndigit_number_u (x, y, naviData->CompassHeading, 3, 0,3);
1230
                                            lcd_putc (x+8, y, 0x1E, 0);     // degree symbol
1231
                                            break;
1232
                                          }
1233
                               break;
1234
                            }
1235
               break;
1236
 
1237
 
1238
 
1239
        case OSD_COMPASS_DIRECTION:
1240
                lcd_printp_at (x, y, (const char *) (pgm_read_word ( &(directions_p[heading_conv(naviData->CompassHeading)]))), 0);
1241
                break;
1242
 
1243
        case OSD_COMPASS_ROSE:
1244
                draw_compass (x, y, naviData->CompassHeading);
1245
                break;
1246
 
1247
        case OSD_CURRENT:
1248
                write_ndigit_number_u_10th (x, y, naviData->Current, 3, 0,0);
1249
                lcd_printp_at (x+4, y, PSTR("A"), 0);
1250
                break;
1251
 
1252
        case OSD_FLYING_TIME:
1253
                write_time (x, y, naviData->FlyingTime);
1254
                lcd_printp_at (x+5, y, PSTR("m"), 0);
1255
                break;
1256
 
1257
        case OSD_GROUND_SPEED:
1258
                write_ndigit_number_u (x, y, (uint16_t) (((uint32_t) naviData->GroundSpeed * (uint32_t) 9) / (uint32_t) 250), 3, 0,0);
1259
                lcd_printp_at (x+3, y, PSTR("Kmh"), 0);
1260
                break;
1261
 
1262
        case OSD_HOME_CIRCLE:
1263
 
1264
          switch (OSD_ScreenMode)
1265
            {
1266
              case    0 :
1267
                          {
1268
                            lcd_o_circle(x, y, 5, 1);
1269
                            if (OSD_HomeMKView)
1270
                             heading_home = (naviData->HomePositionDeviation.Bearing + 360 - naviData->CompassHeading) % 360;
1271
                            else
1272
                             heading_home = (naviData->CompassHeading- naviData->HomePositionDeviation.Bearing + 360 ) % 360;
1273
                            lcd_o_circ_line (x, y, 5, old_hh, 0);
1274
                            old_hh = heading_home;
1275
                            lcd_o_circ_line (x, y, 5, heading_home, 1);
1276
                            break;
1277
                          }
1278
              case    1 :
1279
                          {
1280
                          lcd_o_circle(x, y, 7, 1);
1281
                          if (OSD_HomeMKView)
1282
                           heading_home = (naviData->HomePositionDeviation.Bearing + 360 - naviData->CompassHeading) % 360;
1283
                          else
1284
                           heading_home = (naviData->CompassHeading- naviData->HomePositionDeviation.Bearing + 360 ) % 360;
1285
                          lcd_o_circ_line (x, y, 7, old_hh, 0);
1286
                          old_hh = heading_home;
1287
                          lcd_o_circ_line (x, y, 7, heading_home, 1);
1288
                          break;
1289
                        }
1290
              case    2 :
1291
                          {
1292
                          lcd_o_circle(x, y, 5, 1);
1293
                          if (OSD_HomeMKView)
1294
                           heading_home = (naviData->HomePositionDeviation.Bearing + 360 - naviData->CompassHeading) % 360;
1295
                          else
1296
                           heading_home = (naviData->CompassHeading- naviData->HomePositionDeviation.Bearing + 360 ) % 360;
1297
                          lcd_o_circ_line (x, y, 5, old_hh, 0);
1298
                          old_hh = heading_home;
1299
                          lcd_o_circ_line (x, y, 5, heading_home, 1);
1300
                          break;
1301
                        }
1302
 
1303
 
1304
 
1305
              break;
1306
            }
1307
 
1308
        break;
1309
 
1310
        case OSD_HOME_DEGREE:
1311
                write_ndigit_number_u (x, y, heading_home, 3, 0,0);
1312
                lcd_putc (x+3, y, 0x1e, 0);     // degree symbol
1313
                break;
1314
 
1315
 
1316
 
1317
        case OSD_TARGET_DEGREE:
1318
 
1319
                switch (OSD_ScreenMode)
1320
                            {
1321
                              case    0: case 1 :
1322
                                          {
1323
                                            write_ndigit_number_u (x, y, naviData->TargetPositionDeviation.Bearing/ 10, 3, 0,0);
1324
                                            lcd_putc (x+3, y, 0x1e, 0);     // degree symbol
1325
                                            break;
1326
                                          }
1327
                              case    2 :
1328
                                          {
1329
                                            write_ndigit_number_u (x, y, naviData->TargetPositionDeviation.Bearing/ 10, 3, 0,0);
1330
                                            lcd_putc (x+3, y, 0x1e, 0);     // degree symbol
1331
                                            break;
1332
                                          }
1333
                               break;
1334
                            }
1335
               break;
1336
 
1337
        case OSD_HOME_DISTANCE:
1338
 
1339
 
1340
          switch (OSD_ScreenMode)
1341
                      {
1342
                        case    0: case 1 :
1343
                                    {
1344
                                        write_ndigit_number_u (x, y, naviData->HomePositionDeviation.Distance / 10, 3, 0,0);
1345
                                        lcd_putc (x+3, y, 'm', 0);
1346
                                        draw_homesymbol(x+4,y);
1347
                                        break;
1348
                                    }
1349
                        case    2 :
1350
                                    {
1351
                                        lcd_printp_at (x, y, PSTR("Home"), 0);
1352
                                        write_ndigit_number_u (x+5, y, naviData->HomePositionDeviation.Distance / 10, 3, 0,0);
1353
                                        lcd_printp_at (x+8, y, PSTR("m -"), 0);
1354
                                        break;
1355
                                    }
1356
                         break;
1357
                      }
1358
         break;
1359
 
1360
        case OSD_TARGET:
1361
          switch (OSD_ScreenMode)
1362
                        {
1363
                          case    0: case 1 :
1364
                                      {
1365
                                        write_ndigit_number_u (x, y, naviData->TargetPositionDeviation.Distance / 10, 3, 0,0);
1366
                                        lcd_putc (x+3, y, 'm', 0);
1367
                                        draw_targetsymbol(x+4,y);
1368
                                        break;
1369
                                      }
1370
                          case   2 :
1371
                            {
1372
                              lcd_printp_at (x, y, PSTR("Ziel"), 0);
1373
                              write_ndigit_number_u (x+5, y, naviData->TargetPositionDeviation.Distance / 10, 3, 0,0);
1374
                              lcd_printp_at (x+8, y, PSTR("m -"), 0);
1375
                              break;
1376
                            }
1377
                           break;
1378
                        }
1379
              break;
1380
        case OSD_WAYPOINT:
1381
                if (!OldWP == naviData->WaypointIndex)
1382
                {
1383
//                    BeepTime = 500;
1384
//                    BeepMuster = 0x0080;
1385
                    OldWP = naviData->WaypointIndex;
1386
                    NextWP = true;
1387
                }
1388
                if ((NextWP==true)&& naviData->NCFlags & NC_FLAG_TARGET_REACHED)
1389
                {
1390
                 set_beep ( 500, 0x0080, BeepNormal);
1391
                 NextWP = false;
1392
                }
1393
                  write_ndigit_number_u (x+2, y, naviData->WaypointIndex , 2, 0,0);
1394
 
1395
                lcd_printp_at (x, y, PSTR("WP"), 0);
1396
 
1397
                break;
1398
 
1399
        case OSD_LED1_OUTPUT:
1400
 
1401
 
1402
                if (!OSD_InvertOut)
1403
                {
1404
                    if (naviData->FCStatusFlags2 & FC_STATUS2_OUT1_ACTIVE)
1405
                    {
1406
                        lcd_fcircle (x * 6 + 5, y * 8 + 3, OSD_LEDform, 0);
1407
                        lcd_circle  (x * 6 + 5, y * 8 + 3, 3, 1);
1408
                    }
1409
                    else
1410
                    {
1411
                        lcd_fcircle (x * 6 + 5, y * 8 + 3, OSD_LEDform, 1);
1412
                        lcd_circle  (x * 6 + 5, y * 8 + 3, 3, 1);
1413
                    }
1414
                }
1415
                else
1416
                {
1417
                    if (naviData->FCStatusFlags2 & FC_STATUS2_OUT1_ACTIVE)
1418
                    {
1419
                        lcd_fcircle (x * 6 + 5, y * 8 + 3,OSD_LEDform, 1);
1420
                        lcd_circle  (x * 6 + 5, y * 8 + 3, 3, 1);
1421
                    }
1422
                    else
1423
                    {
1424
                        lcd_fcircle (x * 6 + 5, y * 8 + 3, OSD_LEDform, 0);
1425
                        lcd_circle  (x * 6 + 5, y * 8 + 3, 3, 1);
1426
                    }
1427
                }
1428
                break;
1429
 
1430
        case OSD_LED2_OUTPUT:
1431
 
1432
                if (!OSD_InvertOut)
1433
                {
1434
                        if (naviData->FCStatusFlags2 & FC_STATUS2_OUT2_ACTIVE)
1435
                        {
1436
                                lcd_fcircle (x * 6 + 5, y * 8 + 3, OSD_LEDform, 0);
1437
                                lcd_circle  (x * 6 + 5, y * 8 + 3, 3, 1);
1438
                        }
1439
                        else
1440
                        {
1441
                                lcd_fcircle (x * 6 + 5, y * 8 + 3, OSD_LEDform, 1);
1442
                                lcd_circle  (x * 6 + 5, y * 8 + 3, 3, 1);
1443
                        }
1444
                }
1445
                else
1446
                {
1447
                        if (naviData->FCStatusFlags2 & FC_STATUS2_OUT2_ACTIVE)
1448
                        {
1449
                                lcd_fcircle (x * 6 + 5, y * 8 + 3, OSD_LEDform, 1);
1450
                                lcd_circle  (x * 6 + 5, y * 8 + 3, 3, 1);
1451
                        }
1452
                        else
1453
                        {
1454
                                lcd_fcircle (x * 6 + 5, y * 8 + 3, OSD_LEDform, 0);
1455
                                lcd_circle  (x * 6 + 5, y * 8 + 3, 3, 1);
1456
                        }
1457
                }
1458
                break;
1459
 
1460
        case OSD_MANUELL:
1461
                if (naviData->NCFlags & NC_FLAG_MANUAL_CONTROL)
1462
                        lcd_putc (x, y, 'M', 0); // rc transmitter
1463
                else
1464
                        lcd_putc (x, y, 'X', 0); // clear
1465
                break;
1466
 
1467
        case OSD_NAVI_MODE:
1468
                if (naviData->NCFlags & NC_FLAG_FREE)
1469
                        lcd_puts_at (x, y, strGet(OSD_NAVI_MODE_0), 0); // Navi aus
1470
                else if (naviData->NCFlags & NC_FLAG_PH)
1471
                        lcd_puts_at (x, y, strGet(OSD_NAVI_MODE_1), 0); // Pos. Hold
1472
                else if (naviData->NCFlags & NC_FLAG_CH)
1473
                        lcd_puts_at (x, y, strGet(OSD_NAVI_MODE_2), 0); // Coming Home
1474
                break;
1475
 
1476
        case OSD_RC_INTENSITY:
1477
                write_ndigit_number_u (x, y, naviData->RC_Quality, 3, 0,0);
1478
                lcd_printp_at (x+3, y, PSTR("\x1F"), 0);                // RC-transmitter
1479
                if (naviData->NCFlags & NC_FLAG_NOSERIALLINK)
1480
                {
1481
                        lcd_printpns_at(x+3, y, PSTR("  "), 0);         // Clear
1482
                }
1483
                else
1484
                {
1485
                        lcd_printpns_at(x+3, y, PSTR("PC"), 0);
1486
                }
1487
                break;
1488
 
1489
        case OSD_SATS_IN_USE:
1490
 
1491
 
1492
 
1493
 
1494
                  switch (OSD_ScreenMode)
1495
                      {
1496
                        case    0: case 1 :
1497
                                        {
1498
                                        if (naviData->NCFlags & NC_FLAG_GPS_OK)
1499
                                          {
1500
                                            write_ndigit_number_u (x, y, naviData->SatsInUse, 2, 0,0);
1501
                                            lcd_putc (x+2, y, 0x08, 0);
1502
                                          }
1503
                                        else
1504
                                          {
1505
                                            write_ndigit_number_u (x, y, naviData->SatsInUse, 2, 0,2);
1506
                                            lcd_putc (x+2, y, 0x08, 2);
1507
                                          }
1508
                                        break;
1509
                                        }
1510
                        case   2 :
1511
                                        {
1512
                                        if (naviData->NCFlags & NC_FLAG_GPS_OK)
1513
                                          {
1514
                                            write_ndigit_number_u (x, y, naviData->SatsInUse, 2, 0,0);
1515
                                            lcd_printp_at (x+2, y, PSTR(" Sat"), 0);
1516
                                          }
1517
                                        else
1518
                                          {
1519
                                            write_ndigit_number_u (x, y, naviData->SatsInUse, 2, 0,2);
1520
                                            lcd_printp_at (x+2, y, PSTR(" Sat"),2);
1521
                                          }
1522
                                        break;
1523
                                        }
1524
                         break;
1525
                      }
1526
                              break;
1527
 
1528
 
1529
        case OSD_STATUS_FLAGS:
1530
                // FC_StatusFlags 0.88
1531
                // #define FC_STATUS_MOTOR_RUN           0x01
1532
                // #define FC_STATUS_FLY                 0x02
1533
                // #define FC_STATUS_CALIBRATE           0x04
1534
                // #define FC_STATUS_START               0x08
1535
                // #define FC_STATUS_EMERGENCY_LANDING   0x10
1536
                // #define FC_STATUS_LOWBAT              0x20
1537
                // #define FC_STATUS_VARIO_TRIM_UP       0x40
1538
                // #define FC_STATUS_VARIO_TRIM_DOWN     0x80
1539
 
1540
                if (naviData->FCStatusFlags & FC_STATUS_CALIBRATE)
1541
                        lcd_puts_at (x, y, strGet(OSD_FLAGS_1), 0);     // Calibrate
1542
                else if (naviData->FCStatusFlags & FC_STATUS_START)
1543
                        lcd_puts_at (x, y, strGet(OSD_FLAGS_2), 0);     // Start
1544
                else if (naviData->FCStatusFlags & FC_STATUS_MOTOR_RUN)
1545
                        lcd_puts_at (x, y, strGet(OSD_FLAGS_3), 0);     // Run
1546
                else if (naviData->FCStatusFlags & FC_STATUS_FLY)
1547
                        lcd_puts_at (x, y, strGet(OSD_FLAGS_4), 0);     // Fly
1548
                else if (naviData->FCStatusFlags & FC_STATUS_EMERGENCY_LANDING)
1549
                        lcd_puts_at (x, y, strGet(OSD_FLAGS_5), 0);     // Landing
1550
                else if (naviData->FCStatusFlags & FC_STATUS_LOWBAT)
1551
                        lcd_puts_at (x, y, strGet(OSD_FLAGS_6), 0);     // LowBat
1552
                else
1553
//                      lcd_printp_at (x, y, PSTR("         "), 0);     // Clear
1554
                        lcd_puts_at (x, y, strGet(OSD_FLAGS_0), 0);     // Clear
1555
 
1556
                break;
1557
 
1558
        case OSD_VARIOMETER:
1559
                draw_variometer (x, y, 10, 14, naviData->Variometer);
1560
                break;
1561
 
1562
        case OSD_VARIOWERT:
1563
 
1564
          FC_Fallspeed = (unsigned int)naviData->Variometer;
1565
          FC_Fallspeed = 255-FC_Fallspeed;
1566
 
1567
          if (OSD_VarioBeep && (naviData->FCStatusFlags & FC_STATUS_MOTOR_RUN) && (naviData->FCStatusFlags2 & FC_STATUS2_ALTITUDE_CONTROL))
1568
            { //start Beep
1569
              if (naviData->Variometer <0)          // MK fällt
1570
                {
1571
                 Vario_Beep_Up = 0;                 // Up Beep freischalten
1572
                 Vario_Threshold++;
1573
                 if ((Vario_Beep_Down == 0) && (Vario_Threshold >= Vario_Threshold_Value))
1574
                  {
1575
 
1576
                   set_beep ( 300, 0xffff, BeepNormal);
1577
                   Vario_Threshold = Vario_Threshold_Value;     // auf Maximalwert begrenzen
1578
                  }
1579
                 Vario_Beep_Down++;                 // Interval hochzählen in dem nicht gepiept wird
1580
                 if (Vario_Beep_Down == Vario_Beep_Down_Interval) Vario_Beep_Down = 0;
1581
                }
1582
 
1583
              if (naviData->Variometer == 0) Vario_Threshold = 0;  //Startverzögerung löschen
1584
 
1585
              if (naviData->Variometer >0 )          // MK steigt
1586
                {
1587
                 Vario_Beep_Down = 0;                 // Down Beep freischalten
1588
                 Vario_Threshold++;
1589
 
1590
                 if ((Vario_Beep_Up == 0) && (Vario_Threshold >= Vario_Threshold_Value))
1591
                  {
1592
                   set_beep ( 100, 0xffff, BeepNormal);
1593
                   Vario_Threshold = Vario_Threshold_Value;     // auf Maximalwert begrenzen
1594
                  }
1595
                 Vario_Beep_Up++;                 // Interval hochzählen in dem nicht gepiept wird
1596
                 if (Vario_Beep_Up == Vario_Beep_Up_Interval) Vario_Beep_Up = 0;
1597
                }
1598
            }  // end Beep
1599
 
1600
          if (naviData->Variometer < 0)
1601
                  {
1602
                    if (FC_Fallspeed > OSD_Fallspeed)
1603
 
1604
                      {
1605
                        write_ndigit_number_s_10th (x, y, naviData->Variometer, 3,0,2);
1606
                        lcd_printpns_at(x+4, y, PSTR("m/s"), 2);
1607
                        set_beep ( 1000, 0x0060, BeepNormal);
1608
                      }
1609
                    else
1610
                      {
1611
                      write_ndigit_number_s_10th (x, y, naviData->Variometer, 3,0,0);
1612
                      lcd_printpns_at(x+4, y, PSTR("m/s"), 0);
1613
                      }
1614
                  }
1615
                else
1616
                  {
1617
                  write_ndigit_number_s_10th (x, y, naviData->Variometer, 3,0,0);
1618
                  lcd_printpns_at(x+4, y, PSTR("m/s"), 0);
1619
                  }
1620
 
1621
                break;
1622
 
1623
        }
1624
 
1625
}
1626
 
1627