Subversion Repositories FlightCtrl

Rev

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

Rev Author Line No. Line
1 ingob 1
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2
// + Copyright (c) 04.2007 Holger Buss
3
// + only for non-profit use
4
// + www.MikroKopter.com
5
// + see the File "License.txt" for further Informations
6
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7
 
687 killagreg 8
#include <avr/io.h>
9
#include <avr/interrupt.h>
10
#include <avr/wdt.h>
11
 
12
#include "eeprom.h"
1 ingob 13
#include "main.h"
685 killagreg 14
#include "menu.h"
15
#include "timer0.h"
1 ingob 16
#include "uart.h"
685 killagreg 17
#include "fc.h"
18
#include "_Settings.h"
19
#include "rc.h"
1 ingob 20
 
735 killagreg 21
#define FALSE   0
22
#define TRUE    1
685 killagreg 23
 
735 killagreg 24
uint8_t DebugGetAnforderung = 0, DebugDisplayAnforderung = 0, DebugDataAnforderung = 0, GetVersionAnforderung = 0;
683 killagreg 25
 
735 killagreg 26
volatile uint8_t txd_buffer[TXD_BUFFER_LEN];
27
volatile uint8_t rxd_buffer[RXD_BUFFER_LEN];
1 ingob 28
 
735 killagreg 29
volatile uint8_t RxDataProcessed = 0;
30
volatile uint8_t txd_complete = 1;
31
volatile uint8_t ReceivedBytes = 0;
32
 
33
uint8_t RemotePollDisplayLine = 0;
34
uint8_t NurKanalAnforderung = 0;
35
uint8_t DebugTextAnforderung = 255;
36
uint8_t PcAccess = 100;
37
uint8_t MotorTest[4] = {0,0,0,0};
38
uint8_t DubWiseKeys[4] = {0,0,0,0};
39
uint8_t MySlaveAddr;
40
uint8_t ConfirmFrame;
41
 
42
DebugOut_t              DebugOut;
43
ExternControl_t ExternControl;
44
VersionInfo_t   VersionInfo;
45
 
46
const uint8_t ANALOG_TEXT[32][16] =
499 hbuss 47
{
683 killagreg 48
   //1234567890123456
701 killagreg 49
    "IntegralPitch   ", //0
499 hbuss 50
    "IntegralRoll    ",
701 killagreg 51
    "AccPitch        ",
499 hbuss 52
    "AccRoll         ",
701 killagreg 53
    "GyroYaw         ",
54
    "ReadingHight    ", //5
499 hbuss 55
    "AccZ            ",
707 killagreg 56
    "Thrust          ",
701 killagreg 57
    "CompassHeading  ",
58
    "Voltage         ",
59
    "Receiver Level  ", //10
513 hbuss 60
    "Analog11        ",
701 killagreg 61
    "Motor_Front     ",
62
    "Motor_Rear      ",
63
    "Motor_Left      ",
64
    "Motor_Right     ", //15
513 hbuss 65
    "Acc_Z           ",
701 killagreg 66
    "MeanAccPitch    ",
67
    "MeanAccRoll     ",
68
    "IntegralErrPitch",
499 hbuss 69
    "IntegralErrRoll ", //20
701 killagreg 70
    "MeanIntPitch    ",
711 killagreg 71
    "MeanIntRoll         ",
701 killagreg 72
    "NeutralPitch    ",
513 hbuss 73
    "RollOffset      ",
701 killagreg 74
    "IntRoll*Factor  ", //25
712 killagreg 75
    "ReadingGyroPitch",
701 killagreg 76
    "DirectCorrRoll  ",
712 killagreg 77
    "ReadingGyroRoll ",
701 killagreg 78
    "CorrectionRoll  ",
79
    "I-AttRoll       ", //30
513 hbuss 80
    "StickRoll       "
499 hbuss 81
};
82
 
83
 
84
 
