Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1734 - 1
/*****************************************************************************
2
 *   Copyright (C) 2008 Thomas Kaiser, thomas@ft-fanpage.de                  *
3
 *   Copyright (C) 2009 Peter "woggle" Mack, mac@denich.net                  *
4
 *   Copyright (C) 2011 Christian "Cebra" Brandtner, brandtner@brandtner.net *
5
 *   Copyright (C) 2011 Harald Bongartz                                      *
6
 *                                                                           *
7
 *   This program is free software; you can redistribute it and/or modify    *
8
 *   it under the terms of the GNU General Public License as published by    *
9
 *   the Free Software Foundation; either version 2 of the License.          *
10
 *                                                                           *
11
 *   This program is distributed in the hope that it will be useful,         *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
14
 *   GNU General Public License for more details.                            *
15
 *                                                                           *
16
 *   You should have received a copy of the GNU General Public License       *
17
 *   along with this program; if not, write to the                           *
18
 *   Free Software Foundation, Inc.,                                         *
19
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.               *
20
 *                                                                           *
21
 *                                                                           *
22
 *   Credits to:                                                             *
23
 *   Holger Buss & Ingo Busker from mikrokopter.de for the MK project + SVN  *
24
 *                          http://www.mikrokopter.de                        *
25
 *   Gregor "killagreg" Stobrawa for his version of the MK code              *
26
 *   Thomas Kaiser "thkais" for the original project. See                    *
27
 *                          http://www.ft-fanpage.de/mikrokopter/            *
28
 *                          http://forum.mikrokopter.de/topic-4061-1.html    *
29
 *   Claas Anders "CaScAdE" Rathje for providing the font and his C-OSD code *
30
 *                          http://www.mylifesucks.de/oss/c-osd/             *
31
 *   Harald Bongartz "HaraldB" for providing his Ideas and Code for usibility*
32
 *****************************************************************************/
33
 
34
 
35
#include "cpu.h"
36
#include <avr/io.h>
37
#include <avr/interrupt.h>
38
#include <avr/pgmspace.h>
39
#include <avr/wdt.h>
40
#include <util/delay.h>
41
#include <stdarg.h>
42
 
43
#include "main.h"
44
#include "usart.h"
45
#include "lcd.h"
46
#include "timer.h"
47
#include "uart1.h"
48
#include "eeprom.h"
49
#include "osd.h"
50
 
51
 
52
uint8_t buffer[30];
53
 
54
volatile uint8_t txd_buffer[TXD_BUFFER_LEN];
55
volatile uint8_t txd_complete = TRUE;
56
 
57
volatile uint8_t rxd_buffer[RXD_BUFFER_LEN];
58
volatile uint8_t rxd_buffer_locked = FALSE;
59
volatile uint8_t ReceivedBytes = 0;
60
volatile uint8_t *pRxData = 0;
61
volatile uint8_t RxDataLen = 0;
62
 
63
volatile uint16_t stat_crc_error = 0;
64
volatile uint16_t stat_overflow_error = 0;
65
 
66
volatile uint8_t rx_byte;
67
volatile uint8_t rxFlag = 0;
68
 
69
 
70
#define UART_RXBUFSIZE 64
71
#define UART_NO_DATA          0x0100              /* no receive data available   */
72
 
73
volatile static uint8_t rxbuf[UART_RXBUFSIZE];
74
volatile static uint8_t *volatile rxhead, *volatile rxtail;
75
 
76
 
