Subversion Repositories FlightCtrl

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1180 killagreg 1
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2
// + Copyright (c) 04.2007 Holger Buss
3
// + Nur für den privaten Gebrauch
4
// + www.MikroKopter.com
5
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
7
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
8
// + Sollten direkte oder indirekte kommerzielle Absichten verfolgt werden, ist mit uns (info@mikrokopter.de) Kontakt
9
// + bzgl. der Nutzungsbedingungen aufzunehmen.
10
// + Eine kommerzielle Nutzung ist z.B.Verkauf von MikroKoptern, Bestückung und Verkauf von Platinen oder Bausätzen,
11
// + Verkauf von Luftbildaufnahmen, usw.
12
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
14
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
15
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
17
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
18
// + eindeutig als Ursprung verlinkt werden
19
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
20
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
21
// + Benutzung auf eigene Gefahr
22
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
23
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
24
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
25
// + mit unserer Zustimmung zulässig
26
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
27
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
28
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
29
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
30
// + this list of conditions and the following disclaimer.
31
// +   * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
32
// +     from this software without specific prior written permission.
33
// +   * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
34
// +     for non-commercial use (directly or indirectly)
35
// +     Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
36
// +     with our written permission
37
// +   * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be
38
// +     clearly linked as origin
39
// +   * porting to systems other than hardware from www.mikrokopter.de is not allowed
40
// +  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
41
// +  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
// +  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43
// +  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
44
// +  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
45
// +  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
46
// +  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
47
// +  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN// +  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48
// +  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49
// +  POSSIBILITY OF SUCH DAMAGE.
50
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
51
#include <avr/io.h>
52
#include <avr/interrupt.h>
53
#include <avr/wdt.h>
54
#include <stdarg.h>
55
#include <string.h>
56
 
57
#include "eeprom.h"
58
#include "main.h"
59
#include "menu.h"
60
#include "timer0.h"
61
#include "uart0.h"
62
#include "fc.h"
63
#include "rc.h"
64
#if defined (USE_KILLAGREG) || defined (USE_MK3MAG)
65
#include "ubx.h"
66
#endif
67
#ifdef USE_MK3MAG
68
#include "mk3mag.h"
69
#endif
70
 
71
 
72
#define FC_ADDRESS 1
73
#define NC_ADDRESS 2
74
#define MK3MAG_ADDRESS 3
75
 
76
#define FALSE   0
77
#define TRUE    1
78
 
79
//int8_t test __attribute__ ((section (".noinit")));
80
uint8_t Request_VerInfo                 = FALSE;
81
uint8_t Request_ExternalControl = FALSE;
82
uint8_t Request_Display                 = FALSE;
83
uint8_t Request_Display1                = FALSE;
84
uint8_t Request_DebugData               = FALSE;
85
uint8_t Request_Data3D                  = FALSE;
86
uint8_t Request_DebugLabel              = 255;
87
uint8_t Request_PPMChannels     = FALSE;
88
uint8_t Request_MotorTest               = FALSE;
89
uint8_t DisplayLine = 0;
90
 
91
volatile uint8_t txd_buffer[TXD_BUFFER_LEN];
92
volatile uint8_t rxd_buffer_locked = FALSE;
93
volatile uint8_t rxd_buffer[RXD_BUFFER_LEN];
94
volatile uint8_t txd_complete = TRUE;
95
volatile uint8_t ReceivedBytes = 0;
96
volatile uint8_t *pRxData = 0;
97
volatile uint8_t RxDataLen = 0;
98
 
99
uint8_t PcAccess = 100;
1222 killagreg 100
 