683 killagreg 85
/****************************************************************/
86
/*              Initialization of the USART0                    */
87
/****************************************************************/
88
void USART0_Init (void)
1 ingob 89
{
683 killagreg 90
        uint8_t sreg = SREG;
91
        uint16_t ubrr = (uint16_t) ((uint32_t) SYSCLK/(8 * USART0_BAUD) - 1);
92
 
93
        // disable all interrupts before configuration
94
        cli();
95
 
96
        // disable RX-Interrupt
97
        UCSR0B &= ~(1 << RXCIE0);
98
        // disable TX-Interrupt
99
        UCSR0B &= ~(1 << TXCIE0);
100
 
101
        // set direction of RXD0 and TXD0 pins
102
        // set RXD0 (PD0) as an input pin
103
        PORTD |= (1 << PORTD0);
104
        DDRD &= ~(1 << DDD0);
105
        // set TXD0 (PD1) as an output pin
106
        PORTD |= (1 << PORTD1);
107
        DDRD |=  (1 << DDD1);
108
 
109
        // USART0 Baud Rate Register
110
        // set clock divider
111
        UBRR0H = (uint8_t)(ubrr >> 8);
112
        UBRR0L = (uint8_t)ubrr;
113
 
114
        // USART0 Control and Status Register A, B, C
115
 
116
        // enable double speed operation in
117
        UCSR0A |= (1 << U2X0);
118
        // enable receiver and transmitter in
119
        UCSR0B = (1 << TXEN0) | (1 << RXEN0);
120
        // set asynchronous mode
121
        UCSR0C &= ~(1 << UMSEL01);
122
        UCSR0C &= ~(1 << UMSEL00);
123
        // no parity
124
        UCSR0C &= ~(1 << UPM01);
125
        UCSR0C &= ~(1 << UPM00);
126
        // 1 stop bit
127
        UCSR0C &= ~(1 << USBS0);
128
        // 8-bit
129
        UCSR0B &= ~(1 << UCSZ02);
130
        UCSR0C |=  (1 << UCSZ01);
131
        UCSR0C |=  (1 << UCSZ00);
132
 
133
                // flush receive buffer
134
        while ( UCSR0A & (1<<RXC0) ) UDR0;
135
 
136
        // enable interrupts at the end
137
        // enable RX-Interrupt
138
        UCSR0B |= (1 << RXCIE0);
139
        // enable TX-Interrupt
140
        UCSR0B |= (1 << TXCIE0);
141
 
142
        // restore global interrupt flags
143
    SREG = sreg;
144
}
145
 
146
/****************************************************************/
147
/*               USART0 transmitter ISR                         */
148
/****************************************************************/
149
ISR(USART0_TX_vect)
150
{
735 killagreg 151
        static uint16_t ptr_txd_buffer = 0;
152
        uint8_t tmp_tx;
153
        if(!txd_complete) // transmission not completed
154
        {
155
                ptr_txd_buffer++;                    // die [0] wurde schon gesendet
156
                tmp_tx = txd_buffer[ptr_txd_buffer];
157
                // if terminating character or end of txd buffer was reached
158
                if((tmp_tx == '\r') || (ptr_txd_buffer == TXD_BUFFER_LEN))
159
                {
160
                        ptr_txd_buffer = 0; // reset txd pointer
161
                        txd_complete = 1; // stop transmission
162
                }
163
                UDR0 = tmp_tx; // send current byte will trigger this ISR again
164
        }
165
        // transmission completed
166
        else ptr_txd_buffer = 0;
1 ingob 167
}
168
 
