Subversion Repositories FlightCtrl

Rev

Rev 1634 | Rev 1646 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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