Subversion Repositories Projects

Rev

Rev 436 | Rev 759 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
426 killagreg 1
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2
// + Copyright (c) 04.2007 Holger Buss
3
// + only for non-profit use
4
// + www.MikroKopter.com
5
// + see the File "License.txt" for further Informations
6
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7
 
8
#include <avr/io.h>
9
#include <avr/interrupt.h>
434 killagreg 10
#include <avr/pgmspace.h>
426 killagreg 11
#include <avr/wdt.h>
12
#include <stdarg.h>
13
#include <string.h>
14
 
15
#include "main.h"
16
#include "menu.h"
17
#include "timer0.h"
18
#include "uart0.h"
19
#include "ubx.h"
436 killagreg 20
#include "printf_P.h"
426 killagreg 21
 
22
 
23
#define FC_ADDRESS 1
24
#define NC_ADDRESS 2
25
#define MK3MAG_ADDRESS 3
26
 
27
#define FM_ADDRESS 10 // FOLLOW ME
28
 
29
#define FALSE   0
30
#define TRUE    1
31
 
32
 
33
//int8_t test __attribute__ ((section (".noinit")));
34
uint8_t Request_VerInfo                 = FALSE;
35
uint8_t Request_Display                 = FALSE;
36
uint8_t Request_Display1                = FALSE;
37
uint8_t Request_ExternalControl = FALSE;
38
uint8_t Request_DebugData               = FALSE;
39
uint8_t Request_DebugLabel              = 255;
40
uint8_t Request_SendFollowMe    = FALSE;
41
uint8_t DisplayLine = 0;
42
 
43
volatile uint8_t txd_buffer[TXD_BUFFER_LEN];
44
volatile uint8_t rxd_buffer_locked = FALSE;
45
volatile uint8_t rxd_buffer[RXD_BUFFER_LEN];
46
volatile uint8_t txd_complete = TRUE;
47
volatile uint8_t ReceivedBytes = 0;
48
volatile uint8_t *pRxData = 0;
49
volatile uint8_t RxDataLen = 0;
50
 
51
uint8_t PcAccess = 100;
52
 
53
ExternControl_t ExternControl;
54
DebugOut_t              DebugOut;
55
UART_VersionInfo_t      UART_VersionInfo;
56
 
57
uint16_t DebugData_Timer;
434 killagreg 58
uint16_t DebugData_Interval = 0; // in 1ms
744 woggle 59
uint16_t Display_Interval = 0; // in 1 ms
426 killagreg 60
 
61
Waypoint_t FollowMe;
62
 
434 killagreg 63
// keep lables in flash to save 512 bytes of sram space
64
const prog_uint8_t ANALOG_LABEL[32][16] =
426 killagreg 65
{
66
   //1234567890123456
67
    "Analog_Ch0      ", //0
68
    "Analog_Ch1      ",
69
    "Analog_Ch2      ",
70
    "Analog_Ch3      ",
71
    "Analog_Ch4      ",
72
    "Analog_Ch5      ", //5
73
    "Analog_Ch6      ",
74
    "Analog_Ch7      ",
75
    "UBat            ",
436 killagreg 76
    "SysState        ",
77
    "Debug10         ", //10
78
    "Debug11         ",
79
    "Debug12         ",
80
    "Debug13         ",
81
    "Debug14         ",
82
    "Debug15         ", //15
426 killagreg 83
        "Zellenzahl      ",
84
    "PowerOn         ",
85
    "Debug18         ",
86
    "Debug19         ",
87
    "Debug20         ", //20
88
    "Debug21         ",
89
    "Debug22         ",
90
    "Debug23         ",
91
    "Debug24         ",
92
    "Debug25         ", //25
93
    "Debug26         ",
94
    "Debug27         ",
95
    "Debug28         ",
96
    "Debug29         ",
97
    "Debug30         ", //30
98
    "Debug31         "
99
};
100
 
101
 
102
 
