Subversion Repositories FlightCtrl

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1227 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 <avr/pgmspace.h>
55
#include <stdarg.h>
56
#include <string.h>
57
 
58
#include "eeprom.h"
59
#include "main.h"
60
#include "menu.h"
61
#include "timer0.h"
62
#include "uart0.h"
63
#include "fc.h"
64
#include "rc.h"
65
#if defined (USE_KILLAGREG) || defined (USE_MK3MAG)
66
#include "ubx.h"
67
#endif
68
#ifdef USE_MK3MAG
69
#include "mk3mag.h"
70
#endif
71
 
72
 
73
#define FC_ADDRESS 1
74
#define NC_ADDRESS 2
75
#define MK3MAG_ADDRESS 3
76
 
77
#define FALSE   0
78
#define TRUE    1
79
 
80
//int8_t test __attribute__ ((section (".noinit")));
81
uint8_t Request_VerInfo                 = FALSE;
82
uint8_t Request_ExternalControl = FALSE;
83
uint8_t Request_Display                 = FALSE;
84
uint8_t Request_Display1                = FALSE;
85
uint8_t Request_DebugData               = FALSE;
86
uint8_t Request_Data3D                  = FALSE;
87
uint8_t Request_DebugLabel              = 255;
88
uint8_t Request_PPMChannels     = FALSE;
89
uint8_t Request_MotorTest               = FALSE;
90
uint8_t DisplayLine = 0;
91
 
92
volatile uint8_t txd_buffer[TXD_BUFFER_LEN];
93
volatile uint8_t rxd_buffer_locked = FALSE;
94
volatile uint8_t rxd_buffer[RXD_BUFFER_LEN];
95
volatile uint8_t txd_complete = TRUE;
96
volatile uint8_t ReceivedBytes = 0;
97
volatile uint8_t *pRxData = 0;
98
volatile uint8_t RxDataLen = 0;
99
 
100
uint8_t PcAccess = 100;
101
 
