Subversion Repositories Projects

Rev

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

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