Subversion Repositories Projects

Rev

Rev 468 | Rev 474 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 468 Rev 471
Line 17... Line 17...
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 + SVN *
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
 ****************************************************************************/
Line 31... Line 31...
31
#include <avr/pgmspace.h>
31
#include <avr/pgmspace.h>
32
#include "main.h"
32
#include "main.h"
33
#include "max7456_software_spi.h"
33
#include "max7456_software_spi.h"
34
#include "usart1.h"
34
#include "usart1.h"
35
#include "osd_helpers.h"
35
#include "osd_helpers.h"
-
 
36
#include "config.h"
-
 
37
#include "spi.h"
-
 
38
#include "buttons.h"
Line 36... Line 39...
36
 
39
 
37
/* TODO:
40
/* TODO:
38
 * - verifiy correctness of values
41
 * - verifiy correctness of values
39
 * - clean up code :)
42
 * - clean up code :)
Line 74... Line 77...
74
char stats_item_6[] PROGMEM = "latitude    :";
77
char stats_item_6[] PROGMEM = "latitude    :";
75
char stats_item_7[] PROGMEM = "max current :";
78
char stats_item_7[] PROGMEM = "max current :";
76
char* stats_item_pointers[] PROGMEM = {stats_item_0, stats_item_1, stats_item_2,
79
char* stats_item_pointers[] PROGMEM = {stats_item_0, stats_item_1, stats_item_2,
77
    stats_item_3, stats_item_4, stats_item_5, stats_item_6, stats_item_7};
80
    stats_item_3, stats_item_4, stats_item_5, stats_item_6, stats_item_7};
Line 78... Line -...
78
 
-
 
79
// store more fixed strings in progmen
-
 
80
char ON[] PROGMEM = "ON ";
-
 
81
char OFF[] PROGMEM = "OFF";
-
 
82
 
81
 
Line 83... Line 82...
83
#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))
82
#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))
84
 
83
 
85
// general PAL|NTSC distingiusch stuff
84
// general PAL|NTSC distingiusch stuff
Line 89... Line 88...
89
// battery voltages
88
// battery voltages
90
uint8_t min_voltage = 0;
89
uint8_t min_voltage = 0;
91
uint8_t max_voltage = 0;
90
uint8_t max_voltage = 0;
Line 92... Line 91...
92
 
91
 
93
// Flags
92
// Flags
94
uint8_t COSD_FLAGS = 0, COSD_FLAGS2;
-
 
95
 
-
 
96
/* ##########################################################################
-
 
97
 * debounce buttons
-
 
98
 * ##########################################################################*/
-
 
99
int s1_pressed() {
-
 
100
    if (S1_PRESSED) {
-
 
101
        _delay_ms(25);
-
 
102
        if (S1_PRESSED) return 1;
-
 
103
    }
-
 
104
    return 0;
-
 
105
}
-
 
106
 
-
 
107
int s2_pressed() {
-
 
108
    if (S2_PRESSED) {
-
 
109
        _delay_ms(25);
-
 
110
        if (S2_PRESSED) return 1;
-
 
111
    }
-
 
112
    return 0;
-
 
Line 113... Line 93...
113
}
93
uint8_t COSD_FLAGS = 0, COSD_FLAGS2 = 0;
114
 
94
 
115
/* ##########################################################################
95
/* ##########################################################################
Line 127... Line 107...
127
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
107
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
128
/* ##########################################################################
108
/* ##########################################################################
129
 * timer stuff
109
 * timer stuff
130
 * ##########################################################################*/
110
 * ##########################################################################*/
Line 131... Line -...
131
 
-
 
132
 
-
 
133
/* ##########################################################################
-
 
134
 * STROM TEST
-
 
135
 * ##########################################################################*/
-
 
136
#define INT0_HIGH                       PORTD |=  (1 << PD2);
-
 
137
#define INT0_LOW                        PORTD &= ~(1 << PD2);
-
 
138
 
-
 
