Subversion Repositories Projects

Rev

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

Rev 321 Rev 324
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
 
31
 
32
/* TODO:
32
/* TODO:
33
 * - verifiy correctness of values
33
 * - verifiy correctness of values
-
 
34
 * - clean up code :)
34
 */
35
 */
35
 
36
 
36
/* ##########################################################################
37
/* ##########################################################################
37
 * Debugging and general purpose definitions
38
 * Debugging and general purpose definitions
38
 * ##########################################################################*/
39
 * ##########################################################################*/
39
#define ALLCHARSDEBUG 0         // set to 1 and flash firmware to see all chars
40
#define ALLCHARSDEBUG 0         // set to 1 and flash firmware to see all chars
40
#define WRITECHARS 0            // set to 1 and flash firmware to write new char
41
#define WRITECHARS 224          // set to 2XX and flash firmware to write new char
41
                                                        // enables the allchars as well to see results
42
                                                        // enables the allchars as well to see results
42
#define NTSC 0                          // set to 1 for NTSC mode + lifts the bottom line
43
#define NTSC 0                          // set to 1 for NTSC mode + lifts the bottom line
43
#define ARTHORIZON 0            // set to 1 to enable roll&nick artificial horizon
44
#define ARTHORIZON 0            // set to 1 to enable roll&nick artificial horizon
-
 
45
#define NOOSD 0                         // set to 1 to disable OSD completely
-
 
46
#define NOOSD_BUT_WRN 0         // set to 1 to disable OSD completely but show 
-
 
47
                                                        // battery and receive signal warnings
44
#define UBAT_WRN 94                     // voltage for blinking warning, like FC settings
48
#define UBAT_WRN 94                     // voltage for blinking warning, like FC settings
45
#define RCLVL_WRN 100           // make the RC level blink if below this number
49
#define RCLVL_WRN 100           // make the RC level blink if below this number
46
 
50
 
47
// ### read datasheet before changing stuff below this line :)
51
// ### read datasheet before changing stuff below this line :)
48
#define BLINK   0b01001111      // attribute byte for blinking chars
52
#define BLINK   0b01001111      // attribute byte for blinking chars
49
 
53
 
50
/* ##########################################################################
54
/* ##########################################################################
-
 
55
 * FLAGS usable during runtime
-
 
56
 * ##########################################################################*/
-
 
57
#define COSD_FLAG_NTSC                  1
-
 
58
#define COSD_FLAG_ARTHORIZON    2
-
 
59
#define COSD_FLAG_NOOSD                 4
-
 
60
#define COSD_FLAG_NOOSD_BUT_WRN 8
-
 
61
 
-
 
62
/* ##########################################################################
51
 * Software SPI to communicate with MAX7456
63
 * Software SPI to communicate with MAX7456
52
 * ##########################################################################*/
64
 * ##########################################################################*/
53
#define MAX_CS_HIGH             PORTA |=  (1 << PA1);
65
#define MAX_CS_HIGH             PORTA |=  (1 << PA1);
54
#define MAX_CS_LOW              PORTA &= ~(1 << PA1);
66
#define MAX_CS_LOW              PORTA &= ~(1 << PA1);
55
#define MAX_SDIN_HIGH           PORTA |=  (1 << PA2);
67
#define MAX_SDIN_HIGH           PORTA |=  (1 << PA2);
56
#define MAX_SDIN_LOW            PORTA &= ~(1 << PA2);
68
#define MAX_SDIN_LOW            PORTA &= ~(1 << PA2);
57
#define MAX_SCLK_HIGH           PORTA |=  (1 << PA3);
69
#define MAX_SCLK_HIGH           PORTA |=  (1 << PA3);
58
#define MAX_SCLK_LOW            PORTA &= ~(1 << PA3);
70
#define MAX_SCLK_LOW            PORTA &= ~(1 << PA3);
59
#define MAX_RESET_HIGH          PORTA |=  (1 << PA5);
71
#define MAX_RESET_HIGH          PORTA |=  (1 << PA5);
60
#define MAX_RESET_LOW           PORTA &= ~(1 << PA5);
72
#define MAX_RESET_LOW           PORTA &= ~(1 << PA5);
61
 
73
 
62
/* ##########################################################################
74
/* ##########################################################################
63
 * LED controll
75
 * LED controll
64
 * ##########################################################################*/
76
 * ##########################################################################*/
65
#define LED1_ON                 PORTC |=  (1 << PC0);
77
#define LED1_ON                 PORTC |=  (1 << PC0);
66
#define LED1_OFF                PORTC &= ~(1 << PC0);
78
#define LED1_OFF                PORTC &= ~(1 << PC0);
67
#define LED2_ON                 PORTC |=  (1 << PC1);
79
#define LED2_ON                 PORTC |=  (1 << PC1);
68
#define LED2_OFF                PORTC &= ~(1 << PC1);
80
#define LED2_OFF                PORTC &= ~(1 << PC1);
69
#define LED3_ON                 PORTC |=  (1 << PC2);
81
#define LED3_ON                 PORTC |=  (1 << PC2);
70
#define LED3_OFF                PORTC &= ~(1 << PC2);
82
#define LED3_OFF                PORTC &= ~(1 << PC2);
71
#define LED4_ON                 PORTC |=  (1 << PC3);
83
#define LED4_ON                 PORTC |=  (1 << PC3);
72
#define LED4_OFF                PORTC &= ~(1 << PC3);
84
#define LED4_OFF                PORTC &= ~(1 << PC3);
73
 
85
 
74
/* ##########################################################################
86
/* ##########################################################################
75
 * switch controll
87
 * switch controll
76
 * ##########################################################################*/
88
 * ##########################################################################*/
77
#define S1_PRESSED              !(PINC & (1<<PC4))
89
#define S1_PRESSED              !(PINC & (1<<PC5))
78
#define S2_PRESSED              !(PINC & (1<<PC5))
90
#define S2_PRESSED              !(PINC & (1<<PC4))
79
 
91
 
80
/* ##########################################################################
92
/* ##########################################################################
81
 * gain some fake arm compat :)
93
 * gain some fake arm compat :)
82
 * ##########################################################################*/
94
 * ##########################################################################*/
83
#define u8 uint8_t
95
#define u8 uint8_t
84
#define s8 int8_t
96
#define s8 int8_t
85
#define u16 uint16_t
97
#define u16 uint16_t
86
#define s16 int16_t
98
#define s16 int16_t
87
#define u32 uint32_t
99
#define u32 uint32_t
88
#define s32 int32_t
100
#define s32 int32_t
89
 
101
 
90
#if !(ALLCHARSDEBUG|WRITECHARS)
102
#if !(ALLCHARSDEBUG|WRITECHARS)
91
/* ##########################################################################
103
/* ##########################################################################
92
 * MK data strucs & flags
104
 * MK data strucs & flags
93
 * ##########################################################################*/
105
 * ##########################################################################*/
94
#define NC_FLAG_FREE                    1
106
#define NC_FLAG_FREE                    1
95
#define NC_FLAG_PH                      2
107
#define NC_FLAG_PH                      2
96
#define NC_FLAG_CH                      4
108
#define NC_FLAG_CH                      4
97
#define NC_FLAG_RANGE_LIMIT             8
109
#define NC_FLAG_RANGE_LIMIT             8
98
#define NC_SERIAL_LINK_OK               16
110
#define NC_SERIAL_LINK_OK               16
99
#define NC_FLAG_TARGET_REACHED          32
111
#define NC_FLAG_TARGET_REACHED          32
100
 
-
 
101
 
112
 
102
#define FLAG_MOTOR_RUN  1
113
#define FLAG_MOTOR_RUN  1
103
#define FLAG_FLY        2
114
#define FLAG_FLY        2
104
#define FLAG_CALIBRATE  4
115
#define FLAG_CALIBRATE  4
105
#define FLAG_START      8
116
#define FLAG_START      8
106
 
117
 
107
/*
118
/*
108
 * FC Debug Struct
119
 * FC Debug Struct
109
 * portions taken and adapted from
120
 * portions taken and adapted from
110
 * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Ftags%2FV0.72p%2Fuart.h
121
 * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Ftags%2FV0.72p%2Fuart.h
111
 */
122
 */
112
typedef struct {
123
typedef struct {
113
    uint8_t Digital[2];
124
    uint8_t Digital[2];
114
    uint16_t Analog[32]; // Debugvalues
125
    uint16_t Analog[32]; // Debugvalues
115
} __attribute__((packed)) DebugOut_t;
126
} __attribute__((packed)) DebugOut_t;
116
 
127
 
117
/*
128
/*
118
 * NaviCtrl OSD Structs
129
 * NaviCtrl OSD Structs
119
 * portions taken and adapted from
130
 * portions taken and adapted from
120
 * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=NaviCtrl&path=%2Ftags%2FV0.14e%2Fuart1.h
131
 * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=NaviCtrl&path=%2Ftags%2FV0.14e%2Fuart1.h
121
 */
132
 */
122
typedef struct {
133
typedef struct {
123
    s32 Longitude; // in 1E-7 deg
134
    s32 Longitude; // in 1E-7 deg
124
    s32 Latitude; // in 1E-7 deg
135
    s32 Latitude; // in 1E-7 deg
125
    s32 Altitude; // in mm
136
    s32 Altitude; // in mm
126
    u8 Status; // validity of data
137
    u8 Status; // validity of data
127
} __attribute__((packed)) GPS_Pos_t;
138
} __attribute__((packed)) GPS_Pos_t;
128
 
139
 
129
typedef struct {
140
typedef struct {
130
    s16 Distance; // distance to target in cm
141
    s16 Distance; // distance to target in cm
131
    s16 Bearing; // course to target in deg
142
    s16 Bearing; // course to target in deg
132
} __attribute__((packed)) GPS_PosDev_t;
143
} __attribute__((packed)) GPS_PosDev_t;
133
 
144
 
134
typedef struct {
145
typedef struct {
135
    GPS_Pos_t CurrentPosition; // see ubx.h for details
146
    GPS_Pos_t CurrentPosition; // see ubx.h for details
136
    GPS_Pos_t TargetPosition;
147
    GPS_Pos_t TargetPosition;
137
    GPS_PosDev_t TargetPositionDeviation;
148
    GPS_PosDev_t TargetPositionDeviation;
138
    GPS_Pos_t HomePosition;
149
    GPS_Pos_t HomePosition;
139
    GPS_PosDev_t HomePositionDeviation;
150
    GPS_PosDev_t HomePositionDeviation;
140
    u8 WaypointIndex; // index of current waypoints running from 0 to WaypointNumber-1
151
    u8 WaypointIndex; // index of current waypoints running from 0 to WaypointNumber-1
141
    u8 WaypointNumber; // number of stored waypoints
152
    u8 WaypointNumber; // number of stored waypoints
142
    u8 SatsInUse; // no of satellites used for position solution
153
    u8 SatsInUse; // no of satellites used for position solution
143
    s16 Altimeter; // hight according to air pressure
154
    s16 Altimeter; // hight according to air pressure
144
    s16 Variometer; // climb(+) and sink(-) rate
155
    s16 Variometer; // climb(+) and sink(-) rate
145
    u16 FlyingTime; // in seconds
156
    u16 FlyingTime; // in seconds
146
    u8 UBat; // Battery Voltage in 0.1 Volts
157
    u8 UBat; // Battery Voltage in 0.1 Volts
147
    u16 GroundSpeed; // speed over ground in cm/s (2D)
158
    u16 GroundSpeed; // speed over ground in cm/s (2D)
148
    s16 Heading; // current flight direction in deg as angle to north
159
    s16 Heading; // current flight direction in deg as angle to north
149
    s16 CompassHeading; // current compass value
160
    s16 CompassHeading; // current compass value
150
    s8 AngleNick; // current Nick angle in 1°
161
    s8 AngleNick; // current Nick angle in 1°
151
    s8 AngleRoll; // current Rick angle in 1°
162
    s8 AngleRoll; // current Rick angle in 1°
152
    u8 RC_Quality; // RC_Quality
163
    u8 RC_Quality; // RC_Quality
153
    u8 MKFlags; // Flags from FC
164
    u8 MKFlags; // Flags from FC
154
    u8 NCFlags; // Flags from NC
165
    u8 NCFlags; // Flags from NC
155
    u8 Errorcode; // 0 --> okay
166
    u8 Errorcode; // 0 --> okay
156
    u8 OperatingRadius; // current operation radius around the Home Position in m
167
    u8 OperatingRadius; // current operation radius around the Home Position in m
157
    u8 Reserve[7]; // for future use
168
    u8 Reserve[7]; // for future use
158
} __attribute__((packed)) NaviData_t;
169
} __attribute__((packed)) NaviData_t;
159
 
170
 
160
 
171
 
161
/* ##########################################################################
172
/* ##########################################################################
162
 * global definitions and global vars
173
 * global definitions and global vars
163
 * ##########################################################################*/
174
 * ##########################################################################*/
164
#define baud 57600
175
#define baud 57600
165
 
176
 
166
#define RXD_BUFFER_LEN          150
177
#define RXD_BUFFER_LEN          150
167
#define TXD_BUFFER_LEN          150
178
#define TXD_BUFFER_LEN          150
168
 
179
 
169
volatile uint8_t rxd_buffer_locked = 0;
180
volatile uint8_t rxd_buffer_locked = 0;
170
volatile uint8_t rxd_buffer[RXD_BUFFER_LEN];
181
volatile uint8_t rxd_buffer[RXD_BUFFER_LEN];
171
volatile uint8_t txd_buffer[TXD_BUFFER_LEN];
182
volatile uint8_t txd_buffer[TXD_BUFFER_LEN];
172
volatile uint8_t ReceivedBytes = 0;
183
volatile uint8_t ReceivedBytes = 0;
173
volatile uint8_t *pRxData = 0;
184
volatile uint8_t *pRxData = 0;
174
volatile uint8_t RxDataLen = 0;
185
volatile uint8_t RxDataLen = 0;
175
volatile uint16_t setsReceived = 0;
186
volatile uint16_t setsReceived = 0;
176
 
187
 
177
volatile NaviData_t naviData;
188
volatile NaviData_t naviData;
178
volatile DebugOut_t debugData;
189
volatile DebugOut_t debugData;
179
 
190
 
180
// cache old vars for blinking attribute, checkup is faster than full
191
// cache old vars for blinking attribute, checkup is faster than full
181
// attribute write each time
192
// attribute write each time
182
volatile uint8_t last_UBat = 255;
193
volatile uint8_t last_UBat = 255;
183
volatile uint8_t last_RC_Quality = 255;
194
volatile uint8_t last_RC_Quality = 255;
184
 
195
 
185
// 16bit should be enough, normal LiPos don't last that long
196
// 16bit should be enough, normal LiPos don't last that long
186
volatile uint16_t uptime = 0;
197
volatile uint16_t uptime = 0;
187
volatile uint16_t timer = 0;
198
volatile uint16_t timer = 0;
188
 
199
 
189
#endif // ends !(ALLCHARSDEBUG|WRITECHARS)
200
#endif // ends !(ALLCHARSDEBUG|WRITECHARS)
190
/* ##########################################################################
201
/* ##########################################################################
191
 * MAX7456 SPI & Display stuff
202
 * MAX7456 SPI & Display stuff
192
 * ##########################################################################*/
203
 * ##########################################################################*/
193
 
204
 
194
/**
205
/**
195
 * Send a byte through SPI
206
 * Send a byte through SPI
196
 */
