Subversion Repositories FlightCtrl

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1612 dongfang 1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <string.h>
4
#include <stdlib.h>
5
#include "spi.h"
6
#include "rc.h"
7
#include "eeprom.h"
8
#include "timer0.h"
9
#include "analog.h"
10
#include "attitude.h"
11
#include "flight.h"
12
 
13
//-----------------------------------------
14
 
15
// for compatibility reasons gcc3.x <-> gcc4.x
2035 - 16
// dongfang: Lets try to abandon GCC3.
17
/*
1612 dongfang 18
#ifndef SPCR
19
#define SPCR   SPCR0
20
#endif
21
#ifndef SPIE
22
#define SPIE   SPIE0
23
#endif
24
#ifndef SPE
25
#define SPE    SPE0
26
#endif
27
#ifndef DORD
28
#define DORD   DORD0
29
#endif
30
#ifndef MSTR
31
#define MSTR   MSTR0
32
#endif
33
#ifndef CPOL
34
#define CPOL   CPOL0
35
#endif
36
#ifndef CPHA
37
#define CPHA   CPHA0
38
#endif
39
#ifndef SPR1
40
#define SPR1   SPR01
41
#endif
42
#ifndef SPR0
43
#define SPR0   SPR00
44
#endif
45
 
46
#ifndef SPDR
47
#define SPDR   SPDR0
48
#endif
49
 
50
#ifndef SPSR
51
#define SPSR   SPSR0
52
#endif
53
#ifndef SPIF
54
#define SPIF   SPIF0
55
#endif
56
#ifndef WCOL
57
#define WCOL   WCOL0
58
#endif
1775 - 59
#ifndef SPI2X
1612 dongfang 60
#define SPI2X  SPI2X0
1775 - 61
#endif
2035 - 62
*/
1612 dongfang 63
// -------------------------
2035 - 64
#define DDR_SPI DDRB
65
#define DD_SS   PB4
66
#define DD_SCK  PB7
67
#define DD_MOSI PB5
68
#define DD_MISO PB6
1612 dongfang 69
 
70
#define SLAVE_SELECT_DDR_PORT   DDRC
71
#define SLAVE_SELECT_PORT       PORTC
72
#define SPI_SLAVE_SELECT        PC5
73
 
74
#define SPI_TXSYNCBYTE1 0xAA
75
#define SPI_TXSYNCBYTE2 0x83
76
#define SPI_RXSYNCBYTE1 0x81
77
#define SPI_RXSYNCBYTE2 0x55
78
 
1775 - 79
typedef enum {
1821 - 80
        SPI_SYNC1, SPI_SYNC2, SPI_DATA
1775 - 81
} SPI_RXState_t;
1612 dongfang 82
 
83
// data exchange packets to and From NaviCtrl
1821 - 84
ToNaviCtrl_t toNaviCtrl;
85
FromNaviCtrl_t fromNaviCtrl;
86
SPI_VersionInfo_t SPI_VersionInfo;
1612 dongfang 87
 
88
// rx packet buffer
1775 - 89
#define SPI_RXBUFFER_LEN sizeof(fromNaviCtrl)
1612 dongfang 90
uint8_t SPI_RxBuffer[SPI_RXBUFFER_LEN];
1821 - 91
uint8_t SPI_RxBufferIndex = 0;
1612 dongfang 92
uint8_t SPI_RxBuffer_Request = 0;
93
 
94
// tx packet buffer
1775 - 95
#define SPI_TXBUFFER_LEN sizeof(toNaviCtrl)
1612 dongfang 96
uint8_t *SPI_TxBuffer;
1821 - 97
uint8_t SPI_TxBufferIndex = 0;
1612 dongfang 98
 
99
uint8_t SPITransferCompleted, SPI_ChkSum;
100
uint8_t SPI_RxDataValid = 0;
101
uint8_t NCDataOkay = 0;
102
uint8_t NCSerialDataOkay = 0;
103
 
1821 - 104
uint8_t SPI_CommandSequence[] = { SPI_CMD_USER, SPI_CMD_STICK,
105
                SPI_CMD_PARAMETER1, SPI_CMD_STICK, SPI_CMD_MISC, SPI_CMD_VERSION };
1612 dongfang 106
uint8_t SPI_CommandCounter = 0;
107
 
