AP_Button: allow PWM to be used for button input

This commit is contained in:
Peter Barker 2020-10-01 14:13:47 +10:00 committed by Andrew Tridgell
parent 7ea78791c2
commit 164bd95538
2 changed files with 89 additions and 4 deletions

View File

@ -69,6 +69,34 @@ const AP_Param::GroupInfo AP_Button::var_info[] = {
// @Range: 0 3600
AP_GROUPINFO("REPORT_SEND", 5, AP_Button, report_send_time, 10),
// @Param: OPTIONS1
// @DisplayName: Button Pin 1 Options
// @Description: Options for Pin 1
// @User: Standard
// @Bitmask: 0:PWM Input,1:InvertInput
AP_GROUPINFO("OPTIONS1", 6, AP_Button, options[0], 0),
// @Param: OPTIONS2
// @DisplayName: Button Pin 2 Options
// @Description: Options for Pin 2
// @User: Standard
// @Bitmask: 0:PWM Input,1:InvertInput
AP_GROUPINFO("OPTIONS2", 7, AP_Button, options[1], 0),
// @Param: OPTIONS3
// @DisplayName: Button Pin 3 Options
// @Description: Options for Pin 3
// @User: Standard
// @Bitmask: 0:PWM Input,1:InvertInput
AP_GROUPINFO("OPTIONS3", 8, AP_Button, options[2], 0),
// @Param: OPTIONS4
// @DisplayName: Button Pin 4 Options
// @Description: Options for Pin 4
// @User: Standard
// @Bitmask: 0:PWM Input,1:InvertInput
AP_GROUPINFO("OPTIONS4", 9, AP_Button, options[3], 0),
AP_GROUPEND
};
@ -107,6 +135,31 @@ void AP_Button::update(void)
hal.scheduler->register_timer_process(FUNCTOR_BIND_MEMBER(&AP_Button::timer_update, void));
}
// act on any changes in state
{
WITH_SEMAPHORE(last_debounced_change_ms_sem);
if (last_debounced_change_ms > last_debounce_ms) {
last_debounce_ms = last_debounced_change_ms;
}
}
// update the PWM state:
uint8_t new_pwm_state = 0;
for (uint8_t i=0; i<AP_BUTTON_NUM_PINS; i++) {
if (!is_pwm_input(i)) {
// not a PWM input
continue;
}
const uint16_t pwm_us = pwm_pin_source[i].get_pwm_us();
// these values are the same as used in RC_Channel:
new_pwm_state |= pwm_us > 1800 && pwm_us < 2200;
}
if (new_pwm_state != pwm_state) {
pwm_state = new_pwm_state;
last_debounced_change_ms = AP_HAL::millis64();
}
// act on any changes in state
if (last_change_time_ms != 0 &&
(AP_HAL::millis() - last_report_ms) > AP_BUTTON_REPORT_PERIOD_MS &&
(AP_HAL::millis64() - last_change_time_ms) < report_send_time*1000ULL) {
@ -126,7 +179,11 @@ bool AP_Button::get_button_state(uint8_t number)
if (number == 0 || number > AP_BUTTON_NUM_PINS) {
return false;
}
if (is_pwm_input(number-1)) {
return (pwm_state & (1U<<(number-1)));
}
return ( ((1 << (number - 1)) & debounce_mask) != 0);
};
@ -140,8 +197,12 @@ uint8_t AP_Button::get_mask(void)
if (pin[i] == -1) {
continue;
}
if (is_pwm_input(i)) {
continue;
}
mask |= hal.gpio->read(pin[i]) << i;
}
return mask;
}
@ -159,9 +220,11 @@ void AP_Button::timer_update(void)
last_mask = mask;
last_change_time_ms = now;
}
if ((now - last_change_time_ms) > DEBOUNCE_MS) {
if (debounce_mask != last_mask &&
(now - last_change_time_ms) > DEBOUNCE_MS) {
// crude de-bouncing, debounces all buttons as one, not individually
debounce_mask = last_mask;
last_debounced_change_ms = now;
}
}
@ -170,10 +233,11 @@ void AP_Button::timer_update(void)
*/
void AP_Button::send_report(void)
{
const uint8_t mask = last_mask | pwm_state;
const mavlink_button_change_t packet{
time_boot_ms: AP_HAL::millis(),
last_change_ms: uint32_t(last_change_time_ms),
state: last_mask
last_change_ms: uint32_t(last_debounce_ms),
state: mask,
};
gcs().send_to_active_channels(MAVLINK_MSG_ID_BUTTON_CHANGE,
(const char *)&packet);
@ -186,9 +250,14 @@ void AP_Button::send_report(void)
void AP_Button::setup_pins(void)
{
for (uint8_t i=0; i<AP_BUTTON_NUM_PINS; i++) {
if (is_pwm_input(i)) {
pwm_pin_source[i].set_pin(pin[i], "Button");
continue;
}
if (pin[i] == -1) {
continue;
}
hal.gpio->pinMode(pin[i], HAL_GPIO_INPUT);
// setup pullup
hal.gpio->write(pin[i], 1);

View File

@ -51,6 +51,11 @@ private:
AP_Int8 enable;
AP_Int8 pin[AP_BUTTON_NUM_PINS];
AP_Int8 options[AP_BUTTON_NUM_PINS]; // if a pin's bit is set then it uses PWM assertion
bool is_pwm_input(uint8_t n) const {
return ((uint8_t)options[n].get() & (1U<<0)) != 0;
}
// number of seconds to send change notifications
AP_Int16 report_send_time;
@ -61,6 +66,17 @@ private:
// debounced button press mask
uint8_t debounce_mask;
// current state of PWM pins:
uint8_t pwm_state;
// mask indicating which action was most recent taken for pins
uint8_t state_actioned_mask;
// pwm sources are used when using PWM on the input
AP_HAL::PWMSource pwm_pin_source[AP_BUTTON_NUM_PINS];
uint64_t last_debounced_change_ms;
// when the mask last changed
uint64_t last_change_time_ms;