207
 */
197
void spi_send(uint8_t byte) {
208
void spi_send(uint8_t byte) {
198
    for (int8_t i = 7; i >= 0; i--) {
209
    for (int8_t i = 7; i >= 0; i--) {
199
        if (((byte >> i) & 1)) {
210
        if (((byte >> i) & 1)) {
200
            MAX_SDIN_HIGH
211
            MAX_SDIN_HIGH
201
        } else {
212
        } else {
202
            MAX_SDIN_LOW
213
            MAX_SDIN_LOW
203
        }
214
        }
204
        MAX_SCLK_HIGH
215
        MAX_SCLK_HIGH
205
        MAX_SCLK_LOW
216
        MAX_SCLK_LOW
206
    }
217
    }
207
}
218
}
208
 
219
 
209
/**
220
/**
210
 *  Send <byte> to <address> of MAX7456
221
 *  Send <byte> to <address> of MAX7456
211
 */
222
 */
212
void spi_send_byte(uint8_t address, uint8_t byte) {
223
void spi_send_byte(uint8_t address, uint8_t byte) {
213
    // start sending
224
    // start sending
214
    MAX_CS_LOW
225
    MAX_CS_LOW
215
 
226
 
216
    spi_send(address);
227
    spi_send(address);
217
    spi_send(byte);
228
    spi_send(byte);
218
 
229
 
219
    // end sending
230
    // end sending
220
    MAX_CS_HIGH
231
    MAX_CS_HIGH
221
}
232
}
222
 
233
 
223
/**
234
/**
224
 *  write a <character> to <address> of MAX7456 display memory
235
 *  write a <character> to <address> of MAX7456 display memory
225
 */
236
 */
226
void write_char(uint16_t address, char character) {
237
void write_char(uint16_t address, char character) {
227
    spi_send_byte(0x05, (address & 0xFF00) >> 8); // DMAH
238
    spi_send_byte(0x05, (address & 0xFF00) >> 8); // DMAH
228
    spi_send_byte(0x06, (address & 0x00FF)); // DMAL
239
    spi_send_byte(0x06, (address & 0x00FF)); // DMAL
229
    spi_send_byte(0x07, character); // DMDI
240
    spi_send_byte(0x07, character); // DMDI
230
}
241
}
231
 
242
 
232
/**
243
/**
233
 *  write a character <attribute> to <address> of MAX7456 display memory
244
 *  write a character <attribute> to <address> of MAX7456 display memory
234
 */
245
 */
235
void write_char_att(uint16_t address, char attribute) {
246
void write_char_att(uint16_t address, char attribute) {
236
    // the only important part is that the DMAH[1] is set
247
    // the only important part is that the DMAH[1] is set
237
    // so we add 2 which binary is the 2nd lowest byte
248
    // so we add 2 which binary is the 2nd lowest byte
238
    spi_send_byte(0x05, ((address & 0xFF00) >> 8) | 2); // DMAH
249
    spi_send_byte(0x05, ((address & 0xFF00) >> 8) | 2); // DMAH
239
    spi_send_byte(0x06, (address & 0x00FF)); // DMAL
250
    spi_send_byte(0x06, (address & 0x00FF)); // DMAL
240
    spi_send_byte(0x07, attribute); // DMDI
251
    spi_send_byte(0x07, attribute); // DMDI
241
}
252
}
242
 
253
 
243
/**
254
/**
244
 *  write a <character> at <x>/<y> to MAX7456 display memory
255
 *  write a <character> at <x>/<y> to MAX7456 display memory
245
 */
256
 */
246
void write_char_xy(uint8_t x, uint8_t y, char character) {
257
void write_char_xy(uint8_t x, uint8_t y, char character) {
247
    uint16_t address = y * 30 + x;
258
    uint16_t address = y * 30 + x;
248
    write_char(address, character);
259
    write_char(address, character);
249
}
260
}
250
 
261
 
251
/**
262
/**
252
 *  write a  character <attribute> at <x>/<y> to MAX7456 display memory
263
 *  write a  character <attribute> at <x>/<y> to MAX7456 display memory
253
 */
264
 */
254
void write_char_att_xy(uint8_t x, uint8_t y, char attribute) {
265
void write_char_att_xy(uint8_t x, uint8_t y, char attribute) {
255
    uint16_t address = y * 30 + x;
266
    uint16_t address = y * 30 + x;
256
    write_char_att(address, attribute);
267
    write_char_att(address, attribute);
257
}
268
}
258
 
269
 
259
/**
270
/**
260
 *  clear display by writing blank characters all over it
271
 *  clear display by writing blank characters all over it
261
 */
272
 */
262
void clear(void) {
273
void clear(void) {
263
    uint16_t memory_address = 0;
274
    uint16_t memory_address = 0;
264
    for (unsigned int a = 0; a < 480; a++) {
275
    for (unsigned int a = 0; a < 480; a++) {
265
        write_char(memory_address++, 0);
276
        write_char(memory_address++, 0);
266
    }
277
    }
267
}
278
}
268
 
279
 
269
/**
280
/**
270
 *  write an ascii <character> to <address> of MAX7456 display memory
281
 *  write an ascii <character> to <address> of MAX7456 display memory
271
 */
282
 */
272
void write_ascii_char(uint16_t address, char c) {
283
void write_ascii_char(uint16_t address, char c) {
273
    if (c == 32) c = 0; // remap space
284
    if (c == 32) c = 0; // remap space
274
    else if (c > 48 && c <= 57) c -= 48; // remap numbers
285
    else if (c > 48 && c <= 57) c -= 48; // remap numbers
275
    else if (c == '0') c = 10; // remap zero
286
    else if (c == '0') c = 10; // remap zero
276
    else if (c >= 65 && c <= 90) c -= 54; // remap big letters
287
    else if (c >= 65 && c <= 90) c -= 54; // remap big letters
277
    else if (c >= 97 && c <= 122) c -= 60; // remap small letters
288
    else if (c >= 97 && c <= 122) c -= 60; // remap small letters
278
    else if (c == '(') c = 63; // remap
289
    else if (c == '(') c = 63; // remap
279
    else if (c == ')') c = 64; // remap
290
    else if (c == ')') c = 64; // remap
280
    else if (c == '.') c = 65; // remap
291
    else if (c == '.') c = 65; // remap
281
    else if (c == '?') c = 66; // remap
292
    else if (c == '?') c = 66; // remap
282
    else if (c == ';') c = 67; // remap
293
    else if (c == ';') c = 67; // remap
283
    else if (c == ':') c = 68; // remap
294
    else if (c == ':') c = 68; // remap
284
    else if (c == ',') c = 69; // remap
295
    else if (c == ',') c = 69; // remap
285
    else if (c == '\'') c = 70; // remap
296
    else if (c == '\'') c = 70; // remap
286
    else if (c == '/') c = 71; // remap
297
    else if (c == '/') c = 71; // remap
287
    else if (c == '"') c = 72; // remap
298
    else if (c == '"') c = 72; // remap
288
    else if (c == '-') c = 73; // remap minus
299
    else if (c == '-') c = 73; // remap minus
289
    else if (c == '<') c = 74; // remap
300
    else if (c == '<') c = 74; // remap
290
    else if (c == '>') c = 75; // remap
301
    else if (c == '>') c = 75; // remap
291
    else if (c == '@') c = 76; // remap
302
    else if (c == '@') c = 76; // remap
292
    write_char(address, c);
303
    write_char(address, c);
293
}
304
}
294
 
305
 
295
/**
306
/**
296
 *  write an ascii <string> at <x>/<y> to MAX7456 display memory
307
 *  write an ascii <string> at <x>/<y> to MAX7456 display memory
297
 */
308
 */
298
void write_ascii_string(uint8_t x, uint8_t y, char *string) {
309
void write_ascii_string(uint8_t x, uint8_t y, char *string) {
299
    while (*string) {
310
    while (*string) {
300
        write_ascii_char(((x++)+(y * 30)), *string);
311
        write_ascii_char(((x++)+(y * 30)), *string);
301
        string++;
312
        string++;
302
    }
313
    }
303
}
314
}
304
 
315
 
305
/**
316
/**
306
 *  Write only the last three digits of a <number> at <x>/<y> to MAX7456
317
 *  Write only the last three digits of a <number> at <x>/<y> to MAX7456
307
 *  display memory. takes full 16bit numbers as well for stuff
318
 *  display memory. takes full 16bit numbers as well for stuff
308
 *  like compass only taking three characters (values <= 999)
319
 *  like compass only taking three characters (values <= 999)
309
 */
320
 */
310
void write_3digit_number_u(uint8_t x, uint8_t y, uint16_t number) {
321
void write_3digit_number_u(uint8_t x, uint8_t y, uint16_t number) {
311
    uint16_t num = 100;
322
    uint16_t num = 100;
312
    uint8_t started = 0;
323
    uint8_t started = 0;
313
 
324
 
314
    while (num > 0) {
325
    while (num > 0) {
315
        uint8_t b = number / num;
326
        uint8_t b = number / num;
316
        if (b > 0 || started || num == 1) {
327
        if (b > 0 || started || num == 1) {
317
            write_ascii_char((x++)+(y * 30), '0' + b);
328
            write_ascii_char((x++)+(y * 30), '0' + b);
318
            started = 1;
329
            started = 1;
319
        } else {
330
        } else {
320
            write_ascii_char((x++)+(y * 30), 0);
331
            write_ascii_char((x++)+(y * 30), 0);
321
        }
332
        }
322
        number -= b * num;
333
        number -= b * num;
323
 
334
 
324
        num /= 10;
335
        num /= 10;
325
    }
336
    }
326
}
337
}
327
 
338
 
328
/**
339
/**
329
 *  Write only the last two digits of a number at <x>/<y> to MAX7456
340
 *  Write only the last two digits of a number at <x>/<y> to MAX7456
330
 *  display memory. takes full 16bit numbers as well for stuff
341
 *  display memory. takes full 16bit numbers as well for stuff
331
 *  like seconds only taking two characters (values <= 99)
342
 *  like seconds only taking two characters (values <= 99)
332
 *  Since this is used for seconds only and it looks better, there
343
 *  Since this is used for seconds only and it looks better, there
333
 *  is a trading 0 attached
344
 *  is a trading 0 attached
334
 */
345
 */
335
void write_2digit_number_u(uint8_t x, uint8_t y, uint16_t number) {
346
void write_2digit_number_u(uint8_t x, uint8_t y, uint16_t number) {
336
    uint16_t num = 10;
347
    uint16_t num = 10;
337
    uint8_t started = 0;
348
    uint8_t started = 0;
338
 
349
 
339
    while (num > 0) {
350
    while (num > 0) {
340
        uint8_t b = number / num;
351
        uint8_t b = number / num;
341
        if (b > 0 || started || num == 1) {
352
        if (b > 0 || started || num == 1) {
342
            write_ascii_char((x++)+(y * 30), '0' + b);
353
            write_ascii_char((x++)+(y * 30), '0' + b);
343
            started = 1;
354
            started = 1;
344
        } else {
355
        } else {
345
            write_ascii_char((x++)+(y * 30), '0');
356
            write_ascii_char((x++)+(y * 30), '0');
346
        }
357
        }
347
        number -= b * num;
358
        number -= b * num;
348
 
359
 
349
        num /= 10;
360
        num /= 10;
350
    }
361
    }
351
}
362
}
352
 
363
 
353
/**
364
/**
354
 *  write a unsigned number as /10th at <x>/<y> to MAX7456 display memory
365
 *  write a unsigned number as /10th at <x>/<y> to MAX7456 display memory
355
 */
366
 */
356
void write_number_u_10th(uint8_t x, uint8_t y, uint16_t number) {
367
void write_number_u_10th(uint8_t x, uint8_t y, uint16_t number) {
357
    uint16_t num = 10000;
368
    uint16_t num = 10000;
358
    uint8_t started = 0;
369
    uint8_t started = 0;
359
 
370
 
360
    while (num > 0) {
371
    while (num > 0) {
361
        uint8_t b = number / num;
372
        uint8_t b = number / num;
362
 
373
 
363
        if (b > 0 || started || num == 1) {
374
        if (b > 0 || started || num == 1) {
364
            if ((num / 10) == 0) write_char((x++)+(y * 30), 65);
375
            if ((num / 10) == 0) write_char((x++)+(y * 30), 65);
365
            write_ascii_char((x++)+(y * 30), '0' + b);
376
            write_ascii_char((x++)+(y * 30), '0' + b);
366
            started = 1;
377
            started = 1;
367
        } else {
378
        } else {
368
            write_ascii_char((x++)+(y * 30), 0);
379
            write_ascii_char((x++)+(y * 30), 0);
369
        }
380
        }
370
        number -= b * num;
381
        number -= b * num;
371
 
382
 
372
        num /= 10;
383
        num /= 10;
373
    }
384
    }
374
}
385
}
375
 
386
 
376
/**
387
/**
377
 *  write a unsigned number at <x>/<y> to MAX7456 display memory
388
 *  write a unsigned number at <x>/<y> to MAX7456 display memory
378
 */
389
 */
379
void write_number_u(uint8_t x, uint8_t y, uint16_t number) {
390
void write_number_u(uint8_t x, uint8_t y, uint16_t number) {
380
    uint16_t num = 10000;
391
    uint16_t num = 10000;
381
    uint8_t started = 0;
392
    uint8_t started = 0;
382
 
393
 
383
    while (num > 0) {
394
    while (num > 0) {
384
        uint8_t b = number / num;
395
        uint8_t b = number / num;
385
        if (b > 0 || started || num == 1) {
396
        if (b > 0 || started || num == 1) {
386
            write_ascii_char((x++)+(y * 30), '0' + b);
397
            write_ascii_char((x++)+(y * 30), '0' + b);
387
            started = 1;
398
            started = 1;
388
        } else {
399
        } else {
389
            write_ascii_char((x++)+(y * 30), 0);
400
            write_ascii_char((x++)+(y * 30), 0);
390
        }
401
        }
391
        number -= b * num;
402
        number -= b * num;
392
 
403
 
393
        num /= 10;
404
        num /= 10;
394
    }
405
    }
395
}
406
}
396
 
407
 
397
/**
408
/**
398
 *  write a signed number at <x>/<y> to MAX7456 display memory
409
 *  write a signed number at <x>/<y> to MAX7456 display memory
399
 */
410
 */
400
void write_number_s(uint8_t x, uint8_t y, int16_t w) {
411
void write_number_s(uint8_t x, uint8_t y, int16_t w) {
401
    if (((uint16_t) w) > 32767) {
412
    if (((uint16_t) w) > 32767) {
402
        w = w - 65536;
413
        w = w - 65536;
403
 
414
 
404
        int16_t num = -10000;
415
        int16_t num = -10000;
405
        uint8_t started = 0;
416
        uint8_t started = 0;
406
 
417
 
407
        while (num < 0) {
418
        while (num < 0) {
408
            uint8_t b = w / num;
419
            uint8_t b = w / num;
409
            if (b > 0 || started || num == 1) {
420
            if (b > 0 || started || num == 1) {
410
                if (!started) write_char((x - 1)+(y * 30), 0x49);
421
                if (!started) write_char((x - 1)+(y * 30), 0x49);
411
                write_ascii_char((x++)+(y * 30), '0' + b);
422
                write_ascii_char((x++)+(y * 30), '0' + b);
412
                started = 1;
423
                started = 1;
413
            } else {
424
            } else {
414
                write_ascii_char((x++)+(y * 30), 0);
425
                write_ascii_char((x++)+(y * 30), 0);
415
            }
426
            }
416
            w -= b * num;
427
            w -= b * num;
417
 
428
 
418
            num /= 10;
429
            num /= 10;
419
        }
430
        }
420
    } else {
431
    } else {
421
        write_char((x)+(y * 30), 0);
432
        write_char((x)+(y * 30), 0);
422
        write_number_u(x, y, w);
433
        write_number_u(x, y, w);
423
    }
434
    }
424
}
435
}
425
 
