Subversion Repositories Projects

Rev

Rev 346 | Rev 355 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 346 Rev 349
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
 * draw a compass rose at <x>/<y> for <heading>
166
 * draw a compass rose at <x>/<y> for <heading>
167
 */
167
 */
168
void draw_compass(uint8_t x, uint8_t y, uint16_t heading) {
168
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";
169
    //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,
170
    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,
171
                    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,
172
                    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};
173
                    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
174
        // 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
175
        // 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
176
        // and *10 / 225 would take ages... so we take the uncorrect way
177
    uint8_t front = 19 + (heading / 22);
177
    uint8_t front = 19 + (heading / 22);
178
    for (uint8_t i = 0; i < 9; i++) {
178
    for (uint8_t i = 0; i < 9; i++) {
179
                write_char_xy(x++, y, rose[front - 4 + i]);
179
                write_char_xy(x++, y, rose[front - 4 + i]);
180
    }
180
    }
181
}
181
}
182
 
182
 
183
/* ##########################################################################
183
/* ##########################################################################
184
 * artificial horizon
184
 * artificial horizon
185
 * ##########################################################################*/
185
 * ##########################################################################*/
186
// remember last time displayed values
186
// remember last time displayed values
187
int8_t old_af_x = -1, old_af_y = -1;
187
int8_t old_af_x = -1, old_af_y = -1;
188
 
188
 
189
/**
189
/**
190
 * draw roll und nick indicators (could be enhanced to full artificial horizon)
190
 * draw roll und nick indicators (could be enhanced to full artificial horizon)
191
 * from line <firstline> to <listlines> for given <nick> and <roll> values
191
 * from line <firstline> to <listlines> for given <nick> and <roll> values
192
 */
192
 */
193
void draw_artificial_horizon(uint8_t firstline, uint8_t lastline, int16_t nick, int16_t roll) {
193
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};
194
        char noodle[5] = {225, 225, 226, 227, 227};
195
        uint8_t center_x = 15;
195
        uint8_t center_x = 15;
196
        uint8_t center_y = lastline - firstline;
196
        uint8_t center_y = lastline - firstline;
197
        center_y = 7;
197
        center_y = 7;
198
        write_char_xy(center_x,center_y,228);
198
        write_char_xy(center_x,center_y,228);
199
        uint8_t cpos, nicky, rollx;
199
        uint8_t cpos, nicky, rollx;
200
       
200
       
201
        // which line
201
        // which line
202
        int8_t ypos =  nick / 20;
202
        int8_t ypos =  nick / 20;
203
        // which character from the array?
203
        // which character from the array?
204
        if (nick < 0) {
204
        if (nick < 0) {
205
                cpos = -1*((nick - (ypos * 20))/4);
205
                cpos = -1*((nick - (ypos * 20))/4);
206
                ypos--;
206
                ypos--;
207
        } else cpos = 4-((nick - (ypos * 20))/4);
207
        } else cpos = 4-((nick - (ypos * 20))/4);
208
        if (cpos > 4) cpos = 4;
208
        if (cpos > 4) cpos = 4;
209
 
209
 
210
        nicky = center_y - ypos;
210
        nicky = center_y - ypos;
211
        if (nicky > lastline) nicky = lastline;
211
        if (nicky > lastline) nicky = lastline;
212
        else if (nicky < firstline) nicky = firstline;
212
        else if (nicky < firstline) nicky = firstline;
213
 
213
 
214
        // ensure roll-borders
214
        // ensure roll-borders
215
        rollx = (roll / 8)+15;
215
        rollx = (roll / 8)+15;
216
        if (rollx < 2) rollx = 2;
216
        if (rollx < 2) rollx = 2;
217
        else if (rollx > 28) rollx = 28;
217
        else if (rollx > 28) rollx = 28;
218
 
218
 
219
 
219
 
220
        // clear roll
220
        // clear roll
221
        if (old_af_x != rollx && old_af_x >= 0) {
221
        if (old_af_x != rollx && old_af_x >= 0) {
222
                write_char_xy(old_af_x,13,0);
222
                write_char_xy(old_af_x,13,0);
223
        }
223
        }
224
 
224
 
225
        // clear nick
225
        // clear nick
226
        if (old_af_y != nicky && old_af_y >= 0) {
226
        if (old_af_y != nicky && old_af_y >= 0) {
227
                write_char_xy(center_x-1,old_af_y,0);
227
                write_char_xy(center_x-1,old_af_y,0);
228
                write_char_xy(center_x+1,old_af_y,0);
228
                write_char_xy(center_x+1,old_af_y,0);
229
        }
229
        }
230
 
230
 
231
 
231
 
232
        // draw nick
232
        // draw nick
233
        write_char_xy(center_x-1,nicky,noodle[cpos]);
233
        write_char_xy(center_x-1,nicky,noodle[cpos]);
234
        write_char_xy(center_x+1,nicky,noodle[cpos]);
234
        write_char_xy(center_x+1,nicky,noodle[cpos]);
235
 
235
 
236
        // draw roll
236
        // draw roll
237
        write_char_xy(rollx,lastline,229);
237
        write_char_xy(rollx,lastline,229);
238
 
238
 
239
        // update old vars
239
        // update old vars
240
        old_af_x = rollx;
240
        old_af_x = rollx;
241
        old_af_y = nicky;
241
        old_af_y = nicky;
242
 
242
 
243
        // debug numbers
243
        // debug numbers
244
        //write_3digit_number_u(20,6,cpos);
244
        //write_3digit_number_u(20,6,cpos);
245
        //write_number_s(20,7,ypos);    
245
        //write_number_s(20,7,ypos);    
246
        //write_number_s(0,7,nick);             
246
        //write_number_s(0,7,nick);             
247
        //write_number_s(18,11,roll);   
247
        //write_number_s(18,11,roll);   
248
}
248
}
249
 
249
 
