Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1470 - 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
 
48
uint8_t buffer[30];
49
 
50
volatile uint8_t txd_buffer[TXD_BUFFER_LEN];
51
volatile uint8_t txd_complete = TRUE;
52
 
53
volatile uint8_t rxd_buffer[RXD_BUFFER_LEN];
54
volatile uint8_t rxd_buffer_locked = FALSE;
55
volatile uint8_t ReceivedBytes = 0;
56
volatile uint8_t *pRxData = 0;
57
volatile uint8_t RxDataLen = 0;
58
 
59
volatile uint16_t stat_crc_error = 0;
60
volatile uint16_t stat_overflow_error = 0;
61
 
62
volatile uint8_t rx_byte;
63
volatile uint8_t rxFlag = 0;
64
 
65
 
66
#define UART_RXBUFSIZE 64
67
#define UART_NO_DATA          0x0100              /* no receive data available   */
68
 
69
volatile static uint8_t rxbuf[UART_RXBUFSIZE];
70
volatile static uint8_t *volatile rxhead, *volatile rxtail;
71
 
72
 
73
/*
74
 
75
//-----------------------------------------------------------------------------
76
// USART1 transmitter ISR
77
ISR (USART1_TX_vect)
78
{
79
        static uint16_t ptr_txd1_buffer = 0;
80
        uint8_t tmp_tx1;
81
 
82
        if(!txd1_complete) // transmission not completed
83
        {
84
                ptr_txd1_buffer++;                    // [0] was already sent
85
                tmp_tx1 = txd1_buffer[ptr_txd1_buffer];
86
                // if terminating character or end of txd buffer was reached
87
                if((tmp_tx1 == '\r') || (ptr_txd1_buffer == TXD_BUFFER_LEN))
88
                {
89
                        ptr_txd1_buffer = 0;            // reset txd pointer
90
                        txd1_complete = TRUE;   // stop transmission
91
                }
92
                UDR1 = tmp_tx1; // send current byte will trigger this ISR again
93
        }
94
        // transmission completed
95
        else ptr_txd1_buffer = 0;
96
}
97
 
98
*/
99
 
100
 
101
#ifdef USART_INT
102
//-----------------------------------------------------------------------------
103
// USART0 transmitter ISR
104
ISR (USART_TX_vect)
105
{
106
        static uint16_t ptr_txd_buffer = 0;
107
        uint8_t tmp_tx;
108
 
109
        if(!txd_complete) // transmission not completed
110
        {
111
                ptr_txd_buffer++;                    // [0] was already sent
112
                tmp_tx = txd_buffer[ptr_txd_buffer];
113
                // if terminating character or end of txd buffer was reached
114
                if((tmp_tx == '\r') || (ptr_txd_buffer == TXD_BUFFER_LEN))
115
                {
116
                        ptr_txd_buffer = 0;             // reset txd pointer
117
                        txd_complete = TRUE;    // stop transmission
118
                }
119
                UDR = tmp_tx; // send current byte will trigger this ISR again
120
        }
121
        // transmission completed
122
        else ptr_txd_buffer = 0;
123
}
124
#endif
125
 
126
 
127
 
128
 
129
 
130
//-----------------------------------------------------------------------------
131
//
132
 
133
//
134
//uint8_t uart_getc_nb(uint8_t *c)
135
//{
136
//      if (rxhead==rxtail) return 0;
137
//      *c = *rxtail;
138
//      if (++rxtail == (rxbuf + UART_RXBUFSIZE)) rxtail = rxbuf;
139
//      return 1;
140
//}
141
 
142
 
143
 
144
 
