Subversion Repositories Projects

Rev

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