250
/* ##########################################################################
250
/* ##########################################################################
251
 * A simple config menu for the flags
251
 * A simple config menu for the flags
252
 * ##########################################################################*/
252
 * ##########################################################################*/
253
 
253
 
254
/**
254
/**
255
 * helper function for menu updating
255
 * helper function for menu updating
256
 */
256
 */
257
void config_menu_drawings(uint8_t chosen) {
257
void config_menu_drawings(uint8_t chosen) {
258
    // clear prevoius _cursor_
258
    // clear prevoius _cursor_
259
    write_ascii_string(3, (chosen + 6) % 7, " ");
259
    write_ascii_string(3, (chosen + 6) % 7, " ");
260
    // draw current _cursor_
260
    // draw current _cursor_
261
    write_ascii_string(3, chosen + 6, ">");
261
    write_ascii_string(3, chosen + 6, ">");
262
    if (COSD_FLAGS & COSD_FLAG_HUD) {
262
    if (COSD_FLAGS & COSD_FLAG_HUD) {
263
        write_ascii_string_pgm(23, 6, ON);
263
        write_ascii_string_pgm(23, 6, ON);
264
    } else {
264
    } else {
265
                write_ascii_string_pgm(23, 6, OFF);
265
                write_ascii_string_pgm(23, 6, OFF);
266
    }
266
    }
267
    if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) {
267
    if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) {
268
        write_ascii_string_pgm(23, 7, ON);
268
        write_ascii_string_pgm(23, 7, ON);
269
    } else {
269
    } else {
270
        write_ascii_string_pgm(23, 7, OFF);
270
        write_ascii_string_pgm(23, 7, OFF);
271
    }
271
    }
272
        if (COSD_FLAGS & COSD_FLAG_STATS) {
272
        if (COSD_FLAGS & COSD_FLAG_STATS) {
273
        write_ascii_string_pgm(23, 8, ON);
273
        write_ascii_string_pgm(23, 8, ON);
274
    } else {
274
    } else {
275
        write_ascii_string_pgm(23, 8, OFF);
275
        write_ascii_string_pgm(23, 8, OFF);
276
    }
276
    }
277
    if (COSD_FLAGS & COSD_FLAG_WARNINGS) {
277
    if (COSD_FLAGS & COSD_FLAG_WARNINGS) {
278
        write_ascii_string_pgm(23, 9, ON);
278
        write_ascii_string_pgm(23, 9, ON);
279
    } else {
279
    } else {
280
        write_ascii_string_pgm(23, 9, OFF);
280
        write_ascii_string_pgm(23, 9, OFF);
281
    }
281
    }
282
}
282
}
283
 
283
 
284
/**
284
/**
285
 * some sort of clicking response in the menu
285
 * some sort of clicking response in the menu
286
 */
286
 */
287
void config_menu_doclick(uint8_t chosen, char** menu) {
287
void config_menu_doclick(uint8_t chosen, char** menu) {
288
        write_ascii_string(4, chosen + 6, "DONE              ");
288
        write_ascii_string(4, chosen + 6, "DONE              ");
289
        _delay_ms(1000);
289
        _delay_ms(1000);
290
        write_ascii_string(4, chosen + 6, menu[chosen]);
290
        write_ascii_string(4, chosen + 6, menu[chosen]);
291
}
291
}
292
 
292
 
293
/**
293
/**
294
 * a simple config menu tryout
294
 * a simple config menu tryout
295
 */
295
 */
