Subversion Repositories Projects

Rev

Rev 373 | Rev 378 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 373 Rev 377
1
/****************************************************************************
1
/****************************************************************************
2
 *   Copyright (C) 2009 by Claas Anders "CaScAdE" Rathje                    *
2
 *   Copyright (C) 2009 by Claas Anders "CaScAdE" Rathje                    *
3
 *   admiralcascade@gmail.com                                               *
3
 *   admiralcascade@gmail.com                                               *
4
 *   Project-URL: http://www.mylifesucks.de/oss/c-osd/                      *
4
 *   Project-URL: http://www.mylifesucks.de/oss/c-osd/                      *
5
 *                                                                          *
5
 *                                                                          *
6
 *   This program is free software; you can redistribute it and/or modify   *
6
 *   This program is free software; you can redistribute it and/or modify   *
7
 *   it under the terms of the GNU General Public License as published by   *
7
 *   it under the terms of the GNU General Public License as published by   *
8
 *   the Free Software Foundation; either version 2 of the License.         *
8
 *   the Free Software Foundation; either version 2 of the License.         *
9
 *                                                                          *
9
 *                                                                          *
10
 *   This program is distributed in the hope that it will be useful,        *
10
 *   This program is distributed in the hope that it will be useful,        *
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
13
 *   GNU General Public License for more details.                           *
13
 *   GNU General Public License for more details.                           *
14
 *                                                                          *
14
 *                                                                          *
15
 *   You should have received a copy of the GNU General Public License      *
15
 *   You should have received a copy of the GNU General Public License      *
16
 *   along with this program; if not, write to the                          *
16
 *   along with this program; if not, write to the                          *
17
 *   Free Software Foundation, Inc.,                                        *
17
 *   Free Software Foundation, Inc.,                                        *
18
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.              *
18
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.              *
19
 *                                                                          *
19
 *                                                                          *
20
 *                                                                          *
20
 *                                                                          *
21
 *   Credits to:                                                            *
21
 *   Credits to:                                                            *
22
 *   Holger Buss & Ingo Busker from mikrokopter.de for the MK project       *
22
 *   Holger Buss & Ingo Busker from mikrokopter.de for the MK project       *
23
 *   Gregor "killagreg" Stobrawa for making the MK code readable            *
23
 *   Gregor "killagreg" Stobrawa for making the MK code readable            *
24
 *   Klaus "akku" Buettner for the hardware                                 *
24
 *   Klaus "akku" Buettner for the hardware                                 *
25
 *   Manuel "KeyOz" Schrape for explaining the MK protocol to me            *
25
 *   Manuel "KeyOz" Schrape for explaining the MK protocol to me            *
26
 ****************************************************************************/
26
 ****************************************************************************/
27
 
27
 
28
#include <avr/io.h>
28
#include <avr/io.h>
29
#include <avr/interrupt.h>
29
#include <avr/interrupt.h>
30
#include <util/delay.h>
30
#include <util/delay.h>
31
#include <avr/pgmspace.h> 
31
#include <avr/pgmspace.h> 
32
#include "main.h"
32
#include "main.h"
33
#include "max7456_software_spi.h"
33
#include "max7456_software_spi.h"
34
#include "usart1.h"
34
#include "usart1.h"
35
 
35
 
36
/* TODO:
36
/* TODO:
37
 * - verifiy correctness of values
37
 * - verifiy correctness of values
38
 * - clean up code :)
38
 * - clean up code :)
39
 */
39
 */
40
 
40
 
41
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
41
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
42
// data structs not needed for character flashin
42
// data structs not needed for character flashin
43
#include "mk-data-structs.h"
43
#include "mk-data-structs.h"
44
 
44
 
45
/* ##########################################################################
45
/* ##########################################################################
46
 * global definitions and global vars
46
 * global definitions and global vars
47
 * ##########################################################################*/
47
 * ##########################################################################*/
48
 
48
 
49
volatile uint16_t setsReceived = 0;
49
volatile uint16_t setsReceived = 0;
50
 
50
 
51
volatile NaviData_t naviData;
51
volatile NaviData_t naviData;
52
volatile DebugOut_t debugData;
52
volatile DebugOut_t debugData;
53
 
53
 
54
// cache old vars for blinking attribute, checkup is faster than full
54
// cache old vars for blinking attribute, checkup is faster than full
55
// attribute write each time
55
// attribute write each time
56
volatile uint8_t last_UBat = 255;
56
volatile uint8_t last_UBat = 255;
57
volatile uint8_t last_RC_Quality = 255;
57
volatile uint8_t last_RC_Quality = 255;
58
 
58
 
59
// 16bit should be enough, normal LiPos don't last that long
59
// 16bit should be enough, normal LiPos don't last that long
60
volatile uint16_t uptime = 0;
60
volatile uint16_t uptime = 0;
61
volatile uint16_t timer = 0;
61
volatile uint16_t timer = 0;
62
 
62
 
63
// remember last time data was received
63
// remember last time data was received
64
volatile uint8_t seconds_since_last_data = 0;
64
volatile uint8_t seconds_since_last_data = 0;
65
 
65
 
66
// store stats description in progmem to save space
66
// store stats description in progmem to save space
67
char stats_item_0[] PROGMEM = "max Altitude:";
67
char stats_item_0[] PROGMEM = "max Altitude:";
68
char stats_item_1[] PROGMEM = "max Speed   :";
68
char stats_item_1[] PROGMEM = "max Speed   :";
69
char stats_item_2[] PROGMEM = "max Distance:";
69
char stats_item_2[] PROGMEM = "max Distance:";
70
char stats_item_3[] PROGMEM = "min voltage :";
70
char stats_item_3[] PROGMEM = "min voltage :";
71
char stats_item_4[] PROGMEM = "max time    :";
71
char stats_item_4[] PROGMEM = "max time    :";
72
char* stats_item_pointers[] PROGMEM = {stats_item_0, stats_item_1, stats_item_2, stats_item_3, stats_item_4};
72
char* stats_item_pointers[] PROGMEM = {stats_item_0, stats_item_1, stats_item_2, stats_item_3, stats_item_4};
73
 
73
 
74
// store more fixed strings in progmen
74
// store more fixed strings in progmen
75
char ON[]  PROGMEM = "ON ";
75
char ON[]  PROGMEM = "ON ";
76
char OFF[] PROGMEM = "OFF";
76
char OFF[] PROGMEM = "OFF";
77
 
77
 
78
#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))
78
#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))
79
 
79
 
80
// general PAL|NTSC distingiusch stuff
80
// general PAL|NTSC distingiusch stuff
81
uint8_t top_line = 1;
81
uint8_t top_line = 1;
82
uint8_t bottom_line = 14;
82
uint8_t bottom_line = 14;
83
 
83
 
84
// Flags
84
// Flags
85
uint8_t COSD_FLAGS = 0;
85
uint8_t COSD_FLAGS = 0;
86
 
86
 
87
/* ##########################################################################
87
/* ##########################################################################
88
 * debounce buttons
88
 * debounce buttons
89
 * ##########################################################################*/
89
 * ##########################################################################*/
90
int s1_pressed() {
90
int s1_pressed() {
91
        if (S1_PRESSED) {
91
        if (S1_PRESSED) {
92
                _delay_ms(25);
92
                _delay_ms(25);
93
                if (S1_PRESSED) return 1;
93
                if (S1_PRESSED) return 1;
94
        }
94
        }
95
        return 0;
95
        return 0;
96
}
96
}
97
 
97
 
98
int s2_pressed() {
98
int s2_pressed() {
99
        if (S2_PRESSED) {
99
        if (S2_PRESSED) {
100
                _delay_ms(25);
100
                _delay_ms(25);
101
                if (S2_PRESSED) return 1;
101
                if (S2_PRESSED) return 1;
102
        }
102
        }
103
        return 0;
103
        return 0;
104
}
104
}
105
 
