Subversion Repositories Projects

Rev

Rev 2099 | Rev 2598 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2099 Rev 2225
1
/****************************************************************************
1
/****************************************************************************
2
 *   Copyright (C) 2009-2015 by Claas Anders "CaScAdE" Rathje               *
2
 *   Copyright (C) 2009-2016 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
#include "main.h"
21
#include "main.h"
22
#include <avr/io.h>
22
#include <avr/io.h>
23
#include <avr/eeprom.h>
23
#include <avr/eeprom.h>
24
#include <avr/pgmspace.h>
24
#include <avr/pgmspace.h>
25
#include <avr/interrupt.h>
25
#include <avr/interrupt.h>
26
#include <util/delay.h>
26
#include <util/delay.h>
27
#include <string.h>
27
#include <string.h>
28
#include "max7456_software_spi.h"
28
#include "max7456_software_spi.h"
29
#include "config.h"
29
#include "config.h"
30
#include "buttons.h"
30
#include "buttons.h"
31
#include "usart1.h"
31
#include "usart1.h"
32
#include "osd_helpers.h"
32
#include "osd_helpers.h"
33
 
33
 
34
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
34
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
35
 
35
 
36
// EEPROM bytes
36
// EEPROM bytes
37
uint8_t EEMEM ee_checkbyte1 = CHECKBYTE1;
37
uint8_t EEMEM ee_checkbyte1 = CHECKBYTE1;
38
uint8_t EEMEM ee_checkbyte2 = CHECKBYTE2;
38
uint8_t EEMEM ee_checkbyte2 = CHECKBYTE2;
39
uint8_t EEMEM ee_COSD_FLAGS_MODES = 0;
39
uint8_t EEMEM ee_COSD_FLAGS_MODES = 0;
40
uint8_t EEMEM ee_COSD_FLAGS_CONFIG = 0;
40
uint8_t EEMEM ee_COSD_FLAGS_CONFIG = 0;
41
uint8_t EEMEM ee_COSD_DISPLAYMODE = 0;
41
uint8_t EEMEM ee_COSD_DISPLAYMODE = 0;
42
uint8_t EEMEM ee_COSD_SCOPE [12] = {
42
uint8_t EEMEM ee_COSD_SCOPE [12] = {
43
    5, 5, 0,
43
    5, 5, 0,
44
    25, 5, 0,
44
    25, 5, 0,
45
    5, 10, 0,
45
    5, 10, 0,
46
    25, 10, 0
46
    25, 10, 0
47
};
47
};
48
 
48
 
49
// video modes
49
// video modes
50
const char VM_PAL[] PROGMEM = "PAL ";
50
const char VM_PAL[] PROGMEM = "PAL ";
51
const char VM_NTSC[] PROGMEM = "NTSC";
51
const char VM_NTSC[] PROGMEM = "NTSC";
52
 
52
 
53
#if FCONLY
53
#if FCONLY
54
    const displaymode_t * mode = fcdisplaymodes;
54
    const displaymode_t * mode = fcdisplaymodes;
55
#else
55
#else
56
        const displaymode_t * mode = ncdisplaymodes;
56
        const displaymode_t * mode = ncdisplaymodes;
57
#endif
57
#endif
58
 
58
 
59
/**
59
/**
60
 * read data saved in eeprom, print out message if <verbose> is set
60
 * read data saved in eeprom, print out message if <verbose> is set
61
 */
61
 */
62
void get_eeprom(uint8_t verbose) {
62
void get_eeprom(uint8_t verbose) {
63
    if (eeprom_read_byte(&ee_checkbyte1) == CHECKBYTE1 && eeprom_read_byte(&ee_checkbyte2) == CHECKBYTE2) {
63
    if (eeprom_read_byte(&ee_checkbyte1) == CHECKBYTE1 && eeprom_read_byte(&ee_checkbyte2) == CHECKBYTE2) {
64
        if (verbose) write_ascii_string_pgm(2, 6, PSTR("Loading from EEPROM")); // Loading data
64
        if (verbose) write_ascii_string_pgm(2, 6, PSTR("Loading from EEPROM")); // Loading data
65
        COSD_FLAGS_MODES = eeprom_read_byte(&ee_COSD_FLAGS_MODES);
65
        COSD_FLAGS_MODES = eeprom_read_byte(&ee_COSD_FLAGS_MODES);
66
        COSD_FLAGS_CONFIG = eeprom_read_byte(&ee_COSD_FLAGS_CONFIG);
66
        COSD_FLAGS_CONFIG = eeprom_read_byte(&ee_COSD_FLAGS_CONFIG);
67
        COSD_DISPLAYMODE = eeprom_read_byte(&ee_COSD_DISPLAYMODE);
67
        COSD_DISPLAYMODE = eeprom_read_byte(&ee_COSD_DISPLAYMODE);
68
        //if (verbose) write_ndigit_number_u(23, 11, COSD_DISPLAYMODE, 2, 0);
68
        //if (verbose) write_ndigit_number_u(23, 11, COSD_DISPLAYMODE, 2, 0);
69
        for (int i = 0; i < 12; i++) {
69
        for (int i = 0; i < 12; i++) {
70
            scope[i] = eeprom_read_byte(&ee_COSD_SCOPE[i]);
70
            scope[i] = eeprom_read_byte(&ee_COSD_SCOPE[i]);
71
        }
71
        }
72
    } else {
72
    } else {
73
        if (verbose) write_ascii_string_pgm(2, 6, PSTR("No Data in EEPROM")); // Loading data
73
        if (verbose) write_ascii_string_pgm(2, 6, PSTR("No Data in EEPROM")); // Loading data
74
    }
74
    }
75
}
75
}
76
 
76
 
77
/**
77
/**
78
 * save data to eeprom
78
 * save data to eeprom
79
 */
79
 */
