Subversion Repositories Projects

Rev

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

Rev 335 Rev 336
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 "max7456_software_spi.c"
31
#include "max7456_software_spi.c"
32
#include "usart1.h"
32
#include "usart1.h"
33
 
33
 
34
/* TODO:
34
/* TODO:
35
 * - verifiy correctness of values
35
 * - verifiy correctness of values
36
 * - clean up code :)
36
 * - clean up code :)
37
 */
37
 */
38
 
38
 
39
/* ##########################################################################
39
/* ##########################################################################
40
 * Debugging and general purpose definitions
40
 * Debugging and general purpose definitions
41
 * ##########################################################################*/
41
 * ##########################################################################*/
42
#define ALLCHARSDEBUG 0         // set to 1 and flash firmware to see all chars
42
#define ALLCHARSDEBUG 0         // set to 1 and flash firmware to see all chars
43
 
43
 
44
#ifndef WRITECHARS                      // if WRITECHARS not set via makefile
44
#ifndef WRITECHARS                      // if WRITECHARS not set via makefile
45
#define WRITECHARS -1           // set to 2XX and flash firmware to write new char
45
#define WRITECHARS -1           // set to 2XX and flash firmware to write new char
46
                                                        // enables the allchars as well to see results
46
                                                        // enables the allchars as well to see results
47
#endif
47
#endif
48
 
48
 
49
#ifndef NTSC                            // if NTSC is not thet via makefile
49
#ifndef NTSC                            // if NTSC is not thet via makefile
50
#define NTSC 0                          // set to 1 for NTSC mode + lifts the bottom line
50
#define NTSC 0                          // set to 1 for NTSC mode + lifts the bottom line
51
#endif
51
#endif
52
 
52
 
53
#define ARTHORIZON 0            // set to 1 to enable roll&nick artificial horizon
53
#define ARTHORIZON 0            // set to 1 to enable roll&nick artificial horizon
54
#define NOOSD 0                         // set to 1 to disable OSD completely
54
#define NOOSD 0                         // set to 1 to disable OSD completely
55
#define NOOSD_BUT_WRN 0         // set to 1 to disable OSD completely but show 
55
#define NOOSD_BUT_WRN 0         // set to 1 to disable OSD completely but show 
56
                                                        // battery and receive signal warnings
56
                                                        // battery and receive signal warnings
57
#define UBAT_WRN 94                     // voltage for blinking warning, like FC settings
57
#define UBAT_WRN 94                     // voltage for blinking warning, like FC settings
58
#define RCLVL_WRN 100           // make the RC level blink if below this number
58
#define RCLVL_WRN 100           // make the RC level blink if below this number
59
 
59
 
60
// ### read datasheet before changing stuff below this line :)
60
// ### read datasheet before changing stuff below this line :)
61
#define BLINK   0b01001111      // attribute byte for blinking chars
61
#define BLINK   0b01001111      // attribute byte for blinking chars
62
 
62
 
63
/* ##########################################################################
63
/* ##########################################################################
64
 * FLAGS usable during runtime
64
 * FLAGS usable during runtime
65
 * ##########################################################################*/
65
 * ##########################################################################*/
66
#define COSD_FLAG_NTSC                   1
66
#define COSD_FLAG_NTSC                   1
67
#define COSD_FLAG_ARTHORIZON     2
67
#define COSD_FLAG_ARTHORIZON     2
68
#define COSD_FLAG_NOOSD                  4
68
#define COSD_FLAG_NOOSD                  4
69
#define COSD_FLAG_NOOSD_BUT_WRN  8
69
#define COSD_FLAG_NOOSD_BUT_WRN  8
70
#define COSD_ICONS_WRITTEN              16
70
#define COSD_ICONS_WRITTEN              16
71
 
71
 
72
/* ##########################################################################
72
/* ##########################################################################
73
 * LED controll
73
 * LED controll
74
 * ##########################################################################*/
74
 * ##########################################################################*/
75
#define LED1_ON                 PORTC |=  (1 << PC0);
75
#define LED1_ON                 PORTC |=  (1 << PC0);
76
#define LED1_OFF                PORTC &= ~(1 << PC0);
76
#define LED1_OFF                PORTC &= ~(1 << PC0);
77
#define LED2_ON                 PORTC |=  (1 << PC1);
77
#define LED2_ON                 PORTC |=  (1 << PC1);
78
#define LED2_OFF                PORTC &= ~(1 << PC1);
78
#define LED2_OFF                PORTC &= ~(1 << PC1);
79
#define LED3_ON                 PORTC |=  (1 << PC2);
79
#define LED3_ON                 PORTC |=  (1 << PC2);
80
#define LED3_OFF                PORTC &= ~(1 << PC2);
80
#define LED3_OFF                PORTC &= ~(1 << PC2);
81
#define LED4_ON                 PORTC |=  (1 << PC3);
81
#define LED4_ON                 PORTC |=  (1 << PC3);
82
#define LED4_OFF                PORTC &= ~(1 << PC3);
82
#define LED4_OFF                PORTC &= ~(1 << PC3);
83
 
83
 
84
/* ##########################################################################
84
/* ##########################################################################
85
 * switch controll
85
 * switch controll
86
 * ##########################################################################*/
86
 * ##########################################################################*/
87
#define S1_PRESSED              !(PINC & (1<<PC5))
87
#define S1_PRESSED              !(PINC & (1<<PC5))
88
#define S2_PRESSED              !(PINC & (1<<PC4))
88
#define S2_PRESSED              !(PINC & (1<<PC4))
89
 
89
 
90
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
90
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
91
// data structs
91
// data structs
92
#include "mk-data-structs.h"
92
#include "mk-data-structs.h"
93
 
93
 
94
/* ##########################################################################
94
/* ##########################################################################
95
 * global definitions and global vars
95
 * global definitions and global vars
96
 * ##########################################################################*/
96
 * ##########################################################################*/
97
volatile uint8_t rxd_buffer_locked = 0;
97
volatile uint8_t rxd_buffer_locked = 0;
98
volatile uint8_t rxd_buffer[RXD_BUFFER_LEN];
98
volatile uint8_t rxd_buffer[RXD_BUFFER_LEN];
99
volatile uint8_t txd_buffer[TXD_BUFFER_LEN];
99
volatile uint8_t txd_buffer[TXD_BUFFER_LEN];
100
volatile uint8_t ReceivedBytes = 0;
100
volatile uint8_t ReceivedBytes = 0;
101
volatile uint8_t *pRxData = 0;
101
volatile uint8_t *pRxData = 0;
102
volatile uint8_t RxDataLen = 0;
102
volatile uint8_t RxDataLen = 0;
103
volatile uint16_t setsReceived = 0;
103
volatile uint16_t setsReceived = 0;
104
 
104
 
105
volatile NaviData_t naviData;
105
volatile NaviData_t naviData;
106
volatile DebugOut_t debugData;
106
volatile DebugOut_t debugData;
107
 
107
 