436
 
426
/**
437
/**
427
 *  write <seconds> as human readable time at <x>/<y> to MAX7456 display mem
438
 *  write <seconds> as human readable time at <x>/<y> to MAX7456 display mem
428
 */
439
 */
429
void write_time(uint8_t x, uint8_t y, uint16_t seconds) {
440
void write_time(uint8_t x, uint8_t y, uint16_t seconds) {
430
    uint16_t min = seconds / 60;
441
    uint16_t min = seconds / 60;
431
    seconds -= min * 60;
442
    seconds -= min * 60;
432
    write_3digit_number_u(x, y, min);
443
    write_3digit_number_u(x, y, min);
433
    write_char_xy(x + 3, y, 68);
444
    write_char_xy(x + 3, y, 68);
434
    write_2digit_number_u(x + 4, y, seconds);
445
    write_2digit_number_u(x + 4, y, seconds);
435
}
446
}
436
 
447
 
437
/**
448
/**
438
 * for testing write all chars to screen
449
 * for testing write all chars to screen
439
 */
450
 */
440
void write_all_chars() {
451
void write_all_chars() {
441
    uint16_t x = 3, y = 2, t = 0;
452
    uint16_t x = 3, y = 2, t = 0;
442
    while (t < 256) {
453
    while (t < 256) {
443
        write_char_xy(x++, y, t++);
454
        write_char_xy(x++, y, t++);
444
        if (x > 25) {
455
        if (x > 25) {
445
            y++;
456
            y++;
446
            x = 3;
457
            x = 3;
447
        }
458
        }
448
    }
459
    }
449
}
460
}
450
 
461
 
451
#if !(ALLCHARSDEBUG|WRITECHARS)
462
#if !(ALLCHARSDEBUG|WRITECHARS)
452
/* ##########################################################################
463
/* ##########################################################################
453
 * USART stuff
464
 * USART stuff
454
 * ##########################################################################*/
465
 * ##########################################################################*/
455
 
466
 
456
/**
467
/**
457
 * init usart1
468
 * init usart1
458
 */
469
 */
459
void usart1_init() {
470
void usart1_init() {
460
    UBRR1H = ((F_CPU / (16UL * baud)) - 1) >> 8;
471
    UBRR1H = ((F_CPU / (16UL * baud)) - 1) >> 8;
461
    UBRR1L = (F_CPU / (16UL * baud)) - 1;
472
    UBRR1L = (F_CPU / (16UL * baud)) - 1;
462
 
473
 
463
    // Enable receiver and transmitter; enable RX interrupt
474
    // Enable receiver and transmitter; enable RX interrupt
464
    UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1);
475
    UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1);
465
 
476
 
466
    //asynchronous 8N1
477
    //asynchronous 8N1
467
    UCSR1C = (1 << URSEL1) | (3 << UCSZ10);
478
    UCSR1C = (1 << URSEL1) | (3 << UCSZ10);
468
}
479
}
469
 
480
 
470
/**
481
/**
471
 * send a single <character> through usart1
482
 * send a single <character> through usart1
472
 */
483
 */
473
void usart1_putc(unsigned char character) {
484
void usart1_putc(unsigned char character) {
474
    // wait until UDR ready
485
    // wait until UDR ready
475
    while (!(UCSR1A & (1 << UDRE1)));
486
    while (!(UCSR1A & (1 << UDRE1)));
476
    UDR1 = character;
487
    UDR1 = character;
477
}
488
}
478
 
489
 
479
/**
490
/**
480
 * send a <string> throught usart1
491
 * send a <string> throught usart1
481
 */
492
 */
482
void usart1_puts(char *s) {
493
void usart1_puts(char *s) {
483
    while (*s) {
494
    while (*s) {
484
        usart1_putc(*s);
495
        usart1_putc(*s);
485
        s++;
496
        s++;
486
    }
497
    }
487
}
498
}
488
 
499
 
489
/**
500
/**
490
 * receive data through usart1
501
 * receive data through usart1
491
 * portions taken and adapted from
502
 * portions taken and adapted from
492
 * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Fbranches%2FV0.72p+Code+Redesign+killagreg%2Fuart0.c
503
 * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Fbranches%2FV0.72p+Code+Redesign+killagreg%2Fuart0.c
493
 */
504
 */
494
ISR(SIG_USART1_RECV) {
505
ISR(SIG_USART1_RECV) {
495
    if (rxd_buffer_locked) return; // if rxd buffer is locked immediately return
506
    if (rxd_buffer_locked) return; // if rxd buffer is locked immediately return
496
    LED1_ON
507
    LED1_ON
497
            static uint16_t crc;
508
            static uint16_t crc;
498
    static uint8_t ptr_rxd_buffer = 0;
509
    static uint8_t ptr_rxd_buffer = 0;
499
    uint8_t crc1, crc2;
510
    uint8_t crc1, crc2;
500
    uint8_t c;
511
    uint8_t c;
501
 
512
 
502
    c = UDR1; // catch the received byte
513
    c = UDR1; // catch the received byte
503
 
514
 
504
    // the rxd buffer is unlocked
515
    // the rxd buffer is unlocked
505
    if ((ptr_rxd_buffer == 0) && (c == '#')) // if rxd buffer is empty and syncronisation character is received
516
    if ((ptr_rxd_buffer == 0) && (c == '#')) // if rxd buffer is empty and syncronisation character is received
506
    {
517
    {
507
                /*
518
                /*
508
                // skip other datasets
519
                // skip other datasets
509
        if (ptr_rxd_buffer == 2 && rxd_buffer[ptr_rxd_buffer] != 'O') {
520
        if (ptr_rxd_buffer == 2 && rxd_buffer[ptr_rxd_buffer] != 'O') {
510
                        ptr_rxd_buffer = 0; // reset rxd buffer
521
                        ptr_rxd_buffer = 0; // reset rxd buffer
511
                rxd_buffer_locked = 0; // unlock rxd buffer
522
                rxd_buffer_locked = 0; // unlock rxd buffer
512
                }*/
523
                }*/
513
                rxd_buffer[ptr_rxd_buffer++] = c; // copy 1st byte to buffer
524
                rxd_buffer[ptr_rxd_buffer++] = c; // copy 1st byte to buffer
514
        crc = c; // init crc
525
        crc = c; // init crc
515
    } else if (ptr_rxd_buffer < RXD_BUFFER_LEN) // collect incomming bytes
526
    } else if (ptr_rxd_buffer < RXD_BUFFER_LEN) // collect incomming bytes
516
    {
527
    {
517
        if (c != '\r') // no termination character
528
        if (c != '\r') // no termination character
518
        {
529
        {
519
            rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
530
            rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
520
            crc += c; // update crc
531
            crc += c; // update crc
521
        } else // termination character was received
532
        } else // termination character was received
522
        {
533
        {
523
            // the last 2 bytes are no subject for checksum calculation
534
            // the last 2 bytes are no subject for checksum calculation
524
            // they are the checksum itself
535
            // they are the checksum itself
525
            crc -= rxd_buffer[ptr_rxd_buffer - 2];
536
            crc -= rxd_buffer[ptr_rxd_buffer - 2];
526
            crc -= rxd_buffer[ptr_rxd_buffer - 1];
537
            crc -= rxd_buffer[ptr_rxd_buffer - 1];
527
            // calculate checksum from transmitted data
538
            // calculate checksum from transmitted data
528
            crc %= 4096;
539
            crc %= 4096;
529
            crc1 = '=' + crc / 64;
540
            crc1 = '=' + crc / 64;
530
            crc2 = '=' + crc % 64;
541
            crc2 = '=' + crc % 64;
531
            // compare checksum to transmitted checksum bytes
542
            // compare checksum to transmitted checksum bytes
532
            if ((crc1 == rxd_buffer[ptr_rxd_buffer - 2]) && (crc2 == rxd_buffer[ptr_rxd_buffer - 1])) { // checksum valid
543
            if ((crc1 == rxd_buffer[ptr_rxd_buffer - 2]) && (crc2 == rxd_buffer[ptr_rxd_buffer - 1])) { // checksum valid
533
                rxd_buffer[ptr_rxd_buffer] = '\r'; // set termination character
544
                rxd_buffer[ptr_rxd_buffer] = '\r'; // set termination character
534
                ReceivedBytes = ptr_rxd_buffer + 1; // store number of received bytes
545
                ReceivedBytes = ptr_rxd_buffer + 1; // store number of received bytes
535
                rxd_buffer_locked = 1; // lock the rxd buffer
546
                rxd_buffer_locked = 1; // lock the rxd buffer
536
            } else { // checksum invalid
547
            } else { // checksum invalid
537
                rxd_buffer_locked = 0; // unlock rxd buffer
548
                rxd_buffer_locked = 0; // unlock rxd buffer
538
            }
549
            }
539
            ptr_rxd_buffer = 0; // reset rxd buffer pointer
550
            ptr_rxd_buffer = 0; // reset rxd buffer pointer
540
        }
551
        }
541
    } else // rxd buffer overrun
552
    } else // rxd buffer overrun
542
    {
553
    {
543
        ptr_rxd_buffer = 0; // reset rxd buffer
554
        ptr_rxd_buffer = 0; // reset rxd buffer
544
        rxd_buffer_locked = 0; // unlock rxd buffer
555
        rxd_buffer_locked = 0; // unlock rxd buffer
545
    }
556
    }
546
    LED1_OFF
557
    LED1_OFF
547
}
558
}
548
 
559
 
549
/**
560
/**
550
 * Decode the recevied Buffer
561
 * Decode the recevied Buffer
551
 * portions taken and adapted from
562
 * portions taken and adapted from
552
 * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Ftags%2FV0.72p%2Fuart.c
563
 * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Ftags%2FV0.72p%2Fuart.c
553
 */
564
 */
554
void Decode64(void) {
565
void Decode64(void) {
555
    uint8_t a, b, c, d;
566
    uint8_t a, b, c, d;
556
    uint8_t x, y, z;
567
    uint8_t x, y, z;
557
    uint8_t ptrIn = 3;
568
    uint8_t ptrIn = 3;
558
    uint8_t ptrOut = 3;
569
    uint8_t ptrOut = 3;
559
    uint8_t len = ReceivedBytes - 6;
570
    uint8_t len = ReceivedBytes - 6;
560
 
571
 
561
    while (len) {
572
    while (len) {
562
        a = rxd_buffer[ptrIn++] - '=';
573
        a = rxd_buffer[ptrIn++] - '=';
563
        b = rxd_buffer[ptrIn++] - '=';
574
        b = rxd_buffer[ptrIn++] - '=';
564
        c = rxd_buffer[ptrIn++] - '=';
575
        c = rxd_buffer[ptrIn++] - '=';
565
        d = rxd_buffer[ptrIn++] - '=';
576
        d = rxd_buffer[ptrIn++] - '=';
566
 
577
 
567
        x = (a << 2) | (b >> 4);
578
        x = (a << 2) | (b >> 4);
568
        y = ((b & 0x0f) << 4) | (c >> 2);
579
        y = ((b & 0x0f) << 4) | (c >> 2);
569
        z = ((c & 0x03) << 6) | d;
580
        z = ((c & 0x03) << 6) | d;
570
 
581
 
571
        if (len--) rxd_buffer[ptrOut++] = x;
582
        if (len--) rxd_buffer[ptrOut++] = x;
572
        else break;
583
        else break;
573
        if (len--) rxd_buffer[ptrOut++] = y;
584
        if (len--) rxd_buffer[ptrOut++] = y;
574
        else break;
585
        else break;
575
        if (len--) rxd_buffer[ptrOut++] = z;
586
        if (len--) rxd_buffer[ptrOut++] = z;
576
        else break;
587
        else break;
577
    }
588
    }
578
    pRxData = &rxd_buffer[3];
589
    pRxData = &rxd_buffer[3];
579
    RxDataLen = ptrOut - 3;
590
    RxDataLen = ptrOut - 3;
580
}
591
}
581
 
592
 
582
/**
593
/**
583
 * request Data through USART in special MK format by adding checksum and
594
 * request Data through USART in special MK format by adding checksum and
584
 * encode data in modified Base64
595
 * encode data in modified Base64
585
 * portions taken and adapted from
596
 * portions taken and adapted from
586
 * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Ftags%2FV0.72p%2Fuart.c
597
 * http://svn.mikrokopter.de/mikrowebsvn/filedetails.php?repname=FlightCtrl&path=%2Ftags%2FV0.72p%2Fuart.c
587
 */
598
 */
588
void sendMKData(unsigned char cmd, unsigned char addr, unsigned char *snd, unsigned char len) {
599
void sendMKData(unsigned char cmd, unsigned char addr, unsigned char *snd, unsigned char len) {
589
    unsigned int pt = 0;
600
    unsigned int pt = 0;
590
    unsigned char a, b, c;
601
    unsigned char a, b, c;
591
    unsigned char ptr = 0;
602
    unsigned char ptr = 0;
592
 
603
 
593
    txd_buffer[pt++] = '#'; // Start-Byte
604
    txd_buffer[pt++] = '#'; // Start-Byte
594
    txd_buffer[pt++] = 'a' + addr; // Adress
605
    txd_buffer[pt++] = 'a' + addr; // Adress
595
    txd_buffer[pt++] = cmd; // Command
606
    txd_buffer[pt++] = cmd; // Command
596
    while (len) {
607
    while (len) {
597
        if (len) {
608
        if (len) {
598
            a = snd[ptr++];
609
            a = snd[ptr++];
599
            len--;
610
            len--;
600
        } else a = 0;
611
        } else a = 0;
601
        if (len) {
612
        if (len) {
602
            b = snd[ptr++];
613
            b = snd[ptr++];
603
            len--;
614
            len--;
604
        } else b = 0;
615
        } else b = 0;
605
        if (len) {
616
        if (len) {
606
            c = snd[ptr++];
617
            c = snd[ptr++];
607
            len--;
618
            len--;
608
        } else c = 0;
619
        } else c = 0;
609
        txd_buffer[pt++] = '=' + (a >> 2);
620
        txd_buffer[pt++] = '=' + (a >> 2);
610
        txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
621
        txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
611
        txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
622
        txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
612
        txd_buffer[pt++] = '=' + (c & 0x3f);
623
        txd_buffer[pt++] = '=' + (c & 0x3f);
613
    }
624
    }
614
 
625
 
615
    // add crc
626
    // add crc
616
    unsigned int tmpCRC = 0, i;
627
    unsigned int tmpCRC = 0, i;
617
    for (i = 0; i < pt; i++) {
628
    for (i = 0; i < pt; i++) {
618
        tmpCRC += txd_buffer[i];
629
        tmpCRC += txd_buffer[i];
619
    }
630
    }
620
    tmpCRC %= 4096;
631
    tmpCRC %= 4096;
621
    txd_buffer[i++] = '=' + tmpCRC / 64;
632
    txd_buffer[i++] = '=' + tmpCRC / 64;
622
    txd_buffer[i++] = '=' + tmpCRC % 64;
633
    txd_buffer[i++] = '=' + tmpCRC % 64;
623
    txd_buffer[i++] = '\r';
634
    txd_buffer[i++] = '\r';
624
 
635
 
625
    usart1_puts((char*) txd_buffer);
636
    usart1_puts((char*) txd_buffer);
626
}
637
}
627
 
