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