@@ -174,6 +174,7 @@ class PX4IO : public cdev::CDev, public ModuleBase<PX4IO>, public OutputModuleIn
174
174
175
175
void updateDisarmed ();
176
176
void updateFailsafe ();
177
+ void updateTimerRateGroups ();
177
178
178
179
static int checkcrc (int argc, char *argv[]);
179
180
static int bind (int argc, char *argv[]);
@@ -218,6 +219,7 @@ class PX4IO : public cdev::CDev, public ModuleBase<PX4IO>, public OutputModuleIn
218
219
hrt_abstime _last_status_publish{0 };
219
220
220
221
bool _param_update_force{true }; // /< force a parameter update
222
+ bool _timer_rates_configured{false };
221
223
222
224
/* advertised topics */
223
225
uORB::PublicationMulti<input_rc_s> _to_input_rc{ORB_ID (input_rc)};
@@ -364,8 +366,12 @@ PX4IO::PX4IO(device::Device *interface) :
364
366
OutputModuleInterface(MODULE_NAME, px4::serial_port_to_wq(PX4IO_SERIAL_DEVICE)),
365
367
_interface(interface)
366
368
{
367
- _mixing_output.setAllMinValues (PWM_DEFAULT_MIN);
368
- _mixing_output.setAllMaxValues (PWM_DEFAULT_MAX);
369
+ if (!_mixing_output.useDynamicMixing ()) {
370
+ _mixing_output.setAllMinValues (PWM_DEFAULT_MIN);
371
+ _mixing_output.setAllMaxValues (PWM_DEFAULT_MAX);
372
+ }
373
+
374
+ _mixing_output.setLowrateSchedulingInterval (20_ms);
369
375
}
370
376
371
377
PX4IO::~PX4IO ()
@@ -555,7 +561,7 @@ void PX4IO::updateFailsafe()
555
561
pwm_output_values pwm{};
556
562
557
563
for (unsigned i = 0 ; i < _max_actuators; i++) {
558
- pwm.values [i] = _mixing_output.failsafeValue (i);
564
+ pwm.values [i] = _mixing_output.actualFailsafeValue (i);
559
565
}
560
566
561
567
io_reg_set (PX4IO_PAGE_FAILSAFE_PWM, 0 , pwm.values , _max_actuators);
@@ -575,7 +581,9 @@ void PX4IO::Run()
575
581
perf_count (_interval_perf);
576
582
577
583
// schedule minimal update rate if there are no actuator controls
578
- ScheduleDelayed (20_ms);
584
+ if (!_mixing_output.useDynamicMixing ()) {
585
+ ScheduleDelayed (20_ms);
586
+ }
579
587
580
588
/* if we have new control data from the ORB, handle it */
581
589
if (_param_sys_hitl.get () <= 0 ) {
@@ -705,10 +713,60 @@ void PX4IO::Run()
705
713
perf_end (_cycle_perf);
706
714
}
707
715
716
+ void PX4IO::updateTimerRateGroups ()
717
+ {
718
+ if (_timer_rates_configured) { // avoid setting timer rates on each param update
719
+ return ;
720
+ }
721
+
722
+ _timer_rates_configured = true ;
723
+
724
+ int timer = 0 ;
725
+
726
+ uint16_t timer_rates[PX4IO_P_SETUP_PWM_RATE_GROUP3 - PX4IO_P_SETUP_PWM_RATE_GROUP0 + 1 ] {};
727
+
728
+ for (uint8_t offset = PX4IO_P_SETUP_PWM_RATE_GROUP0; offset <= PX4IO_P_SETUP_PWM_RATE_GROUP3; ++offset) {
729
+ char param_name[17 ];
730
+ snprintf (param_name, sizeof (param_name), " %s_TIM%u" , _mixing_output.paramPrefix (), timer);
731
+
732
+ int32_t tim_config = 0 ;
733
+ param_t handle = param_find (param_name);
734
+
735
+ if (handle == PARAM_INVALID) {
736
+ break ;
737
+ }
738
+
739
+ param_get (handle, &tim_config);
740
+
741
+ if (tim_config > 0 ) {
742
+ timer_rates[timer] = tim_config;
743
+
744
+ } else if (tim_config == -1 ) { // OneShot
745
+ timer_rates[timer] = 0 ;
746
+ }
747
+
748
+ ++timer;
749
+ }
750
+
751
+ int ret = io_reg_set (PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_RATE_GROUP0, timer_rates, timer);
752
+
753
+ if (ret != 0 ) {
754
+ PX4_ERR (" io_reg_set failed (%i)" , ret);
755
+ }
756
+ }
757
+
708
758
void PX4IO::update_params ()
709
759
{
760
+ if (!_mixing_output.armed ().armed && _mixing_output.useDynamicMixing ()) {
761
+ // sync params to IO
762
+ updateTimerRateGroups ();
763
+ updateFailsafe ();
764
+ updateDisarmed ();
765
+ return ;
766
+ }
767
+
710
768
// skip update when armed or PWM disabled
711
- if (_mixing_output.armed ().armed || _class_instance == -1 ) {
769
+ if (_mixing_output.armed ().armed || _class_instance == -1 || _mixing_output. useDynamicMixing () ) {
712
770
return ;
713
771
}
714
772
@@ -1140,18 +1198,29 @@ int PX4IO::io_get_status()
1140
1198
status.pwm_failsafe [i] = io_reg_get (PX4IO_PAGE_FAILSAFE_PWM, i);
1141
1199
}
1142
1200
1143
- // PWM rates, 0 = low rate, 1 = high rate
1144
- const uint16_t pwm_rate = io_reg_get (PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_RATES);
1201
+ if (_mixing_output.useDynamicMixing ()) {
1145
1202
1146
- const int pwm_low_rate = io_reg_get (PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_DEFAULTRATE);
1147
- const int pwm_high_rate = io_reg_get (PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_ALTRATE);
1203
+ int i = 0 ;
1148
1204
1149
- for (unsigned i = 0 ; i < _max_actuators; i++) {
1150
- if (pwm_rate & (1 << i)) {
1151
- status.pwm_rate_hz [i] = pwm_high_rate;
1205
+ for (uint8_t offset = PX4IO_P_SETUP_PWM_RATE_GROUP0; offset <= PX4IO_P_SETUP_PWM_RATE_GROUP3; ++offset) {
1206
+ // This is a bit different than below, setting the groups, not the channels
1207
+ status.pwm_rate_hz [i++] = io_reg_get (PX4IO_PAGE_SETUP, offset);
1208
+ }
1152
1209
1153
- } else {
1154
- status.pwm_rate_hz [i] = pwm_low_rate;
1210
+ } else {
1211
+ // PWM rates, 0 = low rate, 1 = high rate
1212
+ const uint16_t pwm_rate = io_reg_get (PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_RATES);
1213
+
1214
+ const int pwm_low_rate = io_reg_get (PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_DEFAULTRATE);
1215
+ const int pwm_high_rate = io_reg_get (PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_ALTRATE);
1216
+
1217
+ for (unsigned i = 0 ; i < _max_actuators; i++) {
1218
+ if (pwm_rate & (1 << i)) {
1219
+ status.pwm_rate_hz [i] = pwm_high_rate;
1220
+
1221
+ } else {
1222
+ status.pwm_rate_hz [i] = pwm_low_rate;
1223
+ }
1155
1224
}
1156
1225
}
1157
1226
@@ -1532,6 +1601,12 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
1532
1601
1533
1602
case PWM_SERVO_SET_UPDATE_RATE:
1534
1603
PX4_DEBUG (" PWM_SERVO_SET_UPDATE_RATE" );
1604
+
1605
+ if (_mixing_output.useDynamicMixing ()) {
1606
+ ret = -EINVAL;
1607
+ break ;
1608
+ }
1609
+
1535
1610
/* set the requested alternate rate */
1536
1611
ret = io_reg_set (PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_ALTRATE, arg);
1537
1612
break ;
@@ -1545,6 +1620,11 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
1545
1620
case PWM_SERVO_SET_SELECT_UPDATE_RATE: {
1546
1621
PX4_DEBUG (" PWM_SERVO_SET_SELECT_UPDATE_RATE" );
1547
1622
1623
+ if (_mixing_output.useDynamicMixing ()) {
1624
+ ret = -EINVAL;
1625
+ break ;
1626
+ }
1627
+
1548
1628
/* blindly clear the PWM update alarm - might be set for some other reason */
1549
1629
io_reg_set (PX4IO_PAGE_STATUS, PX4IO_P_STATUS_ALARMS, PX4IO_P_STATUS_ALARMS_PWM_ERROR);
1550
1630
@@ -1579,7 +1659,7 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
1579
1659
}
1580
1660
1581
1661
for (unsigned i = 0 ; i < pwm->channel_count ; i++) {
1582
- if (pwm->values [i] != 0 ) {
1662
+ if (pwm->values [i] != 0 && !_mixing_output. useDynamicMixing () ) {
1583
1663
_mixing_output.failsafeValue (i) = math::constrain (pwm->values [i], (uint16_t )PWM_LOWEST_MIN, (uint16_t )PWM_HIGHEST_MAX);
1584
1664
}
1585
1665
}
@@ -1613,7 +1693,7 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
1613
1693
}
1614
1694
1615
1695
for (unsigned i = 0 ; i < pwm->channel_count ; i++) {
1616
- if (pwm->values [i] != 0 ) {
1696
+ if (pwm->values [i] != 0 && !_mixing_output. useDynamicMixing () ) {
1617
1697
_mixing_output.disarmedValue (i) = math::constrain (pwm->values [i], (uint16_t )PWM_LOWEST_MIN, (uint16_t )PWM_HIGHEST_MAX);
1618
1698
}
1619
1699
}
@@ -1645,7 +1725,7 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
1645
1725
}
1646
1726
1647
1727
for (unsigned i = 0 ; i < pwm->channel_count ; i++) {
1648
- if (pwm->values [i] != 0 ) {
1728
+ if (pwm->values [i] != 0 && !_mixing_output. useDynamicMixing () ) {
1649
1729
_mixing_output.minValue (i) = math::constrain (pwm->values [i], (uint16_t )PWM_LOWEST_MIN, (uint16_t )PWM_HIGHEST_MIN);
1650
1730
}
1651
1731
}
@@ -1675,7 +1755,7 @@ int PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
1675
1755
}
1676
1756
1677
1757
for (unsigned i = 0 ; i < pwm->channel_count ; i++) {
1678
- if (pwm->values [i] != 0 ) {
1758
+ if (pwm->values [i] != 0 && !_mixing_output. useDynamicMixing () ) {
1679
1759
_mixing_output.maxValue (i) = math::constrain (pwm->values [i], (uint16_t )PWM_LOWEST_MAX, (uint16_t )PWM_HIGHEST_MAX);
1680
1760
}
1681
1761
}
0 commit comments