105
 
106
 
106
 
107
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
107
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
108
 
108
 
109
/**
109
/**
110
 * serial support
110
 * serial support
111
 */
111
 */
112
//#include "usart1.c"
112
//#include "usart1.c"
113
 
113
 
114
 
114
 
115
/* ##########################################################################
115
/* ##########################################################################
116
 * timer stuff
116
 * timer stuff
117
 * ##########################################################################*/
117
 * ##########################################################################*/
118
 
118
 
119
/**
119
/**
120
 * timer kicks in every 1000uS ^= 1ms
120
 * timer kicks in every 1000uS ^= 1ms
121
 */
121
 */
122
ISR(TIMER0_OVF_vect) {
122
ISR(TIMER0_OVF_vect) {
123
    OCR0 = 6; // preload
123
    OCR0 = 6; // preload
124
    if (!timer--) {
124
    if (!timer--) {
125
        uptime++;
125
        uptime++;
126
        timer = 999;
126
        timer = 999;
127
                seconds_since_last_data++;
127
                seconds_since_last_data++;
128
    }
128
    }
129
}
129
}
130
 
130
 
131
/* ##########################################################################
131
/* ##########################################################################
132
 * compass stuff
132
 * compass stuff
133
 * ##########################################################################*/
133
 * ##########################################################################*/
134
 
134
 
135
/**
135
/**
136
 * convert the <heading> gotton from NC into an index
136
 * convert the <heading> gotton from NC into an index
137
 */
137
 */
138
uint8_t heading_conv(uint16_t heading) {
138
uint8_t heading_conv(uint16_t heading) {
139
    if (heading > 23 && heading < 68) {
139
    if (heading > 23 && heading < 68) {
140
        //direction = "NE";
140
        //direction = "NE";
141
        return 0;
141
        return 0;
142
    } else if (heading > 67 && heading < 113) {
142
    } else if (heading > 67 && heading < 113) {
143
        //direction = "E ";
143
        //direction = "E ";
144
        return 1;
144
        return 1;
145
    } else if (heading > 112 && heading < 158) {
145
    } else if (heading > 112 && heading < 158) {
146
        //direction = "SE";
146
        //direction = "SE";
147
        return 2;
147
        return 2;
148
    } else if (heading > 157 && heading < 203) {
148
    } else if (heading > 157 && heading < 203) {
149
        //direction = "S ";
149
        //direction = "S ";
150
        return 3;
150
        return 3;
151
    } else if (heading > 202 && heading < 248) {
151
    } else if (heading > 202 && heading < 248) {
152
        //direction = "SW";
152
        //direction = "SW";
153
        return 4;
153
        return 4;
154
    } else if (heading > 247 && heading < 293) {
154
    } else if (heading > 247 && heading < 293) {
155
        //direction = "W ";
155
        //direction = "W ";
156
        return 5;
156
        return 5;
157
    } else if (heading > 292 && heading < 338) {
157
    } else if (heading > 292 && heading < 338) {
158
        //direction = "NW";
158
        //direction = "NW";
159
        return 6;
159
        return 6;
160
    }
160
    }
161
    //direction = "N ";
161
    //direction = "N ";
162
    return 7;
162
    return 7;
163
}
163
}
164
 
164
 
165
/**
165
/**
-
 
166
 * convert the <heading> gotton from NC into a more
-
 
167
 * precise index
-
 
168
 */
-
 
169
uint8_t heading_fine_conv(uint16_t heading) {
-
 
170
        if (heading > 337) return 0;
-
 
171
        return (heading * 10) / 225;
-
 
172
}
-
 
173
 
-
 
174
/**
166
 * draw a compass rose at <x>/<y> for <heading>
175
 * draw a compass rose at <x>/<y> for <heading>
167
 */
176
 */
168
void draw_compass(uint8_t x, uint8_t y, uint16_t heading) {
177
void draw_compass(uint8_t x, uint8_t y, uint16_t heading) {
169
    //char* rose = "---N---O---S---W---N---O---S---W---N---O---S---W";
178
    //char* rose = "---N---O---S---W---N---O---S---W---N---O---S---W";
170
    char rose[48] = {216, 215, 216, 211, 216, 215, 216, 213, 216, 215, 216, 212,
179
    char rose[48] = {216, 215, 216, 211, 216, 215, 216, 213, 216, 215, 216, 212,
171
                    216, 215, 216, 214, 216, 215, 216, 211, 216, 215, 216, 213,
180
                    216, 215, 216, 214, 216, 215, 216, 211, 216, 215, 216, 213,
172
                    216, 215, 216, 212, 216, 215, 216, 214, 216, 215, 216, 211,
181
                    216, 215, 216, 212, 216, 215, 216, 214, 216, 215, 216, 211,
173
                    216, 215, 216, 213, 216, 215, 216, 212, 216, 215, 216, 214};
182
                    216, 215, 216, 213, 216, 215, 216, 212, 216, 215, 216, 214};
174
        // the center is char 19 (north), we add the current heading in 8th
183
        // the center is char 19 (north), we add the current heading in 8th
175
        // which would be 22.5 degrees, but float would bloat up the code
184
        // which would be 22.5 degrees, but float would bloat up the code
176
        // and *10 / 225 would take ages... so we take the uncorrect way
185
        // and *10 / 225 would take ages... so we take the uncorrect way
177
    uint8_t front = 19 + (heading / 22);
186
    uint8_t front = 19 + (heading / 22);
178
    for (uint8_t i = 0; i < 9; i++) {
187
    for (uint8_t i = 0; i < 9; i++) {
179
                write_char_xy(x++, y, rose[front - 4 + i]);
188
                write_char_xy(x++, y, rose[front - 4 + i]);
180
    }
189
    }
181
}
190
}
182
 
191
 
183
/* ##########################################################################
192
/* ##########################################################################
-
 
193
 * battery index
-
 
194
 * ##########################################################################*/
-
 
195
/**
-
 
196
 * draw a battery symbol at <x>/<y> according to <voltage>
-
 
197
 */
-
 
198
void draw_battery(uint8_t x, uint8_t y, uint16_t voltage) {
-
 
199
        uint8_t percent = (100* (voltage - UBAT_WRN) / (UBAT_MAX - UBAT_WRN));
-
 
200
        if (percent > 100) percent = 100;
-
 
201
        write_char_xy(x, y, 0x9d - (percent * 13 / 100));
-
 
202
        //write_ndigit_number_u(x, y-1, percent * 13 / 100, 100, 0);
-
 
203
}
-
 
204
 
-
 
205
/**
-
 
206
 * draw variometer arrows at <x>/<y> according to <variometer>
-
 
207
 */
-
 
208
void draw_variometer(uint8_t x, uint8_t y, int16_t variometer) {
-
 
209
        if (variometer == 0) {
-
 
210
                write_char_xy(x, y, 0xbb); // plain line
-
 
211
        } else if (variometer > 0) { // gain height
-
 
212
                switch (variometer / 5){
-
 
213
                        case 0:
-
 
214
                                write_char_xy(x, y, 0xba); // smallest arrow up
-
 
215
                                break;
-
 
216
                        case 1:
-
 
217
                                write_char_xy(x, y, 0xb9); // small arrow up
-
 
218
                                break;
-
 
219
                        case 2:
-
 
220
                                write_char_xy(x, y, 0xb8); // large arrow up
-
 
221
                                break;
-
 
222
                        default:
-
 
223
                                write_char_xy(x, y, 0xb7); // largest arrow up
-
 
224
                }
-
 
225
        } else { // sink
-
 
226
                switch (variometer / -5){
-
 
227
                        case 0:
-
 
228
                                write_char_xy(x, y, 0xbc); // smallest arrow down
-
 
229
                                break;
-
 
230
                        case 1:
-
 
231
                                write_char_xy(x, y, 0xbd); // small arrow down
-
 
232
                                break;
-
 
233
                        case 2:
-
 
234
                                write_char_xy(x, y, 0xbe); // large arrow down
-
 
235
                                break;
-
 
236
                        default:
-
 
237
                                write_char_xy(x, y, 0xbf); // largest arrow down
-
 
238
                }
-
 
239
        }
-
 
240
}
-
 