108
// cache old vars for blinking attribute, checkup is faster than full
108
// cache old vars for blinking attribute, checkup is faster than full
109
// attribute write each time
109
// attribute write each time
110
volatile uint8_t last_UBat = 255;
110
volatile uint8_t last_UBat = 255;
111
volatile uint8_t last_RC_Quality = 255;
111
volatile uint8_t last_RC_Quality = 255;
112
 
112
 
113
// 16bit should be enough, normal LiPos don't last that long
113
// 16bit should be enough, normal LiPos don't last that long
114
volatile uint16_t uptime = 0;
114
volatile uint16_t uptime = 0;
115
volatile uint16_t timer = 0;
115
volatile uint16_t timer = 0;
116
 
116
 
117
// remember last time data was received
117
// remember last time data was received
118
volatile uint8_t seconds_since_last_data = 0;
118
volatile uint8_t seconds_since_last_data = 0;
119
 
119
 
120
#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))
120
#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))
121
 
121
 
122
// general PAL|NTSC distingiusch stuff
122
// general PAL|NTSC distingiusch stuff
123
uint8_t top_line = 1;
123
uint8_t top_line = 1;
124
uint8_t bottom_line = 14;
124
uint8_t bottom_line = 14;
125
 
125
 
126
// Flags
126
// Flags
127
uint8_t COSD_FLAGS = 0;
127
uint8_t COSD_FLAGS = 0;
128
 
128
 
129
/* ##########################################################################
129
/* ##########################################################################
130
 * debounce buttons
130
 * debounce buttons
131
 * ##########################################################################*/
131
 * ##########################################################################*/
132
int s1_pressed() {
132
int s1_pressed() {
133
        if (S1_PRESSED) {
133
        if (S1_PRESSED) {
134
                _delay_ms(25);
134
                _delay_ms(25);
135
                if (S1_PRESSED) return 1;
135
                if (S1_PRESSED) return 1;
136
        }
136
        }
137
        return 0;
137
        return 0;
138
}
138
}
139
 
139
 
140
int s2_pressed() {
140
int s2_pressed() {
141
        if (S2_PRESSED) {
141
        if (S2_PRESSED) {
142
                _delay_ms(25);
142
                _delay_ms(25);
143
                if (S2_PRESSED) return 1;
143
                if (S2_PRESSED) return 1;
144
        }
144
        }
145
        return 0;
145
        return 0;
146
}
146
}
147
 
147
 
148
 
148
 
149
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
149
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
150
 
150
 
151
/**
151
/**
152
 * serial support
152
 * serial support
153
 */
153
 */
154
#include "usart1.c"
154
#include "usart1.c"
155
 
155
 
156
 
156
 
157
/* ##########################################################################
157
/* ##########################################################################
158
 * timer stuff
158
 * timer stuff
159
 * ##########################################################################*/
159
 * ##########################################################################*/
160
 
160
 
161
/**
161
/**
162
 * timer kicks in every 1000uS ^= 1ms
162
 * timer kicks in every 1000uS ^= 1ms
163
 */
163
 */
164
ISR(TIMER0_OVF_vect) {
164
ISR(TIMER0_OVF_vect) {
165
    OCR0 = 6; // preload
165
    OCR0 = 6; // preload
166
    if (!timer--) {
166
    if (!timer--) {
167
        uptime++;
167
        uptime++;
168
        timer = 999;
168
        timer = 999;
169
                seconds_since_last_data++;
169
                seconds_since_last_data++;
170
    }
170
    }
171
}
171
}
172
 
172
 
173
/* ##########################################################################
173
/* ##########################################################################
174
 * compass stuff
174
 * compass stuff
175
 * ##########################################################################*/
175
 * ##########################################################################*/
176
 
176
 
177
/**
177
/**
178
 * convert the <heading> gotton from NC into an index
178
 * convert the <heading> gotton from NC into an index
179
 */
179
 */
180
uint8_t heading_conv(uint16_t heading) {
180
uint8_t heading_conv(uint16_t heading) {
181
    if (heading > 23 && heading < 68) {
181
    if (heading > 23 && heading < 68) {
182
        //direction = "NE";
182
        //direction = "NE";
183
        return 0;
183
        return 0;
184
    } else if (heading > 67 && heading < 113) {
184
    } else if (heading > 67 && heading < 113) {
185
        //direction = "E ";
185
        //direction = "E ";
186
        return 1;
186
        return 1;
187
    } else if (heading > 112 && heading < 158) {
187
    } else if (heading > 112 && heading < 158) {
188
        //direction = "SE";
188
        //direction = "SE";
189
        return 2;
189
        return 2;
190
    } else if (heading > 157 && heading < 203) {
190
    } else if (heading > 157 && heading < 203) {
191
        //direction = "S ";
191
        //direction = "S ";
192
        return 3;
192
        return 3;
193
    } else if (heading > 202 && heading < 248) {
193
    } else if (heading > 202 && heading < 248) {
194
        //direction = "SW";
194
        //direction = "SW";
195
        return 4;
195
        return 4;
196
    } else if (heading > 247 && heading < 293) {
196
    } else if (heading > 247 && heading < 293) {
197
        //direction = "W ";
197
        //direction = "W ";
198
        return 5;
198
        return 5;
199
    } else if (heading > 292 && heading < 338) {
199
    } else if (heading > 292 && heading < 338) {
200
        //direction = "NW";
200
        //direction = "NW";
201
        return 6;
201
        return 6;
202
    }
202
    }
203
    //direction = "N ";
203
    //direction = "N ";
204
    return 7;
204
    return 7;
205
}
205
}
206
 
206
 
207
/**
207
/**
208
 * draw a compass rose at <x>/<y> for <heading>
208
 * draw a compass rose at <x>/<y> for <heading>
209
 */
209
 */
210
void draw_compass(uint8_t x, uint8_t y, uint16_t heading) {
210
void draw_compass(uint8_t x, uint8_t y, uint16_t heading) {
211
    //char* rose = "---N---O---S---W---N---O---S---W---N---O---S---W";
211
    //char* rose = "---N---O---S---W---N---O---S---W---N---O---S---W";
212
    char rose[48] = {216, 215, 216, 211, 216, 215, 216, 213, 216, 215, 216, 212,
212
    char rose[48] = {216, 215, 216, 211, 216, 215, 216, 213, 216, 215, 216, 212,
213
                    216, 215, 216, 214, 216, 215, 216, 211, 216, 215, 216, 213,
213
                    216, 215, 216, 214, 216, 215, 216, 211, 216, 215, 216, 213,
214
                    216, 215, 216, 212, 216, 215, 216, 214, 216, 215, 216, 211,
214
                    216, 215, 216, 212, 216, 215, 216, 214, 216, 215, 216, 211,
215
                    216, 215, 216, 213, 216, 215, 216, 212, 216, 215, 216, 214};
215
                    216, 215, 216, 213, 216, 215, 216, 212, 216, 215, 216, 214};
216
        // the center is char 19 (north), we add the current heading in 8th
216
        // the center is char 19 (north), we add the current heading in 8th
217
        // which would be 22.5 degrees, but float would bloat up the code
217
        // which would be 22.5 degrees, but float would bloat up the code
218
        // and *10 / 225 would take ages... so we take the uncorrect way
218
        // and *10 / 225 would take ages... so we take the uncorrect way
219
    uint8_t front = 19 + (heading / 22);
219
    uint8_t front = 19 + (heading / 22);
220
    for (uint8_t i = 0; i < 9; i++) {
220
    for (uint8_t i = 0; i < 9; i++) {
221
                write_char_xy(x++, y, rose[front - 4 + i]);
221
                write_char_xy(x++, y, rose[front - 4 + i]);
222
    }
222
    }
223
}
223
}
224
 