638
 
628
/* ##########################################################################
639
/* ##########################################################################
629
 * timer stuff
640
 * timer stuff
630
 * ##########################################################################*/
641
 * ##########################################################################*/
631
 
642
 
632
/*
643
/*
633
 * timer kicks in every 1000uS
644
 * timer kicks in every 1000uS
634
 */
645
 */
635
ISR(TIMER0_OVF_vect) {
646
ISR(TIMER0_OVF_vect) {
636
    OCR0 = 6; // preload
647
    OCR0 = 6; // preload
637
    if (!timer--) {
648
    if (!timer--) {
638
        uptime++;
649
        uptime++;
639
        timer = 999;
650
        timer = 999;
640
    }
651
    }
641
}
652
}
642
 
653
 
643
/* ##########################################################################
654
/* ##########################################################################
644
 * compass stuff
655
 * compass stuff
645
 * ##########################################################################*/
656
 * ##########################################################################*/
646
 
657
 
647
/**
658
/**
648
 * convert the <heading> gotton from NC into an index
659
 * convert the <heading> gotton from NC into an index
649
 */
660
 */
650
uint8_t heading_conv(uint16_t heading) {
661
uint8_t heading_conv(uint16_t heading) {
651
    if (heading > 23 && heading < 68) {
662
    if (heading > 23 && heading < 68) {
652
        //direction = "NE";
663
        //direction = "NE";
653
        return 0;
664
        return 0;
654
    } else if (heading > 67 && heading < 113) {
665
    } else if (heading > 67 && heading < 113) {
655
        //direction = "E ";
666
        //direction = "E ";
656
        return 1;
667
        return 1;
657
    } else if (heading > 112 && heading < 158) {
668
    } else if (heading > 112 && heading < 158) {
658
        //direction = "SE";
669
        //direction = "SE";
659
        return 2;
670
        return 2;
660
    } else if (heading > 157 && heading < 203) {
671
    } else if (heading > 157 && heading < 203) {
661
        //direction = "S ";
672
        //direction = "S ";
662
        return 3;
673
        return 3;
663
    } else if (heading > 202 && heading < 248) {
674
    } else if (heading > 202 && heading < 248) {
664
        //direction = "SW";
675
        //direction = "SW";
665
        return 4;
676
        return 4;
666
    } else if (heading > 247 && heading < 293) {
677
    } else if (heading > 247 && heading < 293) {
667
        //direction = "W ";
678
        //direction = "W ";
668
        return 5;
679
        return 5;
669
    } else if (heading > 292 && heading < 338) {
680
    } else if (heading > 292 && heading < 338) {
670
        //direction = "NW";
681
        //direction = "NW";
671
        return 6;
682
        return 6;
672
    }
683
    }
673
    //direction = "N ";
684
    //direction = "N ";
674
    return 7;
685
    return 7;
675
}
686
}
676
 
687
 
677
/**
688
/**
678
 * draw a compass rose at <x>/<y> for <heading>
689
 * draw a compass rose at <x>/<y> for <heading>
679
 */
690
 */
680
void draw_compass(uint8_t x, uint8_t y, uint16_t heading) {
691
void draw_compass(uint8_t x, uint8_t y, uint16_t heading) {
681
    //char* rose = "---N---O---S---W---N---O---S---W---N---O---S---W";
692
    //char* rose = "---N---O---S---W---N---O---S---W---N---O---S---W";
682
    char rose[48] = {216, 215, 216, 211, 216, 215, 216, 213, 216, 215, 216, 212,
693
    char rose[48] = {216, 215, 216, 211, 216, 215, 216, 213, 216, 215, 216, 212,
683
                    216, 215, 216, 214, 216, 215, 216, 211, 216, 215, 216, 213,
694
                    216, 215, 216, 214, 216, 215, 216, 211, 216, 215, 216, 213,
684
                    216, 215, 216, 212, 216, 215, 216, 214, 216, 215, 216, 211,
695
                    216, 215, 216, 212, 216, 215, 216, 214, 216, 215, 216, 211,
685
                    216, 215, 216, 213, 216, 215, 216, 212, 216, 215, 216, 214};
696
                    216, 215, 216, 213, 216, 215, 216, 212, 216, 215, 216, 214};
686
        // the center is char 19 (north), we add the current heading in 8th
697
        // the center is char 19 (north), we add the current heading in 8th
687
        // which would be 22.5 degrees, but float would bloat up the code
698
        // which would be 22.5 degrees, but float would bloat up the code
688
        // and *10 / 225 would take ages... so we take the uncorrect way
699
        // and *10 / 225 would take ages... so we take the uncorrect way
689
    uint8_t front = 19 + (heading / 22);
700
    uint8_t front = 19 + (heading / 22);
690
    for (uint8_t i = 0; i < 9; i++) {
701
    for (uint8_t i = 0; i < 9; i++) {
691
                write_char_xy(x++, y, rose[front - 4 + i]);
702
                write_char_xy(x++, y, rose[front - 4 + i]);
692
    }
703
    }
693
}
704
}
694
 
705
 
695
/* ##########################################################################
706
/* ##########################################################################
696
 * artificial horizon
707
 * artificial horizon
697
 * ##########################################################################*/
708
 * ##########################################################################*/
698
// remember last time displayed values
709
// remember last time displayed values
699
int8_t old_af_x = -1, old_af_y = -1;
710
int8_t old_af_x = -1, old_af_y = -1;
700
 
711
 
701
/**
712
/**
702
 * draw roll und nick indicators (could be enhanced to full artificial horizon)
713
 * draw roll und nick indicators (could be enhanced to full artificial horizon)
703
 * from line <firstline> to <listlines> for given <nick> and <roll> values
714
 * from line <firstline> to <listlines> for given <nick> and <roll> values
704
 */
715
 */
705
void draw_artificial_horizon(uint8_t firstline, uint8_t lastline, int16_t nick, int16_t roll) {
716
void draw_artificial_horizon(uint8_t firstline, uint8_t lastline, int16_t nick, int16_t roll) {
706
        char noodle[5] = {225, 225, 226, 227, 227};
717
        char noodle[5] = {225, 225, 226, 227, 227};
707
        uint8_t center_x = 15;
718
        uint8_t center_x = 15;
708
        uint8_t center_y = lastline - firstline;
719
        uint8_t center_y = lastline - firstline;
709
        center_y = 7;
720
        center_y = 7;
710
        write_char_xy(center_x,center_y,228);
721
        write_char_xy(center_x,center_y,228);
711
        uint8_t cpos, nicky, rollx;
722
        uint8_t cpos, nicky, rollx;
712
       
723
       
713
        // which line
724
        // which line
714
        int8_t ypos =  nick / 20;
725
        int8_t ypos =  nick / 20;
715
        // which character from the array?
726
        // which character from the array?
716
        if (nick < 0) {
727
        if (nick < 0) {
717
                cpos = -1*((nick - (ypos * 20))/4);
728
                cpos = -1*((nick - (ypos * 20))/4);
718
                ypos--;
729
                ypos--;
719
        } else cpos = 4-((nick - (ypos * 20))/4);
730
        } else cpos = 4-((nick - (ypos * 20))/4);
720
        if (cpos > 4) cpos = 4;
731
        if (cpos > 4) cpos = 4;
721
 
732
 
722
        nicky = center_y - ypos;
733
        nicky = center_y - ypos;
723
        if (nicky > lastline) nicky = lastline;
734
        if (nicky > lastline) nicky = lastline;
724
        else if (nicky < firstline) nicky = firstline;
735
        else if (nicky < firstline) nicky = firstline;
725
 
736
 
726
        // ensure roll-borders
737
        // ensure roll-borders
727
        rollx = (roll / 8)+15;
738
        rollx = (roll / 8)+15;
728
        if (rollx < 2) rollx = 2;
739
        if (rollx < 2) rollx = 2;
729
        else if (rollx > 28) rollx = 28;
740
        else if (rollx > 28) rollx = 28;
730
 
741
 
731
 
742
 
732
        // clear roll
743
        // clear roll
733
        if (old_af_x != rollx && old_af_x >= 0) {
744
        if (old_af_x != rollx && old_af_x >= 0) {
734
                write_char_xy(old_af_x,13,0);
745
                write_char_xy(old_af_x,13,0);
735
        }
746
        }
736
 
747
 
737
        // clear nick
748
        // clear nick
738
        if (old_af_y != nicky && old_af_y >= 0) {
749
        if (old_af_y != nicky && old_af_y >= 0) {
739
                write_char_xy(center_x-1,old_af_y,0);
750
                write_char_xy(center_x-1,old_af_y,0);
740
                write_char_xy(center_x+1,old_af_y,0);
751
                write_char_xy(center_x+1,old_af_y,0);
741
        }
752
        }
742
 
753
 
743
 
754
 
744
        // draw nick
755
        // draw nick
745
        write_char_xy(center_x-1,nicky,noodle[cpos]);
756
        write_char_xy(center_x-1,nicky,noodle[cpos]);
746
        write_char_xy(center_x+1,nicky,noodle[cpos]);
757
        write_char_xy(center_x+1,nicky,noodle[cpos]);
747
 
758
 
748
        // draw roll
759
        // draw roll
749
        write_char_xy(rollx,lastline,229);
760
        write_char_xy(rollx,lastline,229);
750
 
761
 
751
        // update old vars
762
        // update old vars
752
        old_af_x = rollx;
763
        old_af_x = rollx;
753
        old_af_y = nicky;
764
        old_af_y = nicky;
754
 
765
 
755
        // debug numbers
766
        // debug numbers
756
        //write_3digit_number_u(20,6,cpos);
767
        //write_3digit_number_u(20,6,cpos);
757
        //write_number_s(20,7,ypos);    
768
        //write_number_s(20,7,ypos);    
758
        //write_number_s(0,7,nick);             
769
        //write_number_s(0,7,nick);             
759
        //write_number_s(18,11,roll);   
770
        //write_number_s(18,11,roll);   
760
}
771
}
761
 
772
 
762
#endif
773
#endif
763
 
774
 
764
/* ##########################################################################
775
/* ##########################################################################
765
 * MAIN
776
 * MAIN
766
 * ##########################################################################*/
777
 * ##########################################################################*/
