Subversion Repositories FlightCtrl

Rev

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

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