Subversion Repositories Projects

Rev

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

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