224
 
225
/* ##########################################################################
225
/* ##########################################################################
226
 * artificial horizon
226
 * artificial horizon
227
 * ##########################################################################*/
227
 * ##########################################################################*/
228
// remember last time displayed values
228
// remember last time displayed values
229
int8_t old_af_x = -1, old_af_y = -1;
229
int8_t old_af_x = -1, old_af_y = -1;
230
 
230
 
231
/**
231
/**
232
 * draw roll und nick indicators (could be enhanced to full artificial horizon)
232
 * draw roll und nick indicators (could be enhanced to full artificial horizon)
233
 * from line <firstline> to <listlines> for given <nick> and <roll> values
233
 * from line <firstline> to <listlines> for given <nick> and <roll> values
234
 */
234
 */
235
void draw_artificial_horizon(uint8_t firstline, uint8_t lastline, int16_t nick, int16_t roll) {
235
void draw_artificial_horizon(uint8_t firstline, uint8_t lastline, int16_t nick, int16_t roll) {
236
        char noodle[5] = {225, 225, 226, 227, 227};
236
        char noodle[5] = {225, 225, 226, 227, 227};
237
        uint8_t center_x = 15;
237
        uint8_t center_x = 15;
238
        uint8_t center_y = lastline - firstline;
238
        uint8_t center_y = lastline - firstline;
239
        center_y = 7;
239
        center_y = 7;
240
        write_char_xy(center_x,center_y,228);
240
        write_char_xy(center_x,center_y,228);
241
        uint8_t cpos, nicky, rollx;
241
        uint8_t cpos, nicky, rollx;
242
       
242
       
243
        // which line
243
        // which line
244
        int8_t ypos =  nick / 20;
244
        int8_t ypos =  nick / 20;
245
        // which character from the array?
245
        // which character from the array?
246
        if (nick < 0) {
246
        if (nick < 0) {
247
                cpos = -1*((nick - (ypos * 20))/4);
247
                cpos = -1*((nick - (ypos * 20))/4);
248
                ypos--;
248
                ypos--;
249
        } else cpos = 4-((nick - (ypos * 20))/4);
249
        } else cpos = 4-((nick - (ypos * 20))/4);
250
        if (cpos > 4) cpos = 4;
250
        if (cpos > 4) cpos = 4;
251
 
251
 
252
        nicky = center_y - ypos;
252
        nicky = center_y - ypos;
253
        if (nicky > lastline) nicky = lastline;
253
        if (nicky > lastline) nicky = lastline;
254
        else if (nicky < firstline) nicky = firstline;
254
        else if (nicky < firstline) nicky = firstline;
255
 
255
 
256
        // ensure roll-borders
256
        // ensure roll-borders
257
        rollx = (roll / 8)+15;
257
        rollx = (roll / 8)+15;
258
        if (rollx < 2) rollx = 2;
258
        if (rollx < 2) rollx = 2;
259
        else if (rollx > 28) rollx = 28;
259
        else if (rollx > 28) rollx = 28;
260
 
260
 
261
 
261
 
262
        // clear roll
262
        // clear roll
263
        if (old_af_x != rollx && old_af_x >= 0) {
263
        if (old_af_x != rollx && old_af_x >= 0) {
264
                write_char_xy(old_af_x,13,0);
264
                write_char_xy(old_af_x,13,0);
265
        }
265
        }
266
 
266
 
267
        // clear nick
267
        // clear nick
268
        if (old_af_y != nicky && old_af_y >= 0) {
268
        if (old_af_y != nicky && old_af_y >= 0) {
269
                write_char_xy(center_x-1,old_af_y,0);
269
                write_char_xy(center_x-1,old_af_y,0);
270
                write_char_xy(center_x+1,old_af_y,0);
270
                write_char_xy(center_x+1,old_af_y,0);
271
        }
271
        }
272
 
272
 
273
 
273
 
274
        // draw nick
274
        // draw nick
275
        write_char_xy(center_x-1,nicky,noodle[cpos]);
275
        write_char_xy(center_x-1,nicky,noodle[cpos]);
276
        write_char_xy(center_x+1,nicky,noodle[cpos]);
276
        write_char_xy(center_x+1,nicky,noodle[cpos]);
277
 
277
 
278
        // draw roll
278
        // draw roll
279
        write_char_xy(rollx,lastline,229);
279
        write_char_xy(rollx,lastline,229);
280
 
280
 
281
        // update old vars
281
        // update old vars
282
        old_af_x = rollx;
282
        old_af_x = rollx;
283
        old_af_y = nicky;
283
        old_af_y = nicky;
284
 
284
 
285
        // debug numbers
285
        // debug numbers
286
        //write_3digit_number_u(20,6,cpos);
286
        //write_3digit_number_u(20,6,cpos);
287
        //write_number_s(20,7,ypos);    
287
        //write_number_s(20,7,ypos);    
288
        //write_number_s(0,7,nick);             
288
        //write_number_s(0,7,nick);             
289
        //write_number_s(18,11,roll);   
289
        //write_number_s(18,11,roll);   
290
}
290
}
291
 
291
 
292
/* ##########################################################################
292
/* ##########################################################################
293
 * A simple config menu for the flags
293
 * A simple config menu for the flags
294
 * ##########################################################################*/
294
 * ##########################################################################*/
