diff --git a/conf/firmwares/subsystems/fixedwing/intermcu_can.makefile b/conf/firmwares/subsystems/fixedwing/intermcu_can.makefile new file mode 100644 index 00000000000..f7927f9745b --- /dev/null +++ b/conf/firmwares/subsystems/fixedwing/intermcu_can.makefile @@ -0,0 +1,12 @@ +# Hey Emacs, this is a -*- makefile -*- + +# InterMCU type CAN + +ifneq ($(TARGET),sim) +$(TARGET).CFLAGS += -DINTER_MCU -DMCU_CAN_LINK +$(TARGET).srcs += link_mcu_can.c +$(TARGET).srcs += mcu_periph/can.c +$(TARGET).srcs += $(SRC_ARCH)/mcu_periph/can_arch.c +endif + +SEPARATE_FBW=1 diff --git a/sw/airborne/firmwares/fixedwing/main_ap.c b/sw/airborne/firmwares/fixedwing/main_ap.c index 5959b958fcf..d4baf211841 100644 --- a/sw/airborne/firmwares/fixedwing/main_ap.c +++ b/sw/airborne/firmwares/fixedwing/main_ap.c @@ -37,8 +37,8 @@ #include "firmwares/fixedwing/main_ap.h" #include "mcu.h" #include "mcu_periph/sys_time.h" - -#include "link_mcu_spi.h" +#include "inter_mcu.h" +#include "link_mcu.h" // Sensors #if USE_GPS @@ -213,7 +213,7 @@ void init_ap( void ) { ins_init(); /************* Links initialization ***************/ -#if defined MCU_SPI_LINK || defined MCU_UART_LINK +#if defined MCU_SPI_LINK || defined MCU_UART_LINK || defined MCU_CAN_LINK link_mcu_init(); #endif #if USE_AUDIO_TELEMETRY @@ -575,7 +575,7 @@ void attitude_loop( void ) { ap_state->commands[COMMAND_PITCH] = h_ctl_elevator_setpoint; -#if defined MCU_SPI_LINK || defined MCU_UART_LINK +#if defined MCU_SPI_LINK || defined MCU_UART_LINK || defined MCU_CAN_LINK link_mcu_send(); #elif defined INTER_MCU && defined SINGLE_MCU /**Directly set the flag indicating to FBW that shared buffer is available*/ diff --git a/sw/airborne/firmwares/fixedwing/main_fbw.c b/sw/airborne/firmwares/fixedwing/main_fbw.c index 0d0ec2e1758..37c94fd6ced 100644 --- a/sw/airborne/firmwares/fixedwing/main_fbw.c +++ b/sw/airborne/firmwares/fixedwing/main_fbw.c @@ -48,17 +48,10 @@ #include "subsystems/datalink/telemetry.h" #endif -#ifdef MCU_SPI_LINK -#include "link_mcu_spi.h" -#endif - -#ifdef MCU_UART_LINK -#include "link_mcu_usart.h" -#endif - uint8_t fbw_mode; #include "inter_mcu.h" +#include "link_mcu.h" #ifdef USE_NPS #include "nps_autopilot.h" @@ -130,8 +123,10 @@ void init_fbw( void ) { #ifdef INTER_MCU inter_mcu_init(); #endif -#ifdef MCU_SPI_LINK +#if defined MCU_SPI_LINK || defined MCU_CAN_LINK link_mcu_init(); +#endif +#ifdef MCU_SPI_LINK link_mcu_restart(); #endif @@ -317,6 +312,11 @@ void periodic_task_fbw( void ) { link_mcu_periodic_task(); #endif +#ifdef MCU_CAN_LINK + inter_mcu_fill_fbw_state(); + link_mcu_periodic_task(); +#endif + #if PERIODIC_TELEMETRY periodic_telemetry_send_Fbw(); #endif diff --git a/sw/airborne/inter_mcu.c b/sw/airborne/inter_mcu.c index aeb4134b3f8..0c62ae1e5d0 100644 --- a/sw/airborne/inter_mcu.c +++ b/sw/airborne/inter_mcu.c @@ -14,9 +14,13 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with paparazzi; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * along with paparazzi; see the file COPYING. If not, see + * . + */ + +/** + * @file inter_mcu.c + * Communication between fbw and ap processes. * */ @@ -28,7 +32,7 @@ static struct ap_state _ap_state; struct fbw_state* fbw_state = &_fbw_state; struct ap_state* ap_state = &_ap_state; #else /* SINGLE_MCU */ -#include "link_mcu_spi.h" +#include "link_mcu.h" struct fbw_state* fbw_state = &link_mcu_from_fbw_msg.payload.from_fbw; struct ap_state* ap_state = &link_mcu_from_ap_msg.payload.from_ap; #endif /* ! SINGLE_MCU */ diff --git a/sw/airborne/inter_mcu.h b/sw/airborne/inter_mcu.h index b26f6b7cf33..ef7f1e31835 100644 --- a/sw/airborne/inter_mcu.h +++ b/sw/airborne/inter_mcu.h @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * Copyright (C) 2003-2005 Pascal Brisset, Antoine Drouin * * This file is part of paparazzi. @@ -15,19 +14,20 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with paparazzi; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * + * along with paparazzi; see the file COPYING. If not, see + * . */ -/** \brief Communication between fbw and ap processes +/** + * @file inter_mcu.h + * Communication between fbw and ap processes. + * * This unit contains the data structure used to communicate between the * "fly by wire" process and the "autopilot" process. It must be linked once in a - * monoprocessor architecture, twice in a twin-processors (the historical - * Atmel AVRs mega8-mega128 one) architecture. In the latter case, the - * inter-mcu communication process (e.g. SPI) must fill and read these data structures. -*/ + * monoprocessor architecture, twice in a twin-processors architecture. + * In the latter case, the inter-mcu communication process (e.g. SPI) must fill and + * read these data structures. + */ #ifndef INTER_MCU_H #define INTER_MCU_H diff --git a/sw/airborne/link_mcu.h b/sw/airborne/link_mcu.h new file mode 100644 index 00000000000..8ceb91197bc --- /dev/null +++ b/sw/airborne/link_mcu.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2003-2014 The Paparazzi Team + * + * This file is part of paparazzi. + * + * paparazzi is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * paparazzi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with paparazzi; see the file COPYING. If not, see + * . + */ + +/** + * @file link_mcu.h + * Common transport functions for the communication between FBW and AP. + */ + +#ifndef LINK_MCU_H +#define LINK_MCU_H + +#ifdef MCU_SPI_LINK +#include "link_mcu_spi.h" +#elif defined MCU_UART_LINK +#include "link_mcu_usart.h" +#elif defined MCU_CAN_LINK +#include "link_mcu_can.h" +#endif + +#endif /* LINK_MCU_H */ diff --git a/sw/airborne/link_mcu_can.c b/sw/airborne/link_mcu_can.c new file mode 100644 index 00000000000..18808154920 --- /dev/null +++ b/sw/airborne/link_mcu_can.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2010-2012 The Paparazzi Team + * + * This file is part of paparazzi. + * + * paparazzi is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * paparazzi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "link_mcu_can.h" +#include "mcu_periph/can.h" +#include "led.h" + +#include "subsystems/commands.h" + + +////////////////////////////////////////////////////////////////////////////////////////////// +// INTERMCU CAN MESSAGES + +// Commands +#define MSG_INTERMCU_COMMAND_MASTER_ID 0x01 +#define MSG_INTERMCU_COMMAND_EXTRA_ID 0x02 +// Channels +#define MSG_INTERMCU_RADIO_LOW_ID 0x04 +#define MSG_INTERMCU_RADIO_HIGH_ID 0x05 +// Trim +#define MSG_INTERMCU_TRIM_ID 0x09 +// Status +#define MSG_INTERMCU_FBW_STATUS_ID 0x10 + + +union { + uint8_t data[8]; + pprz_t cmd[4]; +} imcu_cmd_mstr, imcu_cmd_ext, imcu_chan1, imcu_chan2, imcu_trim; + +#define INTERMCU_COMMAND(_intermcu_payload, nr) (pprz_t)((uint16_t)(*((uint8_t*)_intermcu_payload+0+(2*(nr)))|*((uint8_t*)_intermcu_payload+1+(2*(nr)))<<8)) + +////////////////////////////////////////////////////////////////////////////////////////////// +// READ MESSAGES + + +void link_mcu_on_can_msg(uint32_t id, uint8_t* data, int len); +void link_mcu_on_can_msg(uint32_t id, uint8_t* data, int len) +{ +#if COMMANDS_NB > 8 +#error "INTERMCU_CAN CAN ONLY SEND 4 OR 8 COMMANDS (packets of 8 bytes)" +#endif +#if RADIO_CONTROL_NB_CHANNEL > 8 +#warning "INTERMCU_CAN CAN ONLY SEND 8 RADIO CHANNELS: CHANNELS 9 and higher will not be sent" +#endif + if (len) {} //Remove compile warning + + if (id == MSG_INTERMCU_COMMAND_MASTER_ID) { + for (int i = 0; (i < 4) && (i < COMMANDS_NB); i++) { + ap_state->commands[i] = INTERMCU_COMMAND(data, i); + } +#ifdef LINK_MCU_LED + LED_TOGGLE(LINK_MCU_LED); +#endif + inter_mcu_received_ap = TRUE; + } + + if (id == MSG_INTERMCU_COMMAND_EXTRA_ID) { + for (int i = 0; (i < 4) && (i < (COMMANDS_NB - 4)); i++) { + ap_state->commands[4 + i] = INTERMCU_COMMAND(data, i); + } + } + + + if (id == MSG_INTERMCU_TRIM_ID) { + ap_state->command_roll_trim = ((pprz_t) INTERMCU_COMMAND(data, 0)); + ap_state->command_pitch_trim = ((pprz_t) INTERMCU_COMMAND(data, 1)); + } + + if (id == MSG_INTERMCU_RADIO_LOW_ID) { + for (int i = 0; (i < 4) && (i < RADIO_CONTROL_NB_CHANNEL); i++) { + fbw_state->channels[i] = ((pprz_t)INTERMCU_COMMAND(data, i)); + } + } + + if (id == MSG_INTERMCU_RADIO_HIGH_ID) { + for (int i = 0; (i < 4) && (i < (RADIO_CONTROL_NB_CHANNEL - 4)); i++) { + fbw_state->channels[4 + i] = ((pprz_t)INTERMCU_COMMAND(data, i)); + } + } + + if ((id == MSG_INTERMCU_FBW_STATUS_ID) && (len == 5)) { + fbw_state->ppm_cpt = data[0]; + fbw_state->status = data[1]; + fbw_state->nb_err = data[2]; + fbw_state->vsupply = data[3] + (data[4] << 8); + fbw_state->current = 0; + +#ifdef LINK_MCU_LED + LED_TOGGLE(LINK_MCU_LED); +#endif + inter_mcu_received_fbw = TRUE; + } +} + +////////////////////////////////////////////////////////////////////////////////////////////// +// SEND MESSAGES + + +#ifdef AP +void link_mcu_send(void) +{ + for (int i = 0; (i < COMMANDS_NB) && (i < 4); i++) { + imcu_cmd_mstr.cmd[i] = ap_state->commands[i]; + } + for (int i = 0; (i < (COMMANDS_NB - 4)) && (i < 4); i++) { + imcu_cmd_ext.cmd[i] = ap_state->commands[4 + i]; + } + + ppz_can_transmit(MSG_INTERMCU_COMMAND_MASTER_ID, imcu_cmd_mstr.data, 8); + ppz_can_transmit(MSG_INTERMCU_COMMAND_EXTRA_ID, imcu_cmd_ext.data, 8); + + imcu_trim.cmd[0] = ap_state->command_roll_trim; + imcu_trim.cmd[1] = ap_state->command_pitch_trim; + imcu_trim.cmd[2] = ap_state->command_yaw_trim; + RunOnceEvery(6, ppz_can_transmit(MSG_INTERMCU_TRIM_ID, imcu_trim.data, 6)); +} +#endif + +#ifdef FBW +void link_mcu_periodic_task(void) +{ + // Import: Prepare the next message for AP + inter_mcu_fill_fbw_state(); + + // Transmit Status + uint8_t intermcu_tx_buff[8]; + intermcu_tx_buff[0] = fbw_state->ppm_cpt; + intermcu_tx_buff[1] = fbw_state->status; + intermcu_tx_buff[2] = fbw_state->nb_err; + intermcu_tx_buff[3] = (uint8_t) fbw_state->vsupply; + intermcu_tx_buff[4] = (uint8_t)((fbw_state->vsupply & 0xff00) >> 8); + ppz_can_transmit(MSG_INTERMCU_FBW_STATUS_ID, intermcu_tx_buff, 5); + +#if defined RADIO_CONTROL || RADIO_CONTROL_AUTO1 + // Copy the CHANNELS to the 2 CAN buffers + for (int i = 0; (i < RADIO_CONTROL_NB_CHANNEL) && (i < 4); i++) { + imcu_chan1.cmd[i] = fbw_state->channels[i]; + } + for (int i = 0; (i < (RADIO_CONTROL_NB_CHANNEL - 4)) && (i < 4); i++) { + imcu_chan2.cmd[i] = fbw_state->channels[4 + i]; + } + + if (bit_is_set(fbw_state->status, RC_OK)) { + ppz_can_transmit(MSG_INTERMCU_RADIO_LOW_ID, imcu_chan1.data, 8); + ppz_can_transmit(MSG_INTERMCU_RADIO_HIGH_ID, imcu_chan2.data, 8); + } +#endif +} +#endif + +////////////////////////////////////////////////////////////////////////////////////////////// +// STATUS LOGIC AND TELEMETRY +// Downlink FBW status from AP + +struct link_mcu_msg link_mcu_from_ap_msg; +struct link_mcu_msg link_mcu_from_fbw_msg; + + +#ifdef AP +#include "subsystems/datalink/telemetry.h" + +#define RC_OK 0 +#define RC_LOST 1 +#define RC_REALLY_LOST 2 + + +static void send_commands(void) +{ + DOWNLINK_SEND_COMMANDS(DefaultChannel, DefaultDevice, COMMANDS_NB, ap_state->commands); +} + +static void send_fbw_status(void) +{ + uint8_t rc_status = 0; + uint8_t fbw_status = 0; + if (bit_is_set(fbw_state->status, STATUS_MODE_AUTO)) { + fbw_status = FBW_MODE_AUTO; + } + if (bit_is_set(fbw_state->status, STATUS_MODE_FAILSAFE)) { + fbw_status = FBW_MODE_FAILSAFE; + } + if (bit_is_set(fbw_state->status, STATUS_RADIO_REALLY_LOST)) { + rc_status = RC_REALLY_LOST; + } else if (bit_is_set(fbw_state->status, RC_OK)) { + rc_status = RC_OK; + } else { + rc_status = RC_LOST; + } + DOWNLINK_SEND_FBW_STATUS(DefaultChannel, DefaultDevice, + &(rc_status), &(fbw_state->ppm_cpt), &(fbw_status), &(fbw_state->vsupply), &(fbw_state->current)); +} +#endif + +void link_mcu_init(void) +{ + ppz_can_init(link_mcu_on_can_msg); + +#ifdef AP +#if PERIODIC_TELEMETRY + // If FBW has not telemetry, then AP can send some of the info + register_periodic_telemetry(DefaultPeriodic, "COMMANDS", send_commands); + register_periodic_telemetry(DefaultPeriodic, "FBW_STATUS", send_fbw_status); +#endif +#endif +} + +void link_mcu_event_task(void) +{ + // No event function: CAN_RX_IRQ is called on reception of data +} diff --git a/sw/airborne/link_mcu_can.h b/sw/airborne/link_mcu_can.h new file mode 100644 index 00000000000..6cab3833d76 --- /dev/null +++ b/sw/airborne/link_mcu_can.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010-2012 The Paparazzi Team + * + * This file is part of paparazzi. + * + * paparazzi is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * paparazzi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with paparazzi; see the file COPYING. If not, see + * . + */ + +/** + * @file link_mcu_can.h + * Transport for the communication between FBW and AP via CAN. + * + */ + +#ifndef LINK_MCU_CAN_H +#define LINK_MCU_CAN_H + +#include +#include "inter_mcu.h" + +struct link_mcu_msg { + union { + struct fbw_state from_fbw; + struct ap_state from_ap; + } payload; +}; + +extern struct link_mcu_msg link_mcu_from_ap_msg; +extern struct link_mcu_msg link_mcu_from_fbw_msg; + +extern bool_t link_mcu_received; + +extern void link_mcu_send(void); +extern void link_mcu_init(void); +extern void link_mcu_event_task(void); +extern void link_mcu_periodic_task(void); + + +#endif /* LINK_MCU_CAN_H */ diff --git a/sw/airborne/link_mcu_spi.h b/sw/airborne/link_mcu_spi.h index 118efc8f209..4b61e493a07 100644 --- a/sw/airborne/link_mcu_spi.h +++ b/sw/airborne/link_mcu_spi.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2006 Pascal Brisset, Antoine Drouin + * Copyright (C) 2003-2005 Pascal Brisset, Antoine Drouin * * This file is part of paparazzi. * @@ -14,18 +14,18 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with paparazzi; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * + * along with paparazzi; see the file COPYING. If not, see + * . */ -/** \brief Transport for the communication between FBW and AP in a bi-process - architecture. Essentially adds a checksum to the inter_mcu structure. +/** + * @file link_mcu_spi.h + * Transport for the communication between FBW and AP via SPI. + * */ -#ifndef LINK_MCU_H -#define LINK_MCU_H +#ifndef LINK_MCU_SPI_H +#define LINK_MCU_SPI_H #include #include "inter_mcu.h" @@ -64,4 +64,4 @@ extern uint8_t link_mcu_fbw_nb_err; extern void link_mcu_send(void); #endif /* AP */ -#endif +#endif /* LINK_MCU_SPI_H */ diff --git a/sw/airborne/link_mcu_usart.h b/sw/airborne/link_mcu_usart.h index 775ef90008e..0140c4146ac 100644 --- a/sw/airborne/link_mcu_usart.h +++ b/sw/airborne/link_mcu_usart.h @@ -14,17 +14,18 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with paparazzi; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * + * along with paparazzi; see the file COPYING. If not, see + * . */ -/** \brief Transport for the communication between FBW and AP via UART. +/** + * @file link_mcu_usart.h + * Transport for the communication between FBW and AP via UART. + * */ -#ifndef LINK_MCU_H -#define LINK_MCU_H +#ifndef LINK_MCU_USART_H +#define LINK_MCU_USART_H #include #include "inter_mcu.h" @@ -47,4 +48,4 @@ extern void link_mcu_event_task( void ); extern void link_mcu_periodic_task( void ); -#endif +#endif /* LINK_MCU_USART_H */