77
/*
78
 
79
//-----------------------------------------------------------------------------
80
// USART1 transmitter ISR
81
ISR (USART1_TX_vect)
82
{
83
        static uint16_t ptr_txd1_buffer = 0;
84
        uint8_t tmp_tx1;
85
 
86
        if(!txd1_complete) // transmission not completed
87
        {
88
                ptr_txd1_buffer++;                    // [0] was already sent
89
                tmp_tx1 = txd1_buffer[ptr_txd1_buffer];
90
                // if terminating character or end of txd buffer was reached
91
                if((tmp_tx1 == '\r') || (ptr_txd1_buffer == TXD_BUFFER_LEN))
92
                {
93
                        ptr_txd1_buffer = 0;            // reset txd pointer
94
                        txd1_complete = TRUE;   // stop transmission
95
                }
96
                UDR1 = tmp_tx1; // send current byte will trigger this ISR again
97
        }
98
        // transmission completed
99
        else ptr_txd1_buffer = 0;
100
}
101
 
102
*/
103
 
104
 
105
#ifdef USART_INT
106
//-----------------------------------------------------------------------------
107
// USART0 transmitter ISR
108
ISR (USART_TX_vect)
109
{
110
        static uint16_t ptr_txd_buffer = 0;
111
        uint8_t tmp_tx;
112
 
113
        if(!txd_complete) // transmission not completed
114
        {
115
                ptr_txd_buffer++;                    // [0] was already sent
116
                tmp_tx = txd_buffer[ptr_txd_buffer];
117
                // if terminating character or end of txd buffer was reached
118
                if((tmp_tx == '\r') || (ptr_txd_buffer == TXD_BUFFER_LEN))
119
                {
120
                        ptr_txd_buffer = 0;             // reset txd pointer
121
                        txd_complete = TRUE;    // stop transmission
122
                }
123
                UDR = tmp_tx; // send current byte will trigger this ISR again
124
        }
125
        // transmission completed
126
        else ptr_txd_buffer = 0;
127
}
128
#endif
129
 
130
 
131
 
132
 
133
 
134
//-----------------------------------------------------------------------------
135
//
136
 
137
//
138
//uint8_t uart_getc_nb(uint8_t *c)
139
//{
140
//      if (rxhead==rxtail) return 0;
141
//      *c = *rxtail;
142
//      if (++rxtail == (rxbuf + UART_RXBUFSIZE)) rxtail = rxbuf;
143
//      return 1;
144
//}
145
 
146
 
147
 
148
 