103
/****************************************************************/
104
/*              Initialization of the USART0                    */
105
/****************************************************************/
106
void USART0_Init (void)
107
{
108
        uint8_t sreg = SREG;
109
        uint16_t ubrr = (uint16_t) ((uint32_t) SYSCLK/(8 * USART0_BAUD) - 1);
110
 
111
        // disable all interrupts before configuration
112
        cli();
113
 
114
        // disable RX-Interrupt
115
        UCSR0B &= ~(1 << RXCIE0);
116
        // disable TX-Interrupt
117
        UCSR0B &= ~(1 << TXCIE0);
118
 
119
        // set direction of RXD0 and TXD0 pins
120
        // set RXD0 (PD0) as an input pin
121
        PORTD |= (1 << PORTD0);
122
        DDRD &= ~(1 << DDD0);
123
        // set TXD0 (PD1) as an output pin
124
        PORTD |= (1 << PORTD1);
125
        DDRD |=  (1 << DDD1);
126
 
127
        // USART0 Baud Rate Register
128
        // set clock divider
129
        UBRR0H = (uint8_t)(ubrr >> 8);
130
        UBRR0L = (uint8_t)ubrr;
131
 
132
        // USART0 Control and Status Register A, B, C
133
 
134
        // enable double speed operation in
135
        UCSR0A |= (1 << U2X0);
136
        // enable receiver and transmitter in
137
        UCSR0B = (1 << TXEN0) | (1 << RXEN0);
138
        // set asynchronous mode
139
        UCSR0C &= ~(1 << UMSEL01);
140
        UCSR0C &= ~(1 << UMSEL00);
141
        // no parity
142
        UCSR0C &= ~(1 << UPM01);
143
        UCSR0C &= ~(1 << UPM00);
144
        // 1 stop bit
145
        UCSR0C &= ~(1 << USBS0);
146
        // 8-bit
147
        UCSR0B &= ~(1 << UCSZ02);
148
        UCSR0C |=  (1 << UCSZ01);
149
        UCSR0C |=  (1 << UCSZ00);
150
 
151
                // flush receive buffer
152
        while ( UCSR0A & (1<<RXC0) ) UDR0;
153
 
154
        // enable interrupts at the end
155
        // enable RX-Interrupt
156
        UCSR0B |= (1 << RXCIE0);
157
        // enable TX-Interrupt
158
        UCSR0B |= (1 << TXCIE0);
159
 
160
        // initialize the debug timer
161
        DebugData_Timer = SetDelay(DebugData_Interval);
162
 
163
        // unlock rxd_buffer
164
        rxd_buffer_locked = FALSE;
165
        pRxData = 0;
166
        RxDataLen = 0;
167
 
168
        // no bytes to send
169
        txd_complete = TRUE;
170
 
171
        UART_VersionInfo.SWMajor = VERSION_MAJOR;
172
        UART_VersionInfo.SWMinor = VERSION_MINOR;
173
        UART_VersionInfo.SWPatch = VERSION_PATCH;
174
        UART_VersionInfo.ProtoMajor = VERSION_SERIAL_MAJOR;
175
        UART_VersionInfo.ProtoMinor = VERSION_SERIAL_MINOR;
176
 
177
        // restore global interrupt flags
178
    SREG = sreg;
434 killagreg 179
        sei();
180
    printf("\r\n UART0 init...ok");
426 killagreg 181
}
182
 
183
/****************************************************************/
184
/*               USART0 transmitter ISR                         */
185
/****************************************************************/
186
ISR(USART0_TX_vect)
187
{
188
        static uint16_t ptr_txd_buffer = 0;
189
        uint8_t tmp_tx;
190
        if(!txd_complete) // transmission not completed
191
        {
192
                ptr_txd_buffer++;                    // die [0] wurde schon gesendet
193
                tmp_tx = txd_buffer[ptr_txd_buffer];
194
                // if terminating character or end of txd buffer was reached
195
                if((tmp_tx == '\r') || (ptr_txd_buffer == TXD_BUFFER_LEN))
196
                {
197
                        ptr_txd_buffer = 0; // reset txd pointer
198
                        txd_complete = 1; // stop transmission
199
                }
200
                UDR0 = tmp_tx; // send current byte will trigger this ISR again
201
        }
202
        // transmission completed
203
        else ptr_txd_buffer = 0;
204
}
205
 