145
ISR (USART0_RX_vect)
146
{
147
        static uint16_t crc;
148
        static uint8_t ptr_rxd_buffer = 0;
149
        uint8_t crc1, crc2;
150
        uint8_t c;
151
//      IdleTimer = 0;
152
        if (current_hardware == Wi232)
153
        {
154
//              rx_byte = c;
155
//              rxFlag = 1;
156
                int diff;
157
                uint8_t c;
158
                c=UDR;
159
                diff = rxhead - rxtail;
160
                if (diff < 0) diff += UART_RXBUFSIZE;
161
                if (diff < UART_RXBUFSIZE -1)
162
                {
163
                        *rxhead = c;
164
                        ++rxhead;
165
                        if (rxhead == (rxbuf + UART_RXBUFSIZE)) rxhead = rxbuf;
166
                };
167
//              USART_putc (c);
168
                return;
169
        }
170
 
171
 
172
        if (current_hardware == MKGPS)
173
        {
174
//              rx_byte = c;
175
//              rxFlag = 1;
176
                int diff;
177
                uint8_t c;
178
                c=UDR;
179
                diff = rxhead - rxtail;
180
                if (diff < 0) diff += UART_RXBUFSIZE;
181
                if (diff < UART_RXBUFSIZE -1)
182
                {
183
                        *rxhead = c;
184
                        ++rxhead;
185
                        if (rxhead == (rxbuf + UART_RXBUFSIZE)) rxhead = rxbuf;
186
                };
187
 
188
                return;
189
        }
190
 
191
        c = UDR;  // catch the received byte
192
 
193
 
194
        if (rxd_buffer_locked)
195
                return; // if rxd buffer is locked immediately return
196
 
197
        // the rxd buffer is unlocked
198
        if ((ptr_rxd_buffer == 0) && (c == '#')) // if rxd buffer is empty and syncronisation character is received
199
        {
200
                rxd_buffer[ptr_rxd_buffer++] = c; // copy 1st byte to buffer
201
                crc = c; // init crc
202
        }
203
        else if (ptr_rxd_buffer < RXD_BUFFER_LEN) // collect incomming bytes
204
        {
205
                if(c != '\r') // no termination character
206
                {
207
                        rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
208
                        crc += c; // update crc
209
                }
210
                else // termination character was received
211
                {
212
                        // the last 2 bytes are no subject for checksum calculation
213
                        // they are the checksum itself
214
                        crc -= rxd_buffer[ptr_rxd_buffer-2];
215
                        crc -= rxd_buffer[ptr_rxd_buffer-1];
216
                        // calculate checksum from transmitted data
217
                        crc %= 4096;
218
                        crc1 = '=' + crc / 64;
219
                        crc2 = '=' + crc % 64;
220
                        // compare checksum to transmitted checksum bytes
221
                        if((crc1 == rxd_buffer[ptr_rxd_buffer-2]) && (crc2 == rxd_buffer[ptr_rxd_buffer-1]))
222
                        {   // checksum valid
223
                                rxd_buffer[ptr_rxd_buffer] = '\r'; // set termination character
224
                                ReceivedBytes = ptr_rxd_buffer + 1;// store number of received bytes
225
                                if (mode == rxd_buffer[2])
226
                                {
227
                                        rxd_buffer_locked = TRUE;          // lock the rxd buffer
228
                                        // if 2nd byte is an 'R' enable watchdog that will result in an reset
229
                                        if(rxd_buffer[2] == 'R') {wdt_enable(WDTO_250MS);} // Reset-Commando
230
                                }
231
                        }
232
                        else
233
                        {       // checksum invalid
234
                                stat_crc_error++;
235
                                rxd_buffer_locked = FALSE; // unlock rxd buffer
236
                        }
237
                        ptr_rxd_buffer = 0; // reset rxd buffer pointer
238
                }
239
        }
240
        else // rxd buffer overrun
241
        {
242
                stat_overflow_error++;
243
                ptr_rxd_buffer = 0; // reset rxd buffer
244
                rxd_buffer_locked = FALSE; // unlock rxd buffer
245
        }
246
}
247
 
248
 