683 killagreg 169
/****************************************************************/
170
/*               USART0 receiver ISR                            */
171
/****************************************************************/
172
ISR(USART0_RX_vect)
1 ingob 173
{
735 killagreg 174
        static uint16_t crc;
175
        static uint8_t crc1, crc2, ptr_rxd_buffer = 0;
176
        static uint8_t UartState = 0;
177
        uint8_t CrcOkay = 0;
178
        uint8_t c;
1 ingob 179
 
735 killagreg 180
        c = UDR0; // catch the received byte
181
        if(ptr_rxd_buffer >= RXD_BUFFER_LEN) UartState = 0; // rxd buffer overflow -> reset rx uart state
182
        if(c == '\r' && UartState == 2) // termination character received during data collection state
183
        {
184
                UartState = 0; //reset rxd uart state
185
                // the last 2 bytes are no subject for checksum calculation
186
                // they are the checksum itself
187
                crc -= rxd_buffer[ptr_rxd_buffer-2];
188
                crc -= rxd_buffer[ptr_rxd_buffer-1];
189
                // calculate checksum from transmitted data
190
                crc %= 4096;
191
                crc1 = '=' + crc / 64;
192
                crc2 = '=' + crc % 64;
193
                CrcOkay = 0;
194
                // compare with transmitted checksum bytes
195
                if((crc1 == rxd_buffer[ptr_rxd_buffer-2]) && (crc2 == rxd_buffer[ptr_rxd_buffer-1])) CrcOkay = 1;
196
                else CrcOkay = 0;
197
 
198
                if(RxDataProcessed && CrcOkay) // data already processed and CRC OK?
199
                {
200
                        RxDataProcessed = FALSE;           // reset flag
201
                        ReceivedBytes = ptr_rxd_buffer;    // store number of received bytes
202
                        rxd_buffer[ptr_rxd_buffer] = '\r'; // set termination character
203
                        // if 2nd byte is an 'R' enable watchdog that will result in an reset
204
                        if(rxd_buffer[2] == 'R') wdt_enable(WDTO_250MS); // Reset-Commando
205
                }
683 killagreg 206
        }
735 killagreg 207
        else
208
        switch(UartState)
209
        {
210
                case 0: // reset rxd buffer
211
                        if(c == '#' && RxDataProcessed) UartState = 1;  // start character recieved and previous data already processed
212
                        ptr_rxd_buffer = 0; // reset buffer pointer
213
                        rxd_buffer[ptr_rxd_buffer++] = c; // write character to rxd buffer
214
                        crc = c; // initialize crc
215
                        break;
216
                case 1: // check address
217
                        UartState++; // switch to next state
218
                        rxd_buffer[ptr_rxd_buffer++] = c; // write character to rxd buffer
219
                        crc += c; // update crc
220
                        break;
221
                case 2: //  collect received data
222
                        rxd_buffer[ptr_rxd_buffer] = c; // write character to rxd buffer
223
                        // if buffer overflow -> reset buffer
224
                        if(ptr_rxd_buffer < RXD_BUFFER_LEN) ptr_rxd_buffer++;
225
                        else UartState = 0;
226
                        crc += c; // update checksum
227
                        break;
228
                default:
229
                        UartState = 0;
230
                        break;
231
        }
1 ingob 232
}
233
 
234
 
683 killagreg 235
 
1 ingob 236
// --------------------------------------------------------------------------
735 killagreg 237
void AddCRC(uint16_t datalen)
1 ingob 238
{
683 killagreg 239
 uint16_t tmpCRC = 0,i;
735 killagreg 240
 for(i = 0; i < datalen;i++)
1 ingob 241
  {
683 killagreg 242
   tmpCRC += txd_buffer[i];
1 ingob 243
  }
244
   tmpCRC %= 4096;
683 killagreg 245
   txd_buffer[i++] = '=' + tmpCRC / 64;
246
   txd_buffer[i++] = '=' + tmpCRC % 64;
247
   txd_buffer[i++] = '\r';
735 killagreg 248
  txd_complete = 0;
249
  UDR0 = txd_buffer[0]; // initiates the transmittion
1 ingob 250
}
251
 
252
 
253
 
254
// --------------------------------------------------------------------------
683 killagreg 255
void SendOutData(uint8_t cmd,uint8_t modul, uint8_t *snd, uint8_t len)
1 ingob 256
{
735 killagreg 257
        uint16_t pt = 0;
258
        uint8_t a,b,c;
259
        uint8_t ptr = 0;
1 ingob 260
 
735 killagreg 261
        txd_buffer[pt++] = '#';         // Start character
262
        txd_buffer[pt++] = modul;       // Address (a=0; b=1,...)
263
        txd_buffer[pt++] = cmd;         // Command
1 ingob 264
 
735 killagreg 265
        while(len)
266
        {
267
                if(len) { a = snd[ptr++]; len--;} else a = 0;
268
                if(len) { b = snd[ptr++]; len--;} else b = 0;
269
                if(len) { c = snd[ptr++]; len--;} else c = 0;
270
                txd_buffer[pt++] = '=' + (a >> 2);
271
                txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
272
                txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
273
                txd_buffer[pt++] = '=' + ( c & 0x3f);
274
        }
275
        AddCRC(pt); // add checksum after data block and initates the transmission
1 ingob 276
}
277
 
278
 
279
// --------------------------------------------------------------------------
683 killagreg 280
void Decode64(uint8_t *ptrOut, uint8_t len, uint8_t ptrIn, uint8_t max)  // Wohin mit den Daten; Wie lang; Wo im rxd_buffer
1 ingob 281
{
735 killagreg 282
        uint8_t a,b,c,d;
283
        uint8_t ptr = 0;
284
        uint8_t x,y,z;
285
        while(len)
286
        {
287
                a = rxd_buffer[ptrIn++] - '=';
288
                b = rxd_buffer[ptrIn++] - '=';
289
                c = rxd_buffer[ptrIn++] - '=';
290
                d = rxd_buffer[ptrIn++] - '=';
291
                if(ptrIn > max - 2) break;     // nicht mehr Daten verarbeiten, als empfangen wurden
1 ingob 292
 
735 killagreg 293
                x = (a << 2) | (b >> 4);
294
                y = ((b & 0x0f) << 4) | (c >> 2);
295
                z = ((c & 0x03) << 6) | d;
1 ingob 296
 
735 killagreg 297
                if(len--) ptrOut[ptr++] = x; else break;
298
                if(len--) ptrOut[ptr++] = y; else break;
299
                if(len--) ptrOut[ptr++] = z; else break;
300
        }
1 ingob 301
}
302
 