108
/*********************************************/
109
/*  Initialize SPI interface to NaviCtrl     */
110
/*********************************************/
111
void SPI_MasterInit(void) {
1821 - 112
        DDR_SPI |= (1 << DD_MOSI) | (1 << DD_SCK); // Set MOSI and SCK output, all others input
113
        SLAVE_SELECT_DDR_PORT |= (1 << SPI_SLAVE_SELECT); // set Slave select port as output port
114
 
115
        SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (0 << SPR0) | (0 << SPIE); // Enable SPI, Master, set clock rate fck/64
116
        SPSR = 0;//(1<<SPI2X);
117
 
118
        SLAVE_SELECT_PORT |= (1 << SPI_SLAVE_SELECT); // Deselect Slave
119
 
120
        SPI_TxBuffer = (uint8_t *) &toNaviCtrl; // set pointer to tx-buffer
121
        SPITransferCompleted = 1;
122
        // initialize data packet to NaviControl
2035 - 123
        toNaviCtrl.sync1 = SPI_TXSYNCBYTE1;
124
        toNaviCtrl.sync2 = SPI_TXSYNCBYTE2;
1821 - 125
 
2035 - 126
        toNaviCtrl.command = SPI_CMD_USER;
127
        toNaviCtrl.integralPitch = 0;
128
        toNaviCtrl.integralRoll = 0;
129
        naviCtrlData.serialDataOkay = 0;
130
        //NCSerialDataOkay = 0;
131
        //NCDataOkay = 0;
1821 - 132
 
133
        SPI_RxDataValid = 0;
134
 
2035 - 135
        //SPI_VersionInfo.Major = VERSION_MAJOR;
136
        //SPI_VersionInfo.Minor = VERSION_MINOR;
137
        //SPI_VersionInfo.Patch = VERSION_PATCH;
138
        //SPI_VersionInfo.Compatible = NC_SPI_COMPATIBLE;
1612 dongfang 139
}
140
 