149
ISR (USART0_RX_vect)
150
{
151
        static uint16_t crc;
152
        static uint8_t ptr_rxd_buffer = 0;
153
        uint8_t crc1, crc2;
154
        uint8_t c;
155
//      IdleTimer = 0;
156
        if (current_hardware == Wi232)
157
        {
158
//              rx_byte = c;
159
//              rxFlag = 1;
160
                int diff;
161
                uint8_t c;
162
                c=UDR;
163
                diff = rxhead - rxtail;
164
                if (diff < 0) diff += UART_RXBUFSIZE;
165
                if (diff < UART_RXBUFSIZE -1)
166
                {
167
                        *rxhead = c;
168
                        ++rxhead;
169
                        if (rxhead == (rxbuf + UART_RXBUFSIZE)) rxhead = rxbuf;
170
                };
171
//              USART_putc (c);
172
                return;
173
        }
174
 
175
 
176
        if (current_hardware == MKGPS)
177
        {
178
//              rx_byte = c;
179
//              rxFlag = 1;
180
                int diff;
181
                uint8_t c;
182
                c=UDR;
183
                diff = rxhead - rxtail;
184
                if (diff < 0) diff += UART_RXBUFSIZE;
185
                if (diff < UART_RXBUFSIZE -1)
186
                {
187
                        *rxhead = c;
188
                        ++rxhead;
189
                        if (rxhead == (rxbuf + UART_RXBUFSIZE)) rxhead = rxbuf;
190
                };
191
 
192
                return;
193
        }
194
 
195
        c = UDR;  // catch the received byte
196
        if (OSD_active && OSD_SendOSD)          // Daten an SV2 senden
197
          uart1_putc(c);
198
 
199
 
200
        if (rxd_buffer_locked)
201
                return; // if rxd buffer is locked immediately return
202
 
203
        // the rxd buffer is unlocked
204
        if ((ptr_rxd_buffer == 0) && (c == '#')) // if rxd buffer is empty and syncronisation character is received
205
        {
206
                rxd_buffer[ptr_rxd_buffer++] = c; // copy 1st byte to buffer
207
                crc = c; // init crc
208
        }
209
        else if (ptr_rxd_buffer < RXD_BUFFER_LEN) // collect incomming bytes
210
        {
211
                if(c != '\r') // no termination character
212
                {
213
                        rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
214
                        crc += c; // update crc
215
                }
216
                else // termination character was received
217
                {
218
                        // the last 2 bytes are no subject for checksum calculation
219
                        // they are the checksum itself
220
                        crc -= rxd_buffer[ptr_rxd_buffer-2];
221
                        crc -= rxd_buffer[ptr_rxd_buffer-1];
222
                        // calculate checksum from transmitted data
223
                        crc %= 4096;
224
                        crc1 = '=' + crc / 64;
225
                        crc2 = '=' + crc % 64;
226
                        // compare checksum to transmitted checksum bytes
227
                        if((crc1 == rxd_buffer[ptr_rxd_buffer-2]) && (crc2 == rxd_buffer[ptr_rxd_buffer-1]))
228
                        {   // checksum valid
229
                                rxd_buffer[ptr_rxd_buffer] = '\r'; // set termination character
230
                                ReceivedBytes = ptr_rxd_buffer + 1;// store number of received bytes
231
                                if (mode == rxd_buffer[2])
232
                                {
233
                                        rxd_buffer_locked = TRUE;          // lock the rxd buffer
234
                                        // if 2nd byte is an 'R' enable watchdog that will result in an reset
235
                                        if(rxd_buffer[2] == 'R') {wdt_enable(WDTO_250MS);} // Reset-Commando
236
                                }
237
                        }
238
                        else
239
                        {       // checksum invalid
240
                                stat_crc_error++;
241
                                rxd_buffer_locked = FALSE; // unlock rxd buffer
242
                        }
243
                        ptr_rxd_buffer = 0; // reset rxd buffer pointer
244
                }
245
        }
246
        else // rxd buffer overrun
247
        {
248
                stat_overflow_error++;
249
                ptr_rxd_buffer = 0; // reset rxd buffer
250
                rxd_buffer_locked = FALSE; // unlock rxd buffer
251
        }
252
}
253
 
254
 
255
//-----------------------------------------------------------------------------
256
// Function: uart0_getc()
257
// Purpose:  return byte from ringbuffer
258
// Returns:  lower byte:  received byte from ringbuffer
259
//           higher byte: last receive error
260
//-----------------------------------------------------------------------------
261
char USART_getc(void)
262
{
263
        char val;
264
 
265
//      while(rxhead==rxtail) ;
266
        if (rxhead==rxtail)
267
                return val=0;
268
//      IdleTimer = 0;
269
        val = *rxtail;
270
        if (++rxtail == (rxbuf + UART_RXBUFSIZE))
271
                rxtail = rxbuf;
272
 
273
        return val;
274
}
275
 
276
 
277
uint8_t uart_getc_nb(uint8_t *c)
278
{
279
        if (rxhead==rxtail)
280
                return 0;
281
//      IdleTimer = 0;
282
        *c = *rxtail;
283
        if (++rxtail == (rxbuf + UART_RXBUFSIZE))
284
                rxtail = rxbuf;
285
        return 1;
286
}
287
//-----------------------------------------------------------------------------
288
//
289
 
290
 
291
 
292
 
293
 