139
void SpiMasterInit(void) {
-
 
140
    volatile char IOReg;
-
 
141
    // set PB4(/SS), PB5(MOSI), PB7(SCK) as output
-
 
142
    DDRB = (1 << PB4) | (1 << PB5) | (1 << PB7);
-
 
143
    PORTB |= (1 << PB4); // pullup SS
-
 
144
    // enable SPI Interrupt and SPI in Master Mode with SCK = CK/128
-
 
145
    SPCR = (1 << SPIE) | (1 << SPE) | (1 << MSTR) | (1 << SPR0) | (1 << SPR1);
-
 
146
    IOReg = SPSR; // clear SPIF bit in SPSR
-
 
147
    IOReg = SPDR;
-
 
148
    //sei(); // we do it later
-
 
149
}
-
 
150
 
-
 
151
volatile size_t icnt = 0;
-
 
152
volatile unsigned char * iptr;
-
 
153
volatile unsigned char spi_cmd_buffer[8];
-
 
154
volatile uint8_t spi_ready = 1;
-
 
155
int16_t ampere = 0, max_ampere = 0;
-
 
156
int32_t ampere_wasted = 0;
-
 
157
 
-
 
158
/**
-
 
159
 * SPI interrupt handler
-
 
160
 */
-
 
161
ISR(SPI_STC_vect) {
-
 
162
    *iptr++ = SPDR; // safe received byte to buffer
-
 
163
    icnt--; // dec length
-
 
164
    if (icnt) {
-
 
165
        //SPDR = *iptr; // send next byte
-
 
166
        spi_ready = 1; // we _should_ send later because the slave needs more time
-
 
167
    } else {
-
 
168
        SPCR &= ~_BV(SPIE); // deactivate interrupt
-
 
169
        INT0_HIGH // transfer is done, slave does not need to listen
-
 
170
    }
-
 
171
}
-
 
172
 
-
 
173
/**
-
 
174
 * check if SPI transfer is still busy
-
 
175
 */
-
 
176
int TransferIsBusy(void) {
-
 
177
    return SPCR & _BV(SPIE);
-
 
178
}
-
 
179
 
-
 
180
/**
-
 
181
 * start a new transfer of <data> with length <len>
-
 
182
 */
-
 
183
void StartTransfer(unsigned char *data, size_t len) {
-
 
184
    INT0_LOW // /SS LOW ^= SS HIGH ^= slave should listen
-
 
185
 
-
 
186
    // set up pointer and length for interrupt handler
-
 
187
    iptr = data;
-
 
188
    icnt = len;
-
 
189
 
-
 
190
    SPCR |= _BV(SPIE); // enable spi interrupt
-
 
191
    SPDR = *iptr; // start transfer by first bye
-
 
192
}
-
 
193
 
-
 
194
 
-
 
195
/* ##########################################################################
-
 
196
 * / STROM TEST END
-
 
197
 * ##########################################################################*/
-
 
198
 
111
 
199
/**
112
/**
200
 * timer kicks in every 1000uS ^= 1ms
113
 * timer kicks in every 1000uS ^= 1ms
201
 */
114
 */
202
ISR(TIMER0_OVF_vect) {
115
ISR(TIMER0_OVF_vect) {
Line 209... Line 122...
209
    // in case there is still some spi data to send do it now
122
    // in case there is still some spi data to send do it now
210
    if (spi_ready && icnt) {
123
    if (spi_ready && icnt) {
211
        SPDR = *iptr;
124
        SPDR = *iptr;
212
    }
125
    }
213
}
126
}
214
 
-
 
215
/* ##########################################################################
-
 
216
 * A simple config menu for the flags
-
 
217
 * ##########################################################################*/
-
 
218
 
-
 
219
/**
-
 
220
 * helper function for menu updating
-
 
221
 */
-
 