296
void config_menu(void) {
296
void config_menu(void) {
297
        // disable interrupts (makes the menu more smoothely)
297
        // disable interrupts (makes the menu more smoothely)
298
        cli();
298
        cli();
299
 
299
 
300
        // clear screen
300
        // clear screen
301
        clear();
301
        clear();
302
       
302
       
303
        char* menu[8] = {"Full HUD",
303
        char* menu[8] = {"Full HUD",
304
                                         "Art.Horizon in HUD",
304
                                         "Art.Horizon in HUD",
305
                                         "Statistics",
305
                                         "Statistics",
306
                                         "Warnings",    // TODO: do it!
306
                                         "Warnings",    // TODO: do it!
307
                                         "Reset uptime",
307
                                         "Reset uptime",
308
                                         "Request OSD-data",
308
                                         "Request OSD-data",
309
                                         "Disable Debug-data",
309
                                         "Disable Debug-data",
310
                                         "EXIT"};
310
                                         "EXIT"};
311
 
311
 
312
        uint8_t inmenu = 1;
312
        uint8_t inmenu = 1;
313
        uint8_t chosen = 0;
313
        uint8_t chosen = 0;
314
        write_ascii_string(6,  2, "C-OSD Config Menu");
314
        write_ascii_string(6,  2, "C-OSD Config Menu");
315
 
315
 
316
        // wait a bit before doing stuff so user has chance to release button
316
        // wait a bit before doing stuff so user has chance to release button
317
        _delay_ms(250);
317
        _delay_ms(250);
318
 
318
 
319
        write_ascii_string(4,  6, menu[0]);
319
        write_ascii_string(4,  6, menu[0]);
320
        write_ascii_string(4,  7, menu[1]);
320
        write_ascii_string(4,  7, menu[1]);
321
        write_ascii_string(4,  8, menu[2]);
321
        write_ascii_string(4,  8, menu[2]);
322
        write_ascii_string(4,  9, menu[3]);
322
        write_ascii_string(4,  9, menu[3]);
323
        write_ascii_string(4, 10, menu[4]);
323
        write_ascii_string(4, 10, menu[4]);
324
        write_ascii_string(4, 11, menu[5]);
324
        write_ascii_string(4, 11, menu[5]);
325
        write_ascii_string(4, 12, menu[6]);
325
        write_ascii_string(4, 12, menu[6]);
326
        write_ascii_string(4, 13, menu[7]);
326
        write_ascii_string(4, 13, menu[7]);
327
 
327
 
328
        config_menu_drawings(chosen);
328
        config_menu_drawings(chosen);
329
 
329
 
330
        while (inmenu) {
330
        while (inmenu) {
331
                        if (s2_pressed()) {
331
                        if (s2_pressed()) {
332
                                write_ascii_string(3,  chosen+6, " ");
332
                                write_ascii_string(3,  chosen+6, " ");
333
                                chosen = (chosen + 1) % 8;
333
                                chosen = (chosen + 1) % 8;
334
                                write_ascii_string(3,  chosen+6, ">");
334
                                write_ascii_string(3,  chosen+6, ">");
335
                                _delay_ms(500);
335
                                _delay_ms(500);
336
                        } else if (s1_pressed()) {
336
                        } else if (s1_pressed()) {
337
                                switch (chosen) {
337
                                switch (chosen) {
338
                                        case 0:         // full HUD
338
                                        case 0:         // full HUD
339
                                                COSD_FLAGS ^= COSD_FLAG_HUD;
339
                                                COSD_FLAGS ^= COSD_FLAG_HUD;
340
                                                config_menu_drawings(chosen);
340
                                                config_menu_drawings(chosen);
341
                                                break;
341
                                                break;
342
                                        case 1:         // art horizon
342
                                        case 1:         // art horizon
343
                                                COSD_FLAGS ^= COSD_FLAG_ARTHORIZON;
343
                                                COSD_FLAGS ^= COSD_FLAG_ARTHORIZON;
344
                                                config_menu_drawings(chosen);
344
                                                config_menu_drawings(chosen);
345
                                                break;
345
                                                break;
346
                                        case 2:         // statistics
346
                                        case 2:         // statistics
347
                                                COSD_FLAGS ^= COSD_FLAG_STATS;
347
                                                COSD_FLAGS ^= COSD_FLAG_STATS;
348
                                                config_menu_drawings(chosen);
348
                                                config_menu_drawings(chosen);
349
                                                break;
349
                                                break;
350
                                        case 3:         // warnings
350
                                        case 3:         // warnings
351
                                                COSD_FLAGS ^= COSD_FLAG_WARNINGS;
351
                                                COSD_FLAGS ^= COSD_FLAG_WARNINGS;
352
                                                config_menu_drawings(chosen);
352
                                                config_menu_drawings(chosen);
353
                                                break;
353
                                                break;
354
                                        case 4:         // reset uptime
354
                                        case 4:         // reset uptime
355
                                                uptime = 0;
355
                                                uptime = 0;
356
                                                config_menu_doclick(chosen, menu);
356
                                                config_menu_doclick(chosen, menu);
357
                                                break;
357
                                                break;
358
                                        case 5:         // re-request OSD data
358
                                        case 5:         // re-request OSD data
359
                                                // request OSD Data from NC every 100ms
359
                                                // request OSD Data from NC every 100ms
360
                                                usart1_request_mk_data(1, 'o', 100);
360
                                                usart1_request_mk_data(1, 'o', 100);
361
                                                config_menu_doclick(chosen, menu);
361
                                                config_menu_doclick(chosen, menu);
362
                                                break;
362
                                                break;
363
                                        case 6:         // disable debug data
363
                                        case 6:         // disable debug data
364
                                                // disable sending of debug data
364
                                                // disable sending of debug data
365
                                                // may result in smoother ddata display
365
                                                // may result in smoother ddata display
366
                                                usart1_request_mk_data(0, 'd', 0);
366
                                                usart1_request_mk_data(0, 'd', 0);
367
                                                config_menu_doclick(chosen, menu);
367
                                                config_menu_doclick(chosen, menu);
368
                                                break;
368
                                                break;
369
                                        case 7:         // exit
369
                                        case 7:         // exit
370
                                                inmenu = 0;
370
                                                inmenu = 0;
371
                                                break;
371
                                                break;
372
                                }
372
                                }
373
                                _delay_ms(250);
373
                                _delay_ms(250);
374
                        }
374
                        }
375
        }
375
        }
376
 
376
 
377
        // clear screen up again
377
        // clear screen up again
378
        clear();
378
        clear();
379
 
379
 
380
        // update flags to paint display again if needed
380
        // update flags to paint display again if needed
381
        COSD_FLAGS &= ~COSD_ICONS_WRITTEN;
381
        COSD_FLAGS &= ~COSD_ICONS_WRITTEN;
382
 
382
 
383
        // enable interrupts again
383
        // enable interrupts again
384
        sei();
384
        sei();
385
}
385
}
386
 
386
 
387
#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))
387
#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))
388
/* ##########################################################################
388
/* ##########################################################################
389
 * MAIN
389
 * MAIN
390
 * ##########################################################################*/
390
 * ##########################################################################*/