294
//-----------------------------------------------------------------------------
295
//
296
void USART_Init (unsigned int baudrate)
297
{
298
        // set clock divider
299
//      #undef BAUD
300
//      #define BAUD baudrate
301
//      #include <util/setbaud.h>
302
//      UBRRH = UBRRH_VALUE;
303
//      UBRRL = UBRRL_VALUE;
304
 
305
//#ifndef F_CPU
306
///* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
307
//   F_CPU im Makefile definiert werden, eine nochmalige Definition
308
//   hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
309
//   #ifndef/#endif
310
//
311
//   Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio
312
//   verwendet wird und dort eine andere, nicht zur Hardware passende
313
//   Taktrate eingestellt ist: Dann wird die folgende Definition
314
//   nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?)
315
//   von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
316
//   noch nicht definiert: */
317
//#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
318
//#define F_CPU 18432000UL  // Systemtakt in Hz - Definition als unsigned long beachten
319
                         // Ohne ergeben sich unten Fehler in der Berechnung
320
//#endif
321
//#define BAUD 115200UL      // Baudrate
322
//
323
//// Berechnungen
324
//#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
325
//#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
326
//#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
327
//
328
//
329
//#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
330
//  #error "Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!"
331
//#endif
332
 
333
 
334
        UBRRH = (unsigned char)(baudrate>>8);
335
        UBRRL = (unsigned char) baudrate;
336
//        UBRRH = (unsigned char)(BAUD_REAL>>8);
337
//        UBRRL = (unsigned char) BAUD_REAL;
338
 
339
#if USE_2X
340
        UCSRA |= (1 << U2X);    // enable double speed operation
341
#else
342
        UCSRA &= ~(1 << U2X);   // disable double speed operation
343
#endif
344
 
345
        // set 8N1
346
#if defined (__AVR_ATmega8__) || defined (__AVR_ATmega32__)
347
        UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
348
#else
349
        UCSRC = (1 << UCSZ1) | (1 << UCSZ0);
350
#endif
351
        UCSRB &= ~(1 << UCSZ2);
352
 
353
        // flush receive buffer
354
        while ( UCSRA & (1 << RXC) ) UDR;
355
 
356
        UCSRB |= (1 << RXEN) | (1 << TXEN);
357
#ifdef USART_INT
358
        UCSRB |= (1 << RXCIE) | (1 << TXCIE);
359
#else
360
        UCSRB |= (1 << RXCIE);
361
#endif
362
 
363
        rxhead = rxtail = rxbuf;
364
 
365
}
366
 
367
 
368
 
369
 
370
 
371
//-----------------------------------------------------------------------------
372
// disable the txd pin of usart
373
void USART_DisableTXD (void)
374
{
375
#ifdef USART_INT
376
        UCSRB &= ~(1 << TXCIE);         // disable TX-Interrupt
377
#endif
378
        UCSRB &= ~(1 << TXEN);          // disable TX in USART
379
        DDRB  &= ~(1 << DDB3);          // set TXD pin as input
380
        PORTB &= ~(1 << PORTB3);        // disable pullup on TXD pin
381
}
382
 
383
//-----------------------------------------------------------------------------
384
// enable the txd pin of usart
385
void USART_EnableTXD (void)
386
{
387
        DDRB  |=  (1 << DDB3);          // set TXD pin as output
388
        PORTB &= ~(1 << PORTB3);        // disable pullup on TXD pin
389
        UCSRB |=  (1 << TXEN);          // enable TX in USART
390
#ifdef USART_INT
391
        UCSRB |=  (1 << TXCIE);         // enable TX-Interrupt
392
#endif
393
}
394
 
395
//-----------------------------------------------------------------------------
396
// short script to directly send a request thorugh usart including en- and disabling it
397
// where <address> is the address of the receipient, <label> is which data set to request
398
// and <ms> represents the milliseconds delay between data
399
void USART_request_mk_data (uint8_t cmd, uint8_t addr, uint8_t ms)
400
{
401
        USART_EnableTXD ();     // re-enable TXD pin
402
 
403
        unsigned char mstenth = ms/10;
404
        SendOutData(cmd, addr, 1, &mstenth, 1);
405
        // wait until command transmitted
406
        while (txd_complete == FALSE);
407
 
408
        USART_DisableTXD ();    // disable TXD pin again
409
}
410
 
