diff --git a/libraries/AP_HAL_PX4/GPIO.cpp b/libraries/AP_HAL_PX4/GPIO.cpp index b44d03f45cb1a05de83ff86e9e5de2a8f259cd5a..4e7fd9a63a4057a03c8d4ba2285e0c737d6013c0 100644 --- a/libraries/AP_HAL_PX4/GPIO.cpp +++ b/libraries/AP_HAL_PX4/GPIO.cpp @@ -48,11 +48,11 @@ void PX4GPIO::init() hal.scheduler->panic("Unable to open /dev/tone_alarm"); } -#ifdef CONFIG_ARCH_BOARD_PX4FMU_V1 - _gpio_fmu_fd = open(PX4FMU_DEVICE_PATH, O_RDWR); + _gpio_fmu_fd = open(PX4FMU_DEVICE_PATH, 0); if (_gpio_fmu_fd == -1) { hal.scheduler->panic("Unable to open GPIO"); } +#ifdef CONFIG_ARCH_BOARD_PX4FMU_V1 if (ioctl(_gpio_fmu_fd, GPIO_CLEAR, GPIO_EXT_1) != 0) { hal.console->printf("GPIO: Unable to setup GPIO_1\n"); } @@ -66,7 +66,13 @@ void PX4GPIO::init() } void PX4GPIO::pinMode(uint8_t pin, uint8_t output) -{} +{ + switch (pin) { + case PX4_GPIO_FMU_SERVO_PIN(0) ... PX4_GPIO_FMU_SERVO_PIN(5): + ioctl(_gpio_fmu_fd, output?GPIO_SET_OUTPUT:GPIO_SET_INPUT, 1U<<(pin-PX4_GPIO_FMU_SERVO_PIN(0))); + break; + } +} int8_t PX4GPIO::analogPinToDigitalPin(uint8_t pin) { @@ -114,7 +120,14 @@ uint8_t PX4GPIO::read(uint8_t pin) { ioctl(_gpio_io_fd, GPIO_GET, (unsigned long)&relays); return (relays & PX4IO_P_SETUP_RELAYS_ACC2)?HIGH:LOW; #endif + + case PX4_GPIO_FMU_SERVO_PIN(0) ... PX4_GPIO_FMU_SERVO_PIN(5): { + uint32_t v = 0; + ioctl(_gpio_fmu_fd, GPIO_GET, (unsigned long)&v); + return (v & (1U<<(pin-PX4_GPIO_FMU_SERVO_PIN(0))))?HIGH:LOW; } + } + return LOW; } void PX4GPIO::write(uint8_t pin, uint8_t value) @@ -186,6 +199,10 @@ void PX4GPIO::write(uint8_t pin, uint8_t value) ioctl(_gpio_io_fd, value==LOW?GPIO_CLEAR:GPIO_SET, PX4IO_P_SETUP_RELAYS_ACC2); break; #endif + + case PX4_GPIO_FMU_SERVO_PIN(0) ... PX4_GPIO_FMU_SERVO_PIN(5): + ioctl(_gpio_fmu_fd, value==LOW?GPIO_CLEAR:GPIO_SET, 1U<<(pin-PX4_GPIO_FMU_SERVO_PIN(0))); + break; } } diff --git a/libraries/AP_HAL_PX4/GPIO.h b/libraries/AP_HAL_PX4/GPIO.h index 6f4bde18c9128172d8af7f572a73ecfcdcb13498..6202d2f4fccd3686da15f6d947239ce7c73f50e1 100644 --- a/libraries/AP_HAL_PX4/GPIO.h +++ b/libraries/AP_HAL_PX4/GPIO.h @@ -13,6 +13,12 @@ #define PX4_GPIO_EXT_IO_ACC1_PIN 115 #define PX4_GPIO_EXT_IO_ACC2_PIN 116 +/* + start servo channels used as GPIO at 50. Pin 50 is + the first FMU servo pin + */ +#define PX4_GPIO_FMU_SERVO_PIN(n) (n+50) + #if CONFIG_HAL_BOARD == HAL_BOARD_PX4 # define HAL_GPIO_A_LED_PIN 27 # define HAL_GPIO_B_LED_PIN 26 diff --git a/libraries/AP_HAL_PX4/RCOutput.cpp b/libraries/AP_HAL_PX4/RCOutput.cpp index 4800929ca10d4dbb243028edf9ee6f2b049d41e0..c36f8705a4af9edafc9599d2ee6d071848458c42 100644 --- a/libraries/AP_HAL_PX4/RCOutput.cpp +++ b/libraries/AP_HAL_PX4/RCOutput.cpp @@ -41,29 +41,29 @@ void PX4RCOutput::init(void* unused) return; } - /* if we have 8 servos, then we are attached to PX4IO. In that - * case, we want to open the PX4FMU driver for the 4 additional - * channels - */ - if (_servo_count <= 4) { - return; - } _alt_fd = open("/dev/px4fmu", O_RDWR); if (_alt_fd == -1) { hal.console->printf("RCOutput: failed to open /dev/px4fmu"); return; } +} + + +void PX4RCOutput::_init_alt_channels(void) +{ + if (_alt_fd == -1) { + return; + } if (ioctl(_alt_fd, PWM_SERVO_ARM, 0) != 0) { hal.console->printf("RCOutput: Unable to setup alt IO arming\n"); + return; } -#ifdef PWM_SERVO_SET_ARM_OK if (ioctl(_alt_fd, PWM_SERVO_SET_ARM_OK, 0) != 0) { hal.console->printf("RCOutput: Unable to setup alt IO arming OK\n"); + return; } -#endif if (ioctl(_alt_fd, PWM_SERVO_GET_COUNT, (unsigned long)&_alt_servo_count) != 0) { hal.console->printf("RCOutput: Unable to get servo count\n"); - return; } } @@ -122,7 +122,7 @@ void PX4RCOutput::set_freq(uint32_t chmask, uint16_t freq_hz) uint16_t PX4RCOutput::get_freq(uint8_t ch) { - if (_rate_mask & (1<<ch)) { + if (_rate_mask & (1U<<ch)) { return _freq_hz; } return 50; @@ -130,12 +130,18 @@ uint16_t PX4RCOutput::get_freq(uint8_t ch) void PX4RCOutput::enable_ch(uint8_t ch) { - // channels are always enabled ... + if (ch >= 8 && !(_enabled_channels & (1U<<ch))) { + // this is the first enable of an auxillary channel - setup + // aux channels now. This delayed setup makes it possible to + // use BRD_PWM_COUNT to setup the number of PWM channels. + _init_alt_channels(); + } + _enabled_channels |= (1U<<ch); } void PX4RCOutput::disable_ch(uint8_t ch) { - // channels are always enabled ... + _enabled_channels &= ~(1U<<ch); } void PX4RCOutput::set_safety_pwm(uint32_t chmask, uint16_t period_us) @@ -159,6 +165,10 @@ void PX4RCOutput::write(uint8_t ch, uint16_t period_us) if (ch >= _servo_count + _alt_servo_count) { return; } + if (!(_enabled_channels & (1U<<ch))) { + // not enabled + return; + } if (ch >= _max_channel) { _max_channel = ch + 1; } diff --git a/libraries/AP_HAL_PX4/RCOutput.h b/libraries/AP_HAL_PX4/RCOutput.h index 33cadd06fb71583d031496f502c6685e82bab291..a1027017ebe12598a1e038fb8f1cc0fcb453c3b9 100644 --- a/libraries/AP_HAL_PX4/RCOutput.h +++ b/libraries/AP_HAL_PX4/RCOutput.h @@ -35,6 +35,9 @@ private: unsigned _servo_count; unsigned _alt_servo_count; uint32_t _rate_mask; + uint16_t _enabled_channels; + + void _init_alt_channels(void); }; #endif // __AP_HAL_PX4_RCOUTPUT_H__