diff --git a/libraries/AP_Notify/AP_Notify.cpp b/libraries/AP_Notify/AP_Notify.cpp index bf3b7b1024510..1a1b6d2158276 100644 --- a/libraries/AP_Notify/AP_Notify.cpp +++ b/libraries/AP_Notify/AP_Notify.cpp @@ -535,6 +535,27 @@ void AP_Notify::send_text(const char *str) _send_text_updated_millis = AP_HAL::millis(); } +#if AP_SCRIPTING_ENABLED +void AP_Notify::send_text_scripting(const char *str, uint8_t r) +{ + for (uint8_t i = 0; i < _num_devices; i++) { + if (_devices[i] != nullptr) { + _devices[i]->send_text_blocking(str, r); + } + } +} + +void AP_Notify::release_text_scripting(uint8_t r) +{ + for (uint8_t i = 0; i < _num_devices; i++) { + if (_devices[i] != nullptr) { + _devices[i]->release_text(r); + } + } +} +#endif + + // convert 0-3 to 0-100 int8_t AP_Notify::get_rgb_led_brightness_percent() const { diff --git a/libraries/AP_Notify/AP_Notify.h b/libraries/AP_Notify/AP_Notify.h index 0db8c825bb8ce..b71988bdf1309 100644 --- a/libraries/AP_Notify/AP_Notify.h +++ b/libraries/AP_Notify/AP_Notify.h @@ -210,6 +210,12 @@ class AP_Notify void send_text(const char *str); const char* get_text() const { return _send_text; } uint32_t get_text_updated_millis() const {return _send_text_updated_millis; } + +#if AP_SCRIPTING_ENABLED + // send text to the display using scripting + void send_text_scripting(const char *str, uint8_t r); + void release_text_scripting(uint8_t r); +#endif static const struct AP_Param::GroupInfo var_info[]; int8_t get_buzz_pin() const { return _buzzer_pin; } diff --git a/libraries/AP_Notify/Display.cpp b/libraries/AP_Notify/Display.cpp index 35ecbdb315b67..a17b72637996e 100644 --- a/libraries/AP_Notify/Display.cpp +++ b/libraries/AP_Notify/Display.cpp @@ -404,17 +404,53 @@ void Display::update() void Display::update_all() { - update_text(0); - update_mode(1); + if(!BIT_IS_SET(_send_text_scr_override, 0)) { + update_text(0); + } + + if(!BIT_IS_SET(_send_text_scr_override, 1)) { + update_mode(1); + } + #if AP_BATTERY_ENABLED - update_battery(2); + if(!BIT_IS_SET(_send_text_scr_override, 2)) { + update_battery(2); + } #endif #if AP_GPS_ENABLED - update_gps(3); + if(!BIT_IS_SET(_send_text_scr_override, 3)) { + update_gps(3); + } #endif - //update_gps_sats(4); - update_prearm(4); - update_ekf(5); + + if(!BIT_IS_SET(_send_text_scr_override, 4)) { + //update_gps_sats(4); + update_prearm(4); + } + + if(!BIT_IS_SET(_send_text_scr_override, 5)) { + update_ekf(5); + } +} + +void Display::send_text_blocking(const char *text, uint8_t r) +{ + if (text == nullptr) { + return; + } + if (r >= DISPLAY_TEXT_NUM_ROWS) { + return; + } + BIT_SET(_send_text_scr_override, r); + char txt [DISPLAY_MESSAGE_SIZE] = {}; + memset(txt, ' ', DISPLAY_MESSAGE_SIZE); + memcpy(txt, text, strnlen(text, DISPLAY_MESSAGE_SIZE)); + draw_text(COLUMN(0), ROW(r), txt); +} + +void Display::release_text(uint8_t r) +{ + BIT_CLEAR(_send_text_scr_override, r); } void Display::draw_text(uint16_t x, uint16_t y, const char* c) diff --git a/libraries/AP_Notify/Display.h b/libraries/AP_Notify/Display.h index 5c0fbb3e857b5..6243a3696e6a0 100644 --- a/libraries/AP_Notify/Display.h +++ b/libraries/AP_Notify/Display.h @@ -9,6 +9,7 @@ #define ROW(Y) ((Y * 10) + 6) #define COLUMN(X) ((X * 7) + 0) +#define DISPLAY_TEXT_NUM_ROWS 6 #define DISPLAY_MESSAGE_SIZE 19 class Display_Backend; @@ -19,7 +20,8 @@ class Display: public NotifyDevice { bool init(void) override; void update() override; - + void send_text_blocking(const char *text, uint8_t line) override; + void release_text(uint8_t line) override; private: void draw_char(uint16_t x, uint16_t y, const char c); void draw_text(uint16_t x, uint16_t y, const char *c); @@ -42,6 +44,9 @@ class Display: public NotifyDevice { // stop showing text in display after this many millis: const uint16_t _send_text_valid_millis = 20000; + + //Bitmask of what lines send_text_scripting should override + uint8_t _send_text_scr_override; }; #endif // HAL_DISPLAY_ENABLED diff --git a/libraries/AP_Notify/NotifyDevice.h b/libraries/AP_Notify/NotifyDevice.h index 2f2f76ca92a30..f5f6d89d804bb 100644 --- a/libraries/AP_Notify/NotifyDevice.h +++ b/libraries/AP_Notify/NotifyDevice.h @@ -30,6 +30,10 @@ class NotifyDevice { // give RGB value for single led virtual void rgb_set_id(uint8_t r, uint8_t g, uint8_t b, uint8_t id) {} + // Allow text to be sent or removed from a display + virtual void send_text_blocking(const char *text, uint8_t line) {} + virtual void release_text(uint8_t line) {} + // this pointer is used to read the parameters relative to devices const AP_Notify *pNotify; }; diff --git a/libraries/AP_Scripting/docs/docs.lua b/libraries/AP_Scripting/docs/docs.lua index 0d4ac3d3a7d1d..f9da400326e47 100644 --- a/libraries/AP_Scripting/docs/docs.lua +++ b/libraries/AP_Scripting/docs/docs.lua @@ -2765,6 +2765,14 @@ function notify:handle_rgb(red, green, blue, rate_hz) end ---@param tune string function notify:play_tune(tune) end +-- Display text on a notify display, text too long to fit will automatically be scrolled. +---@param text string -- upto 50 characters +---@param row integer -- row number to display on, 0 is at the top. +function notify:send_text(text, row) end + +-- desc +---@param row integer +function notify:release_text(row) end -- desc ---@class gps diff --git a/libraries/AP_Scripting/examples/hello_world_display.lua b/libraries/AP_Scripting/examples/hello_world_display.lua new file mode 100644 index 0000000000000..cf356da625263 --- /dev/null +++ b/libraries/AP_Scripting/examples/hello_world_display.lua @@ -0,0 +1,66 @@ +-- This script is an example of printing to a display via scripting +-- Connect a supported display to the autopilot, and configure the NTF_DISPLAY_TYPE parameter seen at https://ardupilot.org/copter/docs/common-display-onboard.html +-- The notify:send_text(text, row) method will override default on the display, disabling the default messages + +local switchTimeA +local switchTimeB +local displayWidth = 18 +local function update() + -- Just keep track of when we should switch to a smiley :) + if switchTimeA == nil then + switchTimeA = millis() + 5000 + switchTimeB = switchTimeA + 10000 + end + + -- Example of overriding a line keeping some defaults, here we will replace the battery(1) and GPS(2) rows + if switchTimeA > millis() then + notify:send_text("Hello, World!", 1) + notify:send_text(tostring(millis()), 2) + + -- Next demonstrate we can release the text, and the default will be shown again + elseif switchTimeB > millis() then + notify:release_text(1) + notify:release_text(2) + + -- Example of overriding all lines, a smiley, try moving the autopilot around to see it change + else + -- Generate the smiley + local width = (displayWidth / 2) + local roll = math.floor(width + (ahrs:get_roll() * width)) - 4 + local pitch = math.floor(ahrs:get_pitch() * 6) + 2; + local sub = 5 - roll + if sub < 0 then + sub = 0 + end + local rows = {} + if pitch - 2 >= 0 and pitch - 2 <= 5 then + rows[pitch - 2] = (string.rep(" ", roll) .. " ##"):sub(sub); + end + if pitch - 1 >= 0 and pitch - 1 <= 5 then + rows[pitch - 1] = (string.rep(" ", roll) .. " # #"):sub(sub); + end + if pitch >= 0 and pitch <= 5 then + rows[pitch] = (string.rep(" ", roll) .. " #"):sub(sub); + end + if pitch + 1 >= 0 and pitch + 1 <= 5 then + rows[pitch + 1] = (string.rep(" ", roll) .. " # #"):sub(sub); + end + if pitch + 2 >= 0 and pitch + 2 <= 5 then + rows[pitch + 2] = (string.rep(" ", roll) .. " ##"):sub(sub); + end + if pitch + 3 >= 0 and pitch + 3 <= 5 then + rows[pitch + 3] = ""; + end + + -- Send it out to the display + for i = 0, 5 do + if rows[i] == nil then + rows[i] = "" + end + notify:send_text(rows[i], i) + end + end + + return update, 10 + end + return update, 1000 -- Wait a few seconds before starting diff --git a/libraries/AP_Scripting/generator/description/bindings.desc b/libraries/AP_Scripting/generator/description/bindings.desc index 0eee97bf20d50..3253fad840551 100644 --- a/libraries/AP_Scripting/generator/description/bindings.desc +++ b/libraries/AP_Scripting/generator/description/bindings.desc @@ -191,6 +191,10 @@ singleton AP_Notify depends (!defined(HAL_BUILD_AP_PERIPH) || defined(HAL_PERIPH singleton AP_Notify method play_tune void string singleton AP_Notify method handle_rgb void uint8_t'skip_check uint8_t'skip_check uint8_t'skip_check uint8_t'skip_check singleton AP_Notify method handle_rgb_id void uint8_t'skip_check uint8_t'skip_check uint8_t'skip_check uint8_t'skip_check +singleton AP_Notify method send_text_scripting void string uint8_t'skip_check +singleton AP_Notify method send_text_scripting rename send_text +singleton AP_Notify method release_text_scripting void uint8_t'skip_check +singleton AP_Notify method release_text_scripting rename release_text include AP_Proximity/AP_Proximity.h include AP_Proximity/AP_Proximity_Backend.h