diff --git a/.github/release.yml b/.github/release.yml
new file mode 100644
index 00000000..6c1dd378
--- /dev/null
+++ b/.github/release.yml
@@ -0,0 +1,26 @@
+changelog:
+ exclude:
+ labels:
+ - "cleanup"
+ - "RN: IGNORE"
+ categories:
+ - title: Features
+ labels:
+ - "RN: FEATURE"
+ - "RN: MAJOR FEATURE"
+ - "RN: MINOR FEATURE"
+ - title: Improvements
+ labels:
+ - "RN: IMPROVEMENT"
+ - "RN: UI"
+ - "RN: REFACTOR"
+ - "RN: FONT"
+ - title: Fixes
+ labels:
+ - "RN: BUGFIX"
+ - title: Translation
+ labels:
+ - "RN: TRANSLATION"
+ - title: Known Issues
+ labels:
+ - BUG
diff --git a/.github/stale.yml b/.github/stale.yml
deleted file mode 100644
index 74406576..00000000
--- a/.github/stale.yml
+++ /dev/null
@@ -1,55 +0,0 @@
-# Configuration for probot-stale - https://github.com/probot/stale
-
-# Number of days of inactivity before an Issue or Pull Request becomes stale
-daysUntilStale: 30
-
-# Number of days of inactivity before a stale Issue or Pull Request is closed.
-# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
-daysUntilClose: 7
-
-# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
-exemptLabels:
- - BUG
- - Feature Request
- - Pinned
-
-# Set to true to ignore issues in a project (defaults to false)
-exemptProjects: false
-
-# Set to true to ignore issues in a milestone (defaults to false)
-exemptMilestones: true
-
-# Label to use when marking as stale
-staleLabel: Inactive
-
-# Comment to post when marking as stale. Set to `false` to disable
-markComment: >
- This issue / pull request has been automatically marked as stale because it
- has not had recent activity. It will be closed if no further activity occurs
- within a week.
-
-# Comment to post when removing the stale label.
-# unmarkComment: >
-# Your comment here.
-
-# Comment to post when closing a stale Issue or Pull Request.
-closeComment: >
- Automatically closing as inactive.
-
-# Limit the number of actions per hour, from 1-30. Default is 30
-limitPerRun: 30
-
-# Limit to only `issues` or `pulls`
-# only: issues
-
-# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
-# pulls:
-# daysUntilStale: 30
-# markComment: >
-# This pull request has been automatically marked as stale because it has not had
-# recent activity. It will be closed if no further activity occurs. Thank you
-# for your contributions.
-
-# issues:
-# exemptLabels:
-# - confirmed
diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml
new file mode 100644
index 00000000..74c4c2cd
--- /dev/null
+++ b/.github/workflows/stale.yaml
@@ -0,0 +1,32 @@
+name: 'Close stale issues'
+
+on:
+ schedule:
+ - cron: "30 4 * * *"
+
+jobs:
+ stale:
+ name: 'Check and close stale issues'
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/stale@v3
+ with:
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+ operations-per-run: 30
+ days-before-stale: 30
+ days-before-close: 7
+ stale-issue-message: >
+ This issue has been automatically marked as stale because it
+ has not had recent activity. It will be closed if no further activity occurs
+ within a week.
+ close-issue-message: 'Issue closed automatically as inactive.'
+ exempt-issue-labels: 'BUG,Feature Request,Pinned'
+ stale-issue-label: 'Inactive'
+ stale-pr-message: >
+ This pull request has been automatically marked as stale because it
+ has not had recent activity. It will be closed if no further activity occurs
+ within a week.
+ close-pr-message: 'Pull request closed automatically as inactive.'
+ exempt-pr-labels: 'Pinned'
+ stale-pr-label: 'Inactive'
+ exempt-all-milestones: true
diff --git a/.gitignore b/.gitignore
index 95b7ddbd..63c3ae72 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,7 @@
# Compiled Lua sources
luac.out
-# luarocks build files
+# Luarocks build files
*.src.rock
*.zip
*.tar.gz
@@ -42,6 +42,9 @@ luac.out
# Eclipse
.project
-#directories
+# Visual Studio Code
+.vscode
+
+# Directories
tmp
obj
diff --git a/README.md b/README.md
index eb175806..9e7dd41e 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,17 @@
-# Betaflight TX Lua Scripts
+
+
-## Firmware Considerations
+ [](https://github.com/betaflight/betaflight-tx-lua-scripts/releases) [](https://travis-ci.com/betaflight/betaflight-tx-lua-scripts) [](https://dev.azure.com/Betaflight/Betaflight%20Nightlies/_build/latest?definitionId=1&branchName=master) [](https://www.gnu.org/licenses/gpl-3.0)
+
+## Requirements
- Betaflight - As a best practice, it is recommended to use the most recent stable release of Betaflight to obtain the best possible results;
-- OpenTX - 2.3.4 or newer;
+- Telemetry - Telemetry has to be enabled and supported by the TX / RX for the scripts to be able to communicate with the flight controller;
+- OpenTX - 2.3.12 or newer;
+- EdgeTX - 2.4.0 or newer;
+- ExpressLRS - 2.0.1 or newer;
- Crossfire TX / RX - v2.11 or newer;
-- FrSky TX / RX - While most receivers work fine, it's recommended to update the XSR family of receivers to their most recent firmware version to correct any known bugs in SmartPort telemetry.
+- FrSky TX / RX with support for SmartPort - While most receivers with SmartPort support work fine, it is recommended to update the receiver to the most recent firmware version to correct any known bugs in telemetry.
## Installing
@@ -15,38 +21,64 @@ Download a zip file containing the latest version from the [releases page](https
Unzip the files from the link above and drag the contents of the `obj` folder to your radios SD card. If you do this correctly, the `SCRIPTS` directory will merge with your existing directories, placing the scripts in their appropriate paths. You will know if you did this correctly if the `bf.lua` file shows up in your `/SCRIPTS/TOOLS` directory.
-### How to install
+
+
+## How to use
-Bootloader Method
+Navigate to the TOOLS menu in OpenTX, select "Betaflight setup" or "Betaflight CMS" and press the [ENTER] button. The first time the script is launched after a clean install or upgrade it will go through it's compile procedure and exit back to the TOOLS menu when it's done.
-1. Power off your transmitter and power it back on in boot loader mode.
-2. Connect a USB cable and open the SD card drive on your computer.
-3. Unzip the file and copy the scripts to the root of the SD card.
-4. Unplug the USB cable and power cycle your transmitter.
+### Betaflight setup
-Manual method (varies, based on the model of your transmitter)
+The "Betaflight setup" script lets you configure Betaflight through the MSP protocol.
-1. Power off your transmitter.
-2. Remove the SD card and plug it into a computer
-3. Unzip the file and copy the scripts to the root of the SD card.
-4. Reinsert your SD card into the transmitter
-5. Power up your transmitter.
+
-If you copied the files correctly, you can now go into the OpenTx Tools screen from the main menu and access the Betaflight Configuration tool. The first time you run the script, a message 'Compiling...' will appear in the display before the script is started - this is normal, and is done to minimise the RAM usage of the script.
+#### Controls
-### Running the script as a telemetry page
+- [+] / [-] / [ROTARY ENCODER] - Used to navigate.
+- [PAGE] - Press to move to the next page. Long press to move to the previous page.
+- [ENTER] - Press to access the selected element. Long press to open the function menu.
+- [EXIT] - Press to go back or exit the script.
-Due to issues with input mapping and memory overruns, running the script as a telemetry page **is no longer supported**. The only way to run the script is through the Tools screen in the OpenTX main menu.
+#### Saving your changes
-### Setting up VTX Tables
+Any changes to parameters in the script will not take effect until a save is manually initiated. Change the parameters you want to change, open the function menu by long pressing [ENTER] and select "save page" to send the modified parameters back to the flight controller.
+
+#### Setting up VTX tables
If you are using a VTX that supports the SmartAudio or Tramp protocols then bands and channels etc. are managed using VTX tables since Betaflight version 4.1.0. The script will be downloading and storing the current VTX table for every model the first time the model is connected and the script is run. If you change the VTX table, you have to re-load the updated VTX table in the script, by choosing the 'vtx tables' option in the function menu.
+Depending on the size of the vtx tables and the telemetry protocol used, downloading the vtx tables can take a while.
+
+
+
+### Betaflight CMS
+
+**!! IMPORTANT: TBS Crossfire/Tracer only !!**
+
+"Betaflight CMS" lets you access the same CMS menu that is available in the OSD.
+
+
+
+#### Controls
+
+- [PITCH] - Navigate the current menu.
+- [ROLL] - Enter menu or change selected parameter.
+- [YAW] - Left to go back and right to enter the "SAVE / EXIT" menu.
+- [+] / [ENTER] - Manual refresh. Press if the script doesn't update.
+- [EXIT] - Close CMS menu and exit script. **!! IMPORTANT: Single press only. Long press will exit the script without closing CMS and as a result you will not be able to arm !!**
+
### Background script
-The optional background script offers RTC synchronization and RSSI through MSP. It can be setup as a special or global function in OpenTX. The image below shows how to run the background script as a special function.
-
+The optional background script offers RTC synchronization and RSSI through MSP. RSSI will only be sent if no other RSSI source is detected. It can be setup as a special or global function in OpenTX. The image below shows how to run the background script as a special function.
+
+
+
+## Unstable testing versions
+
+Unstable testing versions of the latest builds of the Lua Script can be downloaded from [here](https://github.com/betaflight/betaflight-tx-lua-scripts-nightlies/releases).
+Be aware that these versions are intended for testing / feedback only, and may be buggy or broken. Caution is advised when using these versions.
## Building from source
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 66f7f867..837910b3 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -15,21 +15,29 @@ variables:
owner: betaflight
repoName: betaflight-tx-lua-scripts-nightlies
releaseNotes: This is a nightly build off the tip of 'master'. It may be unstable and result in corrupted configurations or data loss. **Use only for testing.**
+ vmImage: 'ubuntu-20.04'
name: $(Date:yyyyMMdd).$(BuildID)
+
trigger:
batch: true
branches:
include:
- master
-pr: none
+
+pr:
+ drafts: false
+ branches:
+ include:
+ - master
+ - "*-maintenance"
stages:
- stage: Build
jobs:
- job: 'Linux'
pool:
- vmImage: 'ubuntu-16.04'
+ vmImage: '$(vmImage)'
steps:
- script: sudo apt-get -y install lua5.2
displayName: 'Install lua compiler.'
@@ -44,6 +52,8 @@ stages:
- stage: Release
jobs:
- job: Release
+ pool:
+ vmImage: '$(vmImage)'
steps:
- task: DownloadPipelineArtifact@2
inputs:
diff --git a/bin/build.sh b/bin/build.sh
index a58209fa..be6cb2ac 100755
--- a/bin/build.sh
+++ b/bin/build.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
if [ -d obj ]; then
rm -fR obj/*
diff --git a/docs/assets/images/background_script_setup.png b/docs/assets/images/background_script_setup.png
index fabb458e..09b48066 100644
Binary files a/docs/assets/images/background_script_setup.png and b/docs/assets/images/background_script_setup.png differ
diff --git a/docs/assets/images/bf_lua_logo_dark_mode.png b/docs/assets/images/bf_lua_logo_dark_mode.png
new file mode 100644
index 00000000..3ff9afa4
Binary files /dev/null and b/docs/assets/images/bf_lua_logo_dark_mode.png differ
diff --git a/docs/assets/images/bf_lua_logo_light_mode.png b/docs/assets/images/bf_lua_logo_light_mode.png
new file mode 100644
index 00000000..09a1cac2
Binary files /dev/null and b/docs/assets/images/bf_lua_logo_light_mode.png differ
diff --git a/docs/assets/images/download_vtx_tables.gif b/docs/assets/images/download_vtx_tables.gif
new file mode 100644
index 00000000..350d1200
Binary files /dev/null and b/docs/assets/images/download_vtx_tables.gif differ
diff --git a/docs/assets/images/how_to_use.gif b/docs/assets/images/how_to_use.gif
new file mode 100644
index 00000000..70b5f252
Binary files /dev/null and b/docs/assets/images/how_to_use.gif differ
diff --git a/docs/assets/images/how_to_use_cms.gif b/docs/assets/images/how_to_use_cms.gif
new file mode 100644
index 00000000..05014782
Binary files /dev/null and b/docs/assets/images/how_to_use_cms.gif differ
diff --git a/docs/assets/images/install.gif b/docs/assets/images/install.gif
new file mode 100644
index 00000000..d6f4d0c6
Binary files /dev/null and b/docs/assets/images/install.gif differ
diff --git a/src/BF/use_tools_menu_instead_of_this.txt b/src/BF/use_tools_menu_instead_of_this.txt
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/SCRIPTS/BF/BOARD_INFO/readme.txt b/src/SCRIPTS/BF/BOARD_INFO/readme.txt
new file mode 100644
index 00000000..2fe32c7e
--- /dev/null
+++ b/src/SCRIPTS/BF/BOARD_INFO/readme.txt
@@ -0,0 +1 @@
+Board info downloaded from the flight controller will be stored in this folder.
diff --git a/src/SCRIPTS/BF/CMS/common.lua b/src/SCRIPTS/BF/CMS/common.lua
new file mode 100644
index 00000000..5581d822
--- /dev/null
+++ b/src/SCRIPTS/BF/CMS/common.lua
@@ -0,0 +1,121 @@
+local CONST = {
+ bitmask = {
+ firstChunk = 0x80,
+ lastChunk = 0x40,
+ batchId = 0x3F,
+ rleCharValueMask = 0x7F,
+ rleCharRepeatedMask = 0x80
+ },
+ offset = {
+ meta = 1,
+ sequence = 2,
+ data = 3
+ }
+}
+
+local function cRleDecode(buf)
+ local dest = {}
+ local rpt = false
+ local c = nil
+ for i = 1, #buf do
+ if (rpt == false) then
+ c = bit32.band(buf[i], CONST.bitmask.rleCharValueMask)
+ if (bit32.band(buf[i], CONST.bitmask.rleCharRepeatedMask) > 0) then
+ rpt = true
+ else
+ dest[#dest + 1] = c
+ end
+ else
+ for j = 1, buf[i] do
+ dest[#dest + 1] = c
+ end
+ rpt = false
+ end
+ end
+ return dest
+end
+
+screen = {
+ config = nil,
+ buffer = {},
+ data = {},
+ batchId = 0,
+ sequence = 0,
+ redraws = 2,
+ reset = function()
+ screen.data = {}
+ screen.batchId = 0
+ screen.sequence = 0
+ end,
+ draw = function()
+ lcd.clear()
+ lcd.drawText(screen.config.refresh.left, screen.config.refresh.top, screen.config.refresh.text, screen.config.textSize)
+ for char = 1, #screen.buffer do
+ if (screen.buffer[char] ~= 32) then -- skip spaces to avoid CPU spikes
+ local c = string.char(screen.buffer[char])
+ local row = math.ceil(char / screen.config.cols)
+ local col = char - ((row - 1) * screen.config.cols)
+ local xPos = ((col - 1) * screen.config.pixelsPerChar) + screen.config.xIndent + 1
+ local yPos = ((row - 1) * screen.config.pixelsPerRow) + screen.config.yOffset + 1
+ lcd.drawText(xPos, yPos, c, screen.config.textSize)
+ end
+ end
+ end,
+}
+
+cms = {
+ menuOpen = false,
+ synced = false,
+ init = function(cmsConfig)
+ screen.config = assert(cmsConfig, "Resolution not supported")
+ screen.reset()
+ protocol.cms.close()
+ cms.menuOpen = false
+ cms.synced = false
+ end,
+ open = function()
+ protocol.cms.open(screen.config.rows, screen.config.cols)
+ end,
+ refresh = function()
+ protocol.cms.refresh()
+ end,
+ close = function()
+ protocol.cms.close()
+ cms.menuOpen = false
+ end,
+ update = function()
+ local command, data = protocol.cms.poll()
+ if (command == "update") then
+ local firstChunk = bit32.btest(data[CONST.offset.meta], CONST.bitmask.firstChunk)
+ local lastChunk = bit32.btest(data[CONST.offset.meta], CONST.bitmask.lastChunk)
+ local batchId = bit32.band(data[CONST.offset.meta], CONST.bitmask.batchId)
+ local sequence = data[CONST.offset.sequence]
+ if firstChunk then
+ screen.reset()
+ screen.batchId = batchId
+ screen.sequence = 0
+ end
+ if (screen.batchId == batchId) and (screen.sequence == sequence) then
+ screen.sequence = sequence + 1
+ for i = CONST.offset.data, #data do
+ screen.data[#screen.data + 1] = data[i]
+ end
+ if lastChunk then
+ screen.buffer = cRleDecode(screen.data)
+ screen.redraws = 2
+ screen.reset()
+ cms.synced = true
+ end
+ else
+ protocol.cms.refresh()
+ end
+ cms.menuOpen = true
+ elseif (command == "clear") then
+ screen.reset()
+ end
+ if screen.redraws > 0 then
+ screen.draw()
+ screen.redraws = screen.redraws - 1
+ end
+ end
+}
diff --git a/src/SCRIPTS/BF/CMS/crsf.lua b/src/SCRIPTS/BF/CMS/crsf.lua
new file mode 100644
index 00000000..83c17337
--- /dev/null
+++ b/src/SCRIPTS/BF/CMS/crsf.lua
@@ -0,0 +1,64 @@
+local CONST = {
+ frame = {
+ destination = 1,
+ source = 2,
+ command = 3,
+ content = 4
+ },
+ address = {
+ transmitter = 0xEA,
+ betaflight = 0xC8
+ },
+ frameType = {
+ displayPort = 0x7D
+ },
+ command = {
+ update = 0x01,
+ clear = 0x02,
+ open = 0x03,
+ close = 0x04,
+ refresh = 0x05
+ }
+}
+
+local function crsfDisplayPortCmd(cmd, data)
+ local payloadOut = { CONST.address.betaflight, CONST.address.transmitter, cmd }
+ if data ~= nil then
+ for i = 1, #(data) do
+ payloadOut[3 + i] = data[i]
+ end
+ end
+ return crossfireTelemetryPush(CONST.frameType.displayPort, payloadOut)
+end
+
+protocol.cms.poll = function()
+ local command = nil
+ local dataOut = {}
+ local frameType, data = crossfireTelemetryPop()
+ if (data ~= nil) and (#data > 2) then
+ if (frameType == CONST.frameType.displayPort) and (data[CONST.frame.destination] == CONST.address.transmitter) and (data[CONST.frame.source] == CONST.address.betaflight) then
+ for k,v in pairs(CONST.command) do
+ if (v == data[CONST.frame.command]) then
+ command = k
+ end
+ end
+ for i = CONST.frame.content, #data do
+ dataOut[#dataOut + 1] = data[i]
+ end
+ end
+ end
+ return command, dataOut
+end
+
+protocol.cms.open = function(rows, cols)
+ return crsfDisplayPortCmd(CONST.command.open, { rows, cols })
+end
+
+protocol.cms.close = function()
+ return crsfDisplayPortCmd(CONST.command.close, nil)
+end
+
+protocol.cms.refresh = function()
+ return crsfDisplayPortCmd(CONST.command.refresh, nil)
+end
+
diff --git a/src/SCRIPTS/BF/CONFIRM/acc_cal.lua b/src/SCRIPTS/BF/CONFIRM/acc_cal.lua
new file mode 100644
index 00000000..41a3c8de
--- /dev/null
+++ b/src/SCRIPTS/BF/CONFIRM/acc_cal.lua
@@ -0,0 +1,25 @@
+local template = assert(loadScript(radio.template))()
+local margin = template.margin
+local indent = template.indent
+local lineSpacing = template.lineSpacing
+local tableSpacing = template.tableSpacing
+local sp = template.listSpacing.field
+local yMinLim = radio.yMinLimit
+local x = margin
+local y = yMinLim - lineSpacing
+local inc = { x = function(val) x = x + val return x end, y = function(val) y = y + val return y end }
+local labels = {}
+local fields = {}
+
+labels[#labels + 1] = { t = "Make sure the craft is level", x = x, y = inc.y(lineSpacing) }
+labels[#labels + 1] = { t = "and stable, then press", x = x, y = inc.y(lineSpacing) }
+labels[#labels + 1] = { t = "[ENTER] to calibrate, or", x = x, y = inc.y(lineSpacing) }
+labels[#labels + 1] = { t = "[EXIT] to cancel.", x = x, y = inc.y(lineSpacing) }
+fields[#fields + 1] = { x = x, y = inc.y(lineSpacing), value = "", ro = true }
+
+return {
+ title = "Accelerometer",
+ labels = labels,
+ fields = fields,
+ init = assert(loadScript("acc_cal.lua"))(),
+}
diff --git a/src/SCRIPTS/BF/CONFIRM/vtx_tables.lua b/src/SCRIPTS/BF/CONFIRM/vtx_tables.lua
new file mode 100644
index 00000000..5d51e617
--- /dev/null
+++ b/src/SCRIPTS/BF/CONFIRM/vtx_tables.lua
@@ -0,0 +1,24 @@
+local template = assert(loadScript(radio.template))()
+local margin = template.margin
+local indent = template.indent
+local lineSpacing = template.lineSpacing
+local tableSpacing = template.tableSpacing
+local sp = template.listSpacing.field
+local yMinLim = radio.yMinLimit
+local x = margin
+local y = yMinLim - lineSpacing
+local inc = { x = function(val) x = x + val return x end, y = function(val) y = y + val return y end }
+local labels = {}
+local fields = {}
+
+labels[#labels + 1] = { t = "Download VTX tables? Press", x = x, y = inc.y(lineSpacing) }
+labels[#labels + 1] = { t = "[ENTER] to download, or", x = x, y = inc.y(lineSpacing) }
+labels[#labels + 1] = { t = "[EXIT] to cancel.", x = x, y = inc.y(lineSpacing) }
+fields[#fields + 1] = { x = x, y = inc.y(lineSpacing), value = "", ro = true }
+
+return {
+ title = "VTX Tables",
+ labels = labels,
+ fields = fields,
+ init = assert(loadScript("vtx_tables.lua"))(),
+}
diff --git a/src/SCRIPTS/BF/MSP/common.lua b/src/SCRIPTS/BF/MSP/common.lua
index 46648991..fb119f6c 100644
--- a/src/SCRIPTS/BF/MSP/common.lua
+++ b/src/SCRIPTS/BF/MSP/common.lua
@@ -6,6 +6,7 @@ local MSP_STARTFLAG = bit32.lshift(1,4)
local mspSeq = 0
local mspRemoteSeq = 0
local mspRxBuf = {}
+local mspRxSize = 0
local mspRxCRC = 0
local mspRxReq = 0
local mspStarted = false
@@ -37,12 +38,6 @@ function mspProcessTxQ()
end
if i <= protocol.maxTxBufferSize then
payload[i] = mspTxCRC
- i = i + 1
- -- zero fill
- while i <= protocol.maxTxBufferSize do
- payload[i] = 0
- i = i + 1
- end
protocol.mspSend(payload)
mspTxBuf = {}
mspTxIdx = 1
@@ -68,25 +63,30 @@ function mspSendRequest(cmd, payload)
end
function mspReceivedReply(payload)
- local idx = 1
- local head = payload[idx]
- local err_flag = (bit32.band(head,0x20) ~= 0)
+ local idx = 1
+ local status = payload[idx]
+ local err = bit32.btest(status, 0x80)
+ local version = bit32.rshift(bit32.band(status, 0x60), 5)
+ local start = bit32.btest(status, 0x10)
+ local seq = bit32.band(status, 0x0F)
idx = idx + 1
- if err_flag then
- -- error flag set
+ if err then
mspStarted = false
return nil
end
- local start = (bit32.band(head,0x10) ~= 0)
- local seq = bit32.band(head,0x0F)
if start then
- -- start flag set
mspRxBuf = {}
mspRxSize = payload[idx]
- mspRxCRC = bit32.bxor(mspRxSize,mspLastReq)
- mspRxReq = mspLastReq
+ mspRxReq = mspLastReq
idx = idx + 1
- mspStarted = true
+ if version == 1 then
+ mspRxReq = payload[idx]
+ idx = idx + 1
+ end
+ mspRxCRC = bit32.bxor(mspRxSize, mspRxReq)
+ if mspRxReq == mspLastReq then
+ mspStarted = true
+ end
elseif not mspStarted then
return nil
elseif bit32.band(mspRemoteSeq + 1, 0x0F) ~= seq then
@@ -95,7 +95,7 @@ function mspReceivedReply(payload)
end
while (idx <= protocol.maxRxBufferSize) and (#mspRxBuf < mspRxSize) do
mspRxBuf[#mspRxBuf + 1] = payload[idx]
- mspRxCRC = bit32.bxor(mspRxCRC,payload[idx])
+ mspRxCRC = bit32.bxor(mspRxCRC, payload[idx])
idx = idx + 1
end
if idx > protocol.maxRxBufferSize then
@@ -104,7 +104,7 @@ function mspReceivedReply(payload)
end
mspStarted = false
-- check CRC
- if mspRxCRC ~= payload[idx] then
+ if mspRxCRC ~= payload[idx] and version == 0 then
return nil
end
return mspRxBuf
diff --git a/src/SCRIPTS/BF/MSP/sp.lua b/src/SCRIPTS/BF/MSP/sp.lua
index eaabe8cd..ecc15b1b 100644
--- a/src/SCRIPTS/BF/MSP/sp.lua
+++ b/src/SCRIPTS/BF/MSP/sp.lua
@@ -7,9 +7,11 @@ local REPLY_FRAME_ID = 0x32
local lastSensorId, lastFrameId, lastDataId, lastValue
protocol.mspSend = function(payload)
- local dataId = payload[1] + bit32.lshift(payload[2],8)
- local value = payload[3] + bit32.lshift(payload[4],8)
- + bit32.lshift(payload[5],16) + bit32.lshift(payload[6],24)
+ local dataId = payload[1] + bit32.lshift(payload[2], 8)
+ local value = 0
+ for i = 3, #payload do
+ value = value + bit32.lshift(payload[i], (i - 3) * 8)
+ end
return protocol.push(LOCAL_SENSOR_ID, REQUEST_FRAME_ID, dataId, value)
end
diff --git a/src/SCRIPTS/BF/PAGES/failsafe.lua b/src/SCRIPTS/BF/PAGES/failsafe.lua
new file mode 100644
index 00000000..1ce6fbaa
--- /dev/null
+++ b/src/SCRIPTS/BF/PAGES/failsafe.lua
@@ -0,0 +1,45 @@
+local template = assert(loadScript(radio.template))()
+local margin = template.margin
+local indent = template.indent
+local lineSpacing = template.lineSpacing
+local tableSpacing = template.tableSpacing
+local sp = template.listSpacing.field
+local yMinLim = radio.yMinLimit
+local x = margin
+local y = yMinLim - lineSpacing
+local inc = { x = function(val) x = x + val return x end, y = function(val) y = y + val return y end }
+local labels = {}
+local fields = {}
+
+local procedure = { [0] = "Land", "Drop" }
+
+if apiVersion >= 1.039 then
+ procedure[#procedure + 1] = "Rescue"
+end
+
+if apiVersion >= 1.039 then
+ labels[#labels + 1] = { t = "Failsafe Switch", x = x, y = inc.y(lineSpacing) }
+ fields[#fields + 1] = { t = "Action", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 2, vals = { 5 }, table = { [0] = "Stage 1", "Kill", "Stage 2" } }
+else
+ fields[#fields + 1] = { t = "Kill switch", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 5 }, table = { [0] = "OFF", "ON" } }
+end
+
+labels[#labels + 1] = { t = "Stage 2 Settings" , x = x, y = inc.y(lineSpacing) }
+fields[#fields + 1] = { t = "Procedure", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = #procedure, vals = { 8 }, table = procedure }
+fields[#fields + 1] = { t = "Guard Time", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 200, vals = { 1 }, scale = 10 }
+fields[#fields + 1] = { t = "Thrl Low Delay", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 300, vals = { 6, 7 }, scale = 10 }
+
+labels[#labels + 1] = { t = "Stage 2 Land Settings", x = x, y = inc.y(lineSpacing) }
+fields[#fields + 1] = { t = "Thrl Land Value", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 750, max = 2250, vals = { 3, 4 } }
+fields[#fields + 1] = { t = "Motor Off Delay", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 200, vals = { 2 }, scale = 10 }
+
+return {
+ read = 75, -- MSP_FAILSAFE_CONFIG
+ write = 76, -- MSP_SET_FAILSAFE_CONFIG
+ title = "Failsafe",
+ reboot = true,
+ eepromWrite = true,
+ minBytes = 8,
+ labels = labels,
+ fields = fields,
+}
diff --git a/src/SCRIPTS/BF/PAGES/filters1.lua b/src/SCRIPTS/BF/PAGES/filters1.lua
index d7eb5937..68db6c8e 100644
--- a/src/SCRIPTS/BF/PAGES/filters1.lua
+++ b/src/SCRIPTS/BF/PAGES/filters1.lua
@@ -1,9 +1,4 @@
-local template = loadScript(radio.templateHome.."filters1.lua")
-if template then
- template = template()
-else
- template = assert(loadScript(radio.templateHome.."default_template.lua"))()
-end
+local template = assert(loadScript(radio.template))()
local margin = template.margin
local indent = template.indent
local lineSpacing = template.lineSpacing
@@ -16,18 +11,33 @@ local inc = { x = function(val) x = x + val return x end, y = function(val) y =
local labels = {}
local fields = {}
+local gyroFilterType = { [0] = "PT1", "BIQUAD" }
+
+if apiVersion >= 1.044 then
+ gyroFilterType[#gyroFilterType + 1] = "PT2"
+ gyroFilterType[#gyroFilterType + 1] = "PT3"
+end
+
+local dtermFilterType = gyroFilterType
+
+if apiVersion >= 1.036 and apiVersion <= 1.038 then
+ dtermFilterType = { [0] = "PT1", "BIQUAD", "FIR" }
+end
+
+local dtermFilterType2 = gyroFilterType
+
if apiVersion >= 1.041 then
labels[#labels + 1] = { t = "Gyro Lowpass 1 Dynamic", x = x, y = inc.y(lineSpacing) }
fields[#fields + 1] = { t = "Min Cutoff", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1000, vals = { 30, 31 } }
fields[#fields + 1] = { t = "Max Cutoff", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1000, vals = { 32, 33 } }
- fields[#fields + 1] = { t = "Filter Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 25 }, table = { [0] = "PT1", [1] = "BIQUAD" } }
+ fields[#fields + 1] = { t = "Filter Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = #gyroFilterType, vals = { 25 }, table = gyroFilterType }
end
if apiVersion >= 1.016 then
labels[#labels + 1] = { t = "Gyro Lowpass 1", x = x, y = inc.y(lineSpacing) }
if apiVersion >= 1.039 then
fields[#fields + 1] = { t = "Cutoff", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 16000, vals = { 21, 22 } }
- fields[#fields + 1] = { t = "Filter Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 25 }, table = { [0] = "PT1", [1] = "BIQUAD" } }
+ fields[#fields + 1] = { t = "Filter Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = #gyroFilterType, vals = { 25 }, table = gyroFilterType }
else
fields[#fields + 1] = { t = "Cutoff", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 255, vals = { 1 } }
end
@@ -36,7 +46,7 @@ end
if apiVersion >= 1.039 then
labels[#labels + 1] = { t = "Gyro Lowpass 2", x = x, y = inc.y(lineSpacing) }
fields[#fields + 1] = { t = "Cutoff", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 16000, vals = { 23, 24 } }
- fields[#fields + 1] = { t = "Filter Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 26 }, table = { [0] = "PT1", [1] = "BIQUAD" } }
+ fields[#fields + 1] = { t = "Filter Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = #gyroFilterType, vals = { 26 }, table = gyroFilterType }
end
if apiVersion >= 1.020 then
@@ -55,16 +65,14 @@ if apiVersion >= 1.041 then
labels[#labels + 1] = { t = "D Term Lowpass 1 Dynamic", x = x, y = inc.y(lineSpacing) }
fields[#fields + 1] = { t = "Min Cutoff", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1000, vals = { 34, 35 } }
fields[#fields + 1] = { t = "Max Cutoff", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1000, vals = { 36, 37 } }
- fields[#fields + 1] = { t = "Filter Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 18 }, table = { [0] = "PT1", [1] = "BIQUAD" } }
+ fields[#fields + 1] = { t = "Filter Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = #dtermFilterType, vals = { 18 }, table = dtermFilterType }
end
if apiVersion >= 1.016 then
labels[#labels + 1] = { t = "D Term Lowpass 1", x = x, y = inc.y(lineSpacing) }
fields[#fields + 1] = { t = "Cutoff", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 16000, vals = { 2, 3 } }
- if apiVersion >= 1.036 and apiVersion <= 1.038 then
- fields[#fields + 1] = { t = "Filter Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 2, vals = { 18 }, table = { [0] = "PT1", [1] = "BIQUAD", [2] = "FIR" } }
- elseif apiVersion >= 1.039 then
- fields[#fields + 1] = { t = "Filter Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 18 }, table = { [0] = "PT1", [1] = "BIQUAD" } }
+ if apiVersion >= 1.036 then
+ fields[#fields + 1] = { t = "Filter Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = #dtermFilterType, vals = { 18 }, table = dtermFilterType }
end
end
@@ -72,7 +80,7 @@ if apiVersion >= 1.039 then
labels[#labels + 1] = { t = "D Term Lowpass 2", x = x, y = inc.y(lineSpacing) }
fields[#fields + 1] = { t = "Cutoff", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 16000, vals = { 27, 28 } }
if apiVersion >= 1.041 then
- fields[#fields + 1] = { t = "Filter Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 29 }, table = { [0] = "PT1", [1] = "BIQUAD" } }
+ fields[#fields + 1] = { t = "Filter Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = #dtermFilterType2, vals = { 29 }, table = dtermFilterType2 }
end
end
diff --git a/src/SCRIPTS/BF/PAGES/filters2.lua b/src/SCRIPTS/BF/PAGES/filters2.lua
index 5984a61c..0ba77145 100644
--- a/src/SCRIPTS/BF/PAGES/filters2.lua
+++ b/src/SCRIPTS/BF/PAGES/filters2.lua
@@ -1,9 +1,4 @@
-local template = loadScript(radio.templateHome.."filters2.lua")
-if template then
- template = template()
-else
- template = assert(loadScript(radio.templateHome.."default_template.lua"))()
-end
+local template = assert(loadScript(radio.template))()
local margin = template.margin
local indent = template.indent
local lineSpacing = template.lineSpacing
@@ -24,7 +19,11 @@ if apiVersion >= 1.042 then
if apiVersion < 1.043 then
fields[#fields + 1] = { t = "Range", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 3, vals = { 38 }, table = { [0]="HIGH", "MEDIUM", "LOW", "AUTO" } }
end
- fields[#fields + 1] = { t = "Width %", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 20, vals = { 39 } }
+ if apiVersion >= 1.044 then
+ fields[#fields + 1] = { t = "Count", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 5, vals = { 49 } }
+ else
+ fields[#fields + 1] = { t = "Width %", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 20, vals = { 39 } }
+ end
fields[#fields + 1] = { t = "Q", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1, max = 1000, vals = { 40, 41 } }
if apiVersion >= 1.043 then
fields[#fields + 1] = { t = "Min Frequency", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 60, max = 250, vals = { 42, 43 } }
@@ -47,7 +46,7 @@ return {
self.rpmHarmonics = self.values[44]
end,
preSave = function(self)
- self.reboot = self.values[44] == 0 and self.rpmHarmonics ~= 0
+ self.reboot = self.values[44] == 0 and self.rpmHarmonics ~= 0 and apiVersion <= 1.043
return self.values
end,
}
diff --git a/src/SCRIPTS/BF/PAGES/gpspids.lua b/src/SCRIPTS/BF/PAGES/gpspids.lua
index dd6af065..95382972 100644
--- a/src/SCRIPTS/BF/PAGES/gpspids.lua
+++ b/src/SCRIPTS/BF/PAGES/gpspids.lua
@@ -1,9 +1,4 @@
-local template = loadScript(radio.templateHome.."gpspids.lua")
-if template then
- template = template()
-else
- template = assert(loadScript(radio.templateHome.."default_template.lua"))()
-end
+local template = assert(loadScript(radio.template))()
local margin = template.margin
local indent = template.indent
local lineSpacing = template.lineSpacing
diff --git a/src/SCRIPTS/BF/PAGES/pid_advanced.lua b/src/SCRIPTS/BF/PAGES/pid_advanced.lua
index f9250841..5c136d66 100644
--- a/src/SCRIPTS/BF/PAGES/pid_advanced.lua
+++ b/src/SCRIPTS/BF/PAGES/pid_advanced.lua
@@ -1,9 +1,4 @@
-local template = loadScript(radio.templateHome.."pid_advanced.lua")
-if template then
- template = template()
-else
- template = assert(loadScript(radio.templateHome.."default_template.lua"))()
-end
+local template = assert(loadScript(radio.template))()
local margin = template.margin
local indent = template.indent
local lineSpacing = template.lineSpacing
@@ -25,17 +20,27 @@ if apiVersion >= 1.040 then
end
if apiVersion >= 1.043 then
+ fields[#fields + 1] = { t = "Motor Output Limit",x = x, y = inc.y(lineSpacing), sp = x + sp, min = 1, max = 100, vals = { 48 } }
fields[#fields + 1] = { t = "Dynamic Idle", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 100, vals = { 50 } }
end
-if apiVersion >= 1.016 then
+if apiVersion >= 1.016 and apiVersion <= 1.043 then
fields[#fields + 1] = { t = "VBAT Compensation", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 8 }, table = { [0]="OFF", "ON" } }
end
+if apiVersion >= 1.044 then
+ fields[#fields + 1] = { t = "Vbat Sag Comp", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 150, vals = { 56 } }
+ fields[#fields + 1] = { t = "Thrust Linear", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 150, vals = { 57 } }
+end
+
if apiVersion >= 1.040 and apiVersion <= 1.041 then
fields[#fields + 1] = { t = "Smart Feedforward", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 27 }, table = { [0] = "OFF", "ON" } }
end
+if apiVersion >= 1.041 then
+ fields[#fields + 1] = { t = "Integrated Yaw", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 45 }, table = { [0]="OFF", "ON" } }
+end
+
if apiVersion >= 1.040 then
labels[#labels + 1] = { t = "I Term Relax", x = x, y = inc.y(lineSpacing) }
fields[#fields + 1] = { t = "Axes", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 4, vals = { 28 }, table = { [0]="NONE", "RP", "RPY", "RP (inc)", "RPY (inc)" } }
@@ -47,16 +52,16 @@ if apiVersion >= 1.040 then
end
end
-if apiVersion >= 1.041 then
- fields[#fields + 1] = { t = "Integrated Yaw", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 45 }, table = { [0]="OFF", "ON" } }
-end
-
if apiVersion >= 1.036 then
labels[#labels + 1] = { t = "Anti Gravity", x = x, y = inc.y(lineSpacing) }
if apiVersion >= 1.040 then
fields[#fields + 1] = { t = "Mode", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 39 }, table = { [0]="Smooth", "Step" } }
end
- fields[#fields + 1] = { t = "Gain", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1000, max = 30000, vals = { 22, 23 }, scale = 1000, mult = 100 }
+ if apiVersion >= 1.044 then
+ fields[#fields + 1] = { t = "Gain", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 30000, vals = { 22, 23 }, scale = 1000, mult = 100 }
+ else
+ fields[#fields + 1] = { t = "Gain", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1000, max = 30000, vals = { 22, 23 }, scale = 1000, mult = 100 }
+ end
fields[#fields + 1] = { t = "Threshold", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 20, max = 1000, vals = { 20, 21 } }
end
@@ -73,7 +78,7 @@ return {
self.dynamicIdle = self.values[50]
end,
preSave = function(self)
- self.reboot = self.values[50] ~= self.dynamicIdle
+ self.reboot = self.values[50] ~= self.dynamicIdle and apiVersion <= 1.043
return self.values
end,
}
diff --git a/src/SCRIPTS/BF/PAGES/pids1.lua b/src/SCRIPTS/BF/PAGES/pids1.lua
index b3e9830f..42c40afd 100644
--- a/src/SCRIPTS/BF/PAGES/pids1.lua
+++ b/src/SCRIPTS/BF/PAGES/pids1.lua
@@ -1,9 +1,4 @@
-local template = loadScript(radio.templateHome.."pids1.lua")
-if template then
- template = template()
-else
- template = assert(loadScript(radio.templateHome.."default_template.lua"))()
-end
+local template = assert(loadScript(radio.template))()
local margin = template.margin
local indent = template.indent
local lineSpacing = template.lineSpacing
@@ -16,6 +11,14 @@ local inc = { x = function(val) x = x + val return x end, y = function(val) y =
local labels = {}
local fields = {}
+local pidMax = 200
+local dLabel = "D"
+
+if apiVersion >= 1.044 then
+ pidMax = 250
+ dLabel = "D Max"
+end
+
if apiVersion >= 1.016 then
x = margin
y = yMinLim - tableSpacing.header
@@ -29,26 +32,26 @@ if apiVersion >= 1.016 then
y = yMinLim - tableSpacing.header
labels[#labels + 1] = { t = "P", x = x, y = inc.y(tableSpacing.header) }
- fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = 200, vals = { 1 } }
- fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = 200, vals = { 4 } }
- fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = 200, vals = { 7 } }
+ fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = pidMax, vals = { 1 } }
+ fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = pidMax, vals = { 4 } }
+ fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = pidMax, vals = { 7 } }
x = x + tableSpacing.col
y = yMinLim - tableSpacing.header
labels[#labels + 1] = { t = "I", x = x, y = inc.y(tableSpacing.header) }
- fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = 200, vals = { 2 } }
- fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = 200, vals = { 5 } }
- fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = 200, vals = { 8 } }
+ fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = pidMax, vals = { 2 } }
+ fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = pidMax, vals = { 5 } }
+ fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = pidMax, vals = { 8 } }
x = x + tableSpacing.col
y = yMinLim - tableSpacing.header
- labels[#labels + 1] = { t = "D", x = x, y = inc.y(tableSpacing.header) }
- fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = 200, vals = { 3 } }
- fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = 200, vals = { 6 } }
+ labels[#labels + 1] = { t = dLabel, x = x, y = inc.y(tableSpacing.header) }
+ fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = pidMax, vals = { 3 } }
+ fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = pidMax, vals = { 6 } }
if apiVersion >= 1.041 then
- fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = 200, vals = { 9 } }
+ fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = pidMax, vals = { 9 } }
end
end
diff --git a/src/SCRIPTS/BF/PAGES/pids2.lua b/src/SCRIPTS/BF/PAGES/pids2.lua
index b4c3a68d..7fdb1d1d 100644
--- a/src/SCRIPTS/BF/PAGES/pids2.lua
+++ b/src/SCRIPTS/BF/PAGES/pids2.lua
@@ -1,9 +1,4 @@
-local template = loadScript(radio.templateHome.."pids2.lua")
-if template then
- template = template()
-else
- template = assert(loadScript(radio.templateHome.."default_template.lua"))()
-end
+local template = assert(loadScript(radio.template))()
local margin = template.margin
local indent = template.indent
local lineSpacing = template.lineSpacing
@@ -16,6 +11,12 @@ local inc = { x = function(val) x = x + val return x end, y = function(val) y =
local labels = {}
local fields = {}
+local dMinMax = 100
+
+if apiVersion >= 1.044 then
+ dMinMax = 250
+end
+
if apiVersion >= 1.040 then
x = margin
y = yMinLim - tableSpacing.header
@@ -38,20 +39,25 @@ if apiVersion >= 1.040 then
y = yMinLim - tableSpacing.header
labels[#labels + 1] = { t = "D Min", x = x, y = inc.y(tableSpacing.header) }
- fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = 100, vals = { 40 } }
- fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = 100, vals = { 41 } }
- fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = 100, vals = { 42 } }
+ fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = dMinMax, vals = { 40 } }
+ fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = dMinMax, vals = { 41 } }
+ fields[#fields + 1] = { x = x, y = inc.y(tableSpacing.row), min = 0, max = dMinMax, vals = { 42 } }
end
x = margin
y = inc.y(lineSpacing*0.4)
end
-
-
if apiVersion >= 1.040 then
- labels[#labels + 1] = { t = "Feedforward", x = x, y = inc.y(lineSpacing) }
- fields[#fields + 1] = { t = "Transition", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 100, vals = { 9 }, scale = 100 }
+ labels[#labels + 1] = { t = "Feedforward", x = x, y = inc.y(lineSpacing) }
+ if apiVersion >= 1.044 then
+ fields[#fields + 1] = { t = "Jitter Reduction", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 20, vals = { 55 } }
+ fields[#fields + 1] = { t = "Smoothness", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 75, vals = { 52 } }
+ fields[#fields + 1] = { t = "Averaging", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 3, vals = { 51 }, table = { [0] = "OFF", "2_POINT", "3_POINT", "4_POINT" } }
+ fields[#fields + 1] = { t = "Boost", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 50, vals = { 53 } }
+ fields[#fields + 1] = { t = "Max Rate Limit", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 150, vals = { 54 } }
+ end
+ fields[#fields + 1] = { t = "Transition", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 100, vals = { 9 }, scale = 100 }
end
if apiVersion >= 1.041 then
diff --git a/src/SCRIPTS/BF/PAGES/profiles.lua b/src/SCRIPTS/BF/PAGES/profiles.lua
new file mode 100644
index 00000000..c59ad529
--- /dev/null
+++ b/src/SCRIPTS/BF/PAGES/profiles.lua
@@ -0,0 +1,46 @@
+local template = assert(loadScript(radio.template))()
+local margin = template.margin
+local indent = template.indent
+local lineSpacing = template.lineSpacing
+local tableSpacing = template.tableSpacing
+local sp = template.listSpacing.field
+local yMinLim = radio.yMinLimit
+local x = margin
+local y = yMinLim - lineSpacing
+local inc = { x = function(val) x = x + val return x end, y = function(val) y = y + val return y end }
+local labels = {}
+local fields = {}
+
+local RATEPROFILE_MASK = bit32.lshift(1, 7)
+local profileNumbers = { [0] = "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" }
+
+fields[#fields + 1] = { t = "PID Profile", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 11 }, table = profileNumbers }
+fields[#fields + 1] = { t = "Rate Profile", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 5, vals = { 15 }, table = profileNumbers }
+
+return {
+ read = 150, -- MSP_STATUS_EX
+ write = 210, -- MSP_SELECT_SETTING
+ title = "Profiles",
+ reboot = false,
+ eepromWrite = true,
+ minBytes = 11,
+ labels = labels,
+ fields = fields,
+ pidProfile = 0,
+ postLoad = function(self)
+ local pidProfileCount = self.values[14]
+ self.fields[1].max = pidProfileCount - 1
+ self.pidProfile = self.fields[1].value
+ end,
+ preSave = function(self)
+ local value = 0
+ if self.fields[1].value ~= self.pidProfile then
+ value = self.fields[1].value
+ else
+ value = bit32.bor(self.fields[2].value, RATEPROFILE_MASK)
+ end
+ self.values = {}
+ self.values[1] = value
+ return self.values
+ end,
+}
diff --git a/src/SCRIPTS/BF/PAGES/pwm.lua b/src/SCRIPTS/BF/PAGES/pwm.lua
index 7cb40a4e..5a5c4258 100644
--- a/src/SCRIPTS/BF/PAGES/pwm.lua
+++ b/src/SCRIPTS/BF/PAGES/pwm.lua
@@ -1,9 +1,4 @@
-local template = loadScript(radio.templateHome.."pwm.lua")
-if template then
- template = template()
-else
- template = assert(loadScript(radio.templateHome.."default_template.lua"))()
-end
+local template = assert(loadScript(radio.template))()
local margin = template.margin
local indent = template.indent
local lineSpacing = template.lineSpacing
@@ -16,6 +11,12 @@ local inc = { x = function(val) x = x + val return x end, y = function(val) y =
local labels = {}
local fields = {}
+local gyroSampleRateKhz
+
+if apiVersion >= 1.043 then
+ gyroSampleRateKhz = assert(loadScript("BOARD_INFO/"..mcuId..".lua"))().gyroSampleRateHz / 1000
+end
+
local escProtocols = { [0] = "PWM", "OS125", "OS42", "MSHOT" }
if apiVersion >= 1.020 then
@@ -37,23 +38,24 @@ if apiVersion >= 1.043 then
escProtocols[#escProtocols + 1] = "DISABLED"
end
+labels[#labels + 1] = { t = "System Config", x = x, y = inc.y(lineSpacing) }
if apiVersion >= 1.031 and apiVersion <= 1.040 then
- fields[#fields + 1] = { t = "32kHz Sampling", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 9 }, table = { [0] = "OFF", "ON" }, upd = function(self) self.updateRateTables(self) end }
+ fields[#fields + 1] = { t = "32kHz Sampling", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 9 }, table = { [0] = "OFF", "ON" }, upd = function(self) self.updateRateTables(self) end }
end
-
-if apiVersion >= 1.016 then
- if apiVersion <= 1.042 then
- fields[#fields + 1] = { t = "Gyro Update", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 1, max = 32, vals = { 1 }, table = {}, upd = function(self) self.updatePidRateTable(self) end }
- fields[#fields + 1] = { t = "PID Loop", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 1, max = 16, vals = { 2 }, table = {} }
- end
- fields[#fields + 1] = { t = "Protocol", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = #escProtocols, vals = { 4 }, table = escProtocols }
- fields[#fields + 1] = { t = "Unsynced PWM", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 3 }, table = { [0] = "OFF", "ON" } }
- fields[#fields + 1] = { t = "PWM Frequency", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 200, max = 32000, vals = { 5, 6 }, }
+if apiVersion >= 1.043 then
+ fields[#fields + 1] = { t = "Gyro Update", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1, max = 32, vals = { 1 }, table = {}, upd = function(self) self.updatePidRateTable(self) end, mult = -1, ro = true }
+else
+ fields[#fields + 1] = { t = "Gyro Update", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1, max = 32, vals = { 1 }, table = {}, upd = function(self) self.updatePidRateTable(self) end, mult = -1 }
end
+fields[#fields + 1] = { t = "PID Loop", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1, max = 16, vals = { 2 }, table = {}, mult = -1 }
+labels[#labels + 1] = { t = "ESC/Motor", x = x, y = inc.y(lineSpacing) }
+fields[#fields + 1] = { t = "Protocol", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = #escProtocols, vals = { 4 }, table = escProtocols }
if apiVersion >= 1.031 then
- fields[#fields + 1] = { t = "Idle Throttle %", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 2000, vals = { 7, 8 }, scale = 100 }
+ fields[#fields + 1] = { t = "Idle Throttle %", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 2000, vals = { 7, 8 }, scale = 100 }
end
+fields[#fields + 1] = { t = "Unsynced PWM", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 3 }, table = { [0] = "OFF", "ON" } }
+fields[#fields + 1] = { t = "Frequency", x = x + indent*2, y = inc.y(lineSpacing), sp = x + sp, min = 200, max = 32000, vals = { 5, 6 }, }
return {
read = 90, -- MSP_ADVANCED_CONFIG
@@ -81,6 +83,7 @@ return {
end,
calculateGyroRates = function(self, baseRate)
local idx = self.getGyroDenomFieldIndex(self)
+ baseRate = gyroSampleRateKhz or baseRate
for i=1, 32 do
self.gyroRates[i] = baseRate/i
self.fields[idx].table[i] = string.format("%.2f",baseRate/i)
diff --git a/src/SCRIPTS/BF/PAGES/rates.lua b/src/SCRIPTS/BF/PAGES/rates.lua
index 6f348e6b..355674fb 100644
--- a/src/SCRIPTS/BF/PAGES/rates.lua
+++ b/src/SCRIPTS/BF/PAGES/rates.lua
@@ -1,9 +1,4 @@
-local template = loadScript(radio.templateHome.."rates.lua")
-if template then
- template = template()
-else
- template = assert(loadScript(radio.templateHome.."default_template.lua"))()
-end
+local template = assert(loadScript(radio.template))()
local margin = template.margin
local indent = template.indent
local lineSpacing = template.lineSpacing
@@ -66,6 +61,10 @@ if apiVersion >= 1.016 then
inc.y(lineSpacing*0.4)
end
+if apiVersion >= 1.043 then
+ fields[#fields + 1] = { t = "Rates Type", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 4, vals = { 23 }, table = { [0] = "BF", "RF", "KISS", "ACTUAL", "QUICK"}, postEdit = function(self) self.updateRatesType(self, true) end }
+end
+
if apiVersion >= 1.016 then
labels[#labels + 1] = { t = "Throttle", x = x, y = inc.y(lineSpacing) }
fields[#fields + 1] = { t = "Mid", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 100, vals = { 7 }, scale = 100 }
@@ -91,4 +90,49 @@ return {
minBytes = 12,
labels = labels,
fields = fields,
+ ratesType,
+ getRatesType = function(self)
+ for i = 1, #self.fields do
+ if self.fields[i].vals and self.fields[i].vals[1] == 23 then
+ return self.fields[i].table[self.fields[i].value]
+ end
+ end
+ end,
+ updateRatesType = function(self, applyDefaults)
+ local ratesTable = assert(loadScript("RATETABLES/"..self.getRatesType(self)..".lua"))()
+ for i = 1, #ratesTable.labels do
+ self.labels[i].t = ratesTable.labels[i]
+ end
+ for i = 1, #ratesTable.fields do
+ for k, v in pairs(ratesTable.fields[i]) do
+ self.fields[i][k] = v
+ end
+ end
+ if applyDefaults and self.ratesType ~= self.getRatesType(self) then
+ for i = 1, #ratesTable.defaults do
+ local f = self.fields[i]
+ f.value = ratesTable.defaults[i]
+ for idx=1, #f.vals do
+ self.values[f.vals[idx]] = bit32.rshift(math.floor(f.value*(f.scale or 1) + 0.5), (idx-1)*8)
+ end
+ end
+ else
+ for i = 1, 9 do
+ local f = self.fields[i]
+ f.value = 0
+ for idx=1, #f.vals do
+ local raw_val = self.values[f.vals[idx]] or 0
+ raw_val = bit32.lshift(raw_val, (idx-1)*8)
+ f.value = bit32.bor(f.value, raw_val)
+ end
+ f.value = f.value/(f.scale or 1)
+ end
+ end
+ self.ratesType = self.getRatesType(self)
+ end,
+ postLoad = function(self)
+ if apiVersion >= 1.043 then
+ self.updateRatesType(self)
+ end
+ end,
}
diff --git a/src/SCRIPTS/BF/PAGES/rescue.lua b/src/SCRIPTS/BF/PAGES/rescue.lua
index ecc9785a..c3bc9a2b 100644
--- a/src/SCRIPTS/BF/PAGES/rescue.lua
+++ b/src/SCRIPTS/BF/PAGES/rescue.lua
@@ -1,9 +1,4 @@
-local template = loadScript(radio.templateHome.."rescue.lua")
-if template then
- template = template()
-else
- template = assert(loadScript(radio.templateHome.."default_template.lua"))()
-end
+local template = assert(loadScript(radio.template))()
local margin = template.margin
local indent = template.indent
local lineSpacing = template.lineSpacing
@@ -24,7 +19,10 @@ if apiVersion >= 1.041 then
fields[#fields + 1] = { t = "Ground Speed", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 30, max = 3000, vals = { 7, 8 } }
if apiVersion >= 1.043 then
+ fields[#fields + 1] = { t = "Ascend Rate", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 100, max = 2500, vals = { 17, 18 }, scale = 100 }
+ fields[#fields + 1] = { t = "Descend Rate", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 100, max = 500, vals = { 19, 20 }, scale = 100 }
fields[#fields + 1] = { t = "Arm w/o fix", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 21 }, table = { [0]="OFF","ON"} }
+ fields[#fields + 1] = { t = "Altitude Mode",x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 2, vals = { 22 }, table = { [0]="Maximum", "Fixed", "Current"} }
end
fields[#fields + 1] = { t = "Sanity Check", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 2, vals = { 15 }, table = { [0]="OFF","ON","FS_ONLY"} }
@@ -32,6 +30,10 @@ if apiVersion >= 1.041 then
fields[#fields + 1] = { t = "Min", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1000, max = 2000, vals = { 9, 10 } }
fields[#fields + 1] = { t = "Hover", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1000, max = 2000, vals = { 13, 14 } }
fields[#fields + 1] = { t = "Max", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1000, max = 2000, vals = { 11, 12 } }
+
+ if apiVersion >= 1.044 then
+ fields[#fields + 1] = { t = "Min Dth", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 50, max = 1000, vals = { 23, 24 } }
+ end
end
return {
diff --git a/src/SCRIPTS/BF/PAGES/rx.lua b/src/SCRIPTS/BF/PAGES/rx.lua
index f9939b5e..8c6cd8f8 100644
--- a/src/SCRIPTS/BF/PAGES/rx.lua
+++ b/src/SCRIPTS/BF/PAGES/rx.lua
@@ -1,9 +1,4 @@
-local template = loadScript(radio.templateHome.."rx.lua")
-if template then
- template = template()
-else
- template = assert(loadScript(radio.templateHome.."default_template.lua"))()
-end
+local template = assert(loadScript(radio.template))()
local margin = template.margin
local indent = template.indent
local lineSpacing = template.lineSpacing
@@ -17,19 +12,45 @@ local labels = {}
local fields = {}
if apiVersion >= 1.016 then
- labels[#labels + 1] = { t = "Stick", x = x, y = inc.y(lineSpacing) }
- fields[#fields + 1] = { t = "Low", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1000, max = 2000, vals = { 6, 7 } }
- fields[#fields + 1] = { t = "Center", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1000, max = 2000, vals = { 4, 5 } }
- fields[#fields + 1] = { t = "High", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1000, max = 2000, vals = { 2, 3 } }
+ labels[#labels + 1] = { t = "Stick", x = x, y = inc.y(lineSpacing) }
+ fields[#fields + 1] = { t = "Low", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1000, max = 2000, vals = { 6, 7 } }
+ fields[#fields + 1] = { t = "Center", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1000, max = 2000, vals = { 4, 5 } }
+ fields[#fields + 1] = { t = "High", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1000, max = 2000, vals = { 2, 3 } }
end
-if apiVersion >= 1.020 then
- fields[#fields + 1] = { t = "Interp", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 3, vals = { 13 }, table={ [0]="Off", "Preset", "Auto", "Manual"} }
- fields[#fields + 1] = { t = "Interp Int", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 1, max = 50, vals = { 14 } }
+if apiVersion >= 1.044 then
+ labels[#labels + 1] = { t = "RC Smoothing", x = x, y = inc.y(lineSpacing) }
+ fields[#fields + 1] = { t = "Mode", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 25 }, table = { [0] = "ON", "OFF" } }
+ labels[#labels + 1] = { t = "Cutoffs", x = x + indent, y = inc.y(lineSpacing) }
+ fields[#fields + 1] = { t = "Setpoint", x = x + indent*2, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 255, vals = { 26 }, table = { [0] = "Auto" } }
+ fields[#fields + 1] = { t = "Feedforward", x = x + indent*2, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 255, vals = { 27 }, table = { [0] = "Auto" } }
+ labels[#labels + 1] = { t = "Auto Smoothness", x = x + indent, y = inc.y(lineSpacing) }
+ fields[#fields + 1] = { t = "Setpoint", x = x + indent*2, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 250, vals = { 31 } }
+else
+ if apiVersion >= 1.040 then
+ labels[#labels + 1] = { t = "RC Smoothing", x = x, y = inc.y(lineSpacing) }
+ fields[#fields + 1] = { t = "Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 25 }, table = { [0] = "Interpolation", "Filter" } }
+ fields[#fields + 1] = { t = "Channels", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 4, vals = { 24 }, table = { [0] = "RP", "RPY", "RPYT", "T", "RT" } }
+ labels[#labels + 1] = { t = "Input Filter", x = x, y = inc.y(lineSpacing) }
+ fields[#fields + 1] = { t = "Cutoff", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 255, vals = { 26 }, table = { [0] = "Auto" } }
+ fields[#fields + 1] = { t = "Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 28 }, table = { [0] = "PT1", "BIQUAD"} }
+ labels[#labels + 1] = { t = "Derivative Filter", x = x, y = inc.y(lineSpacing) }
+ fields[#fields + 1] = { t = "Cutoff", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 255, vals = { 27 }, table = { [0] = "Auto" } }
+ fields[#fields + 1] = { t = "Type", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 3, vals = { 29 }, table = { [0] = "Off", "PT1", "BIQUAD", "Auto"} }
+ end
+
+ if apiVersion >= 1.020 then
+ fields[#fields + 1] = { t = "Interpolation", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 3, vals = { 13 }, table={ [0]="Off", "Preset", "Auto", "Manual"} }
+ fields[#fields + 1] = { t = "Interval", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 1, max = 50, vals = { 14 } }
+ end
+
+ if apiVersion >= 1.042 then
+ fields[#fields + 1] = { t = "Auto Smoothness", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 50, vals = { 31 } }
+ end
end
if apiVersion >= 1.031 then
- fields[#fields + 1] = { t = "Cam Angle", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 90, vals = { 23 } }
+ fields[#fields + 1] = { t = "Cam Angle", x = x, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 90, vals = { 23 } }
end
return {
diff --git a/src/SCRIPTS/BF/PAGES/simplified_tuning.lua b/src/SCRIPTS/BF/PAGES/simplified_tuning.lua
new file mode 100644
index 00000000..addaf165
--- /dev/null
+++ b/src/SCRIPTS/BF/PAGES/simplified_tuning.lua
@@ -0,0 +1,40 @@
+local template = assert(loadScript(radio.template))()
+local margin = template.margin
+local indent = template.indent
+local lineSpacing = template.lineSpacing
+local tableSpacing = template.tableSpacing
+local sp = template.listSpacing.field
+local yMinLim = radio.yMinLimit
+local x = margin
+local y = yMinLim - lineSpacing
+local inc = { x = function(val) x = x + val return x end, y = function(val) y = y + val return y end }
+local labels = {}
+local fields = {}
+
+labels[#labels + 1] = { t = "Simplified PID", x = x, y = inc.y(lineSpacing) }
+fields[#fields + 1] = { t = "PID Tuning", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 2, vals = { 1 }, table = { [0] = "OFF", "RP", "RPY" } }
+fields[#fields + 1] = { t = "D Gains", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 200, vals = { 5 }, scale = 100, mult = 5 }
+fields[#fields + 1] = { t = "P&I Gains", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 200, vals = { 6 }, scale = 100, mult = 5 }
+fields[#fields + 1] = { t = "FF Gains", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 200, vals = { 8 }, scale = 100, mult = 5 }
+fields[#fields + 1] = { t = "D Max", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 200, vals = { 7 }, scale = 100, mult = 5 }
+fields[#fields + 1] = { t = "I Gains", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 200, vals = { 4 }, scale = 100, mult = 5 }
+fields[#fields + 1] = { t = "Pitch:Roll D", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 200, vals = { 3 }, scale = 100, mult = 5 }
+fields[#fields + 1] = { t = "Pitch:Roll P,I&FF", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 200, vals = { 9 }, scale = 100, mult = 5 }
+fields[#fields + 1] = { t = "Master Multiplier", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 200, vals = { 2 }, scale = 100, mult = 5 }
+
+labels[#labels + 1] = { t = "Simplified Filter", x = x, y = inc.y(lineSpacing) }
+fields[#fields + 1] = { t = "Gyro Tuning", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 36 }, table = { [0] = "OFF", "ON" } }
+fields[#fields + 1] = { t = "Gyro Multiplier", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 10, max = 200, vals = { 37 }, scale = 100, mult = 5 }
+fields[#fields + 1] = { t = "D Tuning", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 0, max = 1, vals = { 18 }, table = { [0] = "OFF", "ON" } }
+fields[#fields + 1] = { t = "D Multiplier", x = x + indent, y = inc.y(lineSpacing), sp = x + sp, min = 10, max = 200, vals = { 19 }, scale = 100, mult = 5 }
+
+return {
+ read = 140, -- MSP_SIMPLIFIED_TUNING
+ write = 141, -- MSP_SET_SIMPLIFIED_TUNING
+ title = "Simplified Tuning",
+ reboot = false,
+ eepromWrite = true,
+ minBytes = 53,
+ labels = labels,
+ fields = fields,
+}
diff --git a/src/SCRIPTS/BF/PAGES/vtx.lua b/src/SCRIPTS/BF/PAGES/vtx.lua
index dc2168d5..73a035e5 100644
--- a/src/SCRIPTS/BF/PAGES/vtx.lua
+++ b/src/SCRIPTS/BF/PAGES/vtx.lua
@@ -1,18 +1,4 @@
-local md = model.getInfo();
-local vtx_tables = loadScript("/BF/VTX/"..md.name..".lua")
-if vtx_tables then
- vtx_tables = vtx_tables()
-else
- vtx_tables = assert(loadScript("/BF/VTX/vtx_defaults.lua"))()
-end
-local deviceTable = { [1]="6705", [3]="SA", [4]="Tramp", [255]="None" }
-local pitModeTable = { [0]="OFF", "ON" }
-local template = loadScript(radio.templateHome.."vtx.lua")
-if template then
- template = template()
-else
- template = assert(loadScript(radio.templateHome.."default_template.lua"))()
-end
+local template = assert(loadScript(radio.template))()
local margin = template.margin
local indent = template.indent
local lineSpacing = template.lineSpacing
@@ -25,6 +11,15 @@ local inc = { x = function(val) x = x + val return x end, y = function(val) y =
local labels = {}
local fields = {}
+local vtx_tables
+if apiVersion >= 1.042 then
+ vtx_tables = assert(loadScript("VTX_TABLES/"..mcuId..".lua"))()
+else
+ vtx_tables = assert(loadScript("VTX_TABLES/vtx_defaults.lua"))()
+end
+local deviceTable = { [1]="6705", [3]="SA", [4]="Tramp", [255]="None" }
+local pitModeTable = { [0]="OFF", "ON" }
+
if apiVersion >= 1.036 then
fields[#fields + 1] = { t = "Band", x = x, y = inc.y(lineSpacing), sp = x + sp, min=0, max=#(vtx_tables.bandTable), vals = { 2 }, table = vtx_tables.bandTable, upd = function(self) self.handleBandChanUpdate(self) end }
fields[#fields + 1] = { t = "Channel", x = x, y = inc.y(lineSpacing), sp = x + sp, min=1, max=vtx_tables.frequenciesPerBand, vals = { 3 }, upd = function(self) self.handleBandChanUpdate(self) end }
diff --git a/src/SCRIPTS/BF/RATETABLES/ACTUAL.lua b/src/SCRIPTS/BF/RATETABLES/ACTUAL.lua
new file mode 100644
index 00000000..42bf533d
--- /dev/null
+++ b/src/SCRIPTS/BF/RATETABLES/ACTUAL.lua
@@ -0,0 +1,15 @@
+return {
+ labels = { "", "", "ROLL", "PITCH", "YAW", "Cntr", "Sens", "Max", "Rate", "", "Expo" },
+ fields = {
+ { min = 1, max = 200, scale = 0.1 },
+ { min = 1, max = 200, scale = 0.1 },
+ { min = 1, max = 200, scale = 0.1 },
+ { min = 0, max = 200, scale = 0.1 },
+ { min = 0, max = 200, scale = 0.1 },
+ { min = 0, max = 200, scale = 0.1 },
+ { min = 0, max = 100, scale = 100 },
+ { min = 0, max = 100, scale = 100 },
+ { min = 0, max = 100, scale = 100 }
+ },
+ defaults = { 200, 200, 200, 670, 670, 670, 0.54, 0.54, 0.54 }
+}
diff --git a/src/SCRIPTS/BF/RATETABLES/BF.lua b/src/SCRIPTS/BF/RATETABLES/BF.lua
new file mode 100644
index 00000000..343d6df3
--- /dev/null
+++ b/src/SCRIPTS/BF/RATETABLES/BF.lua
@@ -0,0 +1,15 @@
+return {
+ labels = { "", "", "ROLL", "PITCH", "YAW", "RC", "Rate", "Super", "Rate", "RC", "Expo" },
+ fields = {
+ { min = 0, max = 255, scale = 100 },
+ { min = 0, max = 255, scale = 100 },
+ { min = 0, max = 255, scale = 100 },
+ { min = 0, max = 100, scale = 100 },
+ { min = 0, max = 100, scale = 100 },
+ { min = 0, max = 255, scale = 100 },
+ { min = 0, max = 100, scale = 100 },
+ { min = 0, max = 100, scale = 100 },
+ { min = 0, max = 100, scale = 100 }
+ },
+ defaults = { 1.0, 1.0, 1.0, 0.7, 0.7, 0.7, 0.0, 0.0, 0.0 }
+}
diff --git a/src/SCRIPTS/BF/RATETABLES/KISS.lua b/src/SCRIPTS/BF/RATETABLES/KISS.lua
new file mode 100644
index 00000000..f365f270
--- /dev/null
+++ b/src/SCRIPTS/BF/RATETABLES/KISS.lua
@@ -0,0 +1,15 @@
+return {
+ labels = { "", "", "ROLL", "PITCH", "YAW", "RC", "Rate", "", "Rate", "RC", "Curve" },
+ fields = {
+ { min = 1, max = 255, scale = 100 },
+ { min = 1, max = 255, scale = 100 },
+ { min = 1, max = 255, scale = 100 },
+ { min = 0, max = 99, scale = 100 },
+ { min = 0, max = 99, scale = 100 },
+ { min = 0, max = 99, scale = 100 },
+ { min = 0, max = 100, scale = 100 },
+ { min = 0, max = 100, scale = 100 },
+ { min = 0, max = 100, scale = 100 }
+ },
+ defaults = { 1.0, 1.0, 1.0, 0.7, 0.7, 0.7, 0.0, 0.0, 0.0 }
+}
diff --git a/src/SCRIPTS/BF/RATETABLES/QUICK.lua b/src/SCRIPTS/BF/RATETABLES/QUICK.lua
new file mode 100644
index 00000000..367eeef0
--- /dev/null
+++ b/src/SCRIPTS/BF/RATETABLES/QUICK.lua
@@ -0,0 +1,15 @@
+return {
+ labels = { "", "", "ROLL", "PITCH", "YAW", "RC", "Rate", "Max", "Rate", "", "Expo" },
+ fields = {
+ { min = 1, max = 255, scale = 100 },
+ { min = 1, max = 255, scale = 100 },
+ { min = 1, max = 255, scale = 100 },
+ { min = 0, max = 200, scale = 0.1 },
+ { min = 0, max = 200, scale = 0.1 },
+ { min = 0, max = 200, scale = 0.1 },
+ { min = 0, max = 100, scale = 100 },
+ { min = 0, max = 100, scale = 100 },
+ { min = 0, max = 100, scale = 100 }
+ },
+ defaults = { 1.0, 1.0, 1.0, 670, 670, 670, 0.0, 0.0, 0.0 }
+}
diff --git a/src/SCRIPTS/BF/RATETABLES/RF.lua b/src/SCRIPTS/BF/RATETABLES/RF.lua
new file mode 100644
index 00000000..12f74f36
--- /dev/null
+++ b/src/SCRIPTS/BF/RATETABLES/RF.lua
@@ -0,0 +1,15 @@
+return {
+ labels = { "", "", "ROLL", "PITCH", "YAW", "", "Rate", "", "Acro+", "", "Expo" },
+ fields = {
+ { min = 1, max = 200, scale = 0.1 },
+ { min = 1, max = 200, scale = 0.1 },
+ { min = 1, max = 200, scale = 0.1 },
+ { min = 0, max = 100, scale = 1 },
+ { min = 0, max = 100, scale = 1 },
+ { min = 0, max = 100, scale = 1 },
+ { min = 0, max = 100, scale = 1 },
+ { min = 0, max = 100, scale = 1 },
+ { min = 0, max = 100, scale = 1 }
+ },
+ defaults = { 370, 370, 370, 80, 80, 80, 50, 50, 50 }
+}
diff --git a/src/SCRIPTS/BF/TEMPLATES/128x64/default_template.lua b/src/SCRIPTS/BF/TEMPLATES/128x64.lua
similarity index 100%
rename from src/SCRIPTS/BF/TEMPLATES/128x64/default_template.lua
rename to src/SCRIPTS/BF/TEMPLATES/128x64.lua
diff --git a/src/SCRIPTS/BF/TEMPLATES/212x64/default_template.lua b/src/SCRIPTS/BF/TEMPLATES/128x96.lua
similarity index 100%
rename from src/SCRIPTS/BF/TEMPLATES/212x64/default_template.lua
rename to src/SCRIPTS/BF/TEMPLATES/128x96.lua
diff --git a/src/SCRIPTS/BF/TEMPLATES/212x64.lua b/src/SCRIPTS/BF/TEMPLATES/212x64.lua
new file mode 100644
index 00000000..76e110f0
--- /dev/null
+++ b/src/SCRIPTS/BF/TEMPLATES/212x64.lua
@@ -0,0 +1,7 @@
+return {
+ margin = 2,
+ indent = 6,
+ lineSpacing = 8,
+ listSpacing = { line = 8, field = 88 },
+ tableSpacing = { row = 10, col = 30, header = 8 },
+}
diff --git a/src/SCRIPTS/BF/TEMPLATES/320x480/default_template.lua b/src/SCRIPTS/BF/TEMPLATES/320x480.lua
similarity index 100%
rename from src/SCRIPTS/BF/TEMPLATES/320x480/default_template.lua
rename to src/SCRIPTS/BF/TEMPLATES/320x480.lua
diff --git a/src/SCRIPTS/BF/TEMPLATES/480x272/default_template.lua b/src/SCRIPTS/BF/TEMPLATES/480x272.lua
similarity index 100%
rename from src/SCRIPTS/BF/TEMPLATES/480x272/default_template.lua
rename to src/SCRIPTS/BF/TEMPLATES/480x272.lua
diff --git a/src/BF/VTX/vtx_defaults.lua b/src/SCRIPTS/BF/VTX_TABLES/vtx_defaults.lua
similarity index 100%
rename from src/BF/VTX/vtx_defaults.lua
rename to src/SCRIPTS/BF/VTX_TABLES/vtx_defaults.lua
diff --git a/src/SCRIPTS/BF/acc_cal.lua b/src/SCRIPTS/BF/acc_cal.lua
new file mode 100644
index 00000000..582d459c
--- /dev/null
+++ b/src/SCRIPTS/BF/acc_cal.lua
@@ -0,0 +1,24 @@
+local MSP_ACC_CALIBRATION = 205
+local accCalibrated = false
+local lastRunTS = 0
+local INTERVAL = 500
+
+local function processMspReply(cmd,rx_buf)
+ if cmd == MSP_ACC_CALIBRATION then
+ accCalibrated = true
+ end
+end
+
+local function accCal()
+ if lastRunTS == 0 or lastRunTS + INTERVAL < getTime() then
+ lastRunTS = getTime()
+ if not accCalibrated then
+ protocol.mspRead(MSP_ACC_CALIBRATION)
+ end
+ end
+ mspProcessTxQ()
+ processMspReply(mspPollReply())
+ return accCalibrated
+end
+
+return { f = accCal, t = "Calibrating Accelerometer" }
diff --git a/src/SCRIPTS/BF/api_version.lua b/src/SCRIPTS/BF/api_version.lua
new file mode 100644
index 00000000..366fa500
--- /dev/null
+++ b/src/SCRIPTS/BF/api_version.lua
@@ -0,0 +1,26 @@
+local MSP_API_VERSION = 1
+
+local apiVersionReceived = false
+local lastRunTS = 0
+local INTERVAL = 50
+
+local function processMspReply(cmd,rx_buf)
+ if cmd == MSP_API_VERSION and #rx_buf >= 3 then
+ apiVersion = rx_buf[2] + rx_buf[3] / 1000
+ apiVersionReceived = true
+ end
+end
+
+local function getApiVersion()
+ if lastRunTS == 0 or lastRunTS + INTERVAL < getTime() then
+ protocol.mspRead(MSP_API_VERSION)
+ lastRunTS = getTime()
+ end
+
+ mspProcessTxQ()
+ processMspReply(mspPollReply())
+
+ return apiVersionReceived
+end
+
+return { f = getApiVersion, t = "Waiting for API version" }
diff --git a/src/SCRIPTS/BF/background.lua b/src/SCRIPTS/BF/background.lua
index 203be3e7..239a5698 100644
--- a/src/SCRIPTS/BF/background.lua
+++ b/src/SCRIPTS/BF/background.lua
@@ -1,58 +1,41 @@
-local sensorId = -1
-local dataInitialised = false
-local data_init = nil
+local apiVersionReceived = false
+local timeIsSet = false
+local getApiVersion, setRtc, rssiTask
local rssiEnabled = true
-local rssiTask = nil
-
-local function getSensorValue()
- if sensorId == -1 then
- local sensor = getFieldInfo(protocol.stateSensor)
- if type(sensor) == "table" then
- sensorId = sensor['id'] or -1
- end
- end
- return getValue(sensorId)
-end
-
-local function modelActive(sensorValue)
- return type(sensorValue) == "number" and sensorValue > 0
-end
local function run_bg()
- local sensorValue = getSensorValue()
- if modelActive(sensorValue) then
+ if getRSSI() > 0 then
-- Send data when the telemetry connection is available
-- assuming when sensor value higher than 0 there is an telemetry connection
- if not dataInitialised then
- if not data_init then
- data_init = assert(loadScript("data_init.lua"))()
+ if not apiVersionReceived then
+ getApiVersion = getApiVersion or assert(loadScript("api_version.lua"))()
+ apiVersionReceived = getApiVersion.f()
+ if apiVersionReceived then
+ getApiVersion = nil
+ collectgarbage()
end
-
- dataInitialised = data_init()
-
- if dataInitialised then
- data_init = nil
-
+ elseif not timeIsSet then
+ setRtc = setRtc or assert(loadScript("rtc.lua"))()
+ timeIsSet = setRtc.f()
+ if timeIsSet then
+ setRtc = nil
collectgarbage()
end
elseif rssiEnabled and apiVersion >= 1.037 then
- if not rssiTask then
- rssiTask = assert(loadScript("rssi.lua"))()
- end
-
+ rssiTask = rssiTask or assert(loadScript("rssi.lua"))()
rssiEnabled = rssiTask()
-
if not rssiEnabled then
rssiTask = nil
-
collectgarbage()
end
end
else
- dataInitialised = false
+ apiVersionReceived = false
+ timeIsSet = false
rssiEnabled = true
- if data_init or rssiTask then
- data_init = nil
+ if getApiVersion or setRtc or rssiTask then
+ getApiVersion = nil
+ setRtc = nil
rssiTask = nil
collectgarbage()
end
diff --git a/src/SCRIPTS/BF/board_info.lua b/src/SCRIPTS/BF/board_info.lua
new file mode 100644
index 00000000..1fae01e5
--- /dev/null
+++ b/src/SCRIPTS/BF/board_info.lua
@@ -0,0 +1,137 @@
+local MSP_BOARD_INFO = 4
+
+local boardInfoReceived = false
+
+local boardIdentifier = ""
+local hardwareRevision = 0
+local boardType = 0
+local targetCapabilities = 0
+local targetName = ""
+local boardName = ""
+local manufacturerId = ""
+local signature = {}
+local mcuTypeId = 255
+local configurationState = 0
+local gyroSampleRateHz = 0
+local configurationProblems = 0
+local spiRegisteredDeviceCount = 0
+local i2cRegisteredDeviceCount = 0
+
+local lastRunTS = 0
+local INTERVAL = 100
+
+local function processMspReply(cmd, payload)
+ if cmd == MSP_BOARD_INFO then
+ local length
+ local i = 1
+ length = 4
+ for c = 1, 4 do
+ boardIdentifier = boardIdentifier..string.char(payload[i])
+ i = i + 1
+ end
+ for idx = 1, 2 do
+ local raw_val = bit32.lshift(payload[i], (idx-1)*8)
+ hardwareRevision = bit32.bor(hardwareRevision, raw_val)
+ i = i + 1
+ end
+ if apiVersion >= 1.035 then
+ boardType = payload[i]
+ end
+ i = i + 1
+ if apiVersion >= 1.037 then
+ targetCapabilities = payload[i]
+ i = i + 1
+ length = payload[i]
+ i = i + 1
+ for c = 1, length do
+ targetName = targetName..string.char(payload[i])
+ i = i + 1
+ end
+ end
+ if apiVersion >= 1.039 then
+ length = payload[i]
+ i = i + 1
+ for c = 1, length do
+ boardName = boardName..string.char(payload[i])
+ i = i + 1
+ end
+ length = payload[i]
+ i = i + 1
+ for c = 1, length do
+ manufacturerId = manufacturerId..string.char(payload[i])
+ i = i + 1
+ end
+ length = 32
+ for c = 1, 32 do
+ signature[#signature + 1] = payload[i]
+ i = i + 1
+ end
+ end
+ i = i + 1
+ if apiVersion >= 1.041 then
+ mcuTypeId = payload[i]
+ end
+ i = i + 1
+ if apiVersion >= 1.042 then
+ configurationState = payload[i]
+ end
+ if apiVersion >= 1.043 then
+ for idx = 1, 2 do
+ local raw_val = bit32.lshift(payload[i], (idx-1)*8)
+ gyroSampleRateHz = bit32.bor(gyroSampleRateHz, raw_val)
+ i = i + 1
+ end
+ for idx = 1, 4 do
+ local raw_val = bit32.lshift(payload[i], (idx-1)*8)
+ configurationProblems = bit32.bor(configurationProblems, raw_val)
+ i = i + 1
+ end
+ end
+ if apiVersion >= 1.044 then
+ spiRegisteredDeviceCount = payload[i]
+ i = i + 1
+ i2cRegisteredDeviceCount = payload[i]
+ end
+ boardInfoReceived = true
+ end
+end
+
+local function getBoardInfo()
+ if lastRunTS + INTERVAL < getTime() then
+ lastRunTS = getTime()
+ if not boardInfoReceived then
+ protocol.mspRead(MSP_BOARD_INFO)
+ end
+ end
+ mspProcessTxQ()
+ processMspReply(mspPollReply())
+ if boardInfoReceived then
+ local f = io.open("BOARD_INFO/"..mcuId..".lua", 'w')
+ io.write(f, "return {", "\n")
+ io.write(f, " boardIdentifier = "..'"'..boardIdentifier..'"'..",", "\n")
+ io.write(f, " hardwareRevision = "..tostring(hardwareRevision)..",", "\n")
+ io.write(f, " boardType = "..tostring(boardType)..",", "\n")
+ io.write(f, " targetCapabilities = "..tostring(targetCapabilities)..",", "\n")
+ io.write(f, " targetName = "..'"'..targetName..'"'..",", "\n")
+ io.write(f, " boardName = "..'"'..boardName..'"'..",", "\n")
+ io.write(f, " manufacturerId = "..'"'..manufacturerId..'"'..",", "\n")
+ local signatureString = " signature = { "
+ for i = 1, #signature do
+ signatureString = signatureString..tostring(signature[i])..", "
+ end
+ signatureString = signatureString.."},"
+ io.write(f, signatureString, "\n")
+ io.write(f, " mcuTypeId = "..tostring(mcuTypeId)..",", "\n")
+ io.write(f, " configurationState = "..tostring(configurationState)..",", "\n")
+ io.write(f, " gyroSampleRateHz = "..tostring(gyroSampleRateHz)..",", "\n")
+ io.write(f, " configurationProblems = "..tostring(configurationProblems)..",", "\n")
+ io.write(f, " spiRegisteredDeviceCount = "..tostring(spiRegisteredDeviceCount)..",", "\n")
+ io.write(f, " i2cRegisteredDeviceCount = "..tostring(i2cRegisteredDeviceCount)..",", "\n")
+ io.write(f, "}", "\n")
+ io.close(f)
+ assert(loadScript("BOARD_INFO/"..mcuId..".lua", 'c'))
+ end
+ return boardInfoReceived
+end
+
+return { f = getBoardInfo, t = "Downloading board info" }
diff --git a/src/SCRIPTS/BF/cms.lua b/src/SCRIPTS/BF/cms.lua
new file mode 100644
index 00000000..fdb5752c
--- /dev/null
+++ b/src/SCRIPTS/BF/cms.lua
@@ -0,0 +1,35 @@
+local lastMenuEventTime = 0
+local INTERVAL = 80
+
+local function init()
+ cms.init(radio)
+end
+
+local function stickMovement()
+ local threshold = 30
+ return math.abs(getValue('ele')) > threshold or math.abs(getValue('ail')) > threshold or math.abs(getValue('rud')) > threshold
+end
+
+local function run(event)
+ cms.update()
+ if cms.menuOpen == false then
+ cms.open()
+ end
+ if event == radio.refresh.event then
+ cms.synced = false
+ lastMenuEventTime = 0
+ elseif stickMovement() then
+ cms.synced = false
+ lastMenuEventTime = getTime()
+ elseif event == EVT_VIRTUAL_EXIT then
+ cms.close()
+ return 1
+ end
+ if lastMenuEventTime + INTERVAL < getTime() and not cms.synced then
+ lastMenuEventTime = getTime()
+ cms.refresh()
+ end
+ return 0
+end
+
+return { init=init, run=run }
diff --git a/src/SCRIPTS/BF/data_init.lua b/src/SCRIPTS/BF/data_init.lua
deleted file mode 100644
index ae4da07f..00000000
--- a/src/SCRIPTS/BF/data_init.lua
+++ /dev/null
@@ -1,66 +0,0 @@
-local MSP_API_VERSION = 1
-local MSP_SET_RTC = 246
-
-local apiVersionReceived = false
-local timeIsSet = false
-local lastRunTS = 0
-local INTERVAL = 50
-
-local function processMspReply(cmd,rx_buf)
- if cmd == MSP_API_VERSION and #rx_buf >= 3 then
- apiVersion = rx_buf[2] + rx_buf[3] / 1000
-
- apiVersionReceived = true
- end
- if cmd == MSP_SET_RTC then
- timeIsSet = true
- end
-end
-
-local function init()
- if lastRunTS == 0 or lastRunTS + INTERVAL < getTime() then
- if not apiVersionReceived then
- protocol.mspRead(MSP_API_VERSION)
- elseif apiVersionReceived and not timeIsSet then
- -- only send datetime one time after telemetry connection became available
- -- or when connection is restored after e.g. lipo refresh
- local values = {}
- if apiVersion >= 1.041 then
- -- format: seconds after the epoch (32) / milliseconds (16)
- local now = getRtcTime()
-
- for i = 1, 4 do
- values[i] = bit32.band(now, 0xFF)
- now = bit32.rshift(now, 8)
- end
-
- values[5] = 0 -- we don't have milliseconds
- values[6] = 0
- else
- -- format: year (16) / month (8) / day (8) / hour (8) / min (8) / sec (8)
- local now = getDateTime()
- local year = now.year
-
- values[1] = bit32.band(year, 0xFF)
- year = bit32.rshift(year, 8)
- values[2] = bit32.band(year, 0xFF)
- values[3] = now.mon
- values[4] = now.day
- values[5] = now.hour
- values[6] = now.min
- values[7] = now.sec
- end
-
- protocol.mspWrite(MSP_SET_RTC, values)
- end
- lastRunTS = getTime()
- end
-
- mspProcessTxQ()
-
- processMspReply(mspPollReply())
-
- return apiVersionReceived and timeIsSet
-end
-
-return init
diff --git a/src/SCRIPTS/BF/mcu_id.lua b/src/SCRIPTS/BF/mcu_id.lua
new file mode 100644
index 00000000..26d1e2ba
--- /dev/null
+++ b/src/SCRIPTS/BF/mcu_id.lua
@@ -0,0 +1,37 @@
+local MSP_UID = 160
+
+local MCUIdReceived = false
+
+local lastRunTS = 0
+local INTERVAL = 100
+
+local function processMspReply(cmd, payload)
+ if cmd == MSP_UID then
+ local i = 1
+ local id = ""
+ for j = 1, 3 do
+ local s = ""
+ for k = 1, 4 do
+ s = string.format("%02x", payload[i])..s
+ i = i + 1
+ end
+ id = id..s
+ end
+ mcuId = id
+ MCUIdReceived = true
+ end
+end
+
+local function getMCUId()
+ if lastRunTS + INTERVAL < getTime() then
+ lastRunTS = getTime()
+ if not MCUIdReceived then
+ protocol.mspRead(MSP_UID)
+ end
+ end
+ mspProcessTxQ()
+ processMspReply(mspPollReply())
+ return MCUIdReceived
+end
+
+return { f = getMCUId, t = "Waiting for device ID" }
diff --git a/src/SCRIPTS/BF/pages.lua b/src/SCRIPTS/BF/pages.lua
index 2fcdf6f8..68f95ee8 100644
--- a/src/SCRIPTS/BF/pages.lua
+++ b/src/SCRIPTS/BF/pages.lua
@@ -4,6 +4,10 @@ if apiVersion >= 1.036 then
PageFiles[#PageFiles + 1] = { title = "VTX Settings", script = "vtx.lua" }
end
+if apiVersion >= 1.016 then
+ PageFiles[#PageFiles + 1] = { title = "Profiles", script = "profiles.lua" }
+end
+
if apiVersion >= 1.016 then
PageFiles[#PageFiles + 1] = { title = "PIDs 1", script = "pids1.lua" }
end
@@ -20,6 +24,10 @@ if apiVersion >= 1.016 then
PageFiles[#PageFiles + 1] = { title = "Advanced PIDs", script = "pid_advanced.lua" }
end
+if apiVersion >= 1.044 then
+ PageFiles[#PageFiles + 1] = { title = "Simplified Tuning", script = "simplified_tuning.lua" }
+end
+
if apiVersion >= 1.016 then
PageFiles[#PageFiles + 1] = { title = "Filters 1", script = "filters1.lua" }
end
@@ -29,13 +37,17 @@ if apiVersion >= 1.042 then
end
if apiVersion >= 1.016 then
- PageFiles[#PageFiles + 1] = { title = "Gyro / Motor", script = "pwm.lua" }
+ PageFiles[#PageFiles + 1] = { title = "System / Motor", script = "pwm.lua" }
end
if apiVersion >= 1.016 then
PageFiles[#PageFiles + 1] = { title = "Receiver", script = "rx.lua" }
end
+if apiVersion >= 1.016 then
+ PageFiles[#PageFiles + 1] = { title = "Failsafe", script = "failsafe.lua" }
+end
+
if apiVersion >= 1.041 then
PageFiles[#PageFiles + 1] = { title = "GPS Rescue", script = "rescue.lua" }
end
diff --git a/src/SCRIPTS/BF/protocols.lua b/src/SCRIPTS/BF/protocols.lua
index d0c1951d..c415104c 100644
--- a/src/SCRIPTS/BF/protocols.lua
+++ b/src/SCRIPTS/BF/protocols.lua
@@ -2,25 +2,24 @@ local supportedProtocols =
{
smartPort =
{
- transport = "MSP/sp.lua",
- rssi = function() return getValue("RSSI") end,
- stateSensor = "Tmp1",
+ mspTransport = "MSP/sp.lua",
push = sportTelemetryPush,
maxTxBufferSize = 6,
maxRxBufferSize = 6,
saveMaxRetries = 2,
- saveTimeout = 500
+ saveTimeout = 500,
+ cms = {},
},
crsf =
{
- transport = "MSP/crsf.lua",
- rssi = function() return getValue("TQly") end,
- stateSensor = "1RSS",
+ mspTransport = "MSP/crsf.lua",
+ cmsTransport = "CMS/crsf.lua",
push = crossfireTelemetryPush,
maxTxBufferSize = 8,
maxRxBufferSize = 58,
saveMaxRetries = 2,
- saveTimeout = 150
+ saveTimeout = 150,
+ cms = {},
}
}
diff --git a/src/SCRIPTS/BF/radios.lua b/src/SCRIPTS/BF/radios.lua
index 6f200e4c..13eecaa8 100644
--- a/src/SCRIPTS/BF/radios.lua
+++ b/src/SCRIPTS/BF/radios.lua
@@ -2,45 +2,126 @@ local supportedRadios =
{
["128x64"] =
{
- templateHome = "TEMPLATES/128x64/",
- MenuBox = { x=15, y=12, w=100, x_offset=36, h_line=8, h_offset=3 },
- SaveBox = { x=15, y=12, w=100, x_offset=4, h=30, h_offset=5 },
- NoTelem = { 30, 55, "No Telemetry", BLINK },
- textSize = SMLSIZE,
- yMinLimit = 12,
- yMaxLimit = 52,
+ msp = {
+ template = "TEMPLATES/128x64.lua",
+ MenuBox = { x=15, y=12, w=100, x_offset=36, h_line=8, h_offset=3 },
+ SaveBox = { x=15, y=12, w=100, x_offset=4, h=30, h_offset=5 },
+ NoTelem = { 30, 55, "No Telemetry", BLINK },
+ textSize = SMLSIZE,
+ yMinLimit = 12,
+ yMaxLimit = 52,
+ },
+ cms = {
+ rows = 8,
+ cols = 26,
+ pixelsPerRow = 8,
+ pixelsPerChar = 5,
+ xIndent = 0,
+ yOffset = 0,
+ textSize = SMLSIZE,
+ refresh = {
+ event = EVT_VIRTUAL_ENTER,
+ text = "Refresh: [ENT]",
+ top = 1,
+ left = 64,
+ },
+ },
+ },
+ ["128x96"] =
+ {
+ msp = {
+ template = "TEMPLATES/128x96.lua",
+ MenuBox = { x=15, y=12, w=100, x_offset=36, h_line=8, h_offset=3 },
+ SaveBox = { x=15, y=12, w=100, x_offset=4, h=30, h_offset=5 },
+ NoTelem = { 30, 87, "No Telemetry", BLINK },
+ textSize = SMLSIZE,
+ yMinLimit = 12,
+ yMaxLimit = 84,
+ },
+ cms = {
+ rows = 12,
+ cols = 26,
+ pixelsPerRow = 8,
+ pixelsPerChar = 5,
+ xIndent = 0,
+ yOffset = 0,
+ textSize = SMLSIZE,
+ refresh = {
+ event = EVT_VIRTUAL_ENTER,
+ text = "Refresh: [ENT]",
+ top = 1,
+ left = 64,
+ },
+ },
},
["212x64"] =
{
- templateHome = "TEMPLATES/212x64/",
- MenuBox = { x=40, y=12, w=120, x_offset=36, h_line=8, h_offset=3 },
- SaveBox = { x=40, y=12, w=120, x_offset=4, h=30, h_offset=5 },
- NoTelem = { 70, 55, "No Telemetry", BLINK },
- textSize = SMLSIZE,
- yMinLimit = 12,
- yMaxLimit = 52,
+ msp = {
+ template = "TEMPLATES/212x64.lua",
+ MenuBox = { x=40, y=12, w=120, x_offset=36, h_line=8, h_offset=3 },
+ SaveBox = { x=40, y=12, w=120, x_offset=4, h=30, h_offset=5 },
+ NoTelem = { 70, 55, "No Telemetry", BLINK },
+ textSize = SMLSIZE,
+ yMinLimit = 12,
+ yMaxLimit = 52,
+ },
+ cms = {
+ rows = 8,
+ cols = 32,
+ pixelsPerRow = 8,
+ pixelsPerChar = 6,
+ xIndent = 0,
+ yOffset = 0,
+ textSize = SMLSIZE,
+ refresh = {
+ event = EVT_VIRTUAL_INC,
+ text = "Refresh: [+]",
+ top = 1,
+ left = 156,
+ }
+ },
},
["480x272"] =
{
- templateHome = "TEMPLATES/480x272/",
- highRes = true,
- MenuBox = { x=120, y=100, w=200, x_offset=68, h_line=20, h_offset=6 },
- SaveBox = { x=120, y=100, w=180, x_offset=12, h=60, h_offset=12 },
- NoTelem = { 192, LCD_H - 28, "No Telemetry", (TEXT_COLOR or 0) + INVERS + BLINK },
- textSize = 0,
- yMinLimit = 35,
- yMaxLimit = 235,
+ msp = {
+ template = "TEMPLATES/480x272.lua",
+ highRes = true,
+ MenuBox = { x=120, y=100, w=200, x_offset=68, h_line=20, h_offset=6 },
+ SaveBox = { x=120, y=100, w=180, x_offset=12, h=60, h_offset=12 },
+ NoTelem = { 192, LCD_H - 28, "No Telemetry", (TEXT_COLOR or 0) + INVERS + BLINK },
+ textSize = 0,
+ yMinLimit = 35,
+ yMaxLimit = 235,
+ },
+ cms = {
+ rows = 9,
+ cols = 32,
+ pixelsPerRow = 24,
+ pixelsPerChar = 14,
+ xIndent = 14,
+ yOffset = 32,
+ textSize = MIDSIZE,
+ refresh = {
+ event = EVT_VIRTUAL_ENTER,
+ text = "Refresh: [ENT]",
+ top = 1,
+ left = 300,
+ }
+ },
},
["320x480"] =
{
- templateHome = "TEMPLATES/320x480/",
- highRes = true,
- MenuBox = { x= (LCD_W -200)/2, y=LCD_H/2, w=200, x_offset=68, h_line=20, h_offset=6 },
- SaveBox = { x= (LCD_W -200)/2, y=LCD_H/2, w=180, x_offset=12, h=60, h_offset=12 },
- NoTelem = { LCD_W/2 - 50, LCD_H - 28, "No Telemetry", (TEXT_COLOR or 0) + INVERS + BLINK },
- textSize = 0,
- yMinLimit = 35,
- yMaxLimit = 435,
+ msp = {
+ template = "TEMPLATES/320x480.lua",
+ highRes = true,
+ MenuBox = { x= (LCD_W -200)/2, y=LCD_H/2, w=200, x_offset=68, h_line=20, h_offset=6 },
+ SaveBox = { x= (LCD_W -200)/2, y=LCD_H/2, w=180, x_offset=12, h=60, h_offset=12 },
+ NoTelem = { LCD_W/2 - 50, LCD_H - 28, "No Telemetry", (TEXT_COLOR or 0) + INVERS + BLINK },
+ textSize = 0,
+ yMinLimit = 35,
+ yMaxLimit = 435,
+ },
+ cms = nil,
},
}
diff --git a/src/SCRIPTS/BF/rtc.lua b/src/SCRIPTS/BF/rtc.lua
new file mode 100644
index 00000000..955c91e9
--- /dev/null
+++ b/src/SCRIPTS/BF/rtc.lua
@@ -0,0 +1,54 @@
+local MSP_SET_RTC = 246
+
+local timeIsSet = false
+local lastRunTS = 0
+local INTERVAL = 50
+
+local function processMspReply(cmd,rx_buf)
+ if cmd == MSP_SET_RTC then
+ timeIsSet = true
+ end
+end
+
+local function setRtc()
+ if lastRunTS == 0 or lastRunTS + INTERVAL < getTime() then
+ -- only send datetime one time after telemetry connection became available
+ -- or when connection is restored after e.g. lipo refresh
+ local values = {}
+ if apiVersion >= 1.041 then
+ -- format: seconds after the epoch (32) / milliseconds (16)
+ local now = getRtcTime()
+
+ for i = 1, 4 do
+ values[i] = bit32.band(now, 0xFF)
+ now = bit32.rshift(now, 8)
+ end
+
+ values[5] = 0 -- we don't have milliseconds
+ values[6] = 0
+ else
+ -- format: year (16) / month (8) / day (8) / hour (8) / min (8) / sec (8)
+ local now = getDateTime()
+ local year = now.year
+
+ values[1] = bit32.band(year, 0xFF)
+ year = bit32.rshift(year, 8)
+ values[2] = bit32.band(year, 0xFF)
+ values[3] = now.mon
+ values[4] = now.day
+ values[5] = now.hour
+ values[6] = now.min
+ values[7] = now.sec
+ end
+
+ protocol.mspWrite(MSP_SET_RTC, values)
+ lastRunTS = getTime()
+ end
+
+ mspProcessTxQ()
+ processMspReply(mspPollReply())
+
+ return timeIsSet
+end
+
+return { f = setRtc, t = "" }
diff --git a/src/SCRIPTS/BF/ui.lua b/src/SCRIPTS/BF/ui.lua
index c65dfd09..01d6e6e1 100644
--- a/src/SCRIPTS/BF/ui.lua
+++ b/src/SCRIPTS/BF/ui.lua
@@ -1,25 +1,26 @@
local uiStatus =
{
init = 1,
- pages = 2,
- mainMenu = 3,
+ mainMenu = 2,
+ pages = 3,
+ confirm = 4,
}
local pageStatus =
{
- display = 2,
- editing = 3,
- saving = 4,
- popupMenu = 5,
+ display = 1,
+ editing = 2,
+ saving = 3,
}
local uiMsp =
{
reboot = 68,
- eepromWrite = 250
+ eepromWrite = 250,
}
local uiState = uiStatus.init
+local prevUiState
local pageState = pageStatus.display
local requestTimeout = 80
local currentPage = 1
@@ -32,7 +33,7 @@ local popupMenuActive = 1
local killEnterBreak = 0
local pageScrollY = 0
local mainMenuScrollY = 0
-local PageFiles, Page, init, popupMenuList
+local PageFiles, Page, init, popupMenu
local backgroundFill = TEXT_BGCOLOR or ERASE
local foregroundColor = LINE_COLOR or SOLID
@@ -72,22 +73,26 @@ local function eepromWrite()
protocol.mspRead(uiMsp.eepromWrite)
end
-local function getVtxTables()
- uiState = uiStatus.init
- PageFiles = nil
+local function confirm(page)
+ prevUiState = uiState
+ uiState = uiStatus.confirm
invalidatePages()
- io.close(io.open("/BF/VTX/"..model.getInfo().name..".lua", 'w'))
- return 0
+ currentField = 1
+ Page = assert(loadScript(page))()
+ collectgarbage()
end
local function createPopupMenu()
- popupMenuList = {
- { t = "save page", f = saveSettings },
- { t = "reload", f = invalidatePages },
- { t = "reboot", f = rebootFc },
- }
+ popupMenuActive = 1
+ popupMenu = {}
+ if uiState == uiStatus.pages then
+ popupMenu[#popupMenu + 1] = { t = "save page", f = saveSettings }
+ popupMenu[#popupMenu + 1] = { t = "reload", f = invalidatePages }
+ end
+ popupMenu[#popupMenu + 1] = { t = "reboot", f = rebootFc }
+ popupMenu[#popupMenu + 1] = { t = "acc cal", f = function() confirm("CONFIRM/acc_cal.lua") end }
if apiVersion >= 1.042 then
- popupMenuList[#popupMenuList + 1] = { t = "vtx tables", f = getVtxTables }
+ popupMenu[#popupMenu + 1] = { t = "vtx tables", f = function() confirm("CONFIRM/vtx_tables.lua") end }
end
end
@@ -154,7 +159,7 @@ local function incMainMenu(inc)
end
local function incPopupMenu(inc)
- popupMenuActive = clipValue(popupMenuActive + inc, 1, #popupMenuList)
+ popupMenuActive = clipValue(popupMenuActive + inc, 1, #popupMenu)
end
local function requestPage()
@@ -169,7 +174,7 @@ local function drawScreenTitle(screenTitle)
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
lcd.drawText(5,5,screenTitle, MENU_TITLE_COLOR)
else
- lcd.drawFilledRectangle(0, 0, LCD_W, 10)
+ lcd.drawFilledRectangle(0, 0, LCD_W, 10, FORCE)
lcd.drawText(1,1,screenTitle,INVERS)
end
end
@@ -179,7 +184,6 @@ local function drawScreen()
local yMaxLim = radio.yMaxLimit
local currentFieldY = Page.fields[currentField].y
local textOptions = radio.textSize + globalTextOptions
- drawScreenTitle("Betaflight / "..Page.title)
if currentFieldY <= Page.fields[1].y then
pageScrollY = 0
elseif currentFieldY - pageScrollY <= yMinLim then
@@ -190,7 +194,7 @@ local function drawScreen()
for i=1,#Page.labels do
local f = Page.labels[i]
local y = f.y - pageScrollY
- if y >= yMinLim and y <= yMaxLim then
+ if y >= 0 and y <= LCD_H then
lcd.drawText(f.x, y, f.t, textOptions)
end
end
@@ -214,13 +218,14 @@ local function drawScreen()
end
end
local y = f.y - pageScrollY
- if y >= yMinLim and y <= yMaxLim then
+ if y >= 0 and y <= LCD_H then
if f.t then
lcd.drawText(f.x, y, f.t, textOptions)
end
lcd.drawText(f.sp or f.x, y, val, valueOptions)
end
end
+ drawScreenTitle("Betaflight / "..Page.title)
end
local function incValue(inc)
@@ -243,13 +248,13 @@ local function drawPopupMenu()
local w = radio.MenuBox.w
local h_line = radio.MenuBox.h_line
local h_offset = radio.MenuBox.h_offset
- local h = #popupMenuList * h_line + h_offset*2
+ local h = #popupMenu * h_line + h_offset*2
lcd.drawFilledRectangle(x,y,w,h,backgroundFill)
lcd.drawRectangle(x,y,w-1,h-1,foregroundColor)
lcd.drawText(x+h_line/2,y+h_offset,"Menu:",globalTextOptions)
- for i,e in ipairs(popupMenuList) do
+ for i,e in ipairs(popupMenu) do
local textOptions = globalTextOptions
if popupMenuActive == i then
textOptions = textOptions + INVERS
@@ -259,18 +264,35 @@ local function drawPopupMenu()
end
local function run_ui(event)
- if uiState == uiStatus.init then
+ if popupMenu then
+ drawPopupMenu()
+ if event == EVT_VIRTUAL_EXIT then
+ popupMenu = nil
+ 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
+ popupMenu[popupMenuActive].f()
+ popupMenu = nil
+ end
+ end
+ elseif uiState == uiStatus.init then
lcd.clear()
drawScreenTitle("Betaflight Config")
init = init or assert(loadScript("ui_init.lua"))()
- if not init() then
+ lcd.drawText(6, radio.yMinLimit, init.t)
+ if not init.f() then
return 0
end
init = nil
- createPopupMenu()
PageFiles = assert(loadScript("pages.lua"))()
invalidatePages()
- uiState = uiStatus.mainMenu
+ uiState = prevUiState or uiStatus.mainMenu
+ prevUiState = nil
elseif uiState == uiStatus.mainMenu then
if event == EVT_VIRTUAL_EXIT then
return 2
@@ -280,9 +302,11 @@ local function run_ui(event)
incMainMenu(-1)
elseif event == EVT_VIRTUAL_ENTER then
uiState = uiStatus.pages
+ elseif event == EVT_VIRTUAL_ENTER_LONG then
+ killEnterBreak = 1
+ createPopupMenu()
end
lcd.clear()
- drawScreenTitle("Betaflight Config")
local yMinLim = radio.yMinLimit
local yMaxLim = radio.yMaxLimit
local lineSpacing = 10
@@ -300,10 +324,11 @@ local function run_ui(event)
for i=1, #PageFiles do
local attr = currentPage == i and INVERS or 0
local y = (i-1)*lineSpacing + yMinLim - mainMenuScrollY
- if y >= yMinLim and y <= yMaxLim then
+ if y >= 0 and y <= LCD_H then
lcd.drawText(6, y, PageFiles[i].title, attr)
end
end
+ drawScreenTitle("Betaflight Config")
elseif uiState == uiStatus.pages then
if pageState == pageStatus.saving then
if saveTS + saveTimeout < getTime() then
@@ -314,21 +339,6 @@ local function run_ui(event)
invalidatePages()
end
end
- 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
- return popupMenuList[popupMenuActive].f() or 0
- end
- end
elseif pageState == pageStatus.display then
if event == EVT_VIRTUAL_PREV_PAGE then
incPage(-1)
@@ -347,9 +357,8 @@ local function run_ui(event)
end
end
elseif event == EVT_VIRTUAL_ENTER_LONG then
- popupMenuActive = 1
killEnterBreak = 1
- pageState = pageStatus.popupMenu
+ createPopupMenu()
elseif event == EVT_VIRTUAL_EXIT then
invalidatePages()
currentField = 1
@@ -358,6 +367,9 @@ local function run_ui(event)
end
elseif pageState == pageStatus.editing then
if event == EVT_VIRTUAL_EXIT or event == EVT_VIRTUAL_ENTER then
+ if Page.fields[currentField].postEdit then
+ Page.fields[currentField].postEdit(Page)
+ end
pageState = pageStatus.display
elseif event == EVT_VIRTUAL_INC or event == EVT_VIRTUAL_INC_REPT then
incValue(1)
@@ -366,7 +378,7 @@ local function run_ui(event)
end
end
if not Page then
- Page = assert(loadScript("Pages/"..PageFiles[currentPage].script))()
+ Page = assert(loadScript("PAGES/"..PageFiles[currentPage].script))()
collectgarbage()
end
if not Page.values and pageState == pageStatus.display then
@@ -374,9 +386,7 @@ local function run_ui(event)
end
lcd.clear()
drawScreen()
- if pageState == pageStatus.popupMenu then
- drawPopupMenu()
- elseif pageState == pageStatus.saving then
+ if pageState == pageStatus.saving then
local saveMsg = "Saving..."
if saveRetries > 0 then
saveMsg = "Retrying"
@@ -385,8 +395,20 @@ local function run_ui(event)
lcd.drawRectangle(radio.SaveBox.x,radio.SaveBox.y,radio.SaveBox.w,radio.SaveBox.h,SOLID)
lcd.drawText(radio.SaveBox.x+radio.SaveBox.x_offset,radio.SaveBox.y+radio.SaveBox.h_offset,saveMsg,DBLSIZE + globalTextOptions)
end
+ elseif uiState == uiStatus.confirm then
+ lcd.clear()
+ drawScreen()
+ if event == EVT_VIRTUAL_ENTER then
+ uiState = uiStatus.init
+ init = Page.init
+ invalidatePages()
+ elseif event == EVT_VIRTUAL_EXIT then
+ invalidatePages()
+ uiState = prevUiState
+ prevUiState = nil
+ end
end
- if protocol.rssi() == 0 then
+ if getRSSI() == 0 then
lcd.drawText(radio.NoTelem[1],radio.NoTelem[2],radio.NoTelem[3],radio.NoTelem[4])
end
mspProcessTxQ()
diff --git a/src/SCRIPTS/BF/ui_init.lua b/src/SCRIPTS/BF/ui_init.lua
index 8686b5dc..632fea68 100644
--- a/src/SCRIPTS/BF/ui_init.lua
+++ b/src/SCRIPTS/BF/ui_init.lua
@@ -1,35 +1,62 @@
local apiVersionReceived = false
local vtxTablesReceived = false
-local data_init, getVtxTables
-local vtxTables = loadScript("/BF/VTX/"..model.getInfo().name..".lua")
-
-if vtxTables and vtxTables() then
- vtxTablesReceived = true
- vtxTables = nil
- collectgarbage()
-end
+local mcuIdReceived = false
+local boardInfoReceived = false
+local getApiVersion, getVtxTables, getMCUId, getBoardInfo
+local returnTable = { f = nil, t = "" }
local function init()
- if apiVersion == 0 then
- lcd.drawText(6, radio.yMinLimit, "Initialising")
- data_init = data_init or assert(loadScript("data_init.lua"))()
- data_init()
- elseif apiVersion > 0 and not apiVersionReceived then
- data_init = nil
- apiVersionReceived = true
- collectgarbage()
- elseif apiVersion >= 1.042 and not vtxTablesReceived then
- lcd.drawText(6, radio.yMinLimit, "Downloading VTX Tables")
+ if getRSSI() == 0 then
+ returnTable.t = "Waiting for connection"
+ elseif not apiVersionReceived then
+ getApiVersion = getApiVersion or assert(loadScript("api_version.lua"))()
+ returnTable.t = getApiVersion.t
+ apiVersionReceived = getApiVersion.f()
+ if apiVersionReceived then
+ getApiVersion = nil
+ collectgarbage()
+ end
+ elseif not mcuIdReceived and apiVersion >= 1.042 then
+ getMCUId = getMCUId or assert(loadScript("mcu_id.lua"))()
+ returnTable.t = getMCUId.t
+ mcuIdReceived = getMCUId.f()
+ if mcuIdReceived then
+ getMCUId = nil
+ local f = loadScript("VTX_TABLES/"..mcuId..".lua")
+ if f and f() then
+ vtxTablesReceived = true
+ f = nil
+ end
+ collectgarbage()
+ f = loadScript("BOARD_INFO/"..mcuId..".lua")
+ if f and f() then
+ boardInfoReceived = true
+ f = nil
+ end
+ collectgarbage()
+ end
+ elseif not vtxTablesReceived and apiVersion >= 1.042 then
getVtxTables = getVtxTables or assert(loadScript("vtx_tables.lua"))()
- vtxTablesReceived = getVtxTables()
+ returnTable.t = getVtxTables.t
+ vtxTablesReceived = getVtxTables.f()
if vtxTablesReceived then
getVtxTables = nil
collectgarbage()
end
+ elseif not boardInfoReceived and apiVersion >= 1.043 then
+ getBoardInfo = getBoardInfo or assert(loadScript("board_info.lua"))()
+ returnTable.t = getBoardInfo.t
+ boardInfoReceived = getBoardInfo.f()
+ if boardInfoReceived then
+ getBoardInfo = nil
+ collectgarbage()
+ end
else
return true
end
- return apiVersionReceived and vtxTablesReceived
+ return apiVersionReceived and vtxTablesReceived and mcuId and boardInfoReceived
end
-return init
+returnTable.f = init
+
+return returnTable
diff --git a/src/SCRIPTS/BF/vtx_tables.lua b/src/SCRIPTS/BF/vtx_tables.lua
index 83ca15ea..2efa8942 100644
--- a/src/SCRIPTS/BF/vtx_tables.lua
+++ b/src/SCRIPTS/BF/vtx_tables.lua
@@ -82,7 +82,7 @@ local function getVtxTables()
end
end
if vtxTablesReceived then
- local f = io.open("/BF/VTX/"..model.getInfo().name..".lua", 'w')
+ local f = io.open("VTX_TABLES/"..mcuId..".lua", 'w')
io.write(f, "return {", "\n")
io.write(f, " frequencyTable = {", "\n")
for i = 1, #frequencyTable do
@@ -109,11 +109,11 @@ local function getVtxTables()
io.write(f, powerString, "\n")
io.write(f, "}", "\n")
io.close(f)
- assert(loadScript("/BF/VTX/"..model.getInfo().name..".lua", 'c'))
+ assert(loadScript("VTX_TABLES/"..mcuId..".lua", 'c'))
end
mspProcessTxQ()
processMspReply(mspPollReply())
return vtxTablesReceived
end
-return getVtxTables
+return { f = getVtxTables, t = "Downloading VTX tables" }
diff --git a/src/SCRIPTS/FUNCTIONS/bfbkgd.lua b/src/SCRIPTS/FUNCTIONS/bfbkgd.lua
index fcaec519..137000ba 100644
--- a/src/SCRIPTS/FUNCTIONS/bfbkgd.lua
+++ b/src/SCRIPTS/FUNCTIONS/bfbkgd.lua
@@ -1,7 +1,7 @@
chdir("/SCRIPTS/BF")
apiVersion = 0
protocol = assert(loadScript("protocols.lua"))()
-assert(loadScript(protocol.transport))()
+assert(loadScript(protocol.mspTransport))()
assert(loadScript("MSP/common.lua"))()
local background = assert(loadScript("background.lua"))()
diff --git a/src/SCRIPTS/FUNCTIONS/pids.lua b/src/SCRIPTS/FUNCTIONS/bfpids.lua
similarity index 100%
rename from src/SCRIPTS/FUNCTIONS/pids.lua
rename to src/SCRIPTS/FUNCTIONS/bfpids.lua
diff --git a/src/SCRIPTS/TELEMETRY/bf.lua b/src/SCRIPTS/TELEMETRY/bf.lua
deleted file mode 100644
index 3b931cfd..00000000
--- a/src/SCRIPTS/TELEMETRY/bf.lua
+++ /dev/null
@@ -1,6 +0,0 @@
-local function run(event)
- lcd.clear()
- lcd.drawText(2, 2, "Use TOOLS menu instead of this")
-end
-
-return { run=run }
diff --git a/src/SCRIPTS/TOOLS/bf.lua b/src/SCRIPTS/TOOLS/bf.lua
index af3d420b..3c4ee8b1 100644
--- a/src/SCRIPTS/TOOLS/bf.lua
+++ b/src/SCRIPTS/TOOLS/bf.lua
@@ -2,14 +2,15 @@ local toolName = "TNS|Betaflight setup|TNE"
chdir("/SCRIPTS/BF")
apiVersion = 0
+mcuId = nil
local run = nil
local scriptsCompiled = assert(loadScript("COMPILE/scripts_compiled.lua"))()
if scriptsCompiled then
protocol = assert(loadScript("protocols.lua"))()
- radio = assert(loadScript("radios.lua"))()
- assert(loadScript(protocol.transport))()
+ radio = assert(loadScript("radios.lua"))().msp
+ assert(loadScript(protocol.mspTransport))()
assert(loadScript("MSP/common.lua"))()
run = assert(loadScript("ui.lua"))()
else
diff --git a/src/SCRIPTS/TOOLS/bfCms.lua b/src/SCRIPTS/TOOLS/bfCms.lua
new file mode 100644
index 00000000..d9a8b0ab
--- /dev/null
+++ b/src/SCRIPTS/TOOLS/bfCms.lua
@@ -0,0 +1,20 @@
+local toolName = "TNS|Betaflight CMS|TNE"
+chdir("/SCRIPTS/BF")
+
+apiVersion = 0
+
+local cms = { run = nil, init = nil }
+local scriptsCompiled = assert(loadScript("COMPILE/scripts_compiled.lua"))()
+
+if scriptsCompiled then
+ protocol = assert(loadScript("protocols.lua"))()
+ local cmsTransport = assert(protocol.cmsTransport, "Telemetry protocol not supported!")
+ radio = assert(loadScript("radios.lua"))().cms
+ assert(loadScript(cmsTransport))()
+ assert(loadScript("CMS/common.lua"))()
+ cms = assert(loadScript("cms.lua"))()
+else
+ cms = { run = assert(loadScript("COMPILE/compile.lua"))() }
+end
+
+return cms