411
//-----------------------------------------------------------------------------
412
//
413
void USART_putc (char c)
414
{
415
#ifdef USART_INT
416
#else
417
        loop_until_bit_is_set(UCSRA, UDRE);
418
        UDR = c;
419
#endif
420
}
421
 
422
 
423
 
424
//-----------------------------------------------------------------------------
425
//
426
void USART_puts (char *s)
427
{
428
#ifdef USART_INT
429
#else
430
        while (*s)
431
        {
432
                USART_putc (*s);
433
                s++;
434
        }
435
#endif
436
}
437
 
438
//-----------------------------------------------------------------------------
439
//
440
void USART_puts_p (const char *s)
441
{
442
#ifdef USART_INT
443
#else
444
        while (pgm_read_byte(s))
445
        {
446
                USART_putc (pgm_read_byte(s));
447
                s++;
448
        }
449
#endif
450
}
451
 
452
//-----------------------------------------------------------------------------
453
//
454
void SendOutData(uint8_t cmd, uint8_t addr, uint8_t numofbuffers, ...) // uint8_t *pdata, uint8_t len, ...
455
{
456
        va_list ap;
457
        uint16_t pt = 0;
458
        uint8_t a,b,c;
459
        uint8_t ptr = 0;
460
        uint16_t tmpCRC = 0;
461
 
462
        uint8_t *pdata = 0;
463
        int len = 0;
464
 
465
        txd_buffer[pt++] = '#';                                 // Start character
466
        txd_buffer[pt++] = 'a' + addr;  // Address (a=0; b=1,...)
467
        txd_buffer[pt++] = cmd;                                 // Command
468
 
469
        va_start(ap, numofbuffers);
470
        if(numofbuffers)
471
        {
472
                pdata = va_arg (ap, uint8_t*);
473
                len = va_arg (ap, int);
474
                ptr = 0;
475
                numofbuffers--;
476
        }
477
 
478
        while(len)
479
        {
480
                if(len)
481
                {
482
                        a = pdata[ptr++];
483
                        len--;
484
                        if((!len) && numofbuffers)
485
                        {
486
                                pdata = va_arg(ap, uint8_t*);
487
                                len = va_arg(ap, int);
488
                                ptr = 0;
489
                                numofbuffers--;
490
                        }
491
                }
492
                else
493
                        a = 0;
494
 
495
                if(len)
496
                {
497
                        b = pdata[ptr++];
498
                        len--;
499
                        if((!len) && numofbuffers)
500
                        {
501
                                pdata = va_arg(ap, uint8_t*);
502
                                len = va_arg(ap, int);
503
                                ptr = 0;
504
                                numofbuffers--;
505
                        }
506
                }
507
                else
508
                        b = 0;
509
 
510
                if(len)
511
                {
512
                        c = pdata[ptr++];
513
                        len--;
514
                        if((!len) && numofbuffers)
515
                        {
516
                                pdata = va_arg(ap, uint8_t*);
517
                                len = va_arg(ap, int);
518
                                ptr = 0;
519
                                numofbuffers--;
520
                        }
521
                }
522
                else
523
                        c = 0;
524
 
525
                txd_buffer[pt++] = '=' + (a >> 2);
526
                txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
527
                txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
528
                txd_buffer[pt++] = '=' + ( c & 0x3f);
529
        }
530
        va_end(ap);
531
 
532
        for(a = 0; a < pt; a++)
533
        {
534
                tmpCRC += txd_buffer[a];
535
        }
536
        tmpCRC %= 4096;
537
        txd_buffer[pt++] = '=' + tmpCRC / 64;
538
        txd_buffer[pt++] = '=' + tmpCRC % 64;
539
        txd_buffer[pt++] = '\r';
540
 
541
        txd_complete = FALSE;
542
#ifdef USART_INT
543
        UDR = txd_buffer[0]; // initiates the transmittion (continued in the TXD ISR)
544
#else
545
        for(a = 0; a < pt; a++)
546
        {
547
                loop_until_bit_is_set(UCSRA, UDRE);
548
                UDR = txd_buffer[a];
549
        }
550
        txd_complete = TRUE;
551
#endif
552
}
553
 