241
 
-
 
242
/* ##########################################################################
184
 * artificial horizon
243
 * artificial horizon
185
 * ##########################################################################*/
244
 * ##########################################################################*/
186
// remember last time displayed values
245
// remember last time displayed values
187
int8_t old_af_x = -1, old_af_y = -1;
246
int8_t old_af_x = -1, old_af_y = -1;
188
 
247
 
189
/**
248
/**
190
 * draw roll und nick indicators (could be enhanced to full artificial horizon)
249
 * draw roll und nick indicators (could be enhanced to full artificial horizon)
191
 * from line <firstline> to <listlines> for given <nick> and <roll> values
250
 * from line <firstline> to <listlines> for given <nick> and <roll> values
192
 */
251
 */
193
void draw_artificial_horizon(uint8_t firstline, uint8_t lastline, int16_t nick, int16_t roll) {
252
void draw_artificial_horizon(uint8_t firstline, uint8_t lastline, int16_t nick, int16_t roll) {
194
        char noodle[5] = {225, 225, 226, 227, 227};
253
        char noodle[5] = {225, 225, 226, 227, 227};
195
        uint8_t center_x = 15;
254
        uint8_t center_x = 15;
196
        uint8_t center_y = lastline - firstline;
255
        uint8_t center_y = lastline - firstline;
197
        center_y = 7;
256
        center_y = 7;
198
        write_char_xy(center_x,center_y,228);
257
        write_char_xy(center_x,center_y,228);
199
        uint8_t cpos, nicky, rollx;
258
        uint8_t cpos, nicky, rollx;
200
       
259
       
201
        // which line
260
        // which line
202
        int8_t ypos =  nick / 20;
261
        int8_t ypos =  nick / 20;
203
        // which character from the array?
262
        // which character from the array?
204
        if (nick < 0) {
263
        if (nick < 0) {
205
                cpos = -1*((nick - (ypos * 20))/4);
264
                cpos = -1*((nick - (ypos * 20))/4);
206
                ypos--;
265
                ypos--;
207
        } else cpos = 4-((nick - (ypos * 20))/4);
266
        } else cpos = 4-((nick - (ypos * 20))/4);
208
        if (cpos > 4) cpos = 4;
267
        if (cpos > 4) cpos = 4;
209
 
268
 
210
        nicky = center_y - ypos;
269
        nicky = center_y - ypos;
211
        if (nicky > lastline) nicky = lastline;
270
        if (nicky > lastline) nicky = lastline;
212
        else if (nicky < firstline) nicky = firstline;
271
        else if (nicky < firstline) nicky = firstline;
213
 
272
 
214
        // ensure roll-borders
273
        // ensure roll-borders
215
        rollx = (roll / 8)+15;
274
        rollx = (roll / 8)+15;
216
        if (rollx < 2) rollx = 2;
275
        if (rollx < 2) rollx = 2;
217
        else if (rollx > 28) rollx = 28;
276
        else if (rollx > 28) rollx = 28;
218
 
277
 
219
 
278
 
220
        // clear roll
279
        // clear roll
221
        if (old_af_x != rollx && old_af_x >= 0) {
280
        if (old_af_x != rollx && old_af_x >= 0) {
222
                write_char_xy(old_af_x,13,0);
281
                write_char_xy(old_af_x,13,0);
223
        }
282
        }
224
 
283
 
225
        // clear nick
284
        // clear nick
226
        if (old_af_y != nicky && old_af_y >= 0) {
285
        if (old_af_y != nicky && old_af_y >= 0) {
227
                write_char_xy(center_x-1,old_af_y,0);
286
                write_char_xy(center_x-1,old_af_y,0);
228
                write_char_xy(center_x+1,old_af_y,0);
287
                write_char_xy(center_x+1,old_af_y,0);
229
        }
288
        }
230
 
289
 
231
 
290
 
232
        // draw nick
291
        // draw nick
233
        write_char_xy(center_x-1,nicky,noodle[cpos]);
292
        write_char_xy(center_x-1,nicky,noodle[cpos]);
234
        write_char_xy(center_x+1,nicky,noodle[cpos]);
293
        write_char_xy(center_x+1,nicky,noodle[cpos]);
235
 
294
 
236
        // draw roll
295
        // draw roll
237
        write_char_xy(rollx,lastline,229);
296
        write_char_xy(rollx,lastline,229);
238
 
297
 
239
        // update old vars
298
        // update old vars
240
        old_af_x = rollx;
299
        old_af_x = rollx;
241
        old_af_y = nicky;
300
        old_af_y = nicky;
242
 
301
 
243
        // debug numbers
302
        // debug numbers
244
        //write_3digit_number_u(20,6,cpos);
303
        //write_3digit_number_u(20,6,cpos);
245
        //write_number_s(20,7,ypos);    
304
        //write_number_s(20,7,ypos);    
246
        //write_number_s(0,7,nick);             
305
        //write_number_s(0,7,nick);             
247
        //write_number_s(18,11,roll);   
306
        //write_number_s(18,11,roll);   
248
}
307
}
249
 
308
 
250
/* ##########################################################################
309
/* ##########################################################################
251
 * A simple config menu for the flags
310
 * A simple config menu for the flags
252
 * ##########################################################################*/
311
 * ##########################################################################*/
253
 
312
 
254
/**
313
/**
255
 * helper function for menu updating
314
 * helper function for menu updating
256
 */
315
 */
257
void config_menu_drawings(uint8_t chosen) {
316
void config_menu_drawings(uint8_t chosen) {
258
    // clear prevoius _cursor_
317
    // clear prevoius _cursor_
259
    write_ascii_string(3, (chosen + 6) % 7, " ");
318
    write_ascii_string(3, (chosen + 6) % 7, " ");
260
    // draw current _cursor_
319
    // draw current _cursor_
261
    write_ascii_string(3, chosen + 6, ">");
320
    write_ascii_string(3, chosen + 6, ">");
262
    if (COSD_FLAGS & COSD_FLAG_HUD) {
321
    if (COSD_FLAGS & COSD_FLAG_HUD) {
263
        write_ascii_string_pgm(23, 6, ON);
322
        write_ascii_string_pgm(23, 6, ON);
264
    } else {
323
    } else {
265
                write_ascii_string_pgm(23, 6, OFF);
324
                write_ascii_string_pgm(23, 6, OFF);
266
    }
325
    }
267
    if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) {
326
    if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) {
268
        write_ascii_string_pgm(23, 7, ON);
327
        write_ascii_string_pgm(23, 7, ON);
269
    } else {
328
    } else {
270
        write_ascii_string_pgm(23, 7, OFF);
329
        write_ascii_string_pgm(23, 7, OFF);
271
    }
330
    }
272
        if (COSD_FLAGS & COSD_FLAG_STATS) {
331
        if (COSD_FLAGS & COSD_FLAG_STATS) {
273
        write_ascii_string_pgm(23, 8, ON);
332
        write_ascii_string_pgm(23, 8, ON);
274
    } else {
333
    } else {
275
        write_ascii_string_pgm(23, 8, OFF);
334
        write_ascii_string_pgm(23, 8, OFF);
276
    }
335
    }
277
    if (COSD_FLAGS & COSD_FLAG_WARNINGS) {
336
    if (COSD_FLAGS & COSD_FLAG_WARNINGS) {
278
        write_ascii_string_pgm(23, 9, ON);
337
        write_ascii_string_pgm(23, 9, ON);
279
    } else {
338
    } else {
280
        write_ascii_string_pgm(23, 9, OFF);
339
        write_ascii_string_pgm(23, 9, OFF);
281
    }
340
    }
