Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1438 - 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
        }
499
        txd_complete = TRUE;
500
#endif
501
}
502
 
503
//*****************************************************************************
504
// 
505
void Decode64 (void)
506
{
507
        uint8_t a,b,c,d;
508
        uint8_t ptrIn = 3;
509
        uint8_t ptrOut = 3;
510
        uint8_t len = ReceivedBytes - 6;
511
 
512
        while (len)
513
        {
514
                a = rxd_buffer[ptrIn++] - '=';
515
                b = rxd_buffer[ptrIn++] - '=';
516
                c = rxd_buffer[ptrIn++] - '=';
517
                d = rxd_buffer[ptrIn++] - '=';
518
                //if(ptrIn > ReceivedBytes - 3) break;
519
 
520
                if (len--)
521
                        rxd_buffer[ptrOut++] = (a << 2) | (b >> 4);
522
                else
523
                        break;
524
                if (len--)
525
                        rxd_buffer[ptrOut++] = ((b & 0x0f) << 4) | (c >> 2);
526
                else
527
                        break;
528
                if (len--)
529
                        rxd_buffer[ptrOut++] = ((c & 0x03) << 6) | d;
530
                else
531
                        break;
532
        }
533
        pRxData = &rxd_buffer[3];
534
        RxDataLen = ptrOut - 3;
535
}
536
 
537
 
538
//*****************************************************************************
539
// 
540
void SwitchToNC (void)
541
{
542
 
543
        if(hardware == NC)
544
        {
545
                // switch to NC
546
                USART_putc (0x1b);
547
                USART_putc (0x1b);
548
                USART_putc (0x55);
549
                USART_putc (0xaa);
550
                USART_putc (0x00);
551
 
552
                current_hardware = NC;
553
                _delay_ms (50);
554
        }
555
}
556
 
557
//*****************************************************************************
558
// 
559
 
560
 
561
//*****************************************************************************
562
//
563
void SwitchToWi232 (void)
564
{
565
 
566
//      if(hardware == NC)
567
        {
568
                // switch to Wi232
569
 
570
                current_hardware = Wi232;
571
                _delay_ms (50);
572
        }
573
}
574
 
575
//*****************************************************************************
576
//
577
void SwitchToFC (void)
578
{
579
        uint8_t cmd;
580
 
581
        if (current_hardware == NC)
582
        {
583
                // switch to FC
584
                cmd = 0x00;     // 0 = FC, 1 = MK3MAG, 2 = MKGPS
585
                SendOutData('u', ADDRESS_NC, 1, &cmd, 1);
586
 
587
                current_hardware = FC;
588
                _delay_ms (50);
589
        }
590
}
591
 
592
//*****************************************************************************
593
// 
594
void SwitchToMAG (void)
595
{
596
        uint8_t cmd;
597
 
598
        if (current_hardware == NC)
599
        {
600
                // switch to MK3MAG
601
                cmd = 0x01;     // 0 = FC, 1 = MK3MAG, 2 = MKGPS
602
                SendOutData('u', ADDRESS_NC, 1, &cmd, 1);
603
 
604
                current_hardware = MK3MAG;
605
                _delay_ms (50);
606
        }
607
}
608
 
609
//*****************************************************************************
610
// 
611
void SwitchToGPS (void)
612
{
613
        uint8_t cmd;
614
        if (current_hardware == NC)
615
        {
616
                // switch to MKGPS
617
                cmd = 0x02;     // 0 = FC, 1 = MK3MAG, 2 = MKGPS
618
                SendOutData('u', ADDRESS_NC, 1, &cmd, 1);
619
 
620
                current_hardware = MKGPS;
621
                _delay_ms (50);
622
        }
623
}