735 killagreg 303
 
1 ingob 304
// --------------------------------------------------------------------------
735 killagreg 305
void ProcessRxData(void)
1 ingob 306
{
735 killagreg 307
        // if data in the rxd buffer are alredy processed immediately return
308
        if(RxDataProcessed) return;
1 ingob 309
 
735 killagreg 310
        uint8_t tmp_char_arr2[2]; // local buffer
683 killagreg 311
 
735 killagreg 312
        PcAccess = 255;
313
        switch(rxd_buffer[2])
314
        {
315
                case 'a':// Labels of the Analog Deboug outputs
316
                        Decode64((uint8_t *) &tmp_char_arr2[0], sizeof(tmp_char_arr2), 3, ReceivedBytes);
317
                        DebugTextAnforderung = tmp_char_arr2[0];
499 hbuss 318
                        break;
735 killagreg 319
                case 'b': // extern control
320
                        Decode64((uint8_t *) &ExternControl,sizeof(ExternControl), 3, ReceivedBytes);
685 killagreg 321
                        RemoteButtons |= ExternControl.RemoteButtons;
735 killagreg 322
                        ConfirmFrame = ExternControl.Frame;
323
                        break;
324
                case 'c': // extern control with debug request
325
                        Decode64((uint8_t *) &ExternControl,sizeof(ExternControl),3,ReceivedBytes);
685 killagreg 326
                        RemoteButtons |= ExternControl.RemoteButtons;
735 killagreg 327
                        ConfirmFrame = ExternControl.Frame;
328
                        DebugDataAnforderung = 1;
329
                        break;
330
                case 'h':// x-1 display columns
331
                        Decode64((uint8_t *) &tmp_char_arr2[0],sizeof(tmp_char_arr2),3,ReceivedBytes);
332
                        RemoteButtons |= tmp_char_arr2[0];
333
                        if(tmp_char_arr2[1] == 255) NurKanalAnforderung = 1;
334
                        else NurKanalAnforderung = 0; // keine Displaydaten
1 ingob 335
                        DebugDisplayAnforderung = 1;
336
                        break;
735 killagreg 337
                case 't':// motor test
338
                        Decode64((uint8_t *) &MotorTest[0],sizeof(MotorTest),3,ReceivedBytes);
1 ingob 339
                        break;
735 killagreg 340
                case 'k':// keys from DubWise
341
                        Decode64((uint8_t *) &DubWiseKeys[0],sizeof(DubWiseKeys),3,ReceivedBytes);
595 hbuss 342
                        ConfirmFrame = DubWiseKeys[3];
492 hbuss 343
                        break;
735 killagreg 344
                case 'v': // get version and board release
345
                        GetVersionAnforderung = 1;
346
                        break;
347
                case 'g':// get debug data
348
                        DebugGetAnforderung = 1;
349
                        break;
350
                case 'q':// get settings
351
                        Decode64((uint8_t *) &tmp_char_arr2[0],sizeof(tmp_char_arr2),3,ReceivedBytes);
352
                        if(tmp_char_arr2[0] != 0xff)
353
                        {
354
                                if(tmp_char_arr2[0] > 5) tmp_char_arr2[0] = 5; // limit to 5
355
                                // load requested parameter set
356
                                ParamSet_ReadFromEEProm(tmp_char_arr2[0]);
357
                                SendOutData('L' + tmp_char_arr2[0] -1,MySlaveAddr,(uint8_t *) &ParamSet.ChannelAssignment[0],PARAMSET_STRUCT_LEN);
358
                        }
359
                        else // send active parameter set
360
                        SendOutData('L' + GetParamByte(PID_ACTIVE_SET)-1,MySlaveAddr,(uint8_t *) &ParamSet.ChannelAssignment[0],PARAMSET_STRUCT_LEN);
683 killagreg 361
 
735 killagreg 362
                        break;
683 killagreg 363
 
735 killagreg 364
                case 'l':
365
                case 'm':
366
                case 'n':
367
                case 'o':
368
                case 'p': // save parameterset
369
                        Decode64((uint8_t *) &ParamSet.ChannelAssignment[0],PARAMSET_STRUCT_LEN,3,ReceivedBytes);
687 killagreg 370
                        ParamSet_WriteToEEProm(rxd_buffer[2] - 'l' + 1);
735 killagreg 371
                        TurnOver180Pitch = (int32_t) ParamSet.AngleTurnOverPitch * 2500L;
372
                        TurnOver180Roll = (int32_t) ParamSet.AngleTurnOverRoll * 2500L;
373
                        Beep(GetActiveParamSet());
374
                        break;
683 killagreg 375
 
376
 
735 killagreg 377
        }
378
        RxDataProcessed = TRUE;
1 ingob 379
}
380
 