222
void config_menu_drawings(uint8_t chosen) {
-
 
223
    // clear prevoius _cursor_
-
 
224
    write_ascii_string(3, (chosen + 5) % 8, " ");
-
 
225
    // draw current _cursor_
-
 
226
    write_ascii_string(3, chosen + 5, ">");
-
 
227
    if (COSD_FLAGS & COSD_FLAG_HUD) {
-
 
228
        write_ascii_string_pgm(23, 5, ON);
-
 
229
    } else {
-
 
230
        write_ascii_string_pgm(23, 5, OFF);
-
 
231
    }
-
 
232
    if (COSD_FLAGS & COSD_FLAG_ARTHORIZON) {
-
 
233
        write_ascii_string_pgm(23, 6, ON);
-
 
234
    } else {
-
 
235
        write_ascii_string_pgm(23, 6, OFF);
-
 
236
    }
-
 
237
    if (COSD_FLAGS & COSD_FLAG_BIGVARIO) {
-
 
238
        write_ascii_string_pgm(23, 7, ON);
-
 
239
    } else {
-
 
240
        write_ascii_string_pgm(23, 7, OFF);
-
 
241
    }
-
 
242
    if (COSD_FLAGS & COSD_FLAG_STATS) {
-
 
243
        write_ascii_string_pgm(23, 8, ON);
-
 
244
    } else {
-
 
245
        write_ascii_string_pgm(23, 8, OFF);
-
 
246
    }
-
 
247
    if (COSD_FLAGS & COSD_FLAG_WARNINGS) {
-
 
248
        write_ascii_string_pgm(23, 9, ON);
-
 
249
    } else {
-
 
250
        write_ascii_string_pgm(23, 9, OFF);
-
 
251
    }
-
 
252
}
-
 
253
 
-
 
254
/**
-
 
255
 * some sort of clicking response in the menu
-
 
256
 */
-
 
257
void config_menu_doclick(uint8_t chosen, char** menu) {
-
 
258
    write_ascii_string(4, chosen + 5, "DONE              ");
-
 
259
    _delay_ms(1000);
-
 
260
    write_ascii_string(4, chosen + 5, menu[chosen]);
-
 
261
}
-
 
262
 
-
 
263
/**
-
 
264
 * a simple config menu tryout
-
 
265
 */
-
 
