Subversion Repositories Projects

Rev

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

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