Paparazzi UAS  v5.10_stable-5-g83a0da5-dirty
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
intermcu_fbw.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Freek van Tienen <freek.v.tienen@gmail.com>
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  */
22 
27 #include "intermcu_fbw.h"
28 #include "pprzlink/intermcu_msg.h"
30 #include "subsystems/electrical.h"
31 #include "mcu_periph/uart.h"
33 
34 
36 
37 #include BOARD_CONFIG
38 #ifdef BOARD_PX4IO
39 #include "libopencm3/cm3/scb.h"
40 #include "led.h"
41 #include "mcu_periph/sys_time.h"
42 static uint8_t px4RebootSequence[] = {0x41, 0xd7, 0x32, 0x0a, 0x46, 0x39};
43 static uint8_t px4RebootSequenceCount = 0;
44 tid_t px4bl_tid;
45 #endif
46 
47 #if RADIO_CONTROL_NB_CHANNEL > 8
48 #undef RADIO_CONTROL_NB_CHANNEL
49 #define RADIO_CONTROL_NB_CHANNEL 8
50 INFO("InterMCU UART will only send 8 radio channels!")
51 #endif
52 
53 /* Main InterMCU structure */
54 struct intermcu_t intermcu = {
55  .device = (&((INTERMCU_LINK).device)),
56  .enabled = true,
57  .msg_available = false
58 };
59 uint8_t imcu_msg_buf[128] __attribute__((aligned));
60 
62 bool autopilot_motors_on = false;
63 static void intermcu_parse_msg(void (*commands_frame_handler)(void));
64 
65 #ifdef BOARD_PX4IO
66 static void checkPx4RebootCommand(unsigned char b);
67 #endif
68 
69 void intermcu_init(void)
70 {
71  pprz_transport_init(&intermcu.transport);
72 
73 #ifdef BOARD_PX4IO
74  px4bl_tid = sys_time_register_timer(10.0, NULL);
75 #endif
76 }
77 
79 {
80  /* Check for interMCU loss */
81  if (intermcu.time_since_last_frame >= INTERMCU_LOST_CNT) {
82  intermcu.status = INTERMCU_LOST;
83  } else {
84  intermcu.time_since_last_frame++;
85  }
86 }
87 
89 {
90  pprz_t values[9];
91 
96 #ifdef RADIO_MODE
98 #endif
99 #ifdef RADIO_KILL_SWITCH
101 #endif
102 
103 #if defined (RADIO_AUX1) && defined (RADIO_KILL_SWITCH)
104 #warning "RC AUX1 and KILL_SWITCH are on the same channel."
105 #endif
106 
107 #ifdef RADIO_AUX1
109 #endif
110 #ifdef RADIO_AUX2
112 #endif
113 #ifdef RADIO_AUX3
115 #endif
116 
117  pprz_msg_send_IMCU_RADIO_COMMANDS(&(intermcu.transport.trans_tx), intermcu.device,
118  INTERMCU_FBW, &fbw_mode, RADIO_CONTROL_NB_CHANNEL, values);
119 }
120 
122 {
123  // Send Status
124  pprz_msg_send_IMCU_FBW_STATUS(&(intermcu.transport.trans_tx), intermcu.device, INTERMCU_FBW,
127 }
128 
129 #pragma GCC diagnostic ignored "-Wcast-align"
130 static void intermcu_parse_msg(void (*commands_frame_handler)(void))
131 {
132  /* Parse the Inter MCU message */
133  uint8_t msg_id = imcu_msg_buf[1];
134  switch (msg_id) {
135  case DL_IMCU_COMMANDS: {
136  uint8_t i;
137  uint8_t size = DL_IMCU_COMMANDS_values_length(imcu_msg_buf);
138  int16_t *new_commands = DL_IMCU_COMMANDS_values(imcu_msg_buf);
139  intermcu.cmd_status |= DL_IMCU_COMMANDS_status(imcu_msg_buf);
140 
141  // Read the autopilot status and then clear it
142  autopilot_motors_on = INTERMCU_GET_CMD_STATUS(INTERMCU_CMD_MOTORS_ON);
144 
145  for (i = 0; i < size; i++) {
146  intermcu_commands[i] = new_commands[i];
147  }
148 
149  intermcu.status = INTERMCU_OK;
150  intermcu.time_since_last_frame = 0;
151  commands_frame_handler();
152  break;
153  }
154 #if defined(TELEMETRY_INTERMCU_DEV)
155  case DL_IMCU_TELEMETRY: {
156  uint8_t id = DL_IMCU_TELEMETRY_msg_id(imcu_msg_buf);
157  uint8_t size = DL_IMCU_TELEMETRY_msg_length(imcu_msg_buf);
158  uint8_t *msg = DL_IMCU_TELEMETRY_msg(imcu_msg_buf);
159  telemetry_intermcu_on_msg(id, msg, size);
160  break;
161  }
162 #endif
163 #if defined(SPEKTRUM_HAS_SOFT_BIND_PIN) //TODO: make subscribable module parser
164  case DL_IMCU_SPEKTRUM_SOFT_BIND:
166  break;
167 #endif
168 
169  default:
170  break;
171  }
172 }
173 #pragma GCC diagnostic pop
174 
175 void InterMcuEvent(void (*frame_handler)(void))
176 {
177  uint8_t i, c;
178 
179  // Check if there are messages in the device
180  if (intermcu.device->char_available(intermcu.device->periph)) {
181  while (intermcu.device->char_available(intermcu.device->periph) && !intermcu.transport.trans_rx.msg_received) {
182  c = intermcu.device->get_byte(intermcu.device->periph);
183  parse_pprz(&intermcu.transport, c);
184 
185 #ifdef BOARD_PX4IO
186  // TODO: create a hook
187  checkPx4RebootCommand(c);
188 #endif
189  }
190 
191  // If we have a message copy it
192  if (intermcu.transport.trans_rx.msg_received) {
193  for (i = 0; i < intermcu.transport.trans_rx.payload_len; i++) {
194  imcu_msg_buf[i] = intermcu.transport.trans_rx.payload[i];
195  }
196 
197  intermcu.msg_available = true;
198  intermcu.transport.trans_rx.msg_received = false;
199  }
200  }
201 
202  if (intermcu.msg_available) {
203  intermcu_parse_msg(frame_handler);
204  intermcu.msg_available = false;
205  }
206 }
207 
208 
209 /* SOME STUFF FOR PX4IO BOOTLOADER (TODO: move this code) */
210 #ifdef BOARD_PX4IO
211 static void checkPx4RebootCommand(uint8_t b)
212 {
213  if (intermcu.stable_px4_baud == CHANGING_BAUD && sys_time_check_and_ack_timer(px4bl_tid)) {
214  //to prevent a short intermcu comm loss, give some time to changing the baud
215  sys_time_cancel_timer(px4bl_tid);
216  intermcu.stable_px4_baud = PPRZ_BAUD;
217  } else if (intermcu.stable_px4_baud == PX4_BAUD) {
218 
219  if (sys_time_check_and_ack_timer(px4bl_tid)) {
220  //time out the possibility to reboot to the px4 bootloader, to prevent unwanted restarts during flight
221  sys_time_cancel_timer(px4bl_tid);
222  //for unknown reasons, 1500000 baud does not work reliably after prolonged times.
223  //I suspect a temperature related issue, combined with the fbw f1 crystal which is out of specs
224  //After a initial period on 1500000, revert to 230400
225  //We still start at 1500000 to remain compatible with original PX4 firmware. (which always runs at 1500000)
226  uart_periph_set_baudrate(intermcu.device->periph, B230400);
227  intermcu.stable_px4_baud = CHANGING_BAUD;
228  px4bl_tid = sys_time_register_timer(1.0, NULL);
229  return;
230  }
231 
232 #ifdef SYS_TIME_LED
233  LED_ON(SYS_TIME_LED);
234 #endif
235 
236  if (b == px4RebootSequence[px4RebootSequenceCount]) {
237  px4RebootSequenceCount++;
238  } else {
239  px4RebootSequenceCount = 0;
240  }
241 
242  if (px4RebootSequenceCount >= 6) { // 6 = length of rebootSequence + 1
243  px4RebootSequenceCount = 0; // should not be necessary...
244 
245  //send some magic back
246  //this is the same as the Pixhawk IO code would send
247  intermcu.device->put_byte(intermcu.device->periph, 0, 0x00);
248  intermcu.device->put_byte(intermcu.device->periph, 0, 0xe5);
249  intermcu.device->put_byte(intermcu.device->periph, 0, 0x32);
250  intermcu.device->put_byte(intermcu.device->periph, 0, 0x0a);
251  intermcu.device->put_byte(intermcu.device->periph, 0,
252  0x66); // dummy byte, seems to be necessary otherwise one byte is missing at the fmu side...
253 
254  while (((struct uart_periph *)(intermcu.device->periph))->tx_running) {
255  // tx_running is volatile now, so LED_TOGGLE not necessary anymore
256 #ifdef SYS_TIME_LED
257  LED_TOGGLE(SYS_TIME_LED);
258 #endif
259  }
260 
261 #ifdef SYS_TIME_LED
262  LED_OFF(SYS_TIME_LED);
263 #endif
264  scb_reset_system();
265  }
266  }
267 }
268 #endif
#define RADIO_AUX3
Definition: spektrum_arch.h:50
struct intermcu_t intermcu
Definition: intermcu_fbw.c:54
int32_t current
current in milliamps
Definition: electrical.h:49
void intermcu_send_status(uint8_t mode)
Definition: intermcu_fbw.c:121
bool autopilot_motors_on
Definition: intermcu_fbw.c:62
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
void uart_periph_set_baudrate(struct uart_periph *p, uint32_t baud)
Set baudrate.
Definition: uart_arch.c:838
#define INTERMCU_LOST_CNT
Definition: intermcu.h:38
uint8_t imcu_msg_buf[128]
The InterMCU message buffer.
Definition: intermcu_fbw.c:59
void InterMcuEvent(void(*frame_handler)(void))
Definition: intermcu_fbw.c:175
static void intermcu_parse_msg(void(*commands_frame_handler)(void))
Definition: intermcu_fbw.c:130
struct link_device * device
Device used for communication.
Definition: intermcu.h:69
#define RADIO_ROLL
Definition: spektrum_arch.h:43
#define INTERMCU_RADIO_AUX3
Definition: intermcu_fbw.h:48
#define RADIO_YAW
Definition: spektrum_arch.h:45
pprz_t intermcu_commands[COMMANDS_NB]
Definition: intermcu_fbw.c:61
uint8_t cmd_status
Command status information that is transfered (intermcu_cmd_status)
Definition: intermcu.h:75
uint8_t status
Definition: radio_control.h:53
void telemetry_intermcu_on_msg(uint8_t msg_id, uint8_t *msg, uint8_t size)
#define LED_OFF(i)
Definition: led_hw.h:50
Telemetry through InterMCU.
void sys_time_cancel_timer(tid_t id)
Cancel a system timer by id.
Definition: sys_time.c:60
int16_t pprz_t
Definition: paparazzi.h:6
#define RADIO_KILL
Definition: joby_9ch.h:35
enum intermcu_status status
Status of the INTERMCU.
Definition: intermcu.h:71
#define RADIO_AUX2
Definition: spektrum_arch.h:49
InterMCU communication is OK.
Definition: intermcu.h:45
#define INTERMCU_RADIO_PITCH
Definition: intermcu_fbw.h:42
#define INTERMCU_RADIO_MODE
Definition: intermcu_fbw.h:44
pprz_t values[RADIO_CONTROL_NB_CHANNEL]
Definition: radio_control.h:58
bool msg_available
If we have an InterMCU message.
Definition: intermcu.h:74
#define RADIO_AUX1
Definition: spektrum_arch.h:48
#define B230400
Definition: uart_arch.h:49
Rotorcraft Inter-MCU on FlyByWire.
bool enabled
If the InterMCU communication is enabled.
Definition: intermcu.h:73
#define INTERMCU_RADIO_ROLL
Definition: intermcu_fbw.h:41
No interMCU communication anymore.
Definition: intermcu.h:46
#define INTERMCU_RADIO_AUX1
Definition: intermcu_fbw.h:46
Interface for electrical status: supply voltage, current, battery status, etc.
Architecture independent timing functions.
The status of autopilot_motors_on.
Definition: intermcu.h:58
#define RADIO_PITCH
Definition: spektrum_arch.h:44
#define INTERMCU_RADIO_YAW
Definition: intermcu_fbw.h:43
UART peripheral.
Definition: uart.h:70
#define INTERMCU_GET_CMD_STATUS(_bit)
Definition: intermcu.h:65
signed short int16_t
Definition: types.h:17
int8_t tid_t
sys_time timer id type
Definition: sys_time.h:60
struct RadioControl radio_control
Definition: radio_control.c:30
#define RADIO_THROTTLE
Definition: spektrum_arch.h:42
struct pprz_transport transport
Transport over communication line (PPRZ)
Definition: intermcu.h:70
void intermcu_on_rc_frame(uint8_t fbw_mode)
Definition: intermcu_fbw.c:88
#define LED_TOGGLE(i)
Definition: led_hw.h:51
#define INTERMCU_RADIO_KILL_SWITCH
Definition: intermcu_fbw.h:45
#define RADIO_CONTROL_NB_CHANNEL
Definition: spektrum_arch.h:34
#define INTERMCU_RADIO_THROTTLE
Definition: intermcu_fbw.h:40
#define RADIO_MODE
Definition: spektrum_arch.h:59
#define INTERMCU_CLR_CMD_STATUS(_bit)
Definition: intermcu.h:64
uint8_t fbw_mode
Definition: main_fbw.c:63
#define INTERMCU_RADIO_AUX2
Definition: intermcu_fbw.h:47
unsigned char uint8_t
Definition: types.h:14
void intermcu_init(void)
Definition: intermcu_fbw.c:69
void received_spektrum_soft_bind(void)
uint8_t time_since_last_frame
Time since last frame.
Definition: intermcu.h:72
static bool sys_time_check_and_ack_timer(tid_t id)
Check if timer has elapsed.
Definition: sys_time.h:114
uint16_t vsupply
supply voltage in decivolts
Definition: electrical.h:48
#define INTERMCU_FBW
Definition: intermcu.h:35
arch independent LED (Light Emitting Diodes) API
#define LED_ON(i)
Definition: led_hw.h:49
struct Electrical electrical
Definition: electrical.c:65
uint8_t msg[10]
Buffer used for general comunication over SPI (out buffer)
void intermcu_periodic(void)
Definition: intermcu_fbw.c:78
tid_t sys_time_register_timer(float duration, sys_time_cb cb)
Register a new system timer.
Definition: sys_time.c:43
uint8_t frame_rate
Definition: radio_control.h:56