mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-07-01 18:27:53 +00:00
Merge branch 'pascallanger:master' into frankie-dsm-fwrd-prg-enhancements
This commit is contained in:
commit
4f5d33fc8a
610
Lua_scripts/DSM_AR636_TextGen.lua
Normal file
610
Lua_scripts/DSM_AR636_TextGen.lua
Normal file
@ -0,0 +1,610 @@
|
||||
local toolName = "TNS|DSM AR636 Telemetry TextGen|TNE"
|
||||
---- ######################################################################### #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- Developer: Francisco Arzu
|
||||
-- Original idea taken from DsmPID.lua.. don't know who is the author
|
||||
--
|
||||
|
||||
local DEBUG_ON = false
|
||||
--
|
||||
|
||||
local TEXT_SIZE = 0 -- NORMAL
|
||||
local X_COL1_HEADER = 6
|
||||
local X_COL1_DATA = 80
|
||||
local X_COL2_HEADER = 120
|
||||
local X_COL2_DATA = 190
|
||||
local Y_LINE_HEIGHT = 20
|
||||
local Y_HEADER = 0
|
||||
local Y_DATA = Y_HEADER + Y_LINE_HEIGHT
|
||||
|
||||
|
||||
|
||||
|
||||
local function getPage(iParam)
|
||||
-- get page from 0-based index
|
||||
-- {0,1,2,3}: cyclic (1), {4,5,6,7}: tail (2)
|
||||
local res = (math.floor(iParam/4)==0) and 0 or 1
|
||||
return res
|
||||
end
|
||||
|
||||
local function round(v)
|
||||
-- round float
|
||||
local factor = 100
|
||||
return math.floor(v * factor + 0.5) / factor
|
||||
end
|
||||
|
||||
|
||||
local function readValue(sensor)
|
||||
-- read from sensor, round and return
|
||||
local v = getValue(sensor)
|
||||
--v = round(v)
|
||||
return v
|
||||
end
|
||||
|
||||
local function readValueById(sensor)
|
||||
local i = getFieldInfo(sensor)
|
||||
if (i==nil) then return nil end
|
||||
|
||||
local v = getValue(i.id)
|
||||
return v
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function readBatValue(sensor)
|
||||
-- read from sensor, round and return
|
||||
local v = getValue(sensor)
|
||||
if (v==nil) then return "-- V" end
|
||||
|
||||
return string.format("%2.2f V",v)
|
||||
end
|
||||
|
||||
local function readActiveParamValue(sensor)
|
||||
-- read and return a validated active parameter value
|
||||
local v = getValue(sensor)
|
||||
if (v<1 or v>8) then
|
||||
return -1
|
||||
end
|
||||
return v
|
||||
end
|
||||
|
||||
|
||||
local function drawPIDScreen()
|
||||
-- draw labels and params on screen
|
||||
|
||||
local pageId = getValue("FLss")
|
||||
|
||||
lcd.clear()
|
||||
-- if active gain does not validate then assume
|
||||
-- Gain Adjustment Mode is disabled
|
||||
if not (pageId==4401 or pageId==4402) then
|
||||
lcd.drawText(0,0,"BLADE Gain Adjustment", TEXT_SIZE +INVERS)
|
||||
lcd.drawText(20,Y_LINE_HEIGHT*1,"Please enter Gain Adjustment Mode",TEXT_SIZE)
|
||||
lcd.drawText(20,Y_LINE_HEIGHT*2,"Stk: Low/Righ + Low/Right + Panic (3 sec)",TEXT_SIZE)
|
||||
lcd.drawText(20,Y_LINE_HEIGHT*4,"Op: Right Stk: Up/Down to select, Left/Right change value",TEXT_SIZE)
|
||||
lcd.drawText(20,Y_LINE_HEIGHT*5,"Panic to exit",TEXT_SIZE)
|
||||
return
|
||||
end
|
||||
|
||||
local activePage = (pageId % 100)-1 --Last 2 digits, make it zero base
|
||||
|
||||
lcd.drawText (X_COL1_HEADER, Y_HEADER, "Cyclic (0-200)", TEXT_SIZE + INVERS)
|
||||
lcd.drawText (X_COL2_HEADER, Y_HEADER, "Tail (0-200)", TEXT_SIZE + INVERS)
|
||||
|
||||
|
||||
|
||||
local p = readValue("FdeA")
|
||||
local i = readValue("FdeB")
|
||||
local d = readValue("FdeL")
|
||||
local r = readValue("FdeR")
|
||||
|
||||
local titles = {[0]="P:", "I:", "D:", "Response:", "P:","I:","D:", "Filtering:"}
|
||||
local values = {[0]=p,i,d,r,p,i,d,r}
|
||||
|
||||
local activeParam = readActiveParamValue("Hold")-1
|
||||
|
||||
for iParam=0,7 do
|
||||
-- highlight selected parameter
|
||||
local attr = (activeParam==iParam) and INVERS or 0
|
||||
-- circular index (per page)
|
||||
local perPageIndx = (iParam % 4)
|
||||
|
||||
-- set y draw coord
|
||||
local y = (perPageIndx+1)*Y_LINE_HEIGHT+Y_DATA
|
||||
|
||||
-- check if displaying cyclic params.
|
||||
local isCyclicPage = (getPage(iParam)==0)
|
||||
|
||||
-- labels
|
||||
local x = isCyclicPage and X_COL1_HEADER or X_COL2_HEADER
|
||||
-- labels are P,I,D for both pages except for last param
|
||||
local val = titles[iParam]
|
||||
lcd.drawText (x, y, val, TEXT_SIZE)
|
||||
|
||||
-- gains
|
||||
-- set all params for non-active page to '--' rather than 'last value'
|
||||
val = (getPage(iParam)==activePage) and values[iParam] or '--'
|
||||
x = isCyclicPage and X_COL1_DATA or X_COL2_DATA
|
||||
|
||||
if (val~=16384) then -- Active value
|
||||
lcd.drawText (x, y, val, attr + TEXT_SIZE)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function drawFlightLogScreen()
|
||||
-- draw labels and params on screen
|
||||
local h = getValue("Hold")
|
||||
local activeParam = h-1 -- H
|
||||
|
||||
lcd.clear()
|
||||
lcd.drawText (X_COL1_HEADER, Y_HEADER, "Flight Log", TEXT_SIZE + INVERS)
|
||||
|
||||
-- read and return parameters
|
||||
local a = getValue("FdeA")
|
||||
local b = getValue("FdeB")
|
||||
local l = getValue("FdeL")
|
||||
local r = getValue("FdeR")
|
||||
local f = getValue("FLss")
|
||||
|
||||
local titles = {[0]="A:", "B:", "L:", "R:", "F:", "H:"}
|
||||
local values = {[0]=a,b,l,r,f,h}
|
||||
|
||||
for iParam=0,3 do -- A,B,L,R
|
||||
-- highlight selected parameter (rund)
|
||||
local attr = ((activeParam%4)==iParam) and INVERS or 0
|
||||
|
||||
-- set y draw coord
|
||||
local y = iParam*Y_LINE_HEIGHT+Y_DATA
|
||||
|
||||
-- labels
|
||||
local x = X_COL1_HEADER
|
||||
local val = titles[iParam]
|
||||
lcd.drawText (x, y, val, TEXT_SIZE)
|
||||
|
||||
val = values[iParam]
|
||||
x = X_COL1_HEADER + 30
|
||||
if (val~=16384) then -- Active value
|
||||
lcd.drawText (x, y, val, attr + TEXT_SIZE)
|
||||
end
|
||||
end
|
||||
|
||||
for iParam=4,5 do -- F, H
|
||||
-- highlight selected parameter
|
||||
local attr = 0
|
||||
-- set y draw coord
|
||||
local perPageIndx = iParam % 4
|
||||
local y = perPageIndx*Y_LINE_HEIGHT+Y_DATA
|
||||
|
||||
-- labels
|
||||
local x = X_COL2_HEADER
|
||||
local val = titles[iParam]
|
||||
lcd.drawText (x, y, val, TEXT_SIZE + BOLD)
|
||||
|
||||
val = values[iParam]
|
||||
x = X_COL2_HEADER + 30
|
||||
lcd.drawText (x, y, val, attr + TEXT_SIZE + BOLD)
|
||||
end
|
||||
|
||||
-- Bat
|
||||
local bat = readBatValue("A2")
|
||||
local y = (4)*Y_LINE_HEIGHT+Y_HEADER
|
||||
lcd.drawText (X_COL2_HEADER, y, "Bat:", TEXT_SIZE)
|
||||
lcd.drawText (X_COL2_HEADER+30, y, bat, TEXT_SIZE)
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
local function servoAdjustScreen()
|
||||
-- draw labels and params on screen
|
||||
local pageId = getValue("FLss") -- FLss
|
||||
local activeParam = getValue("Hold")-1 -- Hold
|
||||
|
||||
lcd.clear()
|
||||
lcd.drawText (X_COL1_HEADER, Y_HEADER, "BLADE Servo SubTrim", TEXT_SIZE + INVERS)
|
||||
|
||||
if pageId~=1234 then
|
||||
lcd.drawText(20,Y_LINE_HEIGHT*1,"Please enter Servo Adjustment Mode",TEXT_SIZE)
|
||||
lcd.drawText(20,Y_LINE_HEIGHT*2,"Stk: Low/Left + Low/Right + Panic (3 sec)",TEXT_SIZE)
|
||||
lcd.drawText(20,Y_LINE_HEIGHT*4,"Op: R Stk: Up/Down to select, Left/Right change value",TEXT_SIZE)
|
||||
lcd.drawText(20,Y_LINE_HEIGHT*5,"Panic to exit",TEXT_SIZE)
|
||||
return
|
||||
end
|
||||
|
||||
local a = getValue("FdeA")
|
||||
local b = getValue("FdeB")
|
||||
local l = getValue("FdeL")
|
||||
|
||||
local titles = {[0]="Servo1:", "Servo2:", "Servo3:"}
|
||||
local values = {[0]=a,b,l}
|
||||
|
||||
for iParam=0,#values do -- S1,S2,S3
|
||||
-- highlight selected parameter
|
||||
local attr = (activeParam==iParam) and INVERS or 0
|
||||
|
||||
-- set y draw coord
|
||||
local y = (iParam+1)*Y_LINE_HEIGHT+Y_HEADER
|
||||
|
||||
-- labels
|
||||
local x = X_COL1_HEADER
|
||||
local val = titles[iParam]
|
||||
lcd.drawText (x, y, val, TEXT_SIZE)
|
||||
|
||||
val = values[iParam]
|
||||
x = X_COL1_DATA
|
||||
if (val~=16384) then -- Active value
|
||||
lcd.drawText (x, y, val, attr + TEXT_SIZE)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function Unsigned_to_SInt16(value)
|
||||
if value >= 0x8000 then -- Negative value??
|
||||
return value - 0x10000
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
local function getDegreesValue(sensor)
|
||||
local i = getFieldInfo(sensor)
|
||||
if (i==nil) then return "-unk-" end
|
||||
|
||||
local v = getValue(i.id)
|
||||
if v==nil then return "---" end
|
||||
local vs = Unsigned_to_SInt16(v)
|
||||
|
||||
return string.format("%0.1f o",vs/10)
|
||||
end
|
||||
|
||||
|
||||
local function getDecHexValue(sensor)
|
||||
local i = getFieldInfo(sensor)
|
||||
if (i==nil) then return "-unk-" end
|
||||
|
||||
local v = getValue(i.id)
|
||||
if v==nil then return "---" end
|
||||
local vs = Unsigned_to_SInt16(v)
|
||||
|
||||
return string.format("%d (0x%04X)",vs,v)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
local function drawVersionScreen()
|
||||
local paramV = getValue("FdeA")
|
||||
local B = getValue("FdeB")
|
||||
local rxId = getValue("FdeL")
|
||||
local firmware = getValue("FLss")
|
||||
local prodId = getValue("Hold")
|
||||
local bat = readBatValue("A2")
|
||||
|
||||
lcd.clear()
|
||||
lcd.drawText (X_COL1_HEADER, Y_HEADER, "BLADE Version", TEXT_SIZE + INVERS)
|
||||
|
||||
lcd.drawText(20,Y_LINE_HEIGHT*7,"Please Press Panic for 3s",TEXT_SIZE)
|
||||
lcd.drawText(20,Y_LINE_HEIGHT*8,"Usually Panic is Ch7 on a switch and Revesed",TEXT_SIZE)
|
||||
|
||||
|
||||
--Product ID
|
||||
local val = "ID_".. prodId
|
||||
|
||||
if (prodId==243) then val = "Blade 230 V1"
|
||||
elseif (prodId==250) then val = "Blade 230 V2 (not Smart)"
|
||||
elseif (prodId==149) then val = "Blade 250 CFX"
|
||||
end
|
||||
|
||||
local y = Y_LINE_HEIGHT*1+Y_HEADER
|
||||
lcd.drawText (X_COL1_HEADER, y, "Prod:", TEXT_SIZE)
|
||||
lcd.drawText (X_COL1_DATA, y, val, TEXT_SIZE)
|
||||
|
||||
-- RX
|
||||
val = "ID_"..rxId
|
||||
if (rxId==1) then val = "AR636"
|
||||
end
|
||||
|
||||
local y = y + Y_LINE_HEIGHT
|
||||
lcd.drawText (X_COL1_HEADER, y, "RX:", TEXT_SIZE)
|
||||
lcd.drawText (X_COL1_DATA, y, val, TEXT_SIZE)
|
||||
|
||||
-- Firmware
|
||||
val = string.format("%0.2f",firmware/100)
|
||||
local y = y + Y_LINE_HEIGHT
|
||||
lcd.drawText (X_COL1_HEADER, y, "Firmware:", TEXT_SIZE)
|
||||
lcd.drawText (X_COL1_DATA, y, val, TEXT_SIZE)
|
||||
|
||||
-- ParamV
|
||||
local y = y + Y_LINE_HEIGHT
|
||||
lcd.drawText (X_COL1_HEADER, y, "Params:", TEXT_SIZE)
|
||||
lcd.drawText (X_COL1_DATA, y, paramV, TEXT_SIZE)
|
||||
|
||||
-- Vat
|
||||
local y = y + Y_LINE_HEIGHT
|
||||
lcd.drawText (X_COL1_HEADER, y, "Bat:", TEXT_SIZE)
|
||||
lcd.drawText (X_COL1_DATA, y, bat, TEXT_SIZE)
|
||||
end
|
||||
|
||||
local function parseFlightMode(v)
|
||||
-- FlightMode (Hex: MMSGG) MM=Flight Mode, S=Status (0= off, 1=init, 2=Hold, 3=Running) GG=???
|
||||
if v==nil then return "---" end
|
||||
local fm = bit32.rshift(v, 12)
|
||||
local status = bit32.band(bit32.rshift(v, 8),0xF)
|
||||
|
||||
local res = " "..fm.." "
|
||||
|
||||
if (fm==0) then res = res .. " NORMAL"
|
||||
elseif (fm==1) then res = res .. " INTERMEDIATE"
|
||||
elseif (fm==2) then res = res .. " ADVANCED"
|
||||
elseif (fm==5) then res = res .. " PANIC"
|
||||
end
|
||||
|
||||
if (status==2) then res=res .. " HOLD" end
|
||||
|
||||
if (DEBUG_ON) then
|
||||
res = res .. string.format(" (0x%04X)",v)
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
local function drawAlpha6Monitor()
|
||||
lcd.clear()
|
||||
|
||||
local RxStatus = readValueById("2402") -- FlightMode (Hex: MMSGG) MM=Flight Mode, S=Status (0=init, 2=Ready, 3=Sensor Fault) GG=???
|
||||
|
||||
local ARoll = getDegreesValue("2406") --Att Roll
|
||||
local APitch = getDegreesValue("2408") --Att Pitch
|
||||
local AYaw = getDegreesValue("240B") --Att Yaw
|
||||
|
||||
|
||||
lcd.drawText (0,0, "BLADE AS3X/SAFE Monitor", TEXT_SIZE+INVERS)
|
||||
|
||||
local y = Y_LINE_HEIGHT+Y_HEADER
|
||||
-- Flight Mode
|
||||
lcd.drawText (0,y, "F-Mode:"..parseFlightMode(RxStatus), TEXT_SIZE)
|
||||
|
||||
y = y + Y_LINE_HEIGHT
|
||||
lcd.drawText (100+5,y, "Attitude", TEXT_SIZE+BOLD + RIGHT)
|
||||
lcd.drawText (150,y, "Gyro", TEXT_SIZE+BOLD + RIGHT)
|
||||
lcd.drawText (200,y, "Gain", TEXT_SIZE+BOLD + RIGHT)
|
||||
|
||||
y = y + Y_LINE_HEIGHT
|
||||
lcd.drawText (5,y, "Rol:", TEXT_SIZE)
|
||||
lcd.drawText (100-5,y, ARoll, TEXT_SIZE + RIGHT)
|
||||
lcd.drawText (150-5,y, "-", TEXT_SIZE + RIGHT)
|
||||
lcd.drawText (200-5,y, "-", TEXT_SIZE + RIGHT)
|
||||
|
||||
y = y + Y_LINE_HEIGHT
|
||||
lcd.drawText (5,y, "Pitch:", TEXT_SIZE)
|
||||
lcd.drawText (100-5,y, APitch, TEXT_SIZE + RIGHT)
|
||||
lcd.drawText (150-5,y, "-", TEXT_SIZE + RIGHT)
|
||||
lcd.drawText (200-5,y, "-", TEXT_SIZE + RIGHT)
|
||||
|
||||
y = y + Y_LINE_HEIGHT
|
||||
lcd.drawText (5,y, "Yaw:", TEXT_SIZE)
|
||||
lcd.drawText (100-5,y, AYaw, TEXT_SIZE + RIGHT)
|
||||
lcd.drawText (150-5,y, "-", TEXT_SIZE + RIGHT)
|
||||
lcd.drawText (200-5,y, "-", TEXT_SIZE + RIGHT)
|
||||
|
||||
y = y + Y_LINE_HEIGHT + Y_LINE_HEIGHT
|
||||
lcd.drawText (0,y, "Bat: "..readBatValue("A2"), TEXT_SIZE)
|
||||
|
||||
|
||||
-- Debug Values
|
||||
if (DEBUG_ON) then
|
||||
local s2400 = getDecHexValue("2400")
|
||||
local s2402 = getDecHexValue("2402")
|
||||
local s2404 = getDecHexValue("2404")
|
||||
|
||||
local s240D = getDecHexValue("240D")
|
||||
|
||||
local s1G00 = getDecHexValue("1G00")
|
||||
local s1G02 = getDecHexValue("1G02")
|
||||
local s1G04 = getDecHexValue("1G04")
|
||||
local s1G06 = getDecHexValue("1G06")
|
||||
local s1G08 = getDecHexValue("1G08")
|
||||
local s1G0B = getDecHexValue("1G0B")
|
||||
local s1G0D = getDecHexValue("1G0D")
|
||||
|
||||
local titles = {[0]=
|
||||
"2400","2402/FM-S-?",
|
||||
"2404","240D",
|
||||
"1G00","1G02","1G04",
|
||||
"1G06","1G08","1G0B","1G0D"}
|
||||
|
||||
local values = {[0]=
|
||||
s2400,s2402,s2404,s240D,
|
||||
s1G00,s1G02,s1G04,
|
||||
s1G06,s1G08,s1G0B,s1G0D}
|
||||
|
||||
|
||||
-- draw labels and params on screen
|
||||
|
||||
y = Y_LINE_HEIGHT*2 + Y_HEADER
|
||||
for iParam=0,#titles do -- ??
|
||||
-- labels
|
||||
local x = X_COL1_HEADER+220
|
||||
local val = titles[iParam]
|
||||
lcd.drawText (x, y, val, TEXT_SIZE)
|
||||
|
||||
val = values[iParam]
|
||||
x = X_COL1_DATA+250
|
||||
lcd.drawText (x, y, val, TEXT_SIZE)
|
||||
|
||||
y = y + Y_LINE_HEIGHT
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function readAlpha3arameters()
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
local function drawAS3XMonitor()
|
||||
lcd.clear()
|
||||
local s1G00 = getDecHexValue("1G00")
|
||||
local s1G02 = getDecHexValue("1G02")
|
||||
local s1G04 = getDecHexValue("1G04")
|
||||
local s1G06 = getDecHexValue("1G06")
|
||||
local s1G08 = getDecHexValue("1G08")
|
||||
local s1G0B = getDecHexValue("1G0B")
|
||||
local s1G0D = getDecHexValue("1G0D")
|
||||
|
||||
local s6C00 = getDecHexValue("6C00")
|
||||
local s6C02 = getDecHexValue("6C02")
|
||||
local s6C04 = getDecHexValue("6C04")
|
||||
|
||||
|
||||
|
||||
local RRoll = bit32.rshift(getValue("1G00") or 0,8)
|
||||
local RPitch = bit32.band(getValue("1G00") or 0,0xFF)
|
||||
local RYaw = bit32.rshift(getValue("1G02") or 0,8)
|
||||
|
||||
local HRoll = bit32.band(getValue("1G02") or 0,0xFF)
|
||||
local HPitch = bit32.rshift(getValue("1G04") or 0,8)
|
||||
local HYaw = bit32.band(getValue("1G04") or 0,0xFF)
|
||||
|
||||
local ARoll = bit32.rshift(getValue("1G06") or 0,8)
|
||||
local APitch = bit32.band(getValue("1G06") or 0,0xFF)
|
||||
local AYaw = bit32.rshift(getValue("1G08") or 0,8)
|
||||
|
||||
|
||||
lcd.drawText (0,0, "Plane AR636 AS3X Gains", TEXT_SIZE+INVERS)
|
||||
|
||||
local y = Y_LINE_HEIGHT+Y_HEADER
|
||||
-- Flight Mode
|
||||
--lcd.drawText (0,y, "F-Mode: "..(nil or "--"), TEXT_SIZE)
|
||||
|
||||
y = y + Y_LINE_HEIGHT
|
||||
lcd.drawText (100-15,y, "Rate", TEXT_SIZE+BOLD + RIGHT)
|
||||
lcd.drawText (150,y, "Heading", TEXT_SIZE+BOLD + RIGHT)
|
||||
lcd.drawText (200,y, "Actual", TEXT_SIZE+BOLD + RIGHT)
|
||||
|
||||
y = y + Y_LINE_HEIGHT
|
||||
lcd.drawText (5,y, "Roll:", TEXT_SIZE)
|
||||
lcd.drawText (100-5,y, RRoll.."%", TEXT_SIZE + RIGHT)
|
||||
lcd.drawText (150-5,y, HRoll.."%", TEXT_SIZE + RIGHT)
|
||||
lcd.drawText (200-5,y, ARoll.."%", TEXT_SIZE + RIGHT)
|
||||
|
||||
y = y + Y_LINE_HEIGHT
|
||||
lcd.drawText (5,y, "Pitch:", TEXT_SIZE)
|
||||
lcd.drawText (100-5,y, RPitch.."%", TEXT_SIZE + RIGHT)
|
||||
lcd.drawText (150-5,y, HPitch.."%", TEXT_SIZE + RIGHT)
|
||||
lcd.drawText (200-5,y, APitch.."%", TEXT_SIZE + RIGHT)
|
||||
|
||||
y = y + Y_LINE_HEIGHT
|
||||
lcd.drawText (5,y, "Yaw:", TEXT_SIZE)
|
||||
lcd.drawText (100-5,y, RYaw.."%", TEXT_SIZE + RIGHT)
|
||||
lcd.drawText (150-5,y, HYaw.."%", TEXT_SIZE + RIGHT)
|
||||
lcd.drawText (200-5,y, AYaw.."%", TEXT_SIZE + RIGHT)
|
||||
|
||||
|
||||
-- Debug Values
|
||||
if (DEBUG_ON) then
|
||||
local Alpha3Tags = {[0]=
|
||||
"1G00/RA+RE","1G02/RY+HA","1G04R HP+HY","1G06/AR+AP","1G08/AY+?","1G0B","1G0D","6C00","6C02","6C04"}
|
||||
|
||||
local params = {[0]=
|
||||
s1G00,s1G02,s1G04,s1G06,s1G08,s1G0B,s1G0D,s6C00,s6C02,s6C04 }
|
||||
|
||||
y = Y_LINE_HEIGHT*2 + Y_HEADER
|
||||
for iParam=0,#Alpha3Tags do -- ??
|
||||
-- labels
|
||||
local x = X_COL1_HEADER+220
|
||||
local val = Alpha3Tags[iParam]
|
||||
lcd.drawText (x, y, val, TEXT_SIZE)
|
||||
|
||||
val = params[iParam]
|
||||
x = X_COL1_DATA+250
|
||||
lcd.drawText (x, y, val, TEXT_SIZE)
|
||||
|
||||
y = y + Y_LINE_HEIGHT
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local telPage = 1
|
||||
local telPageSelected = 0
|
||||
local pageTitle = {[0]="Main", "Blade Version", "Blade Servo Adjust","Blade Gyro Adjust", "Blade AS3X Monitor", "Plane AS3X Monitor", "Flight Log"}
|
||||
|
||||
local function drawMainScreen(event)
|
||||
lcd.clear()
|
||||
lcd.drawText (X_COL1_HEADER, Y_HEADER, "Main Telemetry TextGen (AR636)", TEXT_SIZE + INVERS)
|
||||
|
||||
for iParam=1,#pageTitle do
|
||||
-- highlight selected parameter
|
||||
local attr = (telPage==iParam) and INVERS or 0
|
||||
|
||||
-- set y draw coord
|
||||
local y = (iParam)*Y_LINE_HEIGHT+Y_DATA
|
||||
|
||||
-- labels
|
||||
local x = X_COL1_HEADER
|
||||
local val = pageTitle[iParam]
|
||||
lcd.drawText (x, y, val, attr + TEXT_SIZE)
|
||||
end
|
||||
|
||||
if event == EVT_VIRTUAL_PREV then
|
||||
if (telPage>1) then telPage = telPage - 1 end
|
||||
elseif event == EVT_VIRTUAL_NEXT then
|
||||
if (telPage<#pageTitle) then telPage = telPage + 1 end
|
||||
elseif event == EVT_VIRTUAL_ENTER then
|
||||
telPageSelected = telPage
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local pageDraw = {[0]=drawMainScreen, drawVersionScreen, servoAdjustScreen,drawPIDScreen, drawAlpha6Monitor, drawAS3XMonitor, drawFlightLogScreen}
|
||||
|
||||
local function run_func(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
end
|
||||
|
||||
if event == EVT_VIRTUAL_EXIT then
|
||||
if (telPageSelected==0) then return 1 end -- on Main?? Exit Script
|
||||
telPageSelected = 0 -- any page, return to Main
|
||||
end
|
||||
|
||||
-- draw specific page
|
||||
pageDraw[telPageSelected](event)
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
local function init_func()
|
||||
|
||||
--if (LCD_W <= 128 or LCD_H <=64) then
|
||||
-- TEXT_SIZE = SMLSIZE
|
||||
-- X_COL1_HEADER = 6
|
||||
-- X_COL1_DATA = 70
|
||||
-- X_COL2_HEADER = 120
|
||||
-- X_COL2_DATA = 180
|
||||
-- Y_LINE_HEIGHT = 10
|
||||
--end
|
||||
end
|
||||
|
||||
return { run=run_func, init=init_func }
|
@ -117,6 +117,7 @@
|
||||
71,1,JJRC345,SkyTmblr,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
|
||||
49,0,KF606,KF606,1,Trim
|
||||
49,1,KF606,MIG320,1,Trim,LED
|
||||
49,2,KF606,ZCZ50,1,Trim,UNK
|
||||
9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
|
||||
9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
|
||||
73,0,Kyosho,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
|
@ -33,7 +33,14 @@ Multiprotocol is distributed in the hope that it will be useful,
|
||||
#define FX620_PAYLOAD_SIZE 7
|
||||
#define FX620_CH_OFFSET 1
|
||||
|
||||
#define FX9630_PACKET_PERIOD 8124
|
||||
#define FX9630_BIND_PACKET_PERIOD 8124
|
||||
#define FX9630_BIND_CHANNEL 51
|
||||
#define FX9630_PAYLOAD_SIZE 8
|
||||
#define FX9630_NUM_CHANNELS 3
|
||||
|
||||
//#define FORCE_FX620_ID
|
||||
//#define FORCE_FX9630_ID
|
||||
|
||||
static void __attribute__((unused)) FX_send_packet()
|
||||
{
|
||||
@ -41,14 +48,36 @@ static void __attribute__((unused)) FX_send_packet()
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
XN297_Hopping(hopping_frequency_no++);
|
||||
if(sub_protocol == FX9630)
|
||||
{
|
||||
XN297_SetTXAddr(rx_tx_addr, 4);
|
||||
if (hopping_frequency_no > FX9630_NUM_CHANNELS)
|
||||
hopping_frequency_no = 0;
|
||||
}
|
||||
else // FX816 and FX620
|
||||
{
|
||||
hopping_frequency_no &= 0x03;
|
||||
}
|
||||
}
|
||||
|
||||
memset(packet,0x00,packet_length);
|
||||
|
||||
//Channels
|
||||
uint8_t val;
|
||||
if (sub_protocol == FX9630)
|
||||
{
|
||||
packet[0] = convert_channel_8b(THROTTLE);
|
||||
packet[1] = convert_channel_8b(AILERON);
|
||||
packet[2] = 0xFF - convert_channel_8b(ELEVATOR);
|
||||
packet[3] = convert_channel_8b(RUDDER);
|
||||
packet[4] = 0x20;
|
||||
packet[5] = GET_FLAG(CH5_SW, 0x01); // DR toggle swich: 0 small throw, 1 large throw
|
||||
packet[5] |= (Channel_data[CH6] < CHANNEL_MIN_COMMAND ? 0x00 : (Channel_data[CH6] > CHANNEL_MAX_COMMAND ? 0x02 : 0x01)) << 1; // Mode A(0) : 6D small throw, B(1) : 6D large throw, C(2) : 3D
|
||||
}
|
||||
else // FX816 and FX620
|
||||
{
|
||||
uint8_t offset=sub_protocol == FX816 ? FX816_CH_OFFSET:FX620_CH_OFFSET;
|
||||
uint8_t val=convert_channel_8b(AILERON);
|
||||
val=convert_channel_8b(AILERON);
|
||||
if(val>127+FX_SWITCH)
|
||||
packet[offset] = sub_protocol == FX816 ? 1:0xFF;
|
||||
else if(val<127-FX_SWITCH)
|
||||
@ -56,6 +85,7 @@ static void __attribute__((unused)) FX_send_packet()
|
||||
else
|
||||
packet[offset] = sub_protocol == FX816 ? 0:0x7F;
|
||||
packet[offset+1] = convert_channel_16b_limit(THROTTLE,0,100); //FX816:0x00..0x63, FX620:0x00..0x5E but that should work
|
||||
}
|
||||
|
||||
//Bind and specifics
|
||||
if(sub_protocol == FX816)
|
||||
@ -67,7 +97,7 @@ static void __attribute__((unused)) FX_send_packet()
|
||||
packet[1] = rx_tx_addr[0];
|
||||
packet[2] = rx_tx_addr[1];
|
||||
}
|
||||
else //FX620
|
||||
else if(sub_protocol == FX620)
|
||||
{
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
@ -82,12 +112,27 @@ static void __attribute__((unused)) FX_send_packet()
|
||||
packet[5] = 0xAB; // Is it based on ID??
|
||||
}
|
||||
}
|
||||
else // FX9630
|
||||
{
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
memcpy(packet,rx_tx_addr, 4);
|
||||
packet[4] = hopping_frequency[1];
|
||||
packet[5] = hopping_frequency[2];
|
||||
packet[7] = 0x55;
|
||||
}
|
||||
}
|
||||
|
||||
//Check
|
||||
uint8_t last_packet_idx = packet_length-1;
|
||||
if (sub_protocol == FX9630 && IS_BIND_IN_PROGRESS)
|
||||
last_packet_idx--;
|
||||
val=0;
|
||||
for(uint8_t i=0;i<packet_length-1;i++)
|
||||
for(uint8_t i=0;i<last_packet_idx;i++)
|
||||
val+=packet[i];
|
||||
packet[packet_length-1]=val;
|
||||
if (sub_protocol == FX9630)
|
||||
val = val ^ 0xFF;
|
||||
packet[last_packet_idx]=val;
|
||||
|
||||
//Debug
|
||||
#if 0
|
||||
@ -112,13 +157,20 @@ static void __attribute__((unused)) FX_RF_init()
|
||||
packet_period = FX816_PACKET_PERIOD;
|
||||
packet_length = FX816_PAYLOAD_SIZE;
|
||||
}
|
||||
else //FX620
|
||||
else if(sub_protocol == FX620)
|
||||
{
|
||||
XN297_SetTXAddr((uint8_t *)"\xaa\xbb\xcc", 3);
|
||||
XN297_RFChannel(FX620_BIND_CHANNEL);
|
||||
packet_period = FX620_BIND_PACKET_PERIOD;
|
||||
packet_length = FX620_PAYLOAD_SIZE;
|
||||
}
|
||||
else // FX9630
|
||||
{
|
||||
XN297_SetTXAddr((uint8_t *)"\x56\x78\x90\x12", 4);
|
||||
XN297_RFChannel(FX9630_BIND_CHANNEL);
|
||||
packet_period = FX9630_BIND_PACKET_PERIOD;
|
||||
packet_length = FX9630_PAYLOAD_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FX_initialize_txid()
|
||||
@ -133,7 +185,7 @@ static void __attribute__((unused)) FX_initialize_txid()
|
||||
for(uint8_t i=0;i<FX_NUM_CHANNELS;i++)
|
||||
hopping_frequency[i]+=rx_tx_addr[3]&0x07;
|
||||
}
|
||||
else//FX620
|
||||
else if(sub_protocol == FX620)
|
||||
{
|
||||
rx_tx_addr[0] = rx_tx_addr[3];
|
||||
hopping_frequency[0] = 0x18 + rx_tx_addr[3]&0x07; // just to try something
|
||||
@ -144,6 +196,17 @@ static void __attribute__((unused)) FX_initialize_txid()
|
||||
for(uint8_t i=1;i<FX_NUM_CHANNELS;i++)
|
||||
hopping_frequency[i] = i*10 + hopping_frequency[0];
|
||||
}
|
||||
else // FX9630
|
||||
{
|
||||
#ifdef FORCE_FX9630_ID
|
||||
memcpy(rx_tx_addr,(uint8_t*)"\xCE\x31\x9B\x73", 4);
|
||||
memcpy(hopping_frequency,"\x13\x1A\x38", FX9630_NUM_CHANNELS); //Original dump=19=0x13,26=0x1A,56=0x38
|
||||
#else
|
||||
hopping_frequency[0] = 0x13; // constant
|
||||
hopping_frequency[1] = RX_num & 0x0F + 0x1A;
|
||||
hopping_frequency[2] = rx_tx_addr[3] & 0x0F + 0x38;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t FX_callback()
|
||||
|
@ -20,6 +20,7 @@ Multiprotocol is distributed in the hope that it will be useful,
|
||||
|
||||
//#define FORCE_KF606_ORIGINAL_ID
|
||||
//#define FORCE_MIG320_ORIGINAL_ID
|
||||
//#define FORCE_ZCZ50_ORIGINAL_ID
|
||||
|
||||
#define KF606_INITIAL_WAIT 500
|
||||
#define KF606_PACKET_PERIOD 3000
|
||||
@ -30,11 +31,17 @@ Multiprotocol is distributed in the hope that it will be useful,
|
||||
|
||||
static void __attribute__((unused)) KF606_send_packet()
|
||||
{
|
||||
uint8_t len = KF606_PAYLOAD_SIZE;
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
if(sub_protocol != KF606_ZCZ50)
|
||||
{
|
||||
packet[0] = 0xAA;
|
||||
memcpy(&packet[1],rx_tx_addr,3);
|
||||
}
|
||||
else
|
||||
memcpy(packet,rx_tx_addr,4);
|
||||
}
|
||||
else
|
||||
{
|
||||
XN297_Hopping(hopping_frequency_no);
|
||||
@ -43,13 +50,13 @@ static void __attribute__((unused)) KF606_send_packet()
|
||||
packet[0] = 0x55;
|
||||
packet[1] = convert_channel_8b(THROTTLE); // 0..255
|
||||
// Deadband is needed on aileron, 40 gives +-6%
|
||||
if(sub_protocol == KF606_KF606)
|
||||
switch(sub_protocol)
|
||||
{
|
||||
case KF606_KF606:
|
||||
packet[2] = convert_channel_8b_limit_deadband(AILERON,0x20,0x80,0xE0,40); // Aileron: Max values:20..80..E0, Low rates:50..80..AF, High rates:3E..80..C1
|
||||
packet[3] = convert_channel_16b_limit(CH5,0xC1,0xDF); // Aileron trim must be on a separated channel C1..D0..DF
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
case KF606_MIG320:
|
||||
packet[2] = convert_channel_8b_limit_deadband(AILERON,0x00,0x80,0xFF,40); // Aileron: High rate:2B..80..DA
|
||||
packet[3] = convert_channel_16b_limit(CH5,0x01,0x1F); // Aileron trim must be on a separated channel 01..10..1F
|
||||
packet[3] += (packet[2]-0x80)>>3; // Drive trims for more aileron authority
|
||||
@ -58,10 +65,17 @@ static void __attribute__((unused)) KF606_send_packet()
|
||||
else if(packet[3] > 0x1F)
|
||||
packet[3] = 0x1F;
|
||||
packet[3] |= GET_FLAG(CH6_SW, 0xC0); // 0xC0 and 0xE0 are both turning the LED off, not sure if there is another hidden feature
|
||||
break;
|
||||
case KF606_ZCZ50:
|
||||
len--; // uses only 3 bytes of payload
|
||||
packet[0] = packet[1]; // Throttle: 0x00..0xFF
|
||||
packet[1] = convert_channel_8b_limit_deadband(AILERON,0x20,0x80,0xE0,40); // Aileron: Max values:20..80..E0, low rate 0x52..0x80..0xB1, high rate: 0x41..0x80..0xC3.
|
||||
packet[2] = convert_channel_16b_limit(CH5,0x01,0x1F); // Trim: 0x01..0x10..0x1F
|
||||
packet[2] |= GET_FLAG(CH6_SW, 0xC0); // Unknown: 0x00 or 0xC0. Left top switch on original TX changes nothing on my plane. Maybe ON/OFF for main motor?
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t len = KF606_PAYLOAD_SIZE;
|
||||
if(sub_protocol == KF606_MIG320)
|
||||
{
|
||||
len++;
|
||||
@ -107,6 +121,19 @@ static void __attribute__((unused)) KF606_initialize_txid()
|
||||
hopping_frequency[0]=68;
|
||||
hopping_frequency[1]=71;
|
||||
#endif
|
||||
if(sub_protocol == KF606_ZCZ50)
|
||||
{
|
||||
rx_tx_addr[1] = rx_tx_addr[0];
|
||||
rx_tx_addr[0]=0xAA;
|
||||
}
|
||||
#ifdef FORCE_ZCZ50_ORIGINAL_ID
|
||||
rx_tx_addr[0]=0xAA;
|
||||
rx_tx_addr[1]=0x67;
|
||||
rx_tx_addr[2]=0x64;
|
||||
rx_tx_addr[3]=0x01;
|
||||
hopping_frequency[0]=48;
|
||||
hopping_frequency[1]=51;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) KF606_RF_init()
|
||||
@ -126,7 +153,7 @@ uint16_t KF606_callback()
|
||||
if(--bind_counter==0)
|
||||
{
|
||||
BIND_DONE;
|
||||
XN297_SetTXAddr(rx_tx_addr, 3);
|
||||
XN297_SetTXAddr(rx_tx_addr, sub_protocol != KF606_ZCZ50 ? 3 : 4);
|
||||
}
|
||||
KF606_send_packet();
|
||||
return KF606_PACKET_PERIOD;
|
||||
@ -153,3 +180,14 @@ void KF606_init()
|
||||
// P[2] = AIL 2B..80..DA
|
||||
// P[3] = TRIM 01..10..1F
|
||||
// channels 68=BB&3F+9 and 71
|
||||
|
||||
|
||||
// ZCZ50v2 protocol (with fake front propeller)
|
||||
// Bind
|
||||
// 250K C=7 S=Y A= E7 E7 E7 E7 E7 P(4)= AA 67 64 01
|
||||
// 3ms on ch7
|
||||
// Normal
|
||||
// 250K C=48 S=Y A= AA 67 64 01 P(3)= 00 80 10
|
||||
// P[0] = THR 0x00..0xFF
|
||||
// P[1] = AIL low rate 0x52..0x80..0xB1, high rate: 0x41..0x80..0xC3
|
||||
// P[2] = TRIM 0x01..0x10..0x1F + UNKNOWN 0x00 or 0xC0
|
||||
|
@ -46,7 +46,7 @@
|
||||
46,V911S,V911S,E119
|
||||
47,GD00x,GD_V1,GD_V2
|
||||
48,V761,3CH,4CH,TOPRC
|
||||
49,KF606,KF606,MIG320
|
||||
49,KF606,KF606,MIG320,ZCZ50
|
||||
50,Redpine,Fast,Slow
|
||||
51,Potensic,A20
|
||||
52,ZSX,280
|
||||
@ -55,7 +55,7 @@
|
||||
55,Frsky_RX,Multi,CloneTX,EraseTX,CPPM
|
||||
56,AFHDS2A_RX,Multi,CPPM
|
||||
57,HoTT,Sync,No_Sync
|
||||
58,FX,816,620
|
||||
58,FX,816,620,9630
|
||||
59,Bayang_RX,Multi,CPPM
|
||||
60,Pelikan,Pro,Lite,SCX24
|
||||
61,Tiger
|
||||
|
@ -171,9 +171,9 @@ const char STR_SUBTYPE_KYOSHO2[] = "\x05""KT-17";
|
||||
const char STR_SUBTYPE_FUTABA[] = "\x05""SFHSS";
|
||||
const char STR_SUBTYPE_JJRC345[] = "\x08""JJRC345\0""SkyTmblr";
|
||||
const char STR_SUBTYPE_MOULKG[] = "\x06""Analog""Digit\0";
|
||||
const char STR_SUBTYPE_KF606[] = "\x06""KF606\0""MIG320";
|
||||
const char STR_SUBTYPE_KF606[] = "\x06""KF606\0""MIG320""ZCZ50\0";
|
||||
const char STR_SUBTYPE_E129[] = "\x04""E129""C186";
|
||||
const char STR_SUBTYPE_FX[] = "\x03""816""620";
|
||||
const char STR_SUBTYPE_FX[] = "\x04""816\0""620\0""9630";
|
||||
#define NO_SUBTYPE nullptr
|
||||
|
||||
#ifdef SEND_CPPM
|
||||
@ -315,7 +315,7 @@ const mm_protocol_definition multi_protocols[] = {
|
||||
{PROTO_FUTABA, STR_FUTABA, STR_SUBTYPE_FUTABA, 1, OPTION_RFTUNE, 1, 1, SW_CC2500, SFHSS_init, SFHSS_callback },
|
||||
#endif
|
||||
#if defined(FX_NRF24L01_INO)
|
||||
{PROTO_FX, STR_FX, STR_SUBTYPE_FX, 2, OPTION_NONE, 0, 0, SW_NRF, FX_init, FX_callback },
|
||||
{PROTO_FX, STR_FX, STR_SUBTYPE_FX, 3, OPTION_NONE, 0, 0, SW_NRF, FX_init, FX_callback },
|
||||
#endif
|
||||
#if defined(FY326_NRF24L01_INO)
|
||||
{PROTO_FY326, STR_FY326, STR_SUBTYPE_FY326, 2, OPTION_NONE, 0, 0, SW_NRF, FY326_init, FY326_callback },
|
||||
@ -360,7 +360,7 @@ const mm_protocol_definition multi_protocols[] = {
|
||||
{PROTO_JOYSWAY, STR_JOYSWAY, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_A7105, JOYSWAY_init, JOYSWAY_callback },
|
||||
#endif
|
||||
#if defined(KF606_CCNRF_INO)
|
||||
{PROTO_KF606, STR_KF606, STR_SUBTYPE_KF606, 2, OPTION_RFTUNE, 0, 0, SW_NRF, KF606_init, KF606_callback },
|
||||
{PROTO_KF606, STR_KF606, STR_SUBTYPE_KF606, 3, OPTION_RFTUNE, 0, 0, SW_NRF, KF606_init, KF606_callback },
|
||||
#endif
|
||||
#if defined(KN_NRF24L01_INO)
|
||||
{PROTO_KN, STR_KN, STR_SUBTYPE_KN, 2, OPTION_NONE, 0, 0, SW_NRF, KN_init, KN_callback },
|
||||
|
@ -19,7 +19,7 @@
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 3
|
||||
#define VERSION_REVISION 3
|
||||
#define VERSION_PATCH_LEVEL 24
|
||||
#define VERSION_PATCH_LEVEL 25
|
||||
|
||||
#define MODE_SERIAL 0
|
||||
|
||||
@ -450,6 +450,7 @@ enum KF606
|
||||
{
|
||||
KF606_KF606 = 0,
|
||||
KF606_MIG320 = 1,
|
||||
KF606_ZCZ50 = 2,
|
||||
};
|
||||
enum E129
|
||||
{
|
||||
@ -460,6 +461,7 @@ enum FX
|
||||
{
|
||||
FX816 = 0,
|
||||
FX620 = 1,
|
||||
FX9630 = 2,
|
||||
};
|
||||
|
||||
#define NONE 0
|
||||
|
@ -670,6 +670,7 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
PROTO_FX
|
||||
FX816
|
||||
FX620
|
||||
FX9630
|
||||
PROTO_FY326
|
||||
FY326
|
||||
FY319
|
||||
@ -717,6 +718,7 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
PROTO_KF606
|
||||
KF606_KF606
|
||||
KF606_MIG320
|
||||
KF606_ZCZ50
|
||||
PROTO_KN
|
||||
WLTOYS
|
||||
FEILUN
|
||||
|
@ -110,7 +110,7 @@ CFlie|38|CFlie||||||||NRF24L01|
|
||||
[J6Pro](Protocols_Details.md#J6Pro---22)|22|||||||||CYRF6936|
|
||||
[JJRC345](Protocols_Details.md#JJRC345---71)|71|JJRC345|SkyTmblr|||||||NRF24L01|XN297
|
||||
[JOYSWAY](Protocols_Details.md#JOYSWAY---84)|84|||||||||NRF24L01|XN297
|
||||
[KF606](Protocols_Details.md#KF606---49)|49|KF606|MIG320|||||||NRF24L01|XN297
|
||||
[KF606](Protocols_Details.md#KF606---49)|49|KF606|MIG320|ZCZ50||||||NRF24L01|XN297
|
||||
[KN](Protocols_Details.md#KN---9)|9|WLTOYS|FEILUN|||||||NRF24L01|
|
||||
[Kyosho](Protocols_Details.md#Kyosho---73)|73|FHSS|Hype|||||||A7105|
|
||||
[Kyosho2](Protocols_Details.md#Kyosho2---93)|93|KT-17||||||||NRF24L01|
|
||||
@ -1049,6 +1049,15 @@ CH1|CH2|CH3|CH4|CH5|CH6
|
||||
---|---|---|---|---|---
|
||||
A||T||TRIM|LED
|
||||
|
||||
### Sub_protocol ZCZ50v2 - *2*
|
||||
Model: ZC-Z50 Cessna
|
||||
|
||||
This might be newer version of the model. My plane does not have front propeller, but its just fake anyway (no motor in the front).
|
||||
|
||||
CH1|CH2|CH3|CH4|CH5|CH6
|
||||
---|---|---|---|---|---
|
||||
A||T||TRIM|UNKNOWN
|
||||
|
||||
## MJXQ - *18*
|
||||
Autobind protocol
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user