Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1471 - 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
 
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
 
58
// löschen und alle mit "naviData->Variometer" ersetzen
59
//int8_t Variometer = 0;
60
 
61
// Hier Höhenanzeigefehler Korrigieren
62
#define AltimeterAdjust 1.5
63
 
64
// stats for after flight
65
int16_t max_Altimeter = 0;
66
uint16_t max_GroundSpeed = 0;
67
int16_t max_Distance = 0;
68
uint8_t min_UBat = 255;
69
uint16_t max_FlyingTime = 0;
70
uint16_t max_Current = 0;
71
uint16_t max_Capacity = 0;
72
 
73
// cache old vars for blinking attribute, checkup is faster than full
74
// attribute write each time
75
volatile uint8_t last_UBat = 255;
76
volatile uint8_t last_RC_Quality = 255;
77
 
78
volatile uint16_t ftimer = 0;
79
 
80
// store stats description in progmem to save space
81
const char stats_item_0[] PROGMEM = "max Altitude:";
82
const char stats_item_1[] PROGMEM = "max Speed   :";
83
const char stats_item_2[] PROGMEM = "max Distance:";
84
const char stats_item_3[] PROGMEM = "min Voltage :";
85
const char stats_item_4[] PROGMEM = "max Time    :";
86
#if 1
87
const char stats_item_5[] PROGMEM = "max Current :";
88
const char stats_item_6[] PROGMEM = "UsedCapacity:";
89
#else
90
const char stats_item_5[] PROGMEM = "Long. :";
91
const char stats_item_6[] PROGMEM = "Lat.  :";
92
#endif
93
 
94
 
95
const char *stats_item_pointers[] PROGMEM = {
96
        stats_item_0,
97
        stats_item_1,
98
        stats_item_2,
99
        stats_item_3,
100
        stats_item_4,
101
        stats_item_5,
102
        stats_item_6
103
};
104
 
105
//char* rose = "-+-N-+-O-+-S-+-W-+-N-+-O-+-S-+-W-+-N-+-O-+-S-+-W";
106
const char rose[48] PROGMEM = {
107
        0x0e, 0x0f, 0x0e, 'N', 0x0e, 0x0f, 0x0e, 'O', 0x0e, 0x0f, 0x0e, 'S',
108
        0x0e, 0x0f, 0x0e, 'W', 0x0e, 0x0f, 0x0e, 'N', 0x0e, 0x0f, 0x0e, 'O',
109
        0x0e, 0x0f, 0x0e, 'S', 0x0e, 0x0f, 0x0e, 'W', 0x0e, 0x0f, 0x0e, 'N',
110
        0x0e, 0x0f, 0x0e, 'O', 0x0e, 0x0f, 0x0e, 'S', 0x0e, 0x0f, 0x0e, 'W',
111
};
112
 
113
// the center is char 19 (north), we add the current heading in 8th
114
// which would be 22.5 degrees, but float would bloat up the code
115
// and *10 / 225 would take ages... so we take the uncorrect way
116
 
117
const char str_NE[] PROGMEM = "NE";
118
const char str_E[] PROGMEM  = "E ";
119
const char str_SE[] PROGMEM = "SE";
120
const char str_S[] PROGMEM  = "S ";
121
const char str_SW[] PROGMEM = "SW";
122
const char str_W[] PROGMEM  = "W ";
123
const char str_NW[] PROGMEM = "NW";
124
const char str_N[] PROGMEM  = "N ";
125
const char *directions_p[8] PROGMEM = {
126
        str_NE,
127
        str_E,
128
        str_SE,
129
        str_S,
130
        str_SW,
131
        str_W,
132
        str_NW,
133
        str_N
134
};
135
 
136
// Flags
137
uint8_t COSD_FLAGS2 = 0;
138
 
139
GPS_Pos_t last5pos[7];
140
uint8_t error = 0;
141
 
142
 
143
//--------------------------------------------------------------
144
// convert the <heading> gotton from NC into an index
145
uint8_t heading_conv (uint16_t heading)
146
{
147
        if (heading > 23 && heading < 68)
148
                return 0;               //direction = "NE";
149
        else if (heading > 67 && heading < 113)
150
                return 1;               //direction = "E ";
151
        else if (heading > 112 && heading < 158)
152
                return 2;               //direction = "SE";
153
        else if (heading > 157 && heading < 203)
154
                return 3;               //direction = "S ";
155
        else if (heading > 202 && heading < 248)
156
                return 4;               //direction = "SW";
157
        else if (heading > 247 && heading < 293)
158
                return 5;               //direction = "W ";
159
        else if (heading > 292 && heading < 338)
160
                return 6;               //direction = "NW";
161
 
162
        return 7;       //direction = "N ";
163
}
164
 
