@ -174,6 +174,7 @@ private:
@@ -174,6 +174,7 @@ private:
void updateDisarmed ( ) ;
void updateFailsafe ( ) ;
void updateTimerRateGroups ( ) ;
static int checkcrc ( int argc , char * argv [ ] ) ;
static int bind ( int argc , char * argv [ ] ) ;
@ -218,6 +219,7 @@ private:
@@ -218,6 +219,7 @@ private:
hrt_abstime _last_status_publish { 0 } ;
bool _param_update_force { true } ; ///< force a parameter update
bool _timer_rates_configured { false } ;
/* advertised topics */
uORB : : PublicationMulti < input_rc_s > _to_input_rc { ORB_ID ( input_rc ) } ;
@ -364,10 +366,14 @@ PX4IO::PX4IO(device::Device *interface) :
@@ -364,10 +366,14 @@ PX4IO::PX4IO(device::Device *interface) :
OutputModuleInterface ( MODULE_NAME , px4 : : serial_port_to_wq ( PX4IO_SERIAL_DEVICE ) ) ,
_interface ( interface )
{
if ( ! _mixing_output . useDynamicMixing ( ) ) {
_mixing_output . setAllMinValues ( PWM_DEFAULT_MIN ) ;
_mixing_output . setAllMaxValues ( PWM_DEFAULT_MAX ) ;
}
_mixing_output . setLowrateSchedulingInterval ( 20 _ms ) ;
}
PX4IO : : ~ PX4IO ( )
{
delete _interface ;
@ -555,7 +561,7 @@ void PX4IO::updateFailsafe()
@@ -555,7 +561,7 @@ void PX4IO::updateFailsafe()
pwm_output_values pwm { } ;
for ( unsigned i = 0 ; i < _max_actuators ; i + + ) {
pwm . values [ i ] = _mixing_output . f ailsafeValue( i ) ;
pwm . values [ i ] = _mixing_output . actualF ailsafeValue( i ) ;
}
io_reg_set ( PX4IO_PAGE_FAILSAFE_PWM , 0 , pwm . values , _max_actuators ) ;
@ -575,7 +581,9 @@ void PX4IO::Run()
@@ -575,7 +581,9 @@ void PX4IO::Run()
perf_count ( _interval_perf ) ;
// schedule minimal update rate if there are no actuator controls
if ( ! _mixing_output . useDynamicMixing ( ) ) {
ScheduleDelayed ( 20 _ms ) ;
}
/* if we have new control data from the ORB, handle it */
if ( _param_sys_hitl . get ( ) < = 0 ) {
@ -705,10 +713,60 @@ void PX4IO::Run()
@@ -705,10 +713,60 @@ void PX4IO::Run()
perf_end ( _cycle_perf ) ;
}
void PX4IO : : updateTimerRateGroups ( )
{
if ( _timer_rates_configured ) { // avoid setting timer rates on each param update
return ;
}
_timer_rates_configured = true ;
int timer = 0 ;
uint16_t timer_rates [ PX4IO_P_SETUP_PWM_RATE_GROUP3 - PX4IO_P_SETUP_PWM_RATE_GROUP0 + 1 ] { } ;
for ( uint8_t offset = PX4IO_P_SETUP_PWM_RATE_GROUP0 ; offset < = PX4IO_P_SETUP_PWM_RATE_GROUP3 ; + + offset ) {
char param_name [ 17 ] ;
snprintf ( param_name , sizeof ( param_name ) , " %s_TIM%u " , _mixing_output . paramPrefix ( ) , timer ) ;
int32_t tim_config = 0 ;
param_t handle = param_find ( param_name ) ;
if ( handle = = PARAM_INVALID ) {
break ;
}
param_get ( handle , & tim_config ) ;
if ( tim_config > 0 ) {
timer_rates [ timer ] = tim_config ;
} else if ( tim_config = = - 1 ) { // OneShot
timer_rates [ timer ] = 0 ;
}
+ + timer ;
}
int ret = io_reg_set ( PX4IO_PAGE_SETUP , PX4IO_P_SETUP_PWM_RATE_GROUP0 , timer_rates , timer ) ;
if ( ret ! = 0 ) {
PX4_ERR ( " io_reg_set failed (%i) " , ret ) ;
}
}
void PX4IO : : update_params ( )
{
if ( ! _mixing_output . armed ( ) . armed & & _mixing_output . useDynamicMixing ( ) ) {
// sync params to IO
updateTimerRateGroups ( ) ;
updateFailsafe ( ) ;
updateDisarmed ( ) ;
return ;
}
// skip update when armed or PWM disabled
if ( _mixing_output . armed ( ) . armed | | _class_instance = = - 1 ) {
if ( _mixing_output . armed ( ) . armed | | _class_instance = = - 1 | | _mixing_output . useDynamicMixing ( ) ) {
return ;
}
@ -1140,6 +1198,16 @@ int PX4IO::io_get_status()
@@ -1140,6 +1198,16 @@ int PX4IO::io_get_status()
status . pwm_failsafe [ i ] = io_reg_get ( PX4IO_PAGE_FAILSAFE_PWM , i ) ;
}
if ( _mixing_output . useDynamicMixing ( ) ) {
int i = 0 ;
for ( uint8_t offset = PX4IO_P_SETUP_PWM_RATE_GROUP0 ; offset < = PX4IO_P_SETUP_PWM_RATE_GROUP3 ; + + offset ) {
// This is a bit different than below, setting the groups, not the channels
status . pwm_rate_hz [ i + + ] = io_reg_get ( PX4IO_PAGE_SETUP , offset ) ;
}
} else {
// PWM rates, 0 = low rate, 1 = high rate
const uint16_t pwm_rate = io_reg_get ( PX4IO_PAGE_SETUP , PX4IO_P_SETUP_PWM_RATES ) ;
@ -1154,6 +1222,7 @@ int PX4IO::io_get_status()
@@ -1154,6 +1222,7 @@ int PX4IO::io_get_status()
status . pwm_rate_hz [ i ] = pwm_low_rate ;
}
}
}
uint16_t raw_inputs = io_reg_get ( PX4IO_PAGE_RAW_RC_INPUT , PX4IO_P_RAW_RC_COUNT ) ;
@ -1532,6 +1601,12 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
@@ -1532,6 +1601,12 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
case PWM_SERVO_SET_UPDATE_RATE :
PX4_DEBUG ( " PWM_SERVO_SET_UPDATE_RATE " ) ;
if ( _mixing_output . useDynamicMixing ( ) ) {
ret = - EINVAL ;
break ;
}
/* set the requested alternate rate */
ret = io_reg_set ( PX4IO_PAGE_SETUP , PX4IO_P_SETUP_PWM_ALTRATE , arg ) ;
break ;
@ -1545,6 +1620,11 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
@@ -1545,6 +1620,11 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
case PWM_SERVO_SET_SELECT_UPDATE_RATE : {
PX4_DEBUG ( " PWM_SERVO_SET_SELECT_UPDATE_RATE " ) ;
if ( _mixing_output . useDynamicMixing ( ) ) {
ret = - EINVAL ;
break ;
}
/* blindly clear the PWM update alarm - might be set for some other reason */
io_reg_set ( PX4IO_PAGE_STATUS , PX4IO_P_STATUS_ALARMS , PX4IO_P_STATUS_ALARMS_PWM_ERROR ) ;
@ -1579,7 +1659,7 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
@@ -1579,7 +1659,7 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
}
for ( unsigned i = 0 ; i < pwm - > channel_count ; i + + ) {
if ( pwm - > values [ i ] ! = 0 ) {
if ( pwm - > values [ i ] ! = 0 & & ! _mixing_output . useDynamicMixing ( ) ) {
_mixing_output . failsafeValue ( i ) = math : : constrain ( pwm - > values [ i ] , ( uint16_t ) PWM_LOWEST_MIN , ( uint16_t ) PWM_HIGHEST_MAX ) ;
}
}
@ -1613,7 +1693,7 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
@@ -1613,7 +1693,7 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
}
for ( unsigned i = 0 ; i < pwm - > channel_count ; i + + ) {
if ( pwm - > values [ i ] ! = 0 ) {
if ( pwm - > values [ i ] ! = 0 & & ! _mixing_output . useDynamicMixing ( ) ) {
_mixing_output . disarmedValue ( i ) = math : : constrain ( pwm - > values [ i ] , ( uint16_t ) PWM_LOWEST_MIN , ( uint16_t ) PWM_HIGHEST_MAX ) ;
}
}
@ -1645,7 +1725,7 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
@@ -1645,7 +1725,7 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
}
for ( unsigned i = 0 ; i < pwm - > channel_count ; i + + ) {
if ( pwm - > values [ i ] ! = 0 ) {
if ( pwm - > values [ i ] ! = 0 & & ! _mixing_output . useDynamicMixing ( ) ) {
_mixing_output . minValue ( i ) = math : : constrain ( pwm - > values [ i ] , ( uint16_t ) PWM_LOWEST_MIN , ( uint16_t ) PWM_HIGHEST_MIN ) ;
}
}
@ -1675,7 +1755,7 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
@@ -1675,7 +1755,7 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
}
for ( unsigned i = 0 ; i < pwm - > channel_count ; i + + ) {
if ( pwm - > values [ i ] ! = 0 ) {
if ( pwm - > values [ i ] ! = 0 & & ! _mixing_output . useDynamicMixing ( ) ) {
_mixing_output . maxValue ( i ) = math : : constrain ( pwm - > values [ i ] , ( uint16_t ) PWM_LOWEST_MAX , ( uint16_t ) PWM_HIGHEST_MAX ) ;
}
}