266
void config_menu(void) {
-
 
267
    // disable interrupts (makes the menu more smoothely)
-
 
268
    cli();
-
 
269
 
-
 
270
    // clear screen
-
 
271
    clear();
-
 
272
 
-
 
273
    char* menu[9] = {"Full HUD",
-
 
274
        "Art.Horizon in HUD",
-
 
275
        "Big Vario bar",
-
 
276
        "Statistics",
-
 
277
        "Warnings", // TODO: do it!
-
 
278
        "Reset uptime",
-
 
279
        "Request OSD-data",
-
 
280
        "Disable Debug-data",
-
 
281
        "EXIT"};
-
 
282
 
-
 
283
    uint8_t inmenu = 1;
-
 
284
    uint8_t chosen = 0;
-
 
285
    write_ascii_string(6, 2, "C-OSD Config Menu");
-
 
286
 
-
 
287
    // wait a bit before doing stuff so user has chance to release button
-
 
288
    _delay_ms(250);
-
 
289
 
-
 
290
    write_ascii_string(4, 5, menu[0]);
-
 
291
    write_ascii_string(4, 6, menu[1]);
-
 
292
    write_ascii_string(4, 7, menu[2]);
-
 
293
    write_ascii_string(4, 8, menu[3]);
-
 
294
    write_ascii_string(4, 9, menu[4]);
-
 
295
    write_ascii_string(4, 10, menu[5]);
-
 
296
    write_ascii_string(4, 11, menu[6]);
-
 
297
    write_ascii_string(4, 12, menu[7]);
-
 
298
    write_ascii_string(4, 13, menu[8]);
-
 
299
 
-
 
300
    config_menu_drawings(chosen);
-
 
301
 
-
 
302
    while (inmenu) {
-
 
303
        if (s2_pressed()) {
-
 
304
            write_ascii_string(3, chosen + 5, " ");
-
 
305
            chosen = (chosen + 1) % 9;
-
 
306
            write_ascii_string(3, chosen + 5, ">");
-
 
307
            _delay_ms(500);
-
 
308
        } else if (s1_pressed()) {
-
 
309
            switch (chosen) {
-
 
310
                case 0: // full HUD
-
 
311
                    COSD_FLAGS ^= COSD_FLAG_HUD;
-
 
312
                    config_menu_drawings(chosen);
-
 
313
                    break;
-
 
314
                case 1: // art horizon
-
 
315
                    COSD_FLAGS ^= COSD_FLAG_ARTHORIZON;
-
 
316
                    config_menu_drawings(chosen);
-
 
317
                    break;
-
 
318
                case 2: // big vario
-
 
319
                    COSD_FLAGS ^= COSD_FLAG_BIGVARIO;
-
 
320
                    config_menu_drawings(chosen);
-
 
321
                    break;
-
 
322
                case 3: // statistics
-
 
323
                    COSD_FLAGS ^= COSD_FLAG_STATS;
-
 
324
                    config_menu_drawings(chosen);
-
 
325
                    break;
-
 
326
                case 4: // warnings
-
 
327
                    COSD_FLAGS ^= COSD_FLAG_WARNINGS;
-
 
328
                    config_menu_drawings(chosen);
-
 
329
                    break;
-
 
330
                case 5: // reset uptime
-
 
331
                    uptime = 0;
-
 
332
                    config_menu_doclick(chosen, menu);
-
 
333
                    break;
-
 
334
                case 6: // re-request OSD data
-
 
335
#if FCONLY
-
 
336
                    // request data ever 100ms from FC;
-
 
337
                    usart1_request_mk_data(0, 'd', 100);
-
 
338
#else
-
 
339
                    // request OSD Data from NC every 100ms
-
 
340
                    usart1_request_mk_data(1, 'o', 100);
-
 
341
 
-
 
342
                    // and disable debug...
-
 
343
                    usart1_request_mk_data(0, 'd', 0);
-
 
344
#endif
-
 
345
                    config_menu_doclick(chosen, menu);
-
 
346
                    break;
-
 
347
                case 7: // disable debug data
-
 
348
                    // disable sending of debug data
-
 
349
                    // may result in smoother ddata display
-
 
350
                    usart1_request_mk_data(0, 'd', 0);
-
 
351
                    config_menu_doclick(chosen, menu);
-
 
352
                    break;
-
 
353
                case 8: // exit
-
 
354
                    inmenu = 0;
-
 
355
                    break;
-
 
356
            }
-
 
357
            _delay_ms(250);
-
 
358
        }
-
 
359
    }
-
 
360
 
-
 
361
    // clear screen up again
-
 
362
    clear();
-
 
363
 
-
 
364
    // update flags to paint display again if needed
-
 
365
    COSD_FLAGS &= ~COSD_ICONS_WRITTEN;
-
 
366
 
-
 
367
    // enable interrupts again
-
 
368
    sei();
-
 
369
}
-
 
370
 
-
 
371
/**
-
 
372
 * auto config some stuff on startup, currently only battery cells
-
 
373
 * TODO: this is testing stuff, strings should go progmem and so on...
-
 
374
 */
-
 