249
//-----------------------------------------------------------------------------
250
// Function: uart0_getc()
251
// Purpose:  return byte from ringbuffer
252
// Returns:  lower byte:  received byte from ringbuffer
253
//           higher byte: last receive error
254
//-----------------------------------------------------------------------------
255
char USART_getc(void)
256
{
257
        char val;
258
 
259
//      while(rxhead==rxtail) ;
260
        if (rxhead==rxtail)
261
                return val=0;
262
//      IdleTimer = 0;
263
        val = *rxtail;
264
        if (++rxtail == (rxbuf + UART_RXBUFSIZE))
265
                rxtail = rxbuf;
266
 
267
        return val;
268
}
269
 
270
 
271
uint8_t uart_getc_nb(uint8_t *c)
272
{
273
        if (rxhead==rxtail)
274
                return 0;
275
//      IdleTimer = 0;
276
        *c = *rxtail;
277
        if (++rxtail == (rxbuf + UART_RXBUFSIZE))
278
                rxtail = rxbuf;
279
        return 1;
280
}
281
//-----------------------------------------------------------------------------
282
//
283
 
284
 
285
 
286
 
287
 
288
//-----------------------------------------------------------------------------
289
//
290
void USART_Init (unsigned int baudrate)
291
{
292
        // set clock divider
293
//      #undef BAUD
294
//      #define BAUD baudrate
295
//      #include <util/setbaud.h>
296
//      UBRRH = UBRRH_VALUE;
297
//      UBRRL = UBRRL_VALUE;
298
 
299
        UBRRH = (unsigned char)(baudrate>>8);
300
        UBRRL = (unsigned char) baudrate;
301
 
302
#if USE_2X
303
        UCSRA |= (1 << U2X);    // enable double speed operation
304
#else
305
        UCSRA &= ~(1 << U2X);   // disable double speed operation
306
#endif
307
 
308
        // set 8N1
309
#if defined (__AVR_ATmega8__) || defined (__AVR_ATmega32__)
310
        UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
311
#else
312
        UCSRC = (1 << UCSZ1) | (1 << UCSZ0);
313
#endif
314
        UCSRB &= ~(1 << UCSZ2);
315
 
316
        // flush receive buffer
317
        while ( UCSRA & (1 << RXC) ) UDR;
318
 
319
        UCSRB |= (1 << RXEN) | (1 << TXEN);
320
#ifdef USART_INT
321
        UCSRB |= (1 << RXCIE) | (1 << TXCIE);
322
#else
323
        UCSRB |= (1 << RXCIE);
324
#endif
325
 
326
        rxhead = rxtail = rxbuf;
327
 
328
}
329
 
330
 
331
 
332
 
333
 
334
//-----------------------------------------------------------------------------
335
// disable the txd pin of usart
336
void USART_DisableTXD (void)
337
{
338
#ifdef USART_INT
339
        UCSRB &= ~(1 << TXCIE);         // disable TX-Interrupt
340
#endif
341
        UCSRB &= ~(1 << TXEN);          // disable TX in USART
342
        DDRB  &= ~(1 << DDB3);          // set TXD pin as input
343
        PORTB &= ~(1 << PORTB3);        // disable pullup on TXD pin
344
}
345
 
346
//-----------------------------------------------------------------------------
347
// enable the txd pin of usart
348
void USART_EnableTXD (void)
349
{
350
        DDRB  |=  (1 << DDB3);          // set TXD pin as output
351
        PORTB &= ~(1 << PORTB3);        // disable pullup on TXD pin
352
        UCSRB |=  (1 << TXEN);          // enable TX in USART
353
#ifdef USART_INT
354
        UCSRB |=  (1 << TXCIE);         // enable TX-Interrupt
355
#endif
356
}
357
 
358
//-----------------------------------------------------------------------------
359
// short script to directly send a request thorugh usart including en- and disabling it
360
// where <address> is the address of the receipient, <label> is which data set to request
361
// and <ms> represents the milliseconds delay between data
362
void USART_request_mk_data (uint8_t cmd, uint8_t addr, uint8_t ms)
363
{
364
        USART_EnableTXD ();     // re-enable TXD pin
365
 
366
        unsigned char mstenth = ms/10;
367
        SendOutData(cmd, addr, 1, &mstenth, 1);
368
        // wait until command transmitted
369
        while (txd_complete == FALSE);
370
 
371
        USART_DisableTXD ();    // disable TXD pin again
372
}
373
 