767
int main(void) {
778
int main(void) {
-
 
779
        // set up FLAGS, compiler should flatten this one
-
 
780
        uint8_t COSD_FLAGS = (NTSC << (COSD_FLAG_NTSC - 1));
-
 
781
        COSD_FLAGS |= (ARTHORIZON << (COSD_FLAG_ARTHORIZON - 1));
-
 
782
        COSD_FLAGS |= (NOOSD << (COSD_FLAG_NOOSD - 1));
-
 
783
        COSD_FLAGS |= (NOOSD_BUT_WRN << (COSD_FLAG_NOOSD_BUT_WRN - 1));
-
 
784
 
-
 
785
        // set up Atmega162 Ports
768
    DDRA |= (1 << PA1); // PA1 output (/CS)
786
    DDRA |= (1 << PA1); // PA1 output (/CS)
769
    MAX_CS_HIGH
787
    MAX_CS_HIGH
770
    DDRA |= (1 << PA2); // PA2 output (SDIN)
788
    DDRA |= (1 << PA2); // PA2 output (SDIN)
771
    MAX_SDIN_LOW
789
    MAX_SDIN_LOW
772
    DDRA |= (1 << PA3); // PA3 output (SCLK)
790
    DDRA |= (1 << PA3); // PA3 output (SCLK)
773
    MAX_SCLK_LOW
791
    MAX_SCLK_LOW
774
    DDRA |= (1 << PA5); // PA5 output (RESET)
792
    DDRA |= (1 << PA5); // PA5 output (RESET)
775
    MAX_RESET_HIGH
793
    MAX_RESET_HIGH
776
 
794
 
777
    DDRC |= (1 << PC0); // PC0 output (LED1 gn)
795
    DDRC |= (1 << PC0); // PC0 output (LED1 gn)
778
    LED1_OFF
796
    LED1_OFF
779
    DDRC |= (1 << PC1); // PC1 output (LED2 rt)
797
    DDRC |= (1 << PC1); // PC1 output (LED2 rt)
780
    LED2_OFF
798
    LED2_OFF
781
    DDRC |= (1 << PC2); // PC2 output (LED3 gn)
799
    DDRC |= (1 << PC2); // PC2 output (LED3 gn)
782
    LED3_OFF
800
    LED3_OFF
783
    DDRC |= (1 << PC3); // PC3 output (LED4 rt)
801
    DDRC |= (1 << PC3); // PC3 output (LED4 rt)
784
    LED4_OFF
802
    LED4_OFF
785
 
803
 
786
    DDRC &= ~(1 << PC4); // PC4 input  (MODE)
804
    DDRC &= ~(1 << PC4); // PC4 input  (MODE)
787
    PORTC |= (1 << PC4); // pullup
805
    PORTC |= (1 << PC4); // pullup
788
    DDRC &= ~(1 << PC5); // PC5 input  (SET)
806
    DDRC &= ~(1 << PC5); // PC5 input  (SET)
789
    PORTC |= (1 << PC5); // pullup
807
    PORTC |= (1 << PC5); // pullup
790
 
808
 
791
    MAX_RESET_LOW
809
    MAX_RESET_LOW
792
    MAX_RESET_HIGH
810
    MAX_RESET_HIGH
-
 
811
 
-
 
812
        // check for keypress at startup
-
 
813
        if (S2_PRESSED) { // togle COSD_FLAG_ARTHORIZON
-
 
814
                        COSD_FLAGS ^= (1 << (COSD_FLAG_ARTHORIZON - 1));
-
 
815
                        _delay_ms(100);
-
 
816
    }
793
 
817
 
794
    // give the FC/NC and the maxim time to come up
818
    // give the FC/NC and the maxim time to come up
795
    LED4_ON
819
    LED4_ON
796
    _delay_ms(2000);
820
    _delay_ms(2000);
797
 
821
 
798
    LED4_OFF
822
    LED4_OFF
799
 
823
 
800
    /* ##########################################################################
824
    /* ##########################################################################
801
     * Pushing NEW chars to the MAX7456
825
     * Pushing NEW chars to the MAX7456
802
     * ##########################################################################*/
826
     * ##########################################################################*/
803
#if WRITECHARS
827
#if WRITECHARS
804
        void learn_char(uint8_t number, unsigned char* data) {
828
        void learn_char(uint8_t number, unsigned char* data) {
805
        // select character to write (CMAH)
829
        // select character to write (CMAH)
806
        spi_send_byte(0x09, number);
830
        spi_send_byte(0x09, number);
807
 
831
 
808
        for (uint8_t i = 0; i < 54; i++) {
832
        for (uint8_t i = 0; i < 54; i++) {
809
            // select 4pixel byte of char (CMAL)
833
            // select 4pixel byte of char (CMAL)
810
            spi_send_byte(0x0A, i);
834
            spi_send_byte(0x0A, i);
811
 
835
 
812
            // write 4pixel byte of char (CMDI)
836
            // write 4pixel byte of char (CMDI)
813
            spi_send_byte(0x0B, data[i]);
837
            spi_send_byte(0x0B, data[i]);
814
        }
838
        }
815
 
839
 
816
        // write to the NVM array from the shadow RAM (CMM)
840
        // write to the NVM array from the shadow RAM (CMM)
817
        spi_send_byte(0x08, 0b10100000);
841
        spi_send_byte(0x08, 0b10100000);
818
 
842
 
819
        // according to maxim writing to nvram takes about 12ms, lets wait longer
843
        // according to maxim writing to nvram takes about 12ms, lets wait longer
820
        _delay_ms(120);
844
        _delay_ms(120);
821
    }
845
    }
822
 
846
 
823
    // DISABLE display (VM0)
847
    // DISABLE display (VM0)
824
    spi_send_byte(0x00, 0b00000000);
848
    spi_send_byte(0x00, 0b00000000);
825
 
849
 
826
    /**
850
    /**
827
     * easy char creation:
851
     * easy char creation:
828
     * http://cascade.dyndns.org/~cascade/scripts/max7456/
852
     * http://cascade.dyndns.org/~cascade/scripts/max7456/
829
     */
853
     */
830
    // GPS
854
    // GPS
831
    unsigned char cc8[54] = {0x55, 0x50, 0x55, 0x55, 0x4a, 0x15, 0x55, 0x2a,
855
    unsigned char cc8[54] = {0x55, 0x50, 0x55, 0x55, 0x4a, 0x15, 0x55, 0x2a,
832
        0x85, 0x55, 0x2a, 0xa1, 0x55, 0x4a, 0xa8, 0x55,
856
        0x85, 0x55, 0x2a, 0xa1, 0x55, 0x4a, 0xa8, 0x55,
833
        0x52, 0xa8, 0x55, 0x54, 0xaa, 0x55, 0x55, 0x09,
857
        0x52, 0xa8, 0x55, 0x54, 0xaa, 0x55, 0x55, 0x09,
834
        0x55, 0x55, 0x52, 0x55, 0x55, 0x1a, 0x55, 0x51,
858
        0x55, 0x55, 0x52, 0x55, 0x55, 0x1a, 0x55, 0x51,
835
        0x96, 0x55, 0x18, 0x85, 0x54, 0x88, 0x28, 0x54,
859
        0x96, 0x55, 0x18, 0x85, 0x54, 0x88, 0x28, 0x54,
836
        0x82, 0x05, 0x55, 0x20, 0xa1, 0x55, 0x48, 0x15,
860
        0x82, 0x05, 0x55, 0x20, 0xa1, 0x55, 0x48, 0x15,
837
        0x55, 0x52, 0x85, 0x55, 0x54, 0x15};
861
        0x55, 0x52, 0x85, 0x55, 0x54, 0x15};
838
 
862
 
839
    unsigned char cc9[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
863
    unsigned char cc9[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
840
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x45,
864
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x45,
841
        0x55, 0x55, 0x21, 0x55, 0x55, 0xa8, 0x55, 0x55,
865
        0x55, 0x55, 0x21, 0x55, 0x55, 0xa8, 0x55, 0x55,
842
        0xa1, 0x55, 0x55, 0x98, 0x15, 0x55, 0x2a, 0x85,
866
        0xa1, 0x55, 0x55, 0x98, 0x15, 0x55, 0x2a, 0x85,
843
        0x55, 0x4a, 0xa1, 0x55, 0x4a, 0xa8, 0x55, 0x52,
867
        0x55, 0x4a, 0xa1, 0x55, 0x4a, 0xa8, 0x55, 0x52,
844
        0xaa, 0x15, 0x54, 0xaa, 0x15, 0x55, 0x28, 0x55,
868
        0xaa, 0x15, 0x54, 0xaa, 0x15, 0x55, 0x28, 0x55,
845
        0x55, 0x41, 0x55, 0x55, 0x55, 0x55};
869
        0x55, 0x41, 0x55, 0x55, 0x55, 0x55};
846
 
870
 
847
    // RC
871
    // RC
848
    unsigned char cca[54] = {0x54, 0xaa, 0x85, 0x52, 0x00, 0x21, 0x48, 0x2a,
872
    unsigned char cca[54] = {0x54, 0xaa, 0x85, 0x52, 0x00, 0x21, 0x48, 0x2a,
849
        0x08, 0x60, 0x80, 0x82, 0x62, 0x08, 0x22, 0x62,
873
        0x08, 0x60, 0x80, 0x82, 0x62, 0x08, 0x22, 0x62,
850
        0x2a, 0x22, 0x62, 0x08, 0x22, 0x60, 0x88, 0x82,
874
        0x2a, 0x22, 0x62, 0x08, 0x22, 0x60, 0x88, 0x82,
851
        0x48, 0x08, 0x08, 0x52, 0x08, 0x21, 0x54, 0x48,
875
        0x48, 0x08, 0x08, 0x52, 0x08, 0x21, 0x54, 0x48,
852
        0x45, 0x55, 0x48, 0x55, 0x55, 0x48, 0x55, 0x55,
876
        0x45, 0x55, 0x48, 0x55, 0x55, 0x48, 0x55, 0x55,
853
        0x48, 0x55, 0x55, 0x48, 0x55, 0x55, 0x48, 0x55,
877
        0x48, 0x55, 0x55, 0x48, 0x55, 0x55, 0x48, 0x55,
854
        0x55, 0x2a, 0x15, 0x54, 0xaa, 0x85};
878
        0x55, 0x2a, 0x15, 0x54, 0xaa, 0x85};
855
 
879
 
856
    // km/h
880
    // km/h
857
    unsigned char ccb[54] = {0x55, 0x55, 0x55, 0x01, 0x55, 0x55, 0x21, 0x55,
881
    unsigned char ccb[54] = {0x55, 0x55, 0x55, 0x01, 0x55, 0x55, 0x21, 0x55,
858
        0x55, 0x20, 0x15, 0x55, 0x22, 0x15, 0x55, 0x28,
882
        0x55, 0x20, 0x15, 0x55, 0x22, 0x15, 0x55, 0x28,
859
        0x15, 0x55, 0x22, 0x15, 0x55, 0x00, 0x00, 0x15,
883
        0x15, 0x55, 0x22, 0x15, 0x55, 0x00, 0x00, 0x15,
860
        0x52, 0xaa, 0x15, 0x52, 0x22, 0x15, 0x52, 0x22,
884
        0x52, 0xaa, 0x15, 0x52, 0x22, 0x15, 0x52, 0x22,
861
        0x15, 0x50, 0x00, 0x05, 0x55, 0x54, 0x85, 0x55,
885
        0x15, 0x50, 0x00, 0x05, 0x55, 0x54, 0x85, 0x55,
862
        0x54, 0x80, 0x55, 0x54, 0xa8, 0x55, 0x54, 0x88,
886
        0x54, 0x80, 0x55, 0x54, 0xa8, 0x55, 0x54, 0x88,
863
        0x55, 0x54, 0x88, 0x55, 0x54, 0x00};
887
        0x55, 0x54, 0x88, 0x55, 0x54, 0x00};
864
 
888
 
865
 
889
 
866
    // small meters m
890
    // small meters m
867
    unsigned char ccc[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
891
    unsigned char ccc[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
868
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
892
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
869
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
893
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
870
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
894
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
871
        0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x15, 0x22,
895
        0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x15, 0x22,
872
        0x8a, 0x15, 0x28, 0xa2, 0x15, 0x20, 0x82, 0x15,
896
        0x8a, 0x15, 0x28, 0xa2, 0x15, 0x20, 0x82, 0x15,
873
        0x20, 0x82, 0x15, 0x00, 0x00, 0x15};
897
        0x20, 0x82, 0x15, 0x00, 0x00, 0x15};
874
 
898
 
875
    // vario down
899
    // vario down
876
    unsigned char ccd[54] = {0x55, 0x00, 0x55, 0x55, 0x28, 0x55, 0x55, 0x28,
900
    unsigned char ccd[54] = {0x55, 0x00, 0x55, 0x55, 0x28, 0x55, 0x55, 0x28,
877
        0x55, 0x55, 0x28, 0x55, 0x55, 0x28, 0x55, 0x55,
901
        0x55, 0x55, 0x28, 0x55, 0x55, 0x28, 0x55, 0x55,
878
        0x28, 0x55, 0x55, 0x28, 0x55, 0x55, 0x28, 0x55,
902
        0x28, 0x55, 0x55, 0x28, 0x55, 0x55, 0x28, 0x55,
879
        0x55, 0x28, 0x55, 0x55, 0x28, 0x55, 0x55, 0x28,
903
        0x55, 0x28, 0x55, 0x55, 0x28, 0x55, 0x55, 0x28,
880
        0x55, 0x00, 0x28, 0x00, 0x2a, 0xaa, 0xa8, 0x0a,
904
        0x55, 0x00, 0x28, 0x00, 0x2a, 0xaa, 0xa8, 0x0a,
881
        0xaa, 0xa0, 0x42, 0xaa, 0x81, 0x50, 0xaa, 0x05,
905
        0xaa, 0xa0, 0x42, 0xaa, 0x81, 0x50, 0xaa, 0x05,
882
        0x54, 0x28, 0x15, 0x55, 0x00, 0x55};
906
        0x54, 0x28, 0x15, 0x55, 0x00, 0x55};
883
 
907
 
884
    // vario hold
908
    // vario hold
885
    unsigned char cce[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
909
    unsigned char cce[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
886
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
910
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
887
        0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00,
911
        0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00,
888
        0x2a, 0xaa, 0xa8, 0x2a, 0xaa, 0xa8, 0x00, 0x00,
912
        0x2a, 0xaa, 0xa8, 0x2a, 0xaa, 0xa8, 0x00, 0x00,
889
        0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
913
        0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
890
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
914
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
891
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
915
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
892
 
916
 
893
    // vario up
917
    // vario up
894
    unsigned char ccf[54] = {0x55, 0x00, 0x55, 0x54, 0x28, 0x15, 0x50, 0xaa,
918
    unsigned char ccf[54] = {0x55, 0x00, 0x55, 0x54, 0x28, 0x15, 0x50, 0xaa,
895
        0x05, 0x42, 0xaa, 0x81, 0x0a, 0xaa, 0xa0, 0x2a,
919
        0x05, 0x42, 0xaa, 0x81, 0x0a, 0xaa, 0xa0, 0x2a,
896
        0xaa, 0xa8, 0x00, 0x28, 0x00, 0x55, 0x28, 0x55,
920
        0xaa, 0xa8, 0x00, 0x28, 0x00, 0x55, 0x28, 0x55,
897
        0x55, 0x28, 0x55, 0x55, 0x28, 0x55, 0x55, 0x28,
921
        0x55, 0x28, 0x55, 0x55, 0x28, 0x55, 0x55, 0x28,
898
        0x55, 0x55, 0x28, 0x55, 0x55, 0x28, 0x55, 0x55,
922
        0x55, 0x55, 0x28, 0x55, 0x55, 0x28, 0x55, 0x55,
899
        0x28, 0x55, 0x55, 0x28, 0x55, 0x55, 0x28, 0x55,
923
        0x28, 0x55, 0x55, 0x28, 0x55, 0x55, 0x28, 0x55,
900
        0x55, 0x28, 0x55, 0x55, 0x00, 0x55};
924
        0x55, 0x28, 0x55, 0x55, 0x00, 0x55};
901
 
925
 
902
    // degree symbol
926
    // degree symbol
903
    unsigned char cd0[54] = {0x55, 0x55, 0x55, 0x54, 0x01, 0x55, 0x52, 0xa8,
927
    unsigned char cd0[54] = {0x55, 0x55, 0x55, 0x54, 0x01, 0x55, 0x52, 0xa8,
904
        0x55, 0x48, 0x02, 0x15, 0x48, 0x52, 0x15, 0x48,
928
        0x55, 0x48, 0x02, 0x15, 0x48, 0x52, 0x15, 0x48,
905
        0x52, 0x15, 0x48, 0x02, 0x15, 0x52, 0xa8, 0x55,
929
        0x52, 0x15, 0x48, 0x02, 0x15, 0x52, 0xa8, 0x55,
906
        0x54, 0x01, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
930
        0x54, 0x01, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
907
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
931
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
908
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
932
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
909
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
933
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
910
 
934
 
911
    // clock on symbol
935
    // clock on symbol
912
    unsigned char cd1[54] = {0x54, 0x14, 0x51, 0x52, 0x82, 0x08, 0x48, 0x22,
936
    unsigned char cd1[54] = {0x54, 0x14, 0x51, 0x52, 0x82, 0x08, 0x48, 0x22,
913
        0x88, 0x48, 0x22, 0x28, 0x48, 0x22, 0x28, 0x52,
937
        0x88, 0x48, 0x22, 0x28, 0x48, 0x22, 0x28, 0x52,
914
        0x82, 0x08, 0x54, 0x14, 0x51, 0x55, 0x40, 0x55,
938
        0x82, 0x08, 0x54, 0x14, 0x51, 0x55, 0x40, 0x55,
915
        0x55, 0x2a, 0x15, 0x54, 0x88, 0x85, 0x52, 0x08,
939
        0x55, 0x2a, 0x15, 0x54, 0x88, 0x85, 0x52, 0x08,
916
        0x21, 0x48, 0x48, 0x08, 0x48, 0x4a, 0x88, 0x48,
940
        0x21, 0x48, 0x48, 0x08, 0x48, 0x4a, 0x88, 0x48,
917
        0x50, 0x08, 0x52, 0x15, 0x21, 0x54, 0x80, 0x85,
941
        0x50, 0x08, 0x52, 0x15, 0x21, 0x54, 0x80, 0x85,
918
        0x55, 0x2a, 0x15, 0x55, 0x40, 0x55};
942
        0x55, 0x2a, 0x15, 0x55, 0x40, 0x55};
919
 
943
 
920
    // clock fly symbol
944
    // clock fly symbol
921
    unsigned char cd2[54] = {0x40, 0x45, 0x11, 0x2a, 0x20, 0x88, 0x20, 0x20,
945
    unsigned char cd2[54] = {0x40, 0x45, 0x11, 0x2a, 0x20, 0x88, 0x20, 0x20,
922
        0x88, 0x28, 0x21, 0x21, 0x21, 0x20, 0x21, 0x21,
946
        0x88, 0x28, 0x21, 0x21, 0x21, 0x20, 0x21, 0x21,
923
        0x2a, 0x21, 0x45, 0x40, 0x45, 0x55, 0x40, 0x55,
947
        0x2a, 0x21, 0x45, 0x40, 0x45, 0x55, 0x40, 0x55,
924
        0x55, 0x2a, 0x15, 0x54, 0x88, 0x85, 0x52, 0x08,
948
        0x55, 0x2a, 0x15, 0x54, 0x88, 0x85, 0x52, 0x08,
925
        0x21, 0x48, 0x48, 0x08, 0x48, 0x4a, 0x88, 0x48,
949
        0x21, 0x48, 0x48, 0x08, 0x48, 0x4a, 0x88, 0x48,
926
        0x50, 0x08, 0x52, 0x15, 0x21, 0x54, 0x80, 0x85,
950
        0x50, 0x08, 0x52, 0x15, 0x21, 0x54, 0x80, 0x85,
927
        0x55, 0x2a, 0x15, 0x55, 0x40, 0x55};
951
        0x55, 0x2a, 0x15, 0x55, 0x40, 0x55};
928
 
952
 
929
    // compass north
953
    // compass north
930
    unsigned char cd3[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
954
    unsigned char cd3[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
931
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54,
955
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54,
932
        0x54, 0x55, 0x52, 0x12, 0x15, 0x52, 0x82, 0x15,
956
        0x54, 0x55, 0x52, 0x12, 0x15, 0x52, 0x82, 0x15,
933
        0x02, 0x82, 0x00, 0xa2, 0x22, 0x2a, 0x02, 0x0a,
957
        0x02, 0x82, 0x00, 0xa2, 0x22, 0x2a, 0x02, 0x0a,
934
        0x00, 0x52, 0x0a, 0x15, 0x52, 0x12, 0x15, 0x54,
958
        0x00, 0x52, 0x0a, 0x15, 0x52, 0x12, 0x15, 0x54,
935
        0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
959
        0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
936
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
960
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
937
 
961
 
938
    // compass south
962
    // compass south
939
    unsigned char cd4[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
963
    unsigned char cd4[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
940
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
964
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
941
        0x01, 0x55, 0x54, 0xa8, 0x55, 0x52, 0x02, 0x15,
965
        0x01, 0x55, 0x54, 0xa8, 0x55, 0x52, 0x02, 0x15,
942
        0x04, 0x84, 0x40, 0xa1, 0x21, 0x2a, 0x04, 0x48,
966
        0x04, 0x84, 0x40, 0xa1, 0x21, 0x2a, 0x04, 0x48,
943
        0x40, 0x52, 0x02, 0x15, 0x54, 0xa8, 0x55, 0x55,
967
        0x40, 0x52, 0x02, 0x15, 0x54, 0xa8, 0x55, 0x55,
944
        0x01, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
968
        0x01, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
945
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
969
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
946
 
970
 
947
    // compass east
971
    // compass east
948
    unsigned char cd5[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
972
    unsigned char cd5[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
949
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54,
973
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54,
950
        0x00, 0x55, 0x52, 0xaa, 0x15, 0x52, 0x00, 0x55,
974
        0x00, 0x55, 0x52, 0xaa, 0x15, 0x52, 0x00, 0x55,
951
        0x02, 0x05, 0x40, 0xa2, 0xa1, 0x2a, 0x02, 0x05,
975
        0x02, 0x05, 0x40, 0xa2, 0xa1, 0x2a, 0x02, 0x05,
952
        0x40, 0x52, 0x00, 0x55, 0x52, 0xaa, 0x15, 0x54,
976
        0x40, 0x52, 0x00, 0x55, 0x52, 0xaa, 0x15, 0x54,
953
        0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
977
        0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
954
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
978
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
955
 
979
 
956
    // compass west
980
    // compass west
957
    unsigned char cd6[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
981
    unsigned char cd6[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
958
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54,
982
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54,
959
        0x54, 0x55, 0x52, 0x12, 0x15, 0x52, 0x12, 0x15,
983
        0x54, 0x55, 0x52, 0x12, 0x15, 0x52, 0x12, 0x15,
960
        0x02, 0x02, 0x00, 0xa2, 0x22, 0x2a, 0x02, 0x8a,
984
        0x02, 0x02, 0x00, 0xa2, 0x22, 0x2a, 0x02, 0x8a,
961
        0x00, 0x52, 0x8a, 0x15, 0x52, 0x12, 0x15, 0x54,
985
        0x00, 0x52, 0x8a, 0x15, 0x52, 0x12, 0x15, 0x54,
962
        0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
986
        0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
963
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
987
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
964
 
988
 
965
    // compass between
989
    // compass between
966
    unsigned char cd7[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
990
    unsigned char cd7[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
967
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
991
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
968
        0x55, 0x55, 0x55, 0x45, 0x55, 0x55, 0x21, 0x55,
992
        0x55, 0x55, 0x55, 0x45, 0x55, 0x55, 0x21, 0x55,
969
        0x01, 0x21, 0x00, 0xa8, 0x20, 0xaa, 0x01, 0x21,
993
        0x01, 0x21, 0x00, 0xa8, 0x20, 0xaa, 0x01, 0x21,
970
        0x00, 0x55, 0x21, 0x55, 0x55, 0x45, 0x55, 0x55,
994
        0x00, 0x55, 0x21, 0x55, 0x55, 0x45, 0x55, 0x55,
971
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
995
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
972
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
996
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
973
 
997
 
974
    // compass line
998
    // compass line
975
    unsigned char cd8[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
999
    unsigned char cd8[54] = {0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
976
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1000
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
977
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1001
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
978
        0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0x00, 0x00,
1002
        0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0x00, 0x00,
979
        0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1003
        0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
980
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1004
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
981
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1005
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
982
 
1006
 
983
    // arrow right
1007
    // arrow right
984
    unsigned char cd9[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1008
    unsigned char cd9[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
985
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1009
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
986
        0x55, 0x15, 0x55, 0x54, 0x85, 0x40, 0x00, 0xa1,
1010
        0x55, 0x15, 0x55, 0x54, 0x85, 0x40, 0x00, 0xa1,
987
        0x2a, 0xaa, 0xa8, 0x2a, 0xaa, 0xa8, 0x40, 0x00,
1011
        0x2a, 0xaa, 0xa8, 0x2a, 0xaa, 0xa8, 0x40, 0x00,
988
        0xa1, 0x55, 0x54, 0x85, 0x55, 0x55, 0x15, 0x55,
1012
        0xa1, 0x55, 0x54, 0x85, 0x55, 0x55, 0x15, 0x55,
989
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1013
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
990
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1014
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
991
 
1015
 
992
    // arrow right-up
1016
    // arrow right-up
993
    unsigned char cda[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1017
    unsigned char cda[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
994
        0x55, 0x55, 0x40, 0x01, 0x55, 0x2a, 0xa8, 0x55,
1018
        0x55, 0x55, 0x40, 0x01, 0x55, 0x2a, 0xa8, 0x55,
995
        0x4a, 0xa8, 0x55, 0x52, 0xa8, 0x55, 0x4a, 0xa8,
1019
        0x4a, 0xa8, 0x55, 0x52, 0xa8, 0x55, 0x4a, 0xa8,
996
        0x55, 0x2a, 0x28, 0x54, 0xa8, 0x48, 0x52, 0xa1,
1020
        0x55, 0x2a, 0x28, 0x54, 0xa8, 0x48, 0x52, 0xa1,
997
        0x51, 0x4a, 0x85, 0x55, 0x52, 0x15, 0x55, 0x54,
1021
        0x51, 0x4a, 0x85, 0x55, 0x52, 0x15, 0x55, 0x54,
998
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1022
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
999
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1023
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1000
 
1024
 
1001
    // arrow up
1025
    // arrow up
1002
    unsigned char cdb[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1026
    unsigned char cdb[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1003
        0x55, 0x55, 0x41, 0x55, 0x55, 0x28, 0x55, 0x54,
1027
        0x55, 0x55, 0x41, 0x55, 0x55, 0x28, 0x55, 0x54,
1004
        0xaa, 0x15, 0x52, 0xaa, 0x85, 0x54, 0x28, 0x15,
1028
        0xaa, 0x15, 0x52, 0xaa, 0x85, 0x54, 0x28, 0x15,
1005
        0x55, 0x28, 0x55, 0x55, 0x28, 0x55, 0x55, 0x28,
1029
        0x55, 0x28, 0x55, 0x55, 0x28, 0x55, 0x55, 0x28,
1006
        0x55, 0x55, 0x28, 0x55, 0x55, 0x28, 0x55, 0x55,
1030
        0x55, 0x55, 0x28, 0x55, 0x55, 0x28, 0x55, 0x55,
1007
        0x28, 0x55, 0x55, 0x41, 0x55, 0x55, 0x55, 0x55,
1031
        0x28, 0x55, 0x55, 0x41, 0x55, 0x55, 0x55, 0x55,
1008
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1032
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1009
 
1033
 
1010
    // arrow left-up
1034
    // arrow left-up
1011
    unsigned char cdc[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1035
    unsigned char cdc[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1012
        0x55, 0x40, 0x01, 0x55, 0x2a, 0xa8, 0x55, 0x2a,
1036
        0x55, 0x40, 0x01, 0x55, 0x2a, 0xa8, 0x55, 0x2a,
1013
        0xa1, 0x55, 0x2a, 0x85, 0x55, 0x2a, 0xa1, 0x55,
1037
        0xa1, 0x55, 0x2a, 0x85, 0x55, 0x2a, 0xa1, 0x55,
1014
        0x28, 0xa8, 0x55, 0x21, 0x2a, 0x15, 0x45, 0x4a,
1038
        0x28, 0xa8, 0x55, 0x21, 0x2a, 0x15, 0x45, 0x4a,
1015
        0x85, 0x55, 0x52, 0xa1, 0x55, 0x54, 0x85, 0x55,
1039
        0x85, 0x55, 0x52, 0xa1, 0x55, 0x54, 0x85, 0x55,
1016
        0x55, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1040
        0x55, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1017
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1041
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1018
 
1042
 
1019
    // arrow left
1043
    // arrow left
1020
    unsigned char cdd[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1044
    unsigned char cdd[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1021
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54,
1045
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54,
1022
        0x55, 0x55, 0x52, 0x15, 0x55, 0x4a, 0x00, 0x01,
1046
        0x55, 0x55, 0x52, 0x15, 0x55, 0x4a, 0x00, 0x01,
1023
        0x2a, 0xaa, 0xa8, 0x2a, 0xaa, 0xa8, 0x4a, 0x00,
1047
        0x2a, 0xaa, 0xa8, 0x2a, 0xaa, 0xa8, 0x4a, 0x00,
1024
        0x01, 0x52, 0x15, 0x55, 0x54, 0x55, 0x55, 0x55,
1048
        0x01, 0x52, 0x15, 0x55, 0x54, 0x55, 0x55, 0x55,
1025
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1049
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1026
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1050
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1027
 
1051
 
1028
    // arrow left-down
1052
    // arrow left-down
1029
    unsigned char cde[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1053
    unsigned char cde[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1030
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x55,
1054
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x55,
1031
        0x54, 0x85, 0x55, 0x52, 0xa1, 0x45, 0x4a, 0x85,
1055
        0x54, 0x85, 0x55, 0x52, 0xa1, 0x45, 0x4a, 0x85,
1032
        0x21, 0x2a, 0x15, 0x28, 0xa8, 0x55, 0x2a, 0xa1,
1056
        0x21, 0x2a, 0x15, 0x28, 0xa8, 0x55, 0x2a, 0xa1,
1033
        0x55, 0x2a, 0x85, 0x55, 0x2a, 0xa1, 0x55, 0x2a,
1057
        0x55, 0x2a, 0x85, 0x55, 0x2a, 0xa1, 0x55, 0x2a,
1034
        0xa8, 0x55, 0x40, 0x01, 0x55, 0x55, 0x55, 0x55,
1058
        0xa8, 0x55, 0x40, 0x01, 0x55, 0x55, 0x55, 0x55,
1035
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1059
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1036
 
1060
 
1037
    // arrow down
1061
    // arrow down
1038
    unsigned char cdf[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1062
    unsigned char cdf[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1039
        0x55, 0x55, 0x41, 0x55, 0x55, 0x28, 0x55, 0x55,
1063
        0x55, 0x55, 0x41, 0x55, 0x55, 0x28, 0x55, 0x55,
1040
        0x28, 0x55, 0x55, 0x28, 0x55, 0x55, 0x28, 0x55,
1064
        0x28, 0x55, 0x55, 0x28, 0x55, 0x55, 0x28, 0x55,
1041
        0x55, 0x28, 0x55, 0x55, 0x28, 0x55, 0x54, 0x28,
1065
        0x55, 0x28, 0x55, 0x55, 0x28, 0x55, 0x54, 0x28,
1042
        0x15, 0x52, 0xaa, 0x85, 0x54, 0xaa, 0x15, 0x55,
1066
        0x15, 0x52, 0xaa, 0x85, 0x54, 0xaa, 0x15, 0x55,
1043
        0x28, 0x55, 0x55, 0x41, 0x55, 0x55, 0x55, 0x55,
1067
        0x28, 0x55, 0x55, 0x41, 0x55, 0x55, 0x55, 0x55,
1044
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1068
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1045
 
1069
 
1046
    // arrow right-down
1070
    // arrow right-down
1047
    unsigned char ce0[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1071
    unsigned char ce0[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1048
        0x55, 0x55, 0x55, 0x55, 0x54, 0x55, 0x55, 0x52,
1072
        0x55, 0x55, 0x55, 0x55, 0x54, 0x55, 0x55, 0x52,
1049
        0x15, 0x55, 0x4a, 0x85, 0x55, 0x52, 0xa1, 0x51,
1073
        0x15, 0x55, 0x4a, 0x85, 0x55, 0x52, 0xa1, 0x51,
1050
        0x54, 0xa8, 0x48, 0x55, 0x2a, 0x28, 0x55, 0x4a,
1074
        0x54, 0xa8, 0x48, 0x55, 0x2a, 0x28, 0x55, 0x4a,
1051
        0xa8, 0x55, 0x52, 0xa8, 0x55, 0x4a, 0xa8, 0x55,
1075
        0xa8, 0x55, 0x52, 0xa8, 0x55, 0x4a, 0xa8, 0x55,
1052
        0x2a, 0xa8, 0x55, 0x40, 0x01, 0x55, 0x55, 0x55,
1076
        0x2a, 0xa8, 0x55, 0x40, 0x01, 0x55, 0x55, 0x55,
1053
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1077
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1054
 
1078
 
1055
        // horizon up
1079
        // horizon up
1056
    unsigned char ce1[54] ={0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0xaa, 0xaa,
1080
    unsigned char ce1[54] ={0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0xaa, 0xaa,
1057
        0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x55,
1081
        0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x55,
1058
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1082
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1059
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1083
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1060
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1084
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1061
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1085
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1062
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1086
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1063
 
1087
 
1064
        // horizon middle
1088
        // horizon middle
1065
    unsigned char ce2[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1089
    unsigned char ce2[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1066
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1090
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1067
        0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00,
1091
        0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00,
1068
        0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00,
1092
        0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00,
1069
        0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1093
        0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1070
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1094
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1071
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1095
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1072
 
1096
 
1073
        // horizon down
1097
        // horizon down
1074
    unsigned char ce3[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1098
    unsigned char ce3[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1075
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1099
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1076
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1100
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1077
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1101
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1078
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00,
1102
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00,
1079
        0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
1103
        0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
1080
        0x00, 0x00, 0x00, 0x55, 0x55, 0x55};
1104
        0x00, 0x00, 0x00, 0x55, 0x55, 0x55};
1081
 
1105
 
1082
        // horizon center
1106
        // horizon center
1083
    unsigned char ce4[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1107
    unsigned char ce4[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1084
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1108
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1085
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1109
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1086
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1110
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1087
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00,
1111
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00,
1088
        0x14, 0x00, 0xaa, 0x14, 0xaa, 0xaa, 0x82, 0xaa,
1112
        0x14, 0x00, 0xaa, 0x14, 0xaa, 0xaa, 0x82, 0xaa,
1089
        0x00, 0xaa, 0x00, 0x54, 0x00, 0x15};
1113
        0x00, 0xaa, 0x00, 0x54, 0x00, 0x15};
1090
 
1114
 
1091
        // horizon roll
1115
        // horizon roll
1092
    unsigned char ce5[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1116
    unsigned char ce5[54] ={0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1093
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1117
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1094
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1118
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1095
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1119
        0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1096
        0x55, 0x00, 0x55, 0x00, 0x2a, 0x14, 0xa8, 0x4a,
1120
        0x55, 0x00, 0x55, 0x00, 0x2a, 0x14, 0xa8, 0x4a,
1097
        0x82, 0xa1, 0x52, 0xaa, 0x85, 0x54, 0xaa, 0x15,
1121
        0x82, 0xa1, 0x52, 0xaa, 0x85, 0x54, 0xaa, 0x15,
1098
        0x55, 0x28, 0x55, 0x55, 0x41, 0x55};
1122
        0x55, 0x28, 0x55, 0x55, 0x41, 0x55};
1099
       
1123
       
1100
        // gps PH
1124
        // gps PH
1101
    unsigned char ce6[54] ={0x55, 0x05, 0x11, 0x54, 0xa0, 0x88, 0x54, 0x88,
1125
    unsigned char ce6[54] ={0x55, 0x05, 0x11, 0x54, 0xa0, 0x88, 0x54, 0x88,
1102
        0x88, 0x54, 0xa0, 0xa8, 0x54, 0x84, 0x88, 0x44,
1126
        0x88, 0x54, 0xa0, 0xa8, 0x54, 0x84, 0x88, 0x44,
1103
        0x84, 0x88, 0x21, 0x15, 0x11, 0xa8, 0x55, 0x55,
1127
        0x84, 0x88, 0x21, 0x15, 0x11, 0xa8, 0x55, 0x55,
1104
        0xa1, 0x55, 0x55, 0x98, 0x15, 0x55, 0x2a, 0x85,
1128
        0xa1, 0x55, 0x55, 0x98, 0x15, 0x55, 0x2a, 0x85,
1105
        0x55, 0x4a, 0xa1, 0x55, 0x4a, 0xa8, 0x55, 0x52,
1129
        0x55, 0x4a, 0xa1, 0x55, 0x4a, 0xa8, 0x55, 0x52,
1106
        0xaa, 0x15, 0x54, 0xaa, 0x15, 0x55, 0x28, 0x55,
1130
        0xaa, 0x15, 0x54, 0xaa, 0x15, 0x55, 0x28, 0x55,
1107
        0x55, 0x41, 0x55, 0x55, 0x55, 0x55};
1131
        0x55, 0x41, 0x55, 0x55, 0x55, 0x55};
1108
       
1132
       
1109
        // gps CH
1133
        // gps CH
1110
    unsigned char ce7[54] ={0x55, 0x55, 0x41, 0x55, 0x55, 0x28, 0x55, 0x54,
1134
    unsigned char ce7[54] ={0x55, 0x55, 0x41, 0x55, 0x55, 0x28, 0x55, 0x54,
1111
        0x81, 0x55, 0x54, 0x85, 0x55, 0x54, 0x81, 0x45,
1135
        0x81, 0x55, 0x54, 0x85, 0x55, 0x54, 0x81, 0x45,
1112
        0x55, 0x28, 0x21, 0x55, 0x01, 0xa8, 0x54, 0x88,
1136
        0x55, 0x28, 0x21, 0x55, 0x01, 0xa8, 0x54, 0x88,
1113
        0xa1, 0x54, 0x88, 0x98, 0x14, 0xa8, 0x2a, 0x84,
1137
        0xa1, 0x54, 0x88, 0x98, 0x14, 0xa8, 0x2a, 0x84,
1114
        0x88, 0x4a, 0xa0, 0x88, 0x4a, 0xa8, 0x11, 0x52,
1138
        0x88, 0x4a, 0xa0, 0x88, 0x4a, 0xa8, 0x11, 0x52,
1115
        0xaa, 0x15, 0x54, 0xaa, 0x15, 0x55, 0x28, 0x55,
1139
        0xaa, 0x15, 0x54, 0xaa, 0x15, 0x55, 0x28, 0x55,
1116
        0x55, 0x41, 0x55, 0x55, 0x55, 0x55};
1140
        0x55, 0x41, 0x55, 0x55, 0x55, 0x55};
1117
 
1141
 
1118
 
1142
 
1119
        // flashing more than 8 chars per time is not profen to be safe
1143
        // flashing more than 8 chars per time is not proven to be safe
-
 
1144
        // so take care
1120
        // so take care
1145
#if WRITECHARS == 200
1121
    /*learn_char(200, cc8);
1146
    learn_char(200, cc8);
1122
    learn_char(201, cc9);
1147
    learn_char(201, cc9);
1123
    learn_char(202, cca);
1148
    learn_char(202, cca);
1124
    learn_char(203, ccb);
1149
    learn_char(203, ccb);
1125
    learn_char(204, ccc);
1150
    learn_char(204, ccc);
1126
    learn_char(205, ccd);
1151
    learn_char(205, ccd);
1127
    learn_char(206, cce);
1152
    learn_char(206, cce);
1128
    learn_char(207, ccf);*/
1153
    learn_char(207, ccf);
-
 
1154
#endif
-
 
1155
#if WRITECHARS == 208
1129
    /*learn_char(208, cd0);
1156
    learn_char(208, cd0);
1130
    learn_char(209, cd1);
1157
    learn_char(209, cd1);
1131
    learn_char(210, cd2);
1158
    learn_char(210, cd2);
1132
    learn_char(211, cd3);
1159
    learn_char(211, cd3);
1133
    learn_char(212, cd4);
1160
    learn_char(212, cd4);
1134
    learn_char(213, cd5);
1161
    learn_char(213, cd5);
1135
    learn_char(214, cd6);
1162
    learn_char(214, cd6);
1136
    learn_char(215, cd7);*/
1163
    learn_char(215, cd7);
-
 
1164
#endif
-
 
1165
#if WRITECHARS == 216
1137
    /*learn_char(216, cd8);
1166
    learn_char(216, cd8);
1138
        learn_char(217, cd9);
1167
        learn_char(217, cd9);
1139
    learn_char(218, cda);
1168
    learn_char(218, cda);
1140
    learn_char(219, cdb);
1169
    learn_char(219, cdb);
1141
    learn_char(220, cdc);
1170
    learn_char(220, cdc);
1142
    learn_char(221, cdd);
1171
    learn_char(221, cdd);
1143
    learn_char(222, cde);
1172
    learn_char(222, cde);
1144
    learn_char(223, cdf);*/
1173
    learn_char(223, cdf);
-
 
1174
#endif
-
 
1175
#if WRITECHARS == 224
1145
    /*learn_char(224, ce0);
1176
    learn_char(224, ce0);
1146
        learn_char(225, ce1);
1177
        learn_char(225, ce1);
1147
        learn_char(226, ce2);
1178
        learn_char(226, ce2);
1148
        learn_char(227, ce3);
1179
        learn_char(227, ce3);
1149
        learn_char(228, ce4);
1180
        learn_char(228, ce4);
1150
        learn_char(229, ce5);
1181
        learn_char(229, ce5);
1151
        learn_char(230, ce6);
1182
        learn_char(230, ce6);
1152
        learn_char(231, ce7);*/
1183
        learn_char(231, ce7);
1153
#endif
1184
#endif
-
 
1185
#endif // write char general
1154
    /* ##########################################################################
1186
    /* ##########################################################################
1155
     * continue normal main
1187
     * continue normal main
1156
     * ##########################################################################*/
1188
     * ##########################################################################*/
-
 
1189
       
1157
#if NTSC
1190
        // Setup Video Mode
-
 
1191
        uint8_t top_line = 1;
-
 
1192
        uint8_t bottom_line = 0;
-
 
1193
        if (COSD_FLAGS & COSD_FLAG_NTSC) {
1158
    // NTSC + enable display immediately (VM0)
1194
        // NTSC + enable display immediately (VM0)
1159
    spi_send_byte(0x00, 0b00001000);
1195
        spi_send_byte(0x00, 0b00001000);
-
 
1196
                bottom_line = 12;
1160
#else
1197
        } else {
1161
    // PAL + enable display immediately (VM0)
1198
        // PAL + enable display immediately (VM0)
1162
    spi_send_byte(0x00, 0b01001000);
1199
        spi_send_byte(0x00, 0b01001000);
-
 
1200
                bottom_line = 14;
1163
#endif
1201
        }
1164
 
1202
 
1165
    // clear all display-mem (DMM)
1203
    // clear all display-mem (DMM)
1166
    spi_send_byte(0x04, 0b00000100);
1204
    spi_send_byte(0x04, 0b00000100);
1167
 
1205
 
1168
    // clearing takes 12uS according to maxim so lets wait longer
1206
    // clearing takes 12uS according to maxim so lets wait longer
1169
    _delay_us(120);
1207
    _delay_us(120);
1170
 
1208
 
1171
    // 8bit mode
1209
    // 8bit mode
1172
    spi_send_byte(0x04, 0b01000000);
1210
    spi_send_byte(0x04, 0b01000000);
1173
 
1211
 
1174
    // write blank chars to whole screen
1212
    // write blank chars to whole screen
1175
    clear();
1213
    clear();
1176
 
1214
 
1177
#if !(ALLCHARSDEBUG|WRITECHARS)
1215
#if !(ALLCHARSDEBUG|WRITECHARS)
1178
    // init usart
1216
    // init usart
1179
    usart1_init();
1217
    usart1_init();
1180
 
1218
 
1181
    // set up timer
1219
    // set up timer
1182
    TCCR0 |= (1 << CS00) | (1 << CS01); // timer0 prescaler 64
1220
    TCCR0 |= (1 << CS00) | (1 << CS01); // timer0 prescaler 64
1183
    OCR0 = 6; // preload
1221
    OCR0 = 6; // preload
1184
    TIMSK |= (1 << TOIE0); // enable overflow timer0
1222
    TIMSK |= (1 << TOIE0); // enable overflow timer0
1185
 
1223
 
1186
    // unmask interrupts
1224
    // unmask interrupts
1187
    sei();
1225
    sei();
1188
#endif
1226
#endif
1189
 
1227
 
1190
    //write_ascii_string(2,  7, "         CaScAdE          ");
1228
    //write_ascii_string(2,  7, "         CaScAdE          ");
1191
    //write_ascii_string(2,  8, "is TESTING his open source");
1229
    //write_ascii_string(2,  8, "is TESTING his open source");
1192
    //write_ascii_string(2,  9, "    EPi OSD Firmware");
1230
    //write_ascii_string(2,  9, "    EPi OSD Firmware");
1193
    //write_ascii_string(2, 10, "Scheiss Kompass");
1231
    //write_ascii_string(2, 10, "Scheiss Kompass");
1194
 
1232
 
1195
 
1233
 
1196
 
1234
 
1197
 
1235
 
1198
    // custom char preview
1236
    // custom char preview
1199
    /*write_char_xy( 2, 7, 200);
1237
    /*write_char_xy( 2, 7, 200);
1200
    write_char_xy( 3, 7, 201);
1238
    write_char_xy( 3, 7, 201);
1201
    write_char_xy( 4, 7, 202);
1239
    write_char_xy( 4, 7, 202);
1202
    write_char_xy( 5, 7, 203);
1240
    write_char_xy( 5, 7, 203);
1203
    write_char_xy( 6, 7, 204);
1241
    write_char_xy( 6, 7, 204);
1204
    write_char_xy( 7, 7, 205);
1242
    write_char_xy( 7, 7, 205);
1205
    write_char_xy( 8, 7, 206);
1243
    write_char_xy( 8, 7, 206);
1206
    write_char_xy( 9, 7, 207);
1244
    write_char_xy( 9, 7, 207);
1207
    write_char_xy(10, 7, 208);
1245
    write_char_xy(10, 7, 208);
1208
    write_char_xy(11, 7, 209);
1246
    write_char_xy(11, 7, 209);
1209
    write_char_xy(12, 7, 210);
1247
    write_char_xy(12, 7, 210);
1210
    write_char_xy(13, 7, 211);
1248
    write_char_xy(13, 7, 211);
1211
    write_char_xy(14, 7, 212);
1249
    write_char_xy(14, 7, 212);
1212
    write_char_xy(15, 7, 213);
1250
    write_char_xy(15, 7, 213);
1213
    write_char_xy(16, 7, 214);
1251
    write_char_xy(16, 7, 214);
1214
    write_char_xy(17, 7, 215);*/
1252
    write_char_xy(17, 7, 215);*/
1215
 
1253
 
1216
    // we are ready
1254
    // we are ready
1217
    LED3_ON
1255
    LED3_ON
1218
 
1256
 
1219
 
1257
 
1220
 
1258
 
1221
#if ALLCHARSDEBUG | WRITECHARS
1259
#if ALLCHARSDEBUG | WRITECHARS
1222
        clear();
1260
        clear();
1223
    write_all_chars();
1261
    write_all_chars();
1224
#else
1262
#else
1225
    // clear serial screen
1263
    // clear serial screen
1226
    //usart1_puts("\x1B[2J\x1B[H");
1264
    //usart1_puts("\x1B[2J\x1B[H");
1227
    //usart1_puts("hello world!\r\n");
1265
    //usart1_puts("hello world!\r\n");
1228
 
1266
 
1229
   
1267
   
1230
    // request data ever 100ms from FC
1268
    // request data ever 100ms from FC
1231
        //unsigned char ms = 10;
1269
        //unsigned char ms = 10;
1232
        //sendMKData('d', 0, &ms, 1);
1270
        //sendMKData('d', 0, &ms, 1);
1233
     
1271
     
1234
    // request OSD Data from NC every 100ms
1272
    // request OSD Data from NC every 100ms
1235
        unsigned char ms = 10;
1273
        unsigned char ms = 10;
1236
    sendMKData('o', 1, &ms, 1);
1274
    sendMKData('o', 1, &ms, 1);
1237
        // and disable debug...
1275
        // and disable debug...
1238
        //ms = 0;
1276
        //ms = 0;
1239
        //sendMKData('d', 0, &ms, 1);
1277
        //sendMKData('d', 0, &ms, 1);
1240
 
-
 
1241
    uint8_t top_line = 1;
-
 
1242
#if NTSC
-
 
1243
    uint8_t bottom_line = 12;
-
 
1244
#else
-
 
1245
    uint8_t bottom_line = 14;
-
 
1246
#endif
1278
 
1247
        // stats for after flight
1279
        // stats for after flight
1248
        int16_t max_Altimeter = 0;
1280
        int16_t max_Altimeter = 0;
1249
        uint16_t max_GroundSpeed = 0;
1281
        uint16_t max_GroundSpeed = 0;
1250
        int16_t max_Distance = 0;
1282
        int16_t max_Distance = 0;
-
 
1283
        uint8_t min_UBat = 255;
-
 
1284
        uint16_t max_FlyingTime = 0;
1251
 
1285
 
1252
        // flags from last round to check for changes
1286
        // flags from last round to check for changes
1253
        uint8_t old_MKFlags = 0;
1287
        uint8_t old_MKFlags = 0;
1254
       
1288
       
1255
    // write fix characters, only update the data dependend
1289
    // write fix characters, only update the data dependend
1256
    write_char_xy(5, top_line, 203); // km/h
1290
    write_char_xy(5, top_line, 203); // km/h
1257
    write_char_xy(10, top_line, 202); // RC-transmitter
1291
    write_char_xy(10, top_line, 202); // RC-transmitter
1258
    write_char_xy(16, top_line, 208); // degree symbol
1292
    write_char_xy(16, top_line, 208); // degree symbol
1259
    write_char_xy(27, top_line, 204); // small meters m
1293
    write_char_xy(27, top_line, 204); // small meters m
1260
    write_ascii_string(6, bottom_line, "V"); // voltage
1294
    write_ascii_string(6, bottom_line, "V"); // voltage
1261
    write_char_xy(14, bottom_line, 209); // on clock
1295
    write_char_xy(14, bottom_line, 209); // on clock
1262
    write_char_xy(22, bottom_line, 210); // fly clock
1296
    write_char_xy(22, bottom_line, 210); // fly clock
1263
    write_char_xy(26, bottom_line, 200); // sat1
1297
    write_char_xy(26, bottom_line, 200); // sat1
1264
    write_char_xy(27, bottom_line, 201); // sat2
1298
    write_char_xy(27, bottom_line, 201); // sat2
1265
 
1299
 
1266
    char* directions[8] = {"NE", "E ", "SE", "S ", "SW", "W ", "NW", "N "};
1300
    char* directions[8] = {"NE", "E ", "SE", "S ", "SW", "W ", "NW", "N "};
1267
        char arrowdir[8] =   { 218,  217,  224,  223,  222,  221,  220, 219};
1301
        char arrowdir[8] =   { 218,  217,  224,  223,  222,  221,  220, 219};
1268
 
1302
 
1269
    while (1) {
1303
    while (1) {
1270
        if (rxd_buffer_locked) {
1304
        if (rxd_buffer_locked) {
1271
            if (rxd_buffer[2] == 'D') { // FC Data
1305
            if (rxd_buffer[2] == 'D') { // FC Data
1272
                /*Decode64();
1306
                /*Decode64();
1273
                debugData = *((DebugOut_t*) pRxData);
1307
                debugData = *((DebugOut_t*) pRxData);
1274
                write_number_s(12, 2, RxDataLen);
1308
                write_number_s(12, 2, RxDataLen);
1275
                write_number_s(20, 2, setsReceived++);
1309
                write_number_s(20, 2, setsReceived++);
1276
                write_number_s(12, 3, debugData.Analog[0]);
1310
                write_number_s(12, 3, debugData.Analog[0]);
1277
                write_number_s(12, 4, debugData.Analog[2]);
1311
                write_number_s(12, 4, debugData.Analog[2]);
1278
                write_number_s(12, 5, debugData.Analog[1]);
1312
                write_number_s(12, 5, debugData.Analog[1]);
1279
                write_number_s(12, 6, debugData.Analog[3]);
1313
                write_number_s(12, 6, debugData.Analog[3]);
1280
                write_number_s(12, 7, debugData.Analog[9]);
1314
                write_number_s(12, 7, debugData.Analog[9]);
1281
                write_number_s(12, 8, debugData.Analog[10]);
1315
                write_number_s(12, 8, debugData.Analog[10]);
1282
                                write_number_s(12, 4, debugData.Analog[12]);
1316
                                write_number_s(12, 4, debugData.Analog[12]);
1283
                                write_number_s(12, 5, debugData.Analog[13]);
1317
                                write_number_s(12, 5, debugData.Analog[13]);
1284
                                write_number_s(12, 6, debugData.Analog[14]);
1318
                                write_number_s(12, 6, debugData.Analog[14]);
1285
                                write_number_s(12, 7, debugData.Analog[15]);*/
1319
                                write_number_s(12, 7, debugData.Analog[15]);*/
1286
            } else if (rxd_buffer[2] == 'O') { // NC OSD Data
1320
            } else if (rxd_buffer[2] == 'O') { // NC OSD Data
1287
                Decode64();
1321
                Decode64();
1288
                naviData = *((NaviData_t*) pRxData);
1322
                naviData = *((NaviData_t*) pRxData);
1289
 
1323
 
1290
                                // first line
1324
                                // first line
1291
                                write_3digit_number_u(2, top_line, (uint16_t)(((uint32_t)naviData.GroundSpeed*36)/1000));
1325
                                write_3digit_number_u(2, top_line, (uint16_t)(((uint32_t)naviData.GroundSpeed*36)/1000));
1292
 
1326
 
1293
                write_3digit_number_u(7, top_line, naviData.RC_Quality);
1327
                write_3digit_number_u(7, top_line, naviData.RC_Quality);
1294
                if (naviData.RC_Quality <= RCLVL_WRN && last_RC_Quality > RCLVL_WRN) {
1328
                if (naviData.RC_Quality <= RCLVL_WRN && last_RC_Quality > RCLVL_WRN) {
1295
                    for (uint8_t x = 0; x < 4; x++)
1329
                    for (uint8_t x = 0; x < 4; x++)
1296
                        write_char_att_xy(7 + x, top_line, BLINK);
1330
                        write_char_att_xy(7 + x, top_line, BLINK);
1297
                } else if (naviData.RC_Quality > RCLVL_WRN && last_RC_Quality <= RCLVL_WRN) {
1331
                } else if (naviData.RC_Quality > RCLVL_WRN && last_RC_Quality <= RCLVL_WRN) {
1298
                    for (uint8_t x = 0; x < 4; x++)
1332
                    for (uint8_t x = 0; x < 4; x++)
1299
                        write_char_att_xy(7 + x, top_line, 0);
1333
                        write_char_att_xy(7 + x, top_line, 0);
1300
                }
1334
                }
1301
                last_RC_Quality = naviData.RC_Quality;
1335
                last_RC_Quality = naviData.RC_Quality;
1302
 
1336
 
1303
                write_3digit_number_u(13, top_line, naviData.CompassHeading);
1337
                write_3digit_number_u(13, top_line, naviData.CompassHeading);
1304
 
1338
 
1305
                write_ascii_string(17, top_line, directions[heading_conv(naviData.CompassHeading)]);
1339
                write_ascii_string(17, top_line, directions[heading_conv(naviData.CompassHeading)]);
1306
 
1340
 
1307
                if (naviData.Variometer == 0) {
1341
                if (naviData.Variometer == 0) {
1308
                    write_char_xy(20, top_line, 206); // plain line
1342
                    write_char_xy(20, top_line, 206); // plain line
1309
                } else if (naviData.Variometer > 0) {
1343
                } else if (naviData.Variometer > 0) {
1310
                    write_char_xy(20, top_line, 207); // arrow up
1344
                    write_char_xy(20, top_line, 207); // arrow up
1311
                } else {
1345
                } else {
1312
                    write_char_xy(20, top_line, 205); // arrow down
1346
                    write_char_xy(20, top_line, 205); // arrow down
1313
                }
1347
                }
1314
 
1348
 
1315
                                // TODO: is this really dm?
1349
                                // TODO: is this really dm?
1316
                write_number_s(22, top_line, naviData.Altimeter/10);
1350
                write_number_s(22, top_line, naviData.Altimeter/10);
1317
 
1351
 
1318
                                // seccond line
1352
                                // seccond line
1319
                draw_compass(11, top_line + 1, naviData.CompassHeading);
1353
                draw_compass(11, top_line + 1, naviData.CompassHeading);
1320
 
1354
 
1321
                                // TODO: verify correctness
1355
                                // TODO: verify correctness
1322
                                uint16_t heading_home = (naviData.HomePositionDeviation.Bearing + 360 - naviData.CompassHeading) % 360;
1356
                                uint16_t heading_home = (naviData.HomePositionDeviation.Bearing + 360 - naviData.CompassHeading) % 360;
1323
                                write_char_xy(27, top_line + 1, arrowdir[heading_conv(heading_home)]);
1357
                                write_char_xy(27, top_line + 1, arrowdir[heading_conv(heading_home)]);
1324
 
1358
 
1325
       
1359
       
1326
                                write_number_s(22, top_line + 1, naviData.HomePositionDeviation.Distance);
1360
                                write_number_s(22, top_line + 1, naviData.HomePositionDeviation.Distance);
1327
 
1361
 
1328
                                // center
1362
                                // center
1329
                                if (naviData.MKFlags & FLAG_MOTOR_RUN) { // should be engines running
1363
                                if (naviData.MKFlags & FLAG_MOTOR_RUN) { // should be engines running
1330
                                        if (!(old_MKFlags & FLAG_MOTOR_RUN)) { // motors just started, clear middle
1364
                                        if (!(old_MKFlags & FLAG_MOTOR_RUN)) { // motors just started, clear middle
1331
                                                for (uint8_t x = 0; x < 30; x++) {
1365
                                                for (uint8_t x = 0; x < 30; x++) {
1332
                                                        write_char_xy(x, 5, 0);
1366
                                                        write_char_xy(x, 5, 0);
1333
                                                        write_char_xy(x, 7, 0);
1367
                                                        write_char_xy(x, 7, 0);
1334
                                                        write_char_xy(x, 9, 0);
1368
                                                        write_char_xy(x, 9, 0);
1335
                                                }
1369
                                                }
1336
                                        }
1370
                                        }
1337
#if ARTHORIZON
1371
                                if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) {
1338
                                draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll);
1372
                                        draw_artificial_horizon(top_line + 2, bottom_line - 1, naviData.AngleNick, naviData.AngleRoll);
1339
#endif
1373
                                }
1340
                                } else {
1374
                                } else {
1341
                                        // stats
1375
                                        // stats
1342
                                        write_ascii_string(2, 5, "max Altitude:");
1376
                                        write_ascii_string(2, 5, "max Altitude:");
1343
                                        write_number_s(17, 5, max_Altimeter/10);
1377
                                        write_number_s(17, 5, max_Altimeter/10);
1344
                                        write_char_xy(22, 5, 204); // small meters m
1378
                                        write_char_xy(22, 5, 204); // small meters m
1345
                                        write_ascii_string(2, 7, "max Speed   :");
1379
                                        write_ascii_string(2, 6, "max Speed   :");
1346
                                        write_3digit_number_u(19, 7, (uint16_t)(((uint32_t)max_GroundSpeed*36)/1000));
1380
                                        write_3digit_number_u(19, 6, (uint16_t)(((uint32_t)max_GroundSpeed*36)/1000));
1347
                                        write_char_xy(22, 7, 203); // km/h
1381
                                        write_char_xy(22, 6, 203); // km/h
1348
                                        write_ascii_string(2, 9, "max Distance:");
1382
                                        write_ascii_string(2, 7, "max Distance:");
1349
                                        write_number_s(17, 9, max_Distance/100);
1383
                                        write_number_s(17, 7, max_Distance/100);
1350
                                        write_char_xy(22, 9, 204); // small meters m
1384
                                        write_char_xy(22, 7, 204); // small meters m
-
 
1385
                                        write_ascii_string(2, 8, "min voltage :");
-
 
1386
                                        //write_number_s(17, 8, min_UBat/10);
-
 
1387
                                        write_number_u_10th(16, 8, min_UBat);
-
 
1388
                                        write_ascii_string(22, 8, "V"); // voltage
-
 
1389
                                        write_ascii_string(2, 9, "max time    :");
-
 
1390
                                        write_number_s(17, 9, max_FlyingTime);
-
 
1391
                                        write_char_xy(22, 9, 210); // fly clock
1351
                                }
1392
                                }
1352
 
1393
 
1353
                                // bottom line
1394
                                // bottom line
1354
                write_number_u_10th(0, bottom_line, naviData.UBat);
1395
                write_number_u_10th(0, bottom_line, naviData.UBat);
1355
                if (naviData.UBat <= UBAT_WRN && last_UBat > UBAT_WRN) {
1396
                if (naviData.UBat <= UBAT_WRN && last_UBat > UBAT_WRN) {
1356
                    for (uint8_t x = 0; x < 7; x++)
1397
                    for (uint8_t x = 0; x < 7; x++)
1357
                        write_char_att_xy(x, bottom_line, BLINK);
1398
                        write_char_att_xy(x, bottom_line, BLINK);
1358
                } else {
1399
                } else {
1359
                    for (uint8_t x = 0; x < 7; x++)
1400
                    for (uint8_t x = 0; x < 7; x++)
1360
                        write_char_att_xy(x, bottom_line, 0);
1401
                        write_char_att_xy(x, bottom_line, 0);
1361
                }
1402
                }
1362
 
1403
 
1363
                write_time(8, bottom_line, uptime);
1404
                write_time(8, bottom_line, uptime);
1364
                write_time(16, bottom_line, naviData.FlyingTime);
1405
                write_time(16, bottom_line, naviData.FlyingTime);
1365
 
1406
 
1366
                write_3digit_number_u(23, bottom_line, naviData.SatsInUse);
1407
                write_3digit_number_u(23, bottom_line, naviData.SatsInUse);
1367
 
1408
 
1368
                                if (naviData.NCFlags & NC_FLAG_CH) {
1409
                                if (naviData.NCFlags & NC_FLAG_CH) {
1369
                                        write_char_xy(27, bottom_line, 231);    // gps ch
1410
                                        write_char_xy(27, bottom_line, 231);    // gps ch
1370
                                } else if (naviData.NCFlags & NC_FLAG_PH) {
1411
                                } else if (naviData.NCFlags & NC_FLAG_PH) {
1371
                                        write_char_xy(27, bottom_line, 230);    // gps ph
1412
                                        write_char_xy(27, bottom_line, 230);    // gps ph
1372
                                } else { // (naviData.NCFlags & NC_FLAG_FREE)
1413
                                } else { // (naviData.NCFlags & NC_FLAG_FREE)
1373
                                        write_char_xy(27, bottom_line, 201);    // sat2 (free)
1414
                                        write_char_xy(27, bottom_line, 201);    // sat2 (free)
1374
                                }
1415
                                }
1375
 
1416
 
1376
                //write_number_s(8, 5, RxDataLen);
1417
                //write_number_s(8, 5, RxDataLen);
1377
                //write_number_s(16, 5, setsReceived++);
1418
                //write_number_s(16, 5, setsReceived++);
1378
 
1419
 
1379
                                // remember statistics
1420
                                // remember statistics
1380
                                if (naviData.Altimeter > max_Altimeter) max_Altimeter = naviData.Altimeter;
1421
                                if (naviData.Altimeter > max_Altimeter) max_Altimeter = naviData.Altimeter;
1381
                                if (naviData.GroundSpeed > max_GroundSpeed) max_GroundSpeed = naviData.GroundSpeed;
1422
                                if (naviData.GroundSpeed > max_GroundSpeed) max_GroundSpeed = naviData.GroundSpeed;
1382
                                if (naviData.HomePositionDeviation.Distance > max_Distance) {
1423
                                if (naviData.HomePositionDeviation.Distance > max_Distance) {
1383
                                        max_Distance = naviData.HomePositionDeviation.Distance;
1424
                                        max_Distance = naviData.HomePositionDeviation.Distance;
1384
                                }
1425
                                }
-
 
1426
                                if (naviData.UBat < min_UBat) min_UBat = naviData.UBat;
-
 
1427
                                if (naviData.FlyingTime > max_FlyingTime) max_FlyingTime = naviData.FlyingTime;
-
 
1428
                               
1385
                                old_MKFlags = naviData.MKFlags;
1429
                                old_MKFlags = naviData.MKFlags;
1386
            }
1430
            }
1387
            rxd_buffer_locked = 0;
1431
            rxd_buffer_locked = 0;
1388
        }
1432
        }
1389
        // handle keypress
1433
        // handle keypress
1390
        if (S1_PRESSED) {
1434
        if (S1_PRESSED) {
1391
            uptime = 0;
1435
            uptime = 0;
1392
            _delay_ms(100);
1436
            _delay_ms(100);
1393
        }
1437
        }
1394
        if (S2_PRESSED) {
1438
        if (S2_PRESSED