102
uint8_t MotorTest_Active  = 0;
103
uint8_t MotorTest[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
104
uint8_t ConfirmFrame;
105
 
106
typedef struct
107
{
108
        int16_t Heading;
109
} __attribute__((packed)) Heading_t;
110
 
111
DebugOut_t              DebugOut;
112
Data3D_t                Data3D;
113
ExternControl_t ExternControl;
114
UART_VersionInfo_t      UART_VersionInfo;
115
 
116
uint16_t DebugData_Timer;
117
uint16_t Data3D_Timer;
118
uint16_t DebugData_Interval = 500; // in 1ms
119
uint16_t Data3D_Interval = 0; // in 1ms
120
 
121
#ifdef USE_MK3MAG
122
int16_t Compass_Timer;
123
#endif
124
 
125
// keep lables in flash to save 512 bytes of sram space
126
const prog_uint8_t ANALOG_LABEL[32][16] =
127
{
128
   //1234567890123456
129
    "AngleNick       ", //0
130
    "AngleRoll       ",
131
    "AccNick         ",
132
    "AccRoll         ",
133
    "YawGyro         ",
134
    "Height Value    ", //5
135
    "AccZ            ",
136
    "Gas             ",
137
    "Compass Heading ",
138
    "Voltage         ",
139
    "Receiver Level  ", //10
140
    "YawGyro Heading ",
141
    "Motor Front     ",
142
    "Motor Rear      ",
143
    "Motor Left      ",
144
    "Motor Right     ", //15
145
    "                ",
146
    "                ",
147
    "                ",
148
    "CompassCalState ",
149
    "NickServo       ", //20
150
    "                ",
151
    "                ",
152
    "                ",
153
    "                ",
154
    "                ", //25
155
    "                ",
156
    "Kalman Max Drift",
157
    "                ",
158
    "Navi Serial Data",
159
    "GPS Nick        ", //30
160
    "GPSS Roll       "
161
};
162
 
163
 
164
 
165
/****************************************************************/
166
/*              Initialization of the USART0                    */
167
/****************************************************************/
168
void USART0_Init (void)
169
{
170
        uint8_t sreg = SREG;
171
        uint16_t ubrr = (uint16_t) ((uint32_t) SYSCLK/(8 * USART0_BAUD) - 1);
172
 
173
        // disable all interrupts before configuration
174
        cli();
175
 
176
        // disable RX-Interrupt
177
        UCSR0B &= ~(1 << RXCIE0);
178
        // disable TX-Interrupt
179
        UCSR0B &= ~(1 << TXCIE0);
180
 
181
        // set direction of RXD0 and TXD0 pins
182
        // set RXD0 (PD0) as an input pin
183
        PORTD |= (1 << PORTD0);
184
        DDRD &= ~(1 << DDD0);
185
        // set TXD0 (PD1) as an output pin
186
        PORTD |= (1 << PORTD1);
187
        DDRD |=  (1 << DDD1);
188
 
189
        // USART0 Baud Rate Register
190
        // set clock divider
191
        UBRR0H = (uint8_t)(ubrr >> 8);
192
        UBRR0L = (uint8_t)ubrr;
193
 
194
        // USART0 Control and Status Register A, B, C
195
 
196
        // enable double speed operation in
197
        UCSR0A |= (1 << U2X0);
198
        // enable receiver and transmitter in
199
        UCSR0B = (1 << TXEN0) | (1 << RXEN0);
200
        // set asynchronous mode
201
        UCSR0C &= ~(1 << UMSEL01);
202
        UCSR0C &= ~(1 << UMSEL00);
203
        // no parity
204
        UCSR0C &= ~(1 << UPM01);
205
        UCSR0C &= ~(1 << UPM00);
206
        // 1 stop bit
207
        UCSR0C &= ~(1 << USBS0);
208
        // 8-bit
209
        UCSR0B &= ~(1 << UCSZ02);
210
        UCSR0C |=  (1 << UCSZ01);
211
        UCSR0C |=  (1 << UCSZ00);
212
 
213
                // flush receive buffer
214
        while ( UCSR0A & (1<<RXC0) ) UDR0;
215
 
216
        // enable interrupts at the end
217
        // enable RX-Interrupt
218
        UCSR0B |= (1 << RXCIE0);
219
        // enable TX-Interrupt
220
        UCSR0B |= (1 << TXCIE0);
221
 
222
        // initialize the debug timer
223
        DebugData_Timer = SetDelay(DebugData_Interval);
224
 
225
        // unlock rxd_buffer
226
        rxd_buffer_locked = FALSE;
227
        pRxData = 0;
228
        RxDataLen = 0;
229
 
230
        // no bytes to send
231
        txd_complete = TRUE;
232
 
233
        #ifdef USE_MK3MAG
234
        Compass_Timer = SetDelay(220);
235
        #endif
236
 
237
        UART_VersionInfo.SWMajor = VERSION_MAJOR;
238
        UART_VersionInfo.SWMinor = VERSION_MINOR;
239
        UART_VersionInfo.SWPatch = VERSION_PATCH;
240
        UART_VersionInfo.ProtoMajor = VERSION_SERIAL_MAJOR;
241
        UART_VersionInfo.ProtoMinor = VERSION_SERIAL_MINOR;
242
 
243
        // restore global interrupt flags
244
    SREG = sreg;
245
}
246
 
247
/****************************************************************/
248
/*               USART0 transmitter ISR                         */
249
/****************************************************************/
250
ISR(USART0_TX_vect)
251
{
252
        static uint16_t ptr_txd_buffer = 0;
253
        uint8_t tmp_tx;
254
        if(!txd_complete) // transmission not completed
255
        {
256
                ptr_txd_buffer++;                    // die [0] wurde schon gesendet
257
                tmp_tx = txd_buffer[ptr_txd_buffer];
258
                // if terminating character or end of txd buffer was reached
259
                if((tmp_tx == '\r') || (ptr_txd_buffer == TXD_BUFFER_LEN))
260
                {
261
                        ptr_txd_buffer = 0; // reset txd pointer
262
                        txd_complete = 1; // stop transmission
263
                }
264
                UDR0 = tmp_tx; // send current byte will trigger this ISR again
265
        }
266
        // transmission completed
267
        else ptr_txd_buffer = 0;
268
}
269
 
270
/****************************************************************/
271
/*               USART0 receiver ISR                            */
272
/****************************************************************/
273
ISR(USART0_RX_vect)
274
{
275
        static uint16_t crc;
276
        static uint8_t ptr_rxd_buffer = 0;
277
        uint8_t crc1, crc2;
278
        uint8_t c;
279
 
280
        c = UDR0;  // catch the received byte
281
 
282
        #if (defined (USE_KILLAGREG) || defined (USE_MK3MAG))
283
        // If the cpu is not an Atmega644P the ublox module should be conneced to rxd of the 1st uart.
284
        if(CPUType != ATMEGA644P) ubx_parser(c);
285
        #endif
286
 
287
        if(rxd_buffer_locked) return; // if rxd buffer is locked immediately return
288
 
289
        // the rxd buffer is unlocked
290
        if((ptr_rxd_buffer == 0) && (c == '#')) // if rxd buffer is empty and syncronisation character is received
291
        {
292
                rxd_buffer[ptr_rxd_buffer++] = c; // copy 1st byte to buffer
293
                crc = c; // init crc
294
        }
295
        #if 0
296
        else if (ptr_rxd_buffer == 1) // handle address
297
        {
298
                rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
299
                crc += c; // update crc
300
        }
301
        #endif
302
        else if (ptr_rxd_buffer < RXD_BUFFER_LEN) // collect incomming bytes
303
        {
304
                if(c != '\r') // no termination character
305
                {
306
                        rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
307
                        crc += c; // update crc
308
                }
309
                else // termination character was received
310
                {
311
                        // the last 2 bytes are no subject for checksum calculation
312
                        // they are the checksum itself
313
                        crc -= rxd_buffer[ptr_rxd_buffer-2];
314
                        crc -= rxd_buffer[ptr_rxd_buffer-1];
315
                        // calculate checksum from transmitted data
316
                        crc %= 4096;
317
                        crc1 = '=' + crc / 64;
318
                        crc2 = '=' + crc % 64;
319
                        // compare checksum to transmitted checksum bytes
320
                        if((crc1 == rxd_buffer[ptr_rxd_buffer-2]) && (crc2 == rxd_buffer[ptr_rxd_buffer-1]))
321
                        {   // checksum valid
322
                                rxd_buffer[ptr_rxd_buffer] = '\r'; // set termination character
323
                                ReceivedBytes = ptr_rxd_buffer + 1;// store number of received bytes
324
                                rxd_buffer_locked = TRUE;          // lock the rxd buffer
325
                                // if 2nd byte is an 'R' enable watchdog that will result in an reset
326
                                if(rxd_buffer[2] == 'R') {wdt_enable(WDTO_250MS);} // Reset-Commando
327
                        }
328
                        else
329
                        {       // checksum invalid
330
                                rxd_buffer_locked = FALSE; // unlock rxd buffer
331
                        }
332
                        ptr_rxd_buffer = 0; // reset rxd buffer pointer
333
                }
334
        }
335
        else // rxd buffer overrun
336
        {
337
                ptr_rxd_buffer = 0; // reset rxd buffer
338
                rxd_buffer_locked = FALSE; // unlock rxd buffer
339
        }
340
 
341
}
342
 
343
 
344
// --------------------------------------------------------------------------
345
void AddCRC(uint16_t datalen)
346
{
347
        uint16_t tmpCRC = 0, i;
348
        for(i = 0; i < datalen; i++)
349
        {
350
                tmpCRC += txd_buffer[i];
351
        }
352
        tmpCRC %= 4096;
353
        txd_buffer[i++] = '=' + tmpCRC / 64;
354
        txd_buffer[i++] = '=' + tmpCRC % 64;
355
        txd_buffer[i++] = '\r';
356
        txd_complete = FALSE;
357
        UDR0 = txd_buffer[0]; // initiates the transmittion (continued in the TXD ISR)
358
}
359
 
360
 
361
 
362
// --------------------------------------------------------------------------
363
void SendOutData(uint8_t cmd, uint8_t addr, uint8_t numofbuffers, ...) // uint8_t *pdata, uint8_t len, ...
364
{
365
        va_list ap;
366
        uint16_t pt = 0;
367
        uint8_t a,b,c;
368
        uint8_t ptr = 0;
369
 
370
        uint8_t *pdata = 0;
371
        int len = 0;
372
 
373
        txd_buffer[pt++] = '#';                 // Start character
374
        txd_buffer[pt++] = 'a' + addr;  // Address (a=0; b=1,...)
375
        txd_buffer[pt++] = cmd;                 // Command
376
 
377
        va_start(ap, numofbuffers);
378
        if(numofbuffers)
379
        {
380
                pdata = va_arg(ap, uint8_t*);
381
                len = va_arg(ap, int);
382
                ptr = 0;
383
                numofbuffers--;
384
        }
385
 
386
        while(len)
387
        {
388
                if(len)
389
                {
390
                        a = pdata[ptr++];
391
                        len--;
392
                        if((!len) && numofbuffers)
393
                        {
394
                                pdata = va_arg(ap, uint8_t*);
395
                                len = va_arg(ap, int);
396
                                ptr = 0;
397
                                numofbuffers--;
398
                        }
399
                }
400
                else a = 0;
401
                if(len)
402
                {
403
                        b = pdata[ptr++];
404
                        len--;
405
                        if((!len) && numofbuffers)
406
                        {
407
                                pdata = va_arg(ap, uint8_t*);
408
                                len = va_arg(ap, int);
409
                                ptr = 0;
410
                                numofbuffers--;
411
                        }
412
                }
413
                else b = 0;
414
                if(len)
415
                {
416
                        c = pdata[ptr++];
417
                        len--;
418
                        if((!len) && numofbuffers)
419
                        {
420
                                pdata = va_arg(ap, uint8_t*);
421
                                len = va_arg(ap, int);
422
                                ptr = 0;
423
                                numofbuffers--;
424
                        }
425
                }
426
                else c = 0;
427
                txd_buffer[pt++] = '=' + (a >> 2);
428
                txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
429
                txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
430
                txd_buffer[pt++] = '=' + ( c & 0x3f);
431
        }
432
        va_end(ap);
433
        AddCRC(pt); // add checksum after data block and initates the transmission
434
}
435
 
436
 
437
// --------------------------------------------------------------------------
438
void Decode64(void)
439
{
440
        uint8_t a,b,c,d;
441
        uint8_t x,y,z;
442
        uint8_t ptrIn = 3;
443
        uint8_t ptrOut = 3;
444
        uint8_t len = ReceivedBytes - 6;
445
 
446
        while(len)
447
        {
448
                a = rxd_buffer[ptrIn++] - '=';
449
                b = rxd_buffer[ptrIn++] - '=';
450
                c = rxd_buffer[ptrIn++] - '=';
451
                d = rxd_buffer[ptrIn++] - '=';
452
                //if(ptrIn > ReceivedBytes - 3) break;
453
 
454
                x = (a << 2) | (b >> 4);
455
                y = ((b & 0x0f) << 4) | (c >> 2);
456
                z = ((c & 0x03) << 6) | d;
457
 
458
                if(len--) rxd_buffer[ptrOut++] = x; else break;
459
                if(len--) rxd_buffer[ptrOut++] = y; else break;
460
                if(len--) rxd_buffer[ptrOut++] = z; else break;
461
        }
462
        pRxData = &rxd_buffer[3];
463
        RxDataLen = ptrOut - 3;
464
}
465
 
466
 
467
// --------------------------------------------------------------------------
468
void USART0_ProcessRxData(void)
469
{
470
        // if data in the rxd buffer are not locked immediately return
471
        if(!rxd_buffer_locked) return;
472
 
473
        uint8_t tempchar1, tempchar2;
474
 
475
        Decode64(); // decode data block in rxd_buffer
476
 
477
        switch(rxd_buffer[1] - 'a')
478
        {
479
                case FC_ADDRESS:
480
 
481
                switch(rxd_buffer[2])
482
                {
483
                        #ifdef USE_MK3MAG
484
                        case 'K':// compass value
485
                                CompassHeading = ((Heading_t *)pRxData)->Heading;
486
                                CompassOffCourse = ((540 + CompassHeading - CompassCourse) % 360) - 180;
487
                                break;
488
                        #endif
489
 
490
                        case 't':// motor test
491
                                if(RxDataLen > 20) //
492
                                {
493
                                        memcpy(&MotorTest[0], (uint8_t*)pRxData, sizeof(MotorTest));
494
                                }
495
                                else
496
                                {
497
                                        memcpy(&MotorTest[0], (uint8_t*)pRxData, 4);
498
                                }
499
                                //Request_MotorTest = TRUE;
500
                                MotorTest_Active = 255;
501
                                PcAccess = 255;
502
                                break;
503
 
504
                        case 'n':// "Get Mixer Table
505
                                while(!txd_complete); // wait for previous frame to be sent
506
                                SendOutData('N', FC_ADDRESS, 1, (uint8_t *) &Mixer, sizeof(Mixer));
507
                                break;
508
 
509
                        case 'm':// "Set Mixer Table
510
                                if(pRxData[0] == EEMIXER_REVISION)
511
                                {
512
                                        memcpy(&Mixer, (uint8_t*)pRxData, sizeof(Mixer));
513
                                        MixerTable_WriteToEEProm();
514
                                        while(!txd_complete); // wait for previous frame to be sent
515
                                        tempchar1 = 1;
516
                                }
517
                                else
518
                                {
519
                                        tempchar1 = 0;
520
                                }
521
                                SendOutData('M', FC_ADDRESS,  1, &tempchar1, 1);
522
                                break;
523
 
524
                        case 'p': // get PPM channels
525
                                Request_PPMChannels = TRUE;
526
                                break;
527
 
528
                        case 'q':// request settings
529
                                if(pRxData[0] == 0xFF)
530
                                {
531
                                        pRxData[0] = GetParamByte(PID_ACTIVE_SET);
532
                                }
533
                                // limit settings range
534
                                if(pRxData[0] < 1) pRxData[0] = 1; // limit to 1
535
                                else if(pRxData[0] > 5) pRxData[0] = 5; // limit to 5
536
                                // load requested parameter set
537
                                ParamSet_ReadFromEEProm(pRxData[0]);
538
                                tempchar1 = pRxData[0];
539
                                tempchar2 = EEPARAM_REVISION;
540
                                while(!txd_complete); // wait for previous frame to be sent
541
                                SendOutData('Q', FC_ADDRESS,3, &tempchar1, sizeof(tempchar1), &tempchar2, sizeof(tempchar2), (uint8_t *) &ParamSet, sizeof(ParamSet));
542
                                break;
543
 
544
                        case 's': // save settings
545
                                if(!(MKFlags & MKFLAG_MOTOR_RUN)) // save settings only if motors ar off
546
                                {
547
                                        if((1 <= pRxData[0]) && (pRxData[0] <= 5) && (pRxData[1] == EEPARAM_REVISION)) // check for setting to be in range and version of settings
548
                                        {
549
                                                memcpy(&ParamSet, (uint8_t*)&pRxData[2], sizeof(ParamSet));
550
                                                ParamSet_WriteToEEProm(pRxData[0]);
551
                                                TurnOver180Nick = (int32_t) ParamSet.AngleTurnOverNick * 2500L;
552
                                                TurnOver180Roll = (int32_t) ParamSet.AngleTurnOverRoll * 2500L;
553
                                                tempchar1 = GetActiveParamSet();
554
                                                Beep(tempchar1);
555
                                        }
556
                                        else
557
                                        {
558
                                                tempchar1 = 0;  //indicate bad data
559
                                        }
560
                                        while(!txd_complete); // wait for previous frame to be sent
561
                                        SendOutData('S', FC_ADDRESS,1, &tempchar1, sizeof(tempchar1));
562
                                }
563
                                break;
564
 
565
                        default:
566
                                //unsupported command received
567
                                break;
568
                } // case FC_ADDRESS:
569
 
570
                default: // any Slave Address
571
 
572
                switch(rxd_buffer[2])
573
                {
574
                        case 'a':// request for labels of the analog debug outputs
575
                                Request_DebugLabel = pRxData[0];
576
                                if(Request_DebugLabel > 31) Request_DebugLabel = 31;
577
                                PcAccess = 255;
578
                                break;
579
 
580
                        case 'b': // submit extern control
581
                                memcpy(&ExternControl, (uint8_t*)pRxData, sizeof(ExternControl));
582
                                ConfirmFrame = ExternControl.Frame;
583
                                PcAccess = 255;
584
                                break;
585
 
586
                        case 'h':// request for display columns
587
                                PcAccess = 255;
588
                                RemoteKeys |= pRxData[0];
589
                                if(RemoteKeys) DisplayLine = 0;
590
                                Request_Display = TRUE;
591
                                break;
592
 
593
                        case 'l':// request for display columns
594
                                PcAccess = 255;
595
                                MenuItem = pRxData[0];
596
                                Request_Display1 = TRUE;
597
                                break;
598
 
599
                        case 'v': // request for version and board release
600
                                Request_VerInfo = TRUE;
601
                                break;
602
 
603
                        case 'g':// get external control data
604
                                Request_ExternalControl = TRUE;
605
                                break;
606
 
607
                        case 'd': // request for the debug data
608
                                DebugData_Interval = (uint16_t) pRxData[0] * 10;
609
                                if(DebugData_Interval > 0) Request_DebugData = TRUE;
610
                                break;
611
 
612
                        case 'c': // request for the 3D data
613
                                Data3D_Interval = (uint16_t) pRxData[0] * 10;
614
                                if(Data3D_Interval > 0) Request_Data3D = TRUE;
615
                                break;
616
 
617
                        default:
618
                                //unsupported command received
619
                                break;
620
                }
621
                break; // default:
622
        }
623
        // unlock the rxd buffer after processing
624
        pRxData = 0;
625
        RxDataLen = 0;
626
        rxd_buffer_locked = FALSE;
627
}
628
 
629
//############################################################################
630
//Routine für die Serielle Ausgabe
631
int16_t uart_putchar (int8_t c)
632
//############################################################################
633
{
634
        if (c == '\n')
635
                uart_putchar('\r');
636
        // wait until previous character was send
637
        loop_until_bit_is_set(UCSR0A, UDRE0);
638
        // send character
639
        UDR0 = c;
640
        return (0);
641
}
642
 
643
 
644
//---------------------------------------------------------------------------------------------
645
void USART0_TransmitTxData(void)
646
{
647
        if(!txd_complete) return;
648
 
649
        if(Request_VerInfo && txd_complete)
650
        {
651
                SendOutData('V', FC_ADDRESS, 1, (uint8_t *) &UART_VersionInfo, sizeof(UART_VersionInfo));
652
                Request_VerInfo = FALSE;
653
        }
654
        if(Request_Display && txd_complete)
655
        {
656
                LCD_PrintMenu();
657
                SendOutData('H', FC_ADDRESS, 2, &DisplayLine, sizeof(DisplayLine), &DisplayBuff[DisplayLine * 20], 20);
658
                DisplayLine++;
659
                if(DisplayLine >= 4) DisplayLine = 0;
660
                Request_Display = FALSE;
661
        }
662
        if(Request_Display1 && txd_complete)
663
        {
664
                LCD_PrintMenu();
665
                SendOutData('L', FC_ADDRESS, 3, &MenuItem, sizeof(MenuItem), &MaxMenuItem, sizeof(MaxMenuItem), DisplayBuff, sizeof(DisplayBuff));
666
                Request_Display1 = FALSE;
667
        }
668
        if(Request_DebugLabel != 0xFF) // Texte für die Analogdaten
669
        {
670
                uint8_t label[16]; // local sram buffer
671
                memcpy_P(label, ANALOG_LABEL[Request_DebugLabel], 16); // read lable from flash to sram buffer
672
                SendOutData('A', FC_ADDRESS, 2, (uint8_t *) &Request_DebugLabel, sizeof(Request_DebugLabel), label, 16);
673
                Request_DebugLabel = 0xFF;
674
        }
675
        if(ConfirmFrame && txd_complete)   // Datensatz ohne CRC bestätigen
676
        {
677
                SendOutData('B', FC_ADDRESS, 1, (uint8_t*)&ConfirmFrame, sizeof(ConfirmFrame));
678
                ConfirmFrame = 0;
679
        }
680
        if( ((DebugData_Interval && CheckDelay(DebugData_Timer)) || Request_DebugData) && txd_complete)
681
        {
682
                SendOutData('D', FC_ADDRESS, 1,(uint8_t *) &DebugOut, sizeof(DebugOut));
683
                DebugData_Timer = SetDelay(DebugData_Interval);
684
                Request_DebugData = FALSE;
685
    }
686
    if( ((Data3D_Interval && CheckDelay(Data3D_Timer)) || Request_Data3D) && txd_complete)
687
        {
688
                SendOutData('C', FC_ADDRESS, 1,(uint8_t *) &Data3D, sizeof(Data3D));
689
                Data3D.AngleNick = (int16_t)((10 * IntegralGyroNick) / GYRO_DEG_FACTOR); // convert to multiple of 0.1°
690
                Data3D.AngleRoll = (int16_t)((10 * IntegralGyroRoll) / GYRO_DEG_FACTOR); // convert to multiple of 0.1°
691
                Data3D.Heading   = (int16_t)((10 * YawGyroHeading)   / GYRO_DEG_FACTOR); // convert to multiple of 0.1°
692
                Data3D_Timer = SetDelay(Data3D_Interval);
693
                Request_Data3D = FALSE;
694
    }
695
        if(Request_ExternalControl && txd_complete)
696
        {
697
                SendOutData('G', FC_ADDRESS, 1,(uint8_t *) &ExternControl, sizeof(ExternControl));
698
                Request_ExternalControl = FALSE;
699
        }
700
 
701
        #ifdef USE_MK3MAG
702
    if((CheckDelay(Compass_Timer)) && txd_complete)
703
        {
704
                ToMk3Mag.Attitude[0] = (int16_t)((10 * IntegralGyroNick) / GYRO_DEG_FACTOR);  // approx. 0.1 deg
705
                ToMk3Mag.Attitude[1] = (int16_t)((10 * IntegralGyroRoll) / GYRO_DEG_FACTOR);  // approx. 0.1 deg
706
                ToMk3Mag.UserParam[0] = FCParam.UserParam1;
707
                ToMk3Mag.UserParam[1] = FCParam.UserParam2;
708
                ToMk3Mag.CalState = CompassCalState;
709
                SendOutData('w', MK3MAG_ADDRESS, 1,(uint8_t *) &ToMk3Mag,sizeof(ToMk3Mag));
710
                // the last state is 5 and should be send only once to avoid multiple flash writing
711
                if(CompassCalState > 4)  CompassCalState = 0;
712
                Compass_Timer = SetDelay(99);
713
        }
714
        #endif
715
 
716
        if(Request_MotorTest && txd_complete)
717
        {
718
                SendOutData('T', FC_ADDRESS, 0);
719
                Request_MotorTest = FALSE;
720
        }
721
        if(Request_PPMChannels && txd_complete)
722
        {
723
                SendOutData('P', FC_ADDRESS, 1, (uint8_t *)&PPM_in, sizeof(PPM_in));
724
                Request_PPMChannels = FALSE;
725
        }
726
}
727