295
void config_menu(void) {
295
void config_menu(void) {
296
        // disable interrupts (makes the menu more smoothely)
296
        // disable interrupts (makes the menu more smoothely)
297
        cli();
297
        cli();
298
 
298
 
299
        // clear screen
299
        // clear screen
300
        clear();
300
        clear();
301
       
301
       
302
        char* menu[4] = {"Normal OSD      ",
302
        char* menu[4] = {"Normal OSD      ",
303
                                         "Art.Horizon     ",
303
                                         "Art.Horizon     ",
304
                                         "NO OSD          ",
304
                                         "NO OSD          ",
305
                                         "NO OSD but WRN  "};
305
                                         "NO OSD but WRN  "};
306
 
306
 
307
        uint8_t inmenu = 1;
307
        uint8_t inmenu = 1;
308
        uint8_t chosen = 0;
308
        uint8_t chosen = 0;
309
        write_ascii_string(10,  4, "Config Menu");
309
        write_ascii_string(10,  4, "Config Menu");
310
       
310
       
311
        // clear all mode flags
311
        // clear all mode flags
312
        COSD_FLAGS &= ~(COSD_FLAG_ARTHORIZON | COSD_FLAG_NOOSD | COSD_FLAG_NOOSD_BUT_WRN);
312
        COSD_FLAGS &= ~(COSD_FLAG_ARTHORIZON | COSD_FLAG_NOOSD | COSD_FLAG_NOOSD_BUT_WRN);
313
 
313
 
314
        // wait a bit before doing stuff so user has chance to release button
314
        // wait a bit before doing stuff so user has chance to release button
315
        _delay_ms(250);
315
        _delay_ms(250);
316
 
316
 
317
        while (inmenu) {
317
        while (inmenu) {
318
                        write_ascii_string(2,  7, menu[chosen]);
318
                        write_ascii_string(2,  7, menu[chosen]);
319
                        if (s2_pressed()) {
319
                        if (s2_pressed()) {
320
                                chosen = (chosen + 1) % 4;
320
                                chosen = (chosen + 1) % 4;
321
                                _delay_ms(500);
321
                                _delay_ms(500);
322
                        } else if (s1_pressed()) {
322
                        } else if (s1_pressed()) {
323
                                switch (chosen) {
323
                                switch (chosen) {
324
                                        case 1:         // artificial horizon
324
                                        case 1:         // artificial horizon
325
                                                COSD_FLAGS |= COSD_FLAG_ARTHORIZON;
325
                                                COSD_FLAGS |= COSD_FLAG_ARTHORIZON;
326
                                                break;
326
                                                break;
327
                                        case 2:         // everything off
327
                                        case 2:         // everything off
328
                                                COSD_FLAGS |= COSD_FLAG_NOOSD;
328
                                                COSD_FLAGS |= COSD_FLAG_NOOSD;
329
                                                break;
329
                                                break;
330
                                        case 3:         // only warning
330
                                        case 3:         // only warning
331
                                                COSD_FLAGS |= COSD_FLAG_NOOSD_BUT_WRN;
331
                                                COSD_FLAGS |= COSD_FLAG_NOOSD_BUT_WRN;
332
                                                break;
332
                                                break;
333
                                        //default:      // normal OSD, so let the flags cleared
333
                                        //default:      // normal OSD, so let the flags cleared
334
                                }
334
                                }
335
                                // leave menu
335
                                // leave menu
336
                                inmenu = 0;
336
                                inmenu = 0;
337
                                _delay_ms(500);
337
                                _delay_ms(500);
338
                        }
338
                        }
339
        }
339
        }
340
 
340
 
341
        // clear screen up again
341
        // clear screen up again
342
        clear();
342
        clear();
343
 
343
 
344
        // update flags to paint display again if needed
344
        // update flags to paint display again if needed
345
        COSD_FLAGS &= ~COSD_ICONS_WRITTEN;
345
        COSD_FLAGS &= ~COSD_ICONS_WRITTEN;
346
 
346
 
347
        // enable interrupts again
347
        // enable interrupts again
348
        sei();
348
        sei();
349
}
349
}
350
 
350
 
351
#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))
351
#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))
352
 
352
 
353
/* ##########################################################################
353
/* ##########################################################################
354
 * MAIN
354
 * MAIN
355
 * ##########################################################################*/
355
 * ##########################################################################*/