80
void save_eeprom() {
80
void save_eeprom() {
81
    eeprom_write_byte(&ee_checkbyte1, CHECKBYTE1);
81
    eeprom_write_byte(&ee_checkbyte1, CHECKBYTE1);
82
    eeprom_write_byte(&ee_checkbyte2, CHECKBYTE2);
82
    eeprom_write_byte(&ee_checkbyte2, CHECKBYTE2);
83
    eeprom_write_byte(&ee_COSD_FLAGS_MODES, COSD_FLAGS_MODES);
83
    eeprom_write_byte(&ee_COSD_FLAGS_MODES, COSD_FLAGS_MODES);
84
    eeprom_write_byte(&ee_COSD_FLAGS_CONFIG, COSD_FLAGS_CONFIG);
84
    eeprom_write_byte(&ee_COSD_FLAGS_CONFIG, COSD_FLAGS_CONFIG);
85
    eeprom_write_byte(&ee_COSD_DISPLAYMODE, COSD_DISPLAYMODE);
85
    eeprom_write_byte(&ee_COSD_DISPLAYMODE, COSD_DISPLAYMODE);
86
    for (int i = 0; i < 12; i++) {
86
    for (int i = 0; i < 12; i++) {
87
        eeprom_write_byte(&ee_COSD_SCOPE[i], scope[i]);
87
        eeprom_write_byte(&ee_COSD_SCOPE[i], scope[i]);
88
    }
88
    }
89
}
89
}
90
 
90
 
91
/**
91
/**
92
 * auto config some stuff on startup, currently only battery cells
92
 * auto config some stuff on startup, currently only battery cells
93
 */
93
 */
