From 56a31f20d39de2f101eb36d4d1f24e8dc22d6a14 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Sat, 8 Jun 2019 10:42:29 +0200 Subject: [PATCH] Bsongis/radio tools (#6484) Lua tools now displayed in RADIO / TOOLS Add a function to write CENTERED text with lcdDrawText --- radio/src/gui/128x64/lcd.cpp | 14 +-- radio/src/gui/128x64/lcd.h | 43 +++---- radio/src/gui/128x64/widgets.cpp | 2 +- radio/src/gui/212x64/lcd.cpp | 6 +- radio/src/gui/212x64/lcd.h | 2 +- radio/src/gui/480x272/lcd.h | 2 - radio/src/gui/common/stdlcd/radio_tools.cpp | 121 +++++++++++++++++--- radio/src/lua/api_general.cpp | 5 +- radio/src/opentx.h | 5 + radio/src/sdcard.h | 1 + 10 files changed, 144 insertions(+), 57 deletions(-) diff --git a/radio/src/gui/128x64/lcd.cpp b/radio/src/gui/128x64/lcd.cpp index 7627c4504..6cb5a16b5 100644 --- a/radio/src/gui/128x64/lcd.cpp +++ b/radio/src/gui/128x64/lcd.cpp @@ -316,15 +316,16 @@ void lcdDrawSizedText(coord_t x, coord_t y, const char * s, uint8_t len, LcdFlag width = getTextWidth(s, len, flags); x -= width; } + else if (flags & CENTERED) { + width = getTextWidth(s, len, flags); + x -= width / 2; + } #endif bool setx = false; while (len--) { unsigned char c; - switch (flags & (BSS+ZCHAR)) { - case BSS: - c = *s; - break; + switch (flags & ZCHAR) { #if !defined(BOOT) case ZCHAR: c = zchar2char(*s); @@ -419,7 +420,7 @@ void lcdDrawTextAtIndex(coord_t x, coord_t y, const char * s,uint8_t idx, LcdFla { uint8_t length; length = *(s++); - lcdDrawSizedText(x, y, s+length*idx, length, flags & ~(BSS|ZCHAR)); + lcdDrawSizedText(x, y, s+length*idx, length, flags & ~ZCHAR); } void lcdDrawHexNumber(coord_t x, coord_t y, uint32_t val, LcdFlags flags) @@ -446,7 +447,6 @@ void lcdDrawHexChar(coord_t x, coord_t y, uint8_t val, LcdFlags flags) } } - void lcdDraw8bitsNumber(coord_t x, coord_t y, int8_t val) { lcdDrawNumber(x, y, val); @@ -484,7 +484,7 @@ void lcdDrawNumber(coord_t x, coord_t y, lcdint_t val, LcdFlags flags, uint8_t l if (neg) { *--s = '-'; } - flags &= ~LEADING0; + flags &= ~(LEADING0 | PREC1 | PREC2); lcdDrawText(x, y, s, flags); } #endif diff --git a/radio/src/gui/128x64/lcd.h b/radio/src/gui/128x64/lcd.h index 9450a78d2..e94fc8270 100644 --- a/radio/src/gui/128x64/lcd.h +++ b/radio/src/gui/128x64/lcd.h @@ -41,33 +41,29 @@ #define BITMAP_BUFFER_SIZE(w, h) (2 + (w) * (((h)+7)/8)) -/* lcd common flags */ +/* lcdDrawText flags */ #define BLINK 0x01 - -/* lcd text flags */ #define INVERS 0x02 #if defined(BOLD_FONT) #define BOLD 0x40 #else #define BOLD 0x00 #endif - -/* lcd putc flags */ +#define LEFT 0x00 /* fake */ +#define RIGHT 0x04 /* align right */ +#define CENTERED 0x20 #define CONDENSED 0x08 #define FIXEDWIDTH 0x10 -/* lcd puts flags */ /* no 0x80 here because of "GV"1 which is aligned LEFT */ /* no 0x10 here because of "MODEL"01 which uses LEADING0 */ - #define BSS 0x00 #define ZCHAR 0x80 -/* lcd outdez flags */ +/* lcdDrawNumber additional flags */ #define LEADING0 0x10 #define PREC1 0x20 #define PREC2 0x30 #define MODE(flags) ((((int8_t)(flags) & 0x30) - 0x10) >> 4) -#define LEFT 0x00 /* fake */ -#define RIGHT 0x04 /* align right */ + #define IS_LEFT_ALIGNED(att) !((att) & RIGHT) #define IS_RIGHT_ALIGNED(att) (!IS_LEFT_ALIGNED(att)) @@ -79,27 +75,26 @@ /* telemetry flags */ #define NO_UNIT 0x40 - #define FONTSIZE_MASK 0x0700 - #define FONTSIZE(x) ((x) & FONTSIZE_MASK) - #define TINSIZE 0x0100 - #define SMLSIZE 0x0200 - #define MIDSIZE 0x0300 - #define DBLSIZE 0x0400 - #define XXLSIZE 0x0500 - #define ERASEBG 0x8000 - #define VERTICAL 0x0800 +#define FONTSIZE_MASK 0x0700 +#define FONTSIZE(x) ((x) & FONTSIZE_MASK) +#define TINSIZE 0x0100 +#define SMLSIZE 0x0200 +#define MIDSIZE 0x0300 +#define DBLSIZE 0x0400 +#define XXLSIZE 0x0500 +#define ERASEBG 0x8000 +#define VERTICAL 0x0800 - #define TIMEBLINK 0x1000 - #define TIMEHOUR 0x2000 - #define STREXPANDED 0x4000 +#define TIMEBLINK 0x1000 +#define TIMEHOUR 0x2000 +#define STREXPANDED 0x4000 - typedef uint32_t LcdFlags; +typedef uint32_t LcdFlags; #define display_t uint8_t #define DISPLAY_BUFFER_SIZE (LCD_W*((LCD_H+7)/8)) extern display_t displayBuf[DISPLAY_BUFFER_SIZE]; - extern coord_t lcdLastRightPos; extern coord_t lcdLastLeftPos; extern coord_t lcdNextPos; diff --git a/radio/src/gui/128x64/widgets.cpp b/radio/src/gui/128x64/widgets.cpp index 5cbab62aa..8aeef5c8b 100644 --- a/radio/src/gui/128x64/widgets.cpp +++ b/radio/src/gui/128x64/widgets.cpp @@ -230,7 +230,7 @@ void drawStatusLine() } lcdDrawFilledRect(0, LCD_H-statusLineHeight, LCD_W, FH, SOLID, ERASE); - lcdDrawText(5, LCD_H+1-statusLineHeight, statusLineMsg, BSS); + lcdDrawText(5, LCD_H+1-statusLineHeight, statusLineMsg); lcdDrawFilledRect(0, LCD_H-statusLineHeight, LCD_W, FH, SOLID); } } diff --git a/radio/src/gui/212x64/lcd.cpp b/radio/src/gui/212x64/lcd.cpp index 23177fa7f..9aa14fe35 100644 --- a/radio/src/gui/212x64/lcd.cpp +++ b/radio/src/gui/212x64/lcd.cpp @@ -268,6 +268,10 @@ void lcdDrawSizedText(coord_t x, coord_t y, const char * s, uint8_t len, LcdFlag width = getTextWidth(s, len, flags); x -= width; } + else if (flags & CENTERED) { + width = getTextWidth(s, len, flags); + x -= width / 2; + } #endif while (len--) { @@ -417,7 +421,7 @@ void lcdDrawNumber(coord_t x, coord_t y, int32_t val, LcdFlags flags, uint8_t le if (neg) { *--s = '-'; } - flags &= ~LEADING0; + flags &= ~(LEADING0 | PREC1 | PREC2); lcdDrawText(x, y, s, flags); } #endif diff --git a/radio/src/gui/212x64/lcd.h b/radio/src/gui/212x64/lcd.h index 1289a32d8..cb8ce9476 100644 --- a/radio/src/gui/212x64/lcd.h +++ b/radio/src/gui/212x64/lcd.h @@ -21,7 +21,6 @@ #ifndef _LCD_H_ #define _LCD_H_ - #define BOX_WIDTH 31 #define coord_t int #define scoord_t int @@ -45,6 +44,7 @@ #define BOLD 0x04 #define LEFT 0x00 #define RIGHT 0x08 +#define CENTERED 0x20 #define FIXEDWIDTH 0x10 /* no 0x80 here because of "GV"1 which is aligned LEFT */ /* no 0x10 here because of "MODEL"01 which uses LEADING0 */ diff --git a/radio/src/gui/480x272/lcd.h b/radio/src/gui/480x272/lcd.h index c541875c3..e5529ac3c 100644 --- a/radio/src/gui/480x272/lcd.h +++ b/radio/src/gui/480x272/lcd.h @@ -34,8 +34,6 @@ #define lcdint_t int32_t -#define BSS 0x00 - /* lcd common flags */ #define BLINK 0x01 diff --git a/radio/src/gui/common/stdlcd/radio_tools.cpp b/radio/src/gui/common/stdlcd/radio_tools.cpp index b1847ed2f..d7baa272d 100644 --- a/radio/src/gui/common/stdlcd/radio_tools.cpp +++ b/radio/src/gui/common/stdlcd/radio_tools.cpp @@ -18,11 +18,12 @@ * GNU General Public License for more details. */ +#include #include "opentx.h" extern uint8_t g_moduleIdx; -void addRadioTool(uint8_t index, const char * label, void (* tool)(event_t), uint8_t module) +bool addRadioTool(uint8_t index, const char * label) { int8_t sub = menuVerticalPosition - HEADER_LINE; LcdFlags attr = (sub == index ? INVERS : 0); @@ -31,54 +32,136 @@ void addRadioTool(uint8_t index, const char * label, void (* tool)(event_t), uin lcdDrawText(3*FW, y, label, (sub == index ? INVERS : 0)); if (attr && s_editMode > 0) { s_editMode = 0; + return true; + } + return false; +} + +void addRadioModuleTool(uint8_t index, const char * label, void (* tool)(event_t), uint8_t module) +{ + if (addRadioTool(index, label)) { g_moduleIdx = module; pushMenu(tool); } } +#define TOOL_NAME_MAXLEN 16 + +bool readToolName(const char * filename, char * name) +{ + FIL file; + char buffer[1024]; + UINT count; + + if (f_open(&file, filename, FA_READ) != FR_OK) { + return "Error opening file"; + } + + if (f_read(&file, &buffer, sizeof(buffer), &count) != FR_OK) { + f_close(&file); + return false; + } + + const char * tns = "TNS|"; + auto * start = std::search(buffer, buffer + sizeof(buffer), tns, tns + 4); + if (start >= buffer + sizeof(buffer)) + return false; + + start += 4; + + const char * tne = "|TNE"; + auto * end = std::search(buffer, buffer + sizeof(buffer), tne, tne + 4); + if (end >= buffer + sizeof(buffer) || end <= start) + return false; + + uint8_t len = end - start; + if (len > TOOL_NAME_MAXLEN) + return false; + + strncpy(name, start, len); + memclear(name + len, TOOL_NAME_MAXLEN + 1 - len); + + return true; +} + +void addRadioScriptTool(uint8_t index, const char * filename) +{ + TCHAR path[_MAX_LFN+1] = SCRIPTS_TOOLS_PATH "/"; + strcat(path, filename); + + char toolName[TOOL_NAME_MAXLEN + 1]; + const char * label; + if (readToolName(path, toolName)) { + label = toolName; + } + else { + char * ext = (char *)getFileExtension(filename); + *ext = '\0'; + label = filename; + } + + if (addRadioTool(index, label)) { + luaExec(path); + } +} + +bool isRadioScriptTool(const char * filename) +{ + const char * ext = getFileExtension(filename); + return ext && !strcasecmp(ext, SCRIPT_EXT); +} + void menuRadioTools(event_t event) { - uint8_t spectrum_modules = 0, power_modules = 0; - if (event == EVT_ENTRY || event == EVT_ENTRY_UP) { - memclear(&reusableBuffer.hardwareAndSettings, sizeof(reusableBuffer.hardwareAndSettings)); + memclear(&reusableBuffer.radioTools, sizeof(reusableBuffer.radioTools)); #if defined(PXX2) for (uint8_t module = 0; module < NUM_MODULES; module++) { if (isModulePXX2(module) && (module == INTERNAL_MODULE ? IS_INTERNAL_MODULE_ON() : IS_EXTERNAL_MODULE_ON())) { - moduleState[module].readModuleInformation(&reusableBuffer.hardwareAndSettings.modules[module], PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID); + moduleState[module].readModuleInformation(&reusableBuffer.radioTools.modules[module], PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID); } } #endif } - for (uint8_t module = 0; module < NUM_MODULES; module++) { - if (isModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[module].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) { - spectrum_modules++; - } - if (isModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[module].information.modelID, MODULE_OPTION_POWER_METER)) { - power_modules++; - } - } - - SIMPLE_MENU(STR_MENUTOOLS, menuTabGeneral, MENU_RADIO_TOOLS, HEADER_LINE + spectrum_modules + power_modules); + SIMPLE_MENU(STR_MENUTOOLS, menuTabGeneral, MENU_RADIO_TOOLS, HEADER_LINE + reusableBuffer.radioTools.linesCount); uint8_t index = 0; #if defined(PXX2) if (isModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) - addRadioTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE); + addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_INT, menuRadioSpectrumAnalyser, INTERNAL_MODULE); if (isModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) - addRadioTool(index++, STR_POWER_METER_INT, menuRadioPowerMeter, INTERNAL_MODULE); + addRadioModuleTool(index++, STR_POWER_METER_INT, menuRadioPowerMeter, INTERNAL_MODULE); if (isModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) - addRadioTool(index++, STR_SPECTRUM_ANALYSER_EXT, menuRadioSpectrumAnalyser, EXTERNAL_MODULE); + addRadioModuleTool(index++, STR_SPECTRUM_ANALYSER_EXT, menuRadioSpectrumAnalyser, EXTERNAL_MODULE); if (isModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER)) - addRadioTool(index++, STR_POWER_METER_EXT, menuRadioPowerMeter, EXTERNAL_MODULE); + addRadioModuleTool(index++, STR_POWER_METER_EXT, menuRadioPowerMeter, EXTERNAL_MODULE); #endif + FILINFO fno; + DIR dir; + + FRESULT res = f_opendir(&dir, SCRIPTS_TOOLS_PATH); + if (res == FR_OK) { + for (;;) { + res = f_readdir(&dir, &fno); /* Read a directory item */ + if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ + if (fno.fattrib & AM_DIR) continue; /* Skip subfolders */ + if (fno.fattrib & AM_HID) continue; /* Skip hidden files */ + if (fno.fattrib & AM_SYS) continue; /* Skip system files */ + + if (isRadioScriptTool(fno.fname)) + addRadioScriptTool(index++, fno.fname); + } + } + if (index == 0) { lcdDrawCenteredText(LCD_H/2, STR_NO_TOOLS); } + + reusableBuffer.radioTools.linesCount = index; } \ No newline at end of file diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 64610142c..a716f834e 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -1418,7 +1418,7 @@ const luaL_Reg opentxLib[] = { { "crossfireTelemetryPush", luaCrossfireTelemetryPush }, #endif { "serialWrite", luaSerialWrite }, - { NULL, NULL } /* sentinel */ + { nullptr, nullptr } /* sentinel */ }; const luaR_value_entry opentxConstants[] = { @@ -1432,6 +1432,7 @@ const luaR_value_entry opentxConstants[] = { { "BLINK", BLINK }, { "RIGHT", RIGHT }, { "LEFT", LEFT }, + { "CENTER", CENTERED }, { "PREC1", PREC1 }, { "PREC2", PREC2 }, { "VALUE", INPUT_TYPE_VALUE }, @@ -1622,5 +1623,5 @@ const luaR_value_entry opentxConstants[] = { {"UNIT_BITFIELD", UNIT_BITFIELD}, {"UNIT_TEXT", UNIT_TEXT}, #endif - { NULL, 0 } /* sentinel */ + { nullptr, 0 } /* sentinel */ }; diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 595fa57dd..2b15c68a1 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -1188,6 +1188,11 @@ union ReusableBuffer } hardwareAndSettings; + struct { + ModuleInformation modules[NUM_MODULES]; + uint8_t linesCount; + } radioTools; + struct { uint8_t stickMode; } generalSettings; diff --git a/radio/src/sdcard.h b/radio/src/sdcard.h index e4c71a534..5f39d936a 100644 --- a/radio/src/sdcard.h +++ b/radio/src/sdcard.h @@ -47,6 +47,7 @@ #define SCRIPTS_MIXES_PATH SCRIPTS_PATH "/MIXES" #define SCRIPTS_FUNCS_PATH SCRIPTS_PATH "/FUNCTIONS" #define SCRIPTS_TELEM_PATH SCRIPTS_PATH "/TELEMETRY" +#define SCRIPTS_TOOLS_PATH SCRIPTS_PATH "/TOOLS" #define LEN_FILE_PATH_MAX (sizeof(SCRIPTS_TELEM_PATH)+1) // longest + "/"