141
/**********************************************************/
2035 - 142
/*  Update Data transfered by the SPI from/to NaviCtrl     */
1612 dongfang 143
/**********************************************************/
2035 - 144
void updateSPI_Buffer(void) {
1821 - 145
        uint8_t i;
146
        int16_t tmp;
147
        cli();
148
        // stop all interrupts to avoid writing of new data during update of that packet.
1775 - 149
 
1821 - 150
        // update content of packet to NaviCtrl
2035 - 151
        // Scaling?
152
        toNaviCtrl.integralPitch = (angle[PITCH] / (GYRO_DEG_FACTOR_PITCHROLL/10)); // convert to multiple of 0.1�
153
        // Scaling?
154
        toNaviCtrl.integralRoll =  (angle[ROLL]   / (GYRO_DEG_FACTOR_PITCHROLL/10)); // convert to multiple of 0.1�
155
        // Scaling?
156
        toNaviCtrl.gyroHeading =   (yawGyroHeading / (GYRO_DEG_FACTOR_YAW / 10));     // convert to multiple of 0.1�
157
        // Scaling?
158
        toNaviCtrl.gyroPitch = rate_ATT[PITCH];
159
        // Scaling?
160
        toNaviCtrl.gyroRoll = rate_ATT[ROLL];
161
        // Scaling?
162
        toNaviCtrl.gyroYaw = yawRate;
163
        // Scaling?
164
        toNaviCtrl.accPitch = getAngleEstimateFromAcc(PITCH) / (GYRO_DEG_FACTOR_PITCHROLL/10); // convert to multiple of 0.1�
165
        // Scaling?
166
        toNaviCtrl.AccRoll =  getAngleEstimateFromAcc(ROLL)  / (GYRO_DEG_FACTOR_PITCHROLL/10);
1612 dongfang 167
 
1821 - 168
        // TODO: What are these little bastards?
169
 
170
        averageAcc[PITCH] = averageAcc[ROLL] = averageAccCount = 0;
171
 
2035 - 172
        switch (toNaviCtrl.command) {
1821 - 173
        case SPI_CMD_USER:
2035 - 174
                for (i = 0; i < sizeof(dynamicParams.userParams); i++) {
175
                        toNaviCtrl.param.asByte[i] = dynamicParams.userParams[i];
1821 - 176
                }
177
                toNaviCtrl.Param.Byte[8] = MKFlags;
178
                MKFlags &= ~(MKFLAG_CALIBRATE | MKFLAG_START); // calibrate and start are temporal states that are cleared immediately after transmitting
2035 - 179
                toNaviCtrl.Param.Byte[9]  = getActiveParamSet();
180
                toNaviCtrl.Param.Byte[10] = 10; //EE_Parameter.ComingHomeAltitude;
181
                toNaviCtrl.Param.Byte[11] = 0;  //FC_StatusFlags2;
1821 - 182
                break;
183
 
184
        case SPI_CMD_PARAMETER1:
185
                toNaviCtrl.Param.Byte[0] = staticParams.NaviGpsModeControl; // Parameters for the Naviboard
186
                toNaviCtrl.Param.Byte[1] = staticParams.NaviGpsGain;
187
                toNaviCtrl.Param.Byte[2] = staticParams.NaviGpsP;
188
                toNaviCtrl.Param.Byte[3] = staticParams.NaviGpsI;
189
                toNaviCtrl.Param.Byte[4] = staticParams.NaviGpsD;
190
                toNaviCtrl.Param.Byte[5] = staticParams.NaviGpsACC;
191
                toNaviCtrl.Param.Byte[6] = staticParams.NaviGpsMinSat;
192
                toNaviCtrl.Param.Byte[7] = staticParams.NaviStickThreshold;
193
                toNaviCtrl.Param.Byte[8] = staticParams.NaviOperatingRadius;
194
                toNaviCtrl.Param.Byte[9] = staticParams.NaviWindCorrection;
195
                toNaviCtrl.Param.Byte[10] = staticParams.NaviSpeedCompensation;
196
                toNaviCtrl.Param.Byte[11] = staticParams.NaviAngleLimitation;
197
                break;
198
 
199
        case SPI_CMD_STICK:
200
                tmp = PPM_in[staticParams.ChannelAssignment[CH_THROTTLE]];
201
                if (tmp > 127)
202
                        tmp = 127;
203
                else if (tmp < -128)
204
                        tmp = -128;
205
                toNaviCtrl.Param.Byte[0] = (int8_t) tmp;
206
                tmp = PPM_in[staticParams.ChannelAssignment[CH_YAW]];
207
                if (tmp > 127)
208
                        tmp = 127;
209
                else if (tmp < -128)
210
                        tmp = -128;
211
                toNaviCtrl.Param.Byte[1] = (int8_t) tmp;
212
                tmp = PPM_in[staticParams.ChannelAssignment[CH_ROLL]];
213
                if (tmp > 127)
214
                        tmp = 127;
215
                else if (tmp < -128)
216
                        tmp = -128;
217
                toNaviCtrl.Param.Byte[2] = (int8_t) tmp;
218
                tmp = PPM_in[staticParams.ChannelAssignment[CH_PITCH]];
219
                if (tmp > 127)
220
                        tmp = 127;
221
                else if (tmp < -128)
222
                        tmp = -128;
223
                toNaviCtrl.Param.Byte[3] = (int8_t) tmp;
224
                toNaviCtrl.Param.Byte[4] = (uint8_t) variables[0];
225
                toNaviCtrl.Param.Byte[5] = (uint8_t) variables[1];
226
                toNaviCtrl.Param.Byte[6] = (uint8_t) variables[2];
227
                toNaviCtrl.Param.Byte[7] = (uint8_t) variables[3];
228
                toNaviCtrl.Param.Byte[8] = (uint8_t) RC_Quality;
229
                break;
230
 
231
        case SPI_CMD_MISC:
232
                toNaviCtrl.Param.Byte[0] = compassCalState;
233
                if (compassCalState > 4) { // jump from 5 to 0
234
                        compassCalState = 0;
235
                }
236
                toNaviCtrl.Param.Byte[1] = staticParams.NaviPHLoginTime;
237
                // TODO: Height and in the correct scaling...
238
                toNaviCtrl.Param.Int[1] = 0; //readingHeight; // at address of Byte 2 and 3
239
                toNaviCtrl.Param.Byte[4] = staticParams.NaviGpsPLimit;
240
                toNaviCtrl.Param.Byte[5] = staticParams.NaviGpsILimit;
241
                toNaviCtrl.Param.Byte[6] = staticParams.NaviGpsDLimit;
242
                break;
243
 
244
        case SPI_CMD_VERSION:
245
                toNaviCtrl.Param.Byte[0] = SPI_VersionInfo.Major;
246
                toNaviCtrl.Param.Byte[1] = SPI_VersionInfo.Minor;
247
                toNaviCtrl.Param.Byte[2] = SPI_VersionInfo.Patch;
248
                toNaviCtrl.Param.Byte[3] = SPI_VersionInfo.Compatible;
2088 - 249
                toNaviCtrl.Param.Byte[4] = boardRelease;
1821 - 250
                break;
251
        default:
252
                break;
253
        }
254
 
255
        sei();
256
        // enable all interrupts
257
 
258
        // analyze content of packet from NaviCtrl if valid
259
        if (SPI_RxDataValid) {
260
                // update gps controls
261
                if (abs(fromNaviCtrl.GPSStickPitch) < 512 && abs(fromNaviCtrl.GPSStickRoll)
262
                                < 512 && (staticParams.GlobalConfig & CFG_GPS_ACTIVE)) {
263
                        GPSStickPitch = fromNaviCtrl.GPSStickPitch;
264
                        GPSStickRoll = fromNaviCtrl.GPSStickRoll;
265
                        NCDataOkay = 250;
266
                }
267
                // update compass readings
268
                if (fromNaviCtrl.CompassHeading <= 360) {
269
                        compassHeading = fromNaviCtrl.CompassHeading;
270
                }
271
                //if(compassHeading < 0) compassOffCourse = 0;
272
                //else compassOffCourse = ((540 + compassHeading - compassCourse) % 360) - 180;
273
                // NaviCtrl wants to beep?
274
                if (fromNaviCtrl.BeepTime > BeepTime && !compassCalState)
275
                        BeepTime = fromNaviCtrl.BeepTime;
276
 
277
                switch (fromNaviCtrl.Command) {
278
                case SPI_KALMAN:
279
                        dynamicParams.KalmanK = fromNaviCtrl.Param.Byte[0];
280
                        dynamicParams.KalmanMaxFusion = fromNaviCtrl.Param.Byte[1];
281
                        dynamicParams.KalmanMaxDrift = fromNaviCtrl.Param.Byte[2];
282
                        NCSerialDataOkay = fromNaviCtrl.Param.Byte[3];
283
                        break;
284
 
285
                default:
286
                        break;
287
                }
288
        } else { // no valid data from NaviCtrl
289
                // disable GPS control
290
                GPSStickPitch = 0;
291
                GPSStickRoll = 0;
292
        }
1612 dongfang 293
}
294
 