282
}
341
}
283
 
342
 
284
/**
343
/**
285
 * some sort of clicking response in the menu
344
 * some sort of clicking response in the menu
286
 */
345
 */
287
void config_menu_doclick(uint8_t chosen, char** menu) {
346
void config_menu_doclick(uint8_t chosen, char** menu) {
288
        write_ascii_string(4, chosen + 6, "DONE              ");
347
        write_ascii_string(4, chosen + 6, "DONE              ");
289
        _delay_ms(1000);
348
        _delay_ms(1000);
290
        write_ascii_string(4, chosen + 6, menu[chosen]);
349
        write_ascii_string(4, chosen + 6, menu[chosen]);
291
}
350
}
292
 
351
 
293
/**
352
/**
294
 * a simple config menu tryout
353
 * a simple config menu tryout
295
 */
354
 */
296
void config_menu(void) {
355
void config_menu(void) {
297
        // disable interrupts (makes the menu more smoothely)
356
        // disable interrupts (makes the menu more smoothely)
298
        cli();
357
        cli();
299
 
358
 
300
        // clear screen
359
        // clear screen
301
        clear();
360
        clear();
302
       
361
       
303
        char* menu[8] = {"Full HUD",
362
        char* menu[8] = {"Full HUD",
304
                                         "Art.Horizon in HUD",
363
                                         "Art.Horizon in HUD",
305
                                         "Statistics",
364
                                         "Statistics",
306
                                         "Warnings",    // TODO: do it!
365
                                         "Warnings",    // TODO: do it!
307
                                         "Reset uptime",
366
                                         "Reset uptime",
308
                                         "Request OSD-data",
367
                                         "Request OSD-data",
309
                                         "Disable Debug-data",
368
                                         "Disable Debug-data",
310
                                         "EXIT"};
369
                                         "EXIT"};
311
 
370
 
312
        uint8_t inmenu = 1;
371
        uint8_t inmenu = 1;
313
        uint8_t chosen = 0;
372
        uint8_t chosen = 0;
314
        write_ascii_string(6,  2, "C-OSD Config Menu");
373
        write_ascii_string(6,  2, "C-OSD Config Menu");
315
 
374
 
316
        // wait a bit before doing stuff so user has chance to release button
375
        // wait a bit before doing stuff so user has chance to release button
317
        _delay_ms(250);
376
        _delay_ms(250);
318
 
377
 
319
        write_ascii_string(4,  6, menu[0]);
378
        write_ascii_string(4,  6, menu[0]);
320
        write_ascii_string(4,  7, menu[1]);
379
        write_ascii_string(4,  7, menu[1]);
321
        write_ascii_string(4,  8, menu[2]);
380
        write_ascii_string(4,  8, menu[2]);
322
        write_ascii_string(4,  9, menu[3]);
381
        write_ascii_string(4,  9, menu[3]);
323
        write_ascii_string(4, 10, menu[4]);
382
        write_ascii_string(4, 10, menu[4]);
324
        write_ascii_string(4, 11, menu[5]);
383
        write_ascii_string(4, 11, menu[5]);
325
        write_ascii_string(4, 12, menu[6]);
384
        write_ascii_string(4, 12, menu[6]);
326
        write_ascii_string(4, 13, menu[7]);
385
        write_ascii_string(4, 13, menu[7]);
327
 
386
 
328
        config_menu_drawings(chosen);
387
        config_menu_drawings(chosen);
329
 
388
 
330
        while (inmenu) {
389
        while (inmenu) {
331
                        if (s2_pressed()) {
390
                        if (s2_pressed()) {
332
                                write_ascii_string(3,  chosen+6, " ");
391
                                write_ascii_string(3,  chosen+6, " ");
333
                                chosen = (chosen + 1) % 8;
392
                                chosen = (chosen + 1) % 8;
334
                                write_ascii_string(3,  chosen+6, ">");
393
                                write_ascii_string(3,  chosen+6, ">");
335
                                _delay_ms(500);
394
                                _delay_ms(500);
336
                        } else if (s1_pressed()) {
395
                        } else if (s1_pressed()) {
337
                                switch (chosen) {
396
                                switch (chosen) {
338
                                        case 0:         // full HUD
397
                                        case 0:         // full HUD
339
                                                COSD_FLAGS ^= COSD_FLAG_HUD;
398
                                                COSD_FLAGS ^= COSD_FLAG_HUD;
340
                                                config_menu_drawings(chosen);
399
                                                config_menu_drawings(chosen);
341
                                                break;
400
                                                break;
342
                                        case 1:         // art horizon
401
                                        case 1:         // art horizon
343
                                                COSD_FLAGS ^= COSD_FLAG_ARTHORIZON;
402
                                                COSD_FLAGS ^= COSD_FLAG_ARTHORIZON;
344
                                                config_menu_drawings(chosen);
403
                                                config_menu_drawings(chosen);
345
                                                break;
404
                                                break;
346
                                        case 2:         // statistics
405
                                        case 2:         // statistics
347
                                                COSD_FLAGS ^= COSD_FLAG_STATS;
406
                                                COSD_FLAGS ^= COSD_FLAG_STATS;
348
                                                config_menu_drawings(chosen);
407
                                                config_menu_drawings(chosen);
349
                                                break;
408
                                                break;
350
                                        case 3:         // warnings
409
                                        case 3:         // warnings
351
                                                COSD_FLAGS ^= COSD_FLAG_WARNINGS;
410
                                                COSD_FLAGS ^= COSD_FLAG_WARNINGS;
352
                                                config_menu_drawings(chosen);
411
                                                config_menu_drawings(chosen);
353
                                                break;
412
                                                break;
354
                                        case 4:         // reset uptime
413
                                        case 4:         // reset uptime
355
                                                uptime = 0;
414
                                                uptime = 0;
356
                                                config_menu_doclick(chosen, menu);
415
                                                config_menu_doclick(chosen, menu);
357
                                                break;
416
                                                break;
358
                                        case 5:         // re-request OSD data
417
                                        case 5:         // re-request OSD data
359
                                                // request OSD Data from NC every 100ms
418
                                                // request OSD Data from NC every 100ms
360
                                                usart1_request_mk_data(1, 'o', 100);
419
                                                usart1_request_mk_data(1, 'o', 100);
361
                                                config_menu_doclick(chosen, menu);
420
                                                config_menu_doclick(chosen, menu);
362
                                                break;
421
                                                break;
363
                                        case 6:         // disable debug data
422
                                        case 6:         // disable debug data
364
                                                // disable sending of debug data
423
                                                // disable sending of debug data
365
                                                // may result in smoother ddata display
424
                                                // may result in smoother ddata display
366
                                                usart1_request_mk_data(0, 'd', 0);
425
                                                usart1_request_mk_data(0, 'd', 0);
367
                                                config_menu_doclick(chosen, menu);
426
                                                config_menu_doclick(chosen, menu);
368
                                                break;
427
                                                break;
369
                                        case 7:         // exit
428
                                        case 7:         // exit
370
                                                inmenu = 0;
429
                                                inmenu = 0;
371
                                                break;
430
                                                break;
372
                                }
431
                                }
373
                                _delay_ms(250);
432
                                _delay_ms(250);
374
                        }
433
                        }
375
        }
434
        }
376
 
435
 
377
        // clear screen up again
436
        // clear screen up again
378
        clear();
437
        clear();
379
 
438
 
380
        // update flags to paint display again if needed
439
        // update flags to paint display again if needed
381
        COSD_FLAGS &= ~COSD_ICONS_WRITTEN;
440
        COSD_FLAGS &= ~COSD_ICONS_WRITTEN;
382
 
441
 
383
        // enable interrupts again
442
        // enable interrupts again
384
        sei();
443
        sei();
385
}
444
}
386
 