206
/****************************************************************/
207
/*               USART0 receiver ISR                            */
208
/****************************************************************/
209
ISR(USART0_RX_vect)
210
{
211
        static uint16_t crc;
212
        static uint8_t ptr_rxd_buffer = 0;
213
        uint8_t crc1, crc2;
214
        uint8_t c;
215
 
216
        c = UDR0;  // catch the received byte
217
 
218
        if(rxd_buffer_locked) return; // if rxd buffer is locked immediately return
219
 
220
        // the rxd buffer is unlocked
221
        if((ptr_rxd_buffer == 0) && (c == '#')) // if rxd buffer is empty and syncronisation character is received
222
        {
223
                rxd_buffer[ptr_rxd_buffer++] = c; // copy 1st byte to buffer
224
                crc = c; // init crc
225
        }
226
        #if 0
227
        else if (ptr_rxd_buffer == 1) // handle address
228
        {
229
                rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
230
                crc += c; // update crc
231
        }
232
        #endif
233
        else if (ptr_rxd_buffer < RXD_BUFFER_LEN) // collect incomming bytes
234
        {
235
                if(c != '\r') // no termination character
236
                {
237
                        rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
238
                        crc += c; // update crc
239
                }
240
                else // termination character was received
241
                {
242
                        // the last 2 bytes are no subject for checksum calculation
243
                        // they are the checksum itself
244
                        crc -= rxd_buffer[ptr_rxd_buffer-2];
245
                        crc -= rxd_buffer[ptr_rxd_buffer-1];
246
                        // calculate checksum from transmitted data
247
                        crc %= 4096;
248
                        crc1 = '=' + crc / 64;
249
                        crc2 = '=' + crc % 64;
250
                        // compare checksum to transmitted checksum bytes
251
                        if((crc1 == rxd_buffer[ptr_rxd_buffer-2]) && (crc2 == rxd_buffer[ptr_rxd_buffer-1]))
252
                        {   // checksum valid
253
                                rxd_buffer[ptr_rxd_buffer] = '\r'; // set termination character
254
                                ReceivedBytes = ptr_rxd_buffer + 1;// store number of received bytes
255
                                rxd_buffer_locked = TRUE;          // lock the rxd buffer
256
                                // if 2nd byte is an 'R' enable watchdog that will result in an reset
257
                                if(rxd_buffer[2] == 'R') {wdt_enable(WDTO_250MS);} // Reset-Commando
258
                        }
259
                        else
260
                        {       // checksum invalid
261
                                rxd_buffer_locked = FALSE; // unlock rxd buffer
262
                        }
263
                        ptr_rxd_buffer = 0; // reset rxd buffer pointer
264
                }
265
        }
266
        else // rxd buffer overrun
267
        {
268
                ptr_rxd_buffer = 0; // reset rxd buffer
269
                rxd_buffer_locked = FALSE; // unlock rxd buffer
270
        }
271
 
272
}
273
 
274
 
275
// --------------------------------------------------------------------------
276
void AddCRC(uint16_t datalen)
277
{
278
        uint16_t tmpCRC = 0, i;
279
        for(i = 0; i < datalen; i++)
280
        {
281
                tmpCRC += txd_buffer[i];
282
        }
283
        tmpCRC %= 4096;
284
        txd_buffer[i++] = '=' + tmpCRC / 64;
285
        txd_buffer[i++] = '=' + tmpCRC % 64;
286
        txd_buffer[i++] = '\r';
287
        txd_complete = FALSE;
288
        UDR0 = txd_buffer[0]; // initiates the transmittion (continued in the TXD ISR)
289
}
290
 
291
 
292
 