94
void init_cosd(uint8_t UBat) {
94
void init_cosd(uint8_t UBat) {
95
    clear();
95
    clear();
96
 
96
 
97
    write_ascii_string_pgm(2, 1, PSTR("C-OSD"));
97
    write_ascii_string_pgm(2, 1, PSTR("C-OSD"));
98
    write_ascii_string_pgm(3, 2, PSTR("boot"));
98
    write_ascii_string_pgm(3, 2, PSTR("boot"));
99
    draw_logo(11, 1);
99
    draw_logo(11, 1);
100
 
100
 
101
    write_ascii_string_pgm(2, 5, PSTR(BUILDOSDBUILDDATE));
101
    write_ascii_string_pgm(2, 5, PSTR(BUILDOSDBUILDDATE));
102
 
102
 
103
    get_eeprom(1);
103
    get_eeprom(1);
104
 
104
 
105
    //write_ascii_string_pgm(23, 2, vm[COSD_FLAGS & COSD_FLAG_NTSC]);
105
    //write_ascii_string_pgm(23, 2, vm[COSD_FLAGS & COSD_FLAG_NTSC]);
106
    if (COSD_FLAGS_CONFIG & COSD_FLAG_NTSC) {
106
    if (COSD_FLAGS_CONFIG & COSD_FLAG_NTSC) {
107
        write_ascii_string_pgm(23, 1, VM_NTSC);
107
        write_ascii_string_pgm(23, 1, VM_NTSC);
108
    } else {
108
    } else {
109
        write_ascii_string_pgm(23, 1, VM_PAL);
109
        write_ascii_string_pgm(23, 1, VM_PAL);
110
    }
110
    }
111
 
111
 
112
 
112
 
113
 
113
 
114
    write_ascii_string_pgm(2, 7, PSTR("Setting  :"));
114
    write_ascii_string_pgm(2, 7, PSTR("Setting  :"));
115
    write_ascii_string_pgm(2, 8, PSTR("Battery:")); // Guessing Number of Cells
115
    write_ascii_string_pgm(2, 8, PSTR("Battery:")); // Guessing Number of Cells
116
       
116
       
117
    write_ascii_string_pgm(13, 8, PSTR("Cells")); // Number of Cells
117
    write_ascii_string_pgm(13, 8, PSTR("Cells")); // Number of Cells
118
    write_ascii_string_pgm(2, 9, PSTR("Warn:")); // Warn Voltage
118
    write_ascii_string_pgm(2, 9, PSTR("Warn:")); // Warn Voltage
119
       
119
       
120
    write_ascii_string_pgm(14, 9, PSTR("Max:")); // Max Voltage
120
    write_ascii_string_pgm(14, 9, PSTR("Max:")); // Max Voltage
121
 
121
 
122
#if FCONLY
122
#if FCONLY
123
    write_ascii_string_pgm(2, 4, PSTR("FC only Mode"));
123
    write_ascii_string_pgm(2, 4, PSTR("FC only Mode"));
124
#else
124
#else
125
    write_ascii_string_pgm(2, 4, PSTR("NaviCtrl Mode"));
125
    write_ascii_string_pgm(2, 4, PSTR("NaviCtrl Mode"));
126
 
126
 
127
    usart1_EnableTXD();
127
    usart1_EnableTXD();
128
    usart1_puts_pgm(PSTR(REQUEST_UART_TO_FC));
128
    usart1_puts_pgm(PSTR(REQUEST_UART_TO_FC));
129
    usart1_DisableTXD();
129
    usart1_DisableTXD();
130
#endif
130
#endif
131
 
131
 
132
paramset_serial setting;
132
paramset_serial setting;
133
 
133
 
134
//#define NOFCOMMUNICATION
134
//#define NOFCOMMUNICATION
135
#ifndef NOFCOMMUNICATION
135
#ifndef NOFCOMMUNICATION
136
    usart1_request_blocking('Q', PSTR(REQUEST_CURRENT_SETTING));
136
    usart1_request_blocking('Q', PSTR(REQUEST_CURRENT_SETTING));
137
        memcpy((char*)(&setting), (char*)pRxData, sizeof(paramset_serial));
137
        memcpy((char*)(&setting), (char*)pRxData, sizeof(paramset_serial));
138
 
138
 
139
        if (setting.param.Revision != EEPARAM_REVISION) {
139
        if (setting.param.Revision != EEPARAM_REVISION) {
140
                write_ascii_string_pgm(3, 11, PSTR("WRONG SETTINGS REVISION"));
140
                write_ascii_string_pgm(3, 11, PSTR("WRONG SETTINGS REVISION"));
141
                write_ascii_string_pgm(3, 12, PSTR("OSD:     FC:"));
141
                write_ascii_string_pgm(3, 12, PSTR("OSD:     FC:"));
142
        write_ndigit_number_u(8, 12, EEPARAM_REVISION, 3, 1);
142
        write_ndigit_number_u(8, 12, EEPARAM_REVISION, 3, 1);
143
        write_ndigit_number_u(15, 12, setting.param.Revision, 3, 1);
143
        write_ndigit_number_u(15, 12, setting.param.Revision, 3, 1);
144
                for (uint8_t i = 0; i < 120; i++) {_delay_ms(1000);}
144
                for (uint8_t i = 0; i < 120; i++) {_delay_ms(1000);}
145
        }
145
        }
146
 
146
 
147
#if FCONLY
147
#if FCONLY
148
#else
148
#else
149
        if (naviData.Version != NAVIDATA_VERSION) {
149
        if (naviData.Version != NAVIDATA_VERSION) {
150
                write_ascii_string_pgm(3, 11, PSTR("WRONG NAVIDATA VERSION"));
150
                write_ascii_string_pgm(3, 11, PSTR("WRONG NAVIDATA VERSION"));
151
                write_ascii_string_pgm(3, 12, PSTR("OSD:     FC:"));
151
                write_ascii_string_pgm(3, 12, PSTR("OSD:     FC:"));
152
        write_ndigit_number_u(8, 12, NAVIDATA_VERSION, 3, 1);
152
        write_ndigit_number_u(8, 12, NAVIDATA_VERSION, 3, 1);
153
        write_ndigit_number_u(15, 12, naviData.Version, 3, 1);
153
        write_ndigit_number_u(15, 12, naviData.Version, 3, 1);
154
                for (uint8_t i = 0; i < 120; i++) {_delay_ms(1000);}
154
                for (uint8_t i = 0; i < 120; i++) {_delay_ms(1000);}
155
        }
155
        }
156
#endif
156
#endif
157
 
157
 
158
    //setting = *((paramset_serial*)pRxData);
158
    //setting = *((paramset_serial*)pRxData);
159
#else 
159
#else 
160
        // manual stuff?        
160
        // manual stuff?        
161
        memcpy((char*)setting.param.Name, "NO FC COMMUN", 12);
161
        memcpy((char*)setting.param.Name, "NO FC COMMUN", 12);
162
        setting.param.UnterspannungsWarnung = 94;
162
        setting.param.UnterspannungsWarnung = 94;
163
#endif // #ifndef NOFCOMMUNICATION
163
#endif // #ifndef NOFCOMMUNICATION
164
    //write_ascii_char(4 + 12 * 30, rxd_buffer[2]);
164
    //write_ascii_char(4 + 12 * 30, rxd_buffer[2]);
165
 
165
 
166
   
166
   
167
 
167
 
168
    write_ndigit_number_u(10, 7, setting.SettingsIndex, 1, 1);
168
    write_ndigit_number_u(10, 7, setting.SettingsIndex, 1, 1);
169
    write_ascii_string_len(13, 7, setting.param.Name, 12);
169
    write_ascii_string_len(13, 7, setting.param.Name, 12);
170
 
170
 
171
    uint8_t cells = 0;
171
    uint8_t cells = 0;
172
    if (CELL_NUM == -1) {
172
    if (CELL_NUM == -1) {
173
#define MAX_CELL_VOLTAGE 43 // max cell volatage for LiPO
173
#define MAX_CELL_VOLTAGE 43 // max cell volatage for LiPO
174
 
174
 
175
        if (setting.param.UnterspannungsWarnung < 50) {
175
        if (setting.param.UnterspannungsWarnung < 50) {
176
            // up to 6s LiPo, less than 2s is technical impossible
176
            // up to 6s LiPo, less than 2s is technical impossible
177
            for (cells = 2; cells < 7; cells++) {
177
            for (cells = 2; cells < 7; cells++) {
178
                if (UBat < cells * MAX_CELL_VOLTAGE) break;
178
                if (UBat < cells * MAX_CELL_VOLTAGE) break;
179
            }
179
            }
180
 
180
 
181
            min_voltage = cells * setting.param.UnterspannungsWarnung;
181
            min_voltage = cells * setting.param.UnterspannungsWarnung;
182
        } else {
182
        } else {
183
            min_voltage = setting.param.UnterspannungsWarnung;
183
            min_voltage = setting.param.UnterspannungsWarnung;
184
            cells = min_voltage / CELL_VOLT_MIN;
184
            cells = min_voltage / CELL_VOLT_MIN;
185
        }
185
        }
186
        //write_ndigit_number_u(10, 13, setting.param.UnterspannungsWarnung, 3, 1);
186
        //write_ndigit_number_u(10, 13, setting.param.UnterspannungsWarnung, 3, 1);
187
    } else {
187
    } else {
188
        cells = CELL_NUM;
188
        cells = CELL_NUM;
189
        min_voltage = cells * CELL_VOLT_MIN;
189
        min_voltage = cells * CELL_VOLT_MIN;
190
    }
190
    }
191
 
191
 
192
    max_voltage = cells * CELL_VOLT_MAX;
192
    max_voltage = cells * CELL_VOLT_MAX;
193
 
193
 
194
    write_ndigit_number_u(11, 8, cells, 1, 0);
194
    write_ndigit_number_u(11, 8, cells, 1, 0);
195
    write_ndigit_number_s_10th(8, 9, min_voltage, 3, 0);
195
    write_ndigit_number_s_10th(8, 9, min_voltage, 3, 0);
196
    write_ndigit_number_s_10th(20, 9, max_voltage, 3, 0);
196
    write_ndigit_number_s_10th(20, 9, max_voltage, 3, 0);
197
 
197
 
198
 
198
 
199
 
199
 
200
    // request version from board
200
    // request version from board
201
#if FCONLY
201
#if FCONLY
202
    //usart1_request_mk_data(0, 'v', 0);
202
    //usart1_request_mk_data(0, 'v', 0);
203
    write_ascii_string_pgm(2, 11, PSTR("FC VERSION: ........"));
203
    write_ascii_string_pgm(2, 11, PSTR("FC VERSION: ........"));
204
    usart1_request_blocking('V', PSTR(REQUEST_FC_VERSION));
204
    usart1_request_blocking('V', PSTR(REQUEST_FC_VERSION));
205
#else
205
#else
206
    usart1_request_nc_uart();
206
    usart1_request_nc_uart();
207
    _delay_ms(200);
207
    _delay_ms(200);
208
    usart1_request_nc_uart();
208
    usart1_request_nc_uart();
209
 
209
 
210
    //usart1_request_mk_data(1, 'v', 0);
210
    //usart1_request_mk_data(1, 'v', 0);
211
    write_ascii_string_pgm(2, 11, PSTR("NC VERSION: ........"));
211
    write_ascii_string_pgm(2, 11, PSTR("NC VERSION: ........"));
212
    usart1_request_blocking('V', PSTR(REQUEST_NC_VERSION));
212
    usart1_request_blocking('V', PSTR(REQUEST_NC_VERSION));
213
#endif
213
#endif
214
    str_VersionInfo VersionInfo;
214
    str_VersionInfo VersionInfo;
215
    //VersionInfo = *((str_VersionInfo*)pRxData);
215
    //VersionInfo = *((str_VersionInfo*)pRxData);
216
        memcpy((char*)(&VersionInfo), (char*)pRxData, sizeof(str_VersionInfo));
216
        memcpy((char*)(&VersionInfo), (char*)pRxData, sizeof(str_VersionInfo));
217
 
217
 
218
    write_ndigit_number_u(14, 11, VersionInfo.SWMajor, 3, 1);
218
    write_ndigit_number_u(14, 11, VersionInfo.SWMajor, 3, 1);
219
    write_ndigit_number_u(18, 11, VersionInfo.SWMinor, 3, 1);
219
    write_ndigit_number_u(18, 11, VersionInfo.SWMinor, 3, 1);
220
    write_ascii_char(22 + 11 * 30, 'a' + VersionInfo.SWPatch);
220
    write_ascii_char(22 + 11 * 30, 'a' + VersionInfo.SWPatch);
221
    // end version request
221
    // end version request
222
 
222
 
223
 
223
 
224
 
224
 
225
 
225
 
226
#if FCONLY
226
#if FCONLY
227
    COSD_DISPLAYMODE %= (sizeof (fcdisplaymodes) / sizeof (displaymode_t));
227
    COSD_DISPLAYMODE %= (sizeof (fcdisplaymodes) / sizeof (displaymode_t));
228
    mode = fcdisplaymodes;
228
    mode = fcdisplaymodes;
229
    mode += COSD_DISPLAYMODE;
229
    mode += COSD_DISPLAYMODE;
230
    osd_fcmode = (int(*)(void)) pgm_read_word(&mode->dfun);
230
    osd_fcmode = (int(*)(void)) pgm_read_word(&mode->dfun);
231
    // re-request data ever 100ms from FC;
231
    // re-request data ever 100ms from FC;
232
    //usart1_request_mk_data(0, 'd', 100);
232
    //usart1_request_mk_data(0, 'd', 100);
233
#else
233
#else
234
    COSD_DISPLAYMODE %= (sizeof (ncdisplaymodes) / sizeof (displaymode_t));
234
    COSD_DISPLAYMODE %= (sizeof (ncdisplaymodes) / sizeof (displaymode_t));
235
    mode = ncdisplaymodes;
235
    mode = ncdisplaymodes;
236
    mode += COSD_DISPLAYMODE;
236
    mode += COSD_DISPLAYMODE;
237
    osd_ncmode = (int(*)(void)) pgm_read_word(&mode->dfun);
237
    osd_ncmode = (int(*)(void)) pgm_read_word(&mode->dfun);
238
    // re-request OSD Data from NC every 100ms
238
    // re-request OSD Data from NC every 100ms
239
    //usart1_request_mk_data(1, 'o', 100);
239
    //usart1_request_mk_data(1, 'o', 100);
240
#endif
240
#endif
241
 
241
 
242
    _delay_ms(5000);
242
    _delay_ms(5000);
243
    clear();
243
    clear();
244
    // update flags to paint display again because of clear
244
    // update flags to paint display again because of clear
245
    COSD_FLAGS_RUNTIME &= ~COSD_ICONS_WRITTEN;
245
    COSD_FLAGS_RUNTIME &= ~COSD_ICONS_WRITTEN;
246
 
246
 
247
    // we got data
247
    // we got data
248
    COSD_FLAGS_RUNTIME |= COSD_DATARECEIVED;
248
    COSD_FLAGS_RUNTIME |= COSD_DATARECEIVED;
249
}
249
}
250
 