375
void auto_config(uint8_t UBat) {
-
 
376
    clear();
-
 
377
    write_ascii_string(2, 2, "C-OSD Initialisation");
-
 
378
#if FCONLY
-
 
379
    write_ascii_string(2, 3, "FC only Mode");
-
 
380
#else
-
 
381
    write_ascii_string(2, 3, "NaviCtrl Mode");
-
 
382
#endif
-
 
383
    write_ascii_string(2, 4, BUILDDATE);
-
 
384
    uint8_t cellnum = 0;
-
 
385
    if (CELL_NUM == -1) {
-
 
386
        write_ascii_string(2, 6, "Guessing Number of Cells");
-
 
387
        do {
-
 
388
            cellnum++;
-
 
389
        } while (UBat > ((cellnum * CELL_VOLT_MAX) + 23));
-
 
390
    } else {
-
 
391
        cellnum = CELL_NUM;
-
 
392
    }
-
 
393
    min_voltage = cellnum * CELL_VOLT_MIN;
-
 
394
    max_voltage = cellnum * CELL_VOLT_MAX;
-
 
395
    write_ascii_string(2, 7, "Number of Cells:");
-
 
396
    write_ndigit_number_u(21, 7, cellnum, 1, 0);
-
 
397
    write_ascii_string(2, 8, "Warn Voltage   :");
-
 
398
    write_ndigit_number_s_10th(20, 8, min_voltage, 100, 0);
-
 
399
    write_ascii_string(2, 9, "Max Voltage    :");
-
 
400
    write_ndigit_number_s_10th(20, 9, max_voltage, 100, 0);
-
 
401
    _delay_ms(200);
-
 
402
    clear();
-
 
403
    // update flags to paint display again because of clear
-
 
404
    COSD_FLAGS &= ~COSD_ICONS_WRITTEN;
-
 
405
}
-
 
406
 
-
 
407
#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))
127
#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))#endif // ends !(ALLCHARSDEBUG|(WRITECHARS != -1))
Line 408... Line 128...
408
 
128
 