293
// --------------------------------------------------------------------------
294
void SendOutData(uint8_t cmd, uint8_t addr, uint8_t numofbuffers, ...) // uint8_t *pdata, uint8_t len, ...
295
{
296
        va_list ap;
297
        uint16_t pt = 0;
298
        uint8_t a,b,c;
299
        uint8_t ptr = 0;
300
 
301
        uint8_t *pdata = 0;
302
        int len = 0;
303
 
304
        txd_buffer[pt++] = '#';                 // Start character
305
        txd_buffer[pt++] = 'a' + addr;  // Address (a=0; b=1,...)
306
        txd_buffer[pt++] = cmd;                 // Command
307
 
308
        va_start(ap, numofbuffers);
309
        if(numofbuffers)
310
        {
311
                pdata = va_arg(ap, uint8_t*);
312
                len = va_arg(ap, int);
313
                ptr = 0;
314
                numofbuffers--;
315
        }
316
 
317
        while(len)
318
        {
319
                if(len)
320
                {
321
                        a = pdata[ptr++];
322
                        len--;
323
                        if((!len) && numofbuffers)
324
                        {
325
                                pdata = va_arg(ap, uint8_t*);
326
                                len = va_arg(ap, int);
327
                                ptr = 0;
328
                                numofbuffers--;
329
                        }
330
                }
331
                else a = 0;
332
                if(len)
333
                {
334
                        b = pdata[ptr++];
335
                        len--;
336
                        if((!len) && numofbuffers)
337
                        {
338
                                pdata = va_arg(ap, uint8_t*);
339
                                len = va_arg(ap, int);
340
                                ptr = 0;
341
                                numofbuffers--;
342
                        }
343
                }
344
                else b = 0;
345
                if(len)
346
                {
347
                        c = pdata[ptr++];
348
                        len--;
349
                        if((!len) && numofbuffers)
350
                        {
351
                                pdata = va_arg(ap, uint8_t*);
352
                                len = va_arg(ap, int);
353
                                ptr = 0;
354
                                numofbuffers--;
355
                        }
356
                }
357
                else c = 0;
358
                txd_buffer[pt++] = '=' + (a >> 2);
359
                txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
360
                txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
361
                txd_buffer[pt++] = '=' + ( c & 0x3f);
362
        }
363
        va_end(ap);
364
        AddCRC(pt); // add checksum after data block and initates the transmission
365
}
366
 
367
 
368
// --------------------------------------------------------------------------
369
void Decode64(void)
370
{
371
        uint8_t a,b,c,d;
372
        uint8_t x,y,z;
373
        uint8_t ptrIn = 3;
374
        uint8_t ptrOut = 3;
375
        uint8_t len = ReceivedBytes - 6;
376
 
377
        while(len)
378
        {
379
                a = rxd_buffer[ptrIn++] - '=';
380
                b = rxd_buffer[ptrIn++] - '=';
381
                c = rxd_buffer[ptrIn++] - '=';
382
                d = rxd_buffer[ptrIn++] - '=';
383
                //if(ptrIn > ReceivedBytes - 3) break;
384
 
385
                x = (a << 2) | (b >> 4);
386
                y = ((b & 0x0f) << 4) | (c >> 2);
387
                z = ((c & 0x03) << 6) | d;
388
 
389
                if(len--) rxd_buffer[ptrOut++] = x; else break;
390
                if(len--) rxd_buffer[ptrOut++] = y; else break;
391
                if(len--) rxd_buffer[ptrOut++] = z; else break;
392
        }
393
        pRxData = &rxd_buffer[3];
394
        RxDataLen = ptrOut - 3;
395
}
396
 
397
 
398
// --------------------------------------------------------------------------
399
void USART0_ProcessRxData(void)
400
{
401
        // if data in the rxd buffer are not locked immediately return
402
        if(!rxd_buffer_locked) return;
403
 
404
        Decode64(); // decode data block in rxd_buffer
405
 
406
 
407
        switch(rxd_buffer[1] - 'a')
408
        {
409
                case FM_ADDRESS:
410
 
411
                        switch(rxd_buffer[2])
412
                        {
413
                                default:
414
                                        //unsupported command received
415
                                        break;
416
                        } // case FC_ADDRESS:
417
 
418
                default: // any Slave Address
419
 
420
                switch(rxd_buffer[2])
421
                        {
422
                                case 'a':// request for labels of the analog debug outputs
423
                                        Request_DebugLabel = pRxData[0];
424
                                        if(Request_DebugLabel > 31) Request_DebugLabel = 31;
425
                                        PcAccess = 255;
426
                                        break;
427
 
428
                                case 'h':// request for display columns
429
                                        PcAccess = 255;
744 woggle 430
                                        if((pRxData[0] & 0x80) == 0x00) // old format
431
                                        {
432
                                                DisplayLine = 2;
433
                                                Display_Interval = 0;
434
                                        }
435
                                        else // new format
436
                                        {
437
                                                RemoteKeys |= ~pRxData[0];
438
                                                Display_Interval = (unsigned int)pRxData[1] * 10;
439
                                                DisplayLine = 4;
440
                                                Request_Display = TRUE;
441
                                        }
426 killagreg 442
                                        break;
443
 
444
                                case 'l':// request for display columns
445
                                        PcAccess = 255;
446
                                        MenuItem = pRxData[0];
447
                                        Request_Display1 = TRUE;
448
                                        break;
449
 
450
                                case 'v': // request for version and board release
451
                                        Request_VerInfo = TRUE;
452
                                        break;
453
 
454
                                case 'd': // request for the debug data
455
                                        DebugData_Interval = (uint16_t) pRxData[0] * 10;
456
                                        if(DebugData_Interval > 0) Request_DebugData = TRUE;
457
                                        break;
458
 
459
                                case 'g':// get external control data
460
                                        Request_ExternalControl = TRUE;
461
                                        break;
462
 
463
                                default:
464
                                        //unsupported command received
465
                                        break;
466
                }
467
                break; // default:
468
        }
469
        // unlock the rxd buffer after processing
470
        pRxData = 0;
471
        RxDataLen = 0;
472
        rxd_buffer_locked = FALSE;
473
}
474
 
