PX4 Firmware
PX4 Autopilot Software http://px4.io
px4io.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2012-2019 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 px4io.cpp
36  * Driver for the PX4IO board.
37  *
38  * PX4IO is connected via DMA enabled high-speed UART.
39  */
40 
41 #include <px4_platform_common/px4_config.h>
42 #include <px4_platform_common/tasks.h>
43 #include <px4_platform_common/sem.hpp>
44 
45 #include <sys/types.h>
46 #include <stdint.h>
47 #include <stdbool.h>
48 #include <assert.h>
49 #include <debug.h>
50 #include <time.h>
51 #include <queue.h>
52 #include <errno.h>
53 #include <string.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <unistd.h>
57 #include <fcntl.h>
58 #include <math.h>
59 #include <crc32.h>
60 
61 #include <arch/board/board.h>
62 
63 #include <drivers/device/device.h>
64 #include <drivers/drv_rc_input.h>
65 #include <drivers/drv_pwm_output.h>
66 #include <drivers/drv_sbus.h>
67 #include <drivers/drv_hrt.h>
68 #include <drivers/drv_mixer.h>
69 
70 #include <rc/dsm.h>
71 
72 #include <lib/mathlib/mathlib.h>
73 #include <lib/mixer/MixerGroup.hpp>
75 #include <perf/perf_counter.h>
76 #include <systemlib/err.h>
77 #include <parameters/param.h>
79 #include <systemlib/mavlink_log.h>
80 
81 #include <uORB/Publication.hpp>
84 #include <uORB/Subscription.hpp>
88 #include <uORB/topics/safety.h>
95 #include <uORB/topics/test_motor.h>
96 
97 #include <debug.h>
98 
100 
101 #include "uploader.h"
102 
103 #include "modules/dataman/dataman.h"
104 
105 #include "px4io_driver.h"
106 
107 #define PX4IO_SET_DEBUG _IOC(0xff00, 0)
108 #define PX4IO_INAIR_RESTART_ENABLE _IOC(0xff00, 1)
109 #define PX4IO_REBOOT_BOOTLOADER _IOC(0xff00, 2)
110 #define PX4IO_CHECK_CRC _IOC(0xff00, 3)
111 
112 static constexpr unsigned UPDATE_INTERVAL_MIN{2}; // 2 ms -> 500 Hz
113 static constexpr unsigned UPDATE_INTERVAL_MAX{100}; // 100 ms -> 10 Hz
114 
115 #define ORB_CHECK_INTERVAL 200000 // 200 ms -> 5 Hz
116 #define IO_POLL_INTERVAL 20000 // 20 ms -> 50 Hz
117 
118 using namespace time_literals;
119 
120 /**
121  * The PX4IO class.
122  *
123  * Encapsulates PX4FMU to PX4IO communications modeled as file operations.
124  */
125 class PX4IO : public cdev::CDev
126 {
127 public:
128  /**
129  * Constructor.
130  *
131  * Initialize all class variables.
132  */
133  PX4IO(device::Device *interface);
134 
135  /**
136  * Destructor.
137  *
138  * Wait for worker thread to terminate.
139  */
140  virtual ~PX4IO();
141 
142  /**
143  * Initialize the PX4IO class.
144  *
145  * Retrieve relevant initial system parameters. Initialize PX4IO registers.
146  */
147  virtual int init();
148 
149  /**
150  * Initialize the PX4IO class.
151  *
152  * Retrieve relevant initial system parameters. Initialize PX4IO registers.
153  *
154  * @param disable_rc_handling set to true to forbid override / RC handling on IO
155  * @param hitl_mode set to suppress publication of actuator_outputs - instead defer to pwm_out_sim
156  */
157  int init(bool disable_rc_handling, bool hitl_mode);
158 
159  /**
160  * Detect if a PX4IO is connected.
161  *
162  * Only validate if there is a PX4IO to talk to.
163  */
164  virtual int detect();
165 
166  /**
167  * IO Control handler.
168  *
169  * Handle all IOCTL calls to the PX4IO file descriptor.
170  *
171  * @param[in] filp file handle (not used). This function is always called directly through object reference
172  * @param[in] cmd the IOCTL command
173  * @param[in] the IOCTL command parameter (optional)
174  */
175  virtual int ioctl(file *filp, int cmd, unsigned long arg);
176 
177  /**
178  * write handler.
179  *
180  * Handle writes to the PX4IO file descriptor.
181  *
182  * @param[in] filp file handle (not used). This function is always called directly through object reference
183  * @param[in] buffer pointer to the data buffer to be written
184  * @param[in] len size in bytes to be written
185  * @return number of bytes written
186  */
187  virtual ssize_t write(file *filp, const char *buffer, size_t len);
188 
189  /**
190  * Set the update rate for actuator outputs from FMU to IO.
191  *
192  * @param[in] rate The rate in Hz actuator outpus are sent to IO.
193  * Min 10 Hz, max 400 Hz
194  */
195  int set_update_rate(int rate);
196 
197  /**
198  * Disable RC input handling
199  */
200  int disable_rc_handling();
201 
202  /**
203  * Print IO status.
204  *
205  * Print all relevant IO status information
206  *
207  * @param extended_status Shows more verbose information (in particular RC config)
208  */
209  void print_status(bool extended_status);
210 
211  /**
212  * Fetch and print debug console output.
213  */
214  int print_debug();
215 
216  /*
217  * To test what happens if IO stops receiving updates from FMU.
218  *
219  * @param is_fail true for failure condition, false for normal operation.
220  */
221  void test_fmu_fail(bool is_fail)
222  {
223  _test_fmu_fail = is_fail;
224  };
225 
226  inline uint16_t system_status() const {return _status;}
227 
228 private:
230 
231  unsigned _hardware; ///< Hardware revision
232  unsigned _max_actuators; ///< Maximum # of actuators supported by PX4IO
233  unsigned _max_controls; ///< Maximum # of controls supported by PX4IO
234  unsigned _max_rc_input; ///< Maximum receiver channels supported by PX4IO
235  unsigned _max_relays; ///< Maximum relays supported by PX4IO
236  unsigned _max_transfer; ///< Maximum number of I2C transfers supported by PX4IO
237 
238  unsigned _update_interval; ///< Subscription interval limiting send rate
239  bool _rc_handling_disabled; ///< If set, IO does not evaluate, but only forward the RC values
240  unsigned _rc_chan_count; ///< Internal copy of the last seen number of RC channels
241  uint64_t _rc_last_valid; ///< last valid timestamp
242 
243  volatile int _task; ///< worker task id
244  volatile bool _task_should_exit; ///< worker terminate flag
245 
246  orb_advert_t _mavlink_log_pub; ///< mavlink log pub
247 
248  perf_counter_t _perf_update; ///< local performance counter for status updates
249  perf_counter_t _perf_write; ///< local performance counter for PWM control writes
250  perf_counter_t _perf_sample_latency; ///< total system latency (based on passed-through timestamp)
251 
252  /* cached IO state */
253  uint16_t _status; ///< Various IO status flags
254  uint16_t _alarms; ///< Various IO alarms
255  uint16_t _last_written_arming_s; ///< the last written arming state reg
256  uint16_t _last_written_arming_c; ///< the last written arming state reg
257 
258  /* subscribed topics */
259  int _t_actuator_controls_0; ///< actuator controls group 0 topic
260 
261  uORB::Subscription _t_actuator_controls_1{ORB_ID(actuator_controls_1)}; ///< actuator controls group 1 topic
262  uORB::Subscription _t_actuator_controls_2{ORB_ID(actuator_controls_2)};; ///< actuator controls group 2 topic
263  uORB::Subscription _t_actuator_controls_3{ORB_ID(actuator_controls_3)};; ///< actuator controls group 3 topic
264  uORB::Subscription _t_actuator_armed{ORB_ID(actuator_armed)}; ///< system armed control topic
265  uORB::Subscription _t_vehicle_control_mode{ORB_ID(vehicle_control_mode)}; ///< vehicle control mode topic
266  uORB::Subscription _parameter_update_sub{ORB_ID(parameter_update)}; ///< parameter update topic
267  uORB::Subscription _t_vehicle_command{ORB_ID(vehicle_command)}; ///< vehicle command topic
268 
269  bool _param_update_force; ///< force a parameter update
270 
271  /* advertised topics */
273  uORB::PublicationMulti<actuator_outputs_s> _to_outputs{ORB_ID(actuator_outputs)};
274  uORB::PublicationMulti<multirotor_motor_limits_s> _to_mixer_status{ORB_ID(multirotor_motor_limits)};
275  uORB::Publication<servorail_status_s> _to_servorail{ORB_ID(servorail_status)};
277 
278  bool _primary_pwm_device; ///< true if we are the default PWM output
279  bool _lockdown_override; ///< allow to override the safety lockdown
280  bool _armed; ///< wether the system is armed
281  bool _override_available; ///< true if manual reversion mode is enabled
282 
283  bool _cb_flighttermination; ///< true if the flight termination circuit breaker is enabled
284  bool _in_esc_calibration_mode; ///< do not send control outputs to IO (used for esc calibration)
285 
286  int32_t _rssi_pwm_chan; ///< RSSI PWM input channel
287  int32_t _rssi_pwm_max; ///< max RSSI input on PWM channel
288  int32_t _rssi_pwm_min; ///< min RSSI input on PWM channel
289  int32_t _thermal_control; ///< thermal control state
290  bool _analog_rc_rssi_stable; ///< true when analog RSSI input is stable
291  float _analog_rc_rssi_volt; ///< analog RSSI voltage
292 
293  bool _test_fmu_fail; ///< To test what happens if IO loses FMU
294 
295  struct MotorTest {
296  uORB::Subscription test_motor_sub{ORB_ID(test_motor)};
297  bool in_test_mode{false};
298  hrt_abstime timeout{0};
299  };
301  bool _hitl_mode; ///< Hardware-in-the-loop simulation mode - don't publish actuator_outputs
302 
303  /**
304  * Trampoline to the worker task
305  */
306  static void task_main_trampoline(int argc, char *argv[]);
307 
308  /**
309  * worker task
310  */
311  void task_main();
312 
313  /**
314  * Send controls for one group to IO
315  */
316  int io_set_control_state(unsigned group);
317 
318  /**
319  * Send all controls to IO
320  */
321  int io_set_control_groups();
322 
323  /**
324  * Update IO's arming-related state
325  */
326  int io_set_arming_state();
327 
328  /**
329  * Push RC channel configuration to IO.
330  */
331  int io_set_rc_config();
332 
333  /**
334  * Fetch status and alarms from IO
335  *
336  * Also publishes battery voltage/current.
337  */
338  int io_get_status();
339 
340  /**
341  * Disable RC input handling
342  */
343  int io_disable_rc_handling();
344 
345  /**
346  * Fetch RC inputs from IO.
347  *
348  * @param input_rc Input structure to populate.
349  * @return OK if data was returned.
350  */
351  int io_get_raw_rc_input(input_rc_s &input_rc);
352 
353  /**
354  * Fetch and publish raw RC input data.
355  */
356  int io_publish_raw_rc();
357 
358  /**
359  * Fetch and publish the PWM servo outputs.
360  */
361  int io_publish_pwm_outputs();
362 
363  /**
364  * write register(s)
365  *
366  * @param page Register page to write to.
367  * @param offset Register offset to start writing at.
368  * @param values Pointer to array of values to write.
369  * @param num_values The number of values to write.
370  * @return OK if all values were successfully written.
371  */
372  int io_reg_set(uint8_t page, uint8_t offset, const uint16_t *values, unsigned num_values);
373 
374  /**
375  * write a register
376  *
377  * @param page Register page to write to.
378  * @param offset Register offset to write to.
379  * @param value Value to write.
380  * @return OK if the value was written successfully.
381  */
382  int io_reg_set(uint8_t page, uint8_t offset, const uint16_t value);
383 
384  /**
385  * read register(s)
386  *
387  * @param page Register page to read from.
388  * @param offset Register offset to start reading from.
389  * @param values Pointer to array where values should be stored.
390  * @param num_values The number of values to read.
391  * @return OK if all values were successfully read.
392  */
393  int io_reg_get(uint8_t page, uint8_t offset, uint16_t *values, unsigned num_values);
394 
395  /**
396  * read a register
397  *
398  * @param page Register page to read from.
399  * @param offset Register offset to start reading from.
400  * @return Register value that was read, or _io_reg_get_error on error.
401  */
402  uint32_t io_reg_get(uint8_t page, uint8_t offset);
403  static const uint32_t _io_reg_get_error = 0x80000000;
404 
405  /**
406  * modify a register
407  *
408  * @param page Register page to modify.
409  * @param offset Register offset to modify.
410  * @param clearbits Bits to clear in the register.
411  * @param setbits Bits to set in the register.
412  */
413  int io_reg_modify(uint8_t page, uint8_t offset, uint16_t clearbits, uint16_t setbits);
414 
415  /**
416  * Send mixer definition text to IO
417  */
418  int mixer_send(const char *buf, unsigned buflen, unsigned retries = 3);
419 
420  /**
421  * Handle a status update from IO.
422  *
423  * Publish IO status information if necessary.
424  *
425  * @param status The status register
426  */
427  int io_handle_status(uint16_t status);
428 
429  /**
430  * Handle an alarm update from IO.
431  *
432  * Publish IO alarm information if necessary.
433  *
434  * @param alarm The status register
435  */
436  int io_handle_alarms(uint16_t alarms);
437 
438  /**
439  * Handle issuing dsm bind ioctl to px4io.
440  *
441  * @param dsmMode 0:dsm2, 1:dsmx
442  */
443  void dsm_bind_ioctl(int dsmMode);
444 
445  /**
446  * Handle a servorail update from IO.
447  *
448  * Publish servo rail information if necessary.
449  *
450  * @param vservo vservo register
451  * @param vrssi vrssi register
452  */
453  void io_handle_vservo(uint16_t vservo, uint16_t vrssi);
454 
455  /**
456  * check and handle test_motor topic updates
457  */
458  void handle_motor_test();
459 
460  /* do not allow to copy this class due to ptr data members */
461  PX4IO(const PX4IO &);
462  PX4IO operator=(const PX4IO &);
463 };
464 
465 namespace
466 {
467 PX4IO *g_dev = nullptr;
468 }
469 
470 #define PX4IO_DEVICE_PATH "/dev/px4io"
471 
473  CDev(PX4IO_DEVICE_PATH),
474  _interface(interface),
475  _hardware(0),
476  _max_actuators(0),
477  _max_controls(0),
478  _max_rc_input(0),
479  _max_relays(0),
480  _max_transfer(16), /* sensible default */
481  _update_interval(0),
482  _rc_handling_disabled(false),
483  _rc_chan_count(0),
484  _rc_last_valid(0),
485  _task(-1),
486  _task_should_exit(false),
487  _mavlink_log_pub(nullptr),
488  _perf_update(perf_alloc(PC_ELAPSED, "io update")),
489  _perf_write(perf_alloc(PC_ELAPSED, "io write")),
490  _perf_sample_latency(perf_alloc(PC_ELAPSED, "io control latency")),
491  _status(0),
492  _alarms(0),
493  _last_written_arming_s(0),
494  _last_written_arming_c(0),
495  _t_actuator_controls_0(-1),
496  _param_update_force(false),
497  _primary_pwm_device(false),
498  _lockdown_override(false),
499  _armed(false),
500  _override_available(false),
501  _cb_flighttermination(true),
502  _in_esc_calibration_mode(false),
503  _rssi_pwm_chan(0),
504  _rssi_pwm_max(0),
505  _rssi_pwm_min(0),
506  _thermal_control(-1),
507  _analog_rc_rssi_stable(false),
508  _analog_rc_rssi_volt(-1.0f),
509  _test_fmu_fail(false),
510  _hitl_mode(false)
511 {
512  /* we need this potentially before it could be set in task_main */
513  g_dev = this;
514 }
515 
517 {
518  /* tell the task we want it to go away */
519  _task_should_exit = true;
520 
521  /* spin waiting for the task to stop */
522  for (unsigned i = 0; (i < 10) && (_task != -1); i++) {
523  /* give it another 100ms */
524  px4_usleep(100000);
525  }
526 
527  /* well, kill it anyway, though this will probably crash */
528  if (_task != -1) {
529  task_delete(_task);
530  }
531 
532  if (_interface != nullptr) {
533  delete _interface;
534  }
535 
536  /* deallocate perfs */
540 
541  g_dev = nullptr;
542 }
543 
544 int
546 {
547  int ret;
548 
549  if (_task == -1) {
550 
551  /* do regular cdev init */
552  ret = CDev::init();
553 
554  if (ret != OK) {
555  return ret;
556  }
557 
558  /* get some parameters */
560 
561  if (protocol != PX4IO_PROTOCOL_VERSION) {
562  if (protocol == _io_reg_get_error) {
563  PX4_ERR("IO not installed");
564 
565  } else {
566  PX4_ERR("IO version error");
567  mavlink_log_emergency(&_mavlink_log_pub, "IO VERSION MISMATCH, PLEASE UPGRADE SOFTWARE!");
568  }
569 
570  return -1;
571  }
572  }
573 
574  PX4_INFO("IO found");
575 
576  return 0;
577 }
578 
579 int
580 PX4IO::init(bool rc_handling_disabled, bool hitl_mode)
581 {
582  _rc_handling_disabled = rc_handling_disabled;
583  _hitl_mode = hitl_mode;
584  return init();
585 }
586 
587 int
589 {
590  int ret;
591  param_t sys_restart_param;
592  int32_t sys_restart_val = DM_INIT_REASON_VOLATILE;
593 
594  sys_restart_param = param_find("SYS_RESTART_TYPE");
595 
596  if (sys_restart_param != PARAM_INVALID) {
597  /* Indicate restart type is unknown */
598  int32_t prev_val;
599  param_get(sys_restart_param, &prev_val);
600 
601  if (prev_val != DM_INIT_REASON_POWER_ON) {
602  param_set_no_notification(sys_restart_param, &sys_restart_val);
603  }
604  }
605 
606  /* do regular cdev init */
607  ret = CDev::init();
608 
609  if (ret != OK) {
610  return ret;
611  }
612 
613  /* get some parameters */
614  unsigned protocol;
615  hrt_abstime start_try_time = hrt_absolute_time();
616 
617  do {
618  px4_usleep(2000);
620  } while (protocol == _io_reg_get_error && (hrt_elapsed_time(&start_try_time) < 700U * 1000U));
621 
622  /* if the error still persists after timing out, we give up */
623  if (protocol == _io_reg_get_error) {
624  mavlink_log_emergency(&_mavlink_log_pub, "Failed to communicate with IO, abort.");
625  return -1;
626  }
627 
628  if (protocol != PX4IO_PROTOCOL_VERSION) {
629  mavlink_log_emergency(&_mavlink_log_pub, "IO protocol/firmware mismatch, abort.");
630  return -1;
631  }
632 
639 
640  if ((_max_actuators < 1) || (_max_actuators > 16) ||
641  (_max_relays > 32) ||
642  (_max_transfer < 16) || (_max_transfer > 255) ||
643  (_max_rc_input < 1) || (_max_rc_input > 255)) {
644 
645  PX4_ERR("config read error");
646  mavlink_log_emergency(&_mavlink_log_pub, "[IO] config read fail, abort.");
647 
648  // ask IO to reboot into bootloader as the failure may
649  // be due to mismatched firmware versions and we want
650  // the startup script to be able to load a new IO
651  // firmware
652 
653  // If IO has already safety off it won't accept going into bootloader mode,
654  // therefore we need to set safety on first.
656 
657  // Now the reboot into bootloader mode should succeed.
659  return -1;
660  }
661 
662  if (_max_rc_input > input_rc_s::RC_INPUT_MAX_CHANNELS) {
663  _max_rc_input = input_rc_s::RC_INPUT_MAX_CHANNELS;
664  }
665 
666  param_get(param_find("RC_RSSI_PWM_CHAN"), &_rssi_pwm_chan);
667  param_get(param_find("RC_RSSI_PWM_MAX"), &_rssi_pwm_max);
668  param_get(param_find("RC_RSSI_PWM_MIN"), &_rssi_pwm_min);
669 
670  /*
671  * Check for IO flight state - if FMU was flagged to be in
672  * armed state, FMU is recovering from an in-air reset.
673  * Read back status and request the commander to arm
674  * in this case.
675  */
676 
677  uint16_t reg;
678 
679  /* get IO's last seen FMU state */
680  ret = io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING, &reg, sizeof(reg));
681 
682  if (ret != OK) {
683  return ret;
684  }
685 
686  /*
687  * in-air restart is only tried if the IO board reports it is
688  * already armed, and has been configured for in-air restart
689  */
692 
693  /* get a status update from IO */
694  io_get_status();
695 
696  mavlink_log_emergency(&_mavlink_log_pub, "RECOVERING FROM FMU IN-AIR RESTART");
697 
698  /* WARNING: COMMANDER app/vehicle status must be initialized.
699  * If this fails (or the app is not started), worst-case IO
700  * remains untouched (so manual override is still available).
701  */
702 
703  uORB::Subscription actuator_armed_sub{ORB_ID(actuator_armed)};
704 
705  /* fill with initial values, clear updated flag */
706  actuator_armed_s actuator_armed{};
707  uint64_t try_start_time = hrt_absolute_time();
708 
709  /* keep checking for an update, ensure we got a arming information,
710  not something that was published a long time ago. */
711  do {
712  if (actuator_armed_sub.update(&actuator_armed)) {
713  // updated data, exit loop
714  break;
715  }
716 
717  /* wait 10 ms */
718  px4_usleep(10000);
719 
720  /* abort after 5s */
721  if ((hrt_absolute_time() - try_start_time) / 1000 > 3000) {
722  mavlink_log_emergency(&_mavlink_log_pub, "Failed to recover from in-air restart (1), abort");
723  return 1;
724  }
725 
726  } while (true);
727 
728  /* send this to itself */
729  param_t sys_id_param = param_find("MAV_SYS_ID");
730  param_t comp_id_param = param_find("MAV_COMP_ID");
731 
732  int32_t sys_id;
733  int32_t comp_id;
734 
735  if (param_get(sys_id_param, &sys_id)) {
736  errx(1, "PRM SYSID");
737  }
738 
739  if (param_get(comp_id_param, &comp_id)) {
740  errx(1, "PRM CMPID");
741  }
742 
743  /* prepare vehicle command */
744  vehicle_command_s vcmd = {};
745  vcmd.target_system = (uint8_t)sys_id;
746  vcmd.target_component = (uint8_t)comp_id;
747  vcmd.source_system = (uint8_t)sys_id;
748  vcmd.source_component = (uint8_t)comp_id;
749  vcmd.confirmation = true; /* ask to confirm command */
750 
752  mavlink_log_emergency(&_mavlink_log_pub, "IO is in failsafe, force failsafe");
753  /* send command to terminate flight via command API */
754  vcmd.timestamp = hrt_absolute_time();
755  vcmd.param1 = 1.0f; /* request flight termination */
756  vcmd.command = vehicle_command_s::VEHICLE_CMD_DO_FLIGHTTERMINATION;
757 
758  /* send command once */
759  uORB::PublicationQueued<vehicle_command_s> vcmd_pub{ORB_ID(vehicle_command)};
760  vcmd_pub.publish(vcmd);
761 
762  /* spin here until IO's state has propagated into the system */
763  do {
764  actuator_armed_sub.update(&actuator_armed);
765 
766  /* wait 50 ms */
767  px4_usleep(50000);
768 
769  /* abort after 5s */
770  if ((hrt_absolute_time() - try_start_time) / 1000 > 2000) {
771  mavlink_log_emergency(&_mavlink_log_pub, "Failed to recover from in-air restart (3), abort");
772  return 1;
773  }
774 
775  /* re-send if necessary */
776  if (!actuator_armed.force_failsafe) {
777  vcmd_pub.publish(vcmd);
778  PX4_WARN("re-sending flight termination cmd");
779  }
780 
781  /* keep waiting for state change for 2 s */
782  } while (!actuator_armed.force_failsafe);
783  }
784 
785  /* send command to arm system via command API */
786  vcmd.timestamp = hrt_absolute_time();
787  vcmd.param1 = 1.0f; /* request arming */
788  vcmd.command = vehicle_command_s::VEHICLE_CMD_COMPONENT_ARM_DISARM;
789 
790  /* send command once */
791  uORB::PublicationQueued<vehicle_command_s> vcmd_pub{ORB_ID(vehicle_command)};
792  vcmd_pub.publish(vcmd);
793 
794  /* spin here until IO's state has propagated into the system */
795  do {
796  actuator_armed_sub.update(&actuator_armed);
797 
798  /* wait 50 ms */
799  px4_usleep(50000);
800 
801  /* abort after 5s */
802  if ((hrt_absolute_time() - try_start_time) / 1000 > 2000) {
803  mavlink_log_emergency(&_mavlink_log_pub, "Failed to recover from in-air restart (2), abort");
804  return 1;
805  }
806 
807  /* re-send if necessary */
808  if (!actuator_armed.armed) {
809  vcmd_pub.publish(vcmd);
810  PX4_WARN("re-sending arm cmd");
811  }
812 
813  /* keep waiting for state change for 2 s */
814  } while (!actuator_armed.armed);
815 
816  /* Indicate restart type is in-flight */
817  sys_restart_val = DM_INIT_REASON_IN_FLIGHT;
818  int32_t prev_val;
819  param_get(sys_restart_param, &prev_val);
820 
821  if (prev_val != sys_restart_val) {
822  param_set(sys_restart_param, &sys_restart_val);
823  }
824 
825  /* regular boot, no in-air restart, init IO */
826 
827  } else {
828 
829  /* dis-arm IO before touching anything */
831  PX4IO_P_SETUP_ARMING_FMU_ARMED |
832  PX4IO_P_SETUP_ARMING_INAIR_RESTART_OK |
836 
837  if (_rc_handling_disabled) {
838  ret = io_disable_rc_handling();
839 
840  if (ret != OK) {
841  PX4_ERR("failed disabling RC handling");
842  return ret;
843  }
844 
845  } else {
846  /* publish RC config to IO */
847  ret = io_set_rc_config();
848 
849  if (ret != OK) {
850  mavlink_log_critical(&_mavlink_log_pub, "IO RC config upload fail");
851  return ret;
852  }
853  }
854 
855  /* Indicate restart type is power on */
856  sys_restart_val = DM_INIT_REASON_POWER_ON;
857  int32_t prev_val;
858  param_get(sys_restart_param, &prev_val);
859 
860  if (prev_val != sys_restart_val) {
861  param_set(sys_restart_param, &sys_restart_val);
862  }
863 
864  }
865 
866  /* set safety to off if circuit breaker enabled */
867  if (circuit_breaker_enabled("CBRK_IO_SAFETY", CBRK_IO_SAFETY_KEY)) {
869  }
870 
871  /* try to claim the generic PWM output device node as well - it's OK if we fail at this */
872  ret = register_driver(PWM_OUTPUT0_DEVICE_PATH, &fops, 0666, (void *)this);
873 
874  if (ret == OK) {
875  PX4_INFO("default PWM output device");
876  _primary_pwm_device = true;
877  }
878 
879  /* start the IO interface task */
880  _task = px4_task_spawn_cmd("px4io",
881  SCHED_DEFAULT,
882  SCHED_PRIORITY_ACTUATOR_OUTPUTS,
883  1500,
885  nullptr);
886 
887  if (_task < 0) {
888  PX4_ERR("task start failed: %d", errno);
889  return -errno;
890  }
891 
892  return OK;
893 }
894 
895 void
896 PX4IO::task_main_trampoline(int argc, char *argv[])
897 {
898  g_dev->task_main();
899 }
900 
901 void
903 {
904  hrt_abstime poll_last = 0;
905  hrt_abstime orb_check_last = 0;
906 
907  /*
908  * Subscribe to the appropriate PWM output topic based on whether we are the
909  * primary PWM output or not.
910  */
911  _t_actuator_controls_0 = orb_subscribe(ORB_ID(actuator_controls_0));
912  orb_set_interval(_t_actuator_controls_0, 20); /* default to 50Hz */
913 
914  if (_t_actuator_controls_0 < 0) {
915  PX4_ERR("actuator subscription failed");
916  goto out;
917  }
918 
919  /* Fetch initial flight termination circuit breaker state */
921 
922  /* poll descriptor */
923  pollfd fds[1];
924  fds[0].fd = _t_actuator_controls_0;
925  fds[0].events = POLLIN;
926 
927  _param_update_force = true;
928 
929  /* lock against the ioctl handler */
930  lock();
931 
932  /* loop talking to IO */
933  while (!_task_should_exit) {
934 
935  /* adjust update interval */
936  if (_update_interval != 0) {
938 
940  /*
941  * NOT changing the rate of groups 1-3 here, because only attitude
942  * really needs to run fast.
943  */
944  _update_interval = 0;
945  }
946 
947  /* sleep waiting for topic updates, but no more than 20ms */
948  unlock();
949  int ret = ::poll(fds, 1, 20);
950  lock();
951 
952  /* this would be bad... */
953  if (ret < 0) {
954  warnx("poll error %d", errno);
955  continue;
956  }
957 
960 
961  /* if we have new control data from the ORB, handle it */
962  if (fds[0].revents & POLLIN) {
963 
964  /* we're not nice to the lower-priority control groups and only check them
965  when the primary group updated (which is now). */
966  (void)io_set_control_groups();
967  }
968 
969  if (!_armed && !_lockdown_override) {
971 
972  } else {
973  _motor_test.in_test_mode = false;
974  }
975 
976  if (now >= poll_last + IO_POLL_INTERVAL) {
977  /* run at 50-250Hz */
978  poll_last = now;
979 
980  /* pull status and alarms from IO */
981  io_get_status();
982 
983  /* get raw R/C input from IO */
985 
986  /* fetch PWM outputs from IO */
988 
989  /* check updates on uORB topics and handle it */
990  bool updated = false;
991 
992  /* arming state */
993  updated = _t_actuator_armed.updated();
994 
995  if (!updated) {
996  updated = _t_vehicle_control_mode.updated();
997  }
998 
999  if (updated) {
1001  }
1002  }
1003 
1004  if (!_armed && (now >= orb_check_last + ORB_CHECK_INTERVAL)) {
1005  /* run at 5Hz */
1006  orb_check_last = now;
1007 
1008  /* vehicle command */
1009  if (_t_vehicle_command.updated()) {
1010  vehicle_command_s cmd{};
1011  _t_vehicle_command.copy(&cmd);
1012 
1013  // Check for a DSM pairing command
1014  if (((unsigned int)cmd.command == vehicle_command_s::VEHICLE_CMD_START_RX_PAIR) && ((int)cmd.param1 == 0)) {
1015  dsm_bind_ioctl((int)cmd.param2);
1016  }
1017  }
1018 
1019  /*
1020  * If parameters have changed, re-send RC mappings to IO
1021  *
1022  * XXX this may be a bit spammy
1023  */
1024 
1025  // check for parameter updates
1027  // clear update
1028  parameter_update_s pupdate;
1029  _parameter_update_sub.copy(&pupdate);
1030 
1031  _param_update_force = false;
1032 
1033  if (!_rc_handling_disabled) {
1034  /* re-upload RC input config as it may have changed */
1035  io_set_rc_config();
1036  }
1037 
1038  /* send RC throttle failsafe value to IO */
1039  int32_t failsafe_param_val;
1040  param_t failsafe_param = param_find("RC_FAILS_THR");
1041 
1042  if (failsafe_param != PARAM_INVALID) {
1043 
1044  param_get(failsafe_param, &failsafe_param_val);
1045 
1046  if (failsafe_param_val > 0) {
1047 
1048  uint16_t failsafe_thr = failsafe_param_val;
1049  int pret = io_reg_set(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_RC_THR_FAILSAFE_US, &failsafe_thr, 1);
1050 
1051  if (pret != OK) {
1052  mavlink_log_critical(&_mavlink_log_pub, "failsafe upload failed, FS: %d us", (int)failsafe_thr);
1053  }
1054  }
1055  }
1056 
1057  /* Check if the IO safety circuit breaker has been updated */
1058  bool circuit_breaker_io_safety_enabled = circuit_breaker_enabled("CBRK_IO_SAFETY", CBRK_IO_SAFETY_KEY);
1059  /* Bypass IO safety switch logic by setting FORCE_SAFETY_OFF */
1060  (void)io_reg_set(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FORCE_SAFETY_OFF, circuit_breaker_io_safety_enabled);
1061 
1062  /* Check if the flight termination circuit breaker has been updated */
1064  /* Tell IO that it can terminate the flight if FMU is not responding or if a failure has been reported by the FailureDetector logic */
1066 
1067  param_get(param_find("RC_RSSI_PWM_CHAN"), &_rssi_pwm_chan);
1068  param_get(param_find("RC_RSSI_PWM_MAX"), &_rssi_pwm_max);
1069  param_get(param_find("RC_RSSI_PWM_MIN"), &_rssi_pwm_min);
1070 
1071  param_t thermal_param = param_find("SENS_EN_THERMAL");
1072 
1073  if (thermal_param != PARAM_INVALID) {
1074 
1075  int32_t thermal_p;
1076  param_get(thermal_param, &thermal_p);
1077 
1078  if (thermal_p != _thermal_control || _param_update_force) {
1079 
1080  _thermal_control = thermal_p;
1081  /* set power management state for thermal */
1082  uint16_t tctrl;
1083 
1084  if (_thermal_control < 0) {
1085  tctrl = PX4IO_THERMAL_IGNORE;
1086 
1087  } else {
1088  tctrl = PX4IO_THERMAL_OFF;
1089  }
1090 
1092  }
1093  }
1094 
1095  /*
1096  * Set invert mask for PWM outputs (does not apply to S.Bus)
1097  */
1098  int16_t pwm_invert_mask = 0;
1099 
1100  for (unsigned i = 0; i < _max_actuators; i++) {
1101  char pname[16];
1102  int32_t ival;
1103 
1104  /* fill the channel reverse mask from parameters */
1105  sprintf(pname, "PWM_MAIN_REV%u", i + 1);
1106  param_t param_h = param_find(pname);
1107 
1108  if (param_h != PARAM_INVALID) {
1109  param_get(param_h, &ival);
1110  pwm_invert_mask |= ((int16_t)(ival != 0)) << i;
1111  }
1112  }
1113 
1114  (void)io_reg_set(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_REVERSE, pwm_invert_mask);
1115 
1116  // update trim values
1117  struct pwm_output_values pwm_values;
1118 
1119 // memset(&pwm_values, 0, sizeof(pwm_values));
1120 // ret = io_reg_get(PX4IO_PAGE_CONTROL_TRIM_PWM, 0, (uint16_t *)pwm_values.values, _max_actuators);
1121 
1122  for (unsigned i = 0; i < _max_actuators; i++) {
1123  char pname[16];
1124  float pval;
1125 
1126  /* fetch the trim values from parameters */
1127  sprintf(pname, "PWM_MAIN_TRIM%u", i + 1);
1128  param_t param_h = param_find(pname);
1129 
1130  if (param_h != PARAM_INVALID) {
1131 
1132  param_get(param_h, &pval);
1133  pwm_values.values[i] = (int16_t)(10000 * pval);
1134  }
1135  }
1136 
1137  /* copy values to registers in IO */
1138  ret = io_reg_set(PX4IO_PAGE_CONTROL_TRIM_PWM, 0, pwm_values.values, _max_actuators);
1139 
1140  float param_val;
1141  param_t parm_handle;
1142 
1143  parm_handle = param_find("TRIM_ROLL");
1144 
1145  if (parm_handle != PARAM_INVALID) {
1146  param_get(parm_handle, &param_val);
1148  }
1149 
1150  parm_handle = param_find("TRIM_PITCH");
1151 
1152  if (parm_handle != PARAM_INVALID) {
1153  param_get(parm_handle, &param_val);
1155  }
1156 
1157  parm_handle = param_find("TRIM_YAW");
1158 
1159  if (parm_handle != PARAM_INVALID) {
1160  param_get(parm_handle, &param_val);
1162  }
1163 
1164  parm_handle = param_find("FW_MAN_R_SC");
1165 
1166  if (parm_handle != PARAM_INVALID) {
1167  param_get(parm_handle, &param_val);
1169  }
1170 
1171  parm_handle = param_find("FW_MAN_P_SC");
1172 
1173  if (parm_handle != PARAM_INVALID) {
1174  param_get(parm_handle, &param_val);
1176  }
1177 
1178  parm_handle = param_find("FW_MAN_Y_SC");
1179 
1180  if (parm_handle != PARAM_INVALID) {
1181  param_get(parm_handle, &param_val);
1183  }
1184 
1185  /* S.BUS output */
1186  int sbus_mode;
1187  parm_handle = param_find("PWM_SBUS_MODE");
1188 
1189  if (parm_handle != PARAM_INVALID) {
1190  param_get(parm_handle, &sbus_mode);
1191 
1192  if (sbus_mode == 1) {
1193  /* enable S.BUS 1 */
1195 
1196  } else if (sbus_mode == 2) {
1197  /* enable S.BUS 2 */
1199 
1200  } else {
1201  /* disable S.BUS */
1204  }
1205  }
1206 
1207  /* thrust to pwm modelling factor */
1208  parm_handle = param_find("THR_MDL_FAC");
1209 
1210  if (parm_handle != PARAM_INVALID) {
1211  param_get(parm_handle, &param_val);
1213  }
1214 
1215  /* maximum motor pwm slew rate */
1216  parm_handle = param_find("MOT_SLEW_MAX");
1217 
1218  if (parm_handle != PARAM_INVALID) {
1219  param_get(parm_handle, &param_val);
1221  }
1222 
1223  /* air-mode */
1224  parm_handle = param_find("MC_AIRMODE");
1225 
1226  if (parm_handle != PARAM_INVALID) {
1227  int32_t param_val_int;
1228  param_get(parm_handle, &param_val_int);
1230  }
1231  }
1232 
1233  }
1234 
1236  }
1237 
1238  unlock();
1239 
1240 out:
1241  PX4_DEBUG("exiting");
1242 
1243  /* clean up the alternate device node */
1244  if (_primary_pwm_device) {
1246  }
1247 
1248  /* tell the dtor that we are exiting */
1249  _task = -1;
1250  _exit(0);
1251 }
1252 
1253 int
1255 {
1256  int ret = io_set_control_state(0);
1257 
1258  /* send auxiliary control groups */
1259  (void)io_set_control_state(1);
1260  (void)io_set_control_state(2);
1261  (void)io_set_control_state(3);
1262 
1263  return ret;
1264 }
1265 
1266 int
1268 {
1269  actuator_controls_s controls{}; ///< actuator outputs
1270 
1271  /* get controls */
1272  bool changed = false;
1273 
1274  switch (group) {
1275  case 0: {
1276  orb_check(_t_actuator_controls_0, &changed);
1277 
1278  if (changed) {
1279  orb_copy(ORB_ID(actuator_controls_0), _t_actuator_controls_0, &controls);
1280  perf_set_elapsed(_perf_sample_latency, hrt_elapsed_time(&controls.timestamp_sample));
1281  }
1282  }
1283  break;
1284 
1285  case 1:
1286  changed = _t_actuator_controls_1.update(&controls);
1287  break;
1288 
1289  case 2:
1290  changed = _t_actuator_controls_2.update(&controls);
1291  break;
1292 
1293  case 3:
1294  changed = _t_actuator_controls_3.update(&controls);
1295  break;
1296  }
1297 
1298  if (!changed && (!_in_esc_calibration_mode || group != 0)) {
1299  return -1;
1300 
1301  } else if (_in_esc_calibration_mode && group == 0) {
1302  /* modify controls to get max pwm (full thrust) on every esc */
1303  memset(&controls, 0, sizeof(controls));
1304 
1305  /* set maximum thrust */
1306  controls.control[3] = 1.0f;
1307  }
1308 
1309  uint16_t regs[_max_actuators];
1310 
1311  for (unsigned i = 0; i < _max_controls; i++) {
1312  /* ensure FLOAT_TO_REG does not produce an integer overflow */
1313  const float ctrl = math::constrain(controls.control[i], -1.0f, 1.0f);
1314 
1315  if (!isfinite(ctrl)) {
1316  regs[i] = INT16_MAX;
1317 
1318  } else {
1319  regs[i] = FLOAT_TO_REG(ctrl);
1320  }
1321 
1322 
1323  }
1324 
1326  /* copy values to registers in IO */
1327  return io_reg_set(PX4IO_PAGE_CONTROLS, group * PX4IO_PROTOCOL_MAX_CONTROL_COUNT, regs, _max_controls);
1328 
1329  } else {
1330  return OK;
1331  }
1332 }
1333 
1334 void
1336 {
1337  test_motor_s test_motor;
1338 
1339  while (_motor_test.test_motor_sub.update(&test_motor)) {
1340  if (test_motor.driver_instance != 0 ||
1341  hrt_elapsed_time(&test_motor.timestamp) > 100_ms) {
1342  continue;
1343  }
1344 
1345  bool in_test_mode = test_motor.action == test_motor_s::ACTION_RUN;
1346 
1347  if (in_test_mode != _motor_test.in_test_mode) {
1348  // reset all outputs to disarmed on state change
1349  pwm_output_values pwm_disarmed;
1350 
1351  if (io_reg_get(PX4IO_PAGE_DISARMED_PWM, 0, pwm_disarmed.values, _max_actuators) == 0) {
1352  for (unsigned i = 0; i < _max_actuators; ++i) {
1353  io_reg_set(PX4IO_PAGE_DIRECT_PWM, i, pwm_disarmed.values[i]);
1354  }
1355  }
1356  }
1357 
1358  if (in_test_mode) {
1359  unsigned idx = test_motor.motor_number;
1360 
1361  if (idx < _max_actuators) {
1362  if (test_motor.value < 0.f) {
1363  pwm_output_values pwm_disarmed;
1364 
1365  if (io_reg_get(PX4IO_PAGE_DISARMED_PWM, 0, pwm_disarmed.values, _max_actuators) == 0) {
1366  io_reg_set(PX4IO_PAGE_DIRECT_PWM, idx, pwm_disarmed.values[idx]);
1367  }
1368 
1369  } else {
1370  pwm_output_values pwm_min;
1371  pwm_output_values pwm_max;
1372 
1375 
1376  uint16_t value = math::constrain<uint16_t>(pwm_min.values[idx] +
1377  (uint16_t)((pwm_max.values[idx] - pwm_min.values[idx]) * test_motor.value),
1378  pwm_min.values[idx], pwm_max.values[idx]);
1379  io_reg_set(PX4IO_PAGE_DIRECT_PWM, idx, value);
1380  }
1381  }
1382  }
1383 
1384  if (test_motor.timeout_ms > 0) {
1385  _motor_test.timeout = test_motor.timestamp + test_motor.timeout_ms * 1000;
1386 
1387  } else {
1388  _motor_test.timeout = 0;
1389  }
1390  }
1391 
1392  _motor_test.in_test_mode = in_test_mode;
1393  }
1394 
1395  // check for timeouts
1397  _motor_test.in_test_mode = false;
1398  _motor_test.timeout = 0;
1399  }
1400 }
1401 
1402 int
1404 {
1405  uint16_t set = 0;
1406  uint16_t clear = 0;
1407 
1409 
1410  if (_t_actuator_armed.copy(&armed)) {
1412 
1413  if (armed.armed || _in_esc_calibration_mode) {
1415 
1416  } else {
1418  }
1419 
1420  _armed = armed.armed;
1421 
1422  if (armed.prearmed) {
1424 
1425  } else {
1427  }
1428 
1429  if ((armed.lockdown || armed.manual_lockdown) && !_lockdown_override) {
1431  _lockdown_override = true;
1432 
1433  } else if (!(armed.lockdown || armed.manual_lockdown) && _lockdown_override) {
1435  _lockdown_override = false;
1436  }
1437 
1438  if (armed.force_failsafe) {
1440 
1441  } else {
1443  }
1444 
1445  // XXX this is for future support in the commander
1446  // but can be removed if unneeded
1447  // if (armed.termination_failsafe) {
1448  // set |= PX4IO_P_SETUP_ARMING_TERMINATION_FAILSAFE;
1449  // } else {
1450  // clear |= PX4IO_P_SETUP_ARMING_TERMINATION_FAILSAFE;
1451  // }
1452 
1453  if (armed.ready_to_arm) {
1455 
1456  } else {
1458  }
1459  }
1460 
1461  vehicle_control_mode_s control_mode;
1462 
1463  if (_t_vehicle_control_mode.copy(&control_mode)) {
1464  if (control_mode.flag_external_manual_override_ok) {
1466  _override_available = true;
1467 
1468  } else {
1470  _override_available = false;
1471  }
1472  }
1473 
1474  if (_last_written_arming_s != set || _last_written_arming_c != clear) {
1475  _last_written_arming_s = set;
1476  _last_written_arming_c = clear;
1478  }
1479 
1480  return 0;
1481 }
1482 
1483 int
1485 {
1486  _rc_handling_disabled = true;
1487  return io_disable_rc_handling();
1488 }
1489 
1490 int
1492 {
1494  uint16_t clear = 0;
1495 
1497 }
1498 
1499 int
1501 {
1502  unsigned offset = 0;
1503  int input_map[_max_rc_input];
1504  int32_t ichan;
1505  int ret = OK;
1506 
1507  /*
1508  * Generate the input channel -> control channel mapping table;
1509  * assign RC_MAP_ROLL/PITCH/YAW/THROTTLE to the canonical
1510  * controls.
1511  */
1512 
1513  /* fill the mapping with an error condition triggering value */
1514  for (unsigned i = 0; i < _max_rc_input; i++) {
1515  input_map[i] = UINT8_MAX;
1516  }
1517 
1518  /*
1519  * NOTE: The indices for mapped channels are 1-based
1520  * for compatibility reasons with existing
1521  * autopilots / GCS'.
1522  */
1523 
1524  /* ROLL */
1525  param_get(param_find("RC_MAP_ROLL"), &ichan);
1526 
1527  if ((ichan > 0) && (ichan <= (int)_max_rc_input)) {
1528  input_map[ichan - 1] = 0;
1529  }
1530 
1531  /* PITCH */
1532  param_get(param_find("RC_MAP_PITCH"), &ichan);
1533 
1534  if ((ichan > 0) && (ichan <= (int)_max_rc_input)) {
1535  input_map[ichan - 1] = 1;
1536  }
1537 
1538  /* YAW */
1539  param_get(param_find("RC_MAP_YAW"), &ichan);
1540 
1541  if ((ichan > 0) && (ichan <= (int)_max_rc_input)) {
1542  input_map[ichan - 1] = 2;
1543  }
1544 
1545  /* THROTTLE */
1546  param_get(param_find("RC_MAP_THROTTLE"), &ichan);
1547 
1548  if ((ichan > 0) && (ichan <= (int)_max_rc_input)) {
1549  input_map[ichan - 1] = 3;
1550  }
1551 
1552  /* FLAPS */
1553  param_get(param_find("RC_MAP_FLAPS"), &ichan);
1554 
1555  if ((ichan > 0) && (ichan <= (int)_max_rc_input)) {
1556  input_map[ichan - 1] = 4;
1557  }
1558 
1559  /* AUX 1*/
1560  param_get(param_find("RC_MAP_AUX1"), &ichan);
1561 
1562  if ((ichan > 0) && (ichan <= (int)_max_rc_input)) {
1563  input_map[ichan - 1] = 5;
1564  }
1565 
1566  /* AUX 2*/
1567  param_get(param_find("RC_MAP_AUX2"), &ichan);
1568 
1569  if ((ichan > 0) && (ichan <= (int)_max_rc_input)) {
1570  input_map[ichan - 1] = 6;
1571  }
1572 
1573  /* AUX 3*/
1574  param_get(param_find("RC_MAP_AUX3"), &ichan);
1575 
1576  if ((ichan > 0) && (ichan <= (int)_max_rc_input)) {
1577  input_map[ichan - 1] = 7;
1578  }
1579 
1580  /* MAIN MODE SWITCH */
1581  param_get(param_find("RC_MAP_MODE_SW"), &ichan);
1582 
1583  if ((ichan > 0) && (ichan <= (int)_max_rc_input)) {
1584  /* use out of normal bounds index to indicate special channel */
1585  input_map[ichan - 1] = PX4IO_P_RC_CONFIG_ASSIGNMENT_MODESWITCH;
1586  }
1587 
1588  /*
1589  * Iterate all possible RC inputs.
1590  */
1591  for (unsigned i = 0; i < _max_rc_input; i++) {
1592  uint16_t regs[PX4IO_P_RC_CONFIG_STRIDE];
1593  char pname[16];
1594  float fval;
1595 
1596  /*
1597  * RC params are floats, but do only
1598  * contain integer values. Do not scale
1599  * or cast them, let the auto-typeconversion
1600  * do its job here.
1601  * Channels: 500 - 2500
1602  * Inverted flag: -1 (inverted) or 1 (normal)
1603  */
1604 
1605  sprintf(pname, "RC%u_MIN", i + 1);
1606  param_get(param_find(pname), &fval);
1607  regs[PX4IO_P_RC_CONFIG_MIN] = fval;
1608 
1609  sprintf(pname, "RC%u_TRIM", i + 1);
1610  param_get(param_find(pname), &fval);
1611  regs[PX4IO_P_RC_CONFIG_CENTER] = fval;
1612 
1613  sprintf(pname, "RC%u_MAX", i + 1);
1614  param_get(param_find(pname), &fval);
1615  regs[PX4IO_P_RC_CONFIG_MAX] = fval;
1616 
1617  sprintf(pname, "RC%u_DZ", i + 1);
1618  param_get(param_find(pname), &fval);
1619  regs[PX4IO_P_RC_CONFIG_DEADZONE] = fval;
1620 
1621  regs[PX4IO_P_RC_CONFIG_ASSIGNMENT] = input_map[i];
1622 
1624  sprintf(pname, "RC%u_REV", i + 1);
1625  param_get(param_find(pname), &fval);
1626 
1627  /*
1628  * This has been taken for the sake of compatibility
1629  * with APM's setup / mission planner: normal: 1,
1630  * inverted: -1
1631  */
1632  if (fval < 0) {
1634  }
1635 
1636  /* send channel config to IO */
1638 
1639  if (ret != OK) {
1640  PX4_ERR("rc config upload failed");
1641  break;
1642  }
1643 
1644  /* check the IO initialisation flag */
1646  mavlink_log_critical(&_mavlink_log_pub, "config for RC%u rejected by IO", i + 1);
1647  break;
1648  }
1649 
1650  offset += PX4IO_P_RC_CONFIG_STRIDE;
1651  }
1652 
1653  return ret;
1654 }
1655 
1656 int
1658 {
1659  int ret = 1;
1660  /**
1661  * WARNING: This section handles in-air resets.
1662  */
1663 
1664  /* check for IO reset - force it back to armed if necessary */
1666  && !(status & PX4IO_P_STATUS_FLAGS_ARM_SYNC)) {
1667  /* set the arming flag */
1669  PX4IO_P_STATUS_FLAGS_SAFETY_OFF | PX4IO_P_STATUS_FLAGS_ARM_SYNC);
1670 
1671  /* set new status */
1672  _status = status;
1674 
1675  } else if (!(_status & PX4IO_P_STATUS_FLAGS_ARM_SYNC)) {
1676 
1677  /* set the sync flag */
1678  ret = io_reg_modify(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_FLAGS, 0, PX4IO_P_STATUS_FLAGS_ARM_SYNC);
1679  /* set new status */
1680  _status = status;
1681 
1682  } else {
1683  ret = 0;
1684 
1685  /* set new status */
1686  _status = status;
1687  }
1688 
1689  /**
1690  * Get and handle the safety status
1691  */
1692  safety_s safety{};
1695  safety.safety_off = (status & PX4IO_P_STATUS_FLAGS_SAFETY_OFF) ? true : false;
1697  safety.override_enabled = (status & PX4IO_P_STATUS_FLAGS_OVERRIDE) ? true : false;
1698 
1700 
1701  return ret;
1702 }
1703 
1704 void
1706 {
1708  mavlink_log_info(&_mavlink_log_pub, "[IO] binding DSM%s RX", (dsmMode == 0) ? "2" : ((dsmMode == 1) ? "-X" : "-X8"));
1709  int ret = ioctl(nullptr, DSM_BIND_START,
1710  (dsmMode == 0) ? DSM2_BIND_PULSES : ((dsmMode == 1) ? DSMX_BIND_PULSES : DSMX8_BIND_PULSES));
1711 
1712  if (ret) {
1713  mavlink_log_critical(&_mavlink_log_pub, "binding failed.");
1714  }
1715 
1716  } else {
1717  mavlink_log_info(&_mavlink_log_pub, "[IO] safety off, bind request rejected");
1718  }
1719 }
1720 
1721 
1722 int
1723 PX4IO::io_handle_alarms(uint16_t alarms)
1724 {
1725 
1726  /* XXX handle alarms */
1727 
1728 
1729  /* set new alarms state */
1730  _alarms = alarms;
1731 
1732  return 0;
1733 }
1734 
1735 void
1736 PX4IO::io_handle_vservo(uint16_t vservo, uint16_t vrssi)
1737 {
1738  servorail_status_s servorail_status{};
1739 
1740  servorail_status.timestamp = hrt_absolute_time();
1741 
1742  /* voltage is scaled to mV */
1743  servorail_status.voltage_v = vservo * 0.001f;
1744  servorail_status.rssi_v = vrssi * 0.001f;
1745 
1746  if (_analog_rc_rssi_volt < 0.0f) {
1747  _analog_rc_rssi_volt = servorail_status.rssi_v;
1748  }
1749 
1750  _analog_rc_rssi_volt = _analog_rc_rssi_volt * 0.99f + servorail_status.rssi_v * 0.01f;
1751 
1752  if (_analog_rc_rssi_volt > 2.5f) {
1753  _analog_rc_rssi_stable = true;
1754  }
1755 
1756  /* lazily publish the servorail voltages */
1757  _to_servorail.publish(servorail_status);
1758 }
1759 
1760 int
1762 {
1763  uint16_t regs[6];
1764  int ret;
1765 
1766  /* get
1767  * STATUS_FLAGS, STATUS_ALARMS, STATUS_VBATT, STATUS_IBATT,
1768  * STATUS_VSERVO, STATUS_VRSSI, STATUS_PRSSI
1769  * in that order */
1770  ret = io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_FLAGS, &regs[0], sizeof(regs) / sizeof(regs[0]));
1771 
1772  if (ret != OK) {
1773  return ret;
1774  }
1775 
1776  io_handle_status(regs[0]);
1777  io_handle_alarms(regs[1]);
1778 
1779  io_handle_vservo(regs[4], regs[5]);
1780 
1781  return ret;
1782 }
1783 
1784 int
1786 {
1787  uint32_t channel_count;
1788  int ret;
1789 
1790  /* we don't have the status bits, so input_source has to be set elsewhere */
1791  input_rc.input_source = input_rc_s::RC_INPUT_SOURCE_UNKNOWN;
1792 
1793  const unsigned prolog = (PX4IO_P_RAW_RC_BASE - PX4IO_P_RAW_RC_COUNT);
1794  uint16_t regs[input_rc_s::RC_INPUT_MAX_CHANNELS + prolog];
1795 
1796  /*
1797  * Read the channel count and the first 9 channels.
1798  *
1799  * This should be the common case (9 channel R/C control being a reasonable upper bound).
1800  */
1801  ret = io_reg_get(PX4IO_PAGE_RAW_RC_INPUT, PX4IO_P_RAW_RC_COUNT, &regs[0], prolog + 9);
1802 
1803  if (ret != OK) {
1804  return ret;
1805  }
1806 
1807  /*
1808  * Get the channel count any any extra channels. This is no more expensive than reading the
1809  * channel count once.
1810  */
1811  channel_count = regs[PX4IO_P_RAW_RC_COUNT];
1812 
1813  /* limit the channel count */
1814  if (channel_count > input_rc_s::RC_INPUT_MAX_CHANNELS) {
1815  channel_count = input_rc_s::RC_INPUT_MAX_CHANNELS;
1816  }
1817 
1819 
1820  input_rc.timestamp = hrt_absolute_time();
1821 
1822  input_rc.rc_ppm_frame_length = regs[PX4IO_P_RAW_RC_DATA];
1823 
1824  if (!_analog_rc_rssi_stable) {
1825  input_rc.rssi = regs[PX4IO_P_RAW_RC_NRSSI];
1826 
1827  } else {
1828  float rssi_analog = ((_analog_rc_rssi_volt - 0.2f) / 3.0f) * 100.0f;
1829 
1830  if (rssi_analog > 100.0f) {
1831  rssi_analog = 100.0f;
1832  }
1833 
1834  if (rssi_analog < 0.0f) {
1835  rssi_analog = 0.0f;
1836  }
1837 
1838  input_rc.rssi = rssi_analog;
1839  }
1840 
1845  input_rc.channel_count = channel_count;
1846 
1847  /* rc_lost has to be set before the call to this function */
1848  if (!input_rc.rc_lost && !input_rc.rc_failsafe) {
1849  _rc_last_valid = input_rc.timestamp;
1850  }
1851 
1853 
1854  /* FIELDS NOT SET HERE */
1855  /* input_rc.input_source is set after this call XXX we might want to mirror the flags in the RC struct */
1856 
1857  if (channel_count > 9) {
1858  ret = io_reg_get(PX4IO_PAGE_RAW_RC_INPUT, PX4IO_P_RAW_RC_BASE + 9, &regs[prolog + 9], channel_count - 9);
1859 
1860  if (ret != OK) {
1861  return ret;
1862  }
1863  }
1864 
1865  /* last thing set are the actual channel values as 16 bit values */
1866  for (unsigned i = 0; i < channel_count; i++) {
1867  input_rc.values[i] = regs[prolog + i];
1868  }
1869 
1870  /* zero the remaining fields */
1871  for (unsigned i = channel_count; i < (sizeof(input_rc.values) / sizeof(input_rc.values[0])); i++) {
1872  input_rc.values[i] = 0;
1873  }
1874 
1875  /* get RSSI from input channel */
1876  if (_rssi_pwm_chan > 0 && _rssi_pwm_chan <= input_rc_s::RC_INPUT_MAX_CHANNELS && _rssi_pwm_max - _rssi_pwm_min != 0) {
1877  int rssi = ((input_rc.values[_rssi_pwm_chan - 1] - _rssi_pwm_min) * 100) /
1879  rssi = rssi > 100 ? 100 : rssi;
1880  rssi = rssi < 0 ? 0 : rssi;
1881  input_rc.rssi = rssi;
1882  }
1883 
1884  return ret;
1885 }
1886 
1887 int
1889 {
1890 
1891  /* fetch values from IO */
1892  input_rc_s rc_val;
1893 
1894  /* set the RC status flag ORDER MATTERS! */
1896 
1897  int ret = io_get_raw_rc_input(rc_val);
1898 
1899  if (ret != OK) {
1900  return ret;
1901  }
1902 
1903  /* sort out the source of the values */
1905  rc_val.input_source = input_rc_s::RC_INPUT_SOURCE_PX4IO_PPM;
1906 
1907  } else if (_status & PX4IO_P_STATUS_FLAGS_RC_DSM) {
1908  rc_val.input_source = input_rc_s::RC_INPUT_SOURCE_PX4IO_SPEKTRUM;
1909 
1910  } else if (_status & PX4IO_P_STATUS_FLAGS_RC_SBUS) {
1911  rc_val.input_source = input_rc_s::RC_INPUT_SOURCE_PX4IO_SBUS;
1912 
1913  } else if (_status & PX4IO_P_STATUS_FLAGS_RC_ST24) {
1914  rc_val.input_source = input_rc_s::RC_INPUT_SOURCE_PX4IO_ST24;
1915 
1916  } else {
1917  rc_val.input_source = input_rc_s::RC_INPUT_SOURCE_UNKNOWN;
1918 
1919  /* only keep publishing RC input if we ever got a valid input */
1920  if (_rc_last_valid == 0) {
1921  /* we have never seen valid RC signals, abort */
1922  return OK;
1923  }
1924  }
1925 
1926  _to_input_rc.publish(rc_val);
1927 
1928  return OK;
1929 }
1930 
1931 int
1933 {
1934  if (_hitl_mode) {
1935  return OK;
1936  }
1937 
1938  /* get servo values from IO */
1939  uint16_t ctl[_max_actuators];
1940  int ret = io_reg_get(PX4IO_PAGE_SERVOS, 0, ctl, _max_actuators);
1941 
1942  if (ret != OK) {
1943  return ret;
1944  }
1945 
1946  actuator_outputs_s outputs = {};
1947  outputs.timestamp = hrt_absolute_time();
1948  outputs.noutputs = _max_actuators;
1949 
1950  /* convert from register format to float */
1951  for (unsigned i = 0; i < _max_actuators; i++) {
1952  outputs.output[i] = ctl[i];
1953  }
1954 
1955  _to_outputs.publish(outputs);
1956 
1957  /* get mixer status flags from IO */
1958  MultirotorMixer::saturation_status saturation_status;
1959  ret = io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_MIXER, &saturation_status.value, 1);
1960 
1961  if (ret != OK) {
1962  return ret;
1963  }
1964 
1965  /* publish mixer status */
1966  if (saturation_status.flags.valid) {
1967  multirotor_motor_limits_s motor_limits{};
1968  motor_limits.timestamp = hrt_absolute_time();
1969  motor_limits.saturation_status = saturation_status.value;
1970 
1971  _to_mixer_status.publish(motor_limits);
1972  }
1973 
1974  return OK;
1975 }
1976 
1977 int
1978 PX4IO::io_reg_set(uint8_t page, uint8_t offset, const uint16_t *values, unsigned num_values)
1979 {
1980  /* range check the transfer */
1981  if (num_values > ((_max_transfer) / sizeof(*values))) {
1982  PX4_DEBUG("io_reg_set: too many registers (%u, max %u)", num_values, _max_transfer / 2);
1983  return -EINVAL;
1984  }
1985 
1986  int ret = _interface->write((page << 8) | offset, (void *)values, num_values);
1987 
1988  if (ret != (int)num_values) {
1989  PX4_DEBUG("io_reg_set(%hhu,%hhu,%u): error %d", page, offset, num_values, ret);
1990  return -1;
1991  }
1992 
1993  return OK;
1994 }
1995 
1996 int
1997 PX4IO::io_reg_set(uint8_t page, uint8_t offset, uint16_t value)
1998 {
1999  return io_reg_set(page, offset, &value, 1);
2000 }
2001 
2002 int
2003 PX4IO::io_reg_get(uint8_t page, uint8_t offset, uint16_t *values, unsigned num_values)
2004 {
2005  /* range check the transfer */
2006  if (num_values > ((_max_transfer) / sizeof(*values))) {
2007  PX4_DEBUG("io_reg_get: too many registers (%u, max %u)", num_values, _max_transfer / 2);
2008  return -EINVAL;
2009  }
2010 
2011  int ret = _interface->read((page << 8) | offset, reinterpret_cast<void *>(values), num_values);
2012 
2013  if (ret != (int)num_values) {
2014  PX4_DEBUG("io_reg_get(%hhu,%hhu,%u): data error %d", page, offset, num_values, ret);
2015  return -1;
2016  }
2017 
2018  return OK;
2019 }
2020 
2021 uint32_t
2022 PX4IO::io_reg_get(uint8_t page, uint8_t offset)
2023 {
2024  uint16_t value;
2025 
2026  if (io_reg_get(page, offset, &value, 1) != OK) {
2027  return _io_reg_get_error;
2028  }
2029 
2030  return value;
2031 }
2032 
2033 int
2034 PX4IO::io_reg_modify(uint8_t page, uint8_t offset, uint16_t clearbits, uint16_t setbits)
2035 {
2036  int ret;
2037  uint16_t value;
2038 
2039  ret = io_reg_get(page, offset, &value, 1);
2040 
2041  if (ret != OK) {
2042  return ret;
2043  }
2044 
2045  value &= ~clearbits;
2046  value |= setbits;
2047 
2048  return io_reg_set(page, offset, value);
2049 }
2050 
2051 int
2053 {
2054 #ifdef CONFIG_ARCH_BOARD_PX4_FMU_V2
2055  int io_fd = -1;
2056 
2057  if (io_fd <= 0) {
2058  io_fd = ::open("/dev/ttyS0", O_RDONLY | O_NONBLOCK | O_NOCTTY);
2059  }
2060 
2061  /* read IO's output */
2062  if (io_fd >= 0) {
2063  pollfd fds[1];
2064  fds[0].fd = io_fd;
2065  fds[0].events = POLLIN;
2066 
2067  px4_usleep(500);
2068  int pret = ::poll(fds, sizeof(fds) / sizeof(fds[0]), 0);
2069 
2070  if (pret > 0) {
2071  int count;
2072  char buf[65];
2073 
2074  do {
2075  count = ::read(io_fd, buf, sizeof(buf) - 1);
2076 
2077  if (count > 0) {
2078  /* enforce null termination */
2079  buf[count] = '\0';
2080  warnx("IO CONSOLE: %s", buf);
2081  }
2082 
2083  } while (count > 0);
2084  }
2085 
2086  ::close(io_fd);
2087  return 0;
2088  }
2089 
2090 #endif
2091  return 1;
2092 
2093 }
2094 
2095 int
2096 PX4IO::mixer_send(const char *buf, unsigned buflen, unsigned retries)
2097 {
2098  /* get debug level */
2100 
2101  uint8_t frame[_max_transfer];
2102 
2103  do {
2104 
2105  px4io_mixdata *msg = (px4io_mixdata *)&frame[0];
2106  unsigned max_len = _max_transfer - sizeof(px4io_mixdata);
2107 
2110 
2111  do {
2112  unsigned count = buflen;
2113 
2114  if (count > max_len) {
2115  count = max_len;
2116  }
2117 
2118  if (count > 0) {
2119  memcpy(&msg->text[0], buf, count);
2120  buf += count;
2121  buflen -= count;
2122 
2123  } else {
2124  continue;
2125  }
2126 
2127  /*
2128  * We have to send an even number of bytes. This
2129  * will only happen on the very last transfer of a
2130  * mixer, and we are guaranteed that there will be
2131  * space left to round up as _max_transfer will be
2132  * even.
2133  */
2134  unsigned total_len = sizeof(px4io_mixdata) + count;
2135 
2136  if (total_len % 2) {
2137  msg->text[count] = '\0';
2138  total_len++;
2139  }
2140 
2141  int ret;
2142 
2143  for (int i = 0; i < 30; i++) {
2144  /* failed, but give it a 2nd shot */
2145  ret = io_reg_set(PX4IO_PAGE_MIXERLOAD, 0, (uint16_t *)frame, total_len / 2);
2146 
2147  if (ret) {
2148  px4_usleep(333);
2149 
2150  } else {
2151  break;
2152  }
2153  }
2154 
2155  /* print mixer chunk */
2156  if (debuglevel > 5 || ret) {
2157 
2158  warnx("fmu sent: \"%s\"", msg->text);
2159 
2160  /* read IO's output */
2161  print_debug();
2162  }
2163 
2164  if (ret) {
2165  PX4_ERR("mixer send error %d", ret);
2166  return ret;
2167  }
2168 
2170 
2171  } while (buflen > 0);
2172 
2173  int ret;
2174 
2175  /* send the closing newline */
2176  msg->text[0] = '\n';
2177  msg->text[1] = '\0';
2178 
2179  for (int i = 0; i < 30; i++) {
2180  /* failed, but give it a 2nd shot */
2181  ret = io_reg_set(PX4IO_PAGE_MIXERLOAD, 0, (uint16_t *)frame, (sizeof(px4io_mixdata) + 2) / 2);
2182 
2183  if (ret) {
2184  px4_usleep(333);
2185 
2186  } else {
2187  break;
2188  }
2189  }
2190 
2191  if (ret == 0) {
2192  /* success, exit */
2193  break;
2194  }
2195 
2196  retries--;
2197 
2198  } while (retries > 0);
2199 
2200  if (retries == 0) {
2201  mavlink_and_console_log_info(&_mavlink_log_pub, "[IO] mixer upload fail");
2202  /* load must have failed for some reason */
2203  return -EINVAL;
2204 
2205  } else {
2206  /* all went well, set the mixer ok flag */
2208  }
2209 }
2210 
2211 void
2212 PX4IO::print_status(bool extended_status)
2213 {
2214  /* basic configuration */
2215  printf("protocol %u hardware %u bootloader %u buffer %uB crc 0x%04x%04x\n",
2222  printf("%u controls %u actuators %u R/C inputs %u analog inputs %u relays\n",
2228 
2229  /* status */
2230  printf("%u bytes free\n",
2233  uint16_t io_status_flags = flags;
2234  printf("status 0x%04hx%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
2235  flags,
2236  ((flags & PX4IO_P_STATUS_FLAGS_OUTPUTS_ARMED) ? " OUTPUTS_ARMED" : ""),
2237  ((flags & PX4IO_P_STATUS_FLAGS_SAFETY_OFF) ? " SAFETY_OFF" : " SAFETY_SAFE"),
2238  ((flags & PX4IO_P_STATUS_FLAGS_OVERRIDE) ? " OVERRIDE" : ""),
2239  ((flags & PX4IO_P_STATUS_FLAGS_RC_OK) ? " RC_OK" : " RC_FAIL"),
2240  ((flags & PX4IO_P_STATUS_FLAGS_RC_PPM) ? " PPM" : ""),
2241  ((flags & PX4IO_P_STATUS_FLAGS_RC_DSM) ? " DSM" : ""),
2242  ((flags & PX4IO_P_STATUS_FLAGS_RC_ST24) ? " ST24" : ""),
2243  ((flags & PX4IO_P_STATUS_FLAGS_RC_SBUS) ? " SBUS" : ""),
2244  ((flags & PX4IO_P_STATUS_FLAGS_FMU_OK) ? " FMU_OK" : " FMU_FAIL"),
2245  ((flags & PX4IO_P_STATUS_FLAGS_RAW_PWM) ? " RAW_PWM_PASSTHROUGH" : ""),
2246  ((flags & PX4IO_P_STATUS_FLAGS_MIXER_OK) ? " MIXER_OK" : " MIXER_FAIL"),
2247  ((flags & PX4IO_P_STATUS_FLAGS_ARM_SYNC) ? " ARM_SYNC" : " ARM_NO_SYNC"),
2248  ((flags & PX4IO_P_STATUS_FLAGS_INIT_OK) ? " INIT_OK" : " INIT_FAIL"),
2249  ((flags & PX4IO_P_STATUS_FLAGS_FAILSAFE) ? " FAILSAFE" : ""));
2251  printf("alarms 0x%04hx%s%s%s%s%s%s%s%s\n",
2252  alarms,
2253  ((alarms & PX4IO_P_STATUS_ALARMS_VBATT_LOW) ? " VBATT_LOW" : ""),
2254  ((alarms & PX4IO_P_STATUS_ALARMS_TEMPERATURE) ? " TEMPERATURE" : ""),
2255  ((alarms & PX4IO_P_STATUS_ALARMS_SERVO_CURRENT) ? " SERVO_CURRENT" : ""),
2256  ((alarms & PX4IO_P_STATUS_ALARMS_ACC_CURRENT) ? " ACC_CURRENT" : ""),
2257  ((alarms & PX4IO_P_STATUS_ALARMS_FMU_LOST) ? " FMU_LOST" : ""),
2258  ((alarms & PX4IO_P_STATUS_ALARMS_RC_LOST) ? " RC_LOST" : ""),
2259  ((alarms & PX4IO_P_STATUS_ALARMS_PWM_ERROR) ? " PWM_ERROR" : ""),
2260  ((alarms & PX4IO_P_STATUS_ALARMS_VSERVO_FAULT) ? " VSERVO_FAULT" : ""));
2261  /* now clear alarms */
2263 
2264  if (_hardware == 2) {
2265  printf("vservo %u mV vservo scale %u\n",
2268  printf("vrssi %u\n", io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_VRSSI));
2269  }
2270 
2271  printf("actuators");
2272 
2273  for (unsigned i = 0; i < _max_actuators; i++) {
2274  printf(" %hi", int16_t(io_reg_get(PX4IO_PAGE_ACTUATORS, i)));
2275  }
2276 
2277  printf("\n");
2278  printf("servos");
2279 
2280  for (unsigned i = 0; i < _max_actuators; i++) {
2281  printf(" %u", io_reg_get(PX4IO_PAGE_SERVOS, i));
2282  }
2283 
2284  uint16_t pwm_invert_mask = io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_PWM_REVERSE);
2285 
2286  printf("\n");
2287  printf("reversed outputs: [");
2288 
2289  for (unsigned i = 0; i < _max_actuators; i++) {
2290  printf("%s", (pwm_invert_mask & (1 << i)) ? "x" : "_");
2291  }
2292 
2293  printf("]");
2294 
2298 
2299  printf(" trims: r: %8.4f p: %8.4f y: %8.4f\n",
2300  (double)trim_roll, (double)trim_pitch, (double)trim_yaw);
2301 
2303  printf("%hu raw R/C inputs", raw_inputs);
2304 
2305  for (unsigned i = 0; i < raw_inputs; i++) {
2307  }
2308 
2309  printf("\n");
2310 
2312  printf("R/C flags: 0x%04hx%s%s%s%s%s\n", flags,
2313  (((io_status_flags & PX4IO_P_STATUS_FLAGS_RC_DSM) && (!(flags & PX4IO_P_RAW_RC_FLAGS_RC_DSM11))) ? " DSM10" : ""),
2314  (((io_status_flags & PX4IO_P_STATUS_FLAGS_RC_DSM) && (flags & PX4IO_P_RAW_RC_FLAGS_RC_DSM11)) ? " DSM11" : ""),
2315  ((flags & PX4IO_P_RAW_RC_FLAGS_FRAME_DROP) ? " FRAME_DROP" : ""),
2316  ((flags & PX4IO_P_RAW_RC_FLAGS_FAILSAFE) ? " FAILSAFE" : ""),
2317  ((flags & PX4IO_P_RAW_RC_FLAGS_MAPPING_OK) ? " MAPPING_OK" : "")
2318  );
2319 
2320  if ((io_status_flags & PX4IO_P_STATUS_FLAGS_RC_PPM)) {
2322  printf("RC data (PPM frame len) %d us\n", frame_len);
2323 
2324  if ((frame_len - raw_inputs * 2000 - 3000) < 0) {
2325  printf("WARNING WARNING WARNING! This RC receiver does not allow safe frame detection.\n");
2326  }
2327  }
2328 
2329  uint16_t mapped_inputs = io_reg_get(PX4IO_PAGE_RC_INPUT, PX4IO_P_RC_VALID);
2330  printf("mapped R/C inputs 0x%04hx", mapped_inputs);
2331 
2332  for (unsigned i = 0; i < _max_rc_input; i++) {
2333  if (mapped_inputs & (1 << i)) {
2334  printf(" %u:%hd", i, REG_TO_SIGNED(io_reg_get(PX4IO_PAGE_RC_INPUT, PX4IO_P_RC_BASE + i)));
2335  }
2336  }
2337 
2338  printf("\n");
2340  printf("ADC inputs");
2341 
2342  for (unsigned i = 0; i < adc_inputs; i++) {
2343  printf(" %u", io_reg_get(PX4IO_PAGE_RAW_ADC_INPUT, i));
2344  }
2345 
2346  printf("\n");
2347 
2348  /* setup and state */
2349  uint16_t features = io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES);
2350  printf("features 0x%04hx%s%s%s%s\n", features,
2351  ((features & PX4IO_P_SETUP_FEATURES_SBUS1_OUT) ? " S.BUS1_OUT" : ""),
2352  ((features & PX4IO_P_SETUP_FEATURES_SBUS2_OUT) ? " S.BUS2_OUT" : ""),
2353  ((features & PX4IO_P_SETUP_FEATURES_PWM_RSSI) ? " RSSI_PWM" : ""),
2354  ((features & PX4IO_P_SETUP_FEATURES_ADC_RSSI) ? " RSSI_ADC" : "")
2355  );
2356  uint16_t arming = io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING);
2357  printf("arming 0x%04hx%s%s%s%s%s%s%s%s%s%s\n",
2358  arming,
2359  ((arming & PX4IO_P_SETUP_ARMING_FMU_ARMED) ? " FMU_ARMED" : " FMU_DISARMED"),
2360  ((arming & PX4IO_P_SETUP_ARMING_FMU_PREARMED) ? " FMU_PREARMED" : " FMU_NOT_PREARMED"),
2361  ((arming & PX4IO_P_SETUP_ARMING_IO_ARM_OK) ? " IO_ARM_OK" : " IO_ARM_DENIED"),
2362  ((arming & PX4IO_P_SETUP_ARMING_MANUAL_OVERRIDE_OK) ? " MANUAL_OVERRIDE_OK" : ""),
2363  ((arming & PX4IO_P_SETUP_ARMING_FAILSAFE_CUSTOM) ? " FAILSAFE_CUSTOM" : ""),
2364  ((arming & PX4IO_P_SETUP_ARMING_INAIR_RESTART_OK) ? " INAIR_RESTART_OK" : ""),
2365  ((arming & PX4IO_P_SETUP_ARMING_ALWAYS_PWM_ENABLE) ? " ALWAYS_PWM_ENABLE" : ""),
2366  ((arming & PX4IO_P_SETUP_ARMING_LOCKDOWN) ? " LOCKDOWN" : ""),
2367  ((arming & PX4IO_P_SETUP_ARMING_FORCE_FAILSAFE) ? " FORCE_FAILSAFE" : ""),
2368  ((arming & PX4IO_P_SETUP_ARMING_TERMINATION_FAILSAFE) ? " TERM_FAILSAFE" : ""),
2369  ((arming & PX4IO_P_SETUP_ARMING_OVERRIDE_IMMEDIATE) ? " OVERRIDE_IMMEDIATE" : "")
2370  );
2371  printf("rates 0x%04x default %u alt %u sbus %u\n",
2376  printf("debuglevel %u\n", io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_SET_DEBUG));
2377 
2378  for (unsigned group = 0; group < 4; group++) {
2379  printf("controls %u:", group);
2380 
2381  for (unsigned i = 0; i < _max_controls; i++) {
2382  printf(" %hd", (int16_t) io_reg_get(PX4IO_PAGE_CONTROLS, group * PX4IO_PROTOCOL_MAX_CONTROL_COUNT + i));
2383  }
2384 
2385  printf("\n");
2386  }
2387 
2388  if (extended_status) {
2389  for (unsigned i = 0; i < _max_rc_input; i++) {
2390  unsigned base = PX4IO_P_RC_CONFIG_STRIDE * i;
2392  printf("input %u min %u center %u max %u deadzone %u assigned %u options 0x%04hx%s%s\n",
2393  i,
2399  options,
2400  ((options & PX4IO_P_RC_CONFIG_OPTIONS_ENABLED) ? " ENABLED" : ""),
2401  ((options & PX4IO_P_RC_CONFIG_OPTIONS_REVERSE) ? " REVERSED" : ""));
2402  }
2403  }
2404 
2405  printf("failsafe");
2406 
2407  for (unsigned i = 0; i < _max_actuators; i++) {
2408  printf(" %u", io_reg_get(PX4IO_PAGE_FAILSAFE_PWM, i));
2409  }
2410 
2411  printf("\ndisarmed values");
2412 
2413  for (unsigned i = 0; i < _max_actuators; i++) {
2414  printf(" %u", io_reg_get(PX4IO_PAGE_DISARMED_PWM, i));
2415  }
2416 
2417  /* IMU heater (Pixhawk 2.1) */
2418  uint16_t heater_level = io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_THERMAL);
2419 
2420  if (heater_level != UINT16_MAX) {
2421  if (heater_level == PX4IO_THERMAL_OFF) {
2422  printf("\nIMU heater off");
2423 
2424  } else {
2425  printf("\nIMU heater level %d", heater_level);
2426  }
2427  }
2428 
2429  if (_hitl_mode) {
2430  printf("\nHITL Mode");
2431  }
2432 
2433  printf("\n");
2434 }
2435 
2436 int
2437 PX4IO::ioctl(file *filep, int cmd, unsigned long arg)
2438 {
2439  SmartLock lock_guard(_lock);
2440  int ret = OK;
2441 
2442  /* regular ioctl? */
2443  switch (cmd) {
2444  case PWM_SERVO_ARM:
2445  /* set the 'armed' bit */
2447  break;
2448 
2449  case PWM_SERVO_SET_ARM_OK:
2450  /* set the 'OK to arm' bit */
2452  break;
2453 
2455  /* clear the 'OK to arm' bit */
2457  break;
2458 
2459  case PWM_SERVO_DISARM:
2460  /* clear the 'armed' bit */
2462  break;
2463 
2465  /* get the default update rate */
2467  break;
2468 
2470  /* set the requested alternate rate */
2472  break;
2473 
2475  /* get the alternative update rate */
2477  break;
2478 
2480 
2481  /* blindly clear the PWM update alarm - might be set for some other reason */
2483 
2484  /* attempt to set the rate map */
2486 
2487  /* check that the changes took */
2489 
2490  if (alarms & PX4IO_P_STATUS_ALARMS_PWM_ERROR) {
2491  ret = -EINVAL;
2492  io_reg_set(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_ALARMS, PX4IO_P_STATUS_ALARMS_PWM_ERROR);
2493  }
2494 
2495  break;
2496  }
2497 
2499 
2501  break;
2502 
2504  struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
2505 
2506  if (pwm->channel_count > _max_actuators)
2507  /* fail with error */
2508  {
2509  return -E2BIG;
2510  }
2511 
2512  /* copy values to registers in IO */
2514  break;
2515  }
2516 
2518  struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
2520 
2522 
2523  if (ret != OK) {
2524  ret = -EIO;
2525  }
2526 
2527  break;
2528  }
2529 
2531  struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
2532 
2533  if (pwm->channel_count > _max_actuators)
2534  /* fail with error */
2535  {
2536  return -E2BIG;
2537  }
2538 
2539  /* copy values to registers in IO */
2541  break;
2542  }
2543 
2545  struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
2547 
2549 
2550  if (ret != OK) {
2551  ret = -EIO;
2552  }
2553 
2554  break;
2555  }
2556 
2557  case PWM_SERVO_SET_MIN_PWM: {
2558  struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
2559 
2560  if (pwm->channel_count > _max_actuators)
2561  /* fail with error */
2562  {
2563  return -E2BIG;
2564  }
2565 
2566  /* copy values to registers in IO */
2568  break;
2569  }
2570 
2571  case PWM_SERVO_GET_MIN_PWM: {
2572  struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
2574 
2576 
2577  if (ret != OK) {
2578  ret = -EIO;
2579  }
2580 
2581  break;
2582  }
2583 
2584  case PWM_SERVO_SET_MAX_PWM: {
2585  struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
2586 
2587  if (pwm->channel_count > _max_actuators)
2588  /* fail with error */
2589  {
2590  return -E2BIG;
2591  }
2592 
2593  /* copy values to registers in IO */
2595  break;
2596  }
2597 
2598  case PWM_SERVO_GET_MAX_PWM: {
2599  struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
2601 
2603 
2604  if (ret != OK) {
2605  ret = -EIO;
2606  }
2607  }
2608 
2609  break;
2610 
2611  case PWM_SERVO_SET_TRIM_PWM: {
2612  struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
2613 
2614  if (pwm->channel_count > _max_actuators)
2615  /* fail with error */
2616  {
2617  return -E2BIG;
2618  }
2619 
2620  /* copy values to registers in IO */
2622  break;
2623  }
2624 
2625  case PWM_SERVO_GET_TRIM_PWM: {
2626  struct pwm_output_values *pwm = (struct pwm_output_values *)arg;
2628 
2630 
2631  if (ret != OK) {
2632  ret = -EIO;
2633  }
2634  }
2635 
2636  break;
2637 
2638  case PWM_SERVO_GET_COUNT:
2639  *(unsigned *)arg = _max_actuators;
2640  break;
2641 
2643  _lockdown_override = arg;
2644  break;
2645 
2647  *(unsigned *)arg = _lockdown_override;
2648  break;
2649 
2651  /* force safety swith off */
2653  break;
2654 
2656  /* force safety switch on */
2658  break;
2659 
2661 
2662  /* force failsafe mode instantly */
2663  if (arg == 0) {
2664  /* clear force failsafe flag */
2666 
2667  } else {
2668  /* set force failsafe flag */
2670  }
2671 
2672  break;
2673 
2675 
2676  /* if failsafe occurs, do not allow the system to recover */
2677  if (arg == 0) {
2678  /* clear termination failsafe flag */
2680 
2681  } else {
2682  /* set termination failsafe flag */
2684  }
2685 
2686  break;
2687 
2689 
2690  /* control whether override on FMU failure is
2691  immediate or waits for override threshold on mode
2692  switch */
2693  if (arg == 0) {
2694  /* clear override immediate flag */
2696 
2697  } else {
2698  /* set override immediate flag */
2700  }
2701 
2702  break;
2703 
2705  /* set the requested SBUS frame rate */
2707  break;
2708 
2709  case DSM_BIND_START:
2710 
2711  /* only allow DSM2, DSM-X and DSM-X with more than 7 channels */
2712  if (arg == DSM2_BIND_PULSES ||
2713  arg == DSMX_BIND_PULSES ||
2714  arg == DSMX8_BIND_PULSES) {
2716  px4_usleep(500000);
2719  px4_usleep(72000);
2721  px4_usleep(50000);
2723 
2724  ret = OK;
2725 
2726  } else {
2727  ret = -EINVAL;
2728  }
2729 
2730  break;
2731 
2732  case DSM_BIND_POWER_UP:
2734  break;
2735 
2737 
2738  /* TODO: we could go lower for e.g. TurboPWM */
2739  unsigned channel = cmd - PWM_SERVO_SET(0);
2740 
2741  /* PWM needs to be either 0 or in the valid range. */
2742  if ((arg != 0) && ((channel >= _max_actuators) ||
2743  (arg < PWM_LOWEST_MIN) ||
2744  (arg > PWM_HIGHEST_MAX))) {
2745  ret = -EINVAL;
2746 
2747  } else {
2749  /* send a direct PWM value */
2750  ret = io_reg_set(PX4IO_PAGE_DIRECT_PWM, channel, arg);
2751 
2752  } else {
2753  /* Just silently accept the ioctl without doing anything
2754  * in test mode. */
2755  ret = OK;
2756  }
2757  }
2758 
2759  break;
2760  }
2761 
2763 
2764  unsigned channel = cmd - PWM_SERVO_GET(0);
2765 
2766  if (channel >= _max_actuators) {
2767  ret = -EINVAL;
2768 
2769  } else {
2770  /* fetch a current PWM value */
2771  uint32_t value = io_reg_get(PX4IO_PAGE_SERVOS, channel);
2772 
2773  if (value == _io_reg_get_error) {
2774  ret = -EIO;
2775 
2776  } else {
2777  *(servo_position_t *)arg = value;
2778  }
2779  }
2780 
2781  break;
2782  }
2783 
2785 
2786  unsigned channel = cmd - PWM_SERVO_GET_RATEGROUP(0);
2787 
2788  *(uint32_t *)arg = io_reg_get(PX4IO_PAGE_PWM_INFO, PX4IO_RATE_MAP_BASE + channel);
2789 
2790  if (*(uint32_t *)arg == _io_reg_get_error) {
2791  ret = -EIO;
2792  }
2793 
2794  break;
2795  }
2796 
2797  case PWM_SERVO_SET_MODE: {
2798  // reset all channels to disarmed when entering/leaving test mode, so that we don't
2799  // accidentially use values from previous tests
2800  pwm_output_values pwm_disarmed;
2801 
2802  if (io_reg_get(PX4IO_PAGE_DISARMED_PWM, 0, pwm_disarmed.values, _max_actuators) == 0) {
2803  for (unsigned i = 0; i < _max_actuators; ++i) {
2804  io_reg_set(PX4IO_PAGE_DIRECT_PWM, i, pwm_disarmed.values[i]);
2805  }
2806  }
2807 
2809  ret = (arg == PWM_SERVO_ENTER_TEST_MODE || PWM_SERVO_EXIT_TEST_MODE) ? 0 : -EINVAL;
2810  }
2811  break;
2812 
2813  case MIXERIOCRESET:
2814  ret = 0; /* load always resets */
2815  break;
2816 
2817  case MIXERIOCLOADBUF: {
2818  const char *buf = (const char *)arg;
2819  ret = mixer_send(buf, strlen(buf));
2820  break;
2821  }
2822 
2823  case PX4IO_SET_DEBUG:
2824  /* set the debug level */
2826  break;
2827 
2830  return -EINVAL;
2831  }
2832 
2833  /* reboot into bootloader - arg must be PX4IO_REBOOT_BL_MAGIC */
2834  usleep(1);
2836  // we don't expect a reply from this operation
2837  ret = OK;
2838  break;
2839 
2840  case PX4IO_CHECK_CRC: {
2841  /* check IO firmware CRC against passed value */
2842  uint32_t io_crc = 0;
2843  ret = io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_CRC, (uint16_t *)&io_crc, 2);
2844 
2845  if (ret != OK) {
2846  return ret;
2847  }
2848 
2849  if (io_crc != arg) {
2850  PX4_DEBUG("crc mismatch 0x%08x 0x%08lx", io_crc, arg);
2851  return -EINVAL;
2852  }
2853 
2854  break;
2855  }
2856 
2858 
2859  /* set/clear the 'in-air restart' bit */
2860  if (arg) {
2862 
2863  } else {
2865  }
2866 
2867  break;
2868 
2870 
2871  if (arg) {
2873 
2874  } else {
2876  }
2877 
2878  break;
2879 
2881 
2882  if (arg) {
2884 
2885  } else {
2887  }
2888 
2889  break;
2890 
2892 
2893  if (arg == 1) {
2895 
2896  } else if (arg == 2) {
2898 
2899  } else {
2902  }
2903 
2904  break;
2905 
2906  default:
2907  /* see if the parent class can make any use of it */
2908  ret = CDev::ioctl(filep, cmd, arg);
2909  break;
2910  }
2911 
2912  return ret;
2913 }
2914 
2915 ssize_t
2916 PX4IO::write(file * /*filp*/, const char *buffer, size_t len)
2917 /* Make it obvious that file * isn't used here */
2918 {
2919  unsigned count = len / 2;
2920 
2921  if (count > _max_actuators) {
2922  count = _max_actuators;
2923  }
2924 
2925  if (count > 0) {
2926 
2928 
2929  int ret = OK;
2930 
2931  /* The write() is silently ignored in test mode. */
2932  if (!_test_fmu_fail) {
2933  ret = io_reg_set(PX4IO_PAGE_DIRECT_PWM, 0, (uint16_t *)buffer, count);
2934  }
2935 
2937 
2938  if (ret != OK) {
2939  return ret;
2940  }
2941  }
2942 
2943  return count * 2;
2944 }
2945 
2946 int
2948 {
2949  unsigned interval_ms = 1000 / rate;
2950 
2952 
2953  return 0;
2954 }
2955 
2956 extern "C" __EXPORT int px4io_main(int argc, char *argv[]);
2957 
2958 namespace
2959 {
2960 
2962 get_interface()
2963 {
2964  device::Device *interface = nullptr;
2965 
2966 #ifdef PX4IO_SERIAL_BASE
2967  interface = PX4IO_serial_interface();
2968 #endif
2969 
2970  if (interface != nullptr) {
2971  goto got;
2972  }
2973 
2974  errx(1, "cannot alloc interface");
2975 
2976 got:
2977 
2978  if (interface->init() != OK) {
2979  delete interface;
2980  errx(1, "interface init failed");
2981  }
2982 
2983  return interface;
2984 }
2985 
2986 void
2987 start(int argc, char *argv[])
2988 {
2989  if (g_dev != nullptr) {
2990  errx(0, "already loaded");
2991  }
2992 
2993  /* allocate the interface */
2994  device::Device *interface = get_interface();
2995 
2996  /* create the driver - it will set g_dev */
2997  (void)new PX4IO(interface);
2998 
2999  if (g_dev == nullptr) {
3000  delete interface;
3001  errx(1, "driver allocation failed");
3002  }
3003 
3004  bool rc_handling_disabled = false;
3005  bool hitl_mode = false;
3006 
3007  /* disable RC handling and/or actuator_output publication on request */
3008  for (int extra_args = 1; extra_args < argc; extra_args++) {
3009  if (!strcmp(argv[extra_args], "norc")) {
3010  rc_handling_disabled = true;
3011 
3012  } else if (!strcmp(argv[extra_args], "hil")) {
3013  hitl_mode = true;
3014 
3015  } else {
3016  warnx("unknown argument: %s", argv[1]);
3017  }
3018  }
3019 
3020  if (OK != g_dev->init(rc_handling_disabled, hitl_mode)) {
3021  delete g_dev;
3022  g_dev = nullptr;
3023  errx(1, "driver init failed");
3024  }
3025 
3026  exit(0);
3027 }
3028 
3029 void
3030 detect(int argc, char *argv[])
3031 {
3032  if (g_dev != nullptr) {
3033  errx(0, "already loaded");
3034  }
3035 
3036  /* allocate the interface */
3037  device::Device *interface = get_interface();
3038 
3039  /* create the driver - it will set g_dev */
3040  (void)new PX4IO(interface);
3041 
3042  if (g_dev == nullptr) {
3043  errx(1, "driver allocation failed");
3044  }
3045 
3046  int ret = g_dev->detect();
3047 
3048  delete g_dev;
3049  g_dev = nullptr;
3050 
3051  if (ret) {
3052  /* nonzero, error */
3053  exit(1);
3054 
3055  } else {
3056  exit(0);
3057  }
3058 }
3059 
3060 void
3061 checkcrc(int argc, char *argv[])
3062 {
3063  bool keep_running = false;
3064 
3065  if (g_dev == nullptr) {
3066  /* allocate the interface */
3067  device::Device *interface = get_interface();
3068 
3069  /* create the driver - it will set g_dev */
3070  (void)new PX4IO(interface);
3071 
3072  if (g_dev == nullptr) {
3073  errx(1, "driver allocation failed");
3074  }
3075 
3076  } else {
3077  /* its already running, don't kill the driver */
3078  keep_running = true;
3079  }
3080 
3081  /*
3082  check IO CRC against CRC of a file
3083  */
3084  if (argc < 2) {
3085  warnx("usage: px4io checkcrc filename");
3086  exit(1);
3087  }
3088 
3089  int fd = open(argv[1], O_RDONLY);
3090 
3091  if (fd == -1) {
3092  warnx("open of %s failed: %d", argv[1], errno);
3093  exit(1);
3094  }
3095 
3096  const uint32_t app_size_max = 0xf000;
3097  uint32_t fw_crc = 0;
3098  uint32_t nbytes = 0;
3099 
3100  while (true) {
3101  uint8_t buf[16];
3102  int n = read(fd, buf, sizeof(buf));
3103 
3104  if (n <= 0) { break; }
3105 
3106  fw_crc = crc32part(buf, n, fw_crc);
3107  nbytes += n;
3108  }
3109 
3110  close(fd);
3111 
3112  while (nbytes < app_size_max) {
3113  uint8_t b = 0xff;
3114  fw_crc = crc32part(&b, 1, fw_crc);
3115  nbytes++;
3116  }
3117 
3118  int ret = g_dev->ioctl(nullptr, PX4IO_CHECK_CRC, fw_crc);
3119 
3120  if (!keep_running) {
3121  delete g_dev;
3122  g_dev = nullptr;
3123  }
3124 
3125  if (ret != OK) {
3126  warn("check CRC failed: %d", ret);
3127  exit(1);
3128  }
3129 
3130  exit(0);
3131 }
3132 
3133 void
3134 bind(int argc, char *argv[])
3135 {
3136  int pulses;
3137 
3138  if (g_dev == nullptr) {
3139  errx(1, "px4io must be started first");
3140  }
3141 
3142  if (argc < 3) {
3143  errx(0, "needs argument, use dsm2, dsmx or dsmx8");
3144  }
3145 
3146  if (!strcmp(argv[2], "dsm2")) {
3147  pulses = DSM2_BIND_PULSES;
3148 
3149  } else if (!strcmp(argv[2], "dsmx")) {
3150  pulses = DSMX_BIND_PULSES;
3151 
3152  } else if (!strcmp(argv[2], "dsmx8")) {
3153  pulses = DSMX8_BIND_PULSES;
3154 
3155  } else {
3156  errx(1, "unknown parameter %s, use dsm2, dsmx or dsmx8", argv[2]);
3157  }
3158 
3159  // Test for custom pulse parameter
3160  if (argc > 3) {
3161  pulses = atoi(argv[3]);
3162  }
3163 
3164  if (g_dev->system_status() & PX4IO_P_STATUS_FLAGS_SAFETY_OFF) {
3165  errx(1, "system must not be armed");
3166  }
3167 
3168  g_dev->ioctl(nullptr, DSM_BIND_START, pulses);
3169 
3170  exit(0);
3171 
3172 }
3173 
3174 void
3175 test(void)
3176 {
3177  int fd;
3178  unsigned servo_count = 0;
3179  unsigned pwm_value = 1000;
3180  int direction = 1;
3181  int ret;
3182 
3183  fd = open(PX4IO_DEVICE_PATH, O_WRONLY);
3184 
3185  if (fd < 0) {
3186  err(1, "failed to open device");
3187  }
3188 
3189  if (ioctl(fd, PWM_SERVO_GET_COUNT, (unsigned long)&servo_count)) {
3190  err(1, "failed to get servo count");
3191  }
3192 
3193  /* tell IO that its ok to disable its safety with the switch */
3194  ret = ioctl(fd, PWM_SERVO_SET_ARM_OK, 0);
3195 
3196  if (ret != OK) {
3197  err(1, "PWM_SERVO_SET_ARM_OK");
3198  }
3199 
3200  if (ioctl(fd, PWM_SERVO_ARM, 0)) {
3201  err(1, "failed to arm servos");
3202  }
3203 
3204  struct pollfd fds;
3205 
3206  fds.fd = 0; /* stdin */
3207 
3208  fds.events = POLLIN;
3209 
3210  warnx("Press CTRL-C or 'c' to abort.");
3211 
3212  for (;;) {
3213 
3214  /* sweep all servos between 1000..2000 */
3215  servo_position_t servos[servo_count];
3216 
3217  for (unsigned i = 0; i < servo_count; i++) {
3218  servos[i] = pwm_value;
3219  }
3220 
3221  ret = write(fd, servos, sizeof(servos));
3222 
3223  if (ret != (int)sizeof(servos)) {
3224  err(1, "error writing PWM servo data, wrote %zu got %d", sizeof(servos), ret);
3225  }
3226 
3227  if (direction > 0) {
3228  if (pwm_value < 2000) {
3229  pwm_value++;
3230 
3231  } else {
3232  direction = -1;
3233  }
3234 
3235  } else {
3236  if (pwm_value > 1000) {
3237  pwm_value--;
3238 
3239  } else {
3240  direction = 1;
3241  }
3242  }
3243 
3244  px4_usleep(250);
3245 
3246  /* readback servo values */
3247  for (unsigned i = 0; i < servo_count; i++) {
3248  servo_position_t value;
3249 
3250  if (ioctl(fd, PWM_SERVO_GET(i), (unsigned long)&value)) {
3251  err(1, "error reading PWM servo %u", i);
3252  }
3253 
3254  if (value != servos[i]) {
3255  warnx("servo %u readback error, got %hu expected %hu", i, value, servos[i]);
3256  }
3257  }
3258 
3259  /* Check if user wants to quit */
3260  char c;
3261  ret = poll(&fds, 1, 0);
3262 
3263  if (ret > 0) {
3264 
3265  read(0, &c, 1);
3266 
3267  if (c == 0x03 || c == 0x63 || c == 'q') {
3268  warnx("User abort\n");
3269  exit(0);
3270  }
3271  }
3272  }
3273 }
3274 
3275 void
3276 monitor(void)
3277 {
3278  /* clear screen */
3279  printf("\033[2J");
3280 
3281  unsigned cancels = 2;
3282 
3283  for (;;) {
3284  pollfd fds[1];
3285 
3286  fds[0].fd = 0;
3287  fds[0].events = POLLIN;
3288 
3289  if (poll(fds, 1, 2000) < 0) {
3290  errx(1, "poll fail");
3291  }
3292 
3293  if (fds[0].revents == POLLIN) {
3294  /* control logic is to cancel with any key */
3295  char c;
3296  (void)read(0, &c, 1);
3297 
3298  if (cancels-- == 0) {
3299  printf("\033[2J\033[H"); /* move cursor home and clear screen */
3300  exit(0);
3301  }
3302  }
3303 
3304  if (g_dev != nullptr) {
3305 
3306  printf("\033[2J\033[H"); /* move cursor home and clear screen */
3307  (void)g_dev->print_status(false);
3308  (void)g_dev->print_debug();
3309  printf("\n\n\n[ Use 'px4io debug <N>' for more output. Hit <enter> three times to exit monitor mode ]\n");
3310 
3311  } else {
3312  errx(1, "driver not loaded, exiting");
3313  }
3314  }
3315 }
3316 
3317 void
3318 if_test(unsigned mode)
3319 {
3320  device::Device *interface = get_interface();
3321  int result;
3322 
3323  if (interface) {
3324  result = interface->ioctl(1, mode); /* XXX magic numbers */
3325  delete interface;
3326 
3327  } else {
3328  errx(1, "interface not loaded, exiting");
3329  }
3330 
3331  errx(0, "test returned %d", result);
3332 }
3333 
3334 void
3335 lockdown(int argc, char *argv[])
3336 {
3337  if (g_dev != nullptr) {
3338 
3339  if (argc > 2 && !strcmp(argv[2], "disable")) {
3340 
3341  warnx("WARNING: ACTUATORS WILL BE LIVE IN HIL! PROCEED?");
3342  warnx("Press 'y' to enable, any other key to abort.");
3343 
3344  /* check if user wants to abort */
3345  char c;
3346 
3347  struct pollfd fds;
3348  int ret;
3350  const unsigned long timeout = 5000000;
3351 
3352  while (hrt_elapsed_time(&start) < timeout) {
3353  fds.fd = 0; /* stdin */
3354  fds.events = POLLIN;
3355  ret = poll(&fds, 1, 0);
3356 
3357  if (ret > 0) {
3358 
3359  if (read(0, &c, 1) > 0) {
3360 
3361  if (c != 'y') {
3362  exit(0);
3363 
3364  } else if (c == 'y') {
3365  break;
3366  }
3367  }
3368  }
3369 
3370  px4_usleep(10000);
3371  }
3372 
3373  if (hrt_elapsed_time(&start) > timeout) {
3374  errx(1, "TIMEOUT! ABORTED WITHOUT CHANGES.");
3375  }
3376 
3378 
3379  warnx("WARNING: ACTUATORS ARE NOW LIVE IN HIL!");
3380 
3381  } else {
3383  warnx("ACTUATORS ARE NOW SAFE IN HIL.");
3384  }
3385 
3386  } else {
3387  errx(1, "driver not loaded, exiting");
3388  }
3389 
3390  exit(0);
3391 }
3392 
3393 } /* namespace */
3394 
3395 int
3396 px4io_main(int argc, char *argv[])
3397 {
3398  /* check for sufficient number of arguments */
3399  if (argc < 2) {
3400  goto out;
3401  }
3402 
3403  if (!PX4_MFT_HW_SUPPORTED(PX4_MFT_PX4IO)) {
3404  errx(1, "PX4IO Not Supported");
3405  }
3406 
3407  if (!strcmp(argv[1], "start")) {
3408  start(argc - 1, argv + 1);
3409  }
3410 
3411  if (!strcmp(argv[1], "detect")) {
3412  detect(argc - 1, argv + 1);
3413  }
3414 
3415  if (!strcmp(argv[1], "checkcrc")) {
3416  checkcrc(argc - 1, argv + 1);
3417  }
3418 
3419  if (!strcmp(argv[1], "update")) {
3420 
3421  if (g_dev != nullptr) {
3422  warnx("loaded, detaching first");
3423  /* stop the driver */
3424  delete g_dev;
3425  g_dev = nullptr;
3426  }
3427 
3428  PX4IO_Uploader *up;
3429 
3430  /* Assume we are using default paths */
3431 
3432  const char *fn[4] = PX4IO_FW_SEARCH_PATHS;
3433 
3434  /* Override defaults if a path is passed on command line */
3435  if (argc > 2) {
3436  fn[0] = argv[2];
3437  fn[1] = nullptr;
3438  }
3439 
3440  up = new PX4IO_Uploader;
3441  int ret = up->upload(&fn[0]);
3442  delete up;
3443 
3444  switch (ret) {
3445  case OK:
3446  break;
3447 
3448  case -ENOENT:
3449  errx(1, "PX4IO firmware file not found");
3450 
3451  case -EEXIST:
3452  case -EIO:
3453  errx(1, "error updating PX4IO - check that bootloader mode is enabled");
3454 
3455  case -EINVAL:
3456  errx(1, "verify failed - retry the update");
3457 
3458  case -ETIMEDOUT:
3459  errx(1, "timed out waiting for bootloader - power-cycle and try again");
3460 
3461  default:
3462  errx(1, "unexpected error %d", ret);
3463  }
3464 
3465  return ret;
3466  }
3467 
3468  if (!strcmp(argv[1], "iftest")) {
3469  if (g_dev != nullptr) {
3470  errx(1, "can't iftest when started");
3471  }
3472 
3473  if_test((argc > 2) ? strtol(argv[2], NULL, 0) : 0);
3474  }
3475 
3476  if (!strcmp(argv[1], "forceupdate")) {
3477  /*
3478  force update of the IO firmware without requiring
3479  the user to hold the safety switch down
3480  */
3481  if (argc <= 3) {
3482  warnx("usage: px4io forceupdate MAGIC filename");
3483  exit(1);
3484  }
3485 
3486  if (g_dev == nullptr) {
3487  warnx("px4io is not started, still attempting upgrade");
3488 
3489  /* allocate the interface */
3490  device::Device *interface = get_interface();
3491 
3492  /* create the driver - it will set g_dev */
3493  (void)new PX4IO(interface);
3494 
3495  if (g_dev == nullptr) {
3496  delete interface;
3497  errx(1, "driver allocation failed");
3498  }
3499  }
3500 
3501  uint16_t arg = atol(argv[2]);
3502  int ret = g_dev->ioctl(nullptr, PX4IO_REBOOT_BOOTLOADER, arg);
3503 
3504  if (ret != OK) {
3505  warnx("reboot failed - %d", ret);
3506  exit(1);
3507  }
3508 
3509  // tear down the px4io instance
3510  delete g_dev;
3511  g_dev = nullptr;
3512 
3513  // upload the specified firmware
3514  const char *fn[2];
3515  fn[0] = argv[3];
3516  fn[1] = nullptr;
3517  PX4IO_Uploader *up = new PX4IO_Uploader;
3518  up->upload(&fn[0]);
3519  delete up;
3520  exit(0);
3521  }
3522 
3523  /* commands below here require a started driver */
3524 
3525  if (g_dev == nullptr) {
3526  errx(1, "not started");
3527  }
3528 
3529  if (!strcmp(argv[1], "limit")) {
3530 
3531  if ((argc > 2)) {
3532  int limitrate = atoi(argv[2]);
3533 
3534  if (limitrate > 0) {
3535  g_dev->set_update_rate(limitrate);
3536 
3537  } else {
3538  errx(1, "invalid rate: %d", limitrate);
3539  }
3540 
3541  } else {
3542  errx(1, "missing argument (50 - 500 Hz)");
3543  return 1;
3544  }
3545 
3546  exit(0);
3547  }
3548 
3549  if (!strcmp(argv[1], "safety_off")) {
3550  int ret = g_dev->ioctl(NULL, PWM_SERVO_SET_FORCE_SAFETY_OFF, 0);
3551 
3552  if (ret != OK) {
3553  warnx("failed to disable safety");
3554  exit(1);
3555  }
3556 
3557  exit(0);
3558  }
3559 
3560  if (!strcmp(argv[1], "safety_on")) {
3561  int ret = g_dev->ioctl(NULL, PWM_SERVO_SET_FORCE_SAFETY_ON, 0);
3562 
3563  if (ret != OK) {
3564  warnx("failed to enable safety");
3565  exit(1);
3566  }
3567 
3568  exit(0);
3569  }
3570 
3571  if (!strcmp(argv[1], "recovery")) {
3572 
3573  /*
3574  * Enable in-air restart support.
3575  * We can cheat and call the driver directly, as it
3576  * doesn't reference filp in ioctl()
3577  */
3579  exit(0);
3580  }
3581 
3582  if (!strcmp(argv[1], "stop")) {
3583 
3584  /* stop the driver */
3585  delete g_dev;
3586  g_dev = nullptr;
3587  exit(0);
3588  }
3589 
3590 
3591  if (!strcmp(argv[1], "status")) {
3592 
3593  warnx("loaded");
3594  g_dev->print_status(true);
3595 
3596  exit(0);
3597  }
3598 
3599  if (!strcmp(argv[1], "debug")) {
3600  if (argc <= 2) {
3601  warnx("usage: px4io debug LEVEL");
3602  exit(1);
3603  }
3604 
3605  if (g_dev == nullptr) {
3606  warnx("not started");
3607  exit(1);
3608  }
3609 
3610  uint8_t level = atoi(argv[2]);
3611  /* we can cheat and call the driver directly, as it
3612  * doesn't reference filp in ioctl()
3613  */
3614  int ret = g_dev->ioctl(nullptr, PX4IO_SET_DEBUG, level);
3615 
3616  if (ret != 0) {
3617  warnx("SET_DEBUG failed: %d", ret);
3618  exit(1);
3619  }
3620 
3621  warnx("SET_DEBUG %hhu OK", level);
3622  exit(0);
3623  }
3624 
3625  if (!strcmp(argv[1], "rx_dsm") ||
3626  !strcmp(argv[1], "rx_dsm_10bit") ||
3627  !strcmp(argv[1], "rx_dsm_11bit") ||
3628  !strcmp(argv[1], "rx_sbus") ||
3629  !strcmp(argv[1], "rx_ppm")) {
3630  errx(0, "receiver type is automatically detected, option '%s' is deprecated", argv[1]);
3631  }
3632 
3633  if (!strcmp(argv[1], "test")) {
3634  test();
3635  }
3636 
3637  if (!strcmp(argv[1], "monitor")) {
3638  monitor();
3639  }
3640 
3641  if (!strcmp(argv[1], "bind")) {
3642  bind(argc, argv);
3643  }
3644 
3645  if (!strcmp(argv[1], "lockdown")) {
3646  lockdown(argc, argv);
3647  }
3648 
3649  if (!strcmp(argv[1], "sbus1_out")) {
3650  /* we can cheat and call the driver directly, as it
3651  * doesn't reference filp in ioctl()
3652  */
3653  int ret = g_dev->ioctl(nullptr, SBUS_SET_PROTO_VERSION, 1);
3654 
3655  if (ret != 0) {
3656  errx(ret, "S.BUS v1 failed");
3657  }
3658 
3659  exit(0);
3660  }
3661 
3662  if (!strcmp(argv[1], "sbus2_out")) {
3663  /* we can cheat and call the driver directly, as it
3664  * doesn't reference filp in ioctl()
3665  */
3666  int ret = g_dev->ioctl(nullptr, SBUS_SET_PROTO_VERSION, 2);
3667 
3668  if (ret != 0) {
3669  errx(ret, "S.BUS v2 failed");
3670  }
3671 
3672  exit(0);
3673  }
3674 
3675  if (!strcmp(argv[1], "rssi_analog")) {
3676  /* we can cheat and call the driver directly, as it
3677  * doesn't reference filp in ioctl()
3678  */
3679  int ret = g_dev->ioctl(nullptr, RC_INPUT_ENABLE_RSSI_ANALOG, 1);
3680 
3681  if (ret != 0) {
3682  errx(ret, "RSSI analog failed");
3683  }
3684 
3685  exit(0);
3686  }
3687 
3688  if (!strcmp(argv[1], "rssi_pwm")) {
3689  /* we can cheat and call the driver directly, as it
3690  * doesn't reference filp in ioctl()
3691  */
3692  int ret = g_dev->ioctl(nullptr, RC_INPUT_ENABLE_RSSI_PWM, 1);
3693 
3694  if (ret != 0) {
3695  errx(ret, "RSSI PWM failed");
3696  }
3697 
3698  exit(0);
3699  }
3700 
3701  if (!strcmp(argv[1], "test_fmu_fail")) {
3702  if (g_dev != nullptr) {
3703  g_dev->test_fmu_fail(true);
3704  exit(0);
3705 
3706  } else {
3707 
3708  errx(1, "px4io must be started first");
3709  }
3710  }
3711 
3712  if (!strcmp(argv[1], "test_fmu_ok")) {
3713  if (g_dev != nullptr) {
3714  g_dev->test_fmu_fail(false);
3715  exit(0);
3716 
3717  } else {
3718 
3719  errx(1, "px4io must be started first");
3720  }
3721  }
3722 
3723 out:
3724  errx(1, "need a command, try 'start', 'stop', 'status', 'test', 'monitor', 'debug <level>',\n"
3725  "'recovery', 'limit <rate>', 'bind', 'checkcrc', 'safety_on', 'safety_off',\n"
3726  "'forceupdate', 'update', 'sbus1_out', 'sbus2_out', 'rssi_analog' or 'rssi_pwm',\n"
3727  "'test_fmu_fail', 'test_fmu_ok'");
3728 }
#define PX4IO_P_STATUS_VSERVO
Definition: protocol.h:134
#define PX4IO_PAGE_RAW_RC_INPUT
Definition: protocol.h:147
#define PARAM_INVALID
Handle returned when a parameter cannot be found.
Definition: param.h:103
constexpr _Tp constrain(_Tp val, _Tp min_val, _Tp max_val)
Definition: Limits.hpp:66
uint8_t action
Definition: test_motor.h:61
#define PX4IO_PAGE_DISARMED_PWM
Definition: protocol.h:303
#define PX4IO_P_SETUP_ARMING_ALWAYS_PWM_ENABLE
Definition: protocol.h:189
void io_handle_vservo(uint16_t vservo, uint16_t vrssi)
Handle a servorail update from IO.
Definition: px4io.cpp:1736
#define PX4IO_P_SETUP_TRIM_PITCH
Pitch trim, in actuator units.
Definition: protocol.h:228
int detect(int bus)
Definition: i2cdetect.cpp:50
#define PX4IO_P_STATUS_FLAGS_FMU_OK
Definition: protocol.h:113
#define PWM_SERVO_GET_SELECT_UPDATE_RATE
check the selected update rates
#define PX4IO_P_CONFIG_CONTROL_COUNT
Definition: protocol.h:94
int orb_copy(const struct orb_metadata *meta, int handle, void *buffer)
Definition: uORB.cpp:90
#define PX4IO_PAGE_ACTUATORS
Definition: protocol.h:141
#define MIXERIOCLOADBUF
Add mixer(s) from the buffer in (const char *)arg.
Definition: drv_mixer.h:79
#define PX4IO_P_CONFIG_ADC_INPUT_COUNT
Definition: protocol.h:97
int32_t _rssi_pwm_chan
RSSI PWM input channel.
Definition: px4io.cpp:286
uint16_t f2i_mixer_magic
Definition: protocol.h:313
#define PWM_SERVO_SET_ARM_OK
set the &#39;ARM ok&#39; bit, which activates the safety switch
R/C input interface.
virtual int init()
Initialize the PX4IO class.
Definition: px4io.cpp:588
#define FLOAT_TO_REG(_float)
Definition: protocol.h:79
void print_status(bool extended_status)
Print IO status.
Definition: px4io.cpp:2212
#define PX4IO_P_RC_BASE
Definition: protocol.h:165
#define PX4IO_P_SETUP_FORCE_SAFETY_OFF
Definition: protocol.h:218
#define PX4IO_P_RC_CONFIG_OPTIONS_REVERSE
Definition: protocol.h:276
unsigned _update_interval
Subscription interval limiting send rate.
Definition: px4io.cpp:238
uORB::Subscription _parameter_update_sub
parameter update topic
Definition: px4io.cpp:266
unsigned _hardware
Hardware revision.
Definition: px4io.cpp:231
static struct vehicle_status_s status
Definition: Commander.cpp:138
uORB::PublicationMulti< multirotor_motor_limits_s > _to_mixer_status
Definition: px4io.cpp:274
RC protocol definition for Spektrum RC.
int32_t _thermal_control
thermal control state
Definition: px4io.cpp:289
virtual int open(file_t *filep)
Handle an open of the device.
Definition: CDev.cpp:141
int io_set_rc_config()
Push RC channel configuration to IO.
Definition: px4io.cpp:1500
int io_publish_raw_rc()
Fetch and publish raw RC input data.
Definition: px4io.cpp:1888
The PX4IO class.
Definition: px4io.cpp:125
uint16_t servo_position_t
Servo output signal type, value is actual servo output pulse width in microseconds.
#define PX4IO_SET_DEBUG
Definition: px4io.cpp:107
int32_t rssi
Definition: input_rc.h:72
Futaba S.BUS / S.BUS 2 compatible interface.
#define SIGNED_TO_REG(_signed)
Definition: protocol.h:76
#define F2I_MIXER_ACTION_APPEND
Definition: protocol.h:318
measure the time elapsed performing an event
Definition: perf_counter.h:56
#define PX4IO_P_SETUP_SET_DEBUG
Definition: protocol.h:211
px4_sem_t _lock
lock to protect access to all class members (also for derived classes)
Definition: CDev.hpp:271
#define DSM_BIND_START
start DSM bind
#define PWM_SERVO_SET_FORCE_SAFETY_ON
force safety switch on (to enable use of safety switch)
#define PX4IO_P_SETUP_PWM_DEFAULTRATE
Definition: protocol.h:197
uORB::Publication< safety_s > _to_safety
Definition: px4io.cpp:276
unsigned _max_actuators
Maximum # of actuators supported by PX4IO.
Definition: px4io.cpp:232
#define PX4IO_P_RAW_FRAME_COUNT
Definition: protocol.h:158
perf_counter_t _perf_write
local performance counter for PWM control writes
Definition: px4io.cpp:249
#define PX4IO_PAGE_RC_INPUT
Definition: protocol.h:163
bool rc_failsafe
Definition: input_rc.h:77
__EXPORT int param_get(param_t param, void *val)
Copy the value of a parameter.
Definition: parameters.cpp:589
#define PWM_SERVO_GET_COUNT
get the number of servos in *(unsigned *)arg
#define PX4IO_P_SETUP_SCALE_PITCH
Pitch scale, in actuator units.
Definition: protocol.h:231
virtual int init()
Definition: airspeed.cpp:92
#define PX4IO_P_SETUP_PWM_REVERSE
Bitmask to reverse PWM channels 1-8.
Definition: protocol.h:226
#define PWM_SERVO_ARM
arm all servo outputs handle by this driver
bool override_enabled
Definition: safety.h:57
#define PWM_SERVO_SET_OVERRIDE_IMMEDIATE
setup OVERRIDE_IMMEDIATE behaviour on FMU fail
#define PX4IO_PAGE_FAILSAFE_PWM
0..CONFIG_ACTUATOR_COUNT-1
Definition: protocol.h:283
#define PX4IO_P_SETUP_SBUS_RATE
frame rate of SBUS1 output in Hz
Definition: protocol.h:234
#define PX4IO_P_CONFIG_RC_INPUT_COUNT
Definition: protocol.h:96
volatile int _task
worker task id
Definition: px4io.cpp:243
void handle_motor_test()
check and handle test_motor topic updates
Definition: px4io.cpp:1335
float _analog_rc_rssi_volt
analog RSSI voltage
Definition: px4io.cpp:291
#define PX4IO_THERMAL_IGNORE
Definition: protocol.h:246
orb_advert_t _mavlink_log_pub
mavlink log pub
Definition: px4io.cpp:246
#define PX4IO_P_STATUS_FLAGS_RC_SBUS
Definition: protocol.h:112
#define PX4IO_PROTOCOL_MAX_CONTROL_COUNT
The protocol does not support more than set here, individual units might support less - see PX4IO_P_C...
Definition: protocol.h:86
__EXPORT int param_set_no_notification(param_t param, const void *val)
Set the value of a parameter, but do not notify the system about the change.
Definition: parameters.cpp:820
#define PX4IO_P_RAW_RC_BASE
Definition: protocol.h:160
int _t_actuator_controls_0
actuator controls group 0 topic
Definition: px4io.cpp:259
#define CBRK_IO_SAFETY_KEY
int io_reg_set(uint8_t page, uint8_t offset, const uint16_t *values, unsigned num_values)
write register(s)
Definition: px4io.cpp:1978
bool circuit_breaker_enabled(const char *breaker, int32_t magic)
#define PX4IO_P_CONFIG_RELAY_COUNT
Definition: protocol.h:98
uint16_t rc_ppm_frame_length
Definition: input_rc.h:75
#define PX4IO_P_RC_VALID
Definition: protocol.h:164
void lock()
Take the driver lock.
Definition: CDev.hpp:264
static constexpr unsigned UPDATE_INTERVAL_MIN
Definition: px4io.cpp:112
#define PX4IO_P_SETUP_ARMING_MANUAL_OVERRIDE_OK
Definition: protocol.h:186
int orb_set_interval(int handle, unsigned interval)
Definition: uORB.cpp:126
__EXPORT int param_set(param_t param, const void *val)
Set the value of a parameter.
Definition: parameters.cpp:814
#define PX4IO_P_SETUP_FORCE_SAFETY_ON
Definition: protocol.h:223
Definition: I2C.hpp:51
#define PX4IO_INAIR_RESTART_ENABLE
Definition: px4io.cpp:108
static void task_main_trampoline(int argc, char *argv[])
uint8_t input_source
Definition: input_rc.h:79
int io_reg_modify(uint8_t page, uint8_t offset, uint16_t clearbits, uint16_t setbits)
modify a register
Definition: px4io.cpp:2034
#define PX4IO_PAGE_MIXERLOAD
Definition: protocol.h:264
#define PX4IO_P_SETUP_PWM_ALTRATE
Definition: protocol.h:198
int io_publish_pwm_outputs()
Fetch and publish the PWM servo outputs.
Definition: px4io.cpp:1932
void perf_set_elapsed(perf_counter_t handle, int64_t elapsed)
Register a measurement.
#define PWM_SERVO_GET_UPDATE_RATE
get alternate servo update rate
#define PWM_SERVO_GET_DISARMED_PWM
get the PWM value when disarmed
void print_status()
Definition: Commander.cpp:517
Interface for PX4IO.
#define PX4IO_P_STATUS_ALARMS_SERVO_CURRENT
Definition: protocol.h:127
#define PX4IO_P_SETUP_CRC
Definition: protocol.h:216
#define PWM_SERVO_CLEAR_ARM_OK
clear the &#39;ARM ok&#39; bit, which deactivates the safety switch
bool override_available
Definition: safety.h:56
#define F2I_MIXER_MAGIC
Definition: protocol.h:314
perf_counter_t _perf_sample_latency
total system latency (based on passed-through timestamp)
Definition: px4io.cpp:250
uint64_t timestamp
Definition: input_rc.h:69
uORB::Subscription _t_actuator_controls_1
actuator controls group 1 topic
Definition: px4io.cpp:261
#define PX4IO_P_SETUP_ARMING_INAIR_RESTART_OK
Definition: protocol.h:188
#define PX4IO_P_STATUS_ALARMS_RC_LOST
Definition: protocol.h:130
#define PWM_SERVO_SET_SBUS_RATE
set SBUS output frame rate in Hz
#define PX4IO_P_STATUS_ALARMS_PWM_ERROR
Definition: protocol.h:131
bool safety_switch_available
Definition: safety.h:54
uint32_t motor_number
Definition: test_motor.h:58
#define PWM_SERVO_SET_SELECT_UPDATE_RATE
selects servo update rates, one bit per servo.
bool _analog_rc_rssi_stable
true when analog RSSI input is stable
Definition: px4io.cpp:290
static const px4_file_operations_t fops
Pointer to the default cdev file operations table; useful for registering clone devices etc...
Definition: CDev.hpp:176
PX4IO interface protocol.
virtual ssize_t read(file_t *filep, char *buffer, size_t buflen)
Perform a read from the device.
Definition: CDev.hpp:111
unsigned _max_controls
Maximum # of controls supported by PX4IO.
Definition: px4io.cpp:233
#define PX4IO_P_SETUP_TRIM_YAW
Yaw trim, in actuator units.
Definition: protocol.h:229
High-resolution timer with callouts and timekeeping.
#define PX4IO_P_STATUS_MIXER
Definition: protocol.h:138
As-needed mixer data upload.
Definition: protocol.h:312
virtual int close(file_t *filep)
Handle a close of the device.
Definition: CDev.cpp:166
int io_handle_status(uint16_t status)
Handle a status update from IO.
Definition: px4io.cpp:1657
MotorTest _motor_test
Definition: px4io.cpp:300
uint16_t rc_lost_frame_count
Definition: input_rc.h:73
Global flash based parameter store.
int io_set_control_state(unsigned group)
Send controls for one group to IO.
Definition: px4io.cpp:1267
#define PX4IO_P_STATUS_FLAGS
Definition: protocol.h:106
#define PX4IO_P_STATUS_ALARMS_TEMPERATURE
Definition: protocol.h:126
#define PWM_SERVO_SET(_servo)
set a single servo to a specific value
#define PX4IO_P_RC_CONFIG_MAX
highest input value
Definition: protocol.h:270
Mixer ioctl interfaces.
static char msg[NUM_MSG][CONFIG_USART1_TXBUFSIZE]
Definition: px4io.c:89
#define PX4IO_P_SETUP_ARMING_FAILSAFE_CUSTOM
Definition: protocol.h:187
__EXPORT int px4io_main(int argc, char *argv[])
Definition: px4io.cpp:3396
PX4IO(device::Device *interface)
Constructor.
Definition: px4io.cpp:472
int orb_subscribe(const struct orb_metadata *meta)
Definition: uORB.cpp:75
#define REG_TO_FLOAT(_reg)
Definition: protocol.h:78
static struct safety_s safety
Definition: Commander.cpp:140
#define PX4IO_P_STATUS_ALARMS_FMU_LOST
Definition: protocol.h:129
int print_debug()
Fetch and print debug console output.
Definition: px4io.cpp:2052
#define PX4IO_P_SETUP_PWM_RATES
Definition: protocol.h:196
#define PX4IO_PAGE_CONTROL_MAX_PWM
0..CONFIG_ACTUATOR_COUNT-1
Definition: protocol.h:297
#define ORB_CHECK_INTERVAL
Definition: px4io.cpp:115
int io_get_status()
Fetch status and alarms from IO.
Definition: px4io.cpp:1761
#define PX4IO_P_RAW_LOST_FRAME_COUNT
Definition: protocol.h:159
#define PX4IO_P_CONFIG_MAX_TRANSFER
Definition: protocol.h:93
bool in_esc_calibration_mode
#define ORB_ID(_name)
Generates a pointer to the uORB metadata structure for a given topic.
Definition: uORB.h:87
uORB::PublicationMulti< actuator_outputs_s > _to_outputs
Definition: px4io.cpp:273
#define PX4IO_P_SETUP_ENABLE_FLIGHTTERMINATION
flight termination; false if the circuit breaker (CBRK_FLIGHTTERM) is set
Definition: protocol.h:244
#define PWM_SERVO_GET_DEFAULT_UPDATE_RATE
get default servo update rate
virtual int ioctl(file *filp, int cmd, unsigned long arg)
IO Control handler.
Definition: px4io.cpp:2437
#define PX4IO_P_SETUP_REBOOT_BL
Definition: protocol.h:213
int mixer_send(const char *buf, unsigned buflen, unsigned retries=3)
Send mixer definition text to IO.
Definition: px4io.cpp:2096
#define PWM_OUTPUT0_DEVICE_PATH
#define F2I_MIXER_ACTION_RESET
Definition: protocol.h:317
int io_set_control_groups()
Send all controls to IO.
Definition: px4io.cpp:1254
int io_disable_rc_handling()
Disable RC input handling.
Definition: px4io.cpp:1491
bool publish(const T &data)
Publish the struct.
Definition: Publication.hpp:68
#define PWM_SERVO_SET_FAILSAFE_PWM
set the PWM value for failsafe
Abstract class for any character device.
Definition: CDev.hpp:58
#define PX4IO_PAGE_SETUP
Definition: protocol.h:175
uint16_t values[PWM_OUTPUT_MAX_CHANNELS]
Header common to all counters.
ETSAirspeed * g_dev
#define PX4IO_P_RAW_RC_FLAGS
Definition: protocol.h:149
void perf_free(perf_counter_t handle)
Free a counter.
virtual int ioctl(device::file_t *filp, int cmd, unsigned long arg)
Definition: airspeed.cpp:133
volatile bool _task_should_exit
worker terminate flag
Definition: px4io.cpp:244
void init()
Activates/configures the hardware registers.
#define PX4IO_P_SETUP_THR_MDL_FAC
factor for modelling motor control signal output to static thrust relationship
Definition: protocol.h:238
#define PX4IO_THERMAL_OFF
Definition: protocol.h:247
uint16_t values[18]
Definition: input_rc.h:76
int unregister_driver(const char *name)
uORB::Subscription test_motor_sub
Definition: px4io.cpp:296
#define PX4IO_PAGE_CONTROL_MIN_PWM
0..CONFIG_ACTUATOR_COUNT-1
Definition: protocol.h:294
#define PX4IO_P_SETUP_DSM
Definition: protocol.h:202
#define PWM_SERVO_SET_DISARMED_PWM
set the PWM value when disarmed - should be no PWM (zero) by default
uint64_t timestamp
Definition: test_motor.h:57
#define PX4IO_P_SETUP_FEATURES
Definition: protocol.h:176
#define DSMX8_BIND_PULSES
Definition: dsm.h:92
#define PX4IO_P_SETUP_ARMING_RC_HANDLING_DISABLED
Definition: protocol.h:190
bool in_test_mode
Definition: px4io.cpp:297
#define PWM_SERVO_SET_TERMINATION_FAILSAFE
make failsafe non-recoverable (termination) if it occurs
#define perf_alloc(a, b)
Definition: px4io.h:59
bool _primary_pwm_device
true if we are the default PWM output
Definition: px4io.cpp:278
Firmware uploader definitions for PX4IO.
void test_fmu_fail(bool is_fail)
Definition: px4io.cpp:221
uint32_t channel_count
Definition: input_rc.h:71
uint8_t driver_instance
Definition: test_motor.h:62
#define PX4IO_PAGE_SERVOS
Definition: protocol.h:144
#define RC_INPUT_ENABLE_RSSI_PWM
Enable RSSI input via PWM signal.
Definition: drv_rc_input.h:78
#define PX4IO_P_RAW_RC_COUNT
Definition: protocol.h:148
device::Device * _interface
Definition: px4io.cpp:229
#define PWM_SERVO_SET_TRIM_PWM
set the TRIM value the output will send
#define PWM_SERVO_ENTER_TEST_MODE
#define PX4IO_P_SETUP_ARMING_IO_ARM_OK
Definition: protocol.h:183
#define PX4IO_P_STATUS_VRSSI
Definition: protocol.h:135
static struct actuator_armed_s armed
Definition: Commander.cpp:139
int io_set_arming_state()
Update IO&#39;s arming-related state.
Definition: px4io.cpp:1403
#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
perf_counter_t _perf_update
local performance counter for status updates
Definition: px4io.cpp:248
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
bool _param_update_force
force a parameter update
Definition: px4io.cpp:269
uint32_t channel_count
uORB::Subscription _t_actuator_armed
actuator controls group 3 topic
Definition: px4io.cpp:264
#define PWM_SERVO_GET_TRIM_PWM
get the TRIM value the output will send
#define PX4IO_P_CONFIG_PROTOCOL_VERSION
Definition: protocol.h:90
#define PWM_OUTPUT_MAX_CHANNELS
#define PX4IO_P_STATUS_FLAGS_ARM_SYNC
Definition: protocol.h:116
#define warnx(...)
Definition: err.h:95
DATAMANAGER driver.
#define PX4IO_P_SETUP_MOTOR_SLEW_MAX
max motor slew rate
Definition: protocol.h:236
Simple error/warning functions, heavily inspired by the BSD functions of the same names...
#define PX4IO_P_SETUP_VSERVO_SCALE
Definition: protocol.h:201
#define PWM_SERVO_SET_FORCE_SAFETY_OFF
force safety switch off (to disable use of safety switch)
#define PX4IO_P_RC_CONFIG_DEADZONE
band around center that is ignored
Definition: protocol.h:271
void task_main(int argc, char *argv[])
bool _hitl_mode
Hardware-in-the-loop simulation mode - don&#39;t publish actuator_outputs.
Definition: px4io.cpp:301
uint16_t system_status() const
Definition: px4io.cpp:226
int32_t _rssi_pwm_min
min RSSI input on PWM channel
Definition: px4io.cpp:288
int register_driver(const char *name, const cdev::px4_file_operations_t *fops, cdev::mode_t mode, void *data)
void perf_end(perf_counter_t handle)
End a performance event.
#define PX4IO_PAGE_PWM_INFO
Definition: protocol.h:171
virtual ~PX4IO()
Destructor.
Definition: px4io.cpp:516
int io_get_raw_rc_input(input_rc_s &input_rc)
Fetch RC inputs from IO.
Definition: px4io.cpp:1785
static void task_main_trampoline(int argc, char *argv[])
Trampoline to the worker task.
Definition: px4io.cpp:896
void test(enum LPS25H_BUS busid)
Perform some basic functional tests on the driver; make sure we can collect data from the sensor in p...
Definition: lps25h.cpp:792
#define PX4IO_P_RC_CONFIG_ASSIGNMENT_MODESWITCH
magic value for mode switch
Definition: protocol.h:273
#define PX4IO_CHECK_CRC
Definition: px4io.cpp:110
#define PX4IO_P_CONFIG_ACTUATOR_COUNT
Definition: protocol.h:95
int(* fn)(int argc, char *argv[])
Definition: tests_main.c:59
bool updated()
Check if there is a new update.
#define PX4IO_PAGE_RC_CONFIG
R/C input configuration.
Definition: protocol.h:267
int disable_rc_handling()
Disable RC input handling.
Definition: px4io.cpp:1484
#define PX4IO_P_STATUS_FLAGS_OVERRIDE
Definition: protocol.h:108
#define PWM_SERVO_GET_RATEGROUP(_n)
get the _n&#39;th rate group&#39;s channels; *(uint32_t *)arg returns a bitmap of channels whose update rates...
uORB::Publication< servorail_status_s > _to_servorail
Definition: px4io.cpp:275
__BEGIN_DECLS typedef uint64_t hrt_abstime
Absolute time, in microsecond units.
Definition: drv_hrt.h:58
unsigned _max_rc_input
Maximum receiver channels supported by PX4IO.
Definition: px4io.cpp:234
virtual int write(unsigned address, void *data, unsigned count)
Write directly to the device.
Definition: Device.hpp:115
uORB::PublicationMulti< input_rc_s > _to_input_rc
Definition: px4io.cpp:272
#define PX4IO_P_STATUS_FREEMEM
Definition: protocol.h:103
#define PX4IO_P_RAW_RC_FLAGS_FRAME_DROP
Definition: protocol.h:150
hrt_abstime timeout
Definition: px4io.cpp:298
#define PWM_SERVO_GET(_servo)
get a single specific servo value
__BEGIN_DECLS typedef void * orb_advert_t
ORB topic advertiser handle.
Definition: uORB.h:134
int io_handle_alarms(uint16_t alarms)
Handle an alarm update from IO.
Definition: px4io.cpp:1723
unsigned _rc_chan_count
Internal copy of the last seen number of RC channels.
Definition: px4io.cpp:240
int fd
Definition: dataman.cpp:146
#define PX4IO_P_STATUS_FLAGS_SAFETY_OFF
Definition: protocol.h:119
#define PX4IO_FORCE_SAFETY_MAGIC
Definition: protocol.h:224
#define PX4IO_P_RAW_RC_FLAGS_RC_DSM11
Definition: protocol.h:152
#define PWM_SERVO_SET_MIN_PWM
set the minimum PWM value the output will send
virtual int ioctl(unsigned operation, unsigned &arg)
Perform a device-specific operation.
Definition: Device.hpp:124
#define PX4IO_P_RAW_RC_FLAGS_RC_OK
Definition: protocol.h:154
#define PX4IO_P_SETUP_TRIM_ROLL
Roll trim, in actuator units.
Definition: protocol.h:227
#define err(eval,...)
Definition: err.h:83
#define PX4IO_P_STATUS_ALARMS
Definition: protocol.h:124
#define DSM2_BIND_PULSES
Definition: dsm.h:90
#define PX4IO_PAGE_STATUS
Definition: protocol.h:102
__EXPORT param_t param_find(const char *name)
Look up a parameter by name.
Definition: parameters.cpp:370
#define MIXERIOCRESET
reset (clear) the mixer configuration
Definition: drv_mixer.h:71
#define PX4IO_P_RC_CONFIG_ASSIGNMENT
mapped input value
Definition: protocol.h:272
#define PX4IO_P_STATUS_ALARMS_VSERVO_FAULT
Definition: protocol.h:132
static int start()
Definition: dataman.cpp:1452
#define IO_POLL_INTERVAL
Definition: px4io.cpp:116
bool _override_available
true if manual reversion mode is enabled
Definition: px4io.cpp:281
#define PX4IO_P_RC_CONFIG_STRIDE
spacing between channel config data
Definition: protocol.h:277
#define PX4IO_PAGE_CONTROL_TRIM_PWM
0..CONFIG_ACTUATOR_COUNT-1
Definition: protocol.h:300
uint32_t timeout_ms
Definition: test_motor.h:60
#define DSMX_BIND_PULSES
Definition: dsm.h:91
#define PX4IO_PAGE_DIRECT_PWM
0..CONFIG_ACTUATOR_COUNT-1
Definition: protocol.h:280
#define PX4IO_P_RC_CONFIG_CENTER
center input value
Definition: protocol.h:269
#define DSM_BIND_POWER_UP
power up DSM receiver
#define PWM_SERVO_SET_MAX_PWM
set the maximum PWM value the output will send
uint16_t rc_total_frame_count
Definition: input_rc.h:74
uint16_t _alarms
Various IO alarms.
Definition: px4io.cpp:254
#define PX4IO_REBOOT_BL_MAGIC
Definition: protocol.h:214
#define PX4IO_P_RC_CONFIG_OPTIONS_ENABLED
Definition: protocol.h:275
static void write(bootloader_app_shared_t *pshared)
bool rc_lost
Definition: input_rc.h:78
#define PX4IO_P_STATUS_FLAGS_RAW_PWM
Definition: protocol.h:114
#define PWM_SERVO_SET_MODE
#define PX4IO_P_SETUP_THERMAL
thermal management
Definition: protocol.h:240
#define PWM_SERVO_SET_FORCE_FAILSAFE
force failsafe mode (failsafe values are set immediately even if failsafe condition not met) ...
#define PX4IO_P_STATUS_FLAGS_RC_OK
Definition: protocol.h:109
#define PX4IO_DEVICE_PATH
Definition: px4io.cpp:470
#define PX4IO_P_SETUP_ARMING_FMU_ARMED
Definition: protocol.h:184
virtual ssize_t write(file *filp, const char *buffer, size_t len)
write handler.
Definition: px4io.cpp:2916
uint16_t _last_written_arming_c
the last written arming state reg
Definition: px4io.cpp:256
int upload(const char *filenames[])
uint64_t timestamp
Definition: safety.h:53
#define PX4IO_P_STATUS_FLAGS_INIT_OK
Definition: protocol.h:117
unsigned _max_relays
Maximum relays supported by PX4IO.
Definition: px4io.cpp:235
#define PX4IO_P_STATUS_FLAGS_RC_ST24
Definition: protocol.h:121
#define PX4IO_PROTOCOL_VERSION
Definition: protocol.h:83
#define PX4IO_P_SETUP_ARMING_FORCE_FAILSAFE
Definition: protocol.h:192
#define PX4IO_P_SETUP_RC_THR_FAILSAFE_US
the throttle failsafe pulse length in microseconds
Definition: protocol.h:221
uORB::Subscription _t_actuator_controls_3
actuator controls group 2 topic
Definition: px4io.cpp:263
#define PWM_SERVO_GET_MIN_PWM
get the minimum PWM value the output will send
struct @83::@85::@87 file
int orb_check(int handle, bool *updated)
Definition: uORB.cpp:95
#define RC_INPUT_ENABLE_RSSI_ANALOG
Enable RSSI input via ADC.
Definition: drv_rc_input.h:75
uORB::Subscription _t_vehicle_command
vehicle command topic
Definition: px4io.cpp:267
bool _armed
wether the system is armed
Definition: px4io.cpp:280
#define PX4IO_P_RAW_RC_FLAGS_MAPPING_OK
Definition: protocol.h:153
#define PX4IO_P_SETUP_ARMING
Definition: protocol.h:182
float value
Definition: test_motor.h:59
#define PX4IO_P_SETUP_FEATURES_PWM_RSSI
enable PWM RSSI parsing
Definition: protocol.h:179
bool _rc_handling_disabled
If set, IO does not evaluate, but only forward the RC values.
Definition: px4io.cpp:239
#define PWM_SERVO_GET_DISABLE_LOCKDOWN
get the lockdown override flag to enable outputs in HIL
int32_t _rssi_pwm_max
max RSSI input on PWM channel
Definition: px4io.cpp:287
#define PX4IO_PAGE_CONFIG
Definition: protocol.h:89
Fundamental base class for all physical drivers (I2C, SPI).
Definition: Device.hpp:65
#define errx(eval,...)
Definition: err.h:89
#define PX4IO_P_SETUP_FEATURES_ADC_RSSI
enable ADC RSSI parsing
Definition: protocol.h:180
uORB::Subscription _t_actuator_controls_2
Definition: px4io.cpp:262
#define PX4IO_P_STATUS_FLAGS_FAILSAFE
Definition: protocol.h:118
void dsm_bind_ioctl(int dsmMode)
Handle issuing dsm bind ioctl to px4io.
Definition: px4io.cpp:1705
#define PX4IO_P_SETUP_SCALE_ROLL
Roll scale, in actuator units.
Definition: protocol.h:230
#define PX4IO_P_SETUP_SCALE_YAW
Yaw scale, in actuator units.
Definition: protocol.h:232
static constexpr unsigned UPDATE_INTERVAL_MAX
Definition: px4io.cpp:113
device::Device * PX4IO_serial_interface()
uint16_t _status
Various IO status flags.
Definition: px4io.cpp:253
#define PX4IO_P_SETUP_ARMING_FMU_PREARMED
Definition: protocol.h:185
bool _test_fmu_fail
To test what happens if IO loses FMU.
Definition: px4io.cpp:293
#define PX4IO_P_STATUS_FLAGS_OUTPUTS_ARMED
Definition: protocol.h:107
#define PX4IO_P_RAW_RC_NRSSI
Definition: protocol.h:156
#define PX4IO_P_SETUP_ARMING_OVERRIDE_IMMEDIATE
Definition: protocol.h:194
uORB::Subscription _t_vehicle_control_mode
vehicle control mode topic
Definition: px4io.cpp:265
#define PX4IO_P_STATUS_ALARMS_ACC_CURRENT
Definition: protocol.h:128
#define OK
Definition: uavcan_main.cpp:71
#define REG_TO_SIGNED(_reg)
Definition: protocol.h:75
#define PX4IO_PAGE_CONTROLS
actuator control groups, one after the other, 8 wide
Definition: protocol.h:251
#define PX4IO_P_SETUP_ARMING_LOCKDOWN
Definition: protocol.h:191
bool update(void *dst)
Update the struct.
unsigned _max_transfer
Maximum number of I2C transfers supported by PX4IO.
Definition: px4io.cpp:236
void task_main()
worker task
Definition: px4io.cpp:902
#define PX4IO_RATE_MAP_BASE
Definition: protocol.h:172
#define PWM_HIGHEST_MAX
Highest maximum PWM in us.
static const uint32_t _io_reg_get_error
Definition: px4io.cpp:403
virtual int detect()
Detect if a PX4IO is connected.
Definition: px4io.cpp:545
#define PX4IO_P_SETUP_FEATURES_SBUS2_OUT
enable S.Bus v2 output
Definition: protocol.h:178
#define CBRK_FLIGHTTERM_KEY
bool _in_esc_calibration_mode
do not send control outputs to IO (used for esc calibration)
Definition: px4io.cpp:284
#define PX4IO_P_RAW_RC_DATA
Definition: protocol.h:157
char text[0]
Definition: protocol.h:320
uint64_t _rc_last_valid
last valid timestamp
Definition: px4io.cpp:241
#define SBUS_SET_PROTO_VERSION
Enable S.BUS version 1 / 2 output (0 to disable)
Definition: drv_sbus.h:56
bool publish(const T &data)
Publish the struct.
#define PX4IO_P_RC_CONFIG_MIN
lowest input value
Definition: protocol.h:268
#define PX4IO_P_STATUS_ALARMS_VBATT_LOW
Definition: protocol.h:125
void unlock()
Release the driver lock.
Definition: CDev.hpp:269
#define PX4IO_P_RC_CONFIG_OPTIONS
channel options bitmask
Definition: protocol.h:274
#define PWM_SERVO_GET_FAILSAFE_PWM
get the PWM value for failsafe
#define PX4IO_P_CONFIG_BOOTLOADER_VERSION
Definition: protocol.h:92
bool _lockdown_override
allow to override the safety lockdown
Definition: px4io.cpp:279
mode
Definition: vtol_type.h:76
int io_reg_get(uint8_t page, uint8_t offset, uint16_t *values, unsigned num_values)
read register(s)
Definition: px4io.cpp:2003
bool copy(void *dst)
Copy the struct.
#define warn(...)
Definition: err.h:94
#define PX4IO_P_SETUP_FEATURES_SBUS1_OUT
enable S.Bus v1 output
Definition: protocol.h:177
bool safety_off
Definition: safety.h:55
uint16_t _last_written_arming_s
the last written arming state reg
Definition: px4io.cpp:255
#define PX4IO_P_SETUP_AIRMODE
air-mode
Definition: protocol.h:242
void perf_begin(perf_counter_t handle)
Begin a performance event.
#define PX4IO_PAGE_RAW_ADC_INPUT
Definition: protocol.h:168
uint64_t timestamp_last_signal
Definition: input_rc.h:70
int set_update_rate(int rate)
Set the update rate for actuator outputs from FMU to IO.
Definition: px4io.cpp:2947
#define PX4IO_P_CONFIG_HARDWARE_VERSION
Definition: protocol.h:91
struct MultirotorMixer::saturation_status::@66 flags
bool _cb_flighttermination
true if the flight termination circuit breaker is enabled
Definition: px4io.cpp:283
#define PX4IO_P_RAW_RC_FLAGS_FAILSAFE
Definition: protocol.h:151
uint8_t action
Definition: protocol.h:316
#define PWM_SERVO_SET_DISABLE_LOCKDOWN
set the lockdown override flag to enable outputs in HIL
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
uint32_t param_t
Parameter handle.
Definition: param.h:98
virtual int read(unsigned address, void *data, unsigned count)
Read directly from the device.
Definition: Device.hpp:103
#define PWM_LOWEST_MIN
Lowest minimum PWM in us.
virtual int poll(file_t *filep, px4_pollfd_struct_t *fds, bool setup)
Perform a poll setup/teardown operation.
Definition: CDev.cpp:213
#define PWM_SERVO_DISARM
disarm all servo outputs (stop generating pulses)
#define PX4IO_P_STATUS_FLAGS_RC_PPM
Definition: protocol.h:110
Performance measuring tools.
#define PX4IO_P_STATUS_FLAGS_RC_DSM
Definition: protocol.h:111
#define PX4IO_P_SETUP_ARMING_TERMINATION_FAILSAFE
Definition: protocol.h:193
#define PWM_SERVO_GET_MAX_PWM
get the maximum PWM value the output will send
#define PWM_SERVO_SET_UPDATE_RATE
set alternate servo update rate
#define PX4IO_REBOOT_BOOTLOADER
Definition: px4io.cpp:109
#define PWM_SERVO_EXIT_TEST_MODE