554
//-----------------------------------------------------------------------------
555
//
556
void Decode64 (void)
557
{
558
        uint8_t a,b,c,d;
559
        uint8_t ptrIn = 3;
560
        uint8_t ptrOut = 3;
561
        uint8_t len = ReceivedBytes - 6;
562
 
563
        while (len)
564
        {
565
                a = rxd_buffer[ptrIn++] - '=';
566
                b = rxd_buffer[ptrIn++] - '=';
567
                c = rxd_buffer[ptrIn++] - '=';
568
                d = rxd_buffer[ptrIn++] - '=';
569
                //if(ptrIn > ReceivedBytes - 3) break;
570
 
571
                if (len--)
572
                        rxd_buffer[ptrOut++] = (a << 2) | (b >> 4);
573
                else
574
                        break;
575
 
576
                if (len--)
577
                        rxd_buffer[ptrOut++] = ((b & 0x0f) << 4) | (c >> 2);
578
                else
579
                        break;
580
 
581
                if (len--)
582
                        rxd_buffer[ptrOut++] = ((c & 0x03) << 6) | d;
583
                else
584
                        break;
585
        }
586
        pRxData = &rxd_buffer[3];
587
        RxDataLen = ptrOut - 3;
588
}
589
 
590
 
591
//-----------------------------------------------------------------------------
592
//
593
void SwitchToNC (void)
594
{
595
 
596
        if(hardware == NC)
597
        {
598
                // switch to NC
599
                USART_putc (0x1b);
600
                USART_putc (0x1b);
601
                USART_putc (0x55);
602
                USART_putc (0xaa);
603
                USART_putc (0x00);
604
                current_hardware = NC;
605
                _delay_ms (50);
606
        }
607
}
608
 
609
//-----------------------------------------------------------------------------
610
//
611
 
612
 
613
//-----------------------------------------------------------------------------
614
//
615
void SwitchToWi232 (void)
616
{
617
 
618
//      if(hardware == NC)
619
        {
620
                // switch to Wi232
621
                current_hardware = Wi232;
622
                _delay_ms (50);
623
        }
624
}
625
 
626
//-----------------------------------------------------------------------------
627
//
628
void SwitchToFC (void)
629
{
630
        uint8_t cmd;
631
 
632
        if (current_hardware == NC)
633
        {
634
                // switch to FC
635
                cmd = 0x00;     // 0 = FC, 1 = MK3MAG, 2 = MKGPS
636
                SendOutData('u', ADDRESS_NC, 1, &cmd, 1);
637
                current_hardware = FC;
638
                _delay_ms (50);
639
        }
640
}
641
 
642
//-----------------------------------------------------------------------------
643
//
644
void SwitchToMAG (void)
645
{
646
        uint8_t cmd;
647
 
648
        if (current_hardware == NC)
649
        {
650
                // switch to MK3MAG
651
                cmd = 0x01;     // 0 = FC, 1 = MK3MAG, 2 = MKGPS
652
                SendOutData('u', ADDRESS_NC, 1, &cmd, 1);
653
                current_hardware = MK3MAG;
654
                _delay_ms (50);
655
        }
656
}
657
 
658
//-----------------------------------------------------------------------------
659
//
660
void SwitchToGPS (void)
661
{
662
        uint8_t cmd;
663
        if (current_hardware == NC)
664
        {
665
                // switch to MKGPS
666
                cmd = 0x02;     // 0 = FC, 1 = MK3MAG, 2 = MKGPS
667
                SendOutData('u', ADDRESS_NC, 1, &cmd, 1);
668
                current_hardware = MKGPS;
669
                _delay_ms (50);
670
        }
671
}