409
/* ##########################################################################
129
/* ##########################################################################
410
 * MAIN
130
 * MAIN
Line 512... Line 232...
512
 
232
 
513
    // we are ready
233
    // we are ready
Line 514... Line 234...
514
    LED3_ON
234
    LED3_ON
515
 
235
 
516
#if ALLCHARSDEBUG | (WRITECHARS != -1)
236
#if ALLCHARSDEBUG | (WRITECHARS != -1)
517
            clear();
237
        clear();
518
    write_all_chars();
238
    write_all_chars();
519
#else
239
#else
520
            // clear serial screen
240
        // clear serial screen
521
            //usart1_puts("\x1B[2J\x1B[H");
241
        //usart1_puts("\x1B[2J\x1B[H");
522
            //usart1_puts("hello world!\r\n");
242
        //usart1_puts("hello world!\r\n");
523
#if FCONLY
243
#if FCONLY
524
            // request data ever 100ms from FC;
244
        // request data ever 100ms from FC;
525
            usart1_request_mk_data(0, 'd', 100);
245
        usart1_request_mk_data(0, 'd', 100);
526
#else
246
#else
Line 527... Line 247...
527
            // request OSD Data from NC every 100ms
247
        // request OSD Data from NC every 100ms
528
            usart1_request_mk_data(1, 'o', 100);
248
        usart1_request_mk_data(1, 'o', 100);
529
 
249
 
Line 544... Line 264...
544
 
264
 
545
    char* directions[8] = {"NE", "E ", "SE", "S ", "SW", "W ", "NW", "N "};
265
    char* directions[8] = {"NE", "E ", "SE", "S ", "SW", "W ", "NW", "N "};
546
    //char arrowdir[8] = {218, 217, 224, 223, 222, 221, 220, 219};
266
    //char arrowdir[8] = {218, 217, 224, 223, 222, 221, 220, 219};
Line 547... Line -...
547
#endif
-
 
548
 
-
 
549
 
267
#endif
550
 
268
 
551
    while (1) {
269
    while (1) {
552
        // in case SPI is ready and there is nothing to send right now
270
        // in case SPI is ready and there is nothing to send right now
553
        if (!icnt && spi_ready) {
271
        if (!icnt && spi_ready) {
Line 564... Line 282...
564
                                ampere_wasted |= spi_cmd_buffer[6];
282
                                ampere_wasted |= spi_cmd_buffer[6];
565
                                //ampere = *((int16_t *) spi_cmd_buffer + 1);
283
                                //ampere = *((int16_t *) spi_cmd_buffer + 1);
566
                                //ampere_wasted = *((int32_t *) &spi_cmd_buffer + 3);
284
                                //ampere_wasted = *((int32_t *) &spi_cmd_buffer + 3);
567
                                // if this is the first receival we should print the small A
285
                                // if this is the first receival we should print the small A
568
                                if (!(COSD_FLAGS2 & COSD_FLAG_STROMREC)) {
286
                                if (!(COSD_FLAGS2 & COSD_FLAG_STROMREC)) {
569
                                        COSD_FLAGS &= ~COSD_ICONS_WRITTEN;
287
                                        COSD_FLAGS2 &= ~COSD_ICONS_WRITTEN;
570
                                        // update this flag
288
                                        // update this flag
571
                        COSD_FLAGS2 |= COSD_FLAG_STROMREC;
289
                        COSD_FLAGS2 |= COSD_FLAG_STROMREC;
572
                                }
290
                                }
573
                //write_ascii_char(8+4*30, 'v'); // valid
291
                //write_ascii_char(8+4*30, 'v'); // valid
574
            } else {
292
            } else {
Line 584... Line 302...
584
                        spi_cmd_buffer[5] = 'F';
302
                        spi_cmd_buffer[5] = 'F';
585
                        spi_cmd_buffer[6] = 'G';
303
                        spi_cmd_buffer[6] = 'G';
586
            StartTransfer((unsigned char*) spi_cmd_buffer, 7);
304
            StartTransfer((unsigned char*) spi_cmd_buffer, 7);
587
        }
305
        }
588
        if (rxd_buffer_locked) {
306
        if (rxd_buffer_locked) {
589
            if (COSD_FLAGS & COSD_FLAG_HUD) {
-
 
590
#if FCONLY
307
#if FCONLY
591
                if (rxd_buffer[2] == 'D') { // FC Data
308
            if (rxd_buffer[2] == 'D') { // FC Data
592
                    Decode64();
309
                Decode64();
593
                    debugData = *((DebugOut_t*) pRxData);
310
                debugData = *((DebugOut_t*) pRxData);
594
 
311
 
595
                    // init on first data retrival, distinguished by last battery :)
312
                // init on first data retrival, distinguished by last battery :)
596
                    if (last_UBat == 255) {
313
                if (last_UBat == 255) {
597
                        // fix for min_UBat
314
                    // fix for min_UBat
598
                        min_UBat = debugData.Analog[9];
315
                    min_UBat = debugData.Analog[9];
599
                        auto_config(debugData.Analog[9]);
316
                    init_cosd(debugData.Analog[9]);
600
                    }
-
 
601
                    #include "osd_fcmode_default.c"
-
 
602
                }
317
                }
-
 
318
                #include "osd_fcmode_default.c"
-
 
319
            }
603
#else
320
#else
604
                if (rxd_buffer[2] == 'O') { // NC OSD Data
321
            if (rxd_buffer[2] == 'O') { // NC OSD Data
605
                    Decode64();
322
                Decode64();
606
                    naviData = *((NaviData_t*) pRxData);
323
                naviData = *((NaviData_t*) pRxData);
607
 
324
 
608
                    // init on first data retrival, distinguished by last battery :)
325
                // init on first data retrival, distinguished by last battery :)
609
                    if (last_UBat == 255) {
326
                if (last_UBat == 255) {
610
                        // fix for min_UBat
327
                    // fix for min_UBat
611
                        min_UBat = naviData.UBat;
328
                    min_UBat = naviData.UBat;
612
                        auto_config(naviData.UBat);
329
                    init_cosd(naviData.UBat);
613
                    }
-
 
614
                    #include "osd_ncmode_default.c"
-
 
615
                }
330
                }
616
#endif
331
                #include "osd_ncmode_default.c"
617
            }
332
            }
-
 
333
#endif
618
            rxd_buffer_locked = 0;
334
            rxd_buffer_locked = 0;
619
        }
335
        }
620
        // handle keypress
336
        // handle keypress
621
        if (s1_pressed()) {
337
        if (s1_pressed()) {
622
            config_menu();
338
            config_menu();