Subversion Repositories Projects

Rev

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

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