101
uint8_t MotorTest_Active  = 0;
102
uint8_t MotorTest[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
1180 killagreg 103
uint8_t ConfirmFrame;
104
 
105
typedef struct
106
{
107
        int16_t Heading;
108
} __attribute__((packed)) Heading_t;
109
 
110
DebugOut_t              DebugOut;
111
Data3D_t                Data3D;
112
ExternControl_t ExternControl;
113
UART_VersionInfo_t      UART_VersionInfo;
114
 
115
uint16_t DebugData_Timer;
116
uint16_t Data3D_Timer;
117
uint16_t DebugData_Interval = 500; // in 1ms
118
uint16_t Data3D_Interval = 0; // in 1ms
119
 
120
#ifdef USE_MK3MAG
121
int16_t Compass_Timer;
122
#endif
123
 
124
 
125
const uint8_t ANALOG_LABEL[32][16] =
126
{
127
   //1234567890123456
128
    "AngleNick       ", //0
129
    "AngleRoll       ",
130
    "AccNick         ",
131
    "AccRoll         ",
132
    "YawGyro         ",
133
    "Height Value    ", //5
134
    "AccZ            ",
135
    "Gas             ",
136
    "Compass Heading ",
137
    "Voltage         ",
138
    "Receiver Level  ", //10
139
    "YawGyro Heading ",
140
    "Motor Front     ",
141
    "Motor Rear      ",
142
    "Motor Left      ",
143
    "Motor Right     ", //15
144
    "                ",
145
    "                ",
146
    "                ",
147
    "CompassCalState ",
148
    "NickServo       ", //20
149
    "                ",
150
    "                ",
151
    "                ",
152
    "                ",
153
    "                ", //25
154
    "                ",
155
    "Kalman Max Drift",
156
    "                ",
1222 killagreg 157
    "Navi Serial Data",
1180 killagreg 158
    "GPS Nick        ", //30
159
    "GPSS Roll       "
160
};
161
 
162
 
163
 
164
/****************************************************************/
165
/*              Initialization of the USART0                    */
166
/****************************************************************/
167
void USART0_Init (void)
168
{
169
        uint8_t sreg = SREG;
170
        uint16_t ubrr = (uint16_t) ((uint32_t) SYSCLK/(8 * USART0_BAUD) - 1);
171
 
172
        // disable all interrupts before configuration
173
        cli();
174
 
175
        // disable RX-Interrupt
176
        UCSR0B &= ~(1 << RXCIE0);
177
        // disable TX-Interrupt
178
        UCSR0B &= ~(1 << TXCIE0);
179
 
180
        // set direction of RXD0 and TXD0 pins
181
        // set RXD0 (PD0) as an input pin
182
        PORTD |= (1 << PORTD0);
183
        DDRD &= ~(1 << DDD0);
184
        // set TXD0 (PD1) as an output pin
185
        PORTD |= (1 << PORTD1);
186
        DDRD |=  (1 << DDD1);
187
 
188
        // USART0 Baud Rate Register
189
        // set clock divider
190
        UBRR0H = (uint8_t)(ubrr >> 8);
191
        UBRR0L = (uint8_t)ubrr;
192
 
193
        // USART0 Control and Status Register A, B, C
194
 
195
        // enable double speed operation in
196
        UCSR0A |= (1 << U2X0);
197
        // enable receiver and transmitter in
198
        UCSR0B = (1 << TXEN0) | (1 << RXEN0);
199
        // set asynchronous mode
200
        UCSR0C &= ~(1 << UMSEL01);
201
        UCSR0C &= ~(1 << UMSEL00);
202
        // no parity
203
        UCSR0C &= ~(1 << UPM01);
204
        UCSR0C &= ~(1 << UPM00);
205
        // 1 stop bit
206
        UCSR0C &= ~(1 << USBS0);
207
        // 8-bit
208
        UCSR0B &= ~(1 << UCSZ02);
209
        UCSR0C |=  (1 << UCSZ01);
210
        UCSR0C |=  (1 << UCSZ00);
211
 
212
                // flush receive buffer
213
        while ( UCSR0A & (1<<RXC0) ) UDR0;
214
 
215
        // enable interrupts at the end
216
        // enable RX-Interrupt
217
        UCSR0B |= (1 << RXCIE0);
218
        // enable TX-Interrupt
219
        UCSR0B |= (1 << TXCIE0);
220
 
221
        // initialize the debug timer
222
        DebugData_Timer = SetDelay(DebugData_Interval);
223
 
224
        // unlock rxd_buffer
225
        rxd_buffer_locked = FALSE;
226
        pRxData = 0;
227
        RxDataLen = 0;
228
 
229
        // no bytes to send
230
        txd_complete = TRUE;
231
 
232
        #ifdef USE_MK3MAG
233
        Compass_Timer = SetDelay(220);
234
        #endif
235
 
236
        UART_VersionInfo.SWMajor = VERSION_MAJOR;
237
        UART_VersionInfo.SWMinor = VERSION_MINOR;
238
        UART_VersionInfo.SWPatch = VERSION_PATCH;
239
        UART_VersionInfo.ProtoMajor = VERSION_SERIAL_MAJOR;
240
        UART_VersionInfo.ProtoMinor = VERSION_SERIAL_MINOR;
241
 
242
        // restore global interrupt flags
243
    SREG = sreg;
244
}
245
 
246
/****************************************************************/
247
/*               USART0 transmitter ISR                         */
248
/****************************************************************/
249
ISR(USART0_TX_vect)
250
{
251
        static uint16_t ptr_txd_buffer = 0;
252
        uint8_t tmp_tx;
253
        if(!txd_complete) // transmission not completed
254
        {
255
                ptr_txd_buffer++;                    // die [0] wurde schon gesendet
256
                tmp_tx = txd_buffer[ptr_txd_buffer];
257
                // if terminating character or end of txd buffer was reached
258
                if((tmp_tx == '\r') || (ptr_txd_buffer == TXD_BUFFER_LEN))
259
                {
260
                        ptr_txd_buffer = 0; // reset txd pointer
261
                        txd_complete = 1; // stop transmission
262
                }
263
                UDR0 = tmp_tx; // send current byte will trigger this ISR again
264
        }
265
        // transmission completed
266
        else ptr_txd_buffer = 0;
267
}
268
 
269
/****************************************************************/
270
/*               USART0 receiver ISR                            */
271
/****************************************************************/
272
ISR(USART0_RX_vect)
273
{
274
        static uint16_t crc;
275
        static uint8_t ptr_rxd_buffer = 0;
276
        uint8_t crc1, crc2;
277
        uint8_t c;
278
 
279
        c = UDR0;  // catch the received byte
280
 
281
        #if (defined (USE_KILLAGREG) || defined (USE_MK3MAG))
282
        // If the cpu is not an Atmega644P the ublox module should be conneced to rxd of the 1st uart.
283
        if(CPUType != ATMEGA644P) ubx_parser(c);
284
        #endif
285
 
286
        if(rxd_buffer_locked) return; // if rxd buffer is locked immediately return
287
 
288
        // the rxd buffer is unlocked
289
        if((ptr_rxd_buffer == 0) && (c == '#')) // if rxd buffer is empty and syncronisation character is received
290
        {
291
                rxd_buffer[ptr_rxd_buffer++] = c; // copy 1st byte to buffer
292
                crc = c; // init crc
293
        }
294
        #if 0
295
        else if (ptr_rxd_buffer == 1) // handle address
296
        {
297
                rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
298
                crc += c; // update crc
299
        }
300
        #endif
301
        else if (ptr_rxd_buffer < RXD_BUFFER_LEN) // collect incomming bytes
302
        {
303
                if(c != '\r') // no termination character
304
                {
305
                        rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
306
                        crc += c; // update crc
307
                }
308
                else // termination character was received
309
                {
310
                        // the last 2 bytes are no subject for checksum calculation
311
                        // they are the checksum itself
312
                        crc -= rxd_buffer[ptr_rxd_buffer-2];
313
                        crc -= rxd_buffer[ptr_rxd_buffer-1];
314
                        // calculate checksum from transmitted data
315
                        crc %= 4096;
316
                        crc1 = '=' + crc / 64;
317
                        crc2 = '=' + crc % 64;
318
                        // compare checksum to transmitted checksum bytes
319
                        if((crc1 == rxd_buffer[ptr_rxd_buffer-2]) && (crc2 == rxd_buffer[ptr_rxd_buffer-1]))
320
                        {   // checksum valid
321
                                rxd_buffer[ptr_rxd_buffer] = '\r'; // set termination character
322
                                ReceivedBytes = ptr_rxd_buffer + 1;// store number of received bytes
323
                                rxd_buffer_locked = TRUE;          // lock the rxd buffer
324
                                // if 2nd byte is an 'R' enable watchdog that will result in an reset
325
                                if(rxd_buffer[2] == 'R') {wdt_enable(WDTO_250MS);} // Reset-Commando
326
                        }
327
                        else
328
                        {       // checksum invalid
329
                                rxd_buffer_locked = FALSE; // unlock rxd buffer
330
                        }
331
                        ptr_rxd_buffer = 0; // reset rxd buffer pointer
332
                }
333
        }
334
        else // rxd buffer overrun
335
        {
336
                ptr_rxd_buffer = 0; // reset rxd buffer
337
                rxd_buffer_locked = FALSE; // unlock rxd buffer
338
        }
339
 
340
}
341
 
342
 
343
// --------------------------------------------------------------------------
344
void AddCRC(uint16_t datalen)
345
{
346
        uint16_t tmpCRC = 0, i;
347
        for(i = 0; i < datalen; i++)
348
        {
349
                tmpCRC += txd_buffer[i];
350
        }
351
        tmpCRC %= 4096;
352
        txd_buffer[i++] = '=' + tmpCRC / 64;
353
        txd_buffer[i++] = '=' + tmpCRC % 64;
354
        txd_buffer[i++] = '\r';
355
        txd_complete = FALSE;
356
        UDR0 = txd_buffer[0]; // initiates the transmittion (continued in the TXD ISR)
357
}
358
 
359
 
360
 
361
// --------------------------------------------------------------------------
362
void SendOutData(uint8_t cmd, uint8_t addr, uint8_t numofbuffers, ...) // uint8_t *pdata, uint8_t len, ...
363
{
364
        va_list ap;
365
        uint16_t pt = 0;
366
        uint8_t a,b,c;
367
        uint8_t ptr = 0;
368
 
369
        uint8_t *pdata = 0;
370
        int len = 0;
371
 
372
        txd_buffer[pt++] = '#';                 // Start character
373
        txd_buffer[pt++] = 'a' + addr;  // Address (a=0; b=1,...)
374
        txd_buffer[pt++] = cmd;                 // Command
375
 
376
        va_start(ap, numofbuffers);
377
        if(numofbuffers)
378
        {
379
                pdata = va_arg(ap, uint8_t*);
380
                len = va_arg(ap, int);
381
                ptr = 0;
382
                numofbuffers--;
383
        }
384
 
385
        while(len)
386
        {
387
                if(len)
388
                {
389
                        a = pdata[ptr++];
390
                        len--;
391
                        if((!len) && numofbuffers)
392
                        {
393
                                pdata = va_arg(ap, uint8_t*);
394
                                len = va_arg(ap, int);
395
                                ptr = 0;
396
                                numofbuffers--;
397
                        }
398
                }
399
                else a = 0;
400
                if(len)
401
                {
402
                        b = pdata[ptr++];
403
                        len--;
404
                        if((!len) && numofbuffers)
405
                        {
406
                                pdata = va_arg(ap, uint8_t*);
407
                                len = va_arg(ap, int);
408
                                ptr = 0;
409
                                numofbuffers--;
410
                        }
411
                }
412
                else b = 0;
413
                if(len)
414
                {
415
                        c = pdata[ptr++];
416
                        len--;
417
                        if((!len) && numofbuffers)
418
                        {
419
                                pdata = va_arg(ap, uint8_t*);
420
                                len = va_arg(ap, int);
421
                                ptr = 0;
422
                                numofbuffers--;
423
                        }
424
                }
425
                else c = 0;
426
                txd_buffer[pt++] = '=' + (a >> 2);
427
                txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
428
                txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
429
                txd_buffer[pt++] = '=' + ( c & 0x3f);
430
        }
431
        va_end(ap);
432
        AddCRC(pt); // add checksum after data block and initates the transmission
433
}
434
 
435
 
436
// --------------------------------------------------------------------------
437
void Decode64(void)
438
{
439
        uint8_t a,b,c,d;
440
        uint8_t x,y,z;
441
        uint8_t ptrIn = 3;
442
        uint8_t ptrOut = 3;
443
        uint8_t len = ReceivedBytes - 6;
444
 
445
        while(len)
446
        {
447
                a = rxd_buffer[ptrIn++] - '=';
448
                b = rxd_buffer[ptrIn++] - '=';
449
                c = rxd_buffer[ptrIn++] - '=';
450
                d = rxd_buffer[ptrIn++] - '=';
451
                //if(ptrIn > ReceivedBytes - 3) break;
452
 
453
                x = (a << 2) | (b >> 4);
454
                y = ((b & 0x0f) << 4) | (c >> 2);
455
                z = ((c & 0x03) << 6) | d;
456
 
457
                if(len--) rxd_buffer[ptrOut++] = x; else break;
458
                if(len--) rxd_buffer[ptrOut++] = y; else break;
459
                if(len--) rxd_buffer[ptrOut++] = z; else break;
460
        }
461
        pRxData = &rxd_buffer[3];
462
        RxDataLen = ptrOut - 3;
463
}
464
 
465
 
466
// --------------------------------------------------------------------------
467
void USART0_ProcessRxData(void)
468
{
469
        // if data in the rxd buffer are not locked immediately return
470
        if(!rxd_buffer_locked) return;
471
 
472
        uint8_t tempchar1, tempchar2;
473
 
474
        Decode64(); // decode data block in rxd_buffer
475
 
476
        switch(rxd_buffer[1] - 'a')
477
        {
478
                case FC_ADDRESS:
479
 
480
                switch(rxd_buffer[2])
481
                {
482
                        #ifdef USE_MK3MAG
483
                        case 'K':// compass value
484
                                CompassHeading = ((Heading_t *)pRxData)->Heading;
485
                                CompassOffCourse = ((540 + CompassHeading - CompassCourse) % 360) - 180;
486
                                break;
487
                        #endif
488
 
489
                        case 't':// motor test
1222 killagreg 490
                                if(RxDataLen > 20) //
491
                                {
492
                                        memcpy(&MotorTest[0], (uint8_t*)pRxData, sizeof(MotorTest));
493
                                }
494
                                else
495
                                {
496
                                        memcpy(&MotorTest[0], (uint8_t*)pRxData, 4);
497
                                }
1180 killagreg 498
                                //Request_MotorTest = TRUE;
1222 killagreg 499
                                MotorTest_Active = 255;
1180 killagreg 500
                                PcAccess = 255;
501
                                break;
502
 
1222 killagreg 503
                        case 'n':// "Get Mixer Table
504
                                while(!txd_complete); // wait for previous frame to be sent
505
                                SendOutData('N', FC_ADDRESS, 1, (uint8_t *) &Mixer, sizeof(Mixer));
506
                                break;
507
 
508
                        case 'm':// "Set Mixer Table
509
                                if(pRxData[0] == EEMIXER_REVISION)
510
                                {
511
                                        memcpy(&Mixer, (uint8_t*)pRxData, sizeof(Mixer));
512
                                        MixerTable_WriteToEEProm();
513
                                        while(!txd_complete); // wait for previous frame to be sent
514
                                        tempchar1 = 1;
515
                                }
516
                                else
517
                                {
518
                                        tempchar1 = 0;
519
                                }
520
                                SendOutData('M', FC_ADDRESS,  1, &tempchar1, 1);
521
                                break;
522
 
1180 killagreg 523
                        case 'p': // get PPM channels
524
                                Request_PPMChannels = TRUE;
525
                                break;
526
 
527
                        case 'q':// request settings
528
                                if(pRxData[0] == 0xFF)
529
                                {
530
                                        pRxData[0] = GetParamByte(PID_ACTIVE_SET);
531
                                }
532
                                // limit settings range
533
                                if(pRxData[0] < 1) pRxData[0] = 1; // limit to 1
534
                                else if(pRxData[0] > 5) pRxData[0] = 5; // limit to 5
535
                                // load requested parameter set
536
                                ParamSet_ReadFromEEProm(pRxData[0]);
537
                                tempchar1 = pRxData[0];
1222 killagreg 538
                                tempchar2 = EEPARAM_REVISION;
1180 killagreg 539
                                while(!txd_complete); // wait for previous frame to be sent
540
                                SendOutData('Q', FC_ADDRESS,3, &tempchar1, sizeof(tempchar1), &tempchar2, sizeof(tempchar2), (uint8_t *) &ParamSet, sizeof(ParamSet));
541
                                break;
542
 
543
                        case 's': // save settings
544
                                if(!(MKFlags & MKFLAG_MOTOR_RUN)) // save settings only if motors ar off
545
                                {
1222 killagreg 546
                                        if((1 <= pRxData[0]) && (pRxData[0] <= 5) && (pRxData[1] == EEPARAM_REVISION)) // check for setting to be in range and version of settings
1180 killagreg 547
                                        {
548
                                                memcpy(&ParamSet, (uint8_t*)&pRxData[2], sizeof(ParamSet));
549
                                                ParamSet_WriteToEEProm(pRxData[0]);
550
                                                TurnOver180Nick = (int32_t) ParamSet.AngleTurnOverNick * 2500L;
551
                                                TurnOver180Roll = (int32_t) ParamSet.AngleTurnOverRoll * 2500L;
552
                                                tempchar1 = GetActiveParamSet();
553
                                                Beep(tempchar1);
554
                                        }
555
                                        else
556
                                        {
557
                                                tempchar1 = 0;  //indicate bad data
558
                                        }
559
                                        while(!txd_complete); // wait for previous frame to be sent
560
                                        SendOutData('S', FC_ADDRESS,1, &tempchar1, sizeof(tempchar1));
561
                                }
562
                                break;
563
 
564
                        default:
565
                                //unsupported command received
566
                                break;
567
                } // case FC_ADDRESS:
568
 
569
                default: // any Slave Address
570
 
571
                switch(rxd_buffer[2])
572
                {
573
                        case 'a':// request for labels of the analog debug outputs
574
                                Request_DebugLabel = pRxData[0];
575
                                if(Request_DebugLabel > 31) Request_DebugLabel = 31;
576
                                PcAccess = 255;
577
                                break;
578
 
579
                        case 'b': // submit extern control
580
                                memcpy(&ExternControl, (uint8_t*)pRxData, sizeof(ExternControl));
581
                                ConfirmFrame = ExternControl.Frame;
582
                                PcAccess = 255;
583
                                break;
584
 
585
                        case 'h':// request for display columns
586
                                PcAccess = 255;
587
                                RemoteKeys |= pRxData[0];
588
                                if(RemoteKeys) DisplayLine = 0;
589
                                Request_Display = TRUE;
590
                                break;
591
 
592
                        case 'l':// request for display columns
593
                                PcAccess = 255;
594
                                MenuItem = pRxData[0];
595
                                Request_Display1 = TRUE;
596
                                break;
597
 
598
                        case 'v': // request for version and board release
599
                                Request_VerInfo = TRUE;
600
                                break;
601
 
602
                        case 'g':// get external control data
603
                                Request_ExternalControl = TRUE;
604
                                break;
605
 
606
                        case 'd': // request for the debug data
607
                                DebugData_Interval = (uint16_t) pRxData[0] * 10;
608
                                if(DebugData_Interval > 0) Request_DebugData = TRUE;
609
                                break;
610
 
611
                        case 'c': // request for the 3D data
612
                                Data3D_Interval = (uint16_t) pRxData[0] * 10;
613
                                if(Data3D_Interval > 0) Request_Data3D = TRUE;
614
                                break;
615
 
616
                        default:
617
                                //unsupported command received
618
                                break;
619
                }
620
                break; // default:
621
        }
622
        // unlock the rxd buffer after processing
623
        pRxData = 0;
624
        RxDataLen = 0;
625
        rxd_buffer_locked = FALSE;
626
}
627
 
628
//############################################################################
629
//Routine für die Serielle Ausgabe
630
int16_t uart_putchar (int8_t c)
631
//############################################################################
632
{
633
        if (c == '\n')
634
                uart_putchar('\r');
635
        // wait until previous character was send
636
        loop_until_bit_is_set(UCSR0A, UDRE0);
637
        // send character
638
        UDR0 = c;
639
        return (0);
640
}
641
 
642
 
643
//---------------------------------------------------------------------------------------------
644
void USART0_TransmitTxData(void)
645
{
646
        if(!txd_complete) return;
647
 
648
        if(Request_VerInfo && txd_complete)
649
        {
650
                SendOutData('V', FC_ADDRESS, 1, (uint8_t *) &UART_VersionInfo, sizeof(UART_VersionInfo));
651
                Request_VerInfo = FALSE;
652
        }
653
        if(Request_Display && txd_complete)
654
        {
655
                LCD_PrintMenu();
656
                SendOutData('H', FC_ADDRESS, 2, &DisplayLine, sizeof(DisplayLine), &DisplayBuff[DisplayLine * 20], 20);
657
                DisplayLine++;
658
                if(DisplayLine >= 4) DisplayLine = 0;
659
                Request_Display = FALSE;
660
        }
661
        if(Request_Display1 && txd_complete)
662
        {
663
                LCD_PrintMenu();
664
                SendOutData('L', FC_ADDRESS, 3, &MenuItem, sizeof(MenuItem), &MaxMenuItem, sizeof(MaxMenuItem), DisplayBuff, sizeof(DisplayBuff));
665
                Request_Display1 = FALSE;
666
        }
667
        if(Request_DebugLabel != 0xFF) // Texte für die Analogdaten
668
        {
669
                SendOutData('A', FC_ADDRESS, 2, (uint8_t *) &Request_DebugLabel, sizeof(Request_DebugLabel), ANALOG_LABEL[Request_DebugLabel], 16);
670
                Request_DebugLabel = 0xFF;
671
        }
672
        if(ConfirmFrame && txd_complete)   // Datensatz ohne CRC bestätigen
673
        {
674
                SendOutData('B', FC_ADDRESS, 1, (uint8_t*)&ConfirmFrame, sizeof(ConfirmFrame));
675
                ConfirmFrame = 0;
676
        }
677
        if( ((DebugData_Interval && CheckDelay(DebugData_Timer)) || Request_DebugData) && txd_complete)
678
        {
679
                SendOutData('D', FC_ADDRESS, 1,(uint8_t *) &DebugOut, sizeof(DebugOut));
680
                DebugData_Timer = SetDelay(DebugData_Interval);
681
                Request_DebugData = FALSE;
682
    }
683
    if( ((Data3D_Interval && CheckDelay(Data3D_Timer)) || Request_Data3D) && txd_complete)
684
        {
685
                SendOutData('C', FC_ADDRESS, 1,(uint8_t *) &Data3D, sizeof(Data3D));
686
                Data3D.AngleNick = (int16_t)((10 * IntegralGyroNick) / GYRO_DEG_FACTOR); // convert to multiple of 0.1°
687
                Data3D.AngleRoll = (int16_t)((10 * IntegralGyroRoll) / GYRO_DEG_FACTOR); // convert to multiple of 0.1°
688
                Data3D.Heading   = (int16_t)((10 * YawGyroHeading)   / GYRO_DEG_FACTOR); // convert to multiple of 0.1°
689
                Data3D_Timer = SetDelay(Data3D_Interval);
690
                Request_Data3D = FALSE;
691
    }
692
        if(Request_ExternalControl && txd_complete)
693
        {
694
                SendOutData('G', FC_ADDRESS, 1,(uint8_t *) &ExternControl, sizeof(ExternControl));
695
                Request_ExternalControl = FALSE;
696
        }
697
 
698
        #ifdef USE_MK3MAG
699
    if((CheckDelay(Compass_Timer)) && txd_complete)
700
        {
1186 killagreg 701
                ToMk3Mag.Attitude[0] = (int16_t)((10 * IntegralGyroNick) / GYRO_DEG_FACTOR);  // approx. 0.1 deg
702
                ToMk3Mag.Attitude[1] = (int16_t)((10 * IntegralGyroRoll) / GYRO_DEG_FACTOR);  // approx. 0.1 deg
1180 killagreg 703
                ToMk3Mag.UserParam[0] = FCParam.UserParam1;
704
                ToMk3Mag.UserParam[1] = FCParam.UserParam2;
705
                ToMk3Mag.CalState = CompassCalState;
706
                SendOutData('w', MK3MAG_ADDRESS, 1,(uint8_t *) &ToMk3Mag,sizeof(ToMk3Mag));
707
                // the last state is 5 and should be send only once to avoid multiple flash writing
708
                if(CompassCalState > 4)  CompassCalState = 0;
709
                Compass_Timer = SetDelay(99);
710
        }
711
        #endif
1222 killagreg 712
 
1180 killagreg 713
        if(Request_MotorTest && txd_complete)
714
        {
715
                SendOutData('T', FC_ADDRESS, 0);
716
                Request_MotorTest = FALSE;
717
        }
718
        if(Request_PPMChannels && txd_complete)
719
        {
720
                SendOutData('P', FC_ADDRESS, 1, (uint8_t *)&PPM_in, sizeof(PPM_in));
721
                Request_PPMChannels = FALSE;
722
        }
723
}
724