Subversion Repositories FlightCtrl

Rev

Rev 1969 | Rev 1974 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1969 Rev 1970
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 example: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
35
// +     Commercial use (for example: 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 "rc.h"
64
#include "rc.h"
65
#include "externalControl.h"
65
#include "externalControl.h"
66
#include "output.h"
66
#include "output.h"
67
#include "attitude.h"
67
#include "attitude.h"
68
 
68
 
69
#ifdef USE_MK3MAG
69
#ifdef USE_MK3MAG
70
#include "mk3mag.h"
70
#include "mk3mag.h"
71
#endif
71
#endif
72
 
72
 
73
#define FC_ADDRESS 1
73
#define FC_ADDRESS 1
74
#define NC_ADDRESS 2
74
#define NC_ADDRESS 2
75
#define MK3MAG_ADDRESS 3
75
#define MK3MAG_ADDRESS 3
76
 
76
 
77
#define FALSE   0
77
#define FALSE   0
78
#define TRUE    1
78
#define TRUE    1
79
//int8_t test __attribute__ ((section (".noinit")));
79
//int8_t test __attribute__ ((section (".noinit")));
80
uint8_t request_VerInfo = FALSE;
80
uint8_t request_VerInfo = FALSE;
81
uint8_t request_ExternalControl = FALSE;
81
uint8_t request_ExternalControl = FALSE;
82
uint8_t request_Display = FALSE;
82
uint8_t request_Display = FALSE;
83
uint8_t request_Display1 = FALSE;
83
uint8_t request_Display1 = FALSE;
84
uint8_t request_DebugData = FALSE;
84
uint8_t request_DebugData = FALSE;
85
uint8_t request_Data3D = FALSE;
85
uint8_t request_Data3D = FALSE;
86
uint8_t request_DebugLabel = 255;
86
uint8_t request_DebugLabel = 255;
87
uint8_t request_PPMChannels = FALSE;
87
uint8_t request_PPMChannels = FALSE;
88
uint8_t request_MotorTest = FALSE;
88
uint8_t request_MotorTest = FALSE;
89
uint8_t request_variables = FALSE;
89
uint8_t request_variables = FALSE;
90
 
90
 
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 = 0; // in 1ms
115
uint16_t DebugData_Interval = 0; // 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
                "rc 0            ",
128
                "rc 0            ",
129
                "rc 1            ",
129
                "rc 1            ",
130
                "rc 2            ", //5
130
                "rc 2            ", //5
131
                "OffsPitch       ",
131
                "OffsPitch       ",
132
                "OffsRoll        ",
132
                "OffsRoll        ",
133
                "AttitudeControl ",
133
                "AttitudeControl ",
134
                "AccPitch (angle)",
134
                "AccPitch (angle)",
135
                "AccRoll (angle) ", //10
135
                "AccRoll (angle) ", //10
136
                "UBat            ",
136
                "UBat            ",
137
                "Pitch Term      ",
137
                "Pitch Term      ",
138
                "Roll Term       ",
138
                "Roll Term       ",
139
                "Yaw Term        ",
139
                "Yaw Term        ",
140
                "ca debug        ", //15
140
                "ca debug        ", //15
141
                "gyroP           ",
141
                "gyroP           ",
142
                "gyroI           ",
142
                "gyroI           ",
143
        "gyroD           ",
143
        "gyroD           ",
144
        "unused          ",
144
        "unused          ",
145
                "dHeightThrottle ", //20
145
                "dHeightThrottle ", //20
146
                "hoverThrottle   ",
146
                "hoverThrottle   ",
147
                "M1              ",
147
                "M1              ",
148
                "M2              ",
148
                "M2              ",
149
                "M3              ",
149
                "M3              ",
150
                "M4              ", //25
150
                "M4              ", //25
151
                "ControlYaw      ",
151
                "ControlYaw      ",
152
                "Airpress. Range ",
152
                "Airpress. Range ",
153
                "DriftCompPitch  ",
153
                "DriftCompPitch  ",
154
                "DriftCompRoll   ",
154
                "DriftCompRoll   ",
155
                "AirpressFiltered", //30
155
                "Altitude        ", //30
156
                "AirpressADC     " };
156
                "AirpressADC     " };
157
 
157
 