374
//-----------------------------------------------------------------------------
375
//
376
void USART_putc (char c)
377
{
378
#ifdef USART_INT
379
#else
380
        loop_until_bit_is_set(UCSRA, UDRE);
381
        UDR = c;
382
#endif
383
}
384
 
385
 
386
 
387
//-----------------------------------------------------------------------------
388
//
389
void USART_puts (char *s)
390
{
391
#ifdef USART_INT
392
#else
393
        while (*s)
394
        {
395
                USART_putc (*s);
396
                s++;
397
        }
398
#endif
399
}
400
 
401
//-----------------------------------------------------------------------------
402
//
403
void USART_puts_p (const char *s)
404
{
405
#ifdef USART_INT
406
#else
407
        while (pgm_read_byte(s))
408
        {
409
                USART_putc (pgm_read_byte(s));
410
                s++;
411
        }
412
#endif
413
}
414
 
415
//-----------------------------------------------------------------------------
416
//
417
void SendOutData(uint8_t cmd, uint8_t addr, uint8_t numofbuffers, ...) // uint8_t *pdata, uint8_t len, ...
418
{
419
        va_list ap;
420
        uint16_t pt = 0;
421
        uint8_t a,b,c;
422
        uint8_t ptr = 0;
423
        uint16_t tmpCRC = 0;
424
 
425
        uint8_t *pdata = 0;
426
        int len = 0;
427
 
428
        txd_buffer[pt++] = '#';                                 // Start character
429
        txd_buffer[pt++] = 'a' + addr;  // Address (a=0; b=1,...)
430
        txd_buffer[pt++] = cmd;                                 // Command
431
 
432
        va_start(ap, numofbuffers);
433
        if(numofbuffers)
434
        {
435
                pdata = va_arg (ap, uint8_t*);
436
                len = va_arg (ap, int);
437
                ptr = 0;
438
                numofbuffers--;
439
        }
440
 
441
        while(len)
442
        {
443
                if(len)
444
                {
445
                        a = pdata[ptr++];
446
                        len--;
447
                        if((!len) && numofbuffers)
448
                        {
449
                                pdata = va_arg(ap, uint8_t*);
450
                                len = va_arg(ap, int);
451
                                ptr = 0;
452
                                numofbuffers--;
453
                        }
454
                }
455
                else
456
                        a = 0;
457
 
458
                if(len)
459
                {
460
                        b = pdata[ptr++];
461
                        len--;
462
                        if((!len) && numofbuffers)
463
                        {
464
                                pdata = va_arg(ap, uint8_t*);
465
                                len = va_arg(ap, int);
466
                                ptr = 0;
467
                                numofbuffers--;
468
                        }
469
                }
470
                else
471
                        b = 0;
472
 
473
                if(len)
474
                {
475
                        c = pdata[ptr++];
476
                        len--;
477
                        if((!len) && numofbuffers)
478
                        {
479
                                pdata = va_arg(ap, uint8_t*);
480
                                len = va_arg(ap, int);
481
                                ptr = 0;
482
                                numofbuffers--;
483
                        }
484
                }
485
                else
486
                        c = 0;
487
 
488
                txd_buffer[pt++] = '=' + (a >> 2);
489
                txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
490
                txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
491
                txd_buffer[pt++] = '=' + ( c & 0x3f);
492
        }
493
        va_end(ap);
494
 
495
        for(a = 0; a < pt; a++)
496
        {
497
                tmpCRC += txd_buffer[a];
498
        }
499
        tmpCRC %= 4096;
500
        txd_buffer[pt++] = '=' + tmpCRC / 64;
501
        txd_buffer[pt++] = '=' + tmpCRC % 64;
502
        txd_buffer[pt++] = '\r';
503
 
504
        txd_complete = FALSE;
505
#ifdef USART_INT
506
        UDR = txd_buffer[0]; // initiates the transmittion (continued in the TXD ISR)
507
#else
508
        for(a = 0; a < pt; a++)
509
        {
510
                loop_until_bit_is_set(UCSRA, UDRE);
511
                UDR = txd_buffer[a];
512
        }
513
        txd_complete = TRUE;
514
#endif
515
}
516
 
