Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

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