PX4 Firmware
PX4 Autopilot Software http://px4.io
mixer.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2012-2017 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file mixer.cpp
36  *
37  * Control channel input/output mixer and failsafe.
38  *
39  * @author Lorenz Meier <lorenz@px4.io>
40  */
41 
42 #include <px4_platform_common/px4_config.h>
43 #include <syslog.h>
44 
45 #include <sys/types.h>
46 #include <stdbool.h>
47 #include <float.h>
48 #include <string.h>
49 #include <math.h>
50 
51 #include <drivers/drv_pwm_output.h>
52 #include <drivers/drv_hrt.h>
53 
54 #include <lib/mixer/MixerGroup.hpp>
56 #include <rc/sbus.h>
57 
59 
60 #include "mixer.h"
61 
62 extern "C" {
63  /* #define DEBUG */
64 #include "px4io.h"
65 }
66 
67 /*
68  * Maximum interval in us before FMU signal is considered lost
69  */
70 #define FMU_INPUT_DROP_LIMIT_US 500000
71 
72 /* current servo arm/disarm state */
73 static volatile bool mixer_servos_armed = false;
74 static volatile bool should_arm = false;
75 static volatile bool should_arm_nothrottle = false;
76 static volatile bool should_always_enable_pwm = false;
77 static volatile bool in_mixer = false;
78 
79 static bool new_fmu_data = false;
80 static uint64_t last_fmu_update = 0;
81 
82 extern int _sbus_fd;
83 
84 /* selected control values and count for mixing */
92 };
93 
94 static volatile mixer_source source;
95 
96 static int mixer_callback(uintptr_t handle, uint8_t control_group, uint8_t control_index, float &control);
97 static int mixer_mix_threadsafe(float *outputs, volatile uint16_t *limits);
98 
100 
101 int mixer_mix_threadsafe(float *outputs, volatile uint16_t *limits)
102 {
103  /* poor mans mutex */
105  return 0;
106  }
107 
108  in_mixer = true;
109  int mixcount = mixer_group.mix(&outputs[0], PX4IO_SERVO_COUNT);
110  *limits = mixer_group.get_saturation_status();
111  in_mixer = false;
112 
113  return mixcount;
114 }
115 
116 void
118 {
119  /* check if the mixer got modified */
121 
122  /* check that we are receiving fresh data from the FMU */
123  irqstate_t irq_flags = enter_critical_section();
124  const hrt_abstime fmu_data_received_time = system_state.fmu_data_received_time;
125  leave_critical_section(irq_flags);
126 
127  if ((fmu_data_received_time == 0) ||
128  hrt_elapsed_time(&fmu_data_received_time) > FMU_INPUT_DROP_LIMIT_US) {
129 
130  /* too long without FMU input, time to go to failsafe */
132  isr_debug(1, "AP RX timeout");
133  }
134 
135  atomic_modify_clear(&r_status_flags, (PX4IO_P_STATUS_FLAGS_FMU_OK));
137 
138  } else {
140 
141  /* this flag is never cleared once OK */
143 
144  if (fmu_data_received_time > last_fmu_update) {
145  new_fmu_data = true;
146  last_fmu_update = fmu_data_received_time;
147  }
148  }
149 
150  /* default to disarmed mixing */
152 
153  /*
154  * Decide which set of controls we're using.
155  */
156 
157  /* Do not mix if we have raw PWM and FMU is ok. */
160 
162  /* a channel based override has been
163  * triggered, with FMU active */
165 
166  } else {
167  /* don't actually mix anything - copy values from r_page_direct_pwm */
168  source = MIX_NONE;
169  memcpy(r_page_servos, r_page_direct_pwm, sizeof(uint16_t)*PX4IO_SERVO_COUNT);
170  }
171 
172  } else {
173 
175  (r_status_flags & PX4IO_P_STATUS_FLAGS_FMU_OK) &&
177 
178  /* mix from FMU controls */
179  source = MIX_FMU;
180  }
181 
182  else if (r_status_flags & PX4IO_P_STATUS_FLAGS_OVERRIDE) {
183 
184  if (r_status_flags & PX4IO_P_STATUS_FLAGS_FMU_OK) {
185 
186  /* if allowed, mix from RC inputs directly up to available rc channels */
188 
189  } else {
190  /* if allowed, mix from RC inputs directly */
192  }
193  }
194  }
195 
196  /*
197  * Decide whether the servos should be armed right now.
198  *
199  * We must be armed, and we must have a PWM source; either raw from
200  * FMU or from the mixer.
201  *
202  */
203  should_arm = (
204  (r_status_flags & PX4IO_P_STATUS_FLAGS_INIT_OK) /* IO initialised without error */
205  && (r_status_flags & PX4IO_P_STATUS_FLAGS_SAFETY_OFF) /* and IO is armed */
206  && (
207  ((r_setup_arming & PX4IO_P_SETUP_ARMING_FMU_ARMED) /* and FMU is armed */
208  && (r_status_flags & PX4IO_P_STATUS_FLAGS_MIXER_OK)) /* and there is valid input via or mixer */
209  || (r_status_flags & PX4IO_P_STATUS_FLAGS_RAW_PWM) /* or direct PWM is set */
210  )
211  );
212 
214  (r_status_flags & PX4IO_P_STATUS_FLAGS_INIT_OK) /* IO initialised without error */
215  && (r_status_flags & PX4IO_P_STATUS_FLAGS_SAFETY_OFF) /* and IO is armed */
216  && (((r_setup_arming & PX4IO_P_SETUP_ARMING_FMU_PREARMED) /* and FMU is prearmed */
217  && (r_status_flags & PX4IO_P_STATUS_FLAGS_MIXER_OK)) /* and there is valid input via or mixer */
218  || (r_status_flags & PX4IO_P_STATUS_FLAGS_RAW_PWM) /* or direct PWM is set */
219  )
220  );
221 
226  );
227 
228  /*
229  * Check if FMU is still alive, if not, terminate the flight
230  */
231  if (REG_TO_BOOL(r_setup_flighttermination) && /* Flight termination is allowed */
232  (source == MIX_DISARMED) && /* and if we ended up not changing the default mixer */
233  should_arm && /* and we should be armed, so we intended to provide outputs */
234  (r_status_flags & PX4IO_P_STATUS_FLAGS_FMU_INITIALIZED)) { /* and FMU is initialized */
235  atomic_modify_or(&r_setup_arming, PX4IO_P_SETUP_ARMING_FORCE_FAILSAFE); /* then FMU is dead -> terminate flight */
236  }
237 
238  /*
239  * Check if we should force failsafe - and do it if we have to
240  */
243  }
244 
245  /*
246  * Set failsafe status flag depending on mixing source
247  */
248  if (source == MIX_FAILSAFE) {
250 
251  } else {
253  }
254 
255  /*
256  * Set simple mixer trim values. If the OK flag is set the mixer is fully loaded.
257  */
258  if (update_trims && r_status_flags & PX4IO_P_STATUS_FLAGS_MIXER_OK) {
259  update_trims = false;
261  }
262 
263  /*
264  * Update air-mode parameter
265  */
267 
268 
269  /*
270  * Run the mixers.
271  */
272  if (source == MIX_FAILSAFE) {
273 
274  /* copy failsafe values to the servo outputs */
275  for (unsigned i = 0; i < PX4IO_SERVO_COUNT; i++) {
277 
278  /* safe actuators for FMU feedback */
279  r_page_actuators[i] = FLOAT_TO_REG((r_page_servos[i] - 1500) / 600.0f);
280  }
281 
282  } else if (source == MIX_DISARMED) {
283 
284  /* copy disarmed values to the servo outputs */
285  for (unsigned i = 0; i < PX4IO_SERVO_COUNT; i++) {
287 
288  /* safe actuators for FMU feedback */
289  r_page_actuators[i] = FLOAT_TO_REG((r_page_servos[i] - 1500) / 600.0f);
290  }
291 
292  } else if (source != MIX_NONE && (r_status_flags & PX4IO_P_STATUS_FLAGS_MIXER_OK)
294 
295  float outputs[PX4IO_SERVO_COUNT];
296  unsigned mixed;
297 
299  /* maximum value the outputs of the multirotor mixer are allowed to change in this cycle
300  * factor 2 is needed because actuator outputs are in the range [-1,1]
301  */
302  float delta_out_max = 2.0f * 1000.0f * dt / (r_page_servo_control_max[0] - r_page_servo_control_min[0]) / REG_TO_FLOAT(
304  mixer_group.set_max_delta_out_once(delta_out_max);
305  }
306 
307  /* update parameter for mc thrust model if it updated */
310  update_mc_thrust_param = false;
311  }
312 
313  /* mix */
314  mixed = mixer_mix_threadsafe(&outputs[0], &r_mixer_limits);
315 
316  /* the pwm limit call takes care of out of band errors */
319 
320  /* clamp unused outputs to zero */
321  for (unsigned i = mixed; i < PX4IO_SERVO_COUNT; i++) {
322  r_page_servos[i] = 0;
323  outputs[i] = 0.0f;
324  }
325 
326  /* store normalized outputs */
327  for (unsigned i = 0; i < PX4IO_SERVO_COUNT; i++) {
328  r_page_actuators[i] = FLOAT_TO_REG(outputs[i]);
329  }
330 
331 
332  if (mixed && new_fmu_data) {
333  new_fmu_data = false;
334 
335  /* Trigger all timer's channels in Oneshot mode to fire
336  * the oneshots with updated values.
337  */
338 
339  up_pwm_update();
340  }
341  }
342 
343  /* set arming */
344  bool needs_to_arm = (should_arm || should_arm_nothrottle || should_always_enable_pwm);
345 
346  /* lockdown means to send a valid pulse which disables the outputs */
347  if (r_setup_arming & PX4IO_P_SETUP_ARMING_LOCKDOWN) {
348  needs_to_arm = true;
349  }
350 
351  if (needs_to_arm && !mixer_servos_armed) {
352  /* need to arm, but not armed */
353  up_pwm_servo_arm(true);
354  mixer_servos_armed = true;
356  isr_debug(5, "> PWM enabled");
357 
358  } else if (!needs_to_arm && mixer_servos_armed) {
359  /* armed but need to disarm */
360  up_pwm_servo_arm(false);
361  mixer_servos_armed = false;
363  isr_debug(5, "> PWM disabled");
364  }
365 
368  && !(r_setup_arming & PX4IO_P_SETUP_ARMING_LOCKDOWN)) {
369  /* update the servo outputs. */
370  for (unsigned i = 0; i < PX4IO_SERVO_COUNT; i++) {
372  }
373 
374  /* set S.BUS1 or S.BUS2 outputs */
375 
377  sbus2_output(_sbus_fd, r_page_servos, PX4IO_SERVO_COUNT);
378 
380  sbus1_output(_sbus_fd, r_page_servos, PX4IO_SERVO_COUNT);
381  }
382 
384  || (r_setup_arming & PX4IO_P_SETUP_ARMING_LOCKDOWN))) {
385  /* set the disarmed servo outputs. */
386  for (unsigned i = 0; i < PX4IO_SERVO_COUNT; i++) {
388  /* copy values into reporting register */
390  }
391 
392  /* set S.BUS1 or S.BUS2 outputs */
394  sbus1_output(_sbus_fd, r_page_servo_disarmed, PX4IO_SERVO_COUNT);
395  }
396 
398  sbus2_output(_sbus_fd, r_page_servo_disarmed, PX4IO_SERVO_COUNT);
399  }
400  }
401 }
402 
403 static int
404 mixer_callback(uintptr_t handle,
405  uint8_t control_group,
406  uint8_t control_index,
407  float &control)
408 {
409  control = 0.0f;
410 
411  if (control_group >= PX4IO_CONTROL_GROUPS) {
412  return -1;
413  }
414 
415  switch (source) {
416  case MIX_FMU:
417  if (control_index < PX4IO_CONTROL_CHANNELS && control_group < PX4IO_CONTROL_GROUPS) {
418  if (r_page_controls[CONTROL_PAGE_INDEX(control_group, control_index)] == INT16_MAX) {
419  //catch NAN values encoded as INT16 max for disarmed outputs
420  control = NAN;
421 
422  } else {
423  control = REG_TO_FLOAT(r_page_controls[CONTROL_PAGE_INDEX(control_group, control_index)]);
424  }
425 
426  break;
427  }
428 
429  return -1;
430 
431  case MIX_OVERRIDE:
432  if (r_page_rc_input[PX4IO_P_RC_VALID] & (1 << CONTROL_PAGE_INDEX(control_group, control_index))) {
433  control = REG_TO_FLOAT(r_page_rc_input[PX4IO_P_RC_BASE + control_index]);
434  break;
435  }
436 
437  return -1;
438 
439  case MIX_OVERRIDE_FMU_OK:
440 
441  /* 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 */
442  if (r_page_rc_input[PX4IO_P_RC_VALID] & (1 << CONTROL_PAGE_INDEX(control_group, control_index))) {
443  control = REG_TO_FLOAT(r_page_rc_input[PX4IO_P_RC_BASE + control_index]);
444  break;
445 
446  } else if (control_index < PX4IO_CONTROL_CHANNELS && control_group < PX4IO_CONTROL_GROUPS) {
447  control = REG_TO_FLOAT(r_page_controls[CONTROL_PAGE_INDEX(control_group, control_index)]);
448  break;
449  }
450 
451  return -1;
452 
453  case MIX_DISARMED:
454  case MIX_FAILSAFE:
455  case MIX_NONE:
456  control = 0.0f;
457  return -1;
458  }
459 
460  /* apply trim offsets for override channels */
462  if (control_group == actuator_controls_s::GROUP_INDEX_ATTITUDE &&
463  control_index == actuator_controls_s::INDEX_ROLL) {
464  control *= REG_TO_FLOAT(r_setup_scale_roll);
465  control += REG_TO_FLOAT(r_setup_trim_roll);
466 
467  } else if (control_group == actuator_controls_s::GROUP_INDEX_ATTITUDE &&
468  control_index == actuator_controls_s::INDEX_PITCH) {
469  control *= REG_TO_FLOAT(r_setup_scale_pitch);
470  control += REG_TO_FLOAT(r_setup_trim_pitch);
471 
472  } else if (control_group == actuator_controls_s::GROUP_INDEX_ATTITUDE &&
473  control_index == actuator_controls_s::INDEX_YAW) {
474  control *= REG_TO_FLOAT(r_setup_scale_yaw);
475  control += REG_TO_FLOAT(r_setup_trim_yaw);
476  }
477  }
478 
479  /* limit output */
480  if (control > 1.0f) {
481  control = 1.0f;
482 
483  } else if (control < -1.0f) {
484  control = -1.0f;
485  }
486 
487  /* motor spinup phase - lock throttle to zero */
489  if ((control_group == actuator_controls_s::GROUP_INDEX_ATTITUDE ||
490  control_group == actuator_controls_s::GROUP_INDEX_ATTITUDE_ALTERNATE) &&
491  control_index == actuator_controls_s::INDEX_THROTTLE) {
492  /* limit the throttle output to zero during motor spinup,
493  * as the motors cannot follow any demand yet
494  */
495  control = 0.0f;
496  }
497  }
498 
499  /* only safety off, but not armed - set throttle as invalid */
501  if ((control_group == actuator_controls_s::GROUP_INDEX_ATTITUDE ||
502  control_group == actuator_controls_s::GROUP_INDEX_ATTITUDE_ALTERNATE) &&
503  control_index == actuator_controls_s::INDEX_THROTTLE) {
504  /* mark the throttle as invalid */
505  control = NAN;
506  }
507  }
508 
509  return 0;
510 }
511 
512 /*
513  * XXX error handling here should be more aggressive; currently it is
514  * possible to get STATUS_FLAGS_MIXER_OK set even though the mixer has
515  * not loaded faithfully.
516  */
517 
518 static char mixer_text[PX4IO_MAX_MIXER_LENGTH]; /* large enough for one mixer */
519 static unsigned mixer_text_length = 0;
520 static bool mixer_update_pending = false;
521 
522 int
524 {
525  /* only run on update */
526  if (!mixer_update_pending) {
527  return 0;
528  }
529 
530  /* do not allow a mixer change while safety off and FMU armed */
533  return 1;
534  }
535 
536  /* abort if we're in the mixer - it will be tried again in the next iteration */
537  if (in_mixer) {
538  return 1;
539  }
540 
541  /* process the text buffer, adding new mixers as their descriptions can be parsed */
542  unsigned resid = mixer_text_length;
543  mixer_group.load_from_buf(mixer_callback, 0, &mixer_text[0], resid);
544 
545  /* if anything was parsed */
546  if (resid != mixer_text_length) {
547 
548  isr_debug(2, "used %u", mixer_text_length - resid);
549 
550  /* copy any leftover text to the base of the buffer for re-use */
551  if (resid > 0) {
552  memmove(&mixer_text[0], &mixer_text[mixer_text_length - resid], resid);
553  /* enforce null termination */
554  mixer_text[resid] = '\0';
555  }
556 
557  mixer_text_length = resid;
558  }
559 
560  mixer_update_pending = false;
561 
562  return 0;
563 }
564 
565 int
566 mixer_handle_text(const void *buffer, size_t length)
567 {
568  /* do not allow a mixer change while safety off and FMU armed */
571  return 1;
572  }
573 
574  /* disable mixing, will be enabled once load is complete */
576 
577  /* set the update flags to dirty so we reload those values after a mixer change */
578  update_trims = true;
579  update_mc_thrust_param = true;
580 
581  /* abort if we're in the mixer - the caller is expected to retry */
582  if (in_mixer) {
583  return 1;
584  }
585 
586  px4io_mixdata *msg = (px4io_mixdata *)buffer;
587 
588  isr_debug(2, "mix txt %u", length);
589 
590  if (length < sizeof(px4io_mixdata)) {
591  return 0;
592  }
593 
594  unsigned text_length = length - sizeof(px4io_mixdata);
595 
596  switch (msg->action) {
598  isr_debug(2, "reset");
599 
600  /* THEN actually delete it */
601  mixer_group.reset();
602  mixer_text_length = 0;
603 
604  /* FALLTHROUGH */
606  isr_debug(2, "append %d", length);
607 
608  /* check for overflow - this would be really fatal */
609  if ((mixer_text_length + text_length + 1) > sizeof(mixer_text)) {
611  return 0;
612  }
613 
614  /* check if the last item has been processed - bail out if not */
615  if (mixer_update_pending) {
616  return 1;
617  }
618 
619  /* append mixer text and nul-terminate, guard against overflow */
620  memcpy(&mixer_text[mixer_text_length], msg->text, text_length);
621  mixer_text_length += text_length;
623  isr_debug(2, "buflen %u", mixer_text_length);
624 
625  /* flag the buffer as ready */
626  mixer_update_pending = true;
627 
628  break;
629  }
630 
631  return 0;
632 }
633 
634 void
636 {
637  /*
638  * Check if a custom failsafe value has been written,
639  * or if the mixer is not ok and bail out.
640  */
641 
644  return;
645  }
646 
647  /* set failsafe defaults to the values for all inputs = 0 */
648  float outputs[PX4IO_SERVO_COUNT];
649  unsigned mixed;
650 
652  /* maximum value the outputs of the multirotor mixer are allowed to change in this cycle
653  * factor 2 is needed because actuator outputs are in the range [-1,1]
654  */
655  float delta_out_max = 2.0f * 1000.0f * dt / (r_page_servo_control_max[0] - r_page_servo_control_min[0]) / REG_TO_FLOAT(
657  mixer_group.set_max_delta_out_once(delta_out_max);
658  }
659 
660  /* update parameter for mc thrust model if it updated */
663  update_mc_thrust_param = false;
664  }
665 
666  /* mix */
667  mixed = mixer_mix_threadsafe(&outputs[0], &r_mixer_limits);
668 
669  /* scale to PWM and update the servo outputs as required */
670  for (unsigned i = 0; i < mixed; i++) {
671 
672  /* scale to servo output */
673  r_page_servo_failsafe[i] = (outputs[i] * 600.0f) + 1500;
674 
675  }
676 
677  /* disable the rest of the outputs */
678  for (unsigned i = mixed; i < PX4IO_SERVO_COUNT; i++) {
679  r_page_servo_failsafe[i] = 0;
680  }
681 
682 }
int load_from_buf(Mixer::ControlCallback control_cb, uintptr_t cb_handle, const char *buf, unsigned &buflen)
Adds mixers to the group based on a text description in a buffer.
Definition: MixerGroup.cpp:173
#define PX4IO_P_SETUP_ARMING_ALWAYS_PWM_ENABLE
Definition: protocol.h:189
#define PX4IO_P_STATUS_FLAGS_FMU_OK
Definition: protocol.h:113
#define r_status_alarms
Definition: px4io.h:108
#define FLOAT_TO_REG(_float)
Definition: protocol.h:79
#define PX4IO_P_RC_BASE
Definition: protocol.h:165
static unsigned mixer_text_length
Definition: mixer.cpp:519
void reset()
Remove all the mixers from the group.
Definition: MixerGroup.hpp:74
void output_limit_calc(const bool armed, const bool pre_armed, const unsigned num_channels, const uint16_t reverse_mask, const uint16_t *disarmed_output, const uint16_t *min_output, const uint16_t *max_output, const float *output, uint16_t *effective_output, output_limit_t *limit)
uint16_t get_saturation_status()
Definition: MixerGroup.cpp:153
#define F2I_MIXER_ACTION_APPEND
Definition: protocol.h:318
#define r_setup_pwm_reverse
Definition: px4io.h:124
static volatile bool mixer_servos_armed
Definition: mixer.cpp:73
static MixerGroup mixer_group
Definition: mixer.cpp:99
int mixer_handle_text(const void *buffer, size_t length)
Definition: mixer.cpp:566
#define PX4IO_P_RC_VALID
Definition: protocol.h:164
static char mixer_text[PX4IO_MAX_MIXER_LENGTH]
Definition: mixer.cpp:518
static int mixer_mix_threadsafe(float *outputs, volatile uint16_t *limits)
Definition: mixer.cpp:101
void isr_debug(uint8_t level, const char *fmt,...)
send a debug message to the console
Definition: px4io.c:120
#define r_setup_scale_yaw
Definition: px4io.h:131
static volatile bool should_arm
Definition: mixer.cpp:74
#define r_mixer_limits
Definition: px4io.h:115
static volatile bool should_arm_nothrottle
Definition: mixer.cpp:75
#define r_setup_features
Definition: px4io.h:117
#define r_setup_arming
Definition: px4io.h:118
static volatile mixer_source source
Definition: mixer.cpp:94
#define FLT_EPSILON
High-resolution timer with callouts and timekeeping.
void atomic_modify_clear(volatile uint16_t *target, uint16_t modification)
Definition: px4io.c:102
unsigned set_trims(int16_t *v, unsigned n)
Definition: MixerGroup.cpp:75
As-needed mixer data upload.
Definition: protocol.h:312
static char msg[NUM_MSG][CONFIG_USART1_TXBUFSIZE]
Definition: px4io.c:89
void set_max_delta_out_once(float delta_out_max)
Update slew rate parameter.
Definition: MixerGroup.cpp:240
#define PX4IO_P_SETUP_ARMING_FAILSAFE_CUSTOM
Definition: protocol.h:187
#define REG_TO_FLOAT(_reg)
Definition: protocol.h:78
#define PX4IO_P_STATUS_ALARMS_FMU_LOST
Definition: protocol.h:129
uint16_t r_page_servo_control_max[]
PAGE 107.
Definition: registers.c:256
enum output_limit_state state
Definition: output_limit.h:67
static int mixer_callback(uintptr_t handle, uint8_t control_group, uint8_t control_index, float &control)
Definition: mixer.cpp:404
int _sbus_fd
Definition: controls.c:67
#define PX4IO_P_STATUS_FLAGS_FMU_INITIALIZED
Definition: protocol.h:120
#define F2I_MIXER_ACTION_RESET
Definition: protocol.h:317
static bool mixer_update_pending
Definition: mixer.cpp:520
#define r_setup_flighttermination
Definition: px4io.h:136
mixer_source
Definition: mixer.cpp:85
void set_thrust_factor(float val)
Sets the thrust factor used to calculate mapping from desired thrust to motor control signal output...
Definition: MixerGroup.cpp:123
void atomic_modify_or(volatile uint16_t *target, uint16_t modification)
Definition: px4io.c:95
#define PX4IO_P_STATUS_FLAGS_MIXER_OK
Definition: protocol.h:115
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
static hrt_abstime hrt_elapsed_time(const hrt_abstime *then)
Compute the delta between a timestamp taken in the past and now.
Definition: drv_hrt.h:102
#define r_status_flags
Definition: px4io.h:107
__EXPORT int up_pwm_servo_set(unsigned channel, servo_position_t value)
Set the current output value for a channel.
uint16_t r_page_controls[]
PAGE 101.
Definition: registers.c:213
void mixer_tick()
Definition: mixer.cpp:117
#define PX4IO_CONTROL_CHANNELS
Definition: px4io.h:66
uint16_t r_page_servo_disarmed[]
PAGE 109.
Definition: registers.c:272
#define r_setup_trim_pitch
Definition: px4io.h:127
Airmode
Definition: Mixer.hpp:139
#define PX4IO_P_STATUS_FLAGS_OVERRIDE
Definition: protocol.h:108
#define r_setup_slew_max
Definition: px4io.h:134
__BEGIN_DECLS typedef uint64_t hrt_abstime
Absolute time, in microsecond units.
Definition: drv_hrt.h:58
bool update_trims
Definition: registers.c:61
#define PX4IO_P_STATUS_FLAGS_SAFETY_OFF
Definition: protocol.h:119
output_limit_t pwm_limit
Definition: px4io.c:71
#define PX4IO_MAX_MIXER_LENGTH
Definition: mixer.h:42
#define r_setup_scale_roll
Definition: px4io.h:129
int mixer_handle_text_create_mixer()
Definition: mixer.cpp:523
void mixer_set_failsafe()
Definition: mixer.cpp:635
#define CONTROL_PAGE_INDEX(_group, _channel)
Definition: px4io.h:185
General defines and structures for the PX4IO module firmware.
struct sys_state_s system_state
Definition: px4io.c:67
uint16_t r_page_servo_control_min[]
PAGE 106.
Definition: registers.c:248
bool update_mc_thrust_param
Definition: registers.c:60
#define PX4IO_SERVO_COUNT
Definition: px4io.h:65
#define PX4IO_P_STATUS_FLAGS_RAW_PWM
Definition: protocol.h:114
static uint64_t last_fmu_update
Definition: mixer.cpp:80
void set_airmode(Mixer::Airmode airmode)
Definition: MixerGroup.cpp:131
void sbus2_output(int sbus_fd, uint16_t *values, uint16_t num_values)
Definition: sbus.cpp:276
#define PX4IO_P_SETUP_ARMING_FMU_ARMED
Definition: protocol.h:184
#define PX4IO_P_STATUS_FLAGS_INIT_OK
Definition: protocol.h:117
#define r_setup_trim_yaw
Definition: px4io.h:128
#define PX4IO_P_SETUP_ARMING_FORCE_FAILSAFE
Definition: protocol.h:192
uint16_t r_page_servos[]
PAGE 3.
Definition: registers.c:108
float dt
Definition: px4io.c:73
uint16_t r_page_actuators[]
PAGE 2.
Definition: registers.c:101
RC protocol definition for S.BUS.
uint16_t r_page_rc_input[]
PAGE 5.
Definition: registers.c:130
int16_t r_page_servo_control_trim[]
PAGE 108.
Definition: registers.c:264
#define r_setup_trim_roll
Definition: px4io.h:126
void sbus1_output(int sbus_fd, uint16_t *values, uint16_t num_values)
Definition: sbus.cpp:237
#define PX4IO_P_STATUS_FLAGS_FAILSAFE
Definition: protocol.h:118
unsigned mix(float *outputs, unsigned space)
Definition: MixerGroup.cpp:53
PX4IO mixer definitions.
__EXPORT void up_pwm_servo_arm(bool armed)
Arm or disarm servo outputs.
#define PX4IO_P_SETUP_ARMING_FMU_PREARMED
Definition: protocol.h:185
uint16_t r_page_direct_pwm[]
PAGE 8.
Definition: registers.c:148
#define PX4IO_P_STATUS_FLAGS_OUTPUTS_ARMED
Definition: protocol.h:107
#define REG_TO_SIGNED(_reg)
Definition: protocol.h:75
#define PX4IO_P_SETUP_ARMING_LOCKDOWN
Definition: protocol.h:191
Group of mixers, built up from single mixers and processed in order when mixing.
Definition: MixerGroup.hpp:42
#define PX4IO_P_SETUP_FEATURES_SBUS2_OUT
enable S.Bus v2 output
Definition: protocol.h:178
char text[0]
Definition: protocol.h:320
static bool new_fmu_data
Definition: mixer.cpp:79
#define r_setup_thr_fac
Definition: px4io.h:133
uint16_t r_page_servo_failsafe[]
PAGE 105.
Definition: registers.c:240
Library for output limiting (PWM for example)
static volatile bool should_always_enable_pwm
Definition: mixer.cpp:76
#define PX4IO_CONTROL_GROUPS
Definition: px4io.h:67
__EXPORT void up_pwm_update(void)
Trigger all timer&#39;s channels in Oneshot mode to fire the oneshot with updated values.
#define PX4IO_P_SETUP_FEATURES_SBUS1_OUT
enable S.Bus v1 output
Definition: protocol.h:177
volatile uint64_t fmu_data_received_time
Last FMU receive time, in microseconds since system boot.
Definition: px4io.h:151
uint8_t action
Definition: protocol.h:316
#define REG_TO_BOOL(_reg)
Definition: protocol.h:81
static volatile bool in_mixer
Definition: mixer.cpp:77
#define r_setup_scale_pitch
Definition: px4io.h:130
#define r_setup_airmode
Definition: px4io.h:135
#define FMU_INPUT_DROP_LIMIT_US
Definition: mixer.cpp:70