445
 
387
#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))
446
#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))
388
/* ##########################################################################
447
/* ##########################################################################
389
 * MAIN
448
 * MAIN
390
 * ##########################################################################*/
449
 * ##########################################################################*/
391
int main(void) {
450
int main(void) {
392
    // set up FLAGS, compiler should flatten this one
451
    // set up FLAGS, compiler should flatten this one
393
    COSD_FLAGS = (NTSC << 0);
452
    COSD_FLAGS = (NTSC << 0);
394
    COSD_FLAGS |= (HUD << 1);
453
    COSD_FLAGS |= (HUD << 1);
395
    COSD_FLAGS |= (ARTHORIZON << 2);
454
    COSD_FLAGS |= (ARTHORIZON << 2);
396
        COSD_FLAGS |= (STATS << 3);
455
        COSD_FLAGS |= (STATS << 3);
397
    COSD_FLAGS |= (WARNINGS << 4);
456
    COSD_FLAGS |= (WARNINGS << 4);
398
 
457
 
399
    // set up Atmega162 Ports
458
    // set up Atmega162 Ports
400
    DDRA |= (1 << PA1); // PA1 output (/CS)
459
    DDRA |= (1 << PA1); // PA1 output (/CS)
401
    MAX_CS_HIGH
460
    MAX_CS_HIGH
402
    DDRA |= (1 << PA2); // PA2 output (SDIN)
461
    DDRA |= (1 << PA2); // PA2 output (SDIN)
403
    MAX_SDIN_LOW
462
    MAX_SDIN_LOW
404
    DDRA |= (1 << PA3); // PA3 output (SCLK)
463
    DDRA |= (1 << PA3); // PA3 output (SCLK)
405
    MAX_SCLK_LOW
464
    MAX_SCLK_LOW
406
    DDRA |= (1 << PA5); // PA5 output (RESET)
465
    DDRA |= (1 << PA5); // PA5 output (RESET)
407
    MAX_RESET_HIGH
466
    MAX_RESET_HIGH
408
 
467
 
409
    DDRC |= (1 << PC0); // PC0 output (LED1 gn)
468
    DDRC |= (1 << PC0); // PC0 output (LED1 gn)
410
    LED1_OFF
469
    LED1_OFF
411
    DDRC |= (1 << PC1); // PC1 output (LED2 rt)
470
    DDRC |= (1 << PC1); // PC1 output (LED2 rt)
412
    LED2_OFF
471
    LED2_OFF
413
    DDRC |= (1 << PC2); // PC2 output (LED3 gn)
472
    DDRC |= (1 << PC2); // PC2 output (LED3 gn)
414
    LED3_OFF
473
    LED3_OFF
415
    DDRC |= (1 << PC3); // PC3 output (LED4 rt)
474
    DDRC |= (1 << PC3); // PC3 output (LED4 rt)
416
    LED4_OFF
475
    LED4_OFF
417
 
476
 
418
    DDRC &= ~(1 << PC4); // PC4 input  (MODE)
477
    DDRC &= ~(1 << PC4); // PC4 input  (MODE)
419
    PORTC |= (1 << PC4); // pullup
478
    PORTC |= (1 << PC4); // pullup
420
    DDRC &= ~(1 << PC5); // PC5 input  (SET)
479
    DDRC &= ~(1 << PC5); // PC5 input  (SET)
421
    PORTC |= (1 << PC5); // pullup
480
    PORTC |= (1 << PC5); // pullup
422
 
481
 
423
    // set up top and bottom lines
482
    // set up top and bottom lines
424
    if (COSD_FLAGS & COSD_FLAG_NTSC) {
483
    if (COSD_FLAGS & COSD_FLAG_NTSC) {
425
        bottom_line = 12;
484
        bottom_line = 12;
426
    } else {
485
    } else {
427
        bottom_line = 14;
486
        bottom_line = 14;
428
    }
487
    }
429
 
488
 
430
    // reset the MAX7456 to be sure any undefined states do no harm
489
    // reset the MAX7456 to be sure any undefined states do no harm
431
    MAX_RESET_LOW
490
    MAX_RESET_LOW
432
    MAX_RESET_HIGH
491
    MAX_RESET_HIGH
433
 
492
 
434
    // give the FC/NC and the maxim time to come up
493
    // give the FC/NC and the maxim time to come up
435
    LED4_ON
494
    LED4_ON
436
    _delay_ms(2000);
495
    _delay_ms(2000);
437
 
496
 
438
    LED4_OFF
497
    LED4_OFF
439
 
498
 
440
 
499
 
441
    //Pushing NEW chars to the MAX7456
500
    //Pushing NEW chars to the MAX7456
442
#if (WRITECHARS != -1)
501
#if (WRITECHARS != -1)
443
    // DISABLE display (VM0)
502
    // DISABLE display (VM0)
444
    spi_send_byte(0x00, 0b00000000);
503
    spi_send_byte(0x00, 0b00000000);
445
#include "characters.c"
504
#include "characters.c"
446
 
505
 
447
#endif 
506
#endif 
448
 
507
 
449
    // Setup Video Mode
508
    // Setup Video Mode
450
    if (COSD_FLAGS & COSD_FLAG_NTSC) {
509
    if (COSD_FLAGS & COSD_FLAG_NTSC) {
451
        // NTSC + enable display immediately (VM0)
510
        // NTSC + enable display immediately (VM0)
452
        spi_send_byte(0x00, 0b00001000);
511
        spi_send_byte(0x00, 0b00001000);
453
    } else {
512
    } else {
454
        // PAL + enable display immediately (VM0)
513
        // PAL + enable display immediately (VM0)
455
        spi_send_byte(0x00, 0b01001000);
514
        spi_send_byte(0x00, 0b01001000);
456
    }
515
    }
457
 
516
 
458
    // clear all display-mem (DMM)
517
    // clear all display-mem (DMM)
459
    spi_send_byte(0x04, 0b00000100);
518
    spi_send_byte(0x04, 0b00000100);
460
 
519
 
461
    // clearing takes 12uS according to maxim so lets wait longer
520
    // clearing takes 12uS according to maxim so lets wait longer
462
    _delay_us(120);
521
    _delay_us(120);
463
 
522
 
464
    // 8bit mode
523
    // 8bit mode
465
    spi_send_byte(0x04, 0b01000000);
524
    spi_send_byte(0x04, 0b01000000);
466
 
525
 
467
    // write blank chars to whole screen
526
    // write blank chars to whole screen
468
    clear();
527
    clear();
469
 
528
 
470
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
529
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
471
    // init usart
530
    // init usart
472
    usart1_init();
531
    usart1_init();
473
 
532
 
474
    // set up timer
533
    // set up timer
475
    TCCR0 |= (1 << CS00) | (1 << CS01); // timer0 prescaler 64
534
    TCCR0 |= (1 << CS00) | (1 << CS01); // timer0 prescaler 64
476
    OCR0 = 6; // preload
535
    OCR0 = 6; // preload
477
    TIMSK |= (1 << TOIE0); // enable overflow timer0
536
    TIMSK |= (1 << TOIE0); // enable overflow timer0
478
 
537
 
479
    // enable interrupts
538
    // enable interrupts
480
    sei();
539
    sei();
481
#endif
540
#endif
482
 
541
 
483
    //write_ascii_string(2,  7, "         CaScAdE          ");
542
    //write_ascii_string(2,  7, "         CaScAdE          ");
484
    //write_ascii_string(2,  8, "is TESTING his open source");
543
    //write_ascii_string(2,  8, "is TESTING his open source");
485
    //write_ascii_string(2,  9, "    EPi OSD Firmware");
544
    //write_ascii_string(2,  9, "    EPi OSD Firmware");
486
 
545
 
487
    // custom char preview
546
    // custom char preview
488
    /*write_char_xy( 2, 7, 200);
547
    /*write_char_xy( 2, 7, 200);
489
    write_char_xy( 3, 7, 201);
548
    write_char_xy( 3, 7, 201);
490
    write_char_xy( 4, 7, 202);
549
    write_char_xy( 4, 7, 202);
491
    write_char_xy( 5, 7, 203);
550
    write_char_xy( 5, 7, 203);
492
    write_char_xy( 6, 7, 204);
551
    write_char_xy( 6, 7, 204);
493
    write_char_xy( 7, 7, 205);
552
    write_char_xy( 7, 7, 205);
494
    write_char_xy( 8, 7, 206);
553
    write_char_xy( 8, 7, 206);
495
    write_char_xy( 9, 7, 207);
554
    write_char_xy( 9, 7, 207);
496
    write_char_xy(10, 7, 208);
555
    write_char_xy(10, 7, 208);
497
    write_char_xy(11, 7, 209);
556
    write_char_xy(11, 7, 209);
498
    write_char_xy(12, 7, 210);
557
    write_char_xy(12, 7, 210);
499
    write_char_xy(13, 7, 211);
558
    write_char_xy(13, 7, 211);
500
    write_char_xy(14, 7, 212);
559
    write_char_xy(14, 7, 212);
501
    write_char_xy(15, 7, 213);
560
    write_char_xy(15, 7, 213);
502
    write_char_xy(16, 7, 214);
561
    write_char_xy(16, 7, 214);
503
    write_char_xy(17, 7, 215);*/
562
    write_char_xy(17, 7, 215);*/
504
 
563
 
505
    // we are ready
564
    // we are ready
506
    LED3_ON
565
    LED3_ON
507
 
566
 
508
 
567
 
509
 
568
 
510
#if ALLCHARSDEBUG | (WRITECHARS != -1)
569
#if ALLCHARSDEBUG | (WRITECHARS != -1)
511
        clear();
570
        clear();
512
    write_all_chars();
571
    write_all_chars();
513
#else
572
#else
514
        // clear serial screen
573
        // clear serial screen
515
        //usart1_puts("\x1B[2J\x1B[H");
574
        //usart1_puts("\x1B[2J\x1B[H");
516
        //usart1_puts("hello world!\r\n");
575
        //usart1_puts("hello world!\r\n");
517
 
576
 
518
 
577
 
519
        // request data ever 100ms from FC;
578
        // request data ever 100ms from FC;
520
        //usart1_request_mk_data(0, 'd', 100);
579
        //usart1_request_mk_data(0, 'd', 100);
521
 
580
 
522
        // request OSD Data from NC every 100ms
581
        // request OSD Data from NC every 100ms
523
        usart1_request_mk_data(1, 'o', 100);
582
        usart1_request_mk_data(1, 'o', 100);
524
 
583
 
525
    // and disable debug...
584
    // and disable debug...
526
        //usart1_request_mk_data(0, 'd', 0);
585
        //usart1_request_mk_data(0, 'd', 0);
527
 
586
 
528
    // disable TXD-pin
587
    // disable TXD-pin
529
    usart1_DisableTXD();
588
    usart1_DisableTXD();
530
 
589
 
531
    // stats for after flight
590
    // stats for after flight
532
    int16_t max_Altimeter = 0;
591
    int16_t max_Altimeter = 0;
533
    uint16_t max_GroundSpeed = 0;
592
    uint16_t max_GroundSpeed = 0;
534
    int16_t max_Distance = 0;
593
    int16_t max_Distance = 0;
535
    uint8_t min_UBat = 255;
594
    uint8_t min_UBat = 255;
536
    uint16_t max_FlyingTime = 0;
595
    uint16_t max_FlyingTime = 0;
537
 
596
 
538
    // flags from last round to check for changes
597
    // flags from last round to check for changes
539
    uint8_t old_MKFlags = 0;
598
    uint8_t old_MKFlags = 0;
540
 
599
 
541
    char* directions[8] = {"NE", "E ", "SE", "S ", "SW", "W ", "NW", "N "};
600
    char* directions[8] = {"NE", "E ", "SE", "S ", "SW", "W ", "NW", "N "};
542
    char arrowdir[8] = {218, 217, 224, 223, 222, 221, 220, 219};
601
    //char arrowdir[8] = {218, 217, 224, 223, 222, 221, 220, 219};
543
 
602
 
544
        /*write_ndigit_number_s_10th(5, 10, 1, 100, 0);
603
        /*write_ndigit_number_s_10th(5, 10, 1, 100, 0);
545
        write_ndigit_number_s_10th(5, 11, -1, 100, 0);
604
        write_ndigit_number_s_10th(5, 11, -1, 100, 0);
546
        write_ndigit_number_s_10th(5, 12, -11, 100, 0);*/
605
        write_ndigit_number_s_10th(5, 12, -11, 100, 0);*/
-
 
606
 
-
 
607
        //write_ndigit_number_u(2,2, heading_fine_conv(45), 100, 0);
547
 
608
 
548
    while (1) {
609
    while (1) {
549
        // write icons at init or after menu/mode-switch
610
        // write icons at init or after menu/mode-switch
550
        if (!(COSD_FLAGS & COSD_ICONS_WRITTEN) && (COSD_FLAGS & COSD_FLAG_HUD)) {
611
        if (!(COSD_FLAGS & COSD_ICONS_WRITTEN) && (COSD_FLAGS & COSD_FLAG_HUD)) {
551
            write_char_xy(5, top_line, 203); // km/h
612
            write_char_xy(5, top_line, 203); // km/h
552
            write_char_xy(10, top_line, 202); // RC-transmitter
613
            write_char_xy(10, top_line, 202); // RC-transmitter
553
            write_char_xy(16, top_line, 208); // degree symbol
614
            write_char_xy(16, top_line, 208); // degree symbol
554
            write_char_xy(27, top_line, 204); // small meters m
615
            write_char_xy(27, top_line, 204); // small meters m
555
            write_ascii_string(6, bottom_line, "V"); // voltage
616
            //write_ascii_string(6, bottom_line, "V"); // voltage
556
            write_char_xy(14, bottom_line, 209); // on clock
617
            write_char_xy(14, bottom_line, 209); // on clock
557
            write_char_xy(22, bottom_line, 210); // fly clock
618
            write_char_xy(22, bottom_line, 210); // fly clock
558
            write_char_xy(26, bottom_line, 200); // sat1
619
            write_char_xy(26, bottom_line, 200); // sat1
559
            write_char_xy(27, bottom_line, 201); // sat2
620
            write_char_xy(27, bottom_line, 201); // sat2
560
            COSD_FLAGS |= COSD_ICONS_WRITTEN;
621
            COSD_FLAGS |= COSD_ICONS_WRITTEN;
561
        }
622
        }
562
        if (rxd_buffer_locked) {
623
        if (rxd_buffer_locked) {
563
            if (COSD_FLAGS & COSD_FLAG_HUD) {
624
            if (COSD_FLAGS & COSD_FLAG_HUD) {
564
                if (rxd_buffer[2] == 'D') { // FC Data
625
                if (rxd_buffer[2] == 'D') { // FC Data
565
                    /*Decode64();
626
                    /*Decode64();
566
                    debugData = *((DebugOut_t*) pRxData);
627
                    debugData = *((DebugOut_t*) pRxData);
567
                    write_number_s(12, 2, RxDataLen);
628
                    write_number_s(12, 2, RxDataLen);
568
                    write_number_s(20, 2, setsReceived++);
629
                    write_number_s(20, 2, setsReceived++);
569
                    write_number_s(12, 3, debugData.Analog[0]); // AngleNick
630
                    write_number_s(12, 3, debugData.Analog[0]); // AngleNick
570
                    write_number_s(12, 4, debugData.Analog[1]); // AngleRoll
631
                    write_number_s(12, 4, debugData.Analog[1]); // AngleRoll
571
                                        write_number_s(12, 5, debugData.Analog[5]); // Height
632
                                        write_number_s(12, 5, debugData.Analog[5]); // Height
572
                    write_number_s(12, 6, debugData.Analog[9]); // Voltage
633
                    write_number_s(12, 6, debugData.Analog[9]); // Voltage
573
                    write_number_s(12, 7, debugData.Analog[10]);// RC Signal
634
                    write_number_s(12, 7, debugData.Analog[10]);// RC Signal
574
                                        write_number_s(12, 8, debugData.Analog[11]);// Gyro compass*/
635
                                        write_number_s(12, 8, debugData.Analog[11]);// Gyro compass*/
575
                } else if (rxd_buffer[2] == 'O') { // NC OSD Data
636
                } else if (rxd_buffer[2] == 'O') { // NC OSD Data
576
                    Decode64();
637
                    Decode64();
577
                    naviData = *((NaviData_t*) pRxData);
638
                    naviData = *((NaviData_t*) pRxData);
578
 
639
 
579
                    // first line
640
                    // first line
580
                    write_ndigit_number_u(2, top_line, (uint16_t) (((uint32_t) naviData.GroundSpeed * (uint32_t)9) / (uint32_t)250), 100, 0);
641
                    write_ndigit_number_u(2, top_line, (uint16_t) (((uint32_t) naviData.GroundSpeed * (uint32_t)9) / (uint32_t)250), 100, 0);
581
 
642
 
582
                    write_ndigit_number_u(7, top_line, naviData.RC_Quality, 100, 0);
643
                    write_ndigit_number_u(7, top_line, naviData.RC_Quality, 100, 0);
583
                    if (naviData.RC_Quality <= RCLVL_WRN && last_RC_Quality > RCLVL_WRN) {
644
                    if (naviData.RC_Quality <= RCLVL_WRN && last_RC_Quality > RCLVL_WRN) {
584
                        for (uint8_t x = 0; x < 4; x++)
645
                        for (uint8_t x = 0; x < 4; x++)
585
                            write_char_att_xy(7 + x, top_line, BLINK);
646
                            write_char_att_xy(7 + x, top_line, BLINK);
586
                    } else if (naviData.RC_Quality > RCLVL_WRN && last_RC_Quality <= RCLVL_WRN) {
647
                    } else if (naviData.RC_Quality > RCLVL_WRN && last_RC_Quality <= RCLVL_WRN) {
587
                        for (uint8_t x = 0; x < 4; x++)
648
                        for (uint8_t x = 0; x < 4; x++)
588
                            write_char_att_xy(7 + x, top_line, 0);
649
                            write_char_att_xy(7 + x, top_line, 0);
589
                    }
650
                    }
590
                    last_RC_Quality = naviData.RC_Quality;
651
                    last_RC_Quality = naviData.RC_Quality;
591
 
652
 
592
                    write_ndigit_number_u(13, top_line, naviData.CompassHeading, 100, 0);
653
                    write_ndigit_number_u(13, top_line, naviData.CompassHeading, 100, 0);
593
 
654
 
594
                    write_ascii_string(17, top_line, directions[heading_conv(naviData.CompassHeading)]);
655
                    write_ascii_string(17, top_line, directions[heading_conv(naviData.CompassHeading)]);
595
 
656
                                       
596
                    if (naviData.Variometer == 0) {
-
 
597
                        write_char_xy(20, top_line, 206); // plain line
-
 
598
                    } else if (naviData.Variometer > 0 && naviData.Variometer <= 10) {
-
 
599
                        write_char_xy(20, top_line, 234); // small arrow up
-
 
600
                    } else if (naviData.Variometer > 10) {
657
                                        draw_variometer(20, top_line, naviData.Variometer);
601
                        write_char_xy(20, top_line, 235); // big arrow up
-
 
602
                    } else if (naviData.Variometer < 0 && naviData.Variometer >= -10) {
-
 
603
                        write_char_xy(20, top_line, 232); // small arrow down
-
 
604
                    } else {
-
 
605
                        write_char_xy(20, top_line, 233); //big arrow down
-
 
606
                    }
-
 
607
 
658
 
608
                    //note:lephisto:according to several sources it's /30
659
                    //note:lephisto:according to several sources it's /30
609
                    if (naviData.Altimeter > 300 || naviData.Altimeter < -300) {
660
                    if (naviData.Altimeter > 300 || naviData.Altimeter < -300) {
610
                        // above 10m only write full meters
661
                        // above 10m only write full meters
611
                        write_ndigit_number_s(23, top_line, naviData.Altimeter / 30, 1000, 0);
662
                        write_ndigit_number_s(23, top_line, naviData.Altimeter / 30, 1000, 0);
612
                    } else {
663
                    } else {
613
                        // up to 10m write meters.dm
664
                        // up to 10m write meters.dm
614
                        //write_number_u_10th(21, top_line, naviData.Altimeter / 3);
665
                        //write_number_u_10th(21, top_line, naviData.Altimeter / 3);
615
                                                write_ndigit_number_s_10th(23, top_line, naviData.Altimeter / 3, 100, 0);
666
                                                write_ndigit_number_s_10th(23, top_line, naviData.Altimeter / 3, 100, 0);
616
                    }
667
                    }
617
 
668
 
618
                    // seccond line
669
                    // seccond line
619
                    draw_compass(11, top_line + 1, naviData.CompassHeading);
670
                    draw_compass(11, top_line + 1, naviData.CompassHeading);
620
 
671
 
621
                    // TODO: verify correctness
672
                    // TODO: verify correctness
622
                    uint16_t heading_home = (naviData.HomePositionDeviation.Bearing + 360 - naviData.CompassHeading) % 360;
673
                    uint16_t heading_home = (naviData.HomePositionDeviation.Bearing + 360 - naviData.CompassHeading) % 360;
623
                    write_char_xy(27, top_line + 1, arrowdir[heading_conv(heading_home)]);
674
                    //write_char_xy(27, top_line + 1, arrowdir[heading_conv(heading_home)]);
-
 
675
                                        // finer resolution, 0xa0 is first character and we add the index 0 <= index < 16
-
 
676
                                        write_char_xy(27, top_line + 1, 0xa0 + heading_fine_conv(heading_home));
624
 
677
 
625
                    write_ndigit_number_u(24, top_line + 1, naviData.HomePositionDeviation.Distance / 10, 100, 0);
678
                    write_ndigit_number_u(24, top_line + 1, naviData.HomePositionDeviation.Distance / 10, 100, 0);
626
 
679
 
627
                    // center
680
                    // center
628
                    if (naviData.MKFlags & FLAG_MOTOR_RUN) { // should be engines running
681
                    if (naviData.MKFlags & FLAG_MOTOR_RUN) { // should be engines running
629
                        if (!(old_MKFlags & FLAG_MOTOR_RUN)) { // motors just started, clear middle
682
                        if (!(old_MKFlags & FLAG_MOTOR_RUN)) { // motors just started, clear middle
630
                            clear();
683
                            clear();
631
                            // update flags to paint display again if needed
684
                            // update flags to paint display again if needed
632
                            COSD_FLAGS &= ~COSD_ICONS_WRITTEN;
685
                            COSD_FLAGS &= ~COSD_ICONS_WRITTEN;
633
                        }
686
                        }
634
                        if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) {
687
                        if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) {
635
                            draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll);
688
                            draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll);
636
                        }
689
                        }
637
                    } else {
690
                    } else {
638
                                                // stats
691
                                                // stats
639
                                                if (COSD_FLAGS & COSD_FLAG_STATS) {
692
                                                if (COSD_FLAGS & COSD_FLAG_STATS) {
640
                                                        write_ascii_string_pgm(2, 5, stats_item_pointers[0]); // max Altitude
693
                                                        write_ascii_string_pgm(2, 5, stats_item_pointers[0]); // max Altitude
641
                                write_ndigit_number_s(18, 5, max_Altimeter / 30, 1000, 0);
694
                                write_ndigit_number_s(18, 5, max_Altimeter / 30, 1000, 0);
642
                                write_char_xy(22, 5, 204); // small meters m
695
                                write_char_xy(22, 5, 204); // small meters m
643
                                                        write_ascii_string_pgm(2, 6, stats_item_pointers[1]); // max Speed
696
                                                        write_ascii_string_pgm(2, 6, stats_item_pointers[1]); // max Speed
644
                                write_ndigit_number_u(19, 6, (uint16_t) (((uint32_t) max_GroundSpeed * 36) / 1000), 100, 0);
697
                                write_ndigit_number_u(19, 6, (uint16_t) (((uint32_t) max_GroundSpeed * 36) / 1000), 100, 0);
645
                                write_char_xy(22, 6, 203); // km/h
698
                                write_char_xy(22, 6, 203); // km/h
646
                                                        write_ascii_string_pgm(2, 7, stats_item_pointers[2]); // max Distance
699
                                                        write_ascii_string_pgm(2, 7, stats_item_pointers[2]); // max Distance
647
                                write_ndigit_number_u(19, 7, max_Distance / 100, 100, 0);
700
                                write_ndigit_number_u(19, 7, max_Distance / 100, 100, 0);
648
                                write_char_xy(22, 7, 204); // small meters m
701
                                write_char_xy(22, 7, 204); // small meters m
649
                                                        write_ascii_string_pgm(2, 8, stats_item_pointers[3]); // min voltage
702
                                                        write_ascii_string_pgm(2, 8, stats_item_pointers[3]); // min voltage
650
                                                        write_ndigit_number_u_10th(18, 8, min_UBat, 100, 0);
703
                                                        write_ndigit_number_u_10th(18, 8, min_UBat, 100, 0);
651
                                write_ascii_string(22, 8, "V"); // voltage
704
                                write_ascii_string(22, 8, "V"); // voltage
652
                                                        write_ascii_string_pgm(2, 9, stats_item_pointers[4]); // max time
705
                                                        write_ascii_string_pgm(2, 9, stats_item_pointers[4]); // max time
653
                                write_time(16, 9, max_FlyingTime);
706
                                write_time(16, 9, max_FlyingTime);
654
                                write_char_xy(22, 9, 210); // fly clock
707
                                write_char_xy(22, 9, 210); // fly clock
655
                                                } else if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) { // if no stats there is space horizon
708
                                                } else if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) { // if no stats there is space horizon
656
                            draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll);
709
                            draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll);
657
                        }
710
                        }
658
                    }
711
                    }
659
 
712
 
660
                    // bottom line
713
                    // bottom line
661
                                        write_ndigit_number_u_10th(2, bottom_line, naviData.UBat, 100, 0);
714
                                        write_ndigit_number_u_10th(2, bottom_line, naviData.UBat, 100, 0);
662
                    if (naviData.UBat <= UBAT_WRN && last_UBat > UBAT_WRN) {
715
                    if (naviData.UBat <= UBAT_WRN && last_UBat > UBAT_WRN) {
663
                        for (uint8_t x = 0; x < 7; x++)
716
                        for (uint8_t x = 0; x < 7; x++)
664
                            write_char_att_xy(x, bottom_line, BLINK);
717
                            write_char_att_xy(x, bottom_line, BLINK);
665
                    } else {
718
                    } else {
666
                        for (uint8_t x = 0; x < 7; x++)
719
                        for (uint8_t x = 0; x < 7; x++)
667
                            write_char_att_xy(x, bottom_line, 0);
720
                            write_char_att_xy(x, bottom_line, 0);
668
                    }
721
                    }
-
 
722
                                        draw_battery(6, bottom_line, naviData.UBat);
669
 
723
 
670
                    write_time(8, bottom_line, uptime);
724
                    write_time(8, bottom_line, uptime);
671
                    write_time(16, bottom_line, naviData.FlyingTime);
725
                    write_time(16, bottom_line, naviData.FlyingTime);
672
 
726
 
673
                    write_ndigit_number_u(24, bottom_line, naviData.SatsInUse, 10, 0);
727
                    write_ndigit_number_u(24, bottom_line, naviData.SatsInUse, 10, 0);
674
 
728
 
675
                    if (naviData.NCFlags & NC_FLAG_CH) {
729
                    if (naviData.NCFlags & NC_FLAG_CH) {
676
                        write_char_xy(27, bottom_line, 231); // gps ch
730
                        write_char_xy(27, bottom_line, 231); // gps ch
677
                    } else if (naviData.NCFlags & NC_FLAG_PH) {
731
                    } else if (naviData.NCFlags & NC_FLAG_PH) {
678
                        write_char_xy(27, bottom_line, 230); // gps ph
732
                        write_char_xy(27, bottom_line, 230); // gps ph
679
                    } else { // (naviData.NCFlags & NC_FLAG_FREE)
733
                    } else { // (naviData.NCFlags & NC_FLAG_FREE)
680
                        write_char_xy(27, bottom_line, 201); // sat2 (free)
734
                        write_char_xy(27, bottom_line, 201); // sat2 (free)
681
                    }
735
                    }
682
 
736
 
683
                    //write_number_s(8, 5, RxDataLen);
737
                    //write_number_s(8, 5, RxDataLen);
684
                    //write_number_s(16, 5, setsReceived++);
738
                    //write_number_s(16, 5, setsReceived++);
685
 
739
 
686
                    // remember statistics
740
                    // remember statistics
687
                    if (naviData.Altimeter > max_Altimeter) max_Altimeter = naviData.Altimeter;
741
                    if (naviData.Altimeter > max_Altimeter) max_Altimeter = naviData.Altimeter;
688
                    if (naviData.GroundSpeed > max_GroundSpeed) max_GroundSpeed = naviData.GroundSpeed;
742
                    if (naviData.GroundSpeed > max_GroundSpeed) max_GroundSpeed = naviData.GroundSpeed;
689
                    if (naviData.HomePositionDeviation.Distance > max_Distance) {
743
                    if (naviData.HomePositionDeviation.Distance > max_Distance) {
690
                        max_Distance = naviData.HomePositionDeviation.Distance;
744
                        max_Distance = naviData.HomePositionDeviation.Distance;
691
                    }
745
                    }
692
                    if (naviData.UBat < min_UBat) min_UBat = naviData.UBat;
746
                    if (naviData.UBat < min_UBat) min_UBat = naviData.UBat;
693
                    if (naviData.FlyingTime > max_FlyingTime) max_FlyingTime = naviData.FlyingTime;
747
                    if (naviData.FlyingTime > max_FlyingTime) max_FlyingTime = naviData.FlyingTime;
694
 
748
 
695
                    old_MKFlags = naviData.MKFlags;
749
                    old_MKFlags = naviData.MKFlags;
696
                }
750
                }
697
            }
751
            }
698
            seconds_since_last_data = 0;
752
            seconds_since_last_data = 0;
699
            rxd_buffer_locked = 0;
753
            rxd_buffer_locked = 0;
700
        }
754
        }
701
        // handle keypress
755
        // handle keypress
702
        if (s1_pressed()) {
756
        if (s1_pressed()) {
703
            config_menu();
757
            config_menu();
704
        }
758
        }
705
        if (seconds_since_last_data > 2) {
759
        if (seconds_since_last_data > 2) {
706
                        // request OSD Data from NC every 100ms
760
                        // request OSD Data from NC every 100ms
707
                        usart1_request_mk_data(1, 'o', 100);
761
                        usart1_request_mk_data(1, 'o', 100);
708
                        seconds_since_last_data = 0;
762
                        seconds_since_last_data = 0;
709
        }
763
        }
710
    }
764
    }
711
#endif
765
#endif
712
    return 0;
766
    return 0;
713
}
767
}
714
 
768