517
//-----------------------------------------------------------------------------
518
//
519
void Decode64 (void)
520
{
521
        uint8_t a,b,c,d;
522
        uint8_t ptrIn = 3;
523
        uint8_t ptrOut = 3;
524
        uint8_t len = ReceivedBytes - 6;
525
 
526
        while (len)
527
        {
528
                a = rxd_buffer[ptrIn++] - '=';
529
                b = rxd_buffer[ptrIn++] - '=';
530
                c = rxd_buffer[ptrIn++] - '=';
531
                d = rxd_buffer[ptrIn++] - '=';
532
                //if(ptrIn > ReceivedBytes - 3) break;
533
 
534
                if (len--)
535
                        rxd_buffer[ptrOut++] = (a << 2) | (b >> 4);
536
                else
537
                        break;
538
 
539
                if (len--)
540
                        rxd_buffer[ptrOut++] = ((b & 0x0f) << 4) | (c >> 2);
541
                else
542
                        break;
543
 
544
                if (len--)
545
                        rxd_buffer[ptrOut++] = ((c & 0x03) << 6) | d;
546
                else
547
                        break;
548
        }
549
        pRxData = &rxd_buffer[3];
550
        RxDataLen = ptrOut - 3;
551
}
552
 
553
 
554
//-----------------------------------------------------------------------------
555
//
556
void SwitchToNC (void)
557
{
558
 
559
        if(hardware == NC)
560
        {
561
                // switch to NC
562
                USART_putc (0x1b);
563
                USART_putc (0x1b);
564
                USART_putc (0x55);
565
                USART_putc (0xaa);
566
                USART_putc (0x00);
567
                current_hardware = NC;
568
                _delay_ms (50);
569
        }
570
}
571
 
572
//-----------------------------------------------------------------------------
573
//
574
 
575
 
576
//-----------------------------------------------------------------------------
577
//
578
void SwitchToWi232 (void)
579
{
580
 
581
//      if(hardware == NC)
582
        {
583
                // switch to Wi232
584
                current_hardware = Wi232;
585
                _delay_ms (50);
586
        }
587
}
588
 
589
//-----------------------------------------------------------------------------
590
//
591
void SwitchToFC (void)
592
{
593
        uint8_t cmd;
594
 
595
        if (current_hardware == NC)
596
        {
597
                // switch to FC
598
                cmd = 0x00;     // 0 = FC, 1 = MK3MAG, 2 = MKGPS
599
                SendOutData('u', ADDRESS_NC, 1, &cmd, 1);
600
                current_hardware = FC;
601
                _delay_ms (50);
602
        }
603
}
604
 
605
//-----------------------------------------------------------------------------
606
//
607
void SwitchToMAG (void)
608
{
609
        uint8_t cmd;
610
 
611
        if (current_hardware == NC)
612
        {
613
                // switch to MK3MAG
614
                cmd = 0x01;     // 0 = FC, 1 = MK3MAG, 2 = MKGPS
615
                SendOutData('u', ADDRESS_NC, 1, &cmd, 1);
616
                current_hardware = MK3MAG;
617
                _delay_ms (50);
618
        }
619
}
620
 
621
//-----------------------------------------------------------------------------
622
//
623
void SwitchToGPS (void)
624
{
625
        uint8_t cmd;
626
        if (current_hardware == NC)
627
        {
628
                // switch to MKGPS
629
                cmd = 0x02;     // 0 = FC, 1 = MK3MAG, 2 = MKGPS
630
                SendOutData('u', ADDRESS_NC, 1, &cmd, 1);
631
                current_hardware = MKGPS;
632
                _delay_ms (50);
633
        }
634
}