-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathardunxt.pde
289 lines (238 loc) · 9.35 KB
/
ardunxt.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
/* ArduNXT - Arduino based Lego Mondstorms NXT universal Remote Control Interface */
/* Please see http://code.google.com/p/ardunxt/ for further details and the latest version */
/* By Christopher Barnes */
/*
// Aspects of this software were derived from code used in ArduPilot
// By Chris Anderson, Jordi Munoz, Bill Premerlani, HappyKillMore
// James Cohen, JB from rotorFX, Automatik, Fefenin, Peter Meister
// & Remzibi.
*/
//TODO
// Commands from NXT:
// set RC Input centre
// save config
// control Mux
// Single status byte for NXT to read to say if anything has changed (bitmap of what?)
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <avr/io.h>
#include <util/twi.h>
// Function Prototypes for integration with twi4nxt code
extern void twi4nxt_attachSlaveRxEvent( void (*)(byte*, uint8_t) );
extern void twi4nxt_attachSlaveTxEvent( void (*)(void) );
#define TITLE_STRING F("ArduNXT Universal RC Interface")
#define VERSION_STRING F("V1.09") // This is NOT the same as the version reported over the NXT interface
// which is defined in NXTI2C.pde
// Select the Baud rate you want to use:
#define SERIAL_BAUD (115200) // Baud Rate used for DSM2 satellite receiver (and diagnostics)
//#define SERIAL_BAUD (38400) // Baud Rate used for GPS and Diagnostics
#define NUM_RCI_CH (7U) // Number of RCInput Channels (e.g. direct from DSM2 satellite receiver)
#define NUM_SERVO_CH (4U) // total number of servo output channels
//#define ATTINY_IN_USE // If you do not hold the ATTiny in reset, on the Ardupilot prototype, then it is in control of the multiplexer
#define MINDSENSORS_NXT_SERVO_COMPATIBLE // If you want FULL compatibility with Mindsensors NXT Servo Sensor (I2C address and Servo Position Readback)
// Some of the code has been migrated from a previous project which uses the following type definitions:
typedef signed char INT_8;
typedef unsigned char UINT_8;
typedef signed int INT_16;
typedef unsigned int UINT_16;
typedef unsigned long UINT_24; // Not sure that there is any way to get a true 24 bit type in Arduino?
typedef signed long INT_32;
typedef unsigned long UINT_32;
#ifndef TRUE
#define TRUE (0x01)
#endif
#ifndef FALSE
#define FALSE (0x00)
#endif
// Flags to control which Diagnostics outputs we want to see on the serial port
typedef union {
struct {
unsigned bGPS:1; // GPS decoding
unsigned bRCInput:1; // RC Input
unsigned bServoOutput:1; // Servo Output
unsigned bNXTInterface:1; // I2C NXT interface
unsigned bMultiplexer:1; // Multiplexer state
unsigned bDigitalInput:1; // Digital Inputs
unsigned bDigitalOutput:1; // Digital Outputs
unsigned bPerformance:1; // Software performance metrics
};
struct {
UINT_8 u8Value;
};
} DiagnosticsFlags;
// Flags to configure ArduNXT
typedef union {
struct {
unsigned bDSM2Enable:1; // Serial Port used for DSM2 satellite receiver
};
struct {
UINT_8 u8Value;
};
} ConfigurationFlags;
// Assorted Flags
typedef union {
struct {
unsigned bFrameUpdate:1; // PWM Servo Output Frame Update
unsigned bFrameMissed:1; // PWM Servo Output Frame has been missed - check Diagnostics for loop execution performance...
};
struct {
UINT_8 u8Value;
};
} MiscFlags;
// Flags to indicate which aspects of the GPS data have been received
typedef union {
struct {
// unsigned bDate:1;
unsigned bTime:1; // Time
unsigned bLatLon:1; // Latitude and Longitude
unsigned bAltitude:1; // Altitude
unsigned bSpeed:1; // Speed and Heding
unsigned bValid:1; // GPS Fix Status (i.e. 2D or better)
unsigned bUpdate:1; // Flag to indicate that data has been updated (i.e. a full set of new values)
unsigned bPresent:1; // GPS module detected
};
struct {
UINT_8 u8Value;
};
} GPSMsgFlags;
// Definition of a GPS Record
typedef struct
{
// UINT_16 u16Date; // binary format date encoding
UINT_32 u32Time; // Milliseconds since midnight (UTC)
INT_32 i32Latitude; // Latitude (min/10000)
INT_32 i32Longitude; // Longitude (min/10000)
UINT_16 u16Altitude; // Altitude (m/10)
UINT_16 u16Speed; // Speed (knots/100) (or cm/s for UBX protocol)
UINT_16 u16Heading; // Heading (degrees/100)
} GPSRecord;
// Flags for Remote Control PWM Input Channels
typedef union {
struct {
// High level
unsigned bValid:1; // Flag to indicate that the channel is being received
unsigned bUpdate:1; // Flag to indicate that data has been updated
// Low level
unsigned bRise:1; // We have recorded a timestamp for rising edge
unsigned bFall:1; // We have recorded a timestamp for a falling edge
unsigned bLost:1; // We have lost a pulse measurements as the handler was not called frequently enough
unsigned bTimerWrap:1;
unsigned bWrap:1; // Flag that we need to add PWM_PERIOD to fall time
};
struct {
UINT_8 u8Value;
};
}
RCInputFlags;
/*************************************************************************
*
*************************************************************************/
// Where things are stored in EEPROM
#define EE_DIAGNOSTICS_FLAGS (0x01)
#define EE_CONFIGURATION_FLAGS (0x02)
/***************************************************************************
General variables
**************************************************************************/
GPSRecord m_GPSNew;
GPSMsgFlags g_GPSMsgFlags;
volatile RCInputFlags g_RCIFlags[NUM_RCI_CH]; // RCInput channel flags
DiagnosticsFlags g_DiagnosticsFlags;
ConfigurationFlags g_ConfigurationFlags;
volatile MiscFlags g_MiscFlags;
unsigned int g_u16Pulse[NUM_RCI_CH]; // RCInput pulse widths
/***************************************************************************
**************************************************************************/
void setup()
{
Init_ArduNXT(); // Initialize application...
Init_Diagnostics(); // Initialise diagnostics output
}
// Main loop executed as fast as possible
void loop()
{
// Each "Handler" is designed to do a small amount of processing each time it is called in
// a co-operative approach to multi-tasking.
ServoOutput_Handler();
RCInput_Handler();
Analogue_Handler();
if(g_ConfigurationFlags.bDSM2Enable)
{
DSM2_Handler();
}
else
{
GPS_Handler();
}
NXT_Handler();
Multiplexer_Handler();
// Support for development diagnostics and debugging information output
if (g_DiagnosticsFlags.bDigitalInput) DigitalInput_Monitor();
if (g_DiagnosticsFlags.bPerformance) Diagnostics_Handler();
}
/*****************************************
*****************************************/
void Init_ArduNXT(void)
{
// Configure ATMega Hardware for ArduNXT
// based on functionality of Ardupilot PCB
// PD0 = RS232 Serial Data input
// PD1 = RS232 Serial Data output
// Assignments which are commented out are initialised in the appropriate module...
// pinMode(2,INPUT); // RC Input pin 0
// pinMode(3,INPUT); // RC Input pin 1
// pinMode(4,INPUT); // MUX output
// pinMode(5,INPUT); // Servo output pin 3
// pinMode(6,INPUT); // RC Input pin 2
// pinMode(7,OUTPUT); // GPS RX Input Mux output can we afford to spare a pin for this?
// pinMode(8,OUTPUT); // Servo output pin 2
// pinMode(9,OUTPUT); // Servo output pin 0
// pinMode(10,OUTPUT); // Servo output pin 1
// pinMode(11,INPUT); // RC Input pin 3
// pinMode(12,OUTPUT); // Blue LED output pin
// pinMode(13,OUTPUT); // Yellow LED output pin
// Initialise basic variables
g_DiagnosticsFlags.u8Value = 0U;
g_MiscFlags.u8Value = 0U;
// Initialise Serial Port
Serial.begin(SERIAL_BAUD);
// Title Header
Serial.println("");
Serial.print(TITLE_STRING);
Serial.println(VERSION_STRING);
Load_Settings();//Loading saved settings
// Override saved settings
g_DiagnosticsFlags.bRCInput = TRUE;
g_ConfigurationFlags.bDSM2Enable = TRUE;
// Initialise all modules
Save_Settings();
Init_Multiplexer();
Init_RCInputCh();
Init_ServoOutput();
Init_NXTIIC();
if(g_ConfigurationFlags.bDSM2Enable)
{
Init_DSM2();
}
else
{
// If Serial Port is in use for DSM2 satellite receiver then it can't also do GPS
Init_GPS();
}
// Everything initialised - enable interrupts
sei();
}
/*****************************************************************************
*****************************************************************************/
void Load_Settings(void)
{
Serial.println("Load Settings");
g_DiagnosticsFlags.u8Value =(byte)eeprom_read_byte((const uint8_t *)EE_DIAGNOSTICS_FLAGS);
g_ConfigurationFlags.u8Value =(byte)eeprom_read_byte((const uint8_t *)EE_CONFIGURATION_FLAGS);
}
void Save_Settings(void)
{
Serial.println("Save Settings");
eeprom_busy_wait();
eeprom_write_byte((uint8_t *)EE_DIAGNOSTICS_FLAGS, g_DiagnosticsFlags.u8Value);
eeprom_write_byte((uint8_t *)EE_CONFIGURATION_FLAGS, g_ConfigurationFlags.u8Value);
}