Subversion Repositories Projects

Rev

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

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