From a09e318e645148be9686290b54f0c34dd4c8e11c Mon Sep 17 00:00:00 2001 From: Jesper Frickmann Date: Sun, 28 Nov 2021 20:48:01 -0500 Subject: [PATCH] [Lua] Add setStickySwitch and getLogicalSwitchValue (#1056) [Lua] Add setStickySwitch and getLogicalSwitchValue (#1056) * Adds setStickySwitch to set the value of a stick logical switch * Adds getLogicalSwitchValue to get the value of a logical switch by index --- radio/src/lua/api_general.cpp | 58 +++++++++++++++++++++++++++++++++++ radio/src/opentx.h | 2 ++ radio/src/opentx_helpers.h | 42 +++++++++++++++++++++++-- radio/src/switches.cpp | 31 +++++++++++++++++++ 4 files changed, 130 insertions(+), 3 deletions(-) diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 08cdf3d26..9b3ca0ccc 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -1848,6 +1848,62 @@ static int luaGetShmVar(lua_State * L) } #endif +/*luadoc +@function setStickySwitch(id, value) + +@param id: integer identifying the sticky logical switch (zero for LS1 etc.). + +@param value: true/false. The new value of the sticky logical switch. + +@retval bufferFull: true/false. This function sends a message from Lua to the logical switch processor +via a buffer with eight slots that are read 10 times per second. If the buffer is full, then a true value +is returned and no messages was sent (i.e. the switch was not changed). + +Sets the value of a sticky logical switch. + +@status current Introduced in 2.6 +*/ + +#if (MAX_LOGICAL_SWITCHES != 64) +#warning "The following code assumes that MAX_LOGICAL_SWITCHES == 64!" +#endif + +static int luaSetStickySwitch(lua_State * L) +{ + int id = luaL_checkinteger(L, 1); + bool value = lua_toboolean(L, 2); + + uint8_t msg = (1 << 6); // This bit is always set to have a non-zero value + if (value) msg |= (1 << 7); + msg |= (id & 0x3F); + + lua_pushboolean(L, luaSetStickySwitchBuffer.write(msg)); + return 1; +} + +/*luadoc +@function getLogicalSwitchValue(id) + +@param id: integer identifying the logical switch (zero for LS1 etc.). + +@retval value: true/false. + +Reads the value of a logical switch. + +@status current Introduced in 2.6 +*/ + +static int luaGetLogicalSwitchValue(lua_State * L) +{ + int id = luaL_checkinteger(L, 1); + + if (id >= 0 && id < MAX_LOGICAL_SWITCHES) + lua_pushboolean(L, getSwitch(SWSRC_FIRST_LOGICAL_SWITCH + id)); + else + lua_pushnil(L); + return 1; +} + const luaL_Reg opentxLib[] = { { "getTime", luaGetTime }, { "getDateTime", luaGetDateTime }, @@ -1907,6 +1963,8 @@ const luaL_Reg opentxLib[] = { { "setShmVar", luaSetShmVar }, { "getShmVar", luaGetShmVar }, #endif + { "setStickySwitch", luaSetStickySwitch }, + { "getLogicalSwitchValue", luaGetLogicalSwitchValue }, { nullptr, nullptr } /* sentinel */ }; diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 5fc09b7ab..3826734ae 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -1310,3 +1310,5 @@ inline bool isAsteriskDisplayed() } #include "module.h" + +extern CircularBuffer luaSetStickySwitchBuffer; diff --git a/radio/src/opentx_helpers.h b/radio/src/opentx_helpers.h index 300d71e38..5f1bfd291 100644 --- a/radio/src/opentx_helpers.h +++ b/radio/src/opentx_helpers.h @@ -56,13 +56,49 @@ inline void SWAP(T & a, T & b) inline void memclear(void * p, size_t size) { -memset(p, 0, size); + memset(p, 0, size); } inline bool is_memclear(void * p, size_t size) { -uint8_t * buf = (uint8_t *)p; -return buf[0] == 0 && memcmp(buf, buf + 1, size - 1) == 0; + uint8_t * buf = (uint8_t *)p; + return buf[0] == 0 && memcmp(buf, buf + 1, size - 1) == 0; } +// Circular buffer to send data between two threads +template +class CircularBuffer { + protected: + volatile T buffer[N] = {0}; + uint8_t readPos = 0; + uint8_t writePos = 0; + + public: + void clear() + { + memclear(this, sizeof(*this)); + } + + T read() + { + T value = buffer[readPos]; + if (value) { + buffer[readPos] = 0; + readPos = (readPos + 1) % N; + } + return value; + } + + // Values must be non-zero + bool write(T value) + { + if (value && !buffer[writePos]) { + buffer[writePos] = value; + writePos = (writePos + 1) % N; + return false; + } + return true; + } +}; + #endif diff --git a/radio/src/switches.cpp b/radio/src/switches.cpp index 325f3d35a..99221d285 100644 --- a/radio/src/switches.cpp +++ b/radio/src/switches.cpp @@ -53,6 +53,7 @@ PACK(struct LogicalSwitchesFlightModeContext { LogicalSwitchContext lsw[MAX_LOGICAL_SWITCHES]; }); LogicalSwitchesFlightModeContext lswFm[MAX_FLIGHT_MODES]; +CircularBuffer luaSetStickySwitchBuffer; #define LS_LAST_VALUE(fm, idx) lswFm[fm].lsw[idx].lastValue @@ -789,6 +790,34 @@ void checkSwitches() void logicalSwitchesTimerTick() { +#if (MAX_LOGICAL_SWITCHES != 64) +#warning "The following code assumes that MAX_LOGICAL_SWITCHES == 64!" +#endif + // Read messages from Lua in the buffer and flick switches + uint8_t msg = luaSetStickySwitchBuffer.read(); + while(msg) { + uint8_t i = msg & 0x3F; + uint8_t s = msg >> 7; + LogicalSwitchData * ls = lswAddress(i); + if (ls->func == LS_FUNC_STICKY) { + for (uint8_t fm=0; fmv2); + else + now = getSwitch(ls->v1); + if (now) + lastValue.last |= 1; + else + lastValue.last &= ~1; + } + } + msg = luaSetStickySwitchBuffer.read(); + } + + // Update logical switches for (uint8_t fm=0; fm