391
int main(void) {
391
int main(void) {
392
    // set up FLAGS, compiler should flatten this one
392
    // set up FLAGS, compiler should flatten this one
393
    COSD_FLAGS = (NTSC << 0);
393
    COSD_FLAGS = (NTSC << 0);
394
    COSD_FLAGS |= (HUD << 1);
394
    COSD_FLAGS |= (HUD << 1);
395
    COSD_FLAGS |= (ARTHORIZON << 2);
395
    COSD_FLAGS |= (ARTHORIZON << 2);
396
        COSD_FLAGS |= (STATS << 3);
396
        COSD_FLAGS |= (STATS << 3);
397
    COSD_FLAGS |= (WARNINGS << 4);
397
    COSD_FLAGS |= (WARNINGS << 4);
398
 
398
 
399
    // set up Atmega162 Ports
399
    // set up Atmega162 Ports
400
    DDRA |= (1 << PA1); // PA1 output (/CS)
400
    DDRA |= (1 << PA1); // PA1 output (/CS)
401
    MAX_CS_HIGH
401
    MAX_CS_HIGH
402
    DDRA |= (1 << PA2); // PA2 output (SDIN)
402
    DDRA |= (1 << PA2); // PA2 output (SDIN)
403
    MAX_SDIN_LOW
403
    MAX_SDIN_LOW
404
    DDRA |= (1 << PA3); // PA3 output (SCLK)
404
    DDRA |= (1 << PA3); // PA3 output (SCLK)
405
    MAX_SCLK_LOW
405
    MAX_SCLK_LOW
406
    DDRA |= (1 << PA5); // PA5 output (RESET)
406
    DDRA |= (1 << PA5); // PA5 output (RESET)
407
    MAX_RESET_HIGH
407
    MAX_RESET_HIGH
408
 
408
 
409
    DDRC |= (1 << PC0); // PC0 output (LED1 gn)
409
    DDRC |= (1 << PC0); // PC0 output (LED1 gn)
410
    LED1_OFF
410
    LED1_OFF
411
    DDRC |= (1 << PC1); // PC1 output (LED2 rt)
411
    DDRC |= (1 << PC1); // PC1 output (LED2 rt)
412
    LED2_OFF
412
    LED2_OFF
413
    DDRC |= (1 << PC2); // PC2 output (LED3 gn)
413
    DDRC |= (1 << PC2); // PC2 output (LED3 gn)
414
    LED3_OFF
414
    LED3_OFF
415
    DDRC |= (1 << PC3); // PC3 output (LED4 rt)
415
    DDRC |= (1 << PC3); // PC3 output (LED4 rt)
416
    LED4_OFF
416
    LED4_OFF
417
 
417
 
418
    DDRC &= ~(1 << PC4); // PC4 input  (MODE)
418
    DDRC &= ~(1 << PC4); // PC4 input  (MODE)
419
    PORTC |= (1 << PC4); // pullup
419
    PORTC |= (1 << PC4); // pullup
420
    DDRC &= ~(1 << PC5); // PC5 input  (SET)
420
    DDRC &= ~(1 << PC5); // PC5 input  (SET)
421
    PORTC |= (1 << PC5); // pullup
421
    PORTC |= (1 << PC5); // pullup
422
 
422
 
423
    // set up top and bottom lines
423
    // set up top and bottom lines
424
    if (COSD_FLAGS & COSD_FLAG_NTSC) {
424
    if (COSD_FLAGS & COSD_FLAG_NTSC) {
425
        bottom_line = 12;
425
        bottom_line = 12;
426
    } else {
426
    } else {
427
        bottom_line = 14;
427
        bottom_line = 14;
428
    }
428
    }
429
 
429
 
430
    // reset the MAX7456 to be sure any undefined states do no harm
430
    // reset the MAX7456 to be sure any undefined states do no harm
431
    MAX_RESET_LOW
431
    MAX_RESET_LOW
432
    MAX_RESET_HIGH
432
    MAX_RESET_HIGH
433
 
433
 
434
    // give the FC/NC and the maxim time to come up
434
    // give the FC/NC and the maxim time to come up
435
    LED4_ON
435
    LED4_ON
436
    _delay_ms(2000);
436
    _delay_ms(2000);
437
 
437
 
438
    LED4_OFF
438
    LED4_OFF
439
 
439
 
440
 
440
 
441
    //Pushing NEW chars to the MAX7456
441
    //Pushing NEW chars to the MAX7456
442
#if (WRITECHARS != -1)
442
#if (WRITECHARS != -1)
443
    // DISABLE display (VM0)
443
    // DISABLE display (VM0)
444
    spi_send_byte(0x00, 0b00000000);
444
    spi_send_byte(0x00, 0b00000000);
445
#include "characters.c"
445
#include "characters.c"
446
 
446
 
447
#endif 
447
#endif 
448
 
448
 
449
    // Setup Video Mode
449
    // Setup Video Mode
450
    if (COSD_FLAGS & COSD_FLAG_NTSC) {
450
    if (COSD_FLAGS & COSD_FLAG_NTSC) {
451
        // NTSC + enable display immediately (VM0)
451
        // NTSC + enable display immediately (VM0)
452
        spi_send_byte(0x00, 0b00001000);
452
        spi_send_byte(0x00, 0b00001000);
453
    } else {
453
    } else {
454
        // PAL + enable display immediately (VM0)
454
        // PAL + enable display immediately (VM0)
455
        spi_send_byte(0x00, 0b01001000);
455
        spi_send_byte(0x00, 0b01001000);
456
    }
456
    }
457
 
457
 
458
    // clear all display-mem (DMM)
458
    // clear all display-mem (DMM)
459
    spi_send_byte(0x04, 0b00000100);
459
    spi_send_byte(0x04, 0b00000100);
460
 
460
 
461
    // clearing takes 12uS according to maxim so lets wait longer
461
    // clearing takes 12uS according to maxim so lets wait longer
462
    _delay_us(120);
462
    _delay_us(120);
463
 
463
 
464
    // 8bit mode
464
    // 8bit mode
465
    spi_send_byte(0x04, 0b01000000);
465
    spi_send_byte(0x04, 0b01000000);
466
 
466
 
467
    // write blank chars to whole screen
467
    // write blank chars to whole screen
468
    clear();
468
    clear();
469
 
469
 
470
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
470
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
471
    // init usart
471
    // init usart
472
    usart1_init();
472
    usart1_init();
473
 
473
 
474
    // set up timer
474
    // set up timer
475
    TCCR0 |= (1 << CS00) | (1 << CS01); // timer0 prescaler 64
475
    TCCR0 |= (1 << CS00) | (1 << CS01); // timer0 prescaler 64
476
    OCR0 = 6; // preload
476
    OCR0 = 6; // preload
477
    TIMSK |= (1 << TOIE0); // enable overflow timer0
477
    TIMSK |= (1 << TOIE0); // enable overflow timer0
478
 
478
 
479
    // enable interrupts
479
    // enable interrupts
480
    sei();
480
    sei();
481
#endif
481
#endif
482
 
482
 
483
    //write_ascii_string(2,  7, "         CaScAdE          ");
483
    //write_ascii_string(2,  7, "         CaScAdE          ");
484
    //write_ascii_string(2,  8, "is TESTING his open source");
484
    //write_ascii_string(2,  8, "is TESTING his open source");
485
    //write_ascii_string(2,  9, "    EPi OSD Firmware");
485
    //write_ascii_string(2,  9, "    EPi OSD Firmware");
486
 
486
 
487
    // custom char preview
487
    // custom char preview
488
    /*write_char_xy( 2, 7, 200);
488
    /*write_char_xy( 2, 7, 200);
489
    write_char_xy( 3, 7, 201);
489
    write_char_xy( 3, 7, 201);
490
    write_char_xy( 4, 7, 202);
490
    write_char_xy( 4, 7, 202);
491
    write_char_xy( 5, 7, 203);
491
    write_char_xy( 5, 7, 203);
492
    write_char_xy( 6, 7, 204);
492
    write_char_xy( 6, 7, 204);
493
    write_char_xy( 7, 7, 205);
493
    write_char_xy( 7, 7, 205);
494
    write_char_xy( 8, 7, 206);
494
    write_char_xy( 8, 7, 206);
495
    write_char_xy( 9, 7, 207);
495
    write_char_xy( 9, 7, 207);
496
    write_char_xy(10, 7, 208);
496
    write_char_xy(10, 7, 208);
497
    write_char_xy(11, 7, 209);
497
    write_char_xy(11, 7, 209);
498
    write_char_xy(12, 7, 210);
498
    write_char_xy(12, 7, 210);
499
    write_char_xy(13, 7, 211);
499
    write_char_xy(13, 7, 211);
500
    write_char_xy(14, 7, 212);
500
    write_char_xy(14, 7, 212);
501
    write_char_xy(15, 7, 213);
501
    write_char_xy(15, 7, 213);
502
    write_char_xy(16, 7, 214);
502
    write_char_xy(16, 7, 214);
503
    write_char_xy(17, 7, 215);*/
503
    write_char_xy(17, 7, 215);*/
504
 
504
 
505
    // we are ready
505
    // we are ready
506
    LED3_ON
506
    LED3_ON
507
 
507
 
508
 
508
 
509
 
509
 
510
#if ALLCHARSDEBUG | (WRITECHARS != -1)
510
#if ALLCHARSDEBUG | (WRITECHARS != -1)
511
        clear();
511
        clear();
512
    write_all_chars();
512
    write_all_chars();
513
#else
513
#else
514
        // clear serial screen
514
        // clear serial screen
515
        //usart1_puts("\x1B[2J\x1B[H");
515
        //usart1_puts("\x1B[2J\x1B[H");
516
        //usart1_puts("hello world!\r\n");
516
        //usart1_puts("hello world!\r\n");
517
 
517
 
518
 
518
 
519
        // request data ever 100ms from FC;
519
        // request data ever 100ms from FC;
520
        //usart1_request_mk_data(0, 'd', 100);
520
        //usart1_request_mk_data(0, 'd', 100);
521
 
521
 
522
        // request OSD Data from NC every 100ms
522
        // request OSD Data from NC every 100ms
523
        usart1_request_mk_data(1, 'o', 100);
523
        usart1_request_mk_data(1, 'o', 100);
524
 
524
 
525
    // and disable debug...
525
    // and disable debug...
526
        //usart1_request_mk_data(0, 'd', 0);
526
        //usart1_request_mk_data(0, 'd', 0);
527
 
527
 
528
    // disable TXD-pin
528
    // disable TXD-pin
529
    usart1_DisableTXD();
529
    usart1_DisableTXD();
530
 
530
 
531
    // stats for after flight
531
    // stats for after flight
532
    int16_t max_Altimeter = 0;
532
    int16_t max_Altimeter = 0;
533
    uint16_t max_GroundSpeed = 0;
533
    uint16_t max_GroundSpeed = 0;
534
    int16_t max_Distance = 0;
534
    int16_t max_Distance = 0;
535
    uint8_t min_UBat = 255;
535
    uint8_t min_UBat = 255;
536
    uint16_t max_FlyingTime = 0;
536
    uint16_t max_FlyingTime = 0;
537
 
537
 
538
    // flags from last round to check for changes
538
    // flags from last round to check for changes
539
    uint8_t old_MKFlags = 0;
539
    uint8_t old_MKFlags = 0;
540
 
540
 
541
    char* directions[8] = {"NE", "E ", "SE", "S ", "SW", "W ", "NW", "N "};
541
    char* directions[8] = {"NE", "E ", "SE", "S ", "SW", "W ", "NW", "N "};
542
    char arrowdir[8] = {218, 217, 224, 223, 222, 221, 220, 219};
542
    char arrowdir[8] = {218, 217, 224, 223, 222, 221, 220, 219};
-
 
543
 
-
 
544
        /*write_ndigit_number_s_10th(5, 10, 1, 100, 0);
-
 
545
        write_ndigit_number_s_10th(5, 11, -1, 100, 0);
-
 
546
        write_ndigit_number_s_10th(5, 12, -11, 100, 0);*/
543
 
547
 
544
    while (1) {
548
    while (1) {
545
        // write icons at init or after menu/mode-switch
549
        // write icons at init or after menu/mode-switch
546
        if (!(COSD_FLAGS & COSD_ICONS_WRITTEN) && (COSD_FLAGS & COSD_FLAG_HUD)) {
550
        if (!(COSD_FLAGS & COSD_ICONS_WRITTEN) && (COSD_FLAGS & COSD_FLAG_HUD)) {
547
            write_char_xy(5, top_line, 203); // km/h
551
            write_char_xy(5, top_line, 203); // km/h
548
            write_char_xy(10, top_line, 202); // RC-transmitter
552
            write_char_xy(10, top_line, 202); // RC-transmitter
549
            write_char_xy(16, top_line, 208); // degree symbol
553
            write_char_xy(16, top_line, 208); // degree symbol
550
            write_char_xy(27, top_line, 204); // small meters m
554
            write_char_xy(27, top_line, 204); // small meters m
551
            write_ascii_string(6, bottom_line, "V"); // voltage
555
            write_ascii_string(6, bottom_line, "V"); // voltage
552
            write_char_xy(14, bottom_line, 209); // on clock
556
            write_char_xy(14, bottom_line, 209); // on clock
553
            write_char_xy(22, bottom_line, 210); // fly clock
557
            write_char_xy(22, bottom_line, 210); // fly clock
554
            write_char_xy(26, bottom_line, 200); // sat1
558
            write_char_xy(26, bottom_line, 200); // sat1
555
            write_char_xy(27, bottom_line, 201); // sat2
559
            write_char_xy(27, bottom_line, 201); // sat2
556
            COSD_FLAGS |= COSD_ICONS_WRITTEN;
560
            COSD_FLAGS |= COSD_ICONS_WRITTEN;
557
        }
561
        }
558
        if (rxd_buffer_locked) {
562
        if (rxd_buffer_locked) {
559
            if (COSD_FLAGS & COSD_FLAG_HUD) {
563
            if (COSD_FLAGS & COSD_FLAG_HUD) {
560
                if (rxd_buffer[2] == 'D') { // FC Data
564
                if (rxd_buffer[2] == 'D') { // FC Data
561
                    /*Decode64();
565
                    /*Decode64();
562
                    debugData = *((DebugOut_t*) pRxData);
566
                    debugData = *((DebugOut_t*) pRxData);
563
                    write_number_s(12, 2, RxDataLen);
567
                    write_number_s(12, 2, RxDataLen);
564
                    write_number_s(20, 2, setsReceived++);
568
                    write_number_s(20, 2, setsReceived++);
565
                    write_number_s(12, 3, debugData.Analog[0]); // AngleNick
569
                    write_number_s(12, 3, debugData.Analog[0]); // AngleNick
566
                    write_number_s(12, 4, debugData.Analog[1]); // AngleRoll
570
                    write_number_s(12, 4, debugData.Analog[1]); // AngleRoll
567
                                        write_number_s(12, 5, debugData.Analog[5]); // Height
571
                                        write_number_s(12, 5, debugData.Analog[5]); // Height
568
                    write_number_s(12, 6, debugData.Analog[9]); // Voltage
572
                    write_number_s(12, 6, debugData.Analog[9]); // Voltage
569
                    write_number_s(12, 7, debugData.Analog[10]);// RC Signal
573
                    write_number_s(12, 7, debugData.Analog[10]);// RC Signal
570
                                        write_number_s(12, 8, debugData.Analog[11]);// Gyro compass*/
574
                                        write_number_s(12, 8, debugData.Analog[11]);// Gyro compass*/
571
                } else if (rxd_buffer[2] == 'O') { // NC OSD Data
575
                } else if (rxd_buffer[2] == 'O') { // NC OSD Data
572
                    Decode64();
576
                    Decode64();
573
                    naviData = *((NaviData_t*) pRxData);
577
                    naviData = *((NaviData_t*) pRxData);
574
 
578
 
575
                    // first line
579
                    // first line
576
                    write_3digit_number_u(2, top_line, (uint16_t) (((uint32_t) naviData.GroundSpeed * 36) / 1000));
580
                    write_ndigit_number_u(2, top_line, (uint16_t) (((uint32_t) naviData.GroundSpeed * 36) / 1000), 100, 0);
577
 
581
 
578
                    write_3digit_number_u(7, top_line, naviData.RC_Quality);
582
                    write_ndigit_number_u(7, top_line, naviData.RC_Quality, 100, 0);
579
                    if (naviData.RC_Quality <= RCLVL_WRN && last_RC_Quality > RCLVL_WRN) {
583
                    if (naviData.RC_Quality <= RCLVL_WRN && last_RC_Quality > RCLVL_WRN) {
580
                        for (uint8_t x = 0; x < 4; x++)
584
                        for (uint8_t x = 0; x < 4; x++)
581
                            write_char_att_xy(7 + x, top_line, BLINK);
585
                            write_char_att_xy(7 + x, top_line, BLINK);
582
                    } else if (naviData.RC_Quality > RCLVL_WRN && last_RC_Quality <= RCLVL_WRN) {
586
                    } else if (naviData.RC_Quality > RCLVL_WRN && last_RC_Quality <= RCLVL_WRN) {
583
                        for (uint8_t x = 0; x < 4; x++)
587
                        for (uint8_t x = 0; x < 4; x++)
584
                            write_char_att_xy(7 + x, top_line, 0);
588
                            write_char_att_xy(7 + x, top_line, 0);
585
                    }
589
                    }
586
                    last_RC_Quality = naviData.RC_Quality;
590
                    last_RC_Quality = naviData.RC_Quality;
587
 
591
 
588
                    write_3digit_number_u(13, top_line, naviData.CompassHeading);
592
                    write_ndigit_number_u(13, top_line, naviData.CompassHeading, 100, 0);
589
 
593
 
590
                    write_ascii_string(17, top_line, directions[heading_conv(naviData.CompassHeading)]);
594
                    write_ascii_string(17, top_line, directions[heading_conv(naviData.CompassHeading)]);
591
 
595
 
592
                    if (naviData.Variometer == 0) {
596
                    if (naviData.Variometer == 0) {
593
                        write_char_xy(20, top_line, 206); // plain line
597
                        write_char_xy(20, top_line, 206); // plain line
594
                    } else if (naviData.Variometer > 0 && naviData.Variometer <= 10) {
598
                    } else if (naviData.Variometer > 0 && naviData.Variometer <= 10) {
595
                        write_char_xy(20, top_line, 234); // small arrow up
599
                        write_char_xy(20, top_line, 234); // small arrow up
596
                    } else if (naviData.Variometer > 10) {
600
                    } else if (naviData.Variometer > 10) {
597
                        write_char_xy(20, top_line, 235); // big arrow up
601
                        write_char_xy(20, top_line, 235); // big arrow up
598
                    } else if (naviData.Variometer < 0 && naviData.Variometer >= -10) {
602
                    } else if (naviData.Variometer < 0 && naviData.Variometer >= -10) {
599
                        write_char_xy(20, top_line, 232); // small arrow down
603
                        write_char_xy(20, top_line, 232); // small arrow down
600
                    } else {
604
                    } else {
601
                        write_char_xy(20, top_line, 233); //big arrow down
605
                        write_char_xy(20, top_line, 233); //big arrow down
602
                    }
606
                    }
603
 
607
 
604
                    //note:lephisto:according to several sources it's /30
608
                    //note:lephisto:according to several sources it's /30
605
                    if (naviData.Altimeter > 300) {
609
                    if (naviData.Altimeter > 300 || naviData.Altimeter < -300) {
606
                        // above 10m only write full meters
610
                        // above 10m only write full meters
607
                        write_number_s(22, top_line, naviData.Altimeter / 30);
611
                        write_ndigit_number_s(23, top_line, naviData.Altimeter / 30, 1000, 0);
608
                    } else {
612
                    } else {
609
                        // up to 10m write meters.dm
613
                        // up to 10m write meters.dm
610
                        write_number_u_10th(21, top_line, naviData.Altimeter / 3);
614
                        //write_number_u_10th(21, top_line, naviData.Altimeter / 3);
-
 
615
                                                write_ndigit_number_s_10th(23, top_line, naviData.Altimeter / 3, 100, 0);
611
                    }
616
                    }
612
 
617
 
613
                    // seccond line
618
                    // seccond line
614
                    draw_compass(11, top_line + 1, naviData.CompassHeading);
619
                    draw_compass(11, top_line + 1, naviData.CompassHeading);
615
 
620
 
616
                    // TODO: verify correctness
621
                    // TODO: verify correctness
617
                    uint16_t heading_home = (naviData.HomePositionDeviation.Bearing + 360 - naviData.CompassHeading) % 360;
622
                    uint16_t heading_home = (naviData.HomePositionDeviation.Bearing + 360 - naviData.CompassHeading) % 360;
618
                    write_char_xy(27, top_line + 1, arrowdir[heading_conv(heading_home)]);
623
                    write_char_xy(27, top_line + 1, arrowdir[heading_conv(heading_home)]);
619
 
624
 
620
                    write_number_s(22, top_line + 1, naviData.HomePositionDeviation.Distance / 100);
625
                    write_ndigit_number_u(24, top_line + 1, naviData.HomePositionDeviation.Distance / 100, 100, 0);
621
 
626
 
622
                    // center
627
                    // center
623
                    if (naviData.MKFlags & FLAG_MOTOR_RUN) { // should be engines running
628
                    if (naviData.MKFlags & FLAG_MOTOR_RUN) { // should be engines running
624
                        if (!(old_MKFlags & FLAG_MOTOR_RUN)) { // motors just started, clear middle
629
                        if (!(old_MKFlags & FLAG_MOTOR_RUN)) { // motors just started, clear middle
625
                            clear();
630
                            clear();
626
                            // update flags to paint display again if needed
631
                            // update flags to paint display again if needed
627
                            COSD_FLAGS &= ~COSD_ICONS_WRITTEN;
632
                            COSD_FLAGS &= ~COSD_ICONS_WRITTEN;
628
                        }
633
                        }
629
                        if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) {
634
                        if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) {
630
                            draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll);
635
                            draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll);
631
                        }
636
                        }
632
                    } else {
637
                    } else {
633
                                                // stats
638
                                                // stats
634
                                                if (COSD_FLAGS & COSD_FLAG_STATS) {
639
                                                if (COSD_FLAGS & COSD_FLAG_STATS) {
635
                                                        write_ascii_string_pgm(2, 5, stats_item_pointers[0]); // max Altitude
640
                                                        write_ascii_string_pgm(2, 5, stats_item_pointers[0]); // max Altitude
636
                                write_number_s(17, 5, max_Altimeter / 30);
641
                                write_ndigit_number_s(18, 5, max_Altimeter / 30, 1000, 0);
637
                                write_char_xy(22, 5, 204); // small meters m
642
                                write_char_xy(22, 5, 204); // small meters m
638
                                                        write_ascii_string_pgm(2, 6, stats_item_pointers[1]); // max Speed
643
                                                        write_ascii_string_pgm(2, 6, stats_item_pointers[1]); // max Speed
639
                                write_3digit_number_u(19, 6, (uint16_t) (((uint32_t) max_GroundSpeed * 36) / 1000));
644
                                write_ndigit_number_u(19, 6, (uint16_t) (((uint32_t) max_GroundSpeed * 36) / 1000), 100, 0);
640
                                write_char_xy(22, 6, 203); // km/h
645
                                write_char_xy(22, 6, 203); // km/h
641
                                                        write_ascii_string_pgm(2, 7, stats_item_pointers[2]); // max Distance
646
                                                        write_ascii_string_pgm(2, 7, stats_item_pointers[2]); // max Distance
642
                                write_number_s(17, 7, max_Distance / 100);
647
                                write_ndigit_number_u(19, 7, max_Distance / 100, 100, 0);
643
                                write_char_xy(22, 7, 204); // small meters m
648
                                write_char_xy(22, 7, 204); // small meters m
644
                                                        write_ascii_string_pgm(2, 8, stats_item_pointers[3]); // min voltage
649
                                                        write_ascii_string_pgm(2, 8, stats_item_pointers[3]); // min voltage
645
                                write_number_u_10th(16, 8, min_UBat);
650
                                                        write_ndigit_number_u_10th(18, 8, min_UBat, 100, 0);
646
                                write_ascii_string(22, 8, "V"); // voltage
651
                                write_ascii_string(22, 8, "V"); // voltage
647
                                                        write_ascii_string_pgm(2, 9, stats_item_pointers[4]); // max time
652
                                                        write_ascii_string_pgm(2, 9, stats_item_pointers[4]); // max time
648
                                write_time(16, 9, max_FlyingTime);
653
                                write_time(16, 9, max_FlyingTime);
649
                                write_char_xy(22, 9, 210); // fly clock
654
                                write_char_xy(22, 9, 210); // fly clock
650
                                                } else if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) { // if no stats there is space horizon
655
                                                } else if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) { // if no stats there is space horizon
651
                            draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll);
656
                            draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll);
652
                        }
657
                        }
653
                    }
658
                    }
654
 
659
 
655
                    // bottom line
660
                    // bottom line
656
                    write_number_u_10th(0, bottom_line, naviData.UBat);
661
                                        write_ndigit_number_u_10th(2, bottom_line, naviData.UBat, 100, 0);
657
                    if (naviData.UBat <= UBAT_WRN && last_UBat > UBAT_WRN) {
662
                    if (naviData.UBat <= UBAT_WRN && last_UBat > UBAT_WRN) {
658
                        for (uint8_t x = 0; x < 7; x++)
663
                        for (uint8_t x = 0; x < 7; x++)
659
                            write_char_att_xy(x, bottom_line, BLINK);
664
                            write_char_att_xy(x, bottom_line, BLINK);
660
                    } else {
665
                    } else {
661
                        for (uint8_t x = 0; x < 7; x++)
666
                        for (uint8_t x = 0; x < 7; x++)
662
                            write_char_att_xy(x, bottom_line, 0);
667
                            write_char_att_xy(x, bottom_line, 0);
663
                    }
668
                    }
664
 
669
 
665
                    write_time(8, bottom_line, uptime);
670
                    write_time(8, bottom_line, uptime);
666
                    write_time(16, bottom_line, naviData.FlyingTime);
671
                    write_time(16, bottom_line, naviData.FlyingTime);
667
 
672
 
668
                    write_3digit_number_u(23, bottom_line, naviData.SatsInUse);
673
                    write_ndigit_number_u(24, bottom_line, naviData.SatsInUse, 10, 0);
669
 
674
 
670
                    if (naviData.NCFlags & NC_FLAG_CH) {
675
                    if (naviData.NCFlags & NC_FLAG_CH) {
671
                        write_char_xy(27, bottom_line, 231); // gps ch
676
                        write_char_xy(27, bottom_line, 231); // gps ch
672
                    } else if (naviData.NCFlags & NC_FLAG_PH) {
677
                    } else if (naviData.NCFlags & NC_FLAG_PH) {
673
                        write_char_xy(27, bottom_line, 230); // gps ph
678
                        write_char_xy(27, bottom_line, 230); // gps ph
674
                    } else { // (naviData.NCFlags & NC_FLAG_FREE)
679
                    } else { // (naviData.NCFlags & NC_FLAG_FREE)
675
                        write_char_xy(27, bottom_line, 201); // sat2 (free)
680
                        write_char_xy(27, bottom_line, 201); // sat2 (free)
676
                    }
681
                    }
677
 
682
 
678
                    //write_number_s(8, 5, RxDataLen);
683
                    //write_number_s(8, 5, RxDataLen);
679
                    //write_number_s(16, 5, setsReceived++);
684
                    //write_number_s(16, 5, setsReceived++);
680
 
685
 
681
                    // remember statistics
686
                    // remember statistics
682
                    if (naviData.Altimeter > max_Altimeter) max_Altimeter = naviData.Altimeter;
687
                    if (naviData.Altimeter > max_Altimeter) max_Altimeter = naviData.Altimeter;
683
                    if (naviData.GroundSpeed > max_GroundSpeed) max_GroundSpeed = naviData.GroundSpeed;
688
                    if (naviData.GroundSpeed > max_GroundSpeed) max_GroundSpeed = naviData.GroundSpeed;
684
                    if (naviData.HomePositionDeviation.Distance > max_Distance) {
689
                    if (naviData.HomePositionDeviation.Distance > max_Distance) {
685
                        max_Distance = naviData.HomePositionDeviation.Distance;
690
                        max_Distance = naviData.HomePositionDeviation.Distance;
686
                    }
691
                    }
687
                    if (naviData.UBat < min_UBat) min_UBat = naviData.UBat;
692
                    if (naviData.UBat < min_UBat) min_UBat = naviData.UBat;
688
                    if (naviData.FlyingTime > max_FlyingTime) max_FlyingTime = naviData.FlyingTime;
693
                    if (naviData.FlyingTime > max_FlyingTime) max_FlyingTime = naviData.FlyingTime;
689
 
694
 
690
                    old_MKFlags = naviData.MKFlags;
695
                    old_MKFlags = naviData.MKFlags;
691
                }
696
                }
692
            }
697
            }
693
            seconds_since_last_data = 0;
698
            seconds_since_last_data = 0;
694
            rxd_buffer_locked = 0;
699
            rxd_buffer_locked = 0;
695
        }
700
        }
696
        // handle keypress
701
        // handle keypress
697
        if (s1_pressed()) {
702
        if (s1_pressed()) {
698
            config_menu();
703
            config_menu();
699
        }
704
        }
700
        if (seconds_since_last_data > 2) {
705
        if (seconds_since_last_data > 2) {
701
                        // request OSD Data from NC every 100ms
706
                        // request OSD Data from NC every 100ms
702
                        usart1_request_mk_data(1, 'o', 100);
707
                        usart1_request_mk_data(1, 'o', 100);
703
                        seconds_since_last_data = 0;
708
                        seconds_since_last_data = 0;
704
        }
709
        }
705
    }
710
    }
706
#endif
711
#endif
707
    return 0;
712
    return 0;
708
}
713
}
709
 
714