356
int main(void) {
356
int main(void) {
357
        // set up FLAGS, compiler should flatten this one
357
        // set up FLAGS, compiler should flatten this one
358
        COSD_FLAGS = (NTSC << (COSD_FLAG_NTSC - 1));
358
        COSD_FLAGS = (NTSC << (COSD_FLAG_NTSC - 1));
359
        COSD_FLAGS |= (ARTHORIZON << (COSD_FLAG_ARTHORIZON - 1));
359
        COSD_FLAGS |= (ARTHORIZON << (COSD_FLAG_ARTHORIZON - 1));
360
        COSD_FLAGS |= (NOOSD << (COSD_FLAG_NOOSD - 1));
360
        COSD_FLAGS |= (NOOSD << (COSD_FLAG_NOOSD - 1));
361
        COSD_FLAGS |= (NOOSD_BUT_WRN << (COSD_FLAG_NOOSD_BUT_WRN - 1));
361
        COSD_FLAGS |= (NOOSD_BUT_WRN << (COSD_FLAG_NOOSD_BUT_WRN - 1));
362
 
362
 
363
        // set up Atmega162 Ports
363
        // set up Atmega162 Ports
364
    DDRA |= (1 << PA1); // PA1 output (/CS)
364
    DDRA |= (1 << PA1); // PA1 output (/CS)
365
    MAX_CS_HIGH
365
    MAX_CS_HIGH
366
    DDRA |= (1 << PA2); // PA2 output (SDIN)
366
    DDRA |= (1 << PA2); // PA2 output (SDIN)
367
    MAX_SDIN_LOW
367
    MAX_SDIN_LOW
368
    DDRA |= (1 << PA3); // PA3 output (SCLK)
368
    DDRA |= (1 << PA3); // PA3 output (SCLK)
369
    MAX_SCLK_LOW
369
    MAX_SCLK_LOW
370
    DDRA |= (1 << PA5); // PA5 output (RESET)
370
    DDRA |= (1 << PA5); // PA5 output (RESET)
371
    MAX_RESET_HIGH
371
    MAX_RESET_HIGH
372
 
372
 
373
    DDRC |= (1 << PC0); // PC0 output (LED1 gn)
373
    DDRC |= (1 << PC0); // PC0 output (LED1 gn)
374
    LED1_OFF
374
    LED1_OFF
375
    DDRC |= (1 << PC1); // PC1 output (LED2 rt)
375
    DDRC |= (1 << PC1); // PC1 output (LED2 rt)
376
    LED2_OFF
376
    LED2_OFF
377
    DDRC |= (1 << PC2); // PC2 output (LED3 gn)
377
    DDRC |= (1 << PC2); // PC2 output (LED3 gn)
378
    LED3_OFF
378
    LED3_OFF
379
    DDRC |= (1 << PC3); // PC3 output (LED4 rt)
379
    DDRC |= (1 << PC3); // PC3 output (LED4 rt)
380
    LED4_OFF
380
    LED4_OFF
381
 
381
 
382
    DDRC &= ~(1 << PC4); // PC4 input  (MODE)
382
    DDRC &= ~(1 << PC4); // PC4 input  (MODE)
383
    PORTC |= (1 << PC4); // pullup
383
    PORTC |= (1 << PC4); // pullup
384
    DDRC &= ~(1 << PC5); // PC5 input  (SET)
384
    DDRC &= ~(1 << PC5); // PC5 input  (SET)
385
    PORTC |= (1 << PC5); // pullup
385
    PORTC |= (1 << PC5); // pullup
386
 
386
 
387
        // set up top and bottom lines
387
        // set up top and bottom lines
388
        if (COSD_FLAGS & COSD_FLAG_NTSC) {
388
        if (COSD_FLAGS & COSD_FLAG_NTSC) {
389
                bottom_line = 12;
389
                bottom_line = 12;
390
        } else {
390
        } else {
391
                bottom_line = 14;
391
                bottom_line = 14;
392
        }
392
        }
393
 
393
 
394
        // reset the MAX7456 to be sure any undefined states do no harm
394
        // reset the MAX7456 to be sure any undefined states do no harm
395
    MAX_RESET_LOW
395
    MAX_RESET_LOW
396
    MAX_RESET_HIGH
396
    MAX_RESET_HIGH
397
 
397
 
398
        // check for keypress at startup
398
        // check for keypress at startup
399
        if (s2_pressed()) { // togle COSD_FLAG_ARTHORIZON
399
        if (s2_pressed()) { // togle COSD_FLAG_ARTHORIZON
400
                        COSD_FLAGS ^= (1 << (COSD_FLAG_ARTHORIZON - 1));
400
                        COSD_FLAGS ^= (1 << (COSD_FLAG_ARTHORIZON - 1));
401
                        _delay_ms(100);
401
                        _delay_ms(100);
402
    }
402
    }
403
 
403
 
404
    // give the FC/NC and the maxim time to come up
404
    // give the FC/NC and the maxim time to come up
405
    LED4_ON
405
    LED4_ON
406
    _delay_ms(2000);
406
    _delay_ms(2000);
407
 
407
 
408
    LED4_OFF
408
    LED4_OFF
409
 
409
 
410
 
410
 
411
     //Pushing NEW chars to the MAX7456
411
     //Pushing NEW chars to the MAX7456
412
#if (WRITECHARS != -1)
412
#if (WRITECHARS != -1)
413
        // DISABLE display (VM0)
413
        // DISABLE display (VM0)
414
    spi_send_byte(0x00, 0b00000000);
414
    spi_send_byte(0x00, 0b00000000);
415
 
415
 
416
        #include "characters.c"
416
        #include "characters.c"
417
#endif 
417
#endif 
418
 
418
 
419
        // Setup Video Mode
419
        // Setup Video Mode
420
        if (COSD_FLAGS & COSD_FLAG_NTSC) {
420
        if (COSD_FLAGS & COSD_FLAG_NTSC) {
421
        // NTSC + enable display immediately (VM0)
421
        // NTSC + enable display immediately (VM0)
422
        spi_send_byte(0x00, 0b00001000);
422
        spi_send_byte(0x00, 0b00001000);
423
        } else {
423
        } else {
424
        // PAL + enable display immediately (VM0)
424
        // PAL + enable display immediately (VM0)
425
        spi_send_byte(0x00, 0b01001000);
425
        spi_send_byte(0x00, 0b01001000);
426
        }
426
        }
427
 
427
 
428
    // clear all display-mem (DMM)
428
    // clear all display-mem (DMM)
429
    spi_send_byte(0x04, 0b00000100);
429
    spi_send_byte(0x04, 0b00000100);
430
 
430
 
431
    // clearing takes 12uS according to maxim so lets wait longer
431
    // clearing takes 12uS according to maxim so lets wait longer
432
    _delay_us(120);
432
    _delay_us(120);
433
 
433
 
434
    // 8bit mode
434
    // 8bit mode
435
    spi_send_byte(0x04, 0b01000000);
435
    spi_send_byte(0x04, 0b01000000);
436
 
436
 
437
    // write blank chars to whole screen
437
    // write blank chars to whole screen
438
    clear();
438
    clear();
439
 
439
 
440
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
440
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
441
    // init usart
441
    // init usart
442
    usart1_init();
442
    usart1_init();
443
 
443
 
444
    // set up timer
444
    // set up timer
445
    TCCR0 |= (1 << CS00) | (1 << CS01); // timer0 prescaler 64
445
    TCCR0 |= (1 << CS00) | (1 << CS01); // timer0 prescaler 64
446
    OCR0 = 6; // preload
446
    OCR0 = 6; // preload
447
    TIMSK |= (1 << TOIE0); // enable overflow timer0
447
    TIMSK |= (1 << TOIE0); // enable overflow timer0
448
 
448
 
449
    // enable interrupts
449
    // enable interrupts
450
    sei();
450
    sei();
451
#endif
451
#endif
452
 
452
 
453
    //write_ascii_string(2,  7, "         CaScAdE          ");
453
    //write_ascii_string(2,  7, "         CaScAdE          ");
454
    //write_ascii_string(2,  8, "is TESTING his open source");
454
    //write_ascii_string(2,  8, "is TESTING his open source");
455
    //write_ascii_string(2,  9, "    EPi OSD Firmware");
455
    //write_ascii_string(2,  9, "    EPi OSD Firmware");
456
 
456
 
457
    // custom char preview
457
    // custom char preview
458
    /*write_char_xy( 2, 7, 200);
458
    /*write_char_xy( 2, 7, 200);
459
    write_char_xy( 3, 7, 201);
459
    write_char_xy( 3, 7, 201);
460
    write_char_xy( 4, 7, 202);
460
    write_char_xy( 4, 7, 202);
461
    write_char_xy( 5, 7, 203);
461
    write_char_xy( 5, 7, 203);
462
    write_char_xy( 6, 7, 204);
462
    write_char_xy( 6, 7, 204);
463
    write_char_xy( 7, 7, 205);
463
    write_char_xy( 7, 7, 205);
464
    write_char_xy( 8, 7, 206);
464
    write_char_xy( 8, 7, 206);
465
    write_char_xy( 9, 7, 207);
465
    write_char_xy( 9, 7, 207);
466
    write_char_xy(10, 7, 208);
466
    write_char_xy(10, 7, 208);
467
    write_char_xy(11, 7, 209);
467
    write_char_xy(11, 7, 209);
468
    write_char_xy(12, 7, 210);
468
    write_char_xy(12, 7, 210);
469
    write_char_xy(13, 7, 211);
469
    write_char_xy(13, 7, 211);
470
    write_char_xy(14, 7, 212);
470
    write_char_xy(14, 7, 212);
471
    write_char_xy(15, 7, 213);
471
    write_char_xy(15, 7, 213);
472
    write_char_xy(16, 7, 214);
472
    write_char_xy(16, 7, 214);
473
    write_char_xy(17, 7, 215);*/
473
    write_char_xy(17, 7, 215);*/
474
 
474
 
475
    // we are ready
475
    // we are ready
476
    LED3_ON
476
    LED3_ON
477
 
477
 
478
 
478
 
479
 
479
 
480
#if ALLCHARSDEBUG | (WRITECHARS != -1)
480
#if ALLCHARSDEBUG | (WRITECHARS != -1)
481
        clear();
481
        clear();
482
    write_all_chars();
482
    write_all_chars();
483
#else
483
#else
484
    // clear serial screen
484
    // clear serial screen
485
    //usart1_puts("\x1B[2J\x1B[H");
485
    //usart1_puts("\x1B[2J\x1B[H");
486
    //usart1_puts("hello world!\r\n");
486
    //usart1_puts("hello world!\r\n");
487
 
487
 
488
   
488
   
489
    // request data ever 100ms from FC
489
    // request data ever 100ms from FC
490
        //unsigned char ms = 10;
490
        //unsigned char ms = 10;
491
        //sendMKData('d', 0, &ms, 1);
491
        //sendMKData('d', 0, &ms, 1);
492
     
492
     
493
    // request OSD Data from NC every 100ms
493
    // request OSD Data from NC every 100ms
494
        unsigned char ms = 10;
494
        unsigned char ms = 10;
495
    sendMKData('o', 1, &ms, 1);
495
    sendMKData('o', 1, &ms, 1);
496
        // and disable debug...
496
        // and disable debug...
497
        //ms = 0;
497
        //ms = 0;
498
        //sendMKData('d', 0, &ms, 1);
498
        //sendMKData('d', 0, &ms, 1);
499
 
499
 
500
        // disable TXD-pin
500
        // disable TXD-pin
501
        usart1_DisableTXD();
501
        usart1_DisableTXD();
502
 
502
 
503
        // stats for after flight
503
        // stats for after flight
504
        int16_t max_Altimeter = 0;
504
        int16_t max_Altimeter = 0;
505
        uint16_t max_GroundSpeed = 0;
505
        uint16_t max_GroundSpeed = 0;
506
        int16_t max_Distance = 0;
506
        int16_t max_Distance = 0;
507
        uint8_t min_UBat = 255;
507
        uint8_t min_UBat = 255;
508
        uint16_t max_FlyingTime = 0;
508
        uint16_t max_FlyingTime = 0;
509
 
509
 
510
        // flags from last round to check for changes
510
        // flags from last round to check for changes
511
        uint8_t old_MKFlags = 0;
511
        uint8_t old_MKFlags = 0;
512
       
512
       
513
    char* directions[8] = {"NE", "E ", "SE", "S ", "SW", "W ", "NW", "N "};
513
    char* directions[8] = {"NE", "E ", "SE", "S ", "SW", "W ", "NW", "N "};
514
        char arrowdir[8] =   { 218,  217,  224,  223,  222,  221,  220, 219};
514
        char arrowdir[8] =   { 218,  217,  224,  223,  222,  221,  220, 219};
515
 
515
 
516
    while (1) {
516
    while (1) {
517
                // write icons at init or after menu/mode-switch
517
                // write icons at init or after menu/mode-switch
518
                if (!(COSD_FLAGS & COSD_ICONS_WRITTEN)) {
518
                if (!(COSD_FLAGS & COSD_ICONS_WRITTEN) && !(COSD_FLAGS & COSD_FLAG_NOOSD)) {
519
                            write_char_xy(5, top_line, 203); // km/h
519
                            write_char_xy(5, top_line, 203); // km/h
520
                            write_char_xy(10, top_line, 202); // RC-transmitter
520
                            write_char_xy(10, top_line, 202); // RC-transmitter
521
                            write_char_xy(16, top_line, 208); // degree symbol
521
                            write_char_xy(16, top_line, 208); // degree symbol
522
                            write_char_xy(27, top_line, 204); // small meters m
522
                            write_char_xy(27, top_line, 204); // small meters m
523
                            write_ascii_string(6, bottom_line, "V"); // voltage
523
                            write_ascii_string(6, bottom_line, "V"); // voltage
524
                            write_char_xy(14, bottom_line, 209); // on clock
524
                            write_char_xy(14, bottom_line, 209); // on clock
525
                            write_char_xy(22, bottom_line, 210); // fly clock
525
                            write_char_xy(22, bottom_line, 210); // fly clock
526
                            write_char_xy(26, bottom_line, 200); // sat1
526
                            write_char_xy(26, bottom_line, 200); // sat1
527
                            write_char_xy(27, bottom_line, 201); // sat2
527
                            write_char_xy(27, bottom_line, 201); // sat2
528
                                COSD_FLAGS |= COSD_ICONS_WRITTEN;
528
                                COSD_FLAGS |= COSD_ICONS_WRITTEN;
529
                }
529
                }
530
        if (rxd_buffer_locked) {
530
        if (rxd_buffer_locked) {
-
 
531
                if (!(COSD_FLAGS & COSD_FLAG_NOOSD)) {
531
            if (rxd_buffer[2] == 'D') { // FC Data
532
                    if (rxd_buffer[2] == 'D') { // FC Data
532
                /*Decode64();
533
                        /*Decode64();
533
                debugData = *((DebugOut_t*) pRxData);
534
                        debugData = *((DebugOut_t*) pRxData);
534
                write_number_s(12, 2, RxDataLen);
535
                        write_number_s(12, 2, RxDataLen);
535
                write_number_s(20, 2, setsReceived++);
536
                        write_number_s(20, 2, setsReceived++);
536
                write_number_s(12, 3, debugData.Analog[0]); // AngleNick
537
                        write_number_s(12, 3, debugData.Analog[0]); // AngleNick
537
                write_number_s(12, 4, debugData.Analog[1]); // AngleRoll
538
                        write_number_s(12, 4, debugData.Analog[1]); // AngleRoll
538
                                write_number_s(12, 5, debugData.Analog[5]); // Height
539
                                        write_number_s(12, 5, debugData.Analog[5]); // Height
539
                write_number_s(12, 6, debugData.Analog[9]); // Voltage
540
                        write_number_s(12, 6, debugData.Analog[9]); // Voltage
540
                write_number_s(12, 7, debugData.Analog[10]);// RC Signal
541
                        write_number_s(12, 7, debugData.Analog[10]);// RC Signal
541
                                write_number_s(12, 8, debugData.Analog[11]);// Gyro compass*/
542
                                        write_number_s(12, 8, debugData.Analog[11]);// Gyro compass*/
542
            } else if (rxd_buffer[2] == 'O') { // NC OSD Data
543
                    } else if (rxd_buffer[2] == 'O') { // NC OSD Data
543
                Decode64();
544
                        Decode64();
544
                naviData = *((NaviData_t*) pRxData);
545
                        naviData = *((NaviData_t*) pRxData);
545
 
546
 
546
                                // first line
547
                                        // first line
547
                                write_3digit_number_u(2, top_line, (uint16_t)(((uint32_t)naviData.GroundSpeed*36)/1000));
548
                                        write_3digit_number_u(2, top_line, (uint16_t)(((uint32_t)naviData.GroundSpeed*36)/1000));
548
 
549
 
549
                write_3digit_number_u(7, top_line, naviData.RC_Quality);
550
                        write_3digit_number_u(7, top_line, naviData.RC_Quality);
550
                if (naviData.RC_Quality <= RCLVL_WRN && last_RC_Quality > RCLVL_WRN) {
551
                        if (naviData.RC_Quality <= RCLVL_WRN && last_RC_Quality > RCLVL_WRN) {
551
                    for (uint8_t x = 0; x < 4; x++)
552
                            for (uint8_t x = 0; x < 4; x++)
552
                        write_char_att_xy(7 + x, top_line, BLINK);
553
                                write_char_att_xy(7 + x, top_line, BLINK);
553
                } else if (naviData.RC_Quality > RCLVL_WRN && last_RC_Quality <= RCLVL_WRN) {
554
                        } else if (naviData.RC_Quality > RCLVL_WRN && last_RC_Quality <= RCLVL_WRN) {
554
                    for (uint8_t x = 0; x < 4; x++)
555
                            for (uint8_t x = 0; x < 4; x++)
555
                        write_char_att_xy(7 + x, top_line, 0);
556
                                write_char_att_xy(7 + x, top_line, 0);
556
                }
557
                        }
557
                last_RC_Quality = naviData.RC_Quality;
558
                        last_RC_Quality = naviData.RC_Quality;
558
 
559
 
559
                write_3digit_number_u(13, top_line, naviData.CompassHeading);
560
                        write_3digit_number_u(13, top_line, naviData.CompassHeading);
560
 
561
 
561
                write_ascii_string(17, top_line, directions[heading_conv(naviData.CompassHeading)]);
562
                        write_ascii_string(17, top_line, directions[heading_conv(naviData.CompassHeading)]);
562
 
563
 
563
                if (naviData.Variometer == 0) {
564
                                        if (naviData.Variometer == 0) {
564
                    write_char_xy(20, top_line, 206); // plain line
565
                                                write_char_xy(20, top_line, 206); // plain line
565
                } else if (naviData.Variometer > 0 && naviData.Variometer <= 10) {
566
                                        } else if (naviData.Variometer > 0 && naviData.Variometer <= 10) {
566
                    write_char_xy(20, top_line, 234); // small arrow up
567
                                                write_char_xy(20, top_line, 234); // small arrow up
567
                } else if (naviData.Variometer > 10) {
568
                                        } else if (naviData.Variometer > 10) {
568
                    write_char_xy(20, top_line, 235); // big arrow up
569
                                                write_char_xy(20, top_line, 235); // big arrow up
569
                } else if (naviData.Variometer < 0 && naviData.Variometer >= -10) {
570
                                        } else if (naviData.Variometer < 0 && naviData.Variometer >= -10) {
570
                    write_char_xy(20, top_line, 232); // small arrow down
571
                                                write_char_xy(20, top_line, 232); // small arrow down
571
                } else {
572
                                        } else {
572
                    write_char_xy(20, top_line, 233); //big arrow down
573
                                                write_char_xy(20, top_line, 233); //big arrow down
573
                }
574
                                        }
574
 
575
 
575
                                // TODO: is this really dm?
576
                                        // TODO: is this really dm?
576
                                //note:lephisto:according to several sources it's /30
577
                                        //note:lephisto:according to several sources it's /30
-
 
578
                        //write_number_s(22, top_line, naviData.Altimeter/30);
-
 
579
                                        if (naviData.Altimeter > 300) {
-
 
580
                                                // above 10m only write full meters
-
 
581
                                                write_number_s(22, top_line, naviData.Altimeter/30);
-
 
582
                                        } else {
-
 
583
                                                // up to 10m write meters.dm
-
 
584
                                                write_number_u_10th(21, top_line, naviData.Altimeter/3);
577
                write_number_s(22, top_line, naviData.Altimeter/30);
585
                                        }
578
 
586
 
579
                                // seccond line
587
                                        // seccond line
580
                draw_compass(11, top_line + 1, naviData.CompassHeading);
588
                        draw_compass(11, top_line + 1, naviData.CompassHeading);
581
 
589
 
582
                                // TODO: verify correctness
590
                                        // TODO: verify correctness
583
                                uint16_t heading_home = (naviData.HomePositionDeviation.Bearing + 360 - naviData.CompassHeading) % 360;
591
                                        uint16_t heading_home = (naviData.HomePositionDeviation.Bearing + 360 - naviData.CompassHeading) % 360;
584
                                write_char_xy(27, top_line + 1, arrowdir[heading_conv(heading_home)]);
592
                                        write_char_xy(27, top_line + 1, arrowdir[heading_conv(heading_home)]);
-
 
593
 
-
 
594
       
-
 
595
                                        write_number_s(22, top_line + 1, naviData.HomePositionDeviation.Distance/100);
-
 
596
 
-
 
597
                                        // center
-
 
598
                                        if (naviData.MKFlags & FLAG_MOTOR_RUN) { // should be engines running
-
 
599
                                                if (!(old_MKFlags & FLAG_MOTOR_RUN)) { // motors just started, clear middle
-
 
600
                                                        clear();
-
 
601
                                                        // update flags to paint display again if needed
-
 
602
                                                        COSD_FLAGS &= ~COSD_ICONS_WRITTEN;
-
 
603
                                                }
-
 
604
                                        if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) {
-
 
605
                                                draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll);
-
 
606
                                        }
-
 
607
                                        } else {
-
 
608
                                                // stats
-
 
609
                                                write_ascii_string(2, 5, "max Altitude:");
-
 
610
                                                write_number_s(17, 5, max_Altimeter/30);
-
 
611
                                                write_char_xy(22, 5, 204); // small meters m
-
 
612
                                                write_ascii_string(2, 6, "max Speed   :");
-
 
613
                                                write_3digit_number_u(19, 6, (uint16_t)(((uint32_t)max_GroundSpeed*36)/1000));
-
 
614
                                                write_char_xy(22, 6, 203); // km/h
-
 
615
                                                write_ascii_string(2, 7, "max Distance:");
-
 
616
                                                write_number_s(17, 7, max_Distance/100);
-
 
617
                                                write_char_xy(22, 7, 204); // small meters m
-
 
618
                                                write_ascii_string(2, 8, "min voltage :");
-
 
619
                                                //write_number_s(17, 8, min_UBat/10);
-
 
620
                                                write_number_u_10th(16, 8, min_UBat);
-
 
621
                                                write_ascii_string(22, 8, "V"); // voltage
-
 
622
                                                write_ascii_string(2, 9, "max time    :");
-
 
623
                                                write_time(16, 9, max_FlyingTime);
-
 
624
                                                write_char_xy(22, 9, 210); // fly clock
-
 
625
                                        }
-
 
626
 
-
 
627
                                        // bottom line
-
 
628
                        write_number_u_10th(0, bottom_line, naviData.UBat);
-
 
629
                        if (naviData.UBat <= UBAT_WRN && last_UBat > UBAT_WRN) {
-
 
630
                            for (uint8_t x = 0; x < 7; x++)
-
 
631
                                write_char_att_xy(x, bottom_line, BLINK);
-
 
632
                        } else {
-
 
633
                            for (uint8_t x = 0; x < 7; x++)
-
 
634
                                write_char_att_xy(x, bottom_line, 0);
-
 
635
                        }
-
 
636
 
-
 
637
                        write_time(8, bottom_line, uptime);
-
 
638
                        write_time(16, bottom_line, naviData.FlyingTime);
-
 
639
 
-
 
640
                        write_3digit_number_u(23, bottom_line, naviData.SatsInUse);
-
 
641
 
-
 
642
                                        if (naviData.NCFlags & NC_FLAG_CH) {
-
 
643
                                                write_char_xy(27, bottom_line, 231);    // gps ch
-
 
644
                                        } else if (naviData.NCFlags & NC_FLAG_PH) {
-
 
645
                                                write_char_xy(27, bottom_line, 230);    // gps ph
-
 
646
                                        } else { // (naviData.NCFlags & NC_FLAG_FREE)
-
 
647
                                                write_char_xy(27, bottom_line, 201);    // sat2 (free)
-
 
648
                                        }
585
 
649
 
586
       
650
                        //write_number_s(8, 5, RxDataLen);
587
                                write_number_s(22, top_line + 1, naviData.HomePositionDeviation.Distance/100);
651
                        //write_number_s(16, 5, setsReceived++);
588
 
-
 
589
                                // center
652
 
590
                                if (naviData.MKFlags & FLAG_MOTOR_RUN) { // should be engines running
653
                                        // remember statistics
591
                                        if (!(old_MKFlags & FLAG_MOTOR_RUN)) { // motors just started, clear middle
654
                                        if (naviData.Altimeter > max_Altimeter) max_Altimeter = naviData.Altimeter;
592
                                                clear();
-
 
593
                                                // update flags to paint display again if needed
-
 
594
                                                COSD_FLAGS &= ~COSD_ICONS_WRITTEN;
-
 
595
                                        }
-
 
596
                                if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) {
-
 
597
                                        draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll);
-
 
598
                                }
-
 
599
                                } else {
-
 
600
                                        // stats
-
 
601
                                        write_ascii_string(2, 5, "max Altitude:");
-
 
602
                                        write_number_s(17, 5, max_Altimeter/10);
-
 
603
                                        write_char_xy(22, 5, 204); // small meters m
-
 
604
                                        write_ascii_string(2, 6, "max Speed   :");
-
 
605
                                        write_3digit_number_u(19, 6, (uint16_t)(((uint32_t)max_GroundSpeed*36)/1000));
-
 
606
                                        write_char_xy(22, 6, 203); // km/h
-
 
607
                                        write_ascii_string(2, 7, "max Distance:");
-
 
608
                                        write_number_s(17, 7, max_Distance/100);
-
 
609
                                        write_char_xy(22, 7, 204); // small meters m
-
 
610
                                        write_ascii_string(2, 8, "min voltage :");
-
 
611
                                        //write_number_s(17, 8, min_UBat/10);
-
 
612
                                        write_number_u_10th(16, 8, min_UBat);
-
 
613
                                        write_ascii_string(22, 8, "V"); // voltage
-
 
614
                                        write_ascii_string(2, 9, "max time    :");
-
 
615
                                        write_time(16, 9, max_FlyingTime);
-
 
616
                                        write_char_xy(22, 9, 210); // fly clock
-
 
617
                                }
-
 
618
 
-
 
619
                                // bottom line
-
 
620
                write_number_u_10th(0, bottom_line, naviData.UBat);
-
 
621
                if (naviData.UBat <= UBAT_WRN && last_UBat > UBAT_WRN) {
-
 
622
                    for (uint8_t x = 0; x < 7; x++)
-
 
623
                        write_char_att_xy(x, bottom_line, BLINK);
-
 
624
                } else {
-
 
625
                    for (uint8_t x = 0; x < 7; x++)
-
 
626
                        write_char_att_xy(x, bottom_line, 0);
-
 
627
                }
-
 
628
 
-
 
629
                write_time(8, bottom_line, uptime);
-
 
630
                write_time(16, bottom_line, naviData.FlyingTime);
-
 
631
 
-
 
632
                write_3digit_number_u(23, bottom_line, naviData.SatsInUse);
-
 
633
 
-
 
634
                                if (naviData.NCFlags & NC_FLAG_CH) {
-
 
635
                                        write_char_xy(27, bottom_line, 231);    // gps ch
-
 
636
                                } else if (naviData.NCFlags & NC_FLAG_PH) {
-
 
637
                                        write_char_xy(27, bottom_line, 230);    // gps ph
-
 
638
                                } else { // (naviData.NCFlags & NC_FLAG_FREE)
-
 
639
                                        write_char_xy(27, bottom_line, 201);    // sat2 (free)
-
 
640
                                }
-
 
641
 
-
 
642
                //write_number_s(8, 5, RxDataLen);
-
 
643
                //write_number_s(16, 5, setsReceived++);
-
 
644
 
-
 
645
                                // remember statistics
-
 
646
                                if (naviData.Altimeter > max_Altimeter) max_Altimeter = naviData.Altimeter;
-
 
647
                                if (naviData.GroundSpeed > max_GroundSpeed) max_GroundSpeed = naviData.GroundSpeed;
655
                                        if (naviData.GroundSpeed > max_GroundSpeed) max_GroundSpeed = naviData.GroundSpeed;
648
                                if (naviData.HomePositionDeviation.Distance > max_Distance) {
656
                                        if (naviData.HomePositionDeviation.Distance > max_Distance) {
649
                                        max_Distance = naviData.HomePositionDeviation.Distance;
657
                                                max_Distance = naviData.HomePositionDeviation.Distance;
650
                                }
658
                                        }
-
 
659
                                        if (naviData.UBat < min_UBat) min_UBat = naviData.UBat;
651
                                if (naviData.UBat < min_UBat) min_UBat = naviData.UBat;
660
                                        if (naviData.FlyingTime > max_FlyingTime) max_FlyingTime = naviData.FlyingTime;
652
                                if (naviData.FlyingTime > max_FlyingTime) max_FlyingTime = naviData.FlyingTime;
661
                               
653
                               
662
                                        old_MKFlags = naviData.MKFlags;
654
                                old_MKFlags = naviData.MKFlags;
663
                    } // (!(COSD_FLAGS & COSD_FLAG_NOOSD))
655
            }
664
                        }
656
                        seconds_since_last_data = 0;
665
                        seconds_since_last_data = 0;
657
            rxd_buffer_locked = 0;
666
            rxd_buffer_locked = 0;
658
        }
667
        }
