|
|
|
@ -61,6 +61,7 @@
@@ -61,6 +61,7 @@
|
|
|
|
|
#include <drivers/device/device.h> |
|
|
|
|
#include <drivers/drv_rc_input.h> |
|
|
|
|
#include <drivers/drv_pwm_output.h> |
|
|
|
|
#include <drivers/drv_sbus.h> |
|
|
|
|
#include <drivers/drv_gpio.h> |
|
|
|
|
#include <drivers/drv_hrt.h> |
|
|
|
|
#include <drivers/drv_mixer.h> |
|
|
|
@ -238,6 +239,7 @@ private:
@@ -238,6 +239,7 @@ private:
|
|
|
|
|
unsigned _update_interval; ///< Subscription interval limiting send rate
|
|
|
|
|
bool _rc_handling_disabled; ///< If set, IO does not evaluate, but only forward the RC values
|
|
|
|
|
unsigned _rc_chan_count; ///< Internal copy of the last seen number of RC channels
|
|
|
|
|
uint64_t _rc_last_valid; ///< last valid timestamp
|
|
|
|
|
|
|
|
|
|
volatile int _task; ///< worker task id
|
|
|
|
|
volatile bool _task_should_exit; ///< worker terminate flag
|
|
|
|
@ -444,7 +446,7 @@ private:
@@ -444,7 +446,7 @@ private:
|
|
|
|
|
* @param vservo vservo register |
|
|
|
|
* @param vrssi vrssi register |
|
|
|
|
*/ |
|
|
|
|
void io_handle_vservo(uint16_t vbatt, uint16_t ibatt); |
|
|
|
|
void io_handle_vservo(uint16_t vservo, uint16_t vrssi); |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -467,6 +469,7 @@ PX4IO::PX4IO(device::Device *interface) :
@@ -467,6 +469,7 @@ PX4IO::PX4IO(device::Device *interface) :
|
|
|
|
|
_update_interval(0), |
|
|
|
|
_rc_handling_disabled(false), |
|
|
|
|
_rc_chan_count(0), |
|
|
|
|
_rc_last_valid(0), |
|
|
|
|
_task(-1), |
|
|
|
|
_task_should_exit(false), |
|
|
|
|
_mavlink_fd(-1), |
|
|
|
@ -1357,7 +1360,10 @@ PX4IO::io_get_status()
@@ -1357,7 +1360,10 @@ PX4IO::io_get_status()
|
|
|
|
|
uint16_t regs[6]; |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
/* get STATUS_FLAGS, STATUS_ALARMS, STATUS_VBATT, STATUS_IBATT in that order */ |
|
|
|
|
/* get
|
|
|
|
|
* STATUS_FLAGS, STATUS_ALARMS, STATUS_VBATT, STATUS_IBATT, |
|
|
|
|
* STATUS_VSERVO, STATUS_VRSSI, STATUS_PRSSI |
|
|
|
|
* in that order */ |
|
|
|
|
ret = io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_FLAGS, ®s[0], sizeof(regs) / sizeof(regs[0])); |
|
|
|
|
|
|
|
|
|
if (ret != OK) |
|
|
|
@ -1394,7 +1400,8 @@ PX4IO::io_get_raw_rc_input(rc_input_values &input_rc)
@@ -1394,7 +1400,8 @@ PX4IO::io_get_raw_rc_input(rc_input_values &input_rc)
|
|
|
|
|
* |
|
|
|
|
* This should be the common case (9 channel R/C control being a reasonable upper bound). |
|
|
|
|
*/ |
|
|
|
|
input_rc.timestamp = hrt_absolute_time(); |
|
|
|
|
input_rc.timestamp_publication = hrt_absolute_time(); |
|
|
|
|
|
|
|
|
|
ret = io_reg_get(PX4IO_PAGE_RAW_RC_INPUT, PX4IO_P_RAW_RC_COUNT, ®s[0], prolog + 9); |
|
|
|
|
|
|
|
|
|
if (ret != OK) |
|
|
|
@ -1404,13 +1411,25 @@ PX4IO::io_get_raw_rc_input(rc_input_values &input_rc)
@@ -1404,13 +1411,25 @@ PX4IO::io_get_raw_rc_input(rc_input_values &input_rc)
|
|
|
|
|
* Get the channel count any any extra channels. This is no more expensive than reading the |
|
|
|
|
* channel count once. |
|
|
|
|
*/ |
|
|
|
|
channel_count = regs[0]; |
|
|
|
|
channel_count = regs[PX4IO_P_RAW_RC_COUNT]; |
|
|
|
|
|
|
|
|
|
if (channel_count != _rc_chan_count) |
|
|
|
|
perf_count(_perf_chan_count); |
|
|
|
|
|
|
|
|
|
_rc_chan_count = channel_count; |
|
|
|
|
|
|
|
|
|
input_rc.rc_ppm_frame_length = regs[PX4IO_P_RAW_RC_DATA]; |
|
|
|
|
input_rc.rssi = regs[PX4IO_P_RAW_RC_NRSSI]; |
|
|
|
|
input_rc.rc_failsafe = (regs[PX4IO_P_RAW_RC_FLAGS] & PX4IO_P_RAW_RC_FLAGS_FAILSAFE); |
|
|
|
|
input_rc.rc_lost_frame_count = regs[PX4IO_P_RAW_LOST_FRAME_COUNT]; |
|
|
|
|
input_rc.rc_total_frame_count = regs[PX4IO_P_RAW_FRAME_COUNT]; |
|
|
|
|
|
|
|
|
|
/* rc_lost has to be set before the call to this function */ |
|
|
|
|
if (!input_rc.rc_lost && !input_rc.rc_failsafe) |
|
|
|
|
_rc_last_valid = input_rc.timestamp_publication; |
|
|
|
|
|
|
|
|
|
input_rc.timestamp_last_signal = _rc_last_valid; |
|
|
|
|
|
|
|
|
|
if (channel_count > 9) { |
|
|
|
|
ret = io_reg_get(PX4IO_PAGE_RAW_RC_INPUT, PX4IO_P_RAW_RC_BASE + 9, ®s[prolog + 9], channel_count - 9); |
|
|
|
|
|
|
|
|
@ -1427,13 +1446,12 @@ PX4IO::io_get_raw_rc_input(rc_input_values &input_rc)
@@ -1427,13 +1446,12 @@ PX4IO::io_get_raw_rc_input(rc_input_values &input_rc)
|
|
|
|
|
int |
|
|
|
|
PX4IO::io_publish_raw_rc() |
|
|
|
|
{ |
|
|
|
|
/* if no raw RC, just don't publish */ |
|
|
|
|
if (!(_status & PX4IO_P_STATUS_FLAGS_RC_OK)) |
|
|
|
|
return OK; |
|
|
|
|
|
|
|
|
|
/* fetch values from IO */ |
|
|
|
|
rc_input_values rc_val; |
|
|
|
|
rc_val.timestamp = hrt_absolute_time(); |
|
|
|
|
|
|
|
|
|
/* set the RC status flag ORDER MATTERS! */ |
|
|
|
|
rc_val.rc_lost = !(_status & PX4IO_P_STATUS_FLAGS_RC_OK); |
|
|
|
|
|
|
|
|
|
int ret = io_get_raw_rc_input(rc_val); |
|
|
|
|
|
|
|
|
@ -1452,13 +1470,11 @@ PX4IO::io_publish_raw_rc()
@@ -1452,13 +1470,11 @@ PX4IO::io_publish_raw_rc()
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
rc_val.input_source = RC_INPUT_SOURCE_UNKNOWN; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* set RSSI */ |
|
|
|
|
|
|
|
|
|
if (rc_val.input_source != RC_INPUT_SOURCE_PX4IO_SBUS) { |
|
|
|
|
// XXX the correct scaling needs to be validated here
|
|
|
|
|
rc_val.rssi = (_servorail_status.rssi_v / 3.3f) * UINT8_MAX; |
|
|
|
|
/* we do not know the RC input, only publish if RC OK flag is set */ |
|
|
|
|
/* if no raw RC, just don't publish */ |
|
|
|
|
if (!(_status & PX4IO_P_STATUS_FLAGS_RC_OK)) |
|
|
|
|
return OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* lazily advertise on first publication */ |
|
|
|
@ -1767,15 +1783,14 @@ PX4IO::print_status()
@@ -1767,15 +1783,14 @@ PX4IO::print_status()
|
|
|
|
|
printf("%u bytes free\n", |
|
|
|
|
io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_FREEMEM)); |
|
|
|
|
uint16_t flags = io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_FLAGS); |
|
|
|
|
printf("status 0x%04x%s%s%s%s%s%s%s%s%s%s%s%s%s\n", |
|
|
|
|
uint16_t io_status_flags = flags; |
|
|
|
|
printf("status 0x%04x%s%s%s%s%s%s%s%s%s%s%s%s\n", |
|
|
|
|
flags, |
|
|
|
|
((flags & PX4IO_P_STATUS_FLAGS_OUTPUTS_ARMED) ? " OUTPUTS_ARMED" : ""), |
|
|
|
|
((flags & PX4IO_P_STATUS_FLAGS_SAFETY_OFF) ? " SAFETY_OFF" : " SAFETY_SAFE"), |
|
|
|
|
((flags & PX4IO_P_STATUS_FLAGS_OVERRIDE) ? " OVERRIDE" : ""), |
|
|
|
|
((flags & PX4IO_P_STATUS_FLAGS_RC_OK) ? " RC_OK" : " RC_FAIL"), |
|
|
|
|
((flags & PX4IO_P_STATUS_FLAGS_RC_PPM) ? " PPM" : ""), |
|
|
|
|
(((flags & PX4IO_P_STATUS_FLAGS_RC_DSM) && (!(flags & PX4IO_P_STATUS_FLAGS_RC_DSM11))) ? " DSM10" : ""), |
|
|
|
|
(((flags & PX4IO_P_STATUS_FLAGS_RC_DSM) && (flags & PX4IO_P_STATUS_FLAGS_RC_DSM11)) ? " DSM11" : ""), |
|
|
|
|
((flags & PX4IO_P_STATUS_FLAGS_RC_SBUS) ? " SBUS" : ""), |
|
|
|
|
((flags & PX4IO_P_STATUS_FLAGS_FMU_OK) ? " FMU_OK" : " FMU_FAIL"), |
|
|
|
|
((flags & PX4IO_P_STATUS_FLAGS_RAW_PWM) ? " RAW_PWM_PASSTHROUGH" : ""), |
|
|
|
@ -1834,8 +1849,17 @@ PX4IO::print_status()
@@ -1834,8 +1849,17 @@ PX4IO::print_status()
|
|
|
|
|
|
|
|
|
|
printf("\n"); |
|
|
|
|
|
|
|
|
|
if ((flags & PX4IO_P_STATUS_FLAGS_RC_PPM)) { |
|
|
|
|
int frame_len = io_reg_get(PX4IO_PAGE_STATUS, PX4IO_P_STATUS_RC_DATA); |
|
|
|
|
flags = io_reg_get(PX4IO_PAGE_RAW_RC_INPUT, PX4IO_P_RAW_RC_FLAGS); |
|
|
|
|
printf("R/C flags: 0x%04x%s%s%s%s%s\n", flags, |
|
|
|
|
(((io_status_flags & PX4IO_P_STATUS_FLAGS_RC_DSM) && (!(flags & PX4IO_P_RAW_RC_FLAGS_RC_DSM11))) ? " DSM10" : ""), |
|
|
|
|
(((io_status_flags & PX4IO_P_STATUS_FLAGS_RC_DSM) && (flags & PX4IO_P_RAW_RC_FLAGS_RC_DSM11)) ? " DSM11" : ""), |
|
|
|
|
((flags & PX4IO_P_RAW_RC_FLAGS_FRAME_DROP) ? " FRAME_DROP" : ""), |
|
|
|
|
((flags & PX4IO_P_RAW_RC_FLAGS_FAILSAFE) ? " FAILSAFE" : ""), |
|
|
|
|
((flags & PX4IO_P_RAW_RC_FLAGS_MAPPING_OK) ? " MAPPING_OK" : "") |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
if ((io_status_flags & PX4IO_P_STATUS_FLAGS_RC_PPM)) { |
|
|
|
|
int frame_len = io_reg_get(PX4IO_PAGE_RAW_RC_INPUT, PX4IO_P_RAW_RC_DATA); |
|
|
|
|
printf("RC data (PPM frame len) %u us\n", frame_len); |
|
|
|
|
|
|
|
|
|
if ((frame_len - raw_inputs * 2000 - 3000) < 0) { |
|
|
|
@ -1861,7 +1885,13 @@ PX4IO::print_status()
@@ -1861,7 +1885,13 @@ PX4IO::print_status()
|
|
|
|
|
printf("\n"); |
|
|
|
|
|
|
|
|
|
/* setup and state */ |
|
|
|
|
printf("features 0x%04x\n", io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES)); |
|
|
|
|
uint16_t features = io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES); |
|
|
|
|
printf("features 0x%04x%s%s%s%s\n", features, |
|
|
|
|
((features & PX4IO_P_SETUP_FEATURES_SBUS1_OUT) ? " S.BUS1_OUT" : ""), |
|
|
|
|
((features & PX4IO_P_SETUP_FEATURES_SBUS2_OUT) ? " S.BUS2_OUT" : ""), |
|
|
|
|
((features & PX4IO_P_SETUP_FEATURES_PWM_RSSI) ? " RSSI_PWM" : ""), |
|
|
|
|
((features & PX4IO_P_SETUP_FEATURES_ADC_RSSI) ? " RSSI_ADC" : "") |
|
|
|
|
); |
|
|
|
|
uint16_t arming = io_reg_get(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_ARMING); |
|
|
|
|
printf("arming 0x%04x%s%s%s%s%s%s\n", |
|
|
|
|
arming, |
|
|
|
@ -2283,6 +2313,38 @@ PX4IO::ioctl(file * /*filep*/, int cmd, unsigned long arg)
@@ -2283,6 +2313,38 @@ PX4IO::ioctl(file * /*filep*/, int cmd, unsigned long arg)
|
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case RC_INPUT_ENABLE_RSSI_ANALOG: |
|
|
|
|
|
|
|
|
|
if (arg) { |
|
|
|
|
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES, 0, PX4IO_P_SETUP_FEATURES_ADC_RSSI); |
|
|
|
|
} else { |
|
|
|
|
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES, PX4IO_P_SETUP_FEATURES_ADC_RSSI, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case RC_INPUT_ENABLE_RSSI_PWM: |
|
|
|
|
|
|
|
|
|
if (arg) { |
|
|
|
|
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES, 0, PX4IO_P_SETUP_FEATURES_PWM_RSSI); |
|
|
|
|
} else { |
|
|
|
|
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES, PX4IO_P_SETUP_FEATURES_PWM_RSSI, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case SBUS_SET_PROTO_VERSION: |
|
|
|
|
|
|
|
|
|
if (arg == 1) { |
|
|
|
|
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES, 0, PX4IO_P_SETUP_FEATURES_SBUS1_OUT); |
|
|
|
|
} else if (arg == 2) { |
|
|
|
|
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES, 0, PX4IO_P_SETUP_FEATURES_SBUS2_OUT); |
|
|
|
|
} else { |
|
|
|
|
ret = io_reg_modify(PX4IO_PAGE_SETUP, PX4IO_P_SETUP_FEATURES, (PX4IO_P_SETUP_FEATURES_SBUS1_OUT | PX4IO_P_SETUP_FEATURES_SBUS2_OUT), 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
/* not a recognized value */ |
|
|
|
|
ret = -ENOTTY; |
|
|
|
@ -2656,7 +2718,7 @@ monitor(void)
@@ -2656,7 +2718,7 @@ monitor(void)
|
|
|
|
|
/* clear screen */ |
|
|
|
|
printf("\033[2J"); |
|
|
|
|
|
|
|
|
|
unsigned cancels = 3; |
|
|
|
|
unsigned cancels = 2; |
|
|
|
|
|
|
|
|
|
for (;;) { |
|
|
|
|
pollfd fds[1]; |
|
|
|
@ -2932,6 +2994,60 @@ px4io_main(int argc, char *argv[])
@@ -2932,6 +2994,60 @@ px4io_main(int argc, char *argv[])
|
|
|
|
|
if (!strcmp(argv[1], "bind")) |
|
|
|
|
bind(argc, argv); |
|
|
|
|
|
|
|
|
|
if (!strcmp(argv[1], "sbus1_out")) { |
|
|
|
|
/* we can cheat and call the driver directly, as it
|
|
|
|
|
* doesn't reference filp in ioctl() |
|
|
|
|
*/ |
|
|
|
|
int ret = g_dev->ioctl(nullptr, SBUS_SET_PROTO_VERSION, 1); |
|
|
|
|
|
|
|
|
|
if (ret != 0) { |
|
|
|
|
errx(ret, "S.BUS v1 failed"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
exit(0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!strcmp(argv[1], "sbus2_out")) { |
|
|
|
|
/* we can cheat and call the driver directly, as it
|
|
|
|
|
* doesn't reference filp in ioctl() |
|
|
|
|
*/ |
|
|
|
|
int ret = g_dev->ioctl(nullptr, SBUS_SET_PROTO_VERSION, 2); |
|
|
|
|
|
|
|
|
|
if (ret != 0) { |
|
|
|
|
errx(ret, "S.BUS v2 failed"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
exit(0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!strcmp(argv[1], "rssi_analog")) { |
|
|
|
|
/* we can cheat and call the driver directly, as it
|
|
|
|
|
* doesn't reference filp in ioctl() |
|
|
|
|
*/ |
|
|
|
|
int ret = g_dev->ioctl(nullptr, RC_INPUT_ENABLE_RSSI_ANALOG, 1); |
|
|
|
|
|
|
|
|
|
if (ret != 0) { |
|
|
|
|
errx(ret, "RSSI analog failed"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
exit(0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!strcmp(argv[1], "rssi_pwm")) { |
|
|
|
|
/* we can cheat and call the driver directly, as it
|
|
|
|
|
* doesn't reference filp in ioctl() |
|
|
|
|
*/ |
|
|
|
|
int ret = g_dev->ioctl(nullptr, RC_INPUT_ENABLE_RSSI_PWM, 1); |
|
|
|
|
|
|
|
|
|
if (ret != 0) { |
|
|
|
|
errx(ret, "RSSI PWM failed"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
exit(0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
out: |
|
|
|
|
errx(1, "need a command, try 'start', 'stop', 'status', 'test', 'monitor', 'debug',\n 'recovery', 'limit', 'current', 'bind', 'checkcrc', 'forceupdate' or 'update'"); |
|
|
|
|
errx(1, "need a command, try 'start', 'stop', 'status', 'test', 'monitor', 'debug <level>',\n" |
|
|
|
|
"'recovery', 'limit <rate>', 'current', 'bind', 'checkcrc',\n" |
|
|
|
|
"'forceupdate', 'update', 'sbus1_out', 'sbus2_out', 'rssi_analog' or 'rssi_pwm'"); |
|
|
|
|
} |
|
|
|
|