165
//--------------------------------------------------------------
166
// draw a compass rose at <x>/<y> for <heading>
167
void draw_compass (uint8_t x, uint8_t y, uint16_t heading)
168
{
169
        uint8_t front = 19 + (heading / 22);
170
        for (uint8_t i = 0; i < 9; i++)
171
                lcd_putc (x++, y, pgm_read_byte(&rose[front - 4 + i]), 0);
172
}
173
 
174
 
175
//--------------------------------------------------------------
176
// variometer
177
// draw variometer arrows at <x>/<y> according to <variometer>
178
//
179
void draw_variometer (uint8_t x, uint8_t y, uint8_t width, uint8_t hight, int16_t variometer)
180
{
181
        lcd_rect (x, y - ((hight) / 2), width, hight, 1);
182
        lcd_frect (x + 1, y - ((hight) / 2) + 1, width - 2, hight - 2, 0);
183
        lcd_line (x, y, x + width, y, 1);
184
 
185
        if (variometer > 0)  // steigend
186
        {
187
                switch (variometer / 5)
188
                {
189
                        case 0:
190
                                lcd_line  (x + 4, y - 1, x + 6, y - 1, 1);      //  1 >  4
191
                        break;
192
 
193
                        case 1:
194
                                lcd_line  (x + 4, y - 1, x + 6, y - 1, 1);      //  1 >  4
195
                                lcd_frect (x + 3, y - 3, 4, 1, 1);                      //  5 >  9
196
                        break;
197
 
198
                        case 2:
199
                                lcd_line  (x + 4, y - 1, x + 6, y - 1, 1);      //  1 >  4
200
                                lcd_frect (x + 3, y - 3, 4, 1, 1);                      //  5 >  9
201
                                lcd_frect (x + 2, y - 5, 6, 1, 1);                      // 10 > 14
202
                        break;
203
 
204
                        default:
205
                                lcd_line  (x + 4, y - 1, x + 6, y - 1, 1);  //  1 >  4
206
                                lcd_frect (x + 3, y - 3, 4, 1, 1);                      //  5 >  9
207
                                lcd_frect (x + 2, y - 5, 6, 1, 1);                      // 10 > 14
208
                                lcd_frect (x + 1, y - 6, 8, 1, 1);                      // 15 >
209
                        break;
210
                }
211
        }
212
        else if (variometer < 0)  // fallend
213
        {
214
                switch ((variometer) / -5)
215
                {
216
                        case 0:
217
                                lcd_line  (x + 4, y + 1, x + 6, y + 1, 1);      // - 1 > - 4
218
                        break;
219
 
220
                        case 1:
221
                                lcd_line  (x + 4, y + 1, x + 6, y + 1, 1);      // - 1 > - 4
222
                                lcd_frect (x + 3, y + 2, 4, 1, 1);                      // - 5 > - 9
223
                        break;
224
 
225
                        case 2:
226
                                lcd_line  (x + 4, y + 1, x + 6, y + 1, 1);      // - 1 > - 4
227
                                lcd_frect (x + 3, y + 2, 4, 1, 1);                      // - 5 > - 9
228
                                lcd_frect (x + 2, y + 4, 6, 1, 1);                      // -10 > -14
229
                        break;
230
 
231
                        default:
232
                                lcd_line  (x + 4, y + 1, x + 6, y + 1, 1);      // - 1 > - 4
233
                                lcd_frect (x + 3, y + 2, 4, 1, 1);                      // - 5 > - 9
234
                                lcd_frect (x + 2, y + 4, 6, 1, 1);                      // -10 > -14
235
                                lcd_frect (x + 1, y + 5, 8, 1, 1);                      // -15 >
236
                        break;
237
                }
238
        }
239
}
240
 
241
 