659
        // handle keypress
668
        // handle keypress
660
        if (s1_pressed()) {
669
        if (s1_pressed()) {
661
                        //sendMKData('d', 1, (unsigned char*) 0, 1);
670
                        //sendMKData('d', 1, (unsigned char*) 0, 1);
662
            // request OSD Data from NC every 100ms
671
            // request OSD Data from NC every 100ms
663
                        /*unsigned char ms = 10;
672
                        /*unsigned char ms = 10;
664
            sendMKData('o', 1, &ms, 1);
673
            sendMKData('o', 1, &ms, 1);
665
            _delay_ms(500);*/
674
            _delay_ms(500);*/
666
                        config_menu();
675
                        config_menu();
667
        }
676
        }
668
                if (s2_pressed()) {
677
                if (s2_pressed()) {
669
            uptime = 0;
678
            uptime = 0;
670
            _delay_ms(100);
679
            _delay_ms(100);
671
        }
680
        }
672
                if (seconds_since_last_data > 2) {
681
                if (seconds_since_last_data > 2) {
673
                        // re-request OSD Data from NC
682
                        // re-request OSD Data from NC
674
                       
683
                       
675
                        // re-enable TXD pin
684
                        // re-enable TXD pin
676
                        usart1_EnableTXD();
685
                        usart1_EnableTXD();
677
                       
686
                       
678
                        // every 100ms
687
                        // every 100ms
679
                        unsigned char ms = 10;
688
                        unsigned char ms = 10;
680
            sendMKData('o', 1, &ms, 1);
689
            sendMKData('o', 1, &ms, 1);
681
                       
690
                       
682
                        // disable TXD pin again
691
                        // disable TXD pin again
683
                        usart1_DisableTXD();
692
                        usart1_DisableTXD();
684
 
693
 
685
                        seconds_since_last_data = 0;
694
                        seconds_since_last_data = 0;
686
                }
695
                }
687
    }
696
    }
688
#endif
697
#endif
689
    return 0;
698
    return 0;
690
}
699
}
691
 
700