250
 
251
/* ##########################################################################
251
/* ##########################################################################
252
 * A simple config menu for the flags
252
 * A simple config menu for the flags
253
 * ##########################################################################*/
253
 * ##########################################################################*/
254
 
254
 
255
/**
255
/**
256
 * helper function for flag display
256
 * helper function for flag display
257
 */
257
 */
258
void onoff(uint8_t col, uint8_t line, uint8_t onoff) {
258
void onoff(uint8_t col, uint8_t line, uint8_t onoff) {
259
    if (onoff) {
259
    if (onoff) {
260
        write_ascii_string_pgm(col, line, PSTR("ON "));
260
        write_ascii_string_pgm(col, line, PSTR("ON "));
261
    } else {
261
    } else {
262
        write_ascii_string_pgm(col, line, PSTR("OFF"));
262
        write_ascii_string_pgm(col, line, PSTR("OFF"));
263
    }
263
    }
264
}
264
}
265
 
265
 
266
/**
266
/**
267
 * helper function for menu updating
267
 * helper function for menu updating
268
 */
268
 */
269
void config_menu_drawings(uint8_t chosen) {
269
void config_menu_drawings(uint8_t chosen) {
270
    static uint8_t old_y = 0;
270
    static uint8_t old_y = 0;
271
    uint8_t x = MENU_LEFT, y = MENU_TOP, line = MENU_TOP;
271
    uint8_t x = MENU_LEFT, y = MENU_TOP, line = MENU_TOP;
272
    //************************************************* 13 to 14
272
    //************************************************* 13 to 14
273
    if (chosen > 6 && chosen < 15) { // right
273
    if (chosen > 6 && chosen < 15) { // right
274
        x = MENU_MIDDLE;
274
        x = MENU_MIDDLE;
275
        y = chosen - 7 + MENU_TOP;
275
        y = chosen - 7 + MENU_TOP;
276
    } else if (chosen < 8) {
276
    } else if (chosen < 8) {
277
        y = chosen + MENU_TOP;
277
        y = chosen + MENU_TOP;
278
    } else {
278
    } else {
279
        y = chosen - 7 + MENU_TOP;
279
        y = chosen - 7 + MENU_TOP;
280
    }
280
    }
281
 
281
 
282
    // clear prevoius _cursor_ and draw current
282
    // clear prevoius _cursor_ and draw current
283
    for (uint8_t myx = MENU_LEFT; myx < 29; myx++) {
283
    for (uint8_t myx = MENU_LEFT; myx < 29; myx++) {
284
        write_char_att_xy(myx, old_y, 0);
284
        write_char_att_xy(myx, old_y, 0);
285
        if (myx > x - 1 && myx < x + 14) {
285
        if (myx > x - 1 && myx < x + 14) {
286
            write_char_att_xy(myx, y, BLACKBG | INVERT);
286
            write_char_att_xy(myx, y, BLACKBG | INVERT);
287
        }
287
        }
288
    };
288
    };
289
 
289
 
290
    write_ascii_string_pgm(MENU_LEFT, line, PSTR("Video"));
290
    write_ascii_string_pgm(MENU_LEFT, line, PSTR("Video"));
291
    if (COSD_FLAGS_CONFIG & COSD_FLAG_NTSC) {
291
    if (COSD_FLAGS_CONFIG & COSD_FLAG_NTSC) {
292
        write_ascii_string_pgm(MENU_LEFT + 10, line, VM_NTSC);
292
        write_ascii_string_pgm(MENU_LEFT + 10, line, VM_NTSC);
293
    } else {
293
    } else {
294
        write_ascii_string_pgm(MENU_LEFT + 10, line, VM_PAL);
294
        write_ascii_string_pgm(MENU_LEFT + 10, line, VM_PAL);
295
    }
295
    }
296
 
296
 
297
    write_ascii_string_pgm(MENU_LEFT, ++line, PSTR("Full HUD"));
297
    write_ascii_string_pgm(MENU_LEFT, ++line, PSTR("Full HUD"));
298
    onoff(MENU_LEFT + 10, line, COSD_FLAGS_MODES & COSD_FLAG_HUD);
298
    onoff(MENU_LEFT + 10, line, COSD_FLAGS_MODES & COSD_FLAG_HUD);
299
 
299
 
300
    write_ascii_string_pgm(MENU_LEFT, ++line, PSTR("Horizon"));
300
    write_ascii_string_pgm(MENU_LEFT, ++line, PSTR("Horizon"));
301
    onoff(MENU_LEFT + 10, line, COSD_FLAGS_MODES & COSD_FLAG_ARTHORIZON);
301
    onoff(MENU_LEFT + 10, line, COSD_FLAGS_MODES & COSD_FLAG_ARTHORIZON);
302
 
302
 
303
    write_ascii_string_pgm(MENU_LEFT, ++line, PSTR("Aggr.Hor."));
303
    write_ascii_string_pgm(MENU_LEFT, ++line, PSTR("Aggr.Hor."));
304
    onoff(MENU_LEFT + 10, line, COSD_FLAGS_MODES & COSD_FLAG_AGGRHORIZON);
304
    onoff(MENU_LEFT + 10, line, COSD_FLAGS_MODES & COSD_FLAG_AGGRHORIZON);
305
 
305
 
306
    write_ascii_string_pgm(MENU_LEFT, ++line, PSTR("Stats"));
306
    write_ascii_string_pgm(MENU_LEFT, ++line, PSTR("Stats"));
307
    onoff(MENU_LEFT + 10, line, COSD_FLAGS_MODES & COSD_FLAG_STATS);
307
    onoff(MENU_LEFT + 10, line, COSD_FLAGS_MODES & COSD_FLAG_STATS);
308
 
308
 
309
    write_ascii_string_pgm(MENU_LEFT, ++line, PSTR("A by FC"));
309
    write_ascii_string_pgm(MENU_LEFT, ++line, PSTR("A by FC"));
310
    onoff(MENU_LEFT + 10, line, COSD_FLAGS_MODES & COSD_FLAG_FCCURRENT);
310
    onoff(MENU_LEFT + 10, line, COSD_FLAGS_MODES & COSD_FLAG_FCCURRENT);
311
 
311
 
312
    write_ascii_string_pgm(MENU_LEFT, ++line, PSTR("GPS Pos"));
312
    write_ascii_string_pgm(MENU_LEFT, ++line, PSTR("GPS Pos"));
313
    onoff(MENU_LEFT + 10, line, COSD_FLAGS_CONFIG & COSD_FLAG_SHOW_COORDS);
313
    onoff(MENU_LEFT + 10, line, COSD_FLAGS_CONFIG & COSD_FLAG_SHOW_COORDS);
314
 
314
 
315
    // 2nd col
315
    // 2nd col
316
    line = 2;
316
    line = 2;
317
 
317
 
318
    write_ascii_string_pgm(MENU_MIDDLE, line, PSTR("V C-Strom"));
318
    write_ascii_string_pgm(MENU_MIDDLE, line, PSTR("V C-Strom"));
319
    onoff(MENU_MIDDLE + 10, line, COSD_FLAGS_MODES & COSD_FLAG_STROMVOLT);
319
    onoff(MENU_MIDDLE + 10, line, COSD_FLAGS_MODES & COSD_FLAG_STROMVOLT);
320
 
320
 
321
    write_ascii_string_pgm(MENU_MIDDLE, ++line, PSTR("Height by"));
321
    write_ascii_string_pgm(MENU_MIDDLE, ++line, PSTR("Height by"));
322
    if (COSD_FLAGS_CONFIG & COSD_FLAG_GPSHEIGHT) {
322
    if (COSD_FLAGS_CONFIG & COSD_FLAG_GPSHEIGHT) {
323
        write_ascii_string_pgm(MENU_MIDDLE + 10, line, PSTR(" GPS"));
323
        write_ascii_string_pgm(MENU_MIDDLE + 10, line, PSTR(" GPS"));
324
    } else {
324
    } else {
325
        write_ascii_string_pgm(MENU_MIDDLE + 10, line, PSTR("BARO"));
325
        write_ascii_string_pgm(MENU_MIDDLE + 10, line, PSTR("BARO"));
326
    }
326
    }
327
 
327
 
328
    write_ascii_string_pgm(MENU_MIDDLE, ++line, PSTR("Feet/mph"));
328
    write_ascii_string_pgm(MENU_MIDDLE, ++line, PSTR("Feet/mph"));
329
    onoff(MENU_MIDDLE + 10, line, COSD_FLAGS_CONFIG & COSD_FLAG_FEET);
329
    onoff(MENU_MIDDLE + 10, line, COSD_FLAGS_CONFIG & COSD_FLAG_FEET);
330
 
330
 
331
    write_ascii_string_pgm(MENU_MIDDLE, ++line, PSTR("Big Vario"));
331
    write_ascii_string_pgm(MENU_MIDDLE, ++line, PSTR("Big Vario"));
332
    onoff(MENU_MIDDLE + 10, line, COSD_FLAGS_MODES & COSD_FLAG_BIGVARIO);
332
    onoff(MENU_MIDDLE + 10, line, COSD_FLAGS_MODES & COSD_FLAG_BIGVARIO);
333
 
333
 
334
    write_ascii_string_pgm(MENU_MIDDLE, ++line, PSTR("Big Speed"));
334
    write_ascii_string_pgm(MENU_MIDDLE, ++line, PSTR("Big Speed"));
335
    onoff(MENU_MIDDLE + 10, line, COSD_FLAGS_CONFIG & COSD_FLAG_BIGSPEED);
335
    onoff(MENU_MIDDLE + 10, line, COSD_FLAGS_CONFIG & COSD_FLAG_BIGSPEED);
336
 
336
 
337
    write_ascii_string_pgm(MENU_MIDDLE, ++line, PSTR("Passive"));
337
    write_ascii_string_pgm(MENU_MIDDLE, ++line, PSTR("Passive"));
338
    onoff(MENU_MIDDLE + 10, line, COSD_FLAGS_CONFIG & COSD_FLAG_PASSIVE);
338
    onoff(MENU_MIDDLE + 10, line, COSD_FLAGS_CONFIG & COSD_FLAG_PASSIVE);
339
 
339
 
340
    write_ascii_string_pgm(MENU_MIDDLE, ++line, PSTR("Cam Scope"));
340
    write_ascii_string_pgm(MENU_MIDDLE, ++line, PSTR("Cam Scope"));
341
    onoff(MENU_MIDDLE + 10, line, COSD_FLAGS_CONFIG & COSD_FLAG_SHOW_SCOPE);
341
    onoff(MENU_MIDDLE + 10, line, COSD_FLAGS_CONFIG & COSD_FLAG_SHOW_SCOPE);
342
 
342
 
343
    write_ascii_string_pgm(MENU_MIDDLE, ++line, PSTR("Move Scope"));
343
    write_ascii_string_pgm(MENU_MIDDLE, ++line, PSTR("Move Scope"));
344
 
344
 
345
 
345
 
346
    // bottom
346
    // bottom
347
    write_ascii_string_pgm(MENU_LEFT, 10, PSTR("Reset uptime"));
347
    write_ascii_string_pgm(MENU_LEFT, 10, PSTR("Reset uptime"));
348
 
348
 
349
    write_ascii_string_pgm(MENU_LEFT, 11, PSTR("Display Mode"));
349
    write_ascii_string_pgm(MENU_LEFT, 11, PSTR("Display Mode"));
350
    write_ascii_string_pgm(15, 11, (const char *)(pgm_read_word(&(mode->desc))));
350
    write_ascii_string_pgm(15, 11, (const char *)(pgm_read_word(&(mode->desc))));
351
 
351
 
352
    write_ascii_string_pgm(MENU_LEFT, 12, PSTR("Save config"));
352
    write_ascii_string_pgm(MENU_LEFT, 12, PSTR("Save config"));
353
    write_ascii_string_pgm(MENU_LEFT, 13, PSTR("EXIT"));
353
    write_ascii_string_pgm(MENU_LEFT, 13, PSTR("EXIT"));
354
 
354
 
355
    old_y = y;
355
    old_y = y;
356
}
356
}
357
 