381
//############################################################################
382
//Routine für die Serielle Ausgabe
683 killagreg 383
int16_t uart_putchar (int8_t c)
1 ingob 384
//############################################################################
385
{
386
        if (c == '\n')
387
                uart_putchar('\r');
735 killagreg 388
        // wait until previous character was send
683 killagreg 389
        loop_until_bit_is_set(UCSR0A, UDRE0);
1 ingob 390
        //Ausgabe des Zeichens
683 killagreg 391
        UDR0 = c;
392
 
1 ingob 393
        return (0);
394
}
395
 
396
 
397
//---------------------------------------------------------------------------------------------
735 killagreg 398
void TransmitTxData(void)
1 ingob 399
{
735 killagreg 400
 static int16_t Debug_Timer = 0;
401
 if(!txd_complete) return;
1 ingob 402
 
735 killagreg 403
   if(DebugGetAnforderung && txd_complete)            // Bei Get werden die vom PC einstellbaren Werte vom PC zurückgelesen
683 killagreg 404
   {
735 killagreg 405
      SendOutData('G',MySlaveAddr,(uint8_t *) &ExternControl,sizeof(ExternControl));
1 ingob 406
          DebugGetAnforderung = 0;
407
   }
408
 
735 killagreg 409
    if((CheckDelay(Debug_Timer) || DebugDataAnforderung) && txd_complete)
1 ingob 410
         {
735 killagreg 411
          SendOutData('D',MySlaveAddr,(uint8_t *) &DebugOut,sizeof(DebugOut));
1 ingob 412
          DebugDataAnforderung = 0;
683 killagreg 413
          Debug_Timer = SetDelay(MIN_DEBUG_INTERVALL);
414
         }
499 hbuss 415
    if(DebugTextAnforderung != 255) // Texte für die Analogdaten
416
     {
683 killagreg 417
      SendOutData('A',DebugTextAnforderung + '0',(uint8_t *) ANALOG_TEXT[DebugTextAnforderung],16);
499 hbuss 418
      DebugTextAnforderung = 255;
419
         }
735 killagreg 420
     if(ConfirmFrame && txd_complete)   // Datensatz ohne CRC bestätigen
595 hbuss 421
         {
683 killagreg 422
      txd_buffer[0] = '#';
423
      txd_buffer[1] = ConfirmFrame;
424
      txd_buffer[2] = '\r';
735 killagreg 425
      txd_complete = 0;
595 hbuss 426
      ConfirmFrame = 0;
683 killagreg 427
      UDR0 = txd_buffer[0];
595 hbuss 428
     }
735 killagreg 429
     if(DebugDisplayAnforderung && txd_complete)
1 ingob 430
         {
685 killagreg 431
      LCD_PrintMenu();
1 ingob 432
          DebugDisplayAnforderung = 0;
683 killagreg 433
      if(++RemotePollDisplayLine == 4 || NurKanalAnforderung)
173 holgerb 434
      {
683 killagreg 435
       SendOutData('4',0,(uint8_t *)&PPM_in,sizeof(PPM_in));   // DisplayZeile übertragen
499 hbuss 436
       RemotePollDisplayLine = -1;
683 killagreg 437
      }
438
      else  SendOutData('0' + RemotePollDisplayLine,0,(uint8_t *)&DisplayBuff[20 * RemotePollDisplayLine],20);   // DisplayZeile übertragen
439
         }
735 killagreg 440
    if(GetVersionAnforderung && txd_complete)
683 killagreg 441
     {
735 killagreg 442
      SendOutData('V',MySlaveAddr,(uint8_t *) &VersionInfo,sizeof(VersionInfo));
1 ingob 443
          GetVersionAnforderung = 0;
444
     }
445
 
446
}
447