2012-08-04 15:12:36 -07:00
/****************************************************************************
*
2014-01-24 17:34:42 +01:00
* Copyright ( c ) 2012 - 2014 PX4 Development Team . All rights reserved .
2012-08-04 15:12:36 -07:00
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
*
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in
* the documentation and / or other materials provided with the
* distribution .
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING ,
* BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS
* OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
* LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
2012-12-29 12:58:41 -08:00
* @ file mixer . cpp
2012-11-07 14:56:03 -08:00
*
* Control channel input / output mixer and failsafe .
2012-08-04 15:12:36 -07:00
*/
# include <nuttx/config.h>
2013-03-09 12:27:29 +01:00
# include <syslog.h>
2012-08-04 15:12:36 -07:00
# include <sys/types.h>
# include <stdbool.h>
2012-11-05 00:55:22 -08:00
# include <string.h>
2012-12-16 15:31:44 +01:00
2012-11-01 23:42:36 -07:00
# include <drivers/drv_pwm_output.h>
2012-12-16 15:31:44 +01:00
# include <drivers/drv_hrt.h>
2012-08-04 15:12:36 -07:00
2013-10-08 17:03:57 +02:00
# include <systemlib/pwm_limit/pwm_limit.h>
2012-12-29 12:58:41 -08:00
# include <systemlib/mixer/mixer.h>
2012-08-04 15:12:36 -07:00
2012-12-29 12:58:41 -08:00
extern " C " {
2012-12-30 01:17:19 -08:00
//#define DEBUG
2012-11-01 23:42:36 -07:00
# include "px4io.h"
2012-12-29 12:58:41 -08:00
}
2012-08-04 15:12:36 -07:00
/*
2012-12-15 23:28:03 +01:00
* Maximum interval in us before FMU signal is considered lost
2012-08-04 15:12:36 -07:00
*/
2014-08-28 21:39:33 +02:00
# define FMU_INPUT_DROP_LIMIT_US 500000
2012-08-04 15:12:36 -07:00
2013-01-05 22:13:12 +01:00
/* XXX need to move the RC_CHANNEL_FUNCTION out of rc_channels.h and into systemlib */
# define ROLL 0
# define PITCH 1
# define YAW 2
# define THROTTLE 3
2013-01-11 07:35:40 +01:00
# define OVERRIDE 4
2013-01-05 22:13:12 +01:00
2012-08-04 15:12:36 -07:00
/* current servo arm/disarm state */
2013-01-14 01:11:29 -08:00
static bool mixer_servos_armed = false ;
2013-06-19 22:59:40 +02:00
static bool should_arm = false ;
static bool should_always_enable_pwm = false ;
2014-01-24 17:34:42 +01:00
static volatile bool in_mixer = false ;
2012-08-04 15:12:36 -07:00
2012-12-29 12:58:41 -08:00
/* selected control values and count for mixing */
2013-01-13 18:57:27 -08:00
enum mixer_source {
2013-01-15 22:22:15 -08:00
MIX_NONE ,
2013-01-13 18:57:27 -08:00
MIX_FMU ,
MIX_OVERRIDE ,
2013-12-11 16:38:11 +01:00
MIX_FAILSAFE ,
MIX_OVERRIDE_FMU_OK
2013-01-13 18:57:27 -08:00
} ;
static mixer_source source ;
2013-01-05 15:46:26 +01:00
2012-12-29 12:58:41 -08:00
static int mixer_callback ( uintptr_t handle ,
2012-12-29 16:01:24 -08:00
uint8_t control_group ,
uint8_t control_index ,
float & control ) ;
2012-12-29 12:58:41 -08:00
static MixerGroup mixer_group ( mixer_callback , 0 ) ;
2012-08-04 15:12:36 -07:00
2013-05-29 17:07:26 +02:00
/* Set the failsafe values of all mixed channels (based on zero throttle, controls centered) */
static void mixer_set_failsafe ( ) ;
2012-11-30 00:02:47 -08:00
void
mixer_tick ( void )
2012-08-04 15:12:36 -07:00
{
2014-01-24 17:34:42 +01:00
2012-12-23 17:20:53 -08:00
/* check that we are receiving fresh data from the FMU */
2014-08-28 21:39:33 +02:00
if ( ( system_state . fmu_data_received_time = = 0 ) | |
hrt_elapsed_time ( & system_state . fmu_data_received_time ) > FMU_INPUT_DROP_LIMIT_US ) {
2013-01-13 18:57:27 -08:00
2013-01-14 01:11:29 -08:00
/* too long without FMU input, time to go to failsafe */
2013-01-26 16:37:35 -08:00
if ( r_status_flags & PX4IO_P_STATUS_FLAGS_FMU_OK ) {
2013-03-15 15:24:52 -07:00
isr_debug ( 1 , " AP RX timeout " ) ;
2013-01-26 16:37:35 -08:00
}
2013-06-07 19:41:41 +02:00
r_status_flags & = ~ ( PX4IO_P_STATUS_FLAGS_FMU_OK ) ;
2013-01-13 18:57:27 -08:00
r_status_alarms | = PX4IO_P_STATUS_ALARMS_FMU_LOST ;
2013-02-24 15:31:40 -08:00
} else {
r_status_flags | = PX4IO_P_STATUS_FLAGS_FMU_OK ;
2014-08-28 21:39:33 +02:00
/* this flag is never cleared once OK */
r_status_flags | = PX4IO_P_STATUS_FLAGS_FMU_INITIALIZED ;
2012-12-23 17:20:53 -08:00
}
2014-07-18 11:18:32 +02:00
/* default to failsafe mixing - it will be forced below if flag is set */
2013-01-15 22:22:15 -08:00
source = MIX_FAILSAFE ;
2012-08-04 15:12:36 -07:00
/*
2013-01-13 18:57:27 -08:00
* Decide which set of controls we ' re using .
2012-08-04 15:12:36 -07:00
*/
2013-05-28 17:46:24 +02:00
2013-06-07 19:41:41 +02:00
/* do not mix if RAW_PWM mode is on and FMU is good */
2013-05-28 17:46:24 +02:00
if ( ( r_status_flags & PX4IO_P_STATUS_FLAGS_RAW_PWM ) & &
2013-06-07 19:41:41 +02:00
( r_status_flags & PX4IO_P_STATUS_FLAGS_FMU_OK ) ) {
2013-01-15 00:41:13 -08:00
2013-06-07 19:41:41 +02:00
/* don't actually mix anything - we already have raw PWM values */
2013-01-15 22:22:15 -08:00
source = MIX_NONE ;
2013-01-15 00:41:13 -08:00
2013-01-15 22:22:15 -08:00
} else {
if ( ! ( r_status_flags & PX4IO_P_STATUS_FLAGS_OVERRIDE ) & &
2013-05-28 17:46:24 +02:00
( r_status_flags & PX4IO_P_STATUS_FLAGS_FMU_OK ) & &
2013-01-15 22:22:15 -08:00
( r_status_flags & PX4IO_P_STATUS_FLAGS_MIXER_OK ) ) {
2013-01-15 00:41:13 -08:00
/* mix from FMU controls */
source = MIX_FMU ;
}
2013-01-15 22:22:15 -08:00
if ( ( r_status_flags & PX4IO_P_STATUS_FLAGS_OVERRIDE ) & &
2013-03-09 11:03:06 +01:00
( r_status_flags & PX4IO_P_STATUS_FLAGS_RC_OK ) & &
2013-08-21 11:17:29 +02:00
( r_status_flags & PX4IO_P_STATUS_FLAGS_MIXER_OK ) & &
2013-12-11 16:38:11 +01:00
! ( r_setup_arming & PX4IO_P_SETUP_ARMING_RC_HANDLING_DISABLED ) & &
2014-08-27 10:46:10 +02:00
! ( r_status_flags & PX4IO_P_STATUS_FLAGS_FMU_OK ) & &
/* do not enter manual override if we asked for termination failsafe and FMU is lost */
! ( r_setup_arming & PX4IO_P_SETUP_ARMING_TERMINATION_FAILSAFE ) ) {
2013-01-15 22:22:15 -08:00
/* if allowed, mix from RC inputs directly */
source = MIX_OVERRIDE ;
2013-12-11 16:38:11 +01:00
} else if ( ( r_status_flags & PX4IO_P_STATUS_FLAGS_OVERRIDE ) & &
( r_status_flags & PX4IO_P_STATUS_FLAGS_RC_OK ) & &
( r_status_flags & PX4IO_P_STATUS_FLAGS_MIXER_OK ) & &
! ( r_setup_arming & PX4IO_P_SETUP_ARMING_RC_HANDLING_DISABLED ) & &
( r_status_flags & PX4IO_P_STATUS_FLAGS_FMU_OK ) ) {
/* if allowed, mix from RC inputs directly up to available rc channels */
source = MIX_OVERRIDE_FMU_OK ;
2013-01-15 22:22:15 -08:00
}
}
2014-08-28 21:39:33 +02:00
/*
* Decide whether the servos should be armed right now .
*
* We must be armed , and we must have a PWM source ; either raw from
* FMU or from the mixer .
*
*/
should_arm = (
/* IO initialised without error */ ( r_status_flags & PX4IO_P_STATUS_FLAGS_INIT_OK )
/* and IO is armed */ & & ( r_status_flags & PX4IO_P_STATUS_FLAGS_SAFETY_OFF )
/* and FMU is armed */ & & (
( ( r_setup_arming & PX4IO_P_SETUP_ARMING_FMU_ARMED )
/* and there is valid input via or mixer */ & & ( r_status_flags & PX4IO_P_STATUS_FLAGS_MIXER_OK ) )
/* or direct PWM is set */ | | ( r_status_flags & PX4IO_P_STATUS_FLAGS_RAW_PWM )
/* or failsafe was set manually */ | | ( ( r_setup_arming & PX4IO_P_SETUP_ARMING_FAILSAFE_CUSTOM ) & & ! ( r_status_flags & PX4IO_P_STATUS_FLAGS_FMU_OK ) )
)
) ;
should_always_enable_pwm = ( r_setup_arming & PX4IO_P_SETUP_ARMING_ALWAYS_PWM_ENABLE )
& & ( r_status_flags & PX4IO_P_STATUS_FLAGS_INIT_OK )
& & ( r_status_flags & PX4IO_P_STATUS_FLAGS_FMU_OK ) ;
2014-08-27 08:00:12 +02:00
/*
* Check if failsafe termination is set - if yes ,
* set the force failsafe flag once entering the first
* failsafe condition .
*/
2014-08-28 21:39:33 +02:00
if ( /* if we have requested flight termination style failsafe (noreturn) */
( r_setup_arming & PX4IO_P_SETUP_ARMING_TERMINATION_FAILSAFE ) & &
/* and we ended up in a failsafe condition */
2014-08-28 20:36:59 +02:00
( source = = MIX_FAILSAFE ) & &
2014-08-28 21:39:33 +02:00
/* and we should be armed, so we intended to provide outputs */
should_arm & &
/* and FMU is initialized */
( r_status_flags & PX4IO_P_STATUS_FLAGS_FMU_INITIALIZED ) ) {
2014-08-27 08:00:12 +02:00
r_setup_arming | = PX4IO_P_SETUP_ARMING_FORCE_FAILSAFE ;
}
2014-07-18 11:18:32 +02:00
/*
* Check if we should force failsafe - and do it if we have to
*/
if ( r_setup_arming & PX4IO_P_SETUP_ARMING_FORCE_FAILSAFE ) {
source = MIX_FAILSAFE ;
}
2013-05-28 17:46:24 +02:00
/*
* Set failsafe status flag depending on mixing source
*/
if ( source = = MIX_FAILSAFE ) {
r_status_flags | = PX4IO_P_STATUS_FLAGS_FAILSAFE ;
} else {
r_status_flags & = ~ ( PX4IO_P_STATUS_FLAGS_FAILSAFE ) ;
}
2013-01-15 22:22:15 -08:00
/*
* Run the mixers .
*/
2013-01-25 22:58:33 -08:00
if ( source = = MIX_FAILSAFE ) {
/* copy failsafe values to the servo outputs */
2013-07-06 23:59:35 -07:00
for ( unsigned i = 0 ; i < PX4IO_SERVO_COUNT ; i + + ) {
2013-01-25 22:58:33 -08:00
r_page_servos [ i ] = r_page_servo_failsafe [ i ] ;
2013-05-28 17:46:24 +02:00
/* safe actuators for FMU feedback */
2013-11-15 11:32:05 +04:00
r_page_actuators [ i ] = FLOAT_TO_REG ( ( r_page_servos [ i ] - 1500 ) / 600.0f ) ;
2013-05-28 17:46:24 +02:00
}
2014-01-24 17:34:42 +01:00
} else if ( source ! = MIX_NONE & & ( r_status_flags & PX4IO_P_STATUS_FLAGS_MIXER_OK ) ) {
2013-01-15 22:22:15 -08:00
2013-07-06 23:59:35 -07:00
float outputs [ PX4IO_SERVO_COUNT ] ;
2013-01-15 22:22:15 -08:00
unsigned mixed ;
/* mix */
2014-01-24 17:34:42 +01:00
/* poor mans mutex */
in_mixer = true ;
2013-07-06 23:59:35 -07:00
mixed = mixer_group . mix ( & outputs [ 0 ] , PX4IO_SERVO_COUNT ) ;
2014-01-24 17:34:42 +01:00
in_mixer = false ;
2013-01-15 22:22:15 -08:00
2014-05-23 20:23:33 +02:00
/* the pwm limit call takes care of out of band errors */
2013-10-11 10:19:50 +02:00
pwm_limit_calc ( should_arm , mixed , r_page_servo_disarmed , r_page_servo_control_min , r_page_servo_control_max , outputs , r_page_servos , & pwm_limit ) ;
2013-10-08 17:03:57 +02:00
2013-07-06 23:59:35 -07:00
for ( unsigned i = mixed ; i < PX4IO_SERVO_COUNT ; i + + )
2013-01-15 22:22:15 -08:00
r_page_servos [ i ] = 0 ;
2013-11-15 11:32:05 +04:00
for ( unsigned i = 0 ; i < PX4IO_SERVO_COUNT ; i + + ) {
r_page_actuators [ i ] = FLOAT_TO_REG ( outputs [ i ] ) ;
}
2013-01-13 18:57:27 -08:00
}
2014-01-16 10:56:15 +01:00
/* set arming */
bool needs_to_arm = ( should_arm | | should_always_enable_pwm ) ;
/* check any conditions that prevent arming */
if ( r_setup_arming & PX4IO_P_SETUP_ARMING_LOCKDOWN ) {
needs_to_arm = false ;
}
if ( ! should_arm & & ! should_always_enable_pwm ) {
needs_to_arm = false ;
}
if ( needs_to_arm & & ! mixer_servos_armed ) {
2012-08-04 15:12:36 -07:00
/* need to arm, but not armed */
2012-11-01 23:42:36 -07:00
up_pwm_servo_arm ( true ) ;
2012-08-04 15:12:36 -07:00
mixer_servos_armed = true ;
2013-06-12 12:30:42 +02:00
r_status_flags | = PX4IO_P_STATUS_FLAGS_OUTPUTS_ARMED ;
2013-06-19 22:59:40 +02:00
isr_debug ( 5 , " > PWM enabled " ) ;
2012-08-04 15:12:36 -07:00
2014-01-16 10:56:15 +01:00
} else if ( ! needs_to_arm & & mixer_servos_armed ) {
2012-11-01 23:42:36 -07:00
/* armed but need to disarm */
up_pwm_servo_arm ( false ) ;
2012-08-04 15:12:36 -07:00
mixer_servos_armed = false ;
2013-06-12 12:30:42 +02:00
r_status_flags & = ~ ( PX4IO_P_STATUS_FLAGS_OUTPUTS_ARMED ) ;
2013-06-19 22:59:40 +02:00
isr_debug ( 5 , " > PWM disabled " ) ;
2012-08-04 15:12:36 -07:00
}
2013-01-26 16:37:35 -08:00
2013-06-19 22:59:40 +02:00
if ( mixer_servos_armed & & should_arm ) {
2013-01-26 16:37:35 -08:00
/* update the servo outputs. */
2013-07-06 23:59:35 -07:00
for ( unsigned i = 0 ; i < PX4IO_SERVO_COUNT ; i + + )
2013-01-26 16:37:35 -08:00
up_pwm_servo_set ( i , r_page_servos [ i ] ) ;
2013-06-19 22:59:40 +02:00
2014-02-12 08:13:53 +01:00
/* set S.BUS1 or S.BUS2 outputs */
2014-02-13 08:22:05 +01:00
if ( r_setup_features & PX4IO_P_SETUP_FEATURES_SBUS2_OUT ) {
2014-02-12 08:13:53 +01:00
sbus2_output ( r_page_servos , PX4IO_SERVO_COUNT ) ;
2014-02-13 08:22:05 +01:00
} else if ( r_setup_features & PX4IO_P_SETUP_FEATURES_SBUS1_OUT ) {
sbus1_output ( r_page_servos , PX4IO_SERVO_COUNT ) ;
}
2014-02-12 08:13:53 +01:00
2013-06-19 22:59:40 +02:00
} else if ( mixer_servos_armed & & should_always_enable_pwm ) {
2013-10-07 16:24:49 +02:00
/* set the disarmed servo outputs. */
2013-08-15 14:04:46 +02:00
for ( unsigned i = 0 ; i < PX4IO_SERVO_COUNT ; i + + )
2013-10-07 16:24:49 +02:00
up_pwm_servo_set ( i , r_page_servo_disarmed [ i ] ) ;
2014-02-12 08:13:53 +01:00
/* set S.BUS1 or S.BUS2 outputs */
if ( r_setup_features & PX4IO_P_SETUP_FEATURES_SBUS1_OUT )
sbus1_output ( r_page_servos , PX4IO_SERVO_COUNT ) ;
if ( r_setup_features & PX4IO_P_SETUP_FEATURES_SBUS2_OUT )
sbus2_output ( r_page_servos , PX4IO_SERVO_COUNT ) ;
2013-01-26 16:37:35 -08:00
}
2012-08-04 15:12:36 -07:00
}
2012-12-29 12:58:41 -08:00
static int
mixer_callback ( uintptr_t handle ,
uint8_t control_group ,
uint8_t control_index ,
float & control )
2012-08-04 15:12:36 -07:00
{
2014-03-05 00:01:27 +04:00
if ( control_group > = PX4IO_CONTROL_GROUPS )
2012-12-29 12:58:41 -08:00
return - 1 ;
2013-01-13 18:57:27 -08:00
switch ( source ) {
case MIX_FMU :
2013-12-11 16:38:11 +01:00
if ( control_index < PX4IO_CONTROL_CHANNELS & & control_group < PX4IO_CONTROL_GROUPS ) {
2013-12-08 11:25:45 +01:00
control = REG_TO_FLOAT ( r_page_controls [ CONTROL_PAGE_INDEX ( control_group , control_index ) ] ) ;
2013-01-13 18:57:27 -08:00
break ;
}
return - 1 ;
case MIX_OVERRIDE :
2013-12-11 16:57:19 +01:00
if ( r_page_rc_input [ PX4IO_P_RC_VALID ] & ( 1 < < CONTROL_PAGE_INDEX ( control_group , control_index ) ) ) {
2013-01-13 18:57:27 -08:00
control = REG_TO_FLOAT ( r_page_rc_input [ PX4IO_P_RC_BASE + control_index ] ) ;
break ;
}
return - 1 ;
2013-12-11 16:38:11 +01:00
case MIX_OVERRIDE_FMU_OK :
/* FMU is ok but we are in override mode, use direct rc control for the available rc channels. The remaining channels are still controlled by the fmu */
2013-12-11 16:57:19 +01:00
if ( r_page_rc_input [ PX4IO_P_RC_VALID ] & ( 1 < < CONTROL_PAGE_INDEX ( control_group , control_index ) ) ) {
2013-12-11 16:38:11 +01:00
control = REG_TO_FLOAT ( r_page_rc_input [ PX4IO_P_RC_BASE + control_index ] ) ;
break ;
} else if ( control_index < PX4IO_CONTROL_CHANNELS & & control_group < PX4IO_CONTROL_GROUPS ) {
control = REG_TO_FLOAT ( r_page_controls [ CONTROL_PAGE_INDEX ( control_group , control_index ) ] ) ;
break ;
}
return - 1 ;
2013-01-13 18:57:27 -08:00
case MIX_FAILSAFE :
2013-01-15 22:22:15 -08:00
case MIX_NONE :
2013-05-29 17:07:26 +02:00
control = 0.0f ;
2013-01-13 18:57:27 -08:00
return - 1 ;
2013-01-06 14:43:37 +01:00
}
2012-12-29 12:58:41 -08:00
return 0 ;
2012-11-05 00:55:22 -08:00
}
2012-12-29 12:58:41 -08:00
2013-01-15 23:01:04 -08:00
/*
* XXX error handling here should be more aggressive ; currently it is
* possible to get STATUS_FLAGS_MIXER_OK set even though the mixer has
* not loaded faithfully .
*/
2013-01-13 18:57:27 -08:00
static char mixer_text [ 256 ] ; /* large enough for one mixer */
2012-12-30 01:17:19 -08:00
static unsigned mixer_text_length = 0 ;
2014-01-24 17:34:42 +01:00
int
2012-12-29 12:58:41 -08:00
mixer_handle_text ( const void * buffer , size_t length )
{
2013-09-02 17:55:27 +02:00
/* do not allow a mixer change while safety off */
if ( ( r_status_flags & PX4IO_P_STATUS_FLAGS_SAFETY_OFF ) ) {
2014-01-24 17:34:42 +01:00
return 1 ;
}
/* abort if we're in the mixer */
if ( in_mixer ) {
return 1 ;
2013-03-07 19:47:43 +01:00
}
2012-12-29 12:58:41 -08:00
px4io_mixdata * msg = ( px4io_mixdata * ) buffer ;
2012-12-29 16:01:24 -08:00
2013-02-23 12:02:00 +01:00
isr_debug ( 2 , " mix txt %u " , length ) ;
2012-12-30 01:17:19 -08:00
2012-12-29 12:58:41 -08:00
if ( length < sizeof ( px4io_mixdata ) )
2014-01-24 17:34:42 +01:00
return 0 ;
2012-12-29 12:58:41 -08:00
unsigned text_length = length - sizeof ( px4io_mixdata ) ;
switch ( msg - > action ) {
case F2I_MIXER_ACTION_RESET :
2013-02-20 12:19:03 +01:00
isr_debug ( 2 , " reset " ) ;
2013-03-07 19:47:43 +01:00
/* FIRST mark the mixer as invalid */
r_status_flags & = ~ PX4IO_P_STATUS_FLAGS_MIXER_OK ;
/* THEN actually delete it */
2012-12-29 12:58:41 -08:00
mixer_group . reset ( ) ;
mixer_text_length = 0 ;
2012-12-29 16:01:24 -08:00
2012-12-29 12:58:41 -08:00
/* FALLTHROUGH */
case F2I_MIXER_ACTION_APPEND :
2013-02-20 12:19:03 +01:00
isr_debug ( 2 , " append %d " , length ) ;
2012-12-29 16:01:24 -08:00
2014-01-24 17:34:42 +01:00
/* disable mixing during the update */
r_status_flags & = ~ PX4IO_P_STATUS_FLAGS_MIXER_OK ;
2013-06-07 10:34:55 +02:00
/* check for overflow - this would be really fatal */
2013-01-15 22:22:15 -08:00
if ( ( mixer_text_length + text_length + 1 ) > sizeof ( mixer_text ) ) {
r_status_flags & = ~ PX4IO_P_STATUS_FLAGS_MIXER_OK ;
2014-01-24 17:34:42 +01:00
return 0 ;
2013-01-15 22:22:15 -08:00
}
2012-12-29 12:58:41 -08:00
2014-01-24 17:34:42 +01:00
/* append mixer text and nul-terminate, guard against overflow */
2012-12-29 12:58:41 -08:00
memcpy ( & mixer_text [ mixer_text_length ] , msg - > text , text_length ) ;
mixer_text_length + = text_length ;
mixer_text [ mixer_text_length ] = ' \0 ' ;
2013-02-20 12:19:03 +01:00
isr_debug ( 2 , " buflen %u " , mixer_text_length ) ;
2012-12-29 12:58:41 -08:00
/* process the text buffer, adding new mixers as their descriptions can be parsed */
2012-12-30 01:17:19 -08:00
unsigned resid = mixer_text_length ;
mixer_group . load_from_buf ( & mixer_text [ 0 ] , resid ) ;
2012-12-29 12:58:41 -08:00
2012-12-30 01:17:19 -08:00
/* if anything was parsed */
if ( resid ! = mixer_text_length ) {
2013-01-15 22:22:15 -08:00
2013-06-07 10:34:55 +02:00
/* only set mixer ok if no residual is left over */
if ( resid = = 0 ) {
r_status_flags | = PX4IO_P_STATUS_FLAGS_MIXER_OK ;
} else {
/* not yet reached the end of the mixer, set as not ok */
r_status_flags & = ~ PX4IO_P_STATUS_FLAGS_MIXER_OK ;
}
2013-01-15 22:22:15 -08:00
2013-02-20 12:19:03 +01:00
isr_debug ( 2 , " used %u " , mixer_text_length - resid ) ;
2012-12-29 12:58:41 -08:00
2012-12-30 15:08:25 -08:00
/* copy any leftover text to the base of the buffer for re-use */
if ( resid > 0 )
memcpy ( & mixer_text [ 0 ] , & mixer_text [ mixer_text_length - resid ] , resid ) ;
2012-12-30 01:17:19 -08:00
2012-12-30 15:08:25 -08:00
mixer_text_length = resid ;
2013-05-29 17:07:26 +02:00
/* update failsafe values */
mixer_set_failsafe ( ) ;
2012-12-30 01:17:19 -08:00
}
2012-12-29 16:01:24 -08:00
2012-12-29 12:58:41 -08:00
break ;
}
2014-01-24 17:34:42 +01:00
return 0 ;
2012-11-05 00:55:22 -08:00
}
2013-05-29 17:07:26 +02:00
static void
mixer_set_failsafe ( )
{
/*
* Check if a custom failsafe value has been written ,
2013-06-07 10:34:55 +02:00
* or if the mixer is not ok and bail out .
2013-05-29 17:07:26 +02:00
*/
2013-06-18 15:35:26 +02:00
2013-06-07 10:34:55 +02:00
if ( ( r_setup_arming & PX4IO_P_SETUP_ARMING_FAILSAFE_CUSTOM ) | |
! ( r_status_flags & PX4IO_P_STATUS_FLAGS_MIXER_OK ) )
2013-05-29 17:07:26 +02:00
return ;
2013-06-07 10:34:55 +02:00
/* set failsafe defaults to the values for all inputs = 0 */
2013-07-06 23:59:35 -07:00
float outputs [ PX4IO_SERVO_COUNT ] ;
2013-05-29 17:07:26 +02:00
unsigned mixed ;
/* mix */
2013-07-06 23:59:35 -07:00
mixed = mixer_group . mix ( & outputs [ 0 ] , PX4IO_SERVO_COUNT ) ;
2013-05-29 17:07:26 +02:00
/* scale to PWM and update the servo outputs as required */
for ( unsigned i = 0 ; i < mixed ; i + + ) {
/* scale to servo output */
r_page_servo_failsafe [ i ] = ( outputs [ i ] * 600.0f ) + 1500 ;
}
/* disable the rest of the outputs */
2013-07-06 23:59:35 -07:00
for ( unsigned i = mixed ; i < PX4IO_SERVO_COUNT ; i + + )
2013-05-29 17:07:26 +02:00
r_page_servo_failsafe [ i ] = 0 ;
}