295
/*********************************************/
296
/*  Start Transmission of packet to NaviCtrl */
297
/*********************************************/
1821 - 298
void SPI_StartTransmitPacket(void) {
299
        if (!SPITransferCompleted)
300
                return; // return immediately if transfer is in progress
301
        else // transmission was completed
302
        {
303
                SLAVE_SELECT_PORT &= ~(1 << SPI_SLAVE_SELECT); // Select slave
304
 
305
                // cyclic commands
306
                toNaviCtrl.Command = SPI_CommandSequence[SPI_CommandCounter++];
307
                if (SPI_CommandCounter >= sizeof(SPI_CommandSequence))
308
                        SPI_CommandCounter = 0;
309
 
310
                SPITransferCompleted = 0; // transfer is in progress
311
                UpdateSPI_Buffer(); // update data in toNaviCtrl
312
 
313
                SPI_TxBufferIndex = 1; //proceed with 2nd byte
314
 
315
                // -- Debug-Output ---
316
                //----
317
                asm volatile ("nop");
318
                asm volatile ("nop");
319
                asm volatile ("nop");
320
                asm volatile ("nop");
321
                asm volatile ("nop");
322
                asm volatile ("nop");
323
                asm volatile ("nop");
324
                asm volatile ("nop");
325
                asm volatile ("nop");
326
                asm volatile ("nop");
327
                asm volatile ("nop");
328
                asm volatile ("nop");
329
                asm volatile ("nop");
330
                asm volatile ("nop");
331
                asm volatile ("nop");
332
                asm volatile ("nop");
333
                asm volatile ("nop");
334
                asm volatile ("nop");
335
                asm volatile ("nop");
336
                asm volatile ("nop");
337
                asm volatile ("nop");
338
                asm volatile ("nop");
339
                asm volatile ("nop");
340
                asm volatile ("nop");
341
                toNaviCtrl.Chksum = toNaviCtrl.Sync1; // init checksum
342
                SPDR = toNaviCtrl.Sync1; // send first byte
343
        }
1612 dongfang 344
}
345
 
346
//------------------------------------------------------
347
// This is the spi data transfer between FlightCtrl and NaviCtrl
348
// Every time this routine is called within the mainloop one byte of the packet to
349
// the NaviCtrl and one byte of the packet from the NaviCtrl is possible transfered
350
 