242
//--------------------------------------------------------------
243
void print_statistics (void)
244
{
245
        uint8_t line = 0;
246
        lcd_cls ();
247
//      lcd_printp_at (12, 7, PSTR("Ende"), 0);
248
        lcd_puts_at(12, 7, strGet(ENDE), 0);
249
 
250
        // max Altitude
251
        lcd_printp_at (0, line, stats_item_pointers[0], 0);
252
        write_ndigit_number_s (13, line, max_Altimeter / (30 / AltimeterAdjust), 4, 0);
253
        lcd_putc (17, line, 'm', 0);
254
 
255
        // max Speed
256
        lcd_printp_at (0, ++line, stats_item_pointers[1], 0);
257
        write_ndigit_number_u (14, line, (uint16_t) (((uint32_t) max_GroundSpeed * (uint32_t) 9) / (uint32_t) 250), 3, 0);
258
        lcd_printp_at(17, line, PSTR("km/h"), 0);
259
 
260
        // max Distance
261
        lcd_printp_at (0, ++line, stats_item_pointers[2], 0);
262
        write_ndigit_number_u (14, line, max_Distance / 10, 3, 0);
263
        lcd_putc (17, line, 'm', 0);
264
 
265
        // max time
266
        lcd_printp_at (0, ++line, stats_item_pointers[4], 0);
267
        write_time (13, line, max_FlyingTime);
268
 
269
        // min voltage
270
        lcd_printp_at (0, ++line, stats_item_pointers[3], 0);
271
        write_ndigit_number_u_10th (13, line, min_UBat, 3, 0);
272
        lcd_putc (17, line, 'V', 0);
273
 
274
#if 1
275
        // max Current
276
        lcd_printp_at (0, ++line, stats_item_pointers[5], 0);
277
        write_ndigit_number_u_10th (13, line, max_Current, 3, 0);
278
        lcd_putc (17, line, 'A', 0);
279
 
280
        // Used Capacity
281
        lcd_printp_at (0, ++line, stats_item_pointers[6], 0);
282
        write_ndigit_number_u (13, line, max_Capacity, 4, 0);
283
        lcd_printp_at(17, line, PSTR("mAh"), 0);
284
#else
285
        // longitude
286
        lcd_printp_at (0, ++line, stats_item_pointers[5], 0);
287
        write_gps_pos (8, line, naviData->CurrentPosition.Longitude);
288
 
289
        // latitude
290
        lcd_printp_at (0, ++line, stats_item_pointers[6], 0);
291
        write_gps_pos (8, line, naviData->CurrentPosition.Latitude);
292
#endif
293
 
294
        while (!get_key_press (1 << KEY_ESC))
295
                timer = TIMEOUT;
296
 
297
        COSD_FLAGS2 &= ~COSD_WASFLYING;
298
        get_key_press(KEY_ALL);
299
        lcd_cls();
300
}
301
 
302
//--------------------------------------------------------------
303
void print_position (void)
304
{
305
        lcd_cls ();
306
//      lcd_printp_at (0, 0, PSTR(" Breitengr  Längengr "), 2);
307
        lcd_puts_at(0, 0, strGet(START_LASTPOS1), 2);
308
//      lcd_printp_at (12, 7, PSTR("Ende"), 0);
309
        lcd_puts_at(12, 7, strGet(ENDE), 0);
310
        uint8_t ij =0;
311
 
312
        for(ij=0;ij<6;ij++)
313
        {
314
                uint32_t lon = last5pos[ij].Longitude;
315
                write_ndigit_number_u (1, ij+1, (uint16_t)(lon/10000000), 2, 0);
316
                lcd_printp_at (3, ij+1, PSTR("."), 0);
317
                write_ndigit_number_u (4, ij+1, (uint16_t)((lon/1000) % 10000), 4, 1);
318
                write_ndigit_number_u (8, ij+1, (uint16_t)((lon/10) % 100), 2, 1);
319
 
320
                uint32_t lat = last5pos[ij].Latitude;
321
                write_ndigit_number_u (12, ij+1, (uint16_t)(lat/10000000), 2, 0);
322
                lcd_printp_at (14, ij+1, PSTR("."), 0);
323
                write_ndigit_number_u (15, ij+1, (uint16_t)((lat/1000) % 10000), 4, 1);
324
                write_ndigit_number_u (19, ij+1, (uint16_t)((lat/10) % 100), 2, 1);
325
        }
326
 
327
        while (!get_key_press (1 << KEY_ESC))
328
                timer = TIMEOUT;
329
 
330
        get_key_press(KEY_ALL);
331
        lcd_cls();
332
}
333
 
