Rev 403 | Rev 408 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 403 | Rev 404 | ||
---|---|---|---|
1 | /**************************************************************************** |
1 | /**************************************************************************** |
2 | * Copyright (C) 2009 by Claas Anders "CaScAdE" Rathje * |
2 | * Copyright (C) 2009 by Claas Anders "CaScAdE" Rathje * |
3 | * admiralcascade@gmail.com * |
3 | * admiralcascade@gmail.com * |
4 | * Project-URL: http://www.mylifesucks.de/oss/c-osd/ * |
4 | * Project-URL: http://www.mylifesucks.de/oss/c-osd/ * |
5 | * * |
5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * |
6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * |
7 | * it under the terms of the GNU General Public License as published by * |
8 | * the Free Software Foundation; either version 2 of the License. * |
8 | * the Free Software Foundation; either version 2 of the License. * |
9 | * * |
9 | * * |
10 | * This program is distributed in the hope that it will be useful, * |
10 | * This program is distributed in the hope that it will be useful, * |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
13 | * GNU General Public License for more details. * |
13 | * GNU General Public License for more details. * |
14 | * * |
14 | * * |
15 | * You should have received a copy of the GNU General Public License * |
15 | * You should have received a copy of the GNU General Public License * |
16 | * along with this program; if not, write to the * |
16 | * along with this program; if not, write to the * |
17 | * Free Software Foundation, Inc., * |
17 | * Free Software Foundation, Inc., * |
18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
19 | * * |
19 | * * |
20 | * * |
20 | * * |
21 | * Credits to: * |
21 | * Credits to: * |
22 | * Holger Buss & Ingo Busker from mikrokopter.de for the MK project * |
22 | * Holger Buss & Ingo Busker from mikrokopter.de for the MK project * |
23 | * Gregor "killagreg" Stobrawa for making the MK code readable * |
23 | * Gregor "killagreg" Stobrawa for making the MK code readable * |
24 | * Klaus "akku" Buettner for the hardware * |
24 | * Klaus "akku" Buettner for the hardware * |
25 | * Manuel "KeyOz" Schrape for explaining the MK protocol to me * |
25 | * Manuel "KeyOz" Schrape for explaining the MK protocol to me * |
26 | ****************************************************************************/ |
26 | ****************************************************************************/ |
27 | 27 | ||
28 | #include <avr/io.h> |
28 | #include <avr/io.h> |
29 | #include <avr/interrupt.h> |
29 | #include <avr/interrupt.h> |
30 | #include <util/delay.h> |
30 | #include <util/delay.h> |
31 | #include <avr/pgmspace.h> |
31 | #include <avr/pgmspace.h> |
32 | #include "main.h" |
32 | #include "main.h" |
33 | #include "max7456_software_spi.h" |
33 | #include "max7456_software_spi.h" |
34 | #include "usart1.h" |
34 | #include "usart1.h" |
35 | #include "osd_helpers.h" |
35 | #include "osd_helpers.h" |
36 | 36 | ||
37 | /* TODO: |
37 | /* TODO: |
38 | * - verifiy correctness of values |
38 | * - verifiy correctness of values |
39 | * - clean up code :) |
39 | * - clean up code :) |
40 | */ |
40 | */ |
41 | 41 | ||
42 | #if !(ALLCHARSDEBUG|(WRITECHARS != -1)) |
42 | #if !(ALLCHARSDEBUG|(WRITECHARS != -1)) |
43 | // data structs not needed for character flashin |
43 | // data structs not needed for character flashin |
44 | #include "mk-data-structs.h" |
44 | #include "mk-data-structs.h" |
45 | 45 | ||
46 | /* ########################################################################## |
46 | /* ########################################################################## |
47 | * global definitions and global vars |
47 | * global definitions and global vars |
48 | * ##########################################################################*/ |
48 | * ##########################################################################*/ |
49 | 49 | ||
50 | volatile uint16_t setsReceived = 0; |
50 | volatile uint16_t setsReceived = 0; |
51 | 51 | ||
52 | volatile NaviData_t naviData; |
52 | volatile NaviData_t naviData; |
53 | volatile DebugOut_t debugData; |
53 | volatile DebugOut_t debugData; |
54 | 54 | ||
55 | // cache old vars for blinking attribute, checkup is faster than full |
55 | // cache old vars for blinking attribute, checkup is faster than full |
56 | // attribute write each time |
56 | // attribute write each time |
57 | volatile uint8_t last_UBat = 255; |
57 | volatile uint8_t last_UBat = 255; |
58 | volatile uint8_t last_RC_Quality = 255; |
58 | volatile uint8_t last_RC_Quality = 255; |
59 | 59 | ||
60 | // 16bit should be enough, normal LiPos don't last that long |
60 | // 16bit should be enough, normal LiPos don't last that long |
61 | volatile uint16_t uptime = 0; |
61 | volatile uint16_t uptime = 0; |
62 | volatile uint16_t timer = 0; |
62 | volatile uint16_t timer = 0; |
63 | 63 | ||
64 | // remember last time data was received |
64 | // remember last time data was received |
65 | volatile uint8_t seconds_since_last_data = 0; |
65 | volatile uint8_t seconds_since_last_data = 0; |
66 | 66 | ||
67 | // store stats description in progmem to save space |
67 | // store stats description in progmem to save space |
68 | char stats_item_0[] PROGMEM = "max Altitude:"; |
68 | char stats_item_0[] PROGMEM = "max Altitude:"; |
69 | char stats_item_1[] PROGMEM = "max Speed :"; |
69 | char stats_item_1[] PROGMEM = "max Speed :"; |
70 | char stats_item_2[] PROGMEM = "max Distance:"; |
70 | char stats_item_2[] PROGMEM = "max Distance:"; |
71 | char stats_item_3[] PROGMEM = "min voltage :"; |
71 | char stats_item_3[] PROGMEM = "min voltage :"; |
72 | char stats_item_4[] PROGMEM = "max time :"; |
72 | char stats_item_4[] PROGMEM = "max time :"; |
73 | char* stats_item_pointers[] PROGMEM = {stats_item_0, stats_item_1, stats_item_2, |
73 | char* stats_item_pointers[] PROGMEM = {stats_item_0, stats_item_1, stats_item_2, |
74 | stats_item_3, stats_item_4}; |
74 | stats_item_3, stats_item_4}; |
75 | 75 | ||
76 | // store more fixed strings in progmen |
76 | // store more fixed strings in progmen |
77 | char ON[] PROGMEM = "ON "; |
77 | char ON[] PROGMEM = "ON "; |
78 | char OFF[] PROGMEM = "OFF"; |
78 | char OFF[] PROGMEM = "OFF"; |
79 | 79 | ||
80 | #endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1)) |
80 | #endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1)) |
81 | 81 | ||
82 | // general PAL|NTSC distingiusch stuff |
82 | // general PAL|NTSC distingiusch stuff |
83 | uint8_t top_line = 1; |
83 | uint8_t top_line = 1; |
84 | uint8_t bottom_line = 14; |
84 | uint8_t bottom_line = 14; |
85 | 85 | ||
86 | // Flags |
86 | // Flags |
87 | uint8_t COSD_FLAGS = 0; |
87 | uint8_t COSD_FLAGS = 0; |
88 | 88 | ||
89 | /* ########################################################################## |
89 | /* ########################################################################## |
90 | * debounce buttons |
90 | * debounce buttons |
91 | * ##########################################################################*/ |
91 | * ##########################################################################*/ |
92 | int s1_pressed() { |
92 | int s1_pressed() { |
93 | if (S1_PRESSED) { |
93 | if (S1_PRESSED) { |
94 | _delay_ms(25); |
94 | _delay_ms(25); |
95 | if (S1_PRESSED) return 1; |
95 | if (S1_PRESSED) return 1; |
96 | } |
96 | } |
97 | return 0; |
97 | return 0; |
98 | } |
98 | } |
99 | 99 | ||
100 | int s2_pressed() { |
100 | int s2_pressed() { |
101 | if (S2_PRESSED) { |
101 | if (S2_PRESSED) { |
102 | _delay_ms(25); |
102 | _delay_ms(25); |
103 | if (S2_PRESSED) return 1; |
103 | if (S2_PRESSED) return 1; |
104 | } |
104 | } |
105 | return 0; |
105 | return 0; |
106 | } |
106 | } |
107 | 107 | ||
108 | /* ########################################################################## |
108 | /* ########################################################################## |
109 | * Interrupt handler |
109 | * Interrupt handler |
110 | * ##########################################################################*/ |
110 | * ##########################################################################*/ |
111 | /** |
111 | /** |
112 | * handler for undefined Interrupts |
112 | * handler for undefined Interrupts |
113 | * if not defined AVR will reset in case any unhandled interrupts occur |
113 | * if not defined AVR will reset in case any unhandled interrupts occur |
114 | */ |
114 | */ |
115 | ISR(__vector_default) { |
115 | ISR(__vector_default) { |
116 | asm("nop"); |
116 | asm("nop"); |
117 | } |
117 | } |
118 | 118 | ||
119 | #if !(ALLCHARSDEBUG|(WRITECHARS != -1)) |
119 | #if !(ALLCHARSDEBUG|(WRITECHARS != -1)) |
120 | /* ########################################################################## |
120 | /* ########################################################################## |
121 | * timer stuff |
121 | * timer stuff |
122 | * ##########################################################################*/ |
122 | * ##########################################################################*/ |
123 | /** |
123 | /** |
124 | * timer kicks in every 1000uS ^= 1ms |
124 | * timer kicks in every 1000uS ^= 1ms |
125 | */ |
125 | */ |
126 | ISR(TIMER0_OVF_vect) { |
126 | ISR(TIMER0_OVF_vect) { |
127 | OCR0 = 15; // preload |
127 | OCR0 = 15; // preload |
128 | if (!timer--) { |
128 | if (!timer--) { |
129 | uptime++; |
129 | uptime++; |
130 | timer = 999; |
130 | timer = 999; |
131 | seconds_since_last_data++; |
131 | seconds_since_last_data++; |
132 | } |
132 | } |
133 | } |
133 | } |
134 | 134 | ||
135 | 135 | ||
136 | /* ########################################################################## |
136 | /* ########################################################################## |
137 | * A simple config menu for the flags |
137 | * A simple config menu for the flags |
138 | * ##########################################################################*/ |
138 | * ##########################################################################*/ |
139 | 139 | ||
140 | /** |
140 | /** |
141 | * helper function for menu updating |
141 | * helper function for menu updating |
142 | */ |
142 | */ |
143 | void config_menu_drawings(uint8_t chosen) { |
143 | void config_menu_drawings(uint8_t chosen) { |
144 | // clear prevoius _cursor_ |
144 | // clear prevoius _cursor_ |
145 | write_ascii_string(3, (chosen + 5) % 8, " "); |
145 | write_ascii_string(3, (chosen + 5) % 8, " "); |
146 | // draw current _cursor_ |
146 | // draw current _cursor_ |
147 | write_ascii_string(3, chosen + 5, ">"); |
147 | write_ascii_string(3, chosen + 5, ">"); |
148 | if (COSD_FLAGS & COSD_FLAG_HUD) { |
148 | if (COSD_FLAGS & COSD_FLAG_HUD) { |
149 | write_ascii_string_pgm(23, 5, ON); |
149 | write_ascii_string_pgm(23, 5, ON); |
150 | } else { |
150 | } else { |
151 | write_ascii_string_pgm(23, 5, OFF); |
151 | write_ascii_string_pgm(23, 5, OFF); |
152 | } |
152 | } |
153 | if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) { |
153 | if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) { |
154 | write_ascii_string_pgm(23, 6, ON); |
154 | write_ascii_string_pgm(23, 6, ON); |
155 | } else { |
155 | } else { |
156 | write_ascii_string_pgm(23, 6, OFF); |
156 | write_ascii_string_pgm(23, 6, OFF); |
157 | } |
157 | } |
158 | if (COSD_FLAGS & COSD_FLAG_BIGVARIO) { |
158 | if (COSD_FLAGS & COSD_FLAG_BIGVARIO) { |
159 | write_ascii_string_pgm(23, 7, ON); |
159 | write_ascii_string_pgm(23, 7, ON); |
160 | } else { |
160 | } else { |
161 | write_ascii_string_pgm(23, 7, OFF); |
161 | write_ascii_string_pgm(23, 7, OFF); |
162 | } |
162 | } |
163 | if (COSD_FLAGS & COSD_FLAG_STATS) { |
163 | if (COSD_FLAGS & COSD_FLAG_STATS) { |
164 | write_ascii_string_pgm(23, 8, ON); |
164 | write_ascii_string_pgm(23, 8, ON); |
165 | } else { |
165 | } else { |
166 | write_ascii_string_pgm(23, 8, OFF); |
166 | write_ascii_string_pgm(23, 8, OFF); |
167 | } |
167 | } |
168 | if (COSD_FLAGS & COSD_FLAG_WARNINGS) { |
168 | if (COSD_FLAGS & COSD_FLAG_WARNINGS) { |
169 | write_ascii_string_pgm(23, 9, ON); |
169 | write_ascii_string_pgm(23, 9, ON); |
170 | } else { |
170 | } else { |
171 | write_ascii_string_pgm(23, 9, OFF); |
171 | write_ascii_string_pgm(23, 9, OFF); |
172 | } |
172 | } |
173 | } |
173 | } |
174 | 174 | ||
175 | /** |
175 | /** |
176 | * some sort of clicking response in the menu |
176 | * some sort of clicking response in the menu |
177 | */ |
177 | */ |
178 | void config_menu_doclick(uint8_t chosen, char** menu) { |
178 | void config_menu_doclick(uint8_t chosen, char** menu) { |
179 | write_ascii_string(4, chosen + 5, "DONE "); |
179 | write_ascii_string(4, chosen + 5, "DONE "); |
180 | _delay_ms(1000); |
180 | _delay_ms(1000); |
181 | write_ascii_string(4, chosen + 5, menu[chosen]); |
181 | write_ascii_string(4, chosen + 5, menu[chosen]); |
182 | } |
182 | } |
183 | 183 | ||
184 | /** |
184 | /** |
185 | * a simple config menu tryout |
185 | * a simple config menu tryout |
186 | */ |
186 | */ |
187 | void config_menu(void) { |
187 | void config_menu(void) { |
188 | // disable interrupts (makes the menu more smoothely) |
188 | // disable interrupts (makes the menu more smoothely) |
189 | cli(); |
189 | cli(); |
190 | 190 | ||
191 | // clear screen |
191 | // clear screen |
192 | clear(); |
192 | clear(); |
193 | 193 | ||
194 | char* menu[9] = {"Full HUD", |
194 | char* menu[9] = {"Full HUD", |
195 | "Art.Horizon in HUD", |
195 | "Art.Horizon in HUD", |
196 | "Big Vario bar", |
196 | "Big Vario bar", |
197 | "Statistics", |
197 | "Statistics", |
198 | "Warnings", // TODO: do it! |
198 | "Warnings", // TODO: do it! |
199 | "Reset uptime", |
199 | "Reset uptime", |
200 | "Request OSD-data", |
200 | "Request OSD-data", |
201 | "Disable Debug-data", |
201 | "Disable Debug-data", |
202 | "EXIT"}; |
202 | "EXIT"}; |
203 | 203 | ||
204 | uint8_t inmenu = 1; |
204 | uint8_t inmenu = 1; |
205 | uint8_t chosen = 0; |
205 | uint8_t chosen = 0; |
206 | write_ascii_string(6, 2, "C-OSD Config Menu"); |
206 | write_ascii_string(6, 2, "C-OSD Config Menu"); |
207 | 207 | ||
208 | // wait a bit before doing stuff so user has chance to release button |
208 | // wait a bit before doing stuff so user has chance to release button |
209 | _delay_ms(250); |
209 | _delay_ms(250); |
210 | 210 | ||
211 | write_ascii_string(4, 5, menu[0]); |
211 | write_ascii_string(4, 5, menu[0]); |
212 | write_ascii_string(4, 6, menu[1]); |
212 | write_ascii_string(4, 6, menu[1]); |
213 | write_ascii_string(4, 7, menu[2]); |
213 | write_ascii_string(4, 7, menu[2]); |
214 | write_ascii_string(4, 8, menu[3]); |
214 | write_ascii_string(4, 8, menu[3]); |
215 | write_ascii_string(4, 9, menu[4]); |
215 | write_ascii_string(4, 9, menu[4]); |
216 | write_ascii_string(4, 10, menu[5]); |
216 | write_ascii_string(4, 10, menu[5]); |
217 | write_ascii_string(4, 11, menu[6]); |
217 | write_ascii_string(4, 11, menu[6]); |
218 | write_ascii_string(4, 12, menu[7]); |
218 | write_ascii_string(4, 12, menu[7]); |
219 | write_ascii_string(4, 13, menu[8]); |
219 | write_ascii_string(4, 13, menu[8]); |
220 | 220 | ||
221 | config_menu_drawings(chosen); |
221 | config_menu_drawings(chosen); |
222 | 222 | ||
223 | while (inmenu) { |
223 | while (inmenu) { |
224 | if (s2_pressed()) { |
224 | if (s2_pressed()) { |
225 | write_ascii_string(3, chosen+5, " "); |
225 | write_ascii_string(3, chosen+5, " "); |
226 | chosen = (chosen + 1) % 9; |
226 | chosen = (chosen + 1) % 9; |
227 | write_ascii_string(3, chosen+5, ">"); |
227 | write_ascii_string(3, chosen+5, ">"); |
228 | _delay_ms(500); |
228 | _delay_ms(500); |
229 | } else if (s1_pressed()) { |
229 | } else if (s1_pressed()) { |
230 | switch (chosen) { |
230 | switch (chosen) { |
231 | case 0: // full HUD |
231 | case 0: // full HUD |
232 | COSD_FLAGS ^= COSD_FLAG_HUD; |
232 | COSD_FLAGS ^= COSD_FLAG_HUD; |
233 | config_menu_drawings(chosen); |
233 | config_menu_drawings(chosen); |
234 | break; |
234 | break; |
235 | case 1: // art horizon |
235 | case 1: // art horizon |
236 | COSD_FLAGS ^= COSD_FLAG_ARTHORIZON; |
236 | COSD_FLAGS ^= COSD_FLAG_ARTHORIZON; |
237 | config_menu_drawings(chosen); |
237 | config_menu_drawings(chosen); |
238 | break; |
238 | break; |
239 | case 2: // big vario |
239 | case 2: // big vario |
240 | COSD_FLAGS ^= COSD_FLAG_BIGVARIO; |
240 | COSD_FLAGS ^= COSD_FLAG_BIGVARIO; |
241 | config_menu_drawings(chosen); |
241 | config_menu_drawings(chosen); |
242 | break; |
242 | break; |
243 | case 3: // statistics |
243 | case 3: // statistics |
244 | COSD_FLAGS ^= COSD_FLAG_STATS; |
244 | COSD_FLAGS ^= COSD_FLAG_STATS; |
245 | config_menu_drawings(chosen); |
245 | config_menu_drawings(chosen); |
246 | break; |
246 | break; |
247 | case 4: // warnings |
247 | case 4: // warnings |
248 | COSD_FLAGS ^= COSD_FLAG_WARNINGS; |
248 | COSD_FLAGS ^= COSD_FLAG_WARNINGS; |
249 | config_menu_drawings(chosen); |
249 | config_menu_drawings(chosen); |
250 | break; |
250 | break; |
251 | case 5: // reset uptime |
251 | case 5: // reset uptime |
252 | uptime = 0; |
252 | uptime = 0; |
253 | config_menu_doclick(chosen, menu); |
253 | config_menu_doclick(chosen, menu); |
254 | break; |
254 | break; |
255 | case 6: // re-request OSD data |
255 | case 6: // re-request OSD data |
256 | // request OSD Data from NC every 100ms |
256 | // request OSD Data from NC every 100ms |
257 | usart1_request_mk_data(1, 'o', 100); |
257 | usart1_request_mk_data(1, 'o', 100); |
258 | config_menu_doclick(chosen, menu); |
258 | config_menu_doclick(chosen, menu); |
259 | break; |
259 | break; |
260 | case 7: // disable debug data |
260 | case 7: // disable debug data |
261 | // disable sending of debug data |
261 | // disable sending of debug data |
262 | // may result in smoother ddata display |
262 | // may result in smoother ddata display |
263 | usart1_request_mk_data(0, 'd', 0); |
263 | usart1_request_mk_data(0, 'd', 0); |
264 | config_menu_doclick(chosen, menu); |
264 | config_menu_doclick(chosen, menu); |
265 | break; |
265 | break; |
266 | case 8: // exit |
266 | case 8: // exit |
267 | inmenu = 0; |
267 | inmenu = 0; |
268 | break; |
268 | break; |
269 | } |
269 | } |
270 | _delay_ms(250); |
270 | _delay_ms(250); |
271 | } |
271 | } |
272 | } |
272 | } |
273 | 273 | ||
274 | // clear screen up again |
274 | // clear screen up again |
275 | clear(); |
275 | clear(); |
276 | 276 | ||
277 | // update flags to paint display again if needed |
277 | // update flags to paint display again if needed |
278 | COSD_FLAGS &= ~COSD_ICONS_WRITTEN; |
278 | COSD_FLAGS &= ~COSD_ICONS_WRITTEN; |
279 | 279 | ||
280 | // enable interrupts again |
280 | // enable interrupts again |
281 | sei(); |
281 | sei(); |
282 | } |
282 | } |
283 | 283 | ||
284 | #endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1)) |
284 | #endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1)) |
285 | /* ########################################################################## |
285 | /* ########################################################################## |
286 | * MAIN |
286 | * MAIN |
287 | * ##########################################################################*/ |
287 | * ##########################################################################*/ |
288 | int main(void) { |
288 | int main(void) { |
289 | // set up FLAGS, compiler should flatten this one |
289 | // set up FLAGS, compiler should flatten this one |
290 | COSD_FLAGS = (NTSC << 0); |
290 | COSD_FLAGS = (NTSC << 0); |
291 | COSD_FLAGS |= (HUD << 1); |
291 | COSD_FLAGS |= (HUD << 1); |
292 | COSD_FLAGS |= (ARTHORIZON << 2); |
292 | COSD_FLAGS |= (ARTHORIZON << 2); |
293 | COSD_FLAGS |= (BIGVARIO << 3); |
293 | COSD_FLAGS |= (BIGVARIO << 3); |
294 | COSD_FLAGS |= (STATS << 4); |
294 | COSD_FLAGS |= (STATS << 4); |
295 | COSD_FLAGS |= (WARNINGS << 5); |
295 | COSD_FLAGS |= (WARNINGS << 5); |
296 | 296 | ||
297 | // set up Atmega162 Ports |
297 | // set up Atmega162 Ports |
298 | DDRA |= (1 << PA1); // PA1 output (/CS) |
298 | DDRA |= (1 << PA1); // PA1 output (/CS) |
299 | MAX_CS_HIGH |
299 | MAX_CS_HIGH |
300 | DDRA |= (1 << PA2); // PA2 output (SDIN) |
300 | DDRA |= (1 << PA2); // PA2 output (SDIN) |
301 | MAX_SDIN_LOW |
301 | MAX_SDIN_LOW |
302 | DDRA |= (1 << PA3); // PA3 output (SCLK) |
302 | DDRA |= (1 << PA3); // PA3 output (SCLK) |
303 | MAX_SCLK_LOW |
303 | MAX_SCLK_LOW |
304 | DDRA |= (1 << PA5); // PA5 output (RESET) |
304 | DDRA |= (1 << PA5); // PA5 output (RESET) |
305 | MAX_RESET_HIGH |
305 | MAX_RESET_HIGH |
306 | 306 | ||
307 | DDRC |= (1 << PC0); // PC0 output (LED1 gn) |
307 | DDRC |= (1 << PC0); // PC0 output (LED1 gn) |
308 | LED1_OFF |
308 | LED1_OFF |
309 | DDRC |= (1 << PC1); // PC1 output (LED2 rt) |
309 | DDRC |= (1 << PC1); // PC1 output (LED2 rt) |
310 | LED2_OFF |
310 | LED2_OFF |
311 | DDRC |= (1 << PC2); // PC2 output (LED3 gn) |
311 | DDRC |= (1 << PC2); // PC2 output (LED3 gn) |
312 | LED3_OFF |
312 | LED3_OFF |
313 | DDRC |= (1 << PC3); // PC3 output (LED4 rt) |
313 | DDRC |= (1 << PC3); // PC3 output (LED4 rt) |
314 | LED4_OFF |
314 | LED4_OFF |
315 | 315 | ||
316 | DDRC &= ~(1 << PC4); // PC4 input (MODE) |
316 | DDRC &= ~(1 << PC4); // PC4 input (MODE) |
317 | PORTC |= (1 << PC4); // pullup |
317 | PORTC |= (1 << PC4); // pullup |
318 | DDRC &= ~(1 << PC5); // PC5 input (SET) |
318 | DDRC &= ~(1 << PC5); // PC5 input (SET) |
319 | PORTC |= (1 << PC5); // pullup |
319 | PORTC |= (1 << PC5); // pullup |
320 | 320 | ||
321 | // set up top and bottom lines |
321 | // set up top and bottom lines |
322 | if (COSD_FLAGS & COSD_FLAG_NTSC) { |
322 | if (COSD_FLAGS & COSD_FLAG_NTSC) { |
323 | bottom_line = 12; |
323 | bottom_line = 12; |
324 | } else { |
324 | } else { |
325 | bottom_line = 14; |
325 | bottom_line = 14; |
326 | } |
326 | } |
327 | 327 | ||
328 | // reset the MAX7456 to be sure any undefined states do no harm |
328 | // reset the MAX7456 to be sure any undefined states do no harm |
329 | MAX_RESET_LOW |
329 | MAX_RESET_LOW |
330 | MAX_RESET_HIGH |
330 | MAX_RESET_HIGH |
331 | 331 | ||
332 | // give the FC/NC and the maxim time to come up |
332 | // give the FC/NC and the maxim time to come up |
333 | LED4_ON |
333 | LED4_ON |
334 | _delay_ms(2000); |
334 | _delay_ms(2000); |
335 | 335 | ||
336 | LED4_OFF |
336 | LED4_OFF |
337 | 337 | ||
338 | 338 | ||
339 | //Pushing NEW chars to the MAX7456 |
339 | //Pushing NEW chars to the MAX7456 |
340 | #if (WRITECHARS != -1) |
340 | #if (WRITECHARS != -1) |
341 | // DISABLE display (VM0) |
341 | // DISABLE display (VM0) |
342 | spi_send_byte(0x00, 0b00000000); |
342 | spi_send_byte(0x00, 0b00000000); |
343 | #include "characters.c" |
343 | #include "characters.c" |
344 | 344 | ||
345 | #endif |
345 | #endif |
346 | 346 | ||
347 | // Setup Video Mode |
347 | // Setup Video Mode |
348 | if (COSD_FLAGS & COSD_FLAG_NTSC) { |
348 | if (COSD_FLAGS & COSD_FLAG_NTSC) { |
349 | // NTSC + enable display immediately (VM0) |
349 | // NTSC + enable display immediately (VM0) |
350 | spi_send_byte(0x00, 0b00001000); |
350 | spi_send_byte(0x00, 0b00001000); |
351 | } else { |
351 | } else { |
352 | // PAL + enable display immediately (VM0) |
352 | // PAL + enable display immediately (VM0) |
353 | spi_send_byte(0x00, 0b01001000); |
353 | spi_send_byte(0x00, 0b01001000); |
354 | } |
354 | } |
355 | 355 | ||
356 | // clear all display-mem (DMM) |
356 | /*// clear all display-mem (DMM) |
357 | spi_send_byte(0x04, 0b00000100); |
357 | spi_send_byte(0x04, 0b00000100); |
358 | 358 | ||
359 | // clearing takes 12uS according to maxim so lets wait longer |
359 | // clearing takes 12uS according to maxim so lets wait longer |
360 | _delay_us(120); |
360 | _delay_us(120); |
361 | 361 | ||
362 | // 8bit mode |
362 | // 8bit mode |
363 | spi_send_byte(0x04, 0b01000000); |
363 | spi_send_byte(0x04, 0b01000000);*/ |
364 | 364 | ||
365 | // write blank chars to whole screen |
365 | // clear display memory and set to 8bit mode |
366 | clear(); |
366 | clear(); |
367 | 367 | ||
368 | #if !(ALLCHARSDEBUG|(WRITECHARS != -1)) |
368 | #if !(ALLCHARSDEBUG|(WRITECHARS != -1)) |
369 | // init usart |
369 | // init usart |
370 | usart1_init(); |
370 | usart1_init(); |
371 | 371 | ||
372 | // set up timer |
372 | // set up timer |
373 | TCCR0 |= (1 << CS00) | (1 << CS01); // timer0 prescaler 64 |
373 | TCCR0 |= (1 << CS00) | (1 << CS01); // timer0 prescaler 64 |
374 | OCR0 = 15; // preload |
374 | OCR0 = 15; // preload |
375 | TIMSK |= (1 << TOIE0); // enable overflow timer0 |
375 | TIMSK |= (1 << TOIE0); // enable overflow timer0 |
376 | 376 | ||
377 | // enable interrupts |
377 | // enable interrupts |
378 | sei(); |
378 | sei(); |
379 | #endif |
379 | #endif |
380 | 380 | ||
381 | //write_ascii_string(2, 7, " CaScAdE "); |
381 | //write_ascii_string(2, 7, " CaScAdE "); |
382 | //write_ascii_string(2, 8, "is TESTING his open source"); |
382 | //write_ascii_string(2, 8, "is TESTING his open source"); |
383 | //write_ascii_string(2, 9, " EPi OSD Firmware"); |
383 | //write_ascii_string(2, 9, " EPi OSD Firmware"); |
384 | 384 | ||
385 | // we are ready |
385 | // we are ready |
386 | LED3_ON |
386 | LED3_ON |
387 | 387 | ||
388 | #if ALLCHARSDEBUG | (WRITECHARS != -1) |
388 | #if ALLCHARSDEBUG | (WRITECHARS != -1) |
389 | clear(); |
389 | clear(); |
390 | write_all_chars(); |
390 | write_all_chars(); |
391 | #else |
391 | #else |
392 | // clear serial screen |
392 | // clear serial screen |
393 | //usart1_puts("\x1B[2J\x1B[H"); |
393 | //usart1_puts("\x1B[2J\x1B[H"); |
394 | //usart1_puts("hello world!\r\n"); |
394 | //usart1_puts("hello world!\r\n"); |
395 | 395 | ||
396 | 396 | ||
397 | // request data ever 100ms from FC; |
397 | // request data ever 100ms from FC; |
398 | //usart1_request_mk_data(0, 'd', 100); |
398 | //usart1_request_mk_data(0, 'd', 100); |
399 | 399 | ||
400 | // request OSD Data from NC every 100ms |
400 | // request OSD Data from NC every 100ms |
401 | usart1_request_mk_data(1, 'o', 100); |
401 | usart1_request_mk_data(1, 'o', 100); |
402 | 402 | ||
403 | // and disable debug... |
403 | // and disable debug... |
404 | usart1_request_mk_data(0, 'd', 0); |
404 | usart1_request_mk_data(0, 'd', 0); |
405 | 405 | ||
406 | // stats for after flight |
406 | // stats for after flight |
407 | int16_t max_Altimeter = 0; |
407 | int16_t max_Altimeter = 0; |
408 | uint16_t max_GroundSpeed = 0; |
408 | uint16_t max_GroundSpeed = 0; |
409 | int16_t max_Distance = 0; |
409 | int16_t max_Distance = 0; |
410 | uint8_t min_UBat = 255; |
410 | uint8_t min_UBat = 255; |
411 | uint16_t max_FlyingTime = 0; |
411 | uint16_t max_FlyingTime = 0; |
412 | 412 | ||
413 | // flags from last round to check for changes |
413 | // flags from last round to check for changes |
414 | uint8_t old_MKFlags = 0; |
414 | uint8_t old_MKFlags = 0; |
415 | 415 | ||
416 | char* directions[8] = {"NE", "E ", "SE", "S ", "SW", "W ", "NW", "N "}; |
416 | char* directions[8] = {"NE", "E ", "SE", "S ", "SW", "W ", "NW", "N "}; |
417 | //char arrowdir[8] = {218, 217, 224, 223, 222, 221, 220, 219}; |
417 | //char arrowdir[8] = {218, 217, 224, 223, 222, 221, 220, 219}; |
418 | 418 | ||
419 | while (1) { |
419 | while (1) { |
420 | // write icons at init or after menu/mode-switch |
420 | // write icons at init or after menu/mode-switch |
421 | if (!(COSD_FLAGS & COSD_ICONS_WRITTEN) && (COSD_FLAGS & COSD_FLAG_HUD)) { |
421 | if (!(COSD_FLAGS & COSD_ICONS_WRITTEN) && (COSD_FLAGS & COSD_FLAG_HUD)) { |
422 | write_char_xy(5, top_line, 0xCB); // km/h |
422 | write_char_xy(5, top_line, 0xCB); // km/h |
423 | write_char_xy(10, top_line, 0xCA); // RC-transmitter |
423 | write_char_xy(10, top_line, 0xCA); // RC-transmitter |
424 | write_char_xy(16, top_line, 0xD0); // degree symbol |
424 | write_char_xy(16, top_line, 0xD0); // degree symbol |
425 | write_char_xy(27, top_line, 0xCC); // small meters m height |
425 | write_char_xy(27, top_line, 0xCC); // small meters m height |
426 | write_char_xy(20, top_line+1, 0xB0); // left circle |
426 | write_char_xy(20, top_line+1, 0xB0); // left circle |
427 | write_char_xy(22, top_line+1, 0xB2); // right circle |
427 | write_char_xy(22, top_line+1, 0xB2); // right circle |
428 | write_char_xy(27, top_line+1, 0xCC); // small meters m home |
428 | write_char_xy(27, top_line+1, 0xCC); // small meters m home |
429 | write_char_xy(7, bottom_line, 0x9E); // small v |
429 | write_char_xy(7, bottom_line, 0x9E); // small v |
430 | write_char_xy(14, bottom_line, 0xD1); // on clock |
430 | write_char_xy(14, bottom_line, 0xD1); // on clock |
431 | write_char_xy(22, bottom_line, 0xD2); // fly clock |
431 | write_char_xy(22, bottom_line, 0xD2); // fly clock |
432 | write_char_xy(26, bottom_line, 0xC8); // sat1 |
432 | write_char_xy(26, bottom_line, 0xC8); // sat1 |
433 | write_char_xy(27, bottom_line, 0xC9); // sat2 |
433 | write_char_xy(27, bottom_line, 0xC9); // sat2 |
434 | COSD_FLAGS |= COSD_ICONS_WRITTEN; |
434 | COSD_FLAGS |= COSD_ICONS_WRITTEN; |
435 | } |
435 | } |
436 | if (rxd_buffer_locked) { |
436 | if (rxd_buffer_locked) { |
437 | if (COSD_FLAGS & COSD_FLAG_HUD) { |
437 | if (COSD_FLAGS & COSD_FLAG_HUD) { |
438 | if (rxd_buffer[2] == 'D') { // FC Data |
438 | if (rxd_buffer[2] == 'D') { // FC Data |
439 | /*Decode64(); |
439 | /*Decode64(); |
440 | debugData = *((DebugOut_t*) pRxData); |
440 | debugData = *((DebugOut_t*) pRxData); |
441 | write_number_s(12, 2, RxDataLen); |
441 | write_number_s(12, 2, RxDataLen); |
442 | write_number_s(20, 2, setsReceived++); |
442 | write_number_s(20, 2, setsReceived++); |
443 | write_number_s(12, 3, debugData.Analog[0]); // AngleNick |
443 | write_number_s(12, 3, debugData.Analog[0]); // AngleNick |
444 | write_number_s(12, 4, debugData.Analog[1]); // AngleRoll |
444 | write_number_s(12, 4, debugData.Analog[1]); // AngleRoll |
445 | write_number_s(12, 5, debugData.Analog[5]); // Height |
445 | write_number_s(12, 5, debugData.Analog[5]); // Height |
446 | write_number_s(12, 6, debugData.Analog[9]); // Voltage |
446 | write_number_s(12, 6, debugData.Analog[9]); // Voltage |
447 | write_number_s(12, 7, debugData.Analog[10]);// RC Signal |
447 | write_number_s(12, 7, debugData.Analog[10]);// RC Signal |
448 | write_number_s(12, 8, debugData.Analog[11]);// Gyro compass |
448 | write_number_s(12, 8, debugData.Analog[11]);// Gyro compass |
449 | seconds_since_last_data = 0;*/ |
449 | seconds_since_last_data = 0;*/ |
450 | } else if (rxd_buffer[2] == 'O') { // NC OSD Data |
450 | } else if (rxd_buffer[2] == 'O') { // NC OSD Data |
451 | Decode64(); |
451 | Decode64(); |
452 | naviData = *((NaviData_t*) pRxData); |
452 | naviData = *((NaviData_t*) pRxData); |
453 | 453 | ||
454 | // first line |
454 | // first line |
455 | write_ndigit_number_u(2, top_line, (uint16_t) (((uint32_t) naviData.GroundSpeed * (uint32_t)9) / (uint32_t)250), 100, 0); |
455 | write_ndigit_number_u(2, top_line, (uint16_t) (((uint32_t) naviData.GroundSpeed * (uint32_t)9) / (uint32_t)250), 100, 0); |
456 | 456 | ||
457 | write_ndigit_number_u(7, top_line, naviData.RC_Quality, 100, 0); |
457 | write_ndigit_number_u(7, top_line, naviData.RC_Quality, 100, 0); |
458 | if (naviData.RC_Quality <= RCLVL_WRN && last_RC_Quality > RCLVL_WRN) { |
458 | if (naviData.RC_Quality <= RCLVL_WRN && last_RC_Quality > RCLVL_WRN) { |
459 | for (uint8_t x = 0; x < 4; x++) |
459 | for (uint8_t x = 0; x < 4; x++) |
460 | write_char_att_xy(7 + x, top_line, BLINK); |
460 | write_char_att_xy(7 + x, top_line, BLINK); |
461 | } else if (naviData.RC_Quality > RCLVL_WRN && last_RC_Quality <= RCLVL_WRN) { |
461 | } else if (naviData.RC_Quality > RCLVL_WRN && last_RC_Quality <= RCLVL_WRN) { |
462 | for (uint8_t x = 0; x < 4; x++) |
462 | for (uint8_t x = 0; x < 4; x++) |
463 | write_char_att_xy(7 + x, top_line, 0); |
463 | write_char_att_xy(7 + x, top_line, 0); |
464 | } |
464 | } |
465 | last_RC_Quality = naviData.RC_Quality; |
465 | last_RC_Quality = naviData.RC_Quality; |
466 | 466 | ||
467 | write_ndigit_number_u(13, top_line, naviData.CompassHeading, 100, 0); |
467 | write_ndigit_number_u(13, top_line, naviData.CompassHeading, 100, 0); |
468 | 468 | ||
469 | write_ascii_string(17, top_line, directions[heading_conv(naviData.CompassHeading)]); |
469 | write_ascii_string(17, top_line, directions[heading_conv(naviData.CompassHeading)]); |
470 | 470 | ||
471 | draw_variometer(21, top_line, naviData.Variometer); |
471 | draw_variometer(21, top_line, naviData.Variometer); |
472 | 472 | ||
473 | //note:lephisto:according to several sources it's /30 |
473 | //note:lephisto:according to several sources it's /30 |
474 | if (naviData.Altimeter > 300 || naviData.Altimeter < -300) { |
474 | if (naviData.Altimeter > 300 || naviData.Altimeter < -300) { |
475 | // above 10m only write full meters |
475 | // above 10m only write full meters |
476 | write_ndigit_number_s(23, top_line, naviData.Altimeter / 30, 1000, 0); |
476 | write_ndigit_number_s(23, top_line, naviData.Altimeter / 30, 1000, 0); |
477 | } else { |
477 | } else { |
478 | // up to 10m write meters.dm |
478 | // up to 10m write meters.dm |
479 | //write_number_u_10th(21, top_line, naviData.Altimeter / 3); |
479 | //write_number_u_10th(21, top_line, naviData.Altimeter / 3); |
480 | write_ndigit_number_s_10th(23, top_line, naviData.Altimeter / 3, 100, 0); |
480 | write_ndigit_number_s_10th(23, top_line, naviData.Altimeter / 3, 100, 0); |
481 | } |
481 | } |
482 | 482 | ||
483 | // seccond line |
483 | // seccond line |
484 | draw_compass(11, top_line + 1, naviData.CompassHeading); |
484 | draw_compass(11, top_line + 1, naviData.CompassHeading); |
485 | 485 | ||
486 | // TODO: verify correctness |
486 | // TODO: verify correctness |
487 | uint16_t heading_home = (naviData.HomePositionDeviation.Bearing + 360 - naviData.CompassHeading) % 360; |
487 | uint16_t heading_home = (naviData.HomePositionDeviation.Bearing + 360 - naviData.CompassHeading) % 360; |
488 | //write_char_xy(21, top_line + 1, arrowdir[heading_conv(heading_home)]); |
488 | //write_char_xy(21, top_line + 1, arrowdir[heading_conv(heading_home)]); |
489 | // finer resolution, 0xa0 is first character and we add the index 0 <= index < 16 |
489 | // finer resolution, 0xa0 is first character and we add the index 0 <= index < 16 |
490 | write_char_xy(21, top_line + 1, 0xa0 + heading_fine_conv(heading_home)); |
490 | write_char_xy(21, top_line + 1, 0xa0 + heading_fine_conv(heading_home)); |
491 | 491 | ||
492 | write_ndigit_number_u(24, top_line + 1, naviData.HomePositionDeviation.Distance / 10, 100, 0); |
492 | write_ndigit_number_u(24, top_line + 1, naviData.HomePositionDeviation.Distance / 10, 100, 0); |
493 | 493 | ||
494 | // center |
494 | // center |
495 | if (naviData.MKFlags & FLAG_MOTOR_RUN) { // should be engines running |
495 | if (naviData.MKFlags & FLAG_MOTOR_RUN) { // should be engines running |
496 | if (!(old_MKFlags & FLAG_MOTOR_RUN)) { // motors just started, clear middle |
496 | if (!(old_MKFlags & FLAG_MOTOR_RUN)) { // motors just started, clear middle |
497 | clear(); |
497 | clear(); |
498 | // update flags to paint display again if needed |
498 | // update flags to paint display again if needed |
499 | COSD_FLAGS &= ~COSD_ICONS_WRITTEN; |
499 | COSD_FLAGS &= ~COSD_ICONS_WRITTEN; |
500 | } |
500 | } |
501 | if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) { |
501 | if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) { |
502 | draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll); |
502 | draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll); |
503 | } |
503 | } |
504 | } else { |
504 | } else { |
505 | // stats |
505 | // stats |
506 | if (COSD_FLAGS & COSD_FLAG_STATS) { |
506 | if (COSD_FLAGS & COSD_FLAG_STATS) { |
507 | write_ascii_string_pgm(2, 5, stats_item_pointers[0]); // max Altitude |
507 | write_ascii_string_pgm(2, 5, stats_item_pointers[0]); // max Altitude |
508 | write_ndigit_number_s(18, 5, max_Altimeter / 30, 1000, 0); |
508 | write_ndigit_number_s(18, 5, max_Altimeter / 30, 1000, 0); |
509 | write_char_xy(22, 5, 204); // small meters m |
509 | write_char_xy(22, 5, 204); // small meters m |
510 | write_ascii_string_pgm(2, 6, stats_item_pointers[1]); // max Speed |
510 | write_ascii_string_pgm(2, 6, stats_item_pointers[1]); // max Speed |
511 | write_ndigit_number_u(19, 6, (uint16_t) (((uint32_t) max_GroundSpeed * (uint32_t)9) / (uint32_t)250), 100, 0); |
511 | write_ndigit_number_u(19, 6, (uint16_t) (((uint32_t) max_GroundSpeed * (uint32_t)9) / (uint32_t)250), 100, 0); |
512 | write_char_xy(22, 6, 203); // km/h |
512 | write_char_xy(22, 6, 203); // km/h |
513 | write_ascii_string_pgm(2, 7, stats_item_pointers[2]); // max Distance |
513 | write_ascii_string_pgm(2, 7, stats_item_pointers[2]); // max Distance |
514 | write_ndigit_number_u(19, 7, max_Distance / 100, 100, 0); |
514 | write_ndigit_number_u(19, 7, max_Distance / 100, 100, 0); |
515 | write_char_xy(22, 7, 204); // small meters m |
515 | write_char_xy(22, 7, 204); // small meters m |
516 | write_ascii_string_pgm(2, 8, stats_item_pointers[3]); // min voltage |
516 | write_ascii_string_pgm(2, 8, stats_item_pointers[3]); // min voltage |
517 | write_ndigit_number_u_10th(18, 8, min_UBat, 100, 0); |
517 | write_ndigit_number_u_10th(18, 8, min_UBat, 100, 0); |
518 | write_char_xy(22, 8, 0x9E); // small v |
518 | write_char_xy(22, 8, 0x9E); // small v |
519 | write_ascii_string_pgm(2, 9, stats_item_pointers[4]); // max time |
519 | write_ascii_string_pgm(2, 9, stats_item_pointers[4]); // max time |
520 | write_time(16, 9, max_FlyingTime); |
520 | write_time(16, 9, max_FlyingTime); |
521 | write_char_xy(22, 9, 210); // fly clock |
521 | write_char_xy(22, 9, 210); // fly clock |
522 | } else if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) { // if no stats there is space horizon |
522 | } else if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) { // if no stats there is space horizon |
523 | draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll); |
523 | draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll); |
524 | } |
524 | } |
525 | } |
525 | } |
526 | if (COSD_FLAGS & COSD_FLAG_BIGVARIO) { |
526 | if (COSD_FLAGS & COSD_FLAG_BIGVARIO) { |
527 | draw_big_variometer(27, 8, naviData.Variometer); |
527 | draw_big_variometer(27, 8, naviData.Variometer); |
528 | } |
528 | } |
529 | 529 | ||
530 | // bottom line |
530 | // bottom line |
531 | draw_battery(2, bottom_line, naviData.UBat); |
531 | draw_battery(2, bottom_line, naviData.UBat); |
532 | write_ndigit_number_u_10th(3, bottom_line, naviData.UBat, 100, 0); |
532 | write_ndigit_number_u_10th(3, bottom_line, naviData.UBat, 100, 0); |
533 | if (naviData.UBat <= UBAT_WRN && last_UBat > UBAT_WRN) { |
533 | if (naviData.UBat <= UBAT_WRN && last_UBat > UBAT_WRN) { |
534 | for (uint8_t x = 2; x < 8; x++) |
534 | for (uint8_t x = 2; x < 8; x++) |
535 | write_char_att_xy(x, bottom_line, BLINK); |
535 | write_char_att_xy(x, bottom_line, BLINK); |
536 | } else { |
536 | } else { |
537 | for (uint8_t x = 2; x < 8; x++) |
537 | for (uint8_t x = 2; x < 8; x++) |
538 | write_char_att_xy(x, bottom_line, 0); |
538 | write_char_att_xy(x, bottom_line, 0); |
539 | } |
539 | } |
540 | 540 | ||
541 | 541 | ||
542 | write_time(8, bottom_line, uptime); |
542 | write_time(8, bottom_line, uptime); |
543 | write_time(16, bottom_line, naviData.FlyingTime); |
543 | write_time(16, bottom_line, naviData.FlyingTime); |
544 | 544 | ||
545 | write_ndigit_number_u(24, bottom_line, naviData.SatsInUse, 10, 0); |
545 | write_ndigit_number_u(24, bottom_line, naviData.SatsInUse, 10, 0); |
546 | 546 | ||
547 | if (naviData.NCFlags & NC_FLAG_CH) { |
547 | if (naviData.NCFlags & NC_FLAG_CH) { |
548 | write_char_xy(27, bottom_line, 231); // gps ch |
548 | write_char_xy(27, bottom_line, 231); // gps ch |
549 | } else if (naviData.NCFlags & NC_FLAG_PH) { |
549 | } else if (naviData.NCFlags & NC_FLAG_PH) { |
550 | write_char_xy(27, bottom_line, 230); // gps ph |
550 | write_char_xy(27, bottom_line, 230); // gps ph |
551 | } else { // (naviData.NCFlags & NC_FLAG_FREE) |
551 | } else { // (naviData.NCFlags & NC_FLAG_FREE) |
552 | write_char_xy(27, bottom_line, 201); // sat2 (free) |
552 | write_char_xy(27, bottom_line, 201); // sat2 (free) |
553 | } |
553 | } |
554 | 554 | ||
555 | //write_number_s(8, 5, RxDataLen); |
555 | //write_number_s(8, 5, RxDataLen); |
556 | //write_number_s(16, 5, setsReceived++); |
556 | //write_number_s(16, 5, setsReceived++); |
557 | 557 | ||
558 | // remember statistics |
558 | // remember statistics |
559 | if (naviData.Altimeter > max_Altimeter) max_Altimeter = naviData.Altimeter; |
559 | if (naviData.Altimeter > max_Altimeter) max_Altimeter = naviData.Altimeter; |
560 | if (naviData.GroundSpeed > max_GroundSpeed) max_GroundSpeed = naviData.GroundSpeed; |
560 | if (naviData.GroundSpeed > max_GroundSpeed) max_GroundSpeed = naviData.GroundSpeed; |
561 | if (naviData.HomePositionDeviation.Distance > max_Distance) { |
561 | if (naviData.HomePositionDeviation.Distance > max_Distance) { |
562 | max_Distance = naviData.HomePositionDeviation.Distance; |
562 | max_Distance = naviData.HomePositionDeviation.Distance; |
563 | } |
563 | } |
564 | if (naviData.UBat < min_UBat) min_UBat = naviData.UBat; |
564 | if (naviData.UBat < min_UBat) min_UBat = naviData.UBat; |
565 | if (naviData.FlyingTime > max_FlyingTime) max_FlyingTime = naviData.FlyingTime; |
565 | if (naviData.FlyingTime > max_FlyingTime) max_FlyingTime = naviData.FlyingTime; |
566 | 566 | ||
567 | old_MKFlags = naviData.MKFlags; |
567 | old_MKFlags = naviData.MKFlags; |
568 | seconds_since_last_data = 0; |
568 | seconds_since_last_data = 0; |
569 | } |
569 | } |
570 | } |
570 | } |
571 | rxd_buffer_locked = 0; |
571 | rxd_buffer_locked = 0; |
572 | } |
572 | } |
573 | // handle keypress |
573 | // handle keypress |
574 | if (s1_pressed()) { |
574 | if (s1_pressed()) { |
575 | config_menu(); |
575 | config_menu(); |
576 | } |
576 | } |
577 | if (seconds_since_last_data > 2) { |
577 | if (seconds_since_last_data > 2) { |
578 | // request OSD Data from NC every 100ms |
578 | // request OSD Data from NC every 100ms |
579 | usart1_request_mk_data(1, 'o', 100); |
579 | usart1_request_mk_data(1, 'o', 100); |
580 | seconds_since_last_data = 0; |
580 | seconds_since_last_data = 0; |
581 | } |
581 | } |
582 | } |
582 | } |
583 | #endif |
583 | #endif |
584 | return 0; |
584 | return 0; |
585 | } |
585 | } |
586 | 586 |