From 5e8fed9d43f35b6d4d4588007a41a8bc0363177f Mon Sep 17 00:00:00 2001 From: Clyde McQueen Date: Mon, 25 Sep 2023 17:50:42 -0700 Subject: [PATCH] Sub: provide script access to joystick buttons --- ArduSub/Sub.cpp | 6 +++++ ArduSub/Sub.h | 19 ++++++++++++++++ ArduSub/joystick.cpp | 42 ++++++++++++++++++++++++++++++++++ ArduSub/script_button.cpp | 47 +++++++++++++++++++++++++++++++++++++++ ArduSub/script_button.h | 34 ++++++++++++++++++++++++++++ 5 files changed, 148 insertions(+) create mode 100644 ArduSub/script_button.cpp create mode 100644 ArduSub/script_button.h diff --git a/ArduSub/Sub.cpp b/ArduSub/Sub.cpp index 4275ddb710..2a90c7f3a6 100644 --- a/ArduSub/Sub.cpp +++ b/ArduSub/Sub.cpp @@ -43,7 +43,13 @@ Sub::Sub() #if CONFIG_HAL_BOARD != HAL_BOARD_SITL failsafe.pilot_input = true; #endif + if (_singleton != nullptr) { + AP_HAL::panic("Can only be one Sub"); + } + _singleton = this; } +Sub *Sub::_singleton = nullptr; + Sub sub; AP_Vehicle& vehicle = sub; diff --git a/ArduSub/Sub.h b/ArduSub/Sub.h index 72f6193542..351949b33a 100644 --- a/ArduSub/Sub.h +++ b/ArduSub/Sub.h @@ -72,6 +72,7 @@ #include "AP_Arming_Sub.h" #include "GCS_Sub.h" #include "mode.h" +#include "script_button.h" #include // Optical Flow library @@ -580,8 +581,26 @@ private: AutoSubMode auto_mode; // controls which auto controller is run GuidedSubMode guided_mode; +#if AP_SCRIPTING_ENABLED + ScriptButton script_buttons[4]; +#endif // AP_SCRIPTING_ENABLED + public: void mainloop_failsafe_check(); + + static Sub *_singleton; + + static Sub *get_singleton() { + return _singleton; + } + +#if AP_SCRIPTING_ENABLED + // For Lua scripting, so index is 1..4, not 0..3 + bool is_button_pressed(uint8_t index); + + // For Lua scripting, so index is 1..4, not 0..3 + uint8_t get_and_clear_button_count(uint8_t index); +#endif // AP_SCRIPTING_ENABLED }; extern const AP_HAL::HAL& hal; diff --git a/ArduSub/joystick.cpp b/ArduSub/joystick.cpp index 5f0f83fe9d..f10d7d3a45 100644 --- a/ArduSub/joystick.cpp +++ b/ArduSub/joystick.cpp @@ -593,6 +593,21 @@ void Sub::handle_jsbutton_press(uint8_t _button, bool shift, bool held) case JSButton::button_function_t::k_custom_6: // Not implemented break; + +#if AP_SCRIPTING_ENABLED + case JSButton::button_function_t::k_script_1: + sub.script_buttons[0].press(); + break; + case JSButton::button_function_t::k_script_2: + sub.script_buttons[1].press(); + break; + case JSButton::button_function_t::k_script_3: + sub.script_buttons[2].press(); + break; + case JSButton::button_function_t::k_script_4: + sub.script_buttons[3].press(); + break; +#endif // AP_SCRIPTING_ENABLED } } @@ -637,6 +652,21 @@ void Sub::handle_jsbutton_release(uint8_t _button, bool shift) { } break; #endif + +#if AP_SCRIPTING_ENABLED + case JSButton::button_function_t::k_script_1: + sub.script_buttons[0].release(); + break; + case JSButton::button_function_t::k_script_2: + sub.script_buttons[1].release(); + break; + case JSButton::button_function_t::k_script_3: + sub.script_buttons[2].release(); + break; + case JSButton::button_function_t::k_script_4: + sub.script_buttons[3].release(); + break; +#endif // AP_SCRIPTING_ENABLED } } @@ -730,3 +760,15 @@ void Sub::clear_input_hold() zTrim = 0; input_hold_engaged = false; } + +#if AP_SCRIPTING_ENABLED +bool Sub::is_button_pressed(uint8_t index) +{ + return script_buttons[index - 1].is_pressed(); +} + +uint8_t Sub::get_and_clear_button_count(uint8_t index) +{ + return script_buttons[index - 1].get_and_clear_count(); +} +#endif // AP_SCRIPTING_ENABLED diff --git a/ArduSub/script_button.cpp b/ArduSub/script_button.cpp new file mode 100644 index 0000000000..fa8f850796 --- /dev/null +++ b/ArduSub/script_button.cpp @@ -0,0 +1,47 @@ +#include "AP_Scripting/AP_Scripting_config.h" + +#if AP_SCRIPTING_ENABLED + +#include +#include "script_button.h" + +void ScriptButton::press() +{ + if (!pressed) { + pressed = true; + + // The count will max out at 255, but it won't roll over to 0. + if (count < std::numeric_limits::max()) { + count++; + } + } +} + +void ScriptButton::release() +{ + pressed = false; +} + +bool ScriptButton::is_pressed() const +{ + return pressed; +} + +uint8_t ScriptButton::get_count() const +{ + return count; +} + +void ScriptButton::clear_count() +{ + count = 0; +} + +uint8_t ScriptButton::get_and_clear_count() +{ + auto result = get_count(); + clear_count(); + return result; +} + +#endif // AP_SCRIPTING_ENABLED diff --git a/ArduSub/script_button.h b/ArduSub/script_button.h new file mode 100644 index 0000000000..31a08a2400 --- /dev/null +++ b/ArduSub/script_button.h @@ -0,0 +1,34 @@ +#pragma once + +#if AP_SCRIPTING_ENABLED + +#include + +// Joystick button object for use in Lua scripts. +// +// Provide 2 ways to use a joystick button: +// is_pressed() returns true if the button is currently (as of the most recent MANUAL_CONTROL msg) pressed +// get_and_clear_count() returns the number of times the button was pressed since the last call +// +class ScriptButton { +public: + ScriptButton(): pressed(false), count(0) {} + + void press(); + + void release(); + + bool is_pressed() const WARN_IF_UNUSED; + + uint8_t get_count() const WARN_IF_UNUSED; + + void clear_count(); + + uint8_t get_and_clear_count(); + +private: + bool pressed; + uint8_t count; +}; + +#endif // AP_SCRIPTING_ENABLED