334
 
335
//--------------------------------------------------------------
336
void osd (uint8_t ShowMode)
337
{
338
        uint8_t flag;
339
        uint8_t tmp_dat;
340
        uint8_t OSD_Mode;
341
        uint8_t info_3D = 0;
342
 
343
        // Clear statistics
344
        max_Altimeter = 0;
345
        max_GroundSpeed = 0;
346
        max_Distance = 0;
347
        min_UBat = 255;
348
        max_FlyingTime = 0;
349
 
350
        // flags from last round to check for changes
351
        uint8_t old_FCFlags = 0;
352
 
353
        uint16_t old_hh = 0;
354
        uint8_t old_AngleNick = 0;
355
        uint8_t old_AngleRoll = 0;
356
 
357
        OSD_Mode = ShowMode;
358
 
359
        if(error == 0)
360
                lcd_cls();
361
 
362
        if (hardware == FC)
363
        {
364
                lcd_printp_at(0, 3, PSTR("Only with NC !"), 0);
365
                timer = 100;
366
                while (timer > 0);
367
 
368
                return;
369
        }
370
 
371
        SwitchToNC();
372
 
373
        mode = 'O';
374
 
375
        // disable debug...
376
        //      RS232_request_mk_data (0, 'd', 0);
377
        tmp_dat = 0;
378
        SendOutData ('d', ADDRESS_ANY, 1, &tmp_dat, 1);
379
 
380
        // request OSD Data from NC every 100ms
381
        //      RS232_request_mk_data (1, 'o', 100);
382
        tmp_dat = 10;
383
        SendOutData ('o', ADDRESS_NC, 1, &tmp_dat, 1);
384
 
385
        flag = 0;
386
        timer = TIMEOUT;
387
        abo_timer = ABO_TIMEOUT;
388
 
389
 
390
        do
391
        {
392
                if (rxd_buffer_locked)
393
                {
394
                        timer = TIMEOUT;
395
                        Decode64 ();
396
                        naviData = (NaviData_t *) pRxData;
397
 
398
                        if(error == 1)
399
                                lcd_cls();
400
 
401
                        error = 0;
402
                        GPS_Pos_t currpos;
403
                        currpos.Latitude = naviData->CurrentPosition.Latitude;
404
                        currpos.Longitude = naviData->CurrentPosition.Longitude;
405
 
406
                        if((currpos.Latitude != last5pos[0].Latitude)&&(currpos.Longitude != last5pos[0].Longitude))
407
                        {
408
                                last5pos[6] = last5pos[5];
409
                                last5pos[5] = last5pos[4];
410
                                last5pos[4] = last5pos[3];
411
                                last5pos[3] = last5pos[2];
412
                                last5pos[2] = last5pos[1];
413
                                last5pos[1] = last5pos[0];
414
                                last5pos[0] = currpos;
415
                        }
416
 
417
                        flag = 1;
418
 
419
                        if (OSD_Mode == 1)
420
                        {
421
                                if (naviData->FCFlags & FCFLAG_MOTOR_RUN)
422
                                { // should be engines running
423
                                        // motors are on, assume we were/are flying
424
                                        COSD_FLAGS2 |= COSD_WASFLYING;
425
                                }
426
                                else
427
                                {       // stats
428
                                        if ((COSD_FLAGS2 & COSD_WASFLYING) | (get_key_press (1 << KEY_ENTER)))
429
                                                print_statistics ();
430
 
431
                                        if (get_key_press (1 << KEY_PLUS))
432
                                                print_position ();
433
                                }
434
 
435
                                lcd_ecircle(22, 35, 16, 1);
436
 
437
                                // Ground Speed
438
                                write_ndigit_number_u (1, 0, (uint16_t) (((uint32_t) naviData->GroundSpeed * (uint32_t) 9) / (uint32_t) 250), 3, 0);
439
                                lcd_printp_at(4, 0, PSTR("km/h"), 0);
440
 
441
                                // Compass
442
                                write_ndigit_number_u (14, 0, naviData->CompassHeading, 3, 0);
443
                                lcd_putc (17, 0, 0x1E, 0);      // degree symbol
444
                                lcd_printp_at (18, 0, (const char *) (pgm_read_word ( &(directions_p[heading_conv(naviData->CompassHeading)]))), 0);
445
 
446
                                draw_compass (12, 1, naviData->CompassHeading);
447
 
448
                                // Altitude
449
                                //note:lephisto:according to several sources it's /30
450
                                if (naviData->Altimeter > (300 / AltimeterAdjust) || naviData->Altimeter < (-300 / AltimeterAdjust))    // above 10m only write full meters
451
                                        write_ndigit_number_s (0, 1, naviData->Altimeter / (30 / AltimeterAdjust), 4, 0);
452
                                else    // up to 10m write meters.dm
453
                                        write_ndigit_number_s_10th (0, 1, naviData->Altimeter / (3 / AltimeterAdjust), 3, 0);
454
 
455
                                lcd_putc (4, 1, 'm', 0);
456
 
457
                                draw_variometer (54, 7, 10, 14, naviData->Variometer);
458
 
459
                                // TODO: verify correctness
460
                                uint16_t heading_home = (naviData->HomePositionDeviation.Bearing + 360 - naviData->CompassHeading) % 360;
461
                                lcd_ecirc_line (22, 35, 15, old_hh, 0);
462
                                old_hh = heading_home;
463
                                lcd_ecirc_line (22, 35, 15, heading_home, 1);
464
 
465
                                write_ndigit_number_u (7, 3, heading_home, 3, 0);
466
                                lcd_putc (10, 3, 0x1e, 0);      // degree symbol
467
 
468
                                write_ndigit_number_u (7, 2, naviData->HomePositionDeviation.Distance / 10, 3, 0);
469
                                lcd_putc (10, 2, 'm', 0);
470
 
471
                                // Sats in use
472
                                lcd_printp_at(11, 4, PSTR("Sats"), 0);
473
                                write_ndigit_number_u (8, 4, naviData->SatsInUse, 2, 0);
474
 
475
                                if (naviData->NCFlags & NC_FLAG_MANUAL_CONTROL)
476
                                        lcd_putc (19, 4, 'M', 0); // rc transmitter
477
                                else
478
                                        lcd_putc (19, 4, 'X', 0); // clear
479
 
480
                                if (naviData->NCFlags & NC_FLAG_CH)
481
                                        lcd_printp_at (8, 5, PSTR("Coming Home"), 0);
482
                                else if (naviData->NCFlags & NC_FLAG_PH)
483
                                        lcd_printp_at (8, 5, PSTR("Pos. Hold  "), 0);
484
                                else    // (naviData->NCFlags & NC_FLAG_FREE)
485
                                        lcd_printp_at (8, 5, PSTR("Free       "), 0);
486
 
487
                                // Flying time
488
                                write_time (7, 6, naviData->FlyingTime);
489
                                lcd_printp_at (12, 6, PSTR("h"), 0);
490
 
491
                                // RC
492
                                write_ndigit_number_u (15, 6, naviData->RC_Quality, 3, 0);
493
                                lcd_printp_at(18, 6, PSTR("\x1F"), 0);          // RC-transmitter
494
                                if (naviData->NCFlags & NC_FLAG_NOSERIALLINK)
495
                                {
496
                                        lcd_printpns_at(19, 6, PSTR("  "), 0);          // clear
497
                                }
498
                                else
499
                                {
500
                                        lcd_printpns_at(19, 6, PSTR("PC"), 0);
501
                                }
502
 
503
                                // Battery level
504
                                write_ndigit_number_u_10th (0, 7, naviData->UBat, 3, 0);
505
                                lcd_putc (4, 7, 'V', 0);
506
 
507
                                // Akku Warnung
508
                                if (naviData->UBat < MK_LowBat)
509
                                { //Beeper ein
510
                                        BeepTime = 3000;
511
                                        BeepMuster = 0x0020;
512
                                }
513
 
514
                                //if (naviData->UBat > MK_LowBat+2)  //bei kurzzeitigen Schwankungen Beeper erst wieder aus wenn UBat 0,2 V höher als Warnschwelle
515
                                //{ //Beeper aus
516
                                //      BeepTime = 0;
517
                                //      BeepMuster = 0xFFFF;
518
                                //}
519
                                // Akku Warnung Ende
520
 
521
                                // Current
522
                                write_ndigit_number_u_10th (7, 7, naviData->Current, 3, 0);
523
                                lcd_putc (11, 7, 'A', 0);
524
 
525
                                // Capacity
526
                                write_ndigit_number_u (14, 7, naviData->UsedCapacity, 4, 0);
527
                                lcd_printp_at(18, 7, PSTR("mAh"), 0);
528
 
529
                                // remember statistics (only when engines running)
530
                                if (naviData->FCFlags & FCFLAG_MOTOR_RUN)
531
                                {
532
                                        if (naviData->Altimeter > max_Altimeter) max_Altimeter = naviData->Altimeter;
533
                                        if (naviData->GroundSpeed > max_GroundSpeed) max_GroundSpeed = naviData->GroundSpeed;
534
                                        if (naviData->HomePositionDeviation.Distance > max_Distance) max_Distance = naviData->HomePositionDeviation.Distance;
535
                                        if (naviData->UBat < min_UBat) min_UBat = naviData->UBat;
536
                                        if (naviData->FlyingTime > max_FlyingTime) max_FlyingTime = naviData->FlyingTime;
537
                                        if (naviData->Current > max_Current) max_Current = naviData->Current;
538
                                        if (naviData->UsedCapacity > max_Capacity) max_Capacity = naviData->UsedCapacity;
539
                                }
540
 
541
                                // remember last values
542
                                last_RC_Quality = naviData->RC_Quality;
543
                                last_UBat = naviData->UBat;
544
                                old_FCFlags = naviData->FCFlags;
545
 
546
                                rxd_buffer_locked = FALSE;
547
                        }
548
        // 3D Lage anzeige beginnt hier -----------------------------------
549
                        else if (OSD_Mode == 3)
550
                        {
551
                                uint16_t head_home = (naviData->HomePositionDeviation.Bearing + 360 - naviData->CompassHeading) % 360;
552
 
553
                                lcd_cls ();
554
 
555
                                lcd_line(0,32,128,32,1);   // horizontal //
556
                                lcd_line(64,0,64,64,1);    // vertical   //
557
                                lcd_printp_at(12, 7, PSTR("End  Info"), 0);
558
 
559
 
560
                                // 45' Angel
561
                                lcd_line(62,11,66,11,1);   //    --    //
562
                                lcd_line(22,30,22,34,1);   //  |       //
563
                                lcd_line(106,30,106,34,1); //       |  //
564
                                lcd_line(62,53,66,53,1);   //    --    //
565
 
566
                                if (info_3D == 1)
567
                                {
568
                                        lcd_line(34,17,36,15,1);   //  /       //
569
                                        lcd_line(92,15,94,17,1);   //       \  //
570
                                        lcd_line(34,47,36,49,1);   //  \       //
571
                                        lcd_line(92,49,94,47,1);   //       /  //
572
 
573
//                                      lcd_printp_at(9, 0, PSTR("V"), 0);
574
//                                      lcd_printp_at(0, 3, PSTR("L"), 0);
575
//                                      lcd_printp_at(20, 3, PSTR("R"), 0);
576
//                                      lcd_printp_at(9, 7, PSTR("H"), 0);
577
 
578
                                        lcd_puts_at(9, 0, strGet(OSD_V), 0);
579
                                        lcd_puts_at(0, 3, strGet(OSD_L), 0);
580
                                        lcd_puts_at(20, 3, strGet(OSD_R), 0);
581
                                        lcd_puts_at(9, 7, strGet(OSD_H), 0);
582
 
583
                                        lcd_printp_at(0, 0, PSTR("N:"), 0);
584
                                        write_ndigit_number_s (2, 0, naviData->AngleNick, 3, 0);
585
 
586
                                        lcd_printp_at(0, 7, PSTR("R:"), 0);
587
                                        write_ndigit_number_s (2, 7, naviData->AngleRoll, 3, 0);
588
 
589
                                        lcd_printp_at(15, 0, PSTR("K:"), 0);
590
                                        write_ndigit_number_s (18, 0,head_home, 3, 0);
591
                                }
592
 
593
                                if (get_key_press (1 << KEY_ENTER))
594
                                {
595
                                        info_3D++;
596
                                        if (info_3D > 1)
597
                                                info_3D = 0;
598
                                }
599
 
600
                                uint8_t Nick = ((-naviData->AngleNick/2)+32);
601
                                uint8_t Roll = -naviData->AngleRoll+64;
602
                                lcd_ecircle(old_AngleRoll,old_AngleNick, 10, 0);
603
                                lcd_ecirc_line (old_AngleRoll, old_AngleNick, 9, old_hh, 0);
604
 
605
                                lcd_ecircle(Roll, Nick, 10, 1);
606
                                lcd_ecirc_line (Roll, Nick, 9, head_home, 1);
607
 
608
                                old_hh = head_home;
609
                                old_AngleNick = Nick;
610
                                old_AngleRoll = Roll;
611
                                // remember last values
612
                                last_RC_Quality = naviData->RC_Quality;
613
                                last_UBat = naviData->UBat;
614
                                old_FCFlags = naviData->FCFlags;
615
                                rxd_buffer_locked = FALSE;
616
                        }
617
 
618
                        if (!abo_timer)
619
                        {       // renew abo every 3 sec
620
                                // request OSD Data from NC every 100ms
621
                                //      RS232_request_mk_data (1, 'o', 100);
622
                                tmp_dat = 10;
623
                                SendOutData ('o', ADDRESS_NC, 1, &tmp_dat, 1);
624
 
625
                                abo_timer = ABO_TIMEOUT;
626
                        }
627
                }
628
        }
629
        while (!get_key_press (1 << KEY_ESC) && timer);
630
 
631
        get_key_press(KEY_ALL);
632
 
633
 
634
        // disable OSD Data from NC
635
        //      RS232_request_mk_data (1, 'o', 0);
636
        tmp_dat = 0;
637
        SendOutData ('o', ADDRESS_NC, 1, &tmp_dat, 1);
638
 
639
        mode = 0;
640
        rxd_buffer_locked = FALSE;
641
 
642
 
643
        // Bei Verbindungsverlusst werden hier die letzten bekannten Koordinaten ausgegeben!!!
644
        if (!timer)
645
        {       // timeout occured
646
                if (flag)
647
                {
648
                        // Falls Spannungswarnung an war Beeper aus//
649
                        BeepTime = 0;
650
                        BeepMuster = 0xFFFF;
651
 
652
                        lcd_cls ();
653
                        WriteLastPosition(last5pos[0].Longitude,last5pos[0].Latitude);  // im EEprom speichern
654
                        lcd_puts_at(0, 0, strGet(OSD_ERROR), 2);
655
 
656
//                      lcd_printp_at (0, 0, PSTR(" ERROR: Datenverlust "), 2);
657
 
658
//                      lcd_printp_at (0, 2, PSTR("Letzte bekannte"), 0);
659
//                      lcd_printp_at (0, 3, PSTR("Position gespeichert."), 0);
660
                        lcd_puts_at(0, 2, strGet(OSD_POS1), 0);
661
                        lcd_puts_at(0, 3, strGet(OSD_POS2), 0);
662
//                      lcd_printp_at (19, 7, PSTR("OK"), 0);
663
                        lcd_puts_at(19, 7, strGet(OK), 0);
664
//                      lcd_printp_at (0, 5, PSTR(" Breitengr  Längengr "), 0);
665
 
666
                        lcd_puts_at(0, 5, strGet(START_LASTPOS1), 0);
667
 
668
                        lcd_puts_at(12, 7, strGet(ENDE), 0);
669
 
670
                        BeepTime = 1500;
671
                        BeepMuster = 0x0040;
672
                        error = 1;
673
 
674
                        uint32_t lon = last5pos[0].Longitude;
675
                        write_ndigit_number_u (1, 6, (uint16_t)(lon/10000000), 2, 0);
676
                        lcd_printp_at (3, 6, PSTR("."), 0);
677
                        write_ndigit_number_u (4, 6, (uint16_t)((lon/1000) % 10000), 4, 1);
678
                        write_ndigit_number_u (8, 6, (uint16_t)((lon/10) % 100), 2, 1);
679
 
680
                        uint32_t lat = last5pos[0].Latitude;
681
                        write_ndigit_number_u (12, 6, (uint16_t)(lat/10000000), 2, 0);
682
                        lcd_printp_at (14, 6, PSTR("."), 0);
683
                        write_ndigit_number_u (15, 6, (uint16_t)((lat/1000) % 10000), 4, 1);
684
                        write_ndigit_number_u (19, 6, (uint16_t)((lat/10) % 100), 2, 1);
685
 
686
                        while (!get_key_press (1 << KEY_ENTER));
687
 
688
                        timer = TIMEOUT;
689
                        lcd_cls();
690
                        return;
691
 
692
                }
693
        }
694
}
695