158
/****************************************************************/
158
/****************************************************************/
159
/*              Initialization of the USART0                    */
159
/*              Initialization of the USART0                    */
160
/****************************************************************/
160
/****************************************************************/
161
void usart0_Init(void) {
161
void usart0_Init(void) {
162
        uint8_t sreg = SREG;
162
        uint8_t sreg = SREG;
163
        uint16_t ubrr = (uint16_t) ((uint32_t) SYSCLK / (8 * USART0_BAUD) - 1);
163
        uint16_t ubrr = (uint16_t) ((uint32_t) SYSCLK / (8 * USART0_BAUD) - 1);
164
 
164
 
165
        // disable all interrupts before configuration
165
        // disable all interrupts before configuration
166
        cli();
166
        cli();
167
 
167
 
168
        // disable RX-Interrupt
168
        // disable RX-Interrupt
169
        UCSR0B &= ~(1 << RXCIE0);
169
        UCSR0B &= ~(1 << RXCIE0);
170
        // disable TX-Interrupt
170
        // disable TX-Interrupt
171
        UCSR0B &= ~(1 << TXCIE0);
171
        UCSR0B &= ~(1 << TXCIE0);
172
 
172
 
173
        // set direction of RXD0 and TXD0 pins
173
        // set direction of RXD0 and TXD0 pins
174
        // set RXD0 (PD0) as an input pin
174
        // set RXD0 (PD0) as an input pin
175
        PORTD |= (1 << PORTD0);
175
        PORTD |= (1 << PORTD0);
176
        DDRD &= ~(1 << DDD0);
176
        DDRD &= ~(1 << DDD0);
177
        // set TXD0 (PD1) as an output pin
177
        // set TXD0 (PD1) as an output pin
178
        PORTD |= (1 << PORTD1);
178
        PORTD |= (1 << PORTD1);
179
        DDRD |= (1 << DDD1);
179
        DDRD |= (1 << DDD1);
180
 
180
 
181
        // USART0 Baud Rate Register
181
        // USART0 Baud Rate Register
182
        // set clock divider
182
        // set clock divider
183
        UBRR0H = (uint8_t) (ubrr >> 8);
183
        UBRR0H = (uint8_t) (ubrr >> 8);
184
        UBRR0L = (uint8_t) ubrr;
184
        UBRR0L = (uint8_t) ubrr;
185
 
185
 
186
        // USART0 Control and Status Register A, B, C
186
        // USART0 Control and Status Register A, B, C
187
 
187
 
188
        // enable double speed operation in
188
        // enable double speed operation in
189
        UCSR0A |= (1 << U2X0);
189
        UCSR0A |= (1 << U2X0);
190
        // enable receiver and transmitter in
190
        // enable receiver and transmitter in
191
        UCSR0B = (1 << TXEN0) | (1 << RXEN0);
191
        UCSR0B = (1 << TXEN0) | (1 << RXEN0);
192
        // set asynchronous mode
192
        // set asynchronous mode
193
        UCSR0C &= ~(1 << UMSEL01);
193
        UCSR0C &= ~(1 << UMSEL01);
194
        UCSR0C &= ~(1 << UMSEL00);
194
        UCSR0C &= ~(1 << UMSEL00);
195
        // no parity
195
        // no parity
196
        UCSR0C &= ~(1 << UPM01);
196
        UCSR0C &= ~(1 << UPM01);
197
        UCSR0C &= ~(1 << UPM00);
197
        UCSR0C &= ~(1 << UPM00);
198
        // 1 stop bit
198
        // 1 stop bit
199
        UCSR0C &= ~(1 << USBS0);
199
        UCSR0C &= ~(1 << USBS0);
200
        // 8-bit
200
        // 8-bit
201
        UCSR0B &= ~(1 << UCSZ02);
201
        UCSR0B &= ~(1 << UCSZ02);
202
        UCSR0C |= (1 << UCSZ01);
202
        UCSR0C |= (1 << UCSZ01);
203
        UCSR0C |= (1 << UCSZ00);
203
        UCSR0C |= (1 << UCSZ00);
204
 
204
 
205
        // flush receive buffer
205
        // flush receive buffer
206
        while (UCSR0A & (1 << RXC0))
206
        while (UCSR0A & (1 << RXC0))
207
                UDR0;
207
                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
{
244
{
245
        static uint16_t ptr_txd_buffer = 0;
245
        static uint16_t ptr_txd_buffer = 0;
246
        uint8_t tmp_tx;
246
        uint8_t tmp_tx;
247
        if (!txd_complete) { // transmission not completed
247
        if (!txd_complete) { // transmission not completed
248
                ptr_txd_buffer++; // die [0] wurde schon gesendet
248
                ptr_txd_buffer++; // die [0] wurde schon gesendet
249
                tmp_tx = txd_buffer[ptr_txd_buffer];
249
                tmp_tx = txd_buffer[ptr_txd_buffer];
250
                // if terminating character or end of txd buffer was reached
250
                // if terminating character or end of txd buffer was reached
251
                if ((tmp_tx == '\r') || (ptr_txd_buffer == TXD_BUFFER_LEN)) {
251
                if ((tmp_tx == '\r') || (ptr_txd_buffer == TXD_BUFFER_LEN)) {
252
                        ptr_txd_buffer = 0; // reset txd pointer
252
                        ptr_txd_buffer = 0; // reset txd pointer
253
                        txd_complete = 1; // stop transmission
253
                        txd_complete = 1; // stop transmission
254
                }
254
                }
255
                UDR0 = tmp_tx; // send current byte will trigger this ISR again
255
                UDR0 = tmp_tx; // send current byte will trigger this ISR again
256
        }
256
        }
257
        // transmission completed
257
        // transmission completed
258
        else
258
        else
259
                ptr_txd_buffer = 0;
259
                ptr_txd_buffer = 0;
260
}
260
}
261
 
261
 
262
/****************************************************************/
262
/****************************************************************/
263
/* USART0 receiver               ISR                            */
263
/* USART0 receiver               ISR                            */
264
/****************************************************************/
264
/****************************************************************/
265
ISR(USART0_RX_vect)
265
ISR(USART0_RX_vect)
266
{
266
{
267
        static uint16_t checksum;
267
        static uint16_t checksum;
268
        static uint8_t ptr_rxd_buffer = 0;
268
        static uint8_t ptr_rxd_buffer = 0;
269
        uint8_t checksum1, checksum2;
269
        uint8_t checksum1, checksum2;
270
        uint8_t c;
270
        uint8_t c;
271
 
271
 
272
        c = UDR0; // catch the received byte
272
        c = UDR0; // catch the received byte
273
 
273
 
274
        if (rxd_buffer_locked)
274
        if (rxd_buffer_locked)
275
                return; // if rxd buffer is locked immediately return
275
                return; // if rxd buffer is locked immediately return
276
 
276
 
277
        // the rxd buffer is unlocked
277
        // the rxd buffer is unlocked
278
        if ((ptr_rxd_buffer == 0) && (c == '#')) { // if rxd buffer is empty and syncronisation character is received
278
        if ((ptr_rxd_buffer == 0) && (c == '#')) { // if rxd buffer is empty and syncronisation character is received
279
                rxd_buffer[ptr_rxd_buffer++] = c; // copy 1st byte to buffer
279
                rxd_buffer[ptr_rxd_buffer++] = c; // copy 1st byte to buffer
280
                checksum = c; // init checksum
280
                checksum = c; // init checksum
281
        }
281
        }
282
#if 0
282
#if 0
283
        else if (ptr_rxd_buffer == 1) { // handle address
283
        else if (ptr_rxd_buffer == 1) { // handle address
284
                rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
284
                rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
285
                checksum += c; // update checksum
285
                checksum += c; // update checksum
286
        }
286
        }
287
#endif
287
#endif
288
        else if (ptr_rxd_buffer < RXD_BUFFER_LEN) { // collect incomming bytes
288
        else if (ptr_rxd_buffer < RXD_BUFFER_LEN) { // collect incomming bytes
289
                if (c != '\r') { // no termination character
289
                if (c != '\r') { // no termination character
290
                        rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
290
                        rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
291
                        checksum += c; // update checksum
291
                        checksum += c; // update checksum
292
                } else { // termination character was received
292
                } else { // termination character was received
293
                        // the last 2 bytes are no subject for checksum calculation
293
                        // the last 2 bytes are no subject for checksum calculation
294
                        // they are the checksum itself
294
                        // they are the checksum itself
295
                        checksum -= rxd_buffer[ptr_rxd_buffer - 2];
295
                        checksum -= rxd_buffer[ptr_rxd_buffer - 2];
296
                        checksum -= rxd_buffer[ptr_rxd_buffer - 1];
296
                        checksum -= rxd_buffer[ptr_rxd_buffer - 1];
297
                        // calculate checksum from transmitted data
297
                        // calculate checksum from transmitted data
298
                        checksum %= 4096;
298
                        checksum %= 4096;
299
                        checksum1 = '=' + checksum / 64;
299
                        checksum1 = '=' + checksum / 64;
300
                        checksum2 = '=' + checksum % 64;
300
                        checksum2 = '=' + checksum % 64;
301
                        // compare checksum to transmitted checksum bytes
301
                        // compare checksum to transmitted checksum bytes
302
                        if ((checksum1 == rxd_buffer[ptr_rxd_buffer - 2]) && (checksum2
302
                        if ((checksum1 == rxd_buffer[ptr_rxd_buffer - 2]) && (checksum2
303
                                        == rxd_buffer[ptr_rxd_buffer - 1])) {
303
                                        == 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') {
309
                                if (rxd_buffer[2] == 'R') {
310
                                        wdt_enable(WDTO_250MS);
310
                                        wdt_enable(WDTO_250MS);
311
                                } // Reset-Commando
311
                                } // Reset-Commando
312
                        } else { // checksum invalid
312
                        } else { // checksum invalid
313
                                rxd_buffer_locked = FALSE; // unlock rxd buffer
313
                                rxd_buffer_locked = FALSE; // unlock rxd buffer
314
                        }
314
                        }
315
                        ptr_rxd_buffer = 0; // reset rxd buffer pointer
315
                        ptr_rxd_buffer = 0; // reset rxd buffer pointer
316
                }
316
                }
317
        } else { // rxd buffer overrun
317
        } else { // rxd buffer overrun
318
                ptr_rxd_buffer = 0; // reset rxd buffer
318
                ptr_rxd_buffer = 0; // reset rxd buffer
319
                rxd_buffer_locked = FALSE; // unlock rxd buffer
319
                rxd_buffer_locked = FALSE; // unlock rxd buffer
320
        }
320
        }
321
}
321
}
322
 
322
 
323
// --------------------------------------------------------------------------
323
// --------------------------------------------------------------------------
324
void Addchecksum(uint16_t datalen) {
324
void Addchecksum(uint16_t datalen) {
325
        uint16_t tmpchecksum = 0, i;
325
        uint16_t tmpchecksum = 0, i;
326
        for (i = 0; i < datalen; i++) {
326
        for (i = 0; i < datalen; i++) {
327
                tmpchecksum += txd_buffer[i];
327
                tmpchecksum += txd_buffer[i];
328
        }
328
        }
329
        tmpchecksum %= 4096;
329
        tmpchecksum %= 4096;
330
        txd_buffer[i++] = '=' + tmpchecksum / 64;
330
        txd_buffer[i++] = '=' + tmpchecksum / 64;
331
        txd_buffer[i++] = '=' + tmpchecksum % 64;
331
        txd_buffer[i++] = '=' + tmpchecksum % 64;
332
        txd_buffer[i++] = '\r';
332
        txd_buffer[i++] = '\r';
333
        txd_complete = FALSE;
333
        txd_complete = FALSE;
334
        UDR0 = txd_buffer[0]; // initiates the transmittion (continued in the TXD ISR)
334
        UDR0 = txd_buffer[0]; // initiates the transmittion (continued in the TXD ISR)
335
}
335
}
336
 
336
 
337
// --------------------------------------------------------------------------
337
// --------------------------------------------------------------------------
338
// application example:
338
// application example:
339
// SendOutData('A', FC_ADDRESS, 2, (uint8_t *)&request_DebugLabel, sizeof(request_DebugLabel), label, 16);
339
// SendOutData('A', FC_ADDRESS, 2, (uint8_t *)&request_DebugLabel, sizeof(request_DebugLabel), label, 16);
340
/*
340
/*
341
 void SendOutData(uint8_t cmd, uint8_t addr, uint8_t numofbuffers, ...) { // uint8_t *pdata, uint8_t len, ...
341
 void SendOutData(uint8_t cmd, uint8_t addr, uint8_t numofbuffers, ...) { // uint8_t *pdata, uint8_t len, ...
342
 va_list ap;
342
 va_list ap;
343
 uint16_t txd_bufferIndex = 0;
343
 uint16_t txd_bufferIndex = 0;
344
 uint8_t *currentBuffer;
344
 uint8_t *currentBuffer;
345
 uint8_t currentBufferIndex;
345
 uint8_t currentBufferIndex;
346
 uint16_t lengthOfCurrentBuffer;
346
 uint16_t lengthOfCurrentBuffer;
347
 uint8_t shift = 0;
347
 uint8_t shift = 0;
348
 
348
 
349
 txd_buffer[txd_bufferIndex++] = '#';                   // Start character
349
 txd_buffer[txd_bufferIndex++] = '#';                   // Start character
350
 txd_buffer[txd_bufferIndex++] = 'a' + addr;            // Address (a=0; b=1,...)
350
 txd_buffer[txd_bufferIndex++] = 'a' + addr;            // Address (a=0; b=1,...)
351
 txd_buffer[txd_bufferIndex++] = cmd;                   // Command
351
 txd_buffer[txd_bufferIndex++] = cmd;                   // Command
352
 
352
 
353
 va_start(ap, numofbuffers);
353
 va_start(ap, numofbuffers);
354
 
354
 
355
 while(numofbuffers) {
355
 while(numofbuffers) {
356
 currentBuffer = va_arg(ap, uint8_t*);
356
 currentBuffer = va_arg(ap, uint8_t*);
357
 lengthOfCurrentBuffer = va_arg(ap, int);
357
 lengthOfCurrentBuffer = va_arg(ap, int);
358
 currentBufferIndex = 0;
358
 currentBufferIndex = 0;
359
 // Encode data: 3 bytes of data are encoded into 4 bytes,
359
 // Encode data: 3 bytes of data are encoded into 4 bytes,
360
 // where the 2 most significant bits are both 0.
360
 // where the 2 most significant bits are both 0.
361
 while(currentBufferIndex != lengthOfCurrentBuffer) {
361
 while(currentBufferIndex != lengthOfCurrentBuffer) {
362
 if (!shift) txd_buffer[txd_bufferIndex] = 0;
362
 if (!shift) txd_buffer[txd_bufferIndex] = 0;
363
 txd_buffer[txd_bufferIndex]  |= currentBuffer[currentBufferIndex] >> (shift + 2);
363
 txd_buffer[txd_bufferIndex]  |= currentBuffer[currentBufferIndex] >> (shift + 2);
364
 txd_buffer[++txd_bufferIndex] = (currentBuffer[currentBufferIndex] << (4 - shift)) & 0b00111111;
364
 txd_buffer[++txd_bufferIndex] = (currentBuffer[currentBufferIndex] << (4 - shift)) & 0b00111111;
365
 shift += 2;
365
 shift += 2;
366
 if (shift == 6) { shift=0; txd_bufferIndex++; }
366
 if (shift == 6) { shift=0; txd_bufferIndex++; }
367
 currentBufferIndex++;
367
 currentBufferIndex++;
368
 }
368
 }
369
 }
369
 }
370
 // If the number of data bytes was not divisible by 3, stuff
370
 // If the number of data bytes was not divisible by 3, stuff
371
 //  with 0 pseudodata  until length is again divisible by 3.
371
 //  with 0 pseudodata  until length is again divisible by 3.
372
 if (shift == 2) {
372
 if (shift == 2) {
373
 // We need to stuff with zero bytes at the end.
373
 // We need to stuff with zero bytes at the end.
374
 txd_buffer[txd_bufferIndex]  &= 0b00110000;
374
 txd_buffer[txd_bufferIndex]  &= 0b00110000;
375
 txd_buffer[++txd_bufferIndex] = 0;
375
 txd_buffer[++txd_bufferIndex] = 0;
376
 shift = 4;
376
 shift = 4;
377
 }
377
 }
378
 if (shift == 4) {
378
 if (shift == 4) {
379
 // We need to stuff with zero bytes at the end.
379
 // We need to stuff with zero bytes at the end.
380
 txd_buffer[txd_bufferIndex++] &= 0b00111100;
380
 txd_buffer[txd_bufferIndex++] &= 0b00111100;
381
 txd_buffer[txd_bufferIndex]    = 0;
381
 txd_buffer[txd_bufferIndex]    = 0;
382
 }
382
 }
383
 va_end(ap);
383
 va_end(ap);
384
 Addchecksum(pt); // add checksum after data block and initates the transmission
384
 Addchecksum(pt); // add checksum after data block and initates the transmission
385
 }
385
 }
386
 */
386
 */
387
 
387
 
388
void SendOutData(uint8_t cmd, uint8_t addr, uint8_t numofbuffers, ...) { // uint8_t *pdata, uint8_t len, ...
388
void SendOutData(uint8_t cmd, uint8_t addr, uint8_t numofbuffers, ...) { // uint8_t *pdata, uint8_t len, ...
389
        va_list ap;
389
        va_list ap;
390
        uint16_t pt = 0;
390
        uint16_t pt = 0;
391
        uint8_t a, b, c;
391
        uint8_t a, b, c;
392
        uint8_t ptr = 0;
392
        uint8_t ptr = 0;
393
 
393
 
394
        uint8_t *pdata = 0;
394
        uint8_t *pdata = 0;
395
        int len = 0;
395
        int len = 0;
396
 
396
 
397
        txd_buffer[pt++] = '#'; // Start character
397
        txd_buffer[pt++] = '#'; // Start character
398
        txd_buffer[pt++] = 'a' + addr; // Address (a=0; b=1,...)
398
        txd_buffer[pt++] = 'a' + addr; // Address (a=0; b=1,...)
399
        txd_buffer[pt++] = cmd; // Command
399
        txd_buffer[pt++] = cmd; // Command
400
 
400
 
401
        va_start(ap, numofbuffers);
401
        va_start(ap, numofbuffers);
402
 
402
 
403
        if (numofbuffers) {
403
        if (numofbuffers) {
404
                pdata = va_arg(ap, uint8_t*);
404
                pdata = va_arg(ap, uint8_t*);
405
                len = va_arg(ap, int);
405
                len = va_arg(ap, int);
406
                ptr = 0;
406
                ptr = 0;
407
                numofbuffers--;
407
                numofbuffers--;
408
        }
408
        }
409
 
409
 
410
        while (len) {
410
        while (len) {
411
                if (len) {
411
                if (len) {
412
                        a = pdata[ptr++];
412
                        a = pdata[ptr++];
413
                        len--;
413
                        len--;
414
                        if ((!len) && numofbuffers) {
414
                        if ((!len) && numofbuffers) {
415
                                pdata = va_arg(ap, uint8_t*);
415
                                pdata = va_arg(ap, uint8_t*);
416
                                len = va_arg(ap, int);
416
                                len = va_arg(ap, int);
417
                                ptr = 0;
417
                                ptr = 0;
418
                                numofbuffers--;
418
                                numofbuffers--;
419
                        }
419
                        }
420
                } else
420
                } else
421
                        a = 0;
421
                        a = 0;
422
                if (len) {
422
                if (len) {
423
                        b = pdata[ptr++];
423
                        b = pdata[ptr++];
424
                        len--;
424
                        len--;
425
                        if ((!len) && numofbuffers) {
425
                        if ((!len) && numofbuffers) {
426
                                pdata = va_arg(ap, uint8_t*);
426
                                pdata = va_arg(ap, uint8_t*);
427
                                len = va_arg(ap, int);
427
                                len = va_arg(ap, int);
428
                                ptr = 0;
428
                                ptr = 0;
429
                                numofbuffers--;
429
                                numofbuffers--;
430
                        }
430
                        }
431
                } else
431
                } else
432
                        b = 0;
432
                        b = 0;
433
                if (len) {
433
                if (len) {
434
                        c = pdata[ptr++];
434
                        c = pdata[ptr++];
435
                        len--;
435
                        len--;
436
                        if ((!len) && numofbuffers) {
436
                        if ((!len) && numofbuffers) {
437
                                pdata = va_arg(ap, uint8_t*);
437
                                pdata = va_arg(ap, uint8_t*);
438
                                len = va_arg(ap, int);
438
                                len = va_arg(ap, int);
439
                                ptr = 0;
439
                                ptr = 0;
440
                                numofbuffers--;
440
                                numofbuffers--;
441
                        }
441
                        }
442
                } else
442
                } else
443
                        c = 0;
443
                        c = 0;
444
                txd_buffer[pt++] = '=' + (a >> 2);
444
                txd_buffer[pt++] = '=' + (a >> 2);
445
                txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
445
                txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
446
                txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
446
                txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
447
                txd_buffer[pt++] = '=' + (c & 0x3f);
447
                txd_buffer[pt++] = '=' + (c & 0x3f);
448
        }
448
        }
449
        va_end(ap);
449
        va_end(ap);
450
        Addchecksum(pt); // add checksum after data block and initates the transmission
450
        Addchecksum(pt); // add checksum after data block and initates the transmission
451
}
451
}
452
 
452
 
453
// --------------------------------------------------------------------------
453
// --------------------------------------------------------------------------
454
void Decode64(void) {
454
void Decode64(void) {
455
        uint8_t a, b, c, d;
455
        uint8_t a, b, c, d;
456
        uint8_t x, y, z;
456
        uint8_t x, y, z;
457
        uint8_t ptrIn = 3;
457
        uint8_t ptrIn = 3;
458
        uint8_t ptrOut = 3;
458
        uint8_t ptrOut = 3;
459
        uint8_t len = ReceivedBytes - 6;
459
        uint8_t len = ReceivedBytes - 6;
460
 
460
 
461
        while (len) {
461
        while (len) {
462
                a = rxd_buffer[ptrIn++] - '=';
462
                a = rxd_buffer[ptrIn++] - '=';
463
                b = rxd_buffer[ptrIn++] - '=';
463
                b = rxd_buffer[ptrIn++] - '=';
464
                c = rxd_buffer[ptrIn++] - '=';
464
                c = rxd_buffer[ptrIn++] - '=';
465
                d = rxd_buffer[ptrIn++] - '=';
465
                d = rxd_buffer[ptrIn++] - '=';
466
                //if(ptrIn > ReceivedBytes - 3) break;
466
                //if(ptrIn > ReceivedBytes - 3) break;
467
 
467
 
468
                x = (a << 2) | (b >> 4);
468
                x = (a << 2) | (b >> 4);
469
                y = ((b & 0x0f) << 4) | (c >> 2);
469
                y = ((b & 0x0f) << 4) | (c >> 2);
470
                z = ((c & 0x03) << 6) | d;
470
                z = ((c & 0x03) << 6) | d;
471
 
471
 
472
                if (len--)
472
                if (len--)
473
                        rxd_buffer[ptrOut++] = x;
473
                        rxd_buffer[ptrOut++] = x;
474
                else
474
                else
475
                        break;
475
                        break;
476
                if (len--)
476
                if (len--)
477
                        rxd_buffer[ptrOut++] = y;
477
                        rxd_buffer[ptrOut++] = y;
478
                else
478
                else
479
                        break;
479
                        break;
480
                if (len--)
480
                if (len--)
481
                        rxd_buffer[ptrOut++] = z;
481
                        rxd_buffer[ptrOut++] = z;
482
                else
482
                else
483
                        break;
483
                        break;
484
        }
484
        }
485
        pRxData = &rxd_buffer[3];
485
        pRxData = &rxd_buffer[3];
486
        RxDataLen = ptrOut - 3;
486
        RxDataLen = ptrOut - 3;
487
}
487
}
488
 
488
 
489
// --------------------------------------------------------------------------
489
// --------------------------------------------------------------------------
490
void usart0_ProcessRxData(void) {
490
void usart0_ProcessRxData(void) {
491
        // We control the motorTestActive var from here: Count it down.
491
        // We control the motorTestActive var from here: Count it down.
492
        if (motorTestActive)
492
        if (motorTestActive)
493
                motorTestActive--;
493
                motorTestActive--;
494
        // if data in the rxd buffer are not locked immediately return
494
        // if data in the rxd buffer are not locked immediately return
495
        if (!rxd_buffer_locked)
495
        if (!rxd_buffer_locked)
496
                return;
496
                return;
497
        uint8_t tempchar1, tempchar2;
497
        uint8_t tempchar1, tempchar2;
498
        Decode64(); // decode data block in rxd_buffer
498
        Decode64(); // decode data block in rxd_buffer
499
 
499
 
500
        switch (rxd_buffer[1] - 'a') {
500
        switch (rxd_buffer[1] - 'a') {
501
 
501
 
502
        case FC_ADDRESS:
502
        case FC_ADDRESS:
503
                switch (rxd_buffer[2]) {
503
                switch (rxd_buffer[2]) {
504
#ifdef USE_MK3MAG
504
#ifdef USE_MK3MAG
505
                case 'K':// compass value
505
                case 'K':// compass value
506
                compassHeading = ((Heading_t *)pRxData)->Heading;
506
                compassHeading = ((Heading_t *)pRxData)->Heading;
507
                // compassOffCourse = ((540 + compassHeading - compassCourse) % 360) - 180;
507
                // compassOffCourse = ((540 + compassHeading - compassCourse) % 360) - 180;
508
                break;
508
                break;
509
#endif
509
#endif
510
                case 't': // motor test
510
                case 't': // motor test
511
                        if (RxDataLen > 20) {
511
                        if (RxDataLen > 20) {
512
                                memcpy(&motorTest[0], (uint8_t*) pRxData, sizeof(motorTest));
512
                                memcpy(&motorTest[0], (uint8_t*) pRxData, sizeof(motorTest));
513
                        } else {
513
                        } else {
514
                                memcpy(&motorTest[0], (uint8_t*) pRxData, 4);
514
                                memcpy(&motorTest[0], (uint8_t*) pRxData, 4);
515
                        }
515
                        }
516
                        motorTestActive = 255;
516
                        motorTestActive = 255;
517
                        externalControlActive = 255;
517
                        externalControlActive = 255;
518
                        break;
518
                        break;
519
 
519
 
520
                case 'n':// "Get Mixer Table
520
                case 'n':// "Get Mixer Table
521
                        while (!txd_complete)
521
                        while (!txd_complete)
522
                                ; // wait for previous frame to be sent
522
                                ; // wait for previous frame to be sent
523
                        SendOutData('N', FC_ADDRESS, 1, (uint8_t *) &mixerMatrix, sizeof(mixerMatrix));
523
                        SendOutData('N', FC_ADDRESS, 1, (uint8_t *) &mixerMatrix, sizeof(mixerMatrix));
524
                        break;
524
                        break;
525
 
525
 
526
                case 'm':// "Set Mixer Table
526
                case 'm':// "Set Mixer Table
527
                        if (pRxData[0] == EEMIXER_REVISION) {
527
                        if (pRxData[0] == EEMIXER_REVISION) {
528
                                memcpy(&mixerMatrix, (uint8_t*) pRxData, sizeof(mixerMatrix));
528
                                memcpy(&mixerMatrix, (uint8_t*) pRxData, sizeof(mixerMatrix));
529
                                mixerMatrix_writeToEEProm();
529
                                mixerMatrix_writeToEEProm();
530
                                while (!txd_complete)
530
                                while (!txd_complete)
531
                                        ; // wait for previous frame to be sent
531
                                        ; // wait for previous frame to be sent
532
                                tempchar1 = 1;
532
                                tempchar1 = 1;
533
                        } else {
533
                        } else {
534
                                tempchar1 = 0;
534
                                tempchar1 = 0;
535
                        }
535
                        }
536
                        SendOutData('M', FC_ADDRESS, 1, &tempchar1, 1);
536
                        SendOutData('M', FC_ADDRESS, 1, &tempchar1, 1);
537
                        break;
537
                        break;
538
 
538
 
539
                case 'p': // get PPM channels
539
                case 'p': // get PPM channels
540
                        request_PPMChannels = TRUE;
540
                        request_PPMChannels = TRUE;
541
                        break;
541
                        break;
542
 
542
 
543
                case 'q':// request settings
543
                case 'q':// request settings
544
                        if (pRxData[0] == 0xFF) {
544
                        if (pRxData[0] == 0xFF) {
545
                                pRxData[0] = getParamByte(PID_ACTIVE_SET);
545
                                pRxData[0] = getParamByte(PID_ACTIVE_SET);
546
                        }
546
                        }
547
                        // limit settings range
547
                        // limit settings range
548
                        if (pRxData[0] < 1)
548
                        if (pRxData[0] < 1)
549
                                pRxData[0] = 1; // limit to 1
549
                                pRxData[0] = 1; // limit to 1
550
                        else if (pRxData[0] > 5)
550
                        else if (pRxData[0] > 5)
551
                                pRxData[0] = 5; // limit to 5
551
                                pRxData[0] = 5; // limit to 5
552
                        // load requested parameter set
552
                        // load requested parameter set
553
                        paramSet_readFromEEProm(pRxData[0]);
553
                        paramSet_readFromEEProm(pRxData[0]);
554
                        tempchar1 = pRxData[0];
554
                        tempchar1 = pRxData[0];
555
                        tempchar2 = EEPARAM_REVISION;
555
                        tempchar2 = EEPARAM_REVISION;
556
                        while (!txd_complete)
556
                        while (!txd_complete)
557
                                ; // wait for previous frame to be sent
557
                                ; // wait for previous frame to be sent
558
                        SendOutData('Q', FC_ADDRESS, 3, &tempchar1, sizeof(tempchar1),
558
                        SendOutData('Q', FC_ADDRESS, 3, &tempchar1, sizeof(tempchar1),
559
                                        &tempchar2, sizeof(tempchar2), (uint8_t *) &staticParams,
559
                                        &tempchar2, sizeof(tempchar2), (uint8_t *) &staticParams,
560
                                        sizeof(staticParams));
560
                                        sizeof(staticParams));
561
                        break;
561
                        break;
562
 
562
 
563
                case 's': // save settings
563
                case 's': // save settings
564
                        if (!(MKFlags & MKFLAG_MOTOR_RUN)) // save settings only if motors are off
564
                        if (!(MKFlags & MKFLAG_MOTOR_RUN)) // save settings only if motors are off
565
                        {
565
                        {
566
                                if ((1 <= pRxData[0]) && (pRxData[0] <= 5) && (pRxData[1]
566
                                if ((1 <= pRxData[0]) && (pRxData[0] <= 5) && (pRxData[1]
567
                                                == EEPARAM_REVISION)) // check for setting to be in range and version of settings
567
                                                == EEPARAM_REVISION)) // check for setting to be in range and version of settings
568
                                {
568
                                {
569
                                        memcpy(&staticParams, (uint8_t*) &pRxData[2], sizeof(staticParams));
569
                                        memcpy(&staticParams, (uint8_t*) &pRxData[2], sizeof(staticParams));
570
                                        paramSet_writeToEEProm(pRxData[0]);
570
                                        paramSet_writeToEEProm(pRxData[0]);
571
                                        tempchar1 = getActiveParamSet();
571
                                        tempchar1 = getActiveParamSet();
572
                                        beepNumber(tempchar1);
572
                                        beepNumber(tempchar1);
573
                                } else {
573
                                } else {
574
                                        tempchar1 = 0; //indicate bad data
574
                                        tempchar1 = 0; //indicate bad data
575
                                }
575
                                }
576
                                while (!txd_complete)
576
                                while (!txd_complete)
577
                                        ; // wait for previous frame to be sent
577
                                        ; // wait for previous frame to be sent
578
                                SendOutData('S', FC_ADDRESS, 1, &tempchar1, sizeof(tempchar1));
578
                                SendOutData('S', FC_ADDRESS, 1, &tempchar1, sizeof(tempchar1));
579
                        }
579
                        }
580
                        break;
580
                        break;
581
 
581
 
582
                default:
582
                default:
583
                        //unsupported command received
583
                        //unsupported command received
584
                        break;
584
                        break;
585
                } // case FC_ADDRESS:
585
                } // case FC_ADDRESS:
586
 
586
 
587
        default: // any Slave Address
587
        default: // any Slave Address
588
                switch (rxd_buffer[2]) {
588
                switch (rxd_buffer[2]) {
589
                case 'a':// request for labels of the analog debug outputs
589
                case 'a':// request for labels of the analog debug outputs
590
                        request_DebugLabel = pRxData[0];
590
                        request_DebugLabel = pRxData[0];
591
                        if (request_DebugLabel > 31)
591
                        if (request_DebugLabel > 31)
592
                                request_DebugLabel = 31;
592
                                request_DebugLabel = 31;
593
                        break;
593
                        break;
594
 
594
 
595
                case 'b': // submit extern control
595
                case 'b': // submit extern control
596
                        memcpy(&externalControl, (uint8_t*) pRxData, sizeof(externalControl));
596
                        memcpy(&externalControl, (uint8_t*) pRxData, sizeof(externalControl));
597
                        ConfirmFrame = externalControl.frame;
597
                        ConfirmFrame = externalControl.frame;
598
                        externalControlActive = 255;
598
                        externalControlActive = 255;
599
                        break;
599
                        break;
600
 
600
 
601
                case 'h':// request for display columns
601
                case 'h':// request for display columns
602
                        RemoteKeys |= pRxData[0];
602
                        RemoteKeys |= pRxData[0];
603
                        if (RemoteKeys)
603
                        if (RemoteKeys)
604
                                DisplayLine = 0;
604
                                DisplayLine = 0;
605
                        request_Display = TRUE;
605
                        request_Display = TRUE;
606
                        break;
606
                        break;
607
 
607
 
608
                case 'l':// request for display columns
608
                case 'l':// request for display columns
609
                        MenuItem = pRxData[0];
609
                        MenuItem = pRxData[0];
610
                        request_Display1 = TRUE;
610
                        request_Display1 = TRUE;
611
                        break;
611
                        break;
612
 
612
 
613
                case 'v': // request for version and board release
613
                case 'v': // request for version and board release
614
                        request_VerInfo = TRUE;
614
                        request_VerInfo = TRUE;
615
                        break;
615
                        break;
616
 
616
 
617
                case 'x':
617
                case 'x':
618
                        request_variables = TRUE;
618
                        request_variables = TRUE;
619
                        break;
619
                        break;
620
 
620
 
621
                case 'g':// get external control data
621
                case 'g':// get external control data
622
                        request_ExternalControl = TRUE;
622
                        request_ExternalControl = TRUE;
623
                        break;
623
                        break;
624
 
624
 
625
                case 'd': // request for the debug data
625
                case 'd': // request for the debug data
626
                        DebugData_Interval = (uint16_t) pRxData[0] * 10;
626
                        DebugData_Interval = (uint16_t) pRxData[0] * 10;
627
                        if (DebugData_Interval > 0)
627
                        if (DebugData_Interval > 0)
628
                                request_DebugData = TRUE;
628
                                request_DebugData = TRUE;
629
                        break;
629
                        break;
630
 
630
 
631
                case 'c': // request for the 3D data
631
                case 'c': // request for the 3D data
632
                        Data3D_Interval = (uint16_t) pRxData[0] * 10;
632
                        Data3D_Interval = (uint16_t) pRxData[0] * 10;
633
                        if (Data3D_Interval > 0)
633
                        if (Data3D_Interval > 0)
634
                                request_Data3D = TRUE;
634
                                request_Data3D = TRUE;
635
                        break;
635
                        break;
636
 
636
 
637
                default:
637
                default:
638
                        //unsupported command received
638
                        //unsupported command received
639
                        break;
639
                        break;
640
                }
640
                }
641
                break; // default:
641
                break; // default:
642
        }
642
        }
643
        // unlock the rxd buffer after processing
643
        // unlock the rxd buffer after processing
644
        pRxData = 0;
644
        pRxData = 0;
645
        RxDataLen = 0;
645
        RxDataLen = 0;
646
        rxd_buffer_locked = FALSE;
646
        rxd_buffer_locked = FALSE;
647
}
647
}
648
 
648
 
649
/************************************************************************/
649
/************************************************************************/
650
/* Routine f�r die Serielle Ausgabe                                     */
650
/* Routine f�r die Serielle Ausgabe                                     */
651
/************************************************************************/
651
/************************************************************************/
652
int16_t uart_putchar(int8_t c) {
652
int16_t uart_putchar(int8_t c) {
653
        if (c == '\n')
653
        if (c == '\n')
654
                uart_putchar('\r');
654
                uart_putchar('\r');
655
        // wait until previous character was send
655
        // wait until previous character was send
656
        loop_until_bit_is_set(UCSR0A, UDRE0);
656
        loop_until_bit_is_set(UCSR0A, UDRE0);
657
        // send character
657
        // send character
658
        UDR0 = c;
658
        UDR0 = c;
659
        return (0);
659
        return (0);
660
}
660
}
661
 
661
 
662
//---------------------------------------------------------------------------------------------
662
//---------------------------------------------------------------------------------------------
663
void usart0_TransmitTxData(void) {
663
void usart0_TransmitTxData(void) {
664
        if (!txd_complete)
664
        if (!txd_complete)
665
                return;
665
                return;
666
 
666
 
667
        if (request_VerInfo && txd_complete) {
667
        if (request_VerInfo && txd_complete) {
668
                SendOutData('V', FC_ADDRESS, 1, (uint8_t *) &UART_VersionInfo,
668
                SendOutData('V', FC_ADDRESS, 1, (uint8_t *) &UART_VersionInfo,
669
                                sizeof(UART_VersionInfo));
669
                                sizeof(UART_VersionInfo));
670
                request_VerInfo = FALSE;
670
                request_VerInfo = FALSE;
671
        }
671
        }
672
 
672
 
673
        if (request_Display && txd_complete) {
673
        if (request_Display && txd_complete) {
674
                LCD_PrintMenu();
674
                LCD_PrintMenu();
675
                SendOutData('H', FC_ADDRESS, 2, &DisplayLine, sizeof(DisplayLine),
675
                SendOutData('H', FC_ADDRESS, 2, &DisplayLine, sizeof(DisplayLine),
676
                                &DisplayBuff[DisplayLine * 20], 20);
676
                                &DisplayBuff[DisplayLine * 20], 20);
677
                DisplayLine++;
677
                DisplayLine++;
678
                if (DisplayLine >= 4)
678
                if (DisplayLine >= 4)
679
                        DisplayLine = 0;
679
                        DisplayLine = 0;
680
                request_Display = FALSE;
680
                request_Display = FALSE;
681
        }
681
        }
682
 
682
 
683
        if (request_Display1 && txd_complete) {
683
        if (request_Display1 && txd_complete) {
684
                LCD_PrintMenu();
684
                LCD_PrintMenu();
685
                SendOutData('L', FC_ADDRESS, 3, &MenuItem, sizeof(MenuItem), &MaxMenuItem,
685
                SendOutData('L', FC_ADDRESS, 3, &MenuItem, sizeof(MenuItem), &MaxMenuItem,
686
                                sizeof(MaxMenuItem), DisplayBuff, sizeof(DisplayBuff));
686
                                sizeof(MaxMenuItem), DisplayBuff, sizeof(DisplayBuff));
687
                request_Display1 = FALSE;
687
                request_Display1 = FALSE;
688
        }
688
        }
689
 
689
 
690
        if (request_DebugLabel != 0xFF) { // Texte f�r die Analogdaten
690
        if (request_DebugLabel != 0xFF) { // Texte f�r die Analogdaten
691
                uint8_t label[16]; // local sram buffer
691
                uint8_t label[16]; // local sram buffer
692
                memcpy_P(label, ANALOG_LABEL[request_DebugLabel], 16); // read lable from flash to sram buffer
692
                memcpy_P(label, ANALOG_LABEL[request_DebugLabel], 16); // read lable from flash to sram buffer
693
                SendOutData('A', FC_ADDRESS, 2, (uint8_t *) &request_DebugLabel,
693
                SendOutData('A', FC_ADDRESS, 2, (uint8_t *) &request_DebugLabel,
694
                                sizeof(request_DebugLabel), label, 16);
694
                                sizeof(request_DebugLabel), label, 16);
695
                request_DebugLabel = 0xFF;
695
                request_DebugLabel = 0xFF;
696
        }
696
        }
697
 
697
 
698
        if (ConfirmFrame && txd_complete) { // Datensatz ohne checksum bestätigen
698
        if (ConfirmFrame && txd_complete) { // Datensatz ohne checksum bestätigen
699
                SendOutData('B', FC_ADDRESS, 1, (uint8_t*) &ConfirmFrame, sizeof(ConfirmFrame));
699
                SendOutData('B', FC_ADDRESS, 1, (uint8_t*) &ConfirmFrame, sizeof(ConfirmFrame));
700
                ConfirmFrame = 0;
700
                ConfirmFrame = 0;
701
        }
701
        }
702
 
702
 
703
        if (((DebugData_Interval && checkDelay(DebugData_Timer)) || request_DebugData)
703
        if (((DebugData_Interval && checkDelay(DebugData_Timer)) || request_DebugData)
704
                        && txd_complete) {
704
                        && txd_complete) {
705
                SendOutData('D', FC_ADDRESS, 1, (uint8_t *) &debugOut, sizeof(debugOut));
705
                SendOutData('D', FC_ADDRESS, 1, (uint8_t *) &debugOut, sizeof(debugOut));
706
                DebugData_Timer = setDelay(DebugData_Interval);
706
                DebugData_Timer = setDelay(DebugData_Interval);
707
                request_DebugData = FALSE;
707
                request_DebugData = FALSE;
708
        }
708
        }
709
 
709
 
710
        if (((Data3D_Interval && checkDelay(Data3D_Timer)) || request_Data3D)
710
        if (((Data3D_Interval && checkDelay(Data3D_Timer)) || request_Data3D)
711
                        && txd_complete) {
711
                        && txd_complete) {
712
                SendOutData('C', FC_ADDRESS, 1, (uint8_t *) &Data3D, sizeof(Data3D));
712
                SendOutData('C', FC_ADDRESS, 1, (uint8_t *) &Data3D, sizeof(Data3D));
713
                Data3D.AngleNick = (int16_t) ((10 * angle[PITCH])
713
                Data3D.AngleNick = (int16_t) ((10 * angle[PITCH])
714
                                / GYRO_DEG_FACTOR_PITCHROLL); // convert to multiple of 0.1°
714
                                / GYRO_DEG_FACTOR_PITCHROLL); // convert to multiple of 0.1°
715
                Data3D.AngleRoll = (int16_t) ((10 * angle[ROLL])
715
                Data3D.AngleRoll = (int16_t) ((10 * angle[ROLL])
716
                                / GYRO_DEG_FACTOR_PITCHROLL); // convert to multiple of 0.1°
716
                                / GYRO_DEG_FACTOR_PITCHROLL); // convert to multiple of 0.1°
717
                Data3D.Heading = (int16_t) ((10 * yawGyroHeading) / GYRO_DEG_FACTOR_YAW); // convert to multiple of 0.1°
717
                Data3D.Heading = (int16_t) ((10 * yawGyroHeading) / GYRO_DEG_FACTOR_YAW); // convert to multiple of 0.1°
718
                Data3D_Timer = setDelay(Data3D_Interval);
718
                Data3D_Timer = setDelay(Data3D_Interval);
719
                request_Data3D = FALSE;
719
                request_Data3D = FALSE;
720
        }
720
        }
721
 
721
 
722
        if (request_ExternalControl && txd_complete) {
722
        if (request_ExternalControl && txd_complete) {
723
                SendOutData('G', FC_ADDRESS, 1, (uint8_t *) &externalControl,
723
                SendOutData('G', FC_ADDRESS, 1, (uint8_t *) &externalControl,
724
                                sizeof(externalControl));
724
                                sizeof(externalControl));
725
                request_ExternalControl = FALSE;
725
                request_ExternalControl = FALSE;
726
        }
726
        }
727
 
727
 
728
#ifdef USE_MK3MAG
728
#ifdef USE_MK3MAG
729
        if((checkDelay(Compass_Timer)) && txd_complete) {
729
        if((checkDelay(Compass_Timer)) && txd_complete) {
730
                toMk3Mag.Attitude[0] = (int16_t)((10 * angle[PITCH]) / GYRO_DEG_FACTOR_PITCHROLL); // approx. 0.1 deg
730
                toMk3Mag.Attitude[0] = (int16_t)((10 * angle[PITCH]) / GYRO_DEG_FACTOR_PITCHROLL); // approx. 0.1 deg
731
                toMk3Mag.Attitude[1] = (int16_t)((10 * angle[ROLL]) / GYRO_DEG_FACTOR_PITCHROLL); // approx. 0.1 deg
731
                toMk3Mag.Attitude[1] = (int16_t)((10 * angle[ROLL]) / GYRO_DEG_FACTOR_PITCHROLL); // approx. 0.1 deg
732
                toMk3Mag.UserParam[0] = dynamicParams.userParams[0];
732
                toMk3Mag.UserParam[0] = dynamicParams.userParams[0];
733
                toMk3Mag.UserParam[1] = dynamicParams.userParams[1];
733
                toMk3Mag.UserParam[1] = dynamicParams.userParams[1];
734
                toMk3Mag.CalState = compassCalState;
734
                toMk3Mag.CalState = compassCalState;
735
                SendOutData('w', MK3MAG_ADDRESS, 1,(uint8_t *) &toMk3Mag,sizeof(toMk3Mag));
735
                SendOutData('w', MK3MAG_ADDRESS, 1,(uint8_t *) &toMk3Mag,sizeof(toMk3Mag));
736
                // the last state is 5 and should be send only once to avoid multiple flash writing
736
                // the last state is 5 and should be send only once to avoid multiple flash writing
737
                if(compassCalState > 4) compassCalState = 0;
737
                if(compassCalState > 4) compassCalState = 0;
738
                Compass_Timer = setDelay(99);
738
                Compass_Timer = setDelay(99);
739
        }
739
        }
740
#endif
740
#endif
741
 
741
 
742
        if (request_MotorTest && txd_complete) {
742
        if (request_MotorTest && txd_complete) {
743
                SendOutData('T', FC_ADDRESS, 0);
743
                SendOutData('T', FC_ADDRESS, 0);
744
                request_MotorTest = FALSE;
744
                request_MotorTest = FALSE;
745
        }
745
        }
746
 
746
 
747
        if (request_PPMChannels && txd_complete) {
747
        if (request_PPMChannels && txd_complete) {
748
                SendOutData('P', FC_ADDRESS, 1, (uint8_t *) &PPM_in, sizeof(PPM_in));
748
                SendOutData('P', FC_ADDRESS, 1, (uint8_t *) &PPM_in, sizeof(PPM_in));
749
                request_PPMChannels = FALSE;
749
                request_PPMChannels = FALSE;
750
        }
750
        }
751
 
751
 
752
        if (request_variables && txd_complete) {
752
        if (request_variables && txd_complete) {
753
                SendOutData('X', FC_ADDRESS, 1, (uint8_t *) &variables, sizeof(variables));
753
                SendOutData('X', FC_ADDRESS, 1, (uint8_t *) &variables, sizeof(variables));
754
                request_variables = FALSE;
754
                request_variables = FALSE;
755
        }
755
        }
756
}
756
}
757
 
757