351
void SPI_TransmitByte(void) {
1821 - 352
        static SPI_RXState_t SPI_RXState = SPI_SYNC1;
353
        uint8_t rxdata;
354
        static uint8_t rxchksum;
355
 
356
        if (SPITransferCompleted)
357
                return; // return immediatly if transfer was completed
358
        if (!(SPSR & (1 << SPIF)))
359
                return; // return if no SPI-IRQ pending
360
        SendSPI = 4; // mait 4 * 0.102 ms for the next call of SPI_TransmitByte() in the main loop
361
 
362
        SLAVE_SELECT_PORT |= (1 << SPI_SLAVE_SELECT); // DeselectSlave
363
 
364
        rxdata = SPDR; // save spi data register
365
 
366
        switch (SPI_RXState) {
367
        case SPI_SYNC1: // first sync byte
368
                SPI_RxBufferIndex = 0; // set pointer to start of rx buffer
369
                rxchksum = rxdata; // initialize checksum
370
                if (rxdata == SPI_RXSYNCBYTE1) { // 1st Syncbyte found
371
                        SPI_RXState = SPI_SYNC2; // trigger to state for second sync byte
372
                }
373
                break;
374
 
375
        case SPI_SYNC2: // second sync byte
376
                if (rxdata == SPI_RXSYNCBYTE2) { // 2nd Syncbyte found
377
                        rxchksum += rxdata; // update checksum
378
                        SPI_RXState = SPI_DATA; // trigger to state for second sync byte
379
                } else // 2nd Syncbyte not found
380
                {
381
                        SPI_RXState = SPI_SYNC1; // jump back to 1st sync byte
382
                }
383
                break;
384
 
385
        case SPI_DATA: // data bytes
386
                SPI_RxBuffer[SPI_RxBufferIndex++] = rxdata; // copy data byte to spi buffer
387
                // if all bytes are received of a packet from the NaviCtrl
388
                if (SPI_RxBufferIndex >= SPI_RXBUFFER_LEN) { // last byte transfered is the checksum of the packet
389
                        if (rxdata == rxchksum) { // checksum matching?
390
                                // copy SPI_RxBuffer -> FromFlightCtrl
391
                                uint8_t *ptr = (uint8_t *) &fromNaviCtrl;
392
                                cli();
393
                                memcpy(ptr, (uint8_t *) SPI_RxBuffer, sizeof(fromNaviCtrl));
394
                                sei();
395
                                SPI_RxDataValid = 1;
396
                        } else { // checksum does not match
397
                                SPI_RxDataValid = 0; // reset valid flag
398
                        }
399
                        SPI_RXState = SPI_SYNC1; // reset state sync
400
                } else { // not all bytes transfered
401
                        rxchksum += rxdata; // update checksum
402
                }
403
                break;
404
        }// eof switch(SPI_RXState)
405
 
406
        // if still some bytes left for transmission to NaviCtrl
407
        if (SPI_TxBufferIndex < SPI_TXBUFFER_LEN) {
408
                SLAVE_SELECT_PORT &= ~(1 << SPI_SLAVE_SELECT); // SelectSlave
409
                asm volatile ("nop");
410
                asm volatile ("nop");
411
                asm volatile ("nop");
412
                asm volatile ("nop");
413
                asm volatile ("nop");
414
                asm volatile ("nop");
415
                asm volatile ("nop");
416
                asm volatile ("nop");
417
                asm volatile ("nop");
418
                asm volatile ("nop");
419
                asm volatile ("nop");
420
                asm volatile ("nop");
421
                asm volatile ("nop");
422
                asm volatile ("nop");
423
                asm volatile ("nop");
424
                asm volatile ("nop");
425
                asm volatile ("nop");
426
                asm volatile ("nop");
427
                asm volatile ("nop");
428
                asm volatile ("nop");
429
                asm volatile ("nop");
430
                asm volatile ("nop");
431
                asm volatile ("nop");
432
                asm volatile ("nop");
433
 
434
                SPDR = SPI_TxBuffer[SPI_TxBufferIndex]; // transmit byte
435
                toNaviCtrl.Chksum += SPI_TxBuffer[SPI_TxBufferIndex]; // update checksum for everey byte that was sent
436
                SPI_TxBufferIndex++;
437
        } else {
438
                //Transfer of all bytes of the packet to NaviCtrl completed
439
                SPITransferCompleted = 1;
440
        }
1612 dongfang 441
}