From 9b0f34fbc0c5c343d4186c81f6916e810f23ace9 Mon Sep 17 00:00:00 2001 From: Hans Christian Olaussen <41271048+klutvott123@users.noreply.github.com> Date: Sun, 3 Nov 2019 22:20:27 +0100 Subject: [PATCH 1/5] Add ui states --- src/SCRIPTS/BF/ui.lua | 259 ++++++++++++++++++++++-------------------- 1 file changed, 134 insertions(+), 125 deletions(-) diff --git a/src/SCRIPTS/BF/ui.lua b/src/SCRIPTS/BF/ui.lua index a929be54..5a0159fb 100644 --- a/src/SCRIPTS/BF/ui.lua +++ b/src/SCRIPTS/BF/ui.lua @@ -1,10 +1,15 @@ +local uiStatus = +{ + mainMenu = 1, + pages = 2, +} + local pageStatus = { display = 2, editing = 3, saving = 4, popupMenu = 5, - mainMenu = 6, } local uiMsp = @@ -15,7 +20,8 @@ local uiMsp = local menuLine = 1 local pageCount = 1 -local currentState = pageStatus.mainMenu +local uiState = uiStatus.mainMenu +local pageState = pageStatus.display local requestTimeout = 80 -- 800ms request timeout local currentPage = 1 local currentLine = 1 @@ -26,7 +32,7 @@ local saveMaxRetries = 0 local popupMenuActive = false local lastRunTS = 0 local killEnterBreak = 0 -local stopDisplay = true +local stopDisplay = false local pageScrollY = 0 local mainMenuScrollY = 0 @@ -58,10 +64,10 @@ local function saveSettings(new) end protocol.mspWrite(Page.write, payload) saveTS = getTime() - if currentState == pageStatus.saving then + if pageState == pageStatus.saving then saveRetries = saveRetries + 1 else - currentState = pageStatus.saving + pageState = pageStatus.saving saveRetries = 0 saveMaxRetries = protocol.saveMaxRetries or 2 -- default 2 saveTimeout = protocol.saveTimeout or 150 -- default 1.5s @@ -71,7 +77,7 @@ end local function invalidatePages() Page = nil - currentState = pageStatus.display + pageState = pageStatus.display saveTS = 0 collectgarbage() end @@ -220,7 +226,7 @@ local function drawScreen() local value_options = text_options if i == currentLine then value_options = text_options + INVERS - if currentState == pageStatus.editing then + if pageState == pageStatus.editing then value_options = value_options + BLINK end end @@ -285,128 +291,22 @@ local function drawPopupMenu() end function run_ui(event) - getPageCount() local now = getTime() -- if lastRunTS old than 500ms if lastRunTS + 50 < now then invalidatePages() if isTelemetryScript then - currentState = pageStatus.display + uiState = uiStatus.pages else - currentState = pageStatus.mainMenu + uiState = uiStatus.mainMenu end end lastRunTS = now - if (currentState == pageStatus.saving) then - if (saveTS + saveTimeout < now) then - if saveRetries < saveMaxRetries then - saveSettings() - else - -- max retries reached - currentState = pageStatus.display - invalidatePages() - end - end - end - -- process send queue - mspProcessTxQ() - -- navigation - if isTelemetryScript and event == EVT_VIRTUAL_MENU_LONG then -- telemetry script - popupMenuActive = 1 - currentState = pageStatus.popupMenu - elseif (not isTelemetryScript) and event == EVT_VIRTUAL_ENTER_LONG then -- standalone - popupMenuActive = 1 - killEnterBreak = 1 - currentState = pageStatus.popupMenu - -- menu is currently displayed - elseif currentState == pageStatus.popupMenu then - if event == EVT_VIRTUAL_EXIT then - currentState = pageStatus.display - elseif event == EVT_VIRTUAL_PREV then - incPopupMenu(-1) - elseif event == EVT_VIRTUAL_NEXT then - incPopupMenu(1) - elseif event == EVT_VIRTUAL_ENTER then - if killEnterBreak == 1 then - killEnterBreak = 0 - else - currentState = pageStatus.display - popupMenuList[popupMenuActive].f() - end - end - -- normal page viewing - elseif currentState <= pageStatus.display then - if not isTelemetryScript and event == EVT_VIRTUAL_PREV_PAGE then - incPage(-1) - killEvents(event) -- X10/T16 issue: pageUp is a long press - elseif (not isTelemetryScript and event == EVT_VIRTUAL_NEXT_PAGE) or (isTelemetryScript and event == EVT_VIRTUAL_MENU) then - incPage(1) - elseif event == EVT_VIRTUAL_PREV or event == EVT_VIRTUAL_PREV_REPT then - incLine(-1) - elseif event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then - incLine(1) - elseif event == EVT_VIRTUAL_ENTER then - if Page then - local field = Page.fields[currentLine] - local idx = field.i or currentLine - if Page.values and Page.values[idx] and (field.ro ~= true) then - currentState = pageStatus.editing - end - end - elseif event == EVT_VIRTUAL_EXIT then - if isTelemetryScript then - return protocol.exitFunc(); - else - stopDisplay = true - end - end - -- editing value - elseif currentState == pageStatus.editing then - if event == EVT_VIRTUAL_EXIT or event == EVT_VIRTUAL_ENTER then - currentState = pageStatus.display - elseif event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then - incValue(1) - elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then - incValue(-1) - end - end - local nextPage = currentPage - while Page == nil do - Page = assert(loadScript(SCRIPT_HOME.."/Pages/"..PageFiles[currentPage].script))() - if Page.requiredVersion and apiVersion > 0 and Page.requiredVersion > apiVersion then - incPage(1) - if currentPage == nextPage then - lcd.clear() - lcd.drawText(radio.NoTelem[1], radio.NoTelem[2], "No Pages! API: " .. apiVersion, radio.NoTelem[4]) - return 1 - end - end - end - if not Page.values and currentState == pageStatus.display then - requestPage() - end - lcd.clear() - if TEXT_BGCOLOR then - lcd.drawFilledRectangle(0, 0, LCD_W, LCD_H, TEXT_BGCOLOR) - end - if currentState ~= pageStatus.mainMenu then - drawScreen() - end - if protocol.rssi() == 0 then - lcd.drawText(radio.NoTelem[1],radio.NoTelem[2],radio.NoTelem[3],radio.NoTelem[4]) + if isTelemetryScript then + uiState = uiStatus.pages end - if currentState == pageStatus.popupMenu then - drawPopupMenu() - elseif currentState == pageStatus.saving then - lcd.drawFilledRectangle(radio.SaveBox.x,radio.SaveBox.y,radio.SaveBox.w,radio.SaveBox.h,backgroundFill) - lcd.drawRectangle(radio.SaveBox.x,radio.SaveBox.y,radio.SaveBox.w,radio.SaveBox.h,SOLID) - if saveRetries <= 0 then - lcd.drawText(radio.SaveBox.x+radio.SaveBox.x_offset,radio.SaveBox.y+radio.SaveBox.h_offset,"Saving...",DBLSIZE + BLINK + (globalTextOptions)) - else - lcd.drawText(radio.SaveBox.x+radio.SaveBox.x_offset,radio.SaveBox.y+radio.SaveBox.h_offset,"Retrying",DBLSIZE + (globalTextOptions)) - end - end - if currentState == pageStatus.mainMenu and (not isTelemetryScript) then + if uiState == uiStatus.mainMenu then + getPageCount() if event == EVT_VIRTUAL_EXIT then return 2 elseif event == EVT_VIRTUAL_NEXT then @@ -436,19 +336,128 @@ function run_ui(event) if event == EVT_VIRTUAL_ENTER and attr == INVERS then invalidatePages() currentPage = i - currentState = pageStatus.display + pageState = pageStatus.display + uiState = uiStatus.pages end if ((i-1)*lineSpacing + yMinLim - mainMenuScrollY) >= yMinLim and ((i-1)*lineSpacing + yMinLim - mainMenuScrollY) <= yMaxLim then lcd.drawText(6, (i-1)*lineSpacing + yMinLim - mainMenuScrollY, PageFiles[i].title, attr) end end end + elseif uiState == uiStatus.pages then + if (pageState == pageStatus.saving) then + if (saveTS + saveTimeout < now) then + if saveRetries < saveMaxRetries then + saveSettings() + else + -- max retries reached + pageState = pageStatus.display + invalidatePages() + end + end + end + -- navigation + if isTelemetryScript and event == EVT_VIRTUAL_MENU_LONG then -- telemetry script + popupMenuActive = 1 + pageState = pageStatus.popupMenu + elseif (not isTelemetryScript) and event == EVT_VIRTUAL_ENTER_LONG then -- standalone + popupMenuActive = 1 + killEnterBreak = 1 + pageState = pageStatus.popupMenu + -- menu is currently displayed + elseif pageState == pageStatus.popupMenu then + if event == EVT_VIRTUAL_EXIT then + pageState = pageStatus.display + elseif event == EVT_VIRTUAL_PREV then + incPopupMenu(-1) + elseif event == EVT_VIRTUAL_NEXT then + incPopupMenu(1) + elseif event == EVT_VIRTUAL_ENTER then + if killEnterBreak == 1 then + killEnterBreak = 0 + else + pageState = pageStatus.display + popupMenuList[popupMenuActive].f() + end + end + -- normal page viewing + elseif pageState <= pageStatus.display then + if not isTelemetryScript and event == EVT_VIRTUAL_PREV_PAGE then + incPage(-1) + killEvents(event) -- X10/T16 issue: pageUp is a long press + elseif (not isTelemetryScript and event == EVT_VIRTUAL_NEXT_PAGE) or (isTelemetryScript and event == EVT_VIRTUAL_MENU) then + incPage(1) + elseif event == EVT_VIRTUAL_PREV or event == EVT_VIRTUAL_PREV_REPT then + incLine(-1) + elseif event == EVT_VIRTUAL_NEXT or event == EVT_VIRTUAL_NEXT_REPT then + incLine(1) + elseif event == EVT_VIRTUAL_ENTER then + if Page then + local field = Page.fields[currentLine] + local idx = field.i or currentLine + if Page.values and Page.values[idx] and (field.ro ~= true) then + pageState = pageStatus.editing + end + end + elseif event == EVT_VIRTUAL_EXIT then + if isTelemetryScript then + return protocol.exitFunc(); + else + stopDisplay = true + end + end + -- editing value + elseif pageState == pageStatus.editing then + if event == EVT_VIRTUAL_EXIT or event == EVT_VIRTUAL_ENTER then + pageState = pageStatus.display + elseif event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then + incValue(1) + elseif event == EVT_VIRTUAL_DEC or event == EVT_VIRTUAL_DEC_REPT then + incValue(-1) + end + end + local nextPage = currentPage + while Page == nil do + Page = assert(loadScript(SCRIPT_HOME.."/Pages/"..PageFiles[currentPage].script))() + if Page.requiredVersion and apiVersion > 0 and Page.requiredVersion > apiVersion then + incPage(1) + if currentPage == nextPage then + lcd.clear() + lcd.drawText(radio.NoTelem[1], radio.NoTelem[2], "No Pages! API: " .. apiVersion, radio.NoTelem[4]) + return 1 + end + end + end + if not Page.values and pageState == pageStatus.display then + requestPage() + end + lcd.clear() + if TEXT_BGCOLOR then + lcd.drawFilledRectangle(0, 0, LCD_W, LCD_H, TEXT_BGCOLOR) + end + drawScreen() + if pageState == pageStatus.popupMenu then + drawPopupMenu() + elseif pageState == pageStatus.saving then + lcd.drawFilledRectangle(radio.SaveBox.x,radio.SaveBox.y,radio.SaveBox.w,radio.SaveBox.h,backgroundFill) + lcd.drawRectangle(radio.SaveBox.x,radio.SaveBox.y,radio.SaveBox.w,radio.SaveBox.h,SOLID) + if saveRetries <= 0 then + lcd.drawText(radio.SaveBox.x+radio.SaveBox.x_offset,radio.SaveBox.y+radio.SaveBox.h_offset,"Saving...",DBLSIZE + BLINK + (globalTextOptions)) + else + lcd.drawText(radio.SaveBox.x+radio.SaveBox.x_offset,radio.SaveBox.y+radio.SaveBox.h_offset,"Retrying",DBLSIZE + (globalTextOptions)) + end + end + if stopDisplay and (not isTelemetryScript) then + invalidatePages() + currentLine = 1 + uiState = uiStatus.mainMenu + stopDisplay = false + end end - if stopDisplay and (not isTelemetryScript) then - currentLine = 1 - currentState = pageStatus.mainMenu - stopDisplay = false - collectgarbage() + -- process send queue + mspProcessTxQ() + if protocol.rssi() == 0 then + lcd.drawText(radio.NoTelem[1],radio.NoTelem[2],radio.NoTelem[3],radio.NoTelem[4]) end processMspReply(mspPollReply()) return 0 From 3d5b716db8e79a7444ceeb5afb9a1a758b9b776f Mon Sep 17 00:00:00 2001 From: Hans Christian Olaussen <41271048+klutvott123@users.noreply.github.com> Date: Thu, 21 Nov 2019 21:44:50 +0100 Subject: [PATCH 2/5] Add apiVersion detection for TOOLS script --- src/SCRIPTS/BF/ui.lua | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/SCRIPTS/BF/ui.lua b/src/SCRIPTS/BF/ui.lua index 5a0159fb..e39d84f2 100644 --- a/src/SCRIPTS/BF/ui.lua +++ b/src/SCRIPTS/BF/ui.lua @@ -1,7 +1,8 @@ local uiStatus = { - mainMenu = 1, + init = 1, pages = 2, + mainMenu = 3, } local pageStatus = @@ -20,7 +21,7 @@ local uiMsp = local menuLine = 1 local pageCount = 1 -local uiState = uiStatus.mainMenu +local uiState = uiStatus.init local pageState = pageStatus.display local requestTimeout = 80 -- 800ms request timeout local currentPage = 1 @@ -37,6 +38,7 @@ local pageScrollY = 0 local mainMenuScrollY = 0 local Page = nil +local background = nil local backgroundFill = TEXT_BGCOLOR or ERASE local foregroundColor = LINE_COLOR or SOLID @@ -298,14 +300,32 @@ function run_ui(event) if isTelemetryScript then uiState = uiStatus.pages else - uiState = uiStatus.mainMenu + uiState = uiStatus.init end end lastRunTS = now if isTelemetryScript then uiState = uiStatus.pages end - if uiState == uiStatus.mainMenu then + if uiState == uiStatus.init then + local yMinLim = radio.yMinLimit + lcd.clear() + drawScreenTitle("Betaflight Config", 0, 0) + lcd.drawText(6, yMinLim, "Initialising") + if apiVersion == 0 then + if not background then + background = assert(loadScript("/SCRIPTS/BF/background.lua"))() + background.init() + else + background.run_bg() + end + return 0 + else + background = nil + invalidatePages() + uiState = uiStatus.mainMenu + end + elseif uiState == uiStatus.mainMenu then getPageCount() if event == EVT_VIRTUAL_EXIT then return 2 From 401ba717b060c66572f009e5d25bd257bc1918fe Mon Sep 17 00:00:00 2001 From: Hans Christian Olaussen <41271048+klutvott123@users.noreply.github.com> Date: Thu, 21 Nov 2019 21:51:16 +0100 Subject: [PATCH 3/5] Fix main menu api/requiredVersion check --- src/SCRIPTS/BF/ui.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SCRIPTS/BF/ui.lua b/src/SCRIPTS/BF/ui.lua index e39d84f2..d756d73f 100644 --- a/src/SCRIPTS/BF/ui.lua +++ b/src/SCRIPTS/BF/ui.lua @@ -48,7 +48,7 @@ local globalTextOptions = TEXT_COLOR or 0 local function getPageCount() pageCount = 0 for i=1,#(PageFiles) do - if (not PageFiles[i].requiredVersion) or (apiVersion == 0) or (apiVersion > 0 and PageFiles[i].requiredVersion < apiVersion) then + if (not PageFiles[i].requiredVersion) or (apiVersion == 0) or (apiVersion > 0 and PageFiles[i].requiredVersion <= apiVersion) then pageCount = pageCount + 1 end end @@ -343,7 +343,7 @@ function run_ui(event) lineSpacing = 25 end for i=1, #PageFiles do - if (not PageFiles[i].requiredVersion) or (apiVersion == 0) or (apiVersion > 0 and PageFiles[i].requiredVersion < apiVersion) then + if (not PageFiles[i].requiredVersion) or (apiVersion == 0) or (apiVersion > 0 and PageFiles[i].requiredVersion <= apiVersion) then local currentLineY = (menuLine-1)*lineSpacing + yMinLim if currentLineY <= yMinLim then mainMenuScrollY = 0 From e555ab49743b95571f429e9a7cbaf97e492fb542 Mon Sep 17 00:00:00 2001 From: Hans Christian Olaussen <41271048+klutvott123@users.noreply.github.com> Date: Thu, 21 Nov 2019 21:54:45 +0100 Subject: [PATCH 4/5] Rename currentLine to currentField Because that's what it actually is. --- src/SCRIPTS/BF/ui.lua | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/SCRIPTS/BF/ui.lua b/src/SCRIPTS/BF/ui.lua index d756d73f..3671f917 100644 --- a/src/SCRIPTS/BF/ui.lua +++ b/src/SCRIPTS/BF/ui.lua @@ -25,7 +25,7 @@ local uiState = uiStatus.init local pageState = pageStatus.display local requestTimeout = 80 -- 800ms request timeout local currentPage = 1 -local currentLine = 1 +local currentField = 1 local saveTS = 0 local saveTimeout = 0 local saveRetries = 0 @@ -166,13 +166,13 @@ end local function incPage(inc) currentPage = incMax(currentPage, inc, #(PageFiles)) Page = nil - currentLine = 1 + currentField = 1 menuLine = currentPage collectgarbage() end local function incLine(inc) - currentLine = clipValue(currentLine + inc, 1, #(Page.fields)) + currentField = clipValue(currentField + inc, 1, #(Page.fields)) end local function incMainMenu(inc) @@ -203,15 +203,15 @@ end local function drawScreen() local yMinLim = radio.yMinLimit or 0 local yMaxLim = radio.yMaxLimit or LCD_H - local currentLineY = Page.fieldLayout[currentLine].y + local currentFieldY = Page.fieldLayout[currentField].y local screen_title = Page.title drawScreenTitle("Betaflight / "..screen_title) - if currentLineY <= Page.fieldLayout[1].y then + if currentFieldY <= Page.fieldLayout[1].y then pageScrollY = 0 - elseif currentLineY - pageScrollY <= yMinLim then - pageScrollY = currentLineY - yMinLim - elseif currentLineY - pageScrollY >= yMaxLim then - pageScrollY = currentLineY - yMaxLim + elseif currentFieldY - pageScrollY <= yMinLim then + pageScrollY = currentFieldY - yMinLim + elseif currentFieldY - pageScrollY >= yMaxLim then + pageScrollY = currentFieldY - yMaxLim end for i=1,#(Page.labels) do local f = Page.labels[i] @@ -226,7 +226,7 @@ local function drawScreen() local pos = Page.fieldLayout[i] local text_options = radio.textSize + globalTextOptions local value_options = text_options - if i == currentLine then + if i == currentField then value_options = text_options + INVERS if pageState == pageStatus.editing then value_options = value_options + BLINK @@ -257,8 +257,8 @@ function clipValue(val,min,max) end local function incValue(inc) - local f = Page.fields[currentLine] - local idx = f.i or currentLine + local f = Page.fields[currentField] + local idx = f.i or currentField local scale = (f.scale or 1) local mult = (f.mult or 1) f.value = clipValue(f.value + ((inc*mult)/scale), (f.min/scale) or 0, (f.max/scale) or 255) @@ -344,13 +344,13 @@ function run_ui(event) end for i=1, #PageFiles do if (not PageFiles[i].requiredVersion) or (apiVersion == 0) or (apiVersion > 0 and PageFiles[i].requiredVersion <= apiVersion) then - local currentLineY = (menuLine-1)*lineSpacing + yMinLim - if currentLineY <= yMinLim then + local currentFieldY = (menuLine-1)*lineSpacing + yMinLim + if currentFieldY <= yMinLim then mainMenuScrollY = 0 - elseif currentLineY - mainMenuScrollY <= yMinLim then - mainMenuScrollY = currentLineY - yMinLim - elseif currentLineY - mainMenuScrollY >= yMaxLim then - mainMenuScrollY = currentLineY - yMaxLim + elseif currentFieldY - mainMenuScrollY <= yMinLim then + mainMenuScrollY = currentFieldY - yMinLim + elseif currentFieldY - mainMenuScrollY >= yMaxLim then + mainMenuScrollY = currentFieldY - yMaxLim end local attr = (menuLine == i and INVERS or 0) if event == EVT_VIRTUAL_ENTER and attr == INVERS then @@ -413,8 +413,8 @@ function run_ui(event) incLine(1) elseif event == EVT_VIRTUAL_ENTER then if Page then - local field = Page.fields[currentLine] - local idx = field.i or currentLine + local field = Page.fields[currentField] + local idx = field.i or currentField if Page.values and Page.values[idx] and (field.ro ~= true) then pageState = pageStatus.editing end @@ -469,7 +469,7 @@ function run_ui(event) end if stopDisplay and (not isTelemetryScript) then invalidatePages() - currentLine = 1 + currentField = 1 uiState = uiStatus.mainMenu stopDisplay = false end From d9bc9fcdb816a0328d2ea927986987d2c039413f Mon Sep 17 00:00:00 2001 From: Hans Christian Olaussen <41271048+klutvott123@users.noreply.github.com> Date: Fri, 22 Nov 2019 18:10:28 +0100 Subject: [PATCH 5/5] allow apiVersion detection in init state for TELEMETRY script --- src/SCRIPTS/BF/ui.lua | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/SCRIPTS/BF/ui.lua b/src/SCRIPTS/BF/ui.lua index 3671f917..8a6fd7e3 100644 --- a/src/SCRIPTS/BF/ui.lua +++ b/src/SCRIPTS/BF/ui.lua @@ -297,16 +297,9 @@ function run_ui(event) -- if lastRunTS old than 500ms if lastRunTS + 50 < now then invalidatePages() - if isTelemetryScript then - uiState = uiStatus.pages - else - uiState = uiStatus.init - end + uiState = uiStatus.init end lastRunTS = now - if isTelemetryScript then - uiState = uiStatus.pages - end if uiState == uiStatus.init then local yMinLim = radio.yMinLimit lcd.clear() @@ -323,7 +316,11 @@ function run_ui(event) else background = nil invalidatePages() - uiState = uiStatus.mainMenu + if isTelemetryScript then + uiState = uiStatus.pages + else + uiState = uiStatus.mainMenu + end end elseif uiState == uiStatus.mainMenu then getPageCount()