357
 
358
/**
358
/**
359
 * some sort of clicking response in the menu
359
 * some sort of clicking response in the menu
360
 */
360
 */
361
void config_menu_doclick(uint8_t chosen) {
361
void config_menu_doclick(uint8_t chosen) {
362
    write_ascii_string_pgm(MENU_LEFT, chosen + MENU_TOP - 7, PSTR("DONE              "));
362
    write_ascii_string_pgm(MENU_LEFT, chosen + MENU_TOP - 7, PSTR("DONE              "));
363
    _delay_ms(500);
363
    _delay_ms(500);
364
    config_menu_drawings(chosen);
364
    config_menu_drawings(chosen);
365
}
365
}
366
 
366
 
367
/**
367
/**
368
 * move around the four scope edges
368
 * move around the four scope edges
369
 */
369
 */
370
void move_scope() {
370
void move_scope() {
371
    uint8_t mode = 0;
371
    uint8_t mode = 0;
372
    clear();
372
    clear();
373
    draw_scope();
373
    draw_scope();
374
    _delay_ms(500);
374
    _delay_ms(500);
375
    while (mode < 12) {
375
    while (mode < 12) {
376
        if (s2_pressed()) { // next
376
        if (s2_pressed()) { // next
377
            mode++;
377
            mode++;
378
            _delay_ms(500);
378
            _delay_ms(500);
379
        } else if (s1_pressed()) {
379
        } else if (s1_pressed()) {
380
            if (mode % 3 == 2) {
380
            if (mode % 3 == 2) {
381
                scope[mode] = (scope[mode] + 1) % 2;
381
                scope[mode] = (scope[mode] + 1) % 2;
382
            } else {
382
            } else {
383
                scope[mode] = (scope[mode] + 1) % ((mode % 3) % 2 == 0 ? 30 : bottom_line);
383
                scope[mode] = (scope[mode] + 1) % ((mode % 3) % 2 == 0 ? 30 : bottom_line);
384
            }
384
            }
385
            clear();
385
            clear();
386
            draw_scope();
386
            draw_scope();
387
            _delay_ms(100);
387
            _delay_ms(100);
388
        }
388
        }
389
    }
389
    }
390
    clear();
390
    clear();
391
}
391
}
392
 