475
//############################################################################
476
//Routine für die Serielle Ausgabe
477
int16_t uart_putchar (int8_t c)
478
//############################################################################
479
{
480
        if (c == '\n')
481
                uart_putchar('\r');
482
        // wait until previous character was send
483
        loop_until_bit_is_set(UCSR0A, UDRE0);
484
        // send character
485
        UDR0 = c;
486
        return (0);
487
}
488
 
489
 
490
//---------------------------------------------------------------------------------------------
491
void USART0_TransmitTxData(void)
492
{
493
        if(!txd_complete) return;
494
 
495
        if(Request_VerInfo && txd_complete)
496
        {
497
                SendOutData('V', FM_ADDRESS, 1, (uint8_t *) &UART_VersionInfo, sizeof(UART_VersionInfo));
498
                Request_VerInfo = FALSE;
499
        }
744 woggle 500
        if( ((DebugData_Interval && CheckDelay(DebugData_Timer)) || Request_Display) && txd_complete)
426 killagreg 501
        {
744 woggle 502
                if(DisplayLine > 3)// new format
503
                {
504
                        LCD_PrintMenu();
505
                        SendOutData('H', FM_ADDRESS, 1, (uint8_t *)DisplayBuff, 80);
506
                }
507
                else // old format
508
                {
509
                        LCD_printfxy(0,0,"!!! INCOMPATIBLE !!!");
510
                        SendOutData('H', FC_ADDRESS, 2, &DisplayLine, sizeof(DisplayLine), (uint8_t *)DisplayBuff, 20);
511
                        if(DisplayLine++ > 3) DisplayLine = 0;
512
                }
426 killagreg 513
                Request_Display = FALSE;
514
        }
515
        if(Request_Display1 && txd_complete)
516
        {
517
                LCD_PrintMenu();
518
                SendOutData('L', FM_ADDRESS, 3, &MenuItem, sizeof(MenuItem), &MaxMenuItem, sizeof(MaxMenuItem), DisplayBuff, sizeof(DisplayBuff));
519
                Request_Display1 = FALSE;
520
        }
521
        if(Request_DebugLabel != 0xFF) // Texte für die Analogdaten
522
        {
434 killagreg 523
                uint8_t label[16]; // local sram buffer
524
                memcpy_P(label, ANALOG_LABEL[Request_DebugLabel], 16); // read lable from flash to sram buffer
525
                SendOutData('A', FM_ADDRESS, 2, (uint8_t *) &Request_DebugLabel, sizeof(Request_DebugLabel), label, 16);
426 killagreg 526
                Request_DebugLabel = 0xFF;
527
        }
528
        if(Request_ExternalControl && txd_complete)
529
        {
530
                SendOutData('G', FM_ADDRESS, 1,(uint8_t *) &ExternControl, sizeof(ExternControl));
531
                Request_ExternalControl = FALSE;
532
        }
533
        if( ((DebugData_Interval && CheckDelay(DebugData_Timer)) || Request_DebugData) && txd_complete)
534
        {
535
                SendOutData('D', FM_ADDRESS, 1,(uint8_t *) &DebugOut, sizeof(DebugOut));
536
                DebugData_Timer = SetDelay(DebugData_Interval);
537
                Request_DebugData = FALSE;
538
    }
539
        if(Request_SendFollowMe && txd_complete)
540
        {
541
                SendOutData('s', NC_ADDRESS, 1, (uint8_t *)&FollowMe, sizeof(FollowMe));
542
                FollowMe.Position.Status = PROCESSED;
543
                Request_SendFollowMe = FALSE;
544
        }
545
}
546