392
 
393
/**
393
/**
394
 * a simple config menu tryout
394
 * a simple config menu tryout
395
 */
395
 */
396
void config_menu(void) {
396
void config_menu(void) {
397
    // disable interrupts (makes the menu more smoothely)
397
    // disable interrupts (makes the menu more smoothely)
398
    cli();
398
    cli();
399
 
399
 
400
    // clear screen
400
    // clear screen
401
    clear();
401
    clear();
402
 
402
 
403
    uint8_t chosen = 0;
403
    uint8_t chosen = 0;
404
    uint8_t inmenu = 1;
404
    uint8_t inmenu = 1;
405
    write_ascii_string_pgm(6, 1, PSTR("C-OSD Config Menu"));
405
    write_ascii_string_pgm(6, 1, PSTR("C-OSD Config Menu"));
406
 
406
 
407
    // wait a bit before doing stuff so user has chance to release button
407
    // wait a bit before doing stuff so user has chance to release button
408
    _delay_ms(250);
408
    _delay_ms(250);
409
 
409
 
410
    config_menu_drawings(chosen);
410
    config_menu_drawings(chosen);
411
 
411
 
412
    while (inmenu) {
412
    while (inmenu) {
413
        if (s2_pressed()) {
413
        if (s2_pressed()) {
414
            chosen = (chosen + 1) % 19;
414
            chosen = (chosen + 1) % 19;
415
            //if (chosen == 12) chosen = 13; // SKIP unused menu space for now
415
            //if (chosen == 12) chosen = 13; // SKIP unused menu space for now
416
            config_menu_drawings(chosen);
416
            config_menu_drawings(chosen);
417
            _delay_ms(500);
417
            _delay_ms(500);
418
        } else if (s1_pressed()) {
418
        } else if (s1_pressed()) {
419
            switch (chosen) {
419
            switch (chosen) {
420
                case 0: // NTSC or PAL
420
                case 0: // NTSC or PAL
421
                    COSD_FLAGS_CONFIG ^= COSD_FLAG_NTSC;
421
                    COSD_FLAGS_CONFIG ^= COSD_FLAG_NTSC;
422
                    // Setup Video Mode
422
                    // Setup Video Mode
423
                    if (COSD_FLAGS_CONFIG & COSD_FLAG_NTSC) {
423
                    if (COSD_FLAGS_CONFIG & COSD_FLAG_NTSC) {
424
                        // NTSC + enable display immediately (VM0)
424
                        // NTSC + enable display immediately (VM0)
425
                        spi_send_byte(0x00, 0b00001000);
425
                        spi_send_byte(0x00, 0b00001000);
426
 
426
 
427
                        bottom_line = 12;
427
                        bottom_line = 12;
428
                    } else {
428
                    } else {
429
                        // PAL + enable display immediately (VM0)
429
                        // PAL + enable display immediately (VM0)
430
                        spi_send_byte(0x00, 0b01001000);
430
                        spi_send_byte(0x00, 0b01001000);
431
 
431
 
432
                        bottom_line = 14;
432
                        bottom_line = 14;
433
                    }
433
                    }
434
                    break;
434
                    break;
435
                case 1: // full HUD
435
                case 1: // full HUD
436
                    COSD_FLAGS_MODES ^= COSD_FLAG_HUD;
436
                    COSD_FLAGS_MODES ^= COSD_FLAG_HUD;
437
                    break;
437
                    break;
438
                case 2: // art horizon
438
                case 2: // art horizon
439
                    COSD_FLAGS_MODES ^= COSD_FLAG_ARTHORIZON;
439
                    COSD_FLAGS_MODES ^= COSD_FLAG_ARTHORIZON;
440
                    break;
440
                    break;
441
                case 3: // aggressiva horizon
441
                case 3: // aggressiva horizon
442
                    COSD_FLAGS_MODES ^= COSD_FLAG_AGGRHORIZON;
442
                    COSD_FLAGS_MODES ^= COSD_FLAG_AGGRHORIZON;
443
                    break;
443
                    break;
444
                case 4: // statistics
444
                case 4: // statistics
445
                    COSD_FLAGS_MODES ^= COSD_FLAG_STATS;
445
                    COSD_FLAGS_MODES ^= COSD_FLAG_STATS;
446
                    break;
446
                    break;
447
                case 5: // current by fc
447
                case 5: // current by fc
448
                    COSD_FLAGS_MODES ^= COSD_FLAG_FCCURRENT;
448
                    COSD_FLAGS_MODES ^= COSD_FLAG_FCCURRENT;
449
                    break;
449
                    break;
450
                case 6: // GPS coordinates while flying
450
                case 6: // GPS coordinates while flying
451
                    COSD_FLAGS_CONFIG ^= COSD_FLAG_SHOW_COORDS;
451
                    COSD_FLAGS_CONFIG ^= COSD_FLAG_SHOW_COORDS;
452
                    break;
452
                    break;
453
                case 7: // 2nd voltage by c-strom
453
                case 7: // 2nd voltage by c-strom
454
                    COSD_FLAGS_MODES ^= COSD_FLAG_STROMVOLT;
454
                    COSD_FLAGS_MODES ^= COSD_FLAG_STROMVOLT;
455
                    break;
455
                    break;
456
                case 8: // GPS or BARO height
456
                case 8: // GPS or BARO height
457
                    COSD_FLAGS_CONFIG ^= COSD_FLAG_GPSHEIGHT;
457
                    COSD_FLAGS_CONFIG ^= COSD_FLAG_GPSHEIGHT;
458
                    break;
458
                    break;
459
                case 9: // Feet and mph?
459
                case 9: // Feet and mph?
460
                    COSD_FLAGS_CONFIG ^= COSD_FLAG_FEET;
460
                    COSD_FLAGS_CONFIG ^= COSD_FLAG_FEET;
461
                    break;
461
                    break;
462
                case 10: // big vario
462
                case 10: // big vario
463
                    COSD_FLAGS_MODES ^= COSD_FLAG_BIGVARIO;
463
                    COSD_FLAGS_MODES ^= COSD_FLAG_BIGVARIO;
464
                    break;
464
                    break;
465
                case 11: // big Speed
465
                case 11: // big Speed
466
                    COSD_FLAGS_CONFIG ^= COSD_FLAG_BIGSPEED;
466
                    COSD_FLAGS_CONFIG ^= COSD_FLAG_BIGSPEED;
467
                    break;
467
                    break;
468
                case 12: // passive
468
                case 12: // passive
469
                    COSD_FLAGS_CONFIG ^= COSD_FLAG_PASSIVE;
469
                    COSD_FLAGS_CONFIG ^= COSD_FLAG_PASSIVE;
470
                    break;
470
                    break;
471
                case 13: // scope
471
                case 13: // scope
472
                    COSD_FLAGS_CONFIG ^= COSD_FLAG_SHOW_SCOPE;
472
                    COSD_FLAGS_CONFIG ^= COSD_FLAG_SHOW_SCOPE;
473
                    break;
473
                    break;
474
                case 14: // move scope
474
                case 14: // move scope
475
                    move_scope();
475
                    move_scope();
476
                    break;
476
                    break;
477
                case 15: // reset uptime
477
                case 15: // reset uptime
478
                    uptime = 0;
478
                    uptime = 0;
479
                    config_menu_doclick(chosen);
479
                    config_menu_doclick(chosen);
480
                    break;
480
                    break;
481
                case 16: // change mode
481
                case 16: // change mode
482
#if FCONLY
482
#if FCONLY
483
                    COSD_DISPLAYMODE = (COSD_DISPLAYMODE + 1) % (sizeof (fcdisplaymodes) / sizeof (displaymode_t));
483
                    COSD_DISPLAYMODE = (COSD_DISPLAYMODE + 1) % (sizeof (fcdisplaymodes) / sizeof (displaymode_t));
484
                    mode = fcdisplaymodes;
484
                    mode = fcdisplaymodes;
485
                    mode += COSD_DISPLAYMODE;
485
                    mode += COSD_DISPLAYMODE;
486
                    osd_fcmode = (int(*)(void)) pgm_read_word(&mode->dfun);
486
                    osd_fcmode = (int(*)(void)) pgm_read_word(&mode->dfun);
487
#else
487
#else
488
                    COSD_DISPLAYMODE = (COSD_DISPLAYMODE + 1) % (sizeof (ncdisplaymodes) / sizeof (displaymode_t));
488
                    COSD_DISPLAYMODE = (COSD_DISPLAYMODE + 1) % (sizeof (ncdisplaymodes) / sizeof (displaymode_t));
489
                    mode = ncdisplaymodes;
489
                    mode = ncdisplaymodes;
490
                    mode += COSD_DISPLAYMODE;
490
                    mode += COSD_DISPLAYMODE;
491
                    osd_ncmode = (int(*)(void)) pgm_read_word(&mode->dfun);
491
                    osd_ncmode = (int(*)(void)) pgm_read_word(&mode->dfun);
492
#endif
492
#endif
493
                    break;
493
                    break;
494
                case 17: // save
494
                case 17: // save
495
                    save_eeprom();
495
                    save_eeprom();
496
                    config_menu_doclick(chosen);
496
                    config_menu_doclick(chosen);
497
                    break;
497
                    break;
498
                case 18: // exit
498
                case 18: // exit
499
                    inmenu = 0;
499
                    inmenu = 0;
500
                    config_menu_doclick(chosen);
500
                    config_menu_doclick(chosen);
501
                    break;
501
                    break;
502
            }
502
            }
503
            config_menu_drawings(chosen);
503
            config_menu_drawings(chosen);
504
            _delay_ms(250);
504
            _delay_ms(250);
505
        }
505
        }
506
    }
506
    }
507
 
507
 
508
    // clear screen up again
508
    // clear screen up again
509
    clear();
509
    clear();
510
 
510
 
511
    // update flags to paint display again if needed
511
    // update flags to paint display again if needed
512
    COSD_FLAGS_RUNTIME &= ~COSD_ICONS_WRITTEN;
512
    COSD_FLAGS_RUNTIME &= ~COSD_ICONS_WRITTEN;
513
 
513
 
514
    // enable interrupts again
514
    // enable interrupts again
515
    sei();
515
    sei();
516
}
516
}
517
 
517
 
518
#endif
518
#endif
519
 
519