mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2026-08-01 10:39:01 +00:00
Compare commits
1 Commits
master
...
pascallang
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7327265e55 |
@@ -1,305 +0,0 @@
|
|||||||
local toolName = "TNS|DumboRC P series|TNE"
|
|
||||||
|
|
||||||
-- EdgeTX/Multi bridge:
|
|
||||||
-- Multi_Buffer[4] is RF payload length, [5..12] is RF payload.
|
|
||||||
-- Multi rewrites the 00 00 token and checksum from its hop state.
|
|
||||||
-- Special1 payload: 18 00 00 arg_l arg_h 00. Args: 1 poll, 2 Set GY EPA, 3 Set FS.
|
|
||||||
-- Special2 payload: 28 00 00 gyro0 gyro1 gyro2 gyro3 00.
|
|
||||||
-- Gyro word: bit0 enable, bit1 phase, bits2..5 SEN channel selector
|
|
||||||
-- (0=NULL, 1..7=CH2..CH8), bits6..13 SEN, bits14..21 PCA,
|
|
||||||
-- bits22..29 AGS, bits30..31 servo frequency (67HZ,250HZ,50HZ,300HZ).
|
|
||||||
|
|
||||||
local PROTO_RLINK = 74
|
|
||||||
local SUB_DUMBORC_P = 4
|
|
||||||
|
|
||||||
local TX_READY = 4
|
|
||||||
local TX_PAYLOAD = 5
|
|
||||||
local TX_MAX_PAYLOAD = 8
|
|
||||||
local RX_READY = 14
|
|
||||||
local RX_PAYLOAD = 15
|
|
||||||
local RX_MAX_PAYLOAD = 32
|
|
||||||
local colorLcd = type(lcd.RGB) == "function"
|
|
||||||
|
|
||||||
local servoHz = { "67HZ", "250HZ", "50HZ", "300HZ" }
|
|
||||||
|
|
||||||
local gyro = { enable = 0, phase = 0, senCh = 0, sen = 0, pca = 0, ags = 0, flags = 0 }
|
|
||||||
local lines = {}
|
|
||||||
local sel = 1
|
|
||||||
local top = 1
|
|
||||||
local edit = false
|
|
||||||
local blink = 0
|
|
||||||
local moduleOk = false
|
|
||||||
local haveValues = false
|
|
||||||
|
|
||||||
local function limit(v, mn, mx)
|
|
||||||
if v < mn then return mn end
|
|
||||||
if v > mx then return mx end
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
|
|
||||||
local function byte(v)
|
|
||||||
return limit(math.floor(tonumber(v) or 0), 0, 255)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function gyroRaw(v)
|
|
||||||
return limit(math.floor(tonumber(v) or 0), 0, 200)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function gyroText(v)
|
|
||||||
local raw = gyroRaw(v)
|
|
||||||
return tostring(math.floor(raw / 2)) .. (raw % 2 == 0 and ".0" or ".5")
|
|
||||||
end
|
|
||||||
|
|
||||||
local function screenLines()
|
|
||||||
if colorLcd then return limit(math.floor(((LCD_H or 272) - 46) / 20), 8, 12) end
|
|
||||||
return 6
|
|
||||||
end
|
|
||||||
|
|
||||||
local function drawTitle(title)
|
|
||||||
if colorLcd and lcd.drawFilledRectangle then
|
|
||||||
lcd.drawFilledRectangle(0, 0, LCD_W, 30, COLOR_THEME_SECONDARY1)
|
|
||||||
lcd.drawText(3, 5, title, COLOR_THEME_PRIMARY2)
|
|
||||||
elseif lcd.drawScreenTitle then
|
|
||||||
lcd.drawScreenTitle(title, 0, 0)
|
|
||||||
else
|
|
||||||
lcd.drawText(0, 0, title, INVERS)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function findModule()
|
|
||||||
for i = 0, 1 do
|
|
||||||
local m = model.getModule(i)
|
|
||||||
if m and m["Type"] == 6 and m["protocol"] == PROTO_RLINK and m["subProtocol"] == SUB_DUMBORC_P then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local function initBuffer()
|
|
||||||
multiBuffer(0, string.byte("R"))
|
|
||||||
if multiBuffer(0) ~= string.byte("R") then
|
|
||||||
error("Not enough memory!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
multiBuffer(1, string.byte("L"))
|
|
||||||
multiBuffer(2, string.byte("n"))
|
|
||||||
multiBuffer(3, string.byte("k"))
|
|
||||||
multiBuffer(TX_READY, 0)
|
|
||||||
multiBuffer(RX_READY, 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function release()
|
|
||||||
for i = 0, RX_PAYLOAD + RX_MAX_PAYLOAD - 1 do
|
|
||||||
multiBuffer(i, 0)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function sendPayload(payload)
|
|
||||||
local len = #payload
|
|
||||||
if len < 1 or len > TX_MAX_PAYLOAD or multiBuffer(TX_READY) ~= 0 then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
for i = 1, TX_MAX_PAYLOAD do
|
|
||||||
multiBuffer(TX_PAYLOAD + i - 1, 0)
|
|
||||||
end
|
|
||||||
for i = 1, #payload do
|
|
||||||
multiBuffer(TX_PAYLOAD + i - 1, byte(payload[i]))
|
|
||||||
end
|
|
||||||
multiBuffer(TX_READY, len)
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
local function sendSpecial1(arg)
|
|
||||||
return sendPayload({ 0x18, 0, 0, arg % 256, math.floor(arg / 256), 0 })
|
|
||||||
end
|
|
||||||
|
|
||||||
local function gyroSelector()
|
|
||||||
if gyro.senCh < 2 or gyro.senCh > 8 then return 0 end
|
|
||||||
return gyro.senCh - 1
|
|
||||||
end
|
|
||||||
|
|
||||||
local function sendGyro()
|
|
||||||
local sen = gyroRaw(gyro.sen)
|
|
||||||
local pca = gyroRaw(gyro.pca)
|
|
||||||
local ags = gyroRaw(gyro.ags)
|
|
||||||
local b0 = gyro.enable + gyro.phase * 2 + gyroSelector() * 4 + (sen % 4) * 64
|
|
||||||
local b1 = math.floor(sen / 4) + (pca % 4) * 64
|
|
||||||
local b2 = math.floor(pca / 4) + (ags % 4) * 64
|
|
||||||
local b3 = math.floor(ags / 4) + limit(gyro.flags, 0, 3) * 64
|
|
||||||
sendPayload({ 0x28, 0, 0, b0, b1, b2, b3, 0 })
|
|
||||||
end
|
|
||||||
|
|
||||||
local function decodeGyroBytes(b0, b1, b2, b3)
|
|
||||||
b0 = byte(b0); b1 = byte(b1); b2 = byte(b2); b3 = byte(b3)
|
|
||||||
gyro.enable = b0 % 2
|
|
||||||
gyro.phase = math.floor(b0 / 2) % 2
|
|
||||||
local selector = math.floor(b0 / 4) % 16
|
|
||||||
gyro.senCh = selector == 0 and 0 or limit(selector + 1, 2, 8)
|
|
||||||
gyro.sen = gyroRaw(math.floor(b0 / 64) + (b1 % 64) * 4)
|
|
||||||
gyro.pca = gyroRaw(math.floor(b1 / 64) + (b2 % 64) * 4)
|
|
||||||
gyro.ags = gyroRaw(math.floor(b2 / 64) + (b3 % 64) * 4)
|
|
||||||
gyro.flags = math.floor(b3 / 64) % 4
|
|
||||||
haveValues = true
|
|
||||||
end
|
|
||||||
|
|
||||||
local function pollRx()
|
|
||||||
local len = multiBuffer(RX_READY)
|
|
||||||
if not len or len == 0 then return end
|
|
||||||
if len > RX_MAX_PAYLOAD then
|
|
||||||
multiBuffer(RX_READY, 0)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local p = {}
|
|
||||||
for i = 1, len do
|
|
||||||
p[i] = multiBuffer(RX_PAYLOAD + i - 1)
|
|
||||||
end
|
|
||||||
multiBuffer(RX_READY, 0)
|
|
||||||
|
|
||||||
if len == 7 and p[1] == 0x01 then
|
|
||||||
decodeGyroBytes(p[3], p[4], p[5], p[6])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function chText()
|
|
||||||
if gyro.senCh == 0 then return "NULL" end
|
|
||||||
return "CH" .. gyro.senCh
|
|
||||||
end
|
|
||||||
|
|
||||||
local function rebuildLines()
|
|
||||||
lines = {
|
|
||||||
{ "Poll RX", "action", function() sendSpecial1(1) end },
|
|
||||||
{ "Gyro", "toggle", "enable" },
|
|
||||||
{ "Phase", "toggle", "phase" },
|
|
||||||
{ "SEN Ch", "channel", "senCh" },
|
|
||||||
{ "SEN", "percent", "sen" },
|
|
||||||
{ "PCA", "percent", "pca" },
|
|
||||||
{ "AGS", "percent", "ags" },
|
|
||||||
{ "Servo Hz", "flags", "flags" },
|
|
||||||
{ "Send Gyro", "action", sendGyro },
|
|
||||||
{ "Set GY EPA", "action", function() sendSpecial1(2) end },
|
|
||||||
{ "Set FS", "action", function() sendSpecial1(3) end },
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function lineValue(line)
|
|
||||||
if line[2] == "action" then return ">" end
|
|
||||||
if not haveValues then return "--" end
|
|
||||||
if line[2] == "toggle" then return gyro[line[3]] == 0 and "Off" or "On" end
|
|
||||||
if line[2] == "channel" then return chText() end
|
|
||||||
if line[2] == "percent" then return gyroText(gyro[line[3]]) end
|
|
||||||
if line[2] == "flags" then return servoHz[gyro.flags + 1] or tostring(gyro.flags) end
|
|
||||||
return ""
|
|
||||||
end
|
|
||||||
|
|
||||||
local function changeValue(dir, fast)
|
|
||||||
local line = lines[sel]
|
|
||||||
if not line then return end
|
|
||||||
local step = fast and 20 or 1
|
|
||||||
haveValues = true
|
|
||||||
|
|
||||||
if line[2] == "toggle" then
|
|
||||||
gyro[line[3]] = dir > 0 and 1 or 0
|
|
||||||
elseif line[2] == "channel" then
|
|
||||||
local vals = { 0, 2, 3, 4, 5, 6, 7, 8 }
|
|
||||||
local pos = 1
|
|
||||||
for i = 1, #vals do
|
|
||||||
if vals[i] == gyro.senCh then pos = i end
|
|
||||||
end
|
|
||||||
gyro.senCh = vals[limit(pos + dir, 1, #vals)]
|
|
||||||
elseif line[2] == "percent" then
|
|
||||||
gyro[line[3]] = gyroRaw(gyro[line[3]] + dir * step)
|
|
||||||
elseif line[2] == "flags" then
|
|
||||||
gyro.flags = limit(gyro.flags + dir, 0, 3)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function fastRotary()
|
|
||||||
return getRotEncSpeed() > 1
|
|
||||||
end
|
|
||||||
|
|
||||||
local function handleEvent(event)
|
|
||||||
local nextEvent = edit and EVT_VIRTUAL_INC or EVT_VIRTUAL_NEXT
|
|
||||||
local prevEvent = edit and EVT_VIRTUAL_DEC or EVT_VIRTUAL_PREV
|
|
||||||
if event == nextEvent then
|
|
||||||
if edit then changeValue(1, fastRotary()) else sel = limit(sel + 1, 1, #lines) end
|
|
||||||
elseif event == prevEvent then
|
|
||||||
if edit then changeValue(-1, fastRotary()) else sel = limit(sel - 1, 1, #lines) end
|
|
||||||
elseif event == EVT_VIRTUAL_NEXT_PAGE then
|
|
||||||
if edit then changeValue(1, true) else sel = limit(sel + screenLines(), 1, #lines) end
|
|
||||||
elseif event == EVT_VIRTUAL_PREV_PAGE then
|
|
||||||
if edit then changeValue(-1, true) else sel = limit(sel - screenLines(), 1, #lines) end
|
|
||||||
killEvents(event)
|
|
||||||
elseif event == EVT_VIRTUAL_ENTER then
|
|
||||||
local line = lines[sel]
|
|
||||||
if line and line[2] == "action" then
|
|
||||||
line[3]()
|
|
||||||
elseif line then
|
|
||||||
edit = not edit
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local count = screenLines()
|
|
||||||
if sel < top then top = sel end
|
|
||||||
if sel >= top + count then top = sel - count + 1 end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function draw()
|
|
||||||
lcd.clear()
|
|
||||||
drawTitle("DumboRC P series")
|
|
||||||
|
|
||||||
local font = colorLcd and 0 or SMLSIZE
|
|
||||||
local x = 2
|
|
||||||
local y = colorLcd and 34 or 9
|
|
||||||
local dy = colorLcd and 20 or 8
|
|
||||||
local valueX = colorLcd and 150 or 82
|
|
||||||
|
|
||||||
if not moduleOk then
|
|
||||||
if colorLcd then
|
|
||||||
lcd.drawText(x, y + dy, "Select Multi RadLink/Dumbo_P", font + BLINK)
|
|
||||||
else
|
|
||||||
lcd.drawText(x, y + dy, "Select RadLink", font + BLINK)
|
|
||||||
lcd.drawText(x, y + dy * 2, "Dumbo_P", font + BLINK)
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
for i = top, math.min(#lines, top + screenLines() - 1) do
|
|
||||||
local attr = font
|
|
||||||
if i == sel then
|
|
||||||
attr = attr + INVERS
|
|
||||||
if edit then
|
|
||||||
blink = (blink + 1) % 30
|
|
||||||
if blink > 15 then attr = font end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local yy = y + (i - top) * dy
|
|
||||||
lcd.drawText(x, yy, lines[i][1], attr)
|
|
||||||
lcd.drawText(valueX, yy, lineValue(lines[i]), attr)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function init()
|
|
||||||
moduleOk = type(multiBuffer) == "function" and findModule()
|
|
||||||
rebuildLines()
|
|
||||||
if moduleOk then initBuffer() end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function run(event)
|
|
||||||
if event == nil then
|
|
||||||
error("Cannot be run as a model script!")
|
|
||||||
return 2
|
|
||||||
elseif event == EVT_VIRTUAL_EXIT then
|
|
||||||
if moduleOk then release() end
|
|
||||||
return 2
|
|
||||||
end
|
|
||||||
if moduleOk then
|
|
||||||
pollRx()
|
|
||||||
handleEvent(event)
|
|
||||||
end
|
|
||||||
draw()
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
return { init = init, run = run }
|
|
||||||
@@ -54,9 +54,10 @@
|
|||||||
28,1,Flysky_AFHDS2A,PPM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
28,1,Flysky_AFHDS2A,PPM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
28,2,Flysky_AFHDS2A,PWM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
28,2,Flysky_AFHDS2A,PWM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
28,4,Flysky_AFHDS2A,Gyro_Off,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,ST_Ga,TH_Ga,Prio,Calib
|
28,4,Flysky_AFHDS2A,PWM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
28,5,Flysky_AFHDS2A,Gyro_On,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,ST_Ga,TH_Ga,Prio,Calib
|
28,5,Flysky_AFHDS2A,PPM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
28,6,Flysky_AFHDS2A,G_On_Rev,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,ST_Ga,TH_Ga,Prio,Calib
|
28,6,Flysky_AFHDS2A,PWM_SB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
|
28,7,Flysky_AFHDS2A,PPM_SB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
56,1,Flysky2A_RX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
56,1,Flysky2A_RX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||||
53,0,Height,5ch,0,Gear
|
53,0,Height,5ch,0,Gear
|
||||||
@@ -86,17 +87,13 @@
|
|||||||
55,1,FrSkyRX,CloneTX,0
|
55,1,FrSkyRX,CloneTX,0
|
||||||
55,2,FrSkyRX,EraseTX,0
|
55,2,FrSkyRX,EraseTX,0
|
||||||
55,3,FrSkyRX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
55,3,FrSkyRX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
58,0,FX,FX816,1
|
58,0,FX,816,1
|
||||||
58,1,FX,FX620,1
|
58,1,FX,620,1
|
||||||
58,2,FX,9630,1,Rate,Gyro,TrimR,TrimA,TrimE
|
58,2,FX,9630,1,Rate,Gyro,TrimR,TrimA,TrimE
|
||||||
58,3,FX,Q560,1,FLIP,Gyro,LEDs
|
58,3,FX,Q560,1,FLIP,Gyro,LEDs
|
||||||
58,4,FX,QF012,1,FLIP,Gyro,Invert,Reset
|
|
||||||
58,5,FX,BM26,1,FLIP,Gyro,LEDs,LED,CALIB
|
|
||||||
58,6,FX,A570,1,STOP,Rate,Color,LED,TrimR,TrimA,TrimE
|
|
||||||
20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
|
20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
|
||||||
20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
|
20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
|
||||||
23,0,FQ777,124,1,Flip,RTH,HLess,Expert
|
23,0,FY326,FY326,1,Flip,RTH,HLess,Expert
|
||||||
23,1,FQ777,XBM37,1,Rate,Flip,HLess,LED,Pict,Video,RTH,OK,ETrim,Atrim
|
|
||||||
47,0,GD00x,V1,1,Trim,LED,Rate
|
47,0,GD00x,V1,1,Trim,LED,Rate
|
||||||
47,1,GD00x,V2,1,Trim,LED,Rate
|
47,1,GD00x,V2,1,Trim,LED,Rate
|
||||||
32,0,GW008,FY326,1,Flip
|
32,0,GW008,FY326,1,Flip
|
||||||
@@ -113,7 +110,7 @@
|
|||||||
26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||||
26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||||
26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||||
26,4,Hontai,XKK170,1,Rate,Emerg,TakLan,Calib,TrimA,TrimE,Optic
|
26,4,Hontai,XKK170,1,Rate,Emerg,TakLan,Calib,TrimA,TrimE
|
||||||
57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||||
2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess
|
2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess
|
||||||
@@ -122,7 +119,7 @@
|
|||||||
22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||||
71,0,JJRC345,JJRC345,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
|
71,0,JJRC345,JJRC345,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
|
||||||
71,1,JJRC345,SkyTmblr,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
|
71,1,JJRC345,SkyTmblr,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
|
||||||
49,0,KF606,KF606,1,Trim,LED
|
49,0,KF606,KF606,1,Trim
|
||||||
49,1,KF606,MIG320,1,Trim,LED
|
49,1,KF606,MIG320,1,Trim,LED
|
||||||
49,2,KF606,ZCZ50,1,Trim,UNK
|
49,2,KF606,ZCZ50,1,Trim,UNK
|
||||||
9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim,Rtrim,Hover
|
9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim,Rtrim,Hover
|
||||||
@@ -136,16 +133,14 @@
|
|||||||
18,4,MJXQ,E010,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
18,4,MJXQ,E010,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
18,5,MJXQ,H26WH,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
18,5,MJXQ,H26WH,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
18,6,MJXQ,Phoenix,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
18,6,MJXQ,Phoenix,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||||
17,0,MT99XX,Std,1,Flip,LED,Pict,Video,HLess,Atrim,Etrim
|
17,0,MT99XX,Std,1,Flip,LED,Pict,Video,HLess
|
||||||
17,1,MT99XX,H7,1,Flip,LED,Pict,Video,HLess,Atrim,Etrim
|
17,1,MT99XX,H7,1,Flip,LED,Pict,Video,HLess
|
||||||
17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess,Atrim,Etrim
|
17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess
|
||||||
17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess,Atrim,Etrim
|
17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess
|
||||||
17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess,Atrim,Etrim
|
17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess
|
||||||
17,5,MT99XX,A180,0,3D_6G,Rate,3D_6G,n-a,n-a,Atrim,Etrim
|
17,5,MT99XX,A180,0,3D_6G
|
||||||
17,6,MT99XX,Dragon,0,Mode,RTH,n-a,n-a,n-a,Atrim,Etrim
|
17,6,MT99XX,Dragon,0,Mode,RTH
|
||||||
17,7,MT99XX,F949G,0,6G_3D,Light,Rates,Unk1,Unk2,Atrim,Etrim
|
17,7,MT99XX,F949G,0,6G_3D,Light
|
||||||
92,0,MT99xx2,PA18,0,MODE,FLIP,RTH,n-a,n-a,Atrim,Etrim
|
|
||||||
92,1,MT99xx2,SU35,0,Mode,LED,LED_FH,Invert,Rate,Atrim,Etrim
|
|
||||||
44,0,NCC1701,Std,1,Warp
|
44,0,NCC1701,Std,1,Warp
|
||||||
77,0,OMP,M2,0,THold,IdleUp,6G_3D
|
77,0,OMP,M2,0,THold,IdleUp,6G_3D
|
||||||
60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
|
60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
|
||||||
@@ -163,9 +158,8 @@
|
|||||||
72,0,Q90C,Std,0,FMode,VTX+
|
72,0,Q90C,Std,0,FMode,VTX+
|
||||||
74,0,RadioLink,Surface,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
|
74,0,RadioLink,Surface,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
|
||||||
74,1,RadioLink,Air,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
|
74,1,RadioLink,Air,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
|
||||||
74,2,RadioLink,DumboRC,0,CH5,CH6,CH7,CH8GY,CH9,CH10,n-a,n-a,n-a,n-a,n-a,n-a
|
74,2,RadioLink,DumboRC,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
|
||||||
74,3,RadioLink,RC4G,0,CH5,FS_CH1,FS_CH2,FS_CH3,FS_CH4
|
74,3,RadioLink,RC4G,0,CH5,FS_CH1,FS_CH2,FS_CH3,FS_CH4
|
||||||
74,4,RadioLink,Dumbo_P,0,CH5,CH6,CH7,CH8GY,CH9,CH10,n-a,n-a,n-a,n-a,n-a,n-a
|
|
||||||
76,0,Realacc,Std,1,Flip,Light,Calib,HLess,RTH,ThCut,Rotat
|
76,0,Realacc,Std,1,Flip,Light,Calib,HLess,RTH,ThCut,Rotat
|
||||||
50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
||||||
50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
||||||
@@ -200,8 +194,8 @@
|
|||||||
62,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
|
62,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
|
||||||
62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video,Flip,Light
|
62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video,Flip,Light
|
||||||
62,2,XK,Cars,0,FMode,TakeOf,Emerg,3D_6G,Pict,Video,Flip,Light
|
62,2,XK,Cars,0,FMode,TakeOf,Emerg,3D_6G,Pict,Video,Flip,Light
|
||||||
99,0,XK2,X4,0,Rate,Mode,Hover,Light,Stunt
|
99,0,XK2,X4,0,Rate,Mode,Hover,Light
|
||||||
99,1,XK2,P10,0,Rate,Mode,Hover,Light,Stunt
|
99,1,XK2,P10,0,Rate,Mode,Hover,Light
|
||||||
8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess
|
8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess
|
||||||
8,1,YD717,SkyWlkr,1,Flip,Light,Pict,Video,HLess
|
8,1,YD717,SkyWlkr,1,Flip,Light,Pict,Video,HLess
|
||||||
8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess
|
8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess
|
||||||
@@ -219,10 +213,11 @@
|
|||||||
85,0,E016H,Std,1,Stop,Flip,n-a,HLess,RTH
|
85,0,E016H,Std,1,Stop,Flip,n-a,HLess,RTH
|
||||||
87,0,IKEA
|
87,0,IKEA
|
||||||
89,0,LOSI
|
89,0,LOSI
|
||||||
90,0,MouldKg,A4444,0
|
90,0,MouldKg,Analog,0
|
||||||
90,1,MouldKg,D4444,0
|
90,1,MouldKg,Digit,0
|
||||||
90,2,MouldKg,A664,0
|
|
||||||
91,0,Xerall,Tank,0,FlTa,TakLan,Rate,HLess,Photo,Video,TrimR,TrimE,TrimA
|
91,0,Xerall,Tank,0,FlTa,TakLan,Rate,HLess,Photo,Video,TrimR,TrimE,TrimA
|
||||||
|
92,0,MT99xx2,PA18,0,MODE,FLIP,RTH
|
||||||
|
92,1,MT99xx2,SU35,0,Mode,LED,LED_FH,Invert,Rate
|
||||||
93,0,Kyosho2,KT-17,0
|
93,0,Kyosho2,KT-17,0
|
||||||
94,0,Scorpio
|
94,0,Scorpio
|
||||||
95,0,Bluefly,HP100,0,CH5,CH6,CH7,CH8
|
95,0,Bluefly,HP100,0,CH5,CH6,CH7,CH8
|
||||||
@@ -237,6 +232,3 @@
|
|||||||
102,1,JIABAILE,Gyro,0,Speed,Light,Flash,ST_Tr
|
102,1,JIABAILE,Gyro,0,Speed,Light,Flash,ST_Tr
|
||||||
103,0,H36,Std,1,Flip,HLess,RTH
|
103,0,H36,Std,1,Flip,HLess,RTH
|
||||||
104,0,KAMTOM,Std,0,ST_Tr,TH_Tr,TH_DR
|
104,0,KAMTOM,Std,0,ST_Tr,TH_Tr,TH_DR
|
||||||
105,0,Shenqi2,Std,1
|
|
||||||
106,0,WL91x,Std,0
|
|
||||||
107,0,WPL,Std,0,Light,TH_DR,ST_DR
|
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ local function Multi_Init()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--Exceptions on first 4 channels...
|
--Exceptions on first 4 channels...
|
||||||
if ( protocol == 73 or (protocol == 74 and (sub_protocol == 0 or sub_protocol == 2 or sub_protocol == 4)) or (protocol == 60 and sub_protocol == 2) or protocol == 89) then -- Kyosho or RadioLink (Surface or DumboRC/P) or Pelikan/SCX24 or Losi
|
if ( protocol == 73 or (protocol == 74 and sub_protocol == 0) or (protocol == 60 and sub_protocol == 2) or protocol == 89) then -- Kyosho or RadioLink Surface or Pelikan/SCX24 or Losi
|
||||||
channel_names[1] = "ST"
|
channel_names[1] = "ST"
|
||||||
channel_names[2] = "THR"
|
channel_names[2] = "THR"
|
||||||
channel_names[3] = "CH3"
|
channel_names[3] = "CH3"
|
||||||
|
|||||||
@@ -183,18 +183,8 @@ uint16_t AFHDS2A_RX_callback()
|
|||||||
case AFHDS2A_RX_DATA:
|
case AFHDS2A_RX_DATA:
|
||||||
if (AFHDS2A_RX_data_ready()) {
|
if (AFHDS2A_RX_data_ready()) {
|
||||||
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
|
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
|
||||||
if (memcmp(&packet[1], rx_id, 4) == 0 && memcmp(&packet[5], rx_tx_addr, 4) == 0)
|
if (memcmp(&packet[1], rx_id, 4) == 0 && memcmp(&packet[5], rx_tx_addr, 4) == 0) {
|
||||||
{
|
if (packet[0] == 0x58 && packet[37] == 0x00 && (telemetry_link&0x7F) == 0) { // standard packet, send channels to TX
|
||||||
#if 0
|
|
||||||
//if(packet[0] == 0xAA)
|
|
||||||
{
|
|
||||||
for(uint8_t i=0;i<AFHDS2A_RX_TXPACKET_SIZE;i++)
|
|
||||||
debug(" %02X",packet[i]);
|
|
||||||
debugln("");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (packet[0] == 0x58 && packet[37] == 0x00 && (telemetry_link&0x7F) == 0)
|
|
||||||
{ // standard packet, send channels to TX
|
|
||||||
int rssi = min(A7105_ReadReg(A7105_1D_RSSI_THOLD),160);
|
int rssi = min(A7105_ReadReg(A7105_1D_RSSI_THOLD),160);
|
||||||
RX_RSSI = map16b(rssi, 160, 8, 0, 128);
|
RX_RSSI = map16b(rssi, 160, 8, 0, 128);
|
||||||
AFHDS2A_RX_build_telemetry_packet();
|
AFHDS2A_RX_build_telemetry_packet();
|
||||||
|
|||||||
@@ -93,19 +93,15 @@ static void AFHDS2A_update_telemetry()
|
|||||||
if (option & 0x80)
|
if (option & 0x80)
|
||||||
{// forward 0xAA and 0xAC telemetry to TX, skip rx and tx id to save space
|
{// forward 0xAA and 0xAC telemetry to TX, skip rx and tx id to save space
|
||||||
packet_in[0]= TX_RSSI;
|
packet_in[0]= TX_RSSI;
|
||||||
//Fix for CROSSOVER-RX,
|
debug("T(%02X)=",packet[0]);
|
||||||
if(packet[17+8]==0xFF && packet[21+8]==0xFC && packet[25+8]==0xFF)
|
|
||||||
packet[17+8]=0xFE; // RX_ERR_RATE needed for TX to validate the telem
|
|
||||||
#if 0
|
|
||||||
debug("T(%02X)=",packet[0]);
|
|
||||||
for(uint8_t i=9;i < AFHDS2A_RXPACKET_SIZE; i++)
|
|
||||||
debug(" %02X",packet[i]);
|
|
||||||
debugln("");
|
|
||||||
#endif
|
|
||||||
for(uint8_t i=9;i < AFHDS2A_RXPACKET_SIZE; i++)
|
for(uint8_t i=9;i < AFHDS2A_RXPACKET_SIZE; i++)
|
||||||
|
{
|
||||||
packet_in[i-8]=packet[i];
|
packet_in[i-8]=packet[i];
|
||||||
|
debug(" %02X",packet[i]);
|
||||||
|
}
|
||||||
packet_in[29]=packet[0]; // 0xAA Normal telemetry, 0xAC Extended telemetry
|
packet_in[29]=packet[0]; // 0xAA Normal telemetry, 0xAC Extended telemetry
|
||||||
telemetry_link=2;
|
telemetry_link=2;
|
||||||
|
debugln("");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -190,9 +186,16 @@ static void AFHDS2A_build_packet(uint8_t type)
|
|||||||
case AFHDS2A_PACKET_STICKS:
|
case AFHDS2A_PACKET_STICKS:
|
||||||
packet[0] = 0x58;
|
packet[0] = 0x58;
|
||||||
//16 channels + RX_LQI on channel 17
|
//16 channels + RX_LQI on channel 17
|
||||||
for(uint8_t ch=0; ch<17; ch++)
|
for(uint8_t ch=0; ch<num_ch; ch++)
|
||||||
{
|
{
|
||||||
val = convert_channel_ppm(sub_protocol<AFHDS2A_GYRO_OFF?CH_AETR[ch]:ch); // No remapping for BS receivers
|
if(ch == 16 // CH17=RX_LQI
|
||||||
|
#ifdef AFHDS2A_LQI_CH
|
||||||
|
|| ch == (AFHDS2A_LQI_CH-1) // override channel with LQI
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
val = 2000 - 10*RX_LQI;
|
||||||
|
else
|
||||||
|
val = convert_channel_ppm(CH_AETR[ch]);
|
||||||
if(ch<14)
|
if(ch<14)
|
||||||
{
|
{
|
||||||
packet[9 + ch*2] = val;
|
packet[9 + ch*2] = val;
|
||||||
@@ -200,41 +203,46 @@ static void AFHDS2A_build_packet(uint8_t type)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(ch == 16) //CH17=RX_LQI
|
|
||||||
val = 2000 - 10*RX_LQI;
|
|
||||||
packet[10 + (ch-14)*6] |= (val)<<4;
|
packet[10 + (ch-14)*6] |= (val)<<4;
|
||||||
packet[12 + (ch-14)*6] |= (val)&0xF0;
|
packet[12 + (ch-14)*6] |= (val)&0xF0;
|
||||||
packet[14 + (ch-14)*6] |= (val>>4)&0xF0;
|
packet[14 + (ch-14)*6] |= (val>>4)&0xF0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
|
||||||
uint8_t next_hop = (hopping_frequency_no+1)&0x0F;
|
|
||||||
packet[34] |= next_hop<<4;
|
|
||||||
packet[36] |= next_hop?0x80:0x90;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case AFHDS2A_PACKET_FAILSAFE:
|
case AFHDS2A_PACKET_FAILSAFE:
|
||||||
packet[0] = 0x56;
|
packet[0] = 0x56;
|
||||||
for(uint8_t ch=0; ch<16; ch++)
|
for(uint8_t ch=0; ch<num_ch; ch++)
|
||||||
{ // Failsafe values
|
{
|
||||||
#ifdef FAILSAFE_ENABLE
|
#ifdef FAILSAFE_ENABLE
|
||||||
val = Failsafe_data[protocol==PROTO_AFHDS2A?CH_AETR[ch]:ch]; // No remapping for BS receivers
|
if(ch<16)
|
||||||
|
val = Failsafe_data[CH_AETR[ch]];
|
||||||
|
else
|
||||||
|
val = FAILSAFE_CHANNEL_NOPULSES;
|
||||||
if(val!=FAILSAFE_CHANNEL_HOLD && val!=FAILSAFE_CHANNEL_NOPULSES)
|
if(val!=FAILSAFE_CHANNEL_HOLD && val!=FAILSAFE_CHANNEL_NOPULSES)
|
||||||
|
{ // Failsafe values
|
||||||
val = (((val<<2)+val)>>3)+860;
|
val = (((val<<2)+val)>>3)+860;
|
||||||
|
if(ch<14)
|
||||||
|
{
|
||||||
|
packet[9 + ch*2] = val;
|
||||||
|
packet[10 + ch*2] = (val>>8)&0x0F;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
packet[10 + (ch-14)*6] &= 0x0F;
|
||||||
|
packet[10 + (ch-14)*6] |= (val)<<4;
|
||||||
|
packet[12 + (ch-14)*6] &= 0x0F;
|
||||||
|
packet[12 + (ch-14)*6] |= (val)&0xF0;
|
||||||
|
packet[14 + (ch-14)*6] &= 0x0F;
|
||||||
|
packet[14 + (ch-14)*6] |= (val>>4)&0xF0;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
val = 0x0FFF;
|
if(ch<14)
|
||||||
if(ch<14)
|
{ // no values
|
||||||
{
|
packet[9 + ch*2] = 0xff;
|
||||||
packet[9 + ch*2] = val;
|
packet[10+ ch*2] = 0xff;
|
||||||
packet[10 + ch*2] = (val>>8)&0x0F;
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
packet[10 + (ch-14)*6] |= (val)<<4;
|
|
||||||
packet[12 + (ch-14)*6] |= (val)&0xF0;
|
|
||||||
packet[14 + (ch-14)*6] |= (val>>4)&0xF0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AFHDS2A_PACKET_SETTINGS:
|
case AFHDS2A_PACKET_SETTINGS:
|
||||||
@@ -245,43 +253,17 @@ static void AFHDS2A_build_packet(uint8_t type)
|
|||||||
if(val<50 || val>400) val=50; // default is 50Hz
|
if(val<50 || val>400) val=50; // default is 50Hz
|
||||||
packet[11]= val;
|
packet[11]= val;
|
||||||
packet[12]= val >> 8;
|
packet[12]= val >> 8;
|
||||||
memset(&packet[15],0xFF,22);
|
packet[13] = sub_protocol & 0x01; // 1 -> PPM output enabled
|
||||||
#ifndef MULTI_AIR
|
packet[14]= 0x00;
|
||||||
if(sub_protocol < AFHDS2A_GYRO_OFF)
|
for(uint8_t i=15; i<37; i++)
|
||||||
{
|
packet[i] = 0xff;
|
||||||
#endif
|
packet[18] = 0x05; // ?
|
||||||
packet[13] = sub_protocol & 0x01; // 1 -> PPM output enabled
|
packet[19] = 0xdc; // ?
|
||||||
packet[14] = 0x00; // ?
|
packet[20] = 0x05; // ?
|
||||||
packet[18] = 0x05; // ?
|
if(sub_protocol&2)
|
||||||
packet[19] = 0xdc; // ?
|
packet[21] = 0xdd; // SBUS output enabled
|
||||||
packet[20] = 0x05; // ?
|
|
||||||
if(sub_protocol&2)
|
|
||||||
packet[21] = 0xdd; // SBUS output enabled
|
|
||||||
else
|
|
||||||
packet[21] = 0xde; // IBUS
|
|
||||||
#ifndef MULTI_AIR
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{//BS receivers
|
packet[21] = 0xde; // IBUS
|
||||||
if(sub_protocol == AFHDS2A_GYRO_OFF)
|
|
||||||
{
|
|
||||||
memset(&packet[15],0x00,4);
|
|
||||||
packet[22] = 0xFC; // ?
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{//AFHDS2A_GYRO_ON & AFHDS2A_GYRO_ON_REV
|
|
||||||
packet[15] = convert_channel_16b_limit(CH13,0,100); // ST Gain
|
|
||||||
packet[16] = convert_channel_16b_limit(CH14,0,100); // TH Gain
|
|
||||||
packet[17] = convert_channel_16b_limit(CH15,0,100); // Priority
|
|
||||||
if(sub_protocol == AFHDS2A_GYRO_ON_REV)
|
|
||||||
packet[17] |= 0x80; // Reverse
|
|
||||||
packet[18] = CH16_SW?(0x32|0x80):0x32; // Calib|50?
|
|
||||||
packet[19] = 0x64; // 100?
|
|
||||||
packet[20] = 0x64; // 100?
|
|
||||||
packet[22] = 0xFE; // ?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
packet[37] = 0x00;
|
packet[37] = 0x00;
|
||||||
@@ -301,9 +283,6 @@ uint16_t AFHDS2A_callback()
|
|||||||
static uint16_t packet_counter;
|
static uint16_t packet_counter;
|
||||||
uint8_t data_rx=0;
|
uint8_t data_rx=0;
|
||||||
uint16_t start;
|
uint16_t start;
|
||||||
#ifndef MULTI_AIR
|
|
||||||
static uint16_t Prev_Channel[4] = { 0,0,0,0 };
|
|
||||||
#endif
|
|
||||||
#ifndef FORCE_AFHDS2A_TUNING
|
#ifndef FORCE_AFHDS2A_TUNING
|
||||||
A7105_AdjustLOBaseFreq(1);
|
A7105_AdjustLOBaseFreq(1);
|
||||||
#endif
|
#endif
|
||||||
@@ -388,39 +367,10 @@ uint16_t AFHDS2A_callback()
|
|||||||
AFHDS2A_build_packet(packet_type);
|
AFHDS2A_build_packet(packet_type);
|
||||||
data_rx=A7105_ReadReg(A7105_00_MODE); // Check if something has been received...
|
data_rx=A7105_ReadReg(A7105_00_MODE); // Check if something has been received...
|
||||||
A7105_WriteData(AFHDS2A_TXPACKET_SIZE, hopping_frequency[hopping_frequency_no++]);
|
A7105_WriteData(AFHDS2A_TXPACKET_SIZE, hopping_frequency[hopping_frequency_no++]);
|
||||||
hopping_frequency_no &= 0x0F; // AFHDS2A_NUMFREQ
|
if(hopping_frequency_no >= AFHDS2A_NUMFREQ)
|
||||||
#if 0
|
hopping_frequency_no = 0;
|
||||||
for(uint8_t i=0; i<AFHDS2A_TXPACKET_SIZE; i++)
|
|
||||||
debug(" %02X",packet[i]);
|
|
||||||
debugln("");
|
|
||||||
#endif
|
|
||||||
#ifndef MULTI_AIR
|
|
||||||
if(sub_protocol > AFHDS2A_GYRO_OFF)
|
|
||||||
{//Gyro is on
|
|
||||||
//Check if gyro settings have changed
|
|
||||||
uint16_t val;
|
|
||||||
for(uint8_t i=0;i<4;i++)
|
|
||||||
{
|
|
||||||
val = Channel_data[CH13+i] - Prev_Channel[i];
|
|
||||||
if(val&0x8000) val ^= 0xFFFF;
|
|
||||||
if(val > 10)
|
|
||||||
{//This setting has significantly changed
|
|
||||||
Prev_Channel[i] = Channel_data[CH13+i];
|
|
||||||
packet_sent = 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(packet_sent && (packet_counter%5)==0)
|
|
||||||
{//Inform the RX of the change
|
|
||||||
packet_type = AFHDS2A_PACKET_SETTINGS;
|
|
||||||
packet_sent--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if(!(packet_counter % 1313))
|
if(!(packet_counter % 1313))
|
||||||
{//Send settings every 5s
|
|
||||||
packet_type = AFHDS2A_PACKET_SETTINGS;
|
packet_type = AFHDS2A_PACKET_SETTINGS;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef FAILSAFE_ENABLE
|
#ifdef FAILSAFE_ENABLE
|
||||||
@@ -498,6 +448,9 @@ void AFHDS2A_init()
|
|||||||
rx_id[i]=eeprom_read_byte((EE_ADDR)(addr+i));
|
rx_id[i]=eeprom_read_byte((EE_ADDR)(addr+i));
|
||||||
}
|
}
|
||||||
hopping_frequency_no = 0;
|
hopping_frequency_no = 0;
|
||||||
packet_sent = 0;
|
if(sub_protocol&0x04)
|
||||||
|
num_ch=17;
|
||||||
|
else
|
||||||
|
num_ch=14;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ uint16_t DSM_callback()
|
|||||||
#define DSM_CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2
|
#define DSM_CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2
|
||||||
#ifdef STM32_BOARD
|
#ifdef STM32_BOARD
|
||||||
#define DSM_WRITE_DELAY 1600 // Time after write to verify write complete
|
#define DSM_WRITE_DELAY 1600 // Time after write to verify write complete
|
||||||
#define DSM_READ_DELAY 300 // Time before write to check read phase, and switch channels.
|
#define DSM_READ_DELAY 400 // Time before write to check read phase, and switch channels.
|
||||||
#else
|
#else
|
||||||
#define DSM_WRITE_DELAY 1950 // Time after write to verify write complete
|
#define DSM_WRITE_DELAY 1950 // Time after write to verify write complete
|
||||||
#define DSM_READ_DELAY 600 // Time before write to check read phase, and switch channels.
|
#define DSM_READ_DELAY 600 // Time before write to check read phase, and switch channels.
|
||||||
@@ -462,7 +462,7 @@ uint16_t DSM_callback()
|
|||||||
else
|
else
|
||||||
return DSM2_SFC_PERIOD - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY;
|
return DSM2_SFC_PERIOD - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY;
|
||||||
}
|
}
|
||||||
return 10900 - DSM_WRITE_DELAY - DSM_READ_DELAY; //Was 11000 but the SR6200A needs 10900 to report telemetry correctly
|
return 11000 - DSM_WRITE_DELAY - DSM_READ_DELAY;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY;
|
return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY;
|
||||||
@@ -470,15 +470,12 @@ uint16_t DSM_callback()
|
|||||||
case DSM_CH2_READ_B:
|
case DSM_CH2_READ_B:
|
||||||
//Read telemetry
|
//Read telemetry
|
||||||
rx_phase = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
|
rx_phase = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
|
||||||
//debug("ST1:%02X ",rx_phase);
|
|
||||||
if((rx_phase & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
|
if((rx_phase & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
|
||||||
rx_phase |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
|
rx_phase |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
|
||||||
//debug("ST2:%02X ",rx_phase);
|
|
||||||
if((rx_phase & 0x07) == 0x02)
|
if((rx_phase & 0x07) == 0x02)
|
||||||
{ // good data (complete with no errors)
|
{ // good data (complete with no errors)
|
||||||
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read
|
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read
|
||||||
length=CYRF_ReadRegister(CYRF_09_RX_COUNT);
|
length=CYRF_ReadRegister(CYRF_09_RX_COUNT);
|
||||||
//debug("RX(%d)",length);
|
|
||||||
if(length>TELEMETRY_BUFFER_SIZE-2)
|
if(length>TELEMETRY_BUFFER_SIZE-2)
|
||||||
length=TELEMETRY_BUFFER_SIZE-2;
|
length=TELEMETRY_BUFFER_SIZE-2;
|
||||||
CYRF_ReadDataPacketLen(packet_in+1, length);
|
CYRF_ReadDataPacketLen(packet_in+1, length);
|
||||||
@@ -492,11 +489,8 @@ uint16_t DSM_callback()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
packet_in[0]=CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;// store RSSI of the received telemetry signal
|
packet_in[0]=CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;// store RSSI of the received telemetry signal
|
||||||
//for(uint8_t i=0;i<length+1;i++)
|
|
||||||
// debug(" %02X", packet_in[i]);
|
|
||||||
telemetry_link=1;
|
telemetry_link=1;
|
||||||
}
|
}
|
||||||
//debugln("");
|
|
||||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
|
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
|
||||||
if (phase == DSM_CH2_READ_A && (sub_protocol==DSM2_1F || sub_protocol==DSMX_1F) && num_ch < 8) // 22ms mode
|
if (phase == DSM_CH2_READ_A && (sub_protocol==DSM2_1F || sub_protocol==DSMX_1F) && num_ch < 8) // 22ms mode
|
||||||
{
|
{
|
||||||
@@ -599,7 +593,6 @@ void DSM_init()
|
|||||||
uint16_t temp = DSM_CLONE_EEPROM_OFFSET;
|
uint16_t temp = DSM_CLONE_EEPROM_OFFSET;
|
||||||
for(uint8_t i=0;i<4;i++)
|
for(uint8_t i=0;i<4;i++)
|
||||||
cyrfmfg_id[i] = eeprom_read_byte((EE_ADDR)temp++);
|
cyrfmfg_id[i] = eeprom_read_byte((EE_ADDR)temp++);
|
||||||
cyrfmfg_id[3]^=RX_num; //Model match
|
|
||||||
#if DEBUG_BIND
|
#if DEBUG_BIND
|
||||||
debugln("Using cloned ID");
|
debugln("Using cloned ID");
|
||||||
debug("Clone ID=")
|
debug("Clone ID=")
|
||||||
@@ -620,7 +613,8 @@ void DSM_init()
|
|||||||
{
|
{
|
||||||
//SUB_PROTO_VALID;
|
//SUB_PROTO_VALID;
|
||||||
CYRF_GetMfgData(cyrfmfg_id);
|
CYRF_GetMfgData(cyrfmfg_id);
|
||||||
cyrfmfg_id[3]^=RX_num; //Model match
|
//Model match
|
||||||
|
cyrfmfg_id[3]^=RX_num;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,8 +44,9 @@ static void __attribute__((unused)) E129_build_data_packet()
|
|||||||
packet[ 1] = 0xA6; // Set to A5 every few packets??
|
packet[ 1] = 0xA6; // Set to A5 every few packets??
|
||||||
|
|
||||||
//Flags
|
//Flags
|
||||||
packet[ 2] = 0xF7; // E129 High rate 0xF7, low 0xF4
|
if(sub_protocol == E129_E129)
|
||||||
if(sub_protocol == E129_C186)
|
packet[ 2] = 0xF7; // High rate 0xF7, low 0xF4
|
||||||
|
else //C186
|
||||||
{
|
{
|
||||||
packet[ 2] = 0xFA; // High rate 0xFA, medium 0xF7, low 0xF4
|
packet[ 2] = 0xFA; // High rate 0xFA, medium 0xF7, low 0xF4
|
||||||
packet[13] = bit_reverse(rx_tx_addr[2]);
|
packet[13] = bit_reverse(rx_tx_addr[2]);
|
||||||
|
|||||||
@@ -31,19 +31,6 @@ enum {
|
|||||||
FQ777_FLAG_FLIP = 0x80,
|
FQ777_FLAG_FLIP = 0x80,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
|
||||||
XBM37_B5_OK = 0x80,
|
|
||||||
XBM37_B6_RATE_LOW = 0x00,
|
|
||||||
XBM37_B6_RATE_MID = 0x01,
|
|
||||||
XBM37_B6_RATE_HIGH = 0x02,
|
|
||||||
XBM37_B6_LED_OFF = 0x04,
|
|
||||||
XBM37_B6_RTH = 0x08,
|
|
||||||
XBM37_B6_HEADLESS = 0x10,
|
|
||||||
XBM37_B6_VIDEO = 0x20,
|
|
||||||
XBM37_B6_PICTURE = 0x40,
|
|
||||||
XBM37_B6_FLIP = 0x80,
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint8_t ssv_xor[] = {0x80,0x44,0x64,0x75,0x6C,0x71,0x2A,0x36,0x7C,0xF1,0x6E,0x52,0x9,0x9D,0x1F,0x78,0x3F,0xE1,0xEE,0x16,0x6D,0xE8,0x73,0x9,0x15,0xD7,0x92,0xE7,0x3,0xBA};
|
const uint8_t ssv_xor[] = {0x80,0x44,0x64,0x75,0x6C,0x71,0x2A,0x36,0x7C,0xF1,0x6E,0x52,0x9,0x9D,0x1F,0x78,0x3F,0xE1,0xEE,0x16,0x6D,0xE8,0x73,0x9,0x15,0xD7,0x92,0xE7,0x3,0xBA};
|
||||||
uint8_t FQ777_bind_addr [] = {0xe7,0xe7,0xe7,0xe7,0x67};
|
uint8_t FQ777_bind_addr [] = {0xe7,0xe7,0xe7,0xe7,0x67};
|
||||||
|
|
||||||
@@ -100,21 +87,12 @@ static void __attribute__((unused)) FQ777_send_packet()
|
|||||||
uint8_t packet_ori[8];
|
uint8_t packet_ori[8];
|
||||||
if (IS_BIND_IN_PROGRESS)
|
if (IS_BIND_IN_PROGRESS)
|
||||||
{
|
{
|
||||||
// Byte 0 is always 0x20; bytes 1-3 are sub-protocol specific
|
// 4,5,6 = address fields
|
||||||
|
// last field is checksum of address fields
|
||||||
packet_ori[0] = 0x20;
|
packet_ori[0] = 0x20;
|
||||||
if (sub_protocol == XBM37)
|
packet_ori[1] = 0x15;
|
||||||
{
|
packet_ori[2] = 0x05;
|
||||||
packet_ori[1] = 0x14;
|
packet_ori[3] = 0x06;
|
||||||
packet_ori[2] = 0x07;
|
|
||||||
packet_ori[3] = 0x03;
|
|
||||||
}
|
|
||||||
else // FQ777
|
|
||||||
{
|
|
||||||
packet_ori[1] = 0x15;
|
|
||||||
packet_ori[2] = 0x05;
|
|
||||||
packet_ori[3] = 0x06;
|
|
||||||
}
|
|
||||||
// Bytes 4-6: address fields, byte 7: checksum of address fields (shared by both protocols)
|
|
||||||
packet_ori[4] = rx_tx_addr[0];
|
packet_ori[4] = rx_tx_addr[0];
|
||||||
packet_ori[5] = rx_tx_addr[1];
|
packet_ori[5] = rx_tx_addr[1];
|
||||||
packet_ori[6] = rx_tx_addr[2];
|
packet_ori[6] = rx_tx_addr[2];
|
||||||
@@ -122,64 +100,36 @@ static void __attribute__((unused)) FQ777_send_packet()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (sub_protocol == XBM37)
|
// throt, yaw, pitch, roll, trims, flags/left button,00,right button
|
||||||
{
|
//0-3 0x00-0x64
|
||||||
packet_ori[0] = convert_channel_16b_limit(THROTTLE,0xE1,0); // reverse channel
|
//4 roll/pitch/yaw trims. cycles through one trim at a time - 0-40 trim1, 40-80 trim2, 80-C0 trim3 (center: A0 20 60)
|
||||||
packet_ori[1] = convert_channel_16b_limit(RUDDER,0,0xE1);
|
//5 flags for throttle button, two buttons above throttle - def: 0x40
|
||||||
packet_ori[2] = convert_channel_16b_limit(AILERON,0xE1,0); // reverse channel
|
//6 00 ??
|
||||||
packet_ori[3] = convert_channel_16b_limit(ELEVATOR,0xE1,0); // reverse channel
|
//7 checksum - add values in other fields
|
||||||
packet_ori[4] = (convert_channel_8b(CH13) >> 2) + 1; // ele trim (01..20..40) front ^ plus 0x01, back - minus 0x01 per click
|
|
||||||
packet_ori[5] = 0x3F - (convert_channel_8b(CH14) >> 2) // ail trim (40..20..01) left <- plus 0x01, right -> minus 0x01 per click
|
|
||||||
| GET_FLAG(CH12_SW, XBM37_B5_OK); // bit7 = OK button ...unknown use for this model?
|
|
||||||
|
|
||||||
uint8_t rate_bits;
|
|
||||||
if (CH5_SW)
|
// Trims are usually done through the radio configuration but leaving the code here just in case...
|
||||||
rate_bits = XBM37_B6_RATE_HIGH; // high rate
|
uint8_t trim_mod = packet_count % 144;
|
||||||
else if (Channel_data[CH5] < CHANNEL_MIN_COMMAND)
|
uint8_t trim_val = 0;
|
||||||
rate_bits = XBM37_B6_RATE_LOW; // low rate
|
if (36 <= trim_mod && trim_mod < 72) // yaw
|
||||||
else
|
trim_val = 0x20; // don't modify yaw trim
|
||||||
rate_bits = XBM37_B6_RATE_MID; // medium rate
|
else
|
||||||
|
if (108 < trim_mod && trim_mod) // pitch
|
||||||
|
trim_val = 0xA0;
|
||||||
|
else // roll
|
||||||
|
trim_val = 0x60;
|
||||||
|
|
||||||
packet_ori[6] = rate_bits // bits[1:0] = rate
|
packet_ori[0] = convert_channel_16b_limit(THROTTLE,0,0x64);
|
||||||
| GET_FLAG(CH8_SW, XBM37_B6_LED_OFF) // bit2 = LED off
|
packet_ori[1] = convert_channel_16b_limit(RUDDER,0,0x64);
|
||||||
| GET_FLAG(CH11_SW, XBM37_B6_RTH) // bit3 = RTH
|
packet_ori[2] = convert_channel_16b_limit(ELEVATOR,0,0x64);
|
||||||
| GET_FLAG(CH7_SW, XBM37_B6_HEADLESS) // bit4 = headless
|
packet_ori[3] = convert_channel_16b_limit(AILERON,0,0x64);
|
||||||
| GET_FLAG(CH10_SW, XBM37_B6_VIDEO) // bit5 = video
|
packet_ori[4] = trim_val; // calculated above
|
||||||
| GET_FLAG(CH9_SW, XBM37_B6_PICTURE) // bit6 = picture
|
packet_ori[5] = GET_FLAG(CH5_SW, FQ777_FLAG_FLIP)
|
||||||
| GET_FLAG(CH6_SW, XBM37_B6_FLIP); // bit7 = flip
|
| GET_FLAG(CH7_SW, FQ777_FLAG_HEADLESS)
|
||||||
}
|
| GET_FLAG(!CH6_SW, FQ777_FLAG_RETURN)
|
||||||
else // FQ777
|
| GET_FLAG(CH8_SW,FQ777_FLAG_EXPERT);
|
||||||
{
|
packet_ori[6] = 0x00;
|
||||||
// throt, yaw, pitch, roll, trims, flags/left button,00,right button
|
// calculate checksum
|
||||||
//0-3 0x00-0x64
|
|
||||||
//4 roll/pitch/yaw trims. cycles through one trim at a time - 0-40 trim1, 40-80 trim2, 80-C0 trim3 (center: A0 20 60)
|
|
||||||
//5 flags for throttle button, two buttons above throttle - def: 0x40
|
|
||||||
//6 00 ??
|
|
||||||
//7 checksum - add values in other fields
|
|
||||||
|
|
||||||
// Trims are usually done through the radio configuration but leaving the code here just in case...
|
|
||||||
uint8_t trim_mod = packet_count % 144;
|
|
||||||
uint8_t trim_val = 0;
|
|
||||||
if (36 <= trim_mod && trim_mod < 72) // yaw
|
|
||||||
trim_val = 0x20; // don't modify yaw trim
|
|
||||||
else
|
|
||||||
if (108 < trim_mod && trim_mod) // pitch
|
|
||||||
trim_val = 0xA0;
|
|
||||||
else // roll
|
|
||||||
trim_val = 0x60;
|
|
||||||
|
|
||||||
packet_ori[0] = convert_channel_16b_limit(THROTTLE,0,0x64);
|
|
||||||
packet_ori[1] = convert_channel_16b_limit(RUDDER,0,0x64);
|
|
||||||
packet_ori[2] = convert_channel_16b_limit(ELEVATOR,0,0x64);
|
|
||||||
packet_ori[3] = convert_channel_16b_limit(AILERON,0,0x64);
|
|
||||||
packet_ori[4] = trim_val; // calculated above
|
|
||||||
packet_ori[5] = GET_FLAG(CH5_SW, FQ777_FLAG_FLIP)
|
|
||||||
| GET_FLAG(CH7_SW, FQ777_FLAG_HEADLESS)
|
|
||||||
| GET_FLAG(!CH6_SW, FQ777_FLAG_RETURN)
|
|
||||||
| GET_FLAG(CH8_SW,FQ777_FLAG_EXPERT);
|
|
||||||
packet_ori[6] = 0x00;
|
|
||||||
}
|
|
||||||
// Data packet checksum: sum of bytes 0-6 (not applied to bind packets)
|
|
||||||
uint8_t checksum = 0;
|
uint8_t checksum = 0;
|
||||||
for (int i = 0; i < 7; ++i)
|
for (int i = 0; i < 7; ++i)
|
||||||
checksum += packet_ori[i];
|
checksum += packet_ori[i];
|
||||||
@@ -231,17 +181,12 @@ void FQ777_init(void)
|
|||||||
BIND_IN_PROGRESS; // autobind protocol
|
BIND_IN_PROGRESS; // autobind protocol
|
||||||
bind_counter = FQ777_BIND_COUNT;
|
bind_counter = FQ777_BIND_COUNT;
|
||||||
packet_count=0;
|
packet_count=0;
|
||||||
// Sub-protocol hop channel table: first 3 channels differ; channel[3]=0x07 is shared
|
hopping_frequency[0] = 0x4D;
|
||||||
static const uint8_t hop_ch[2][3] = {
|
hopping_frequency[1] = 0x43;
|
||||||
{0x4D, 0x43, 0x27}, // FQ777
|
hopping_frequency[2] = 0x27;
|
||||||
{0x49, 0x34, 0x26}, // XBM-37
|
|
||||||
};
|
|
||||||
hopping_frequency[0] = hop_ch[sub_protocol][0];
|
|
||||||
hopping_frequency[1] = hop_ch[sub_protocol][1];
|
|
||||||
hopping_frequency[2] = hop_ch[sub_protocol][2];
|
|
||||||
hopping_frequency[3] = 0x07;
|
hopping_frequency[3] = 0x07;
|
||||||
hopping_frequency_no=0;
|
hopping_frequency_no=0;
|
||||||
rx_tx_addr[2] = (sub_protocol == XBM37) ? (RX_num & 0x3F) : 0x00; // XBM-37 uses receiver number (0-63) for model match capability
|
rx_tx_addr[2] = 0x00;
|
||||||
rx_tx_addr[3] = 0xe7;
|
rx_tx_addr[3] = 0xe7;
|
||||||
rx_tx_addr[4] = 0x67;
|
rx_tx_addr[4] = 0x67;
|
||||||
FQ777_RF_init();
|
FQ777_RF_init();
|
||||||
|
|||||||
@@ -34,29 +34,14 @@ Multiprotocol is distributed in the hope that it will be useful,
|
|||||||
#define FX620_CH_OFFSET 1
|
#define FX620_CH_OFFSET 1
|
||||||
|
|
||||||
#define FX9630_PACKET_PERIOD 8124 //8156 on QIDI-560
|
#define FX9630_PACKET_PERIOD 8124 //8156 on QIDI-560
|
||||||
|
#define FX9630_BIND_PACKET_PERIOD 8124
|
||||||
#define FX9630_BIND_CHANNEL 51
|
#define FX9630_BIND_CHANNEL 51
|
||||||
#define FX9630_PAYLOAD_SIZE 8
|
#define FX9630_PAYLOAD_SIZE 8
|
||||||
#define FX9630_NUM_CHANNELS 3
|
#define FX9630_NUM_CHANNELS 3
|
||||||
#define FX9630_WRITE_TIME 500
|
|
||||||
|
|
||||||
#define FX_QF012_PACKET_PERIOD 12194
|
|
||||||
#define FX_QF012_RX_PAYLOAD_SIZE 3
|
|
||||||
|
|
||||||
#define FX_BM26_BIND_CHANNEL 40
|
|
||||||
#define FX_BM26_PACKET_PERIOD 14066
|
|
||||||
|
|
||||||
#define FX_A570_PACKET_PERIOD 10270
|
|
||||||
|
|
||||||
//#define FORCE_FX620_ID
|
//#define FORCE_FX620_ID
|
||||||
//#define FORCE_FX9630_ID
|
//#define FORCE_FX9630_ID
|
||||||
//#define FORCE_QIDI_ID
|
//#define FORCE_QIDI_ID
|
||||||
//#define FORCE_FX_A570_ID
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
FX_DATA=0,
|
|
||||||
FX_RX,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void __attribute__((unused)) FX_send_packet()
|
static void __attribute__((unused)) FX_send_packet()
|
||||||
{
|
{
|
||||||
@@ -67,20 +52,21 @@ static void __attribute__((unused)) FX_send_packet()
|
|||||||
{
|
{
|
||||||
XN297_Hopping(hopping_frequency_no++);
|
XN297_Hopping(hopping_frequency_no++);
|
||||||
if(sub_protocol >= FX9630)
|
if(sub_protocol >= FX9630)
|
||||||
{ // FX9630 & FX_Q560 & FX_QF012 & FX_A570
|
{ // FX9630 & FX_Q560
|
||||||
|
XN297_SetTXAddr(rx_tx_addr, 4);
|
||||||
if (hopping_frequency_no >= FX9630_NUM_CHANNELS)
|
if (hopping_frequency_no >= FX9630_NUM_CHANNELS)
|
||||||
{
|
{
|
||||||
hopping_frequency_no = 0;
|
hopping_frequency_no = 0;
|
||||||
if(sub_protocol == FX9630)
|
if(sub_protocol == FX9630)
|
||||||
{
|
{
|
||||||
trim_ch++;
|
trim_ch++;
|
||||||
trim_ch &= 3;
|
if(trim_ch > 3) trim_ch = 0;
|
||||||
}
|
}
|
||||||
else // FX_Q560 & FX_QF012 & FX_A570
|
else // FX_Q560
|
||||||
trim_ch = 0;
|
trim_ch = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // FX816 & FX620
|
else // FX816 and FX620
|
||||||
{
|
{
|
||||||
hopping_frequency_no &= 0x03;
|
hopping_frequency_no &= 0x03;
|
||||||
}
|
}
|
||||||
@@ -90,7 +76,23 @@ static void __attribute__((unused)) FX_send_packet()
|
|||||||
|
|
||||||
//Channels
|
//Channels
|
||||||
uint8_t val;
|
uint8_t val;
|
||||||
if (sub_protocol == FX816 || sub_protocol == FX620)
|
if (sub_protocol >= FX9630)
|
||||||
|
{ // FX9630 & FX_Q560
|
||||||
|
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);
|
||||||
|
val = trim_ch==0 ? 0x20 : (convert_channel_8b(trim_ch + CH6) >> 2); // no trim on Throttle
|
||||||
|
packet[4] = val; // Trim for channel x 0C..20..34
|
||||||
|
packet[5] = (trim_ch << 4) // channel x << 4
|
||||||
|
| GET_FLAG(CH5_SW, 0x01) // DR toggle swich: 0 small throw, 1 large throw / Q560 acrobatic
|
||||||
|
// FX9630 =>0:6G small throw, 1:6G large throw, 2:3D
|
||||||
|
// QIDI-550=>0:3D, 1:6G, 2:Torque
|
||||||
|
| (Channel_data[CH6] < CHANNEL_MIN_COMMAND ? 0x00 : (Channel_data[CH6] > CHANNEL_MAX_COMMAND ? 0x04 : 0x02));
|
||||||
|
if(sub_protocol == FX_Q560)
|
||||||
|
packet[5] |= GET_FLAG(CH7_SW, 0x18); // Q560 LED flag 0x10 conflicting with trim_ch... Corrected on new boards using 0x08 instead
|
||||||
|
}
|
||||||
|
else // FX816 and FX620
|
||||||
{
|
{
|
||||||
uint8_t offset=sub_protocol == FX816 ? FX816_CH_OFFSET:FX620_CH_OFFSET;
|
uint8_t offset=sub_protocol == FX816 ? FX816_CH_OFFSET:FX620_CH_OFFSET;
|
||||||
val=convert_channel_8b(AILERON);
|
val=convert_channel_8b(AILERON);
|
||||||
@@ -102,60 +104,6 @@ static void __attribute__((unused)) FX_send_packet()
|
|||||||
packet[offset] = sub_protocol == FX816 ? 0:0x7F;
|
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
|
packet[offset+1] = convert_channel_16b_limit(THROTTLE,0,100); //FX816:0x00..0x63, FX620:0x00..0x5E but that should work
|
||||||
}
|
}
|
||||||
else if (sub_protocol == FX_A570)
|
|
||||||
{
|
|
||||||
packet[0] = convert_channel_16b_limit(THROTTLE,0x1C,0xE4);
|
|
||||||
packet[1] = convert_channel_16b_limit(AILERON,0xE4,0x1C);
|
|
||||||
packet[2] = convert_channel_16b_limit(ELEVATOR,0xE4,0x1C);
|
|
||||||
packet[3] = convert_channel_16b_limit(RUDDER,0x1C,0xE4);
|
|
||||||
// Trims - Ruddder L:01 R:02, Aileron L:03 R:04, Elevator Fwd:05 Back:06
|
|
||||||
packet[4] = (Channel_data[CH10] < CHANNEL_MIN_COMMAND ? 0x01 : GET_FLAG(CH10_SW, 0x02)) // Rudder trim
|
|
||||||
| (Channel_data[CH11] < CHANNEL_MIN_COMMAND ? 0x03 : GET_FLAG(CH11_SW, 0x04)) // Aileron trim
|
|
||||||
| (Channel_data[CH12] < CHANNEL_MIN_COMMAND ? 0x06 : GET_FLAG(CH12_SW, 0x05)); // Elevator trim
|
|
||||||
packet[5] = GET_FLAG(CH5_SW, 0x40) // motors stop
|
|
||||||
// A570 flight modes = 0>vertical flight(3 axis mode):00, 1>flat flight(6G):02, 2>vertical flight(2 axis mode):04
|
|
||||||
| (Channel_data[CH6] < CHANNEL_MIN_COMMAND ? 0x00 : (Channel_data[CH6] > CHANNEL_MAX_COMMAND ? 0x04 : 0x02))
|
|
||||||
| GET_FLAG(CH7_SW, 0x01) // 0:low rate, 1:high rate
|
|
||||||
| GET_FLAG(CH8_SW, 0x08) // LED color change
|
|
||||||
| GET_FLAG(CH9_SW, 0x10); // LED off
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // FX9630 & FX_Q560 & FX_QF012 & FX_BM26
|
|
||||||
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);
|
|
||||||
if ( sub_protocol == FX_BM26 ) // BM26 Ail, Elev, Rud range between 0x00-0x3F-0x7F
|
|
||||||
{
|
|
||||||
packet[1] >>= 1;
|
|
||||||
packet[2] >>= 1;
|
|
||||||
packet[3] >>= 1;
|
|
||||||
}
|
|
||||||
val = trim_ch==0 ? 0x20 : (convert_channel_8b(trim_ch + CH6) >> 2); // no trim on Throttle
|
|
||||||
packet[4] = val; // Trim for channel x 0C..20..34
|
|
||||||
packet[5] = (trim_ch << 4) // channel x << 4
|
|
||||||
| GET_FLAG(CH5_SW, (sub_protocol == FX_QF012 ? 0x08 : 0x01)) // DR toggle swich: 0 small throw, 1 large throw / Q560 acrobatic / QF012 Special effects
|
|
||||||
// FX9630 =>0:6G small throw, 1:6G large throw, 2:3D
|
|
||||||
// QIDI-550=>0:3D, 1:6G, 2:Torque
|
|
||||||
// QF012=>0:beginner(6G), 1:mid(3D), 2:expert(Gyro off)
|
|
||||||
| (Channel_data[CH6] < CHANNEL_MIN_COMMAND ? 0x00 : (Channel_data[CH6] > CHANNEL_MAX_COMMAND ? 0x04 : 0x02));
|
|
||||||
if(sub_protocol == FX_Q560)
|
|
||||||
packet[5] |= GET_FLAG(CH7_SW, 0x18); // Q560 LED flag 0x10 conflicting with trim_ch... Corrected on new boards using 0x08 instead
|
|
||||||
else if (sub_protocol == FX_QF012)
|
|
||||||
packet[5] |= GET_FLAG(CH7_SW, 0x40) // QF012 invert flight
|
|
||||||
| GET_FLAG(CH8_SW, 0x80); // QF012 Restore fine tunning midpoint
|
|
||||||
else if ( sub_protocol == FX_BM26 )
|
|
||||||
{
|
|
||||||
packet[5] &= 0xC0;
|
|
||||||
packet[5] += 0x40;
|
|
||||||
// BM26 P51=>0:beginner(6G), 1:mid(3D), 2:expert(Gyro off)
|
|
||||||
packet[5] |= (Channel_data[CH6] < CHANNEL_MIN_COMMAND ? 0x08 : (Channel_data[CH6] > CHANNEL_MAX_COMMAND ? 0x0C : 0x0A));
|
|
||||||
packet[6] = GET_FLAG( CH5_SW, 0x20) // 6G Roll
|
|
||||||
| GET_FLAG(!CH7_SW, 0x08) // Light control switch, default on
|
|
||||||
| GET_FLAG(!CH8_SW, 0x10) // Turn signal switch, default on
|
|
||||||
| GET_FLAG( CH9_SW, 0x01); // Gyro Calibration
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Bind and specifics
|
//Bind and specifics
|
||||||
if(sub_protocol == FX816)
|
if(sub_protocol == FX816)
|
||||||
@@ -182,7 +130,7 @@ static void __attribute__((unused)) FX_send_packet()
|
|||||||
packet[5] = 0xAB; // Is it based on ID??
|
packet[5] = 0xAB; // Is it based on ID??
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // FX9630 & FX_Q560 & FX_QF012 & FX_BM26 & FX_A570
|
else // FX9630 & FX_Q560
|
||||||
{
|
{
|
||||||
if(IS_BIND_IN_PROGRESS)
|
if(IS_BIND_IN_PROGRESS)
|
||||||
{
|
{
|
||||||
@@ -204,8 +152,6 @@ static void __attribute__((unused)) FX_send_packet()
|
|||||||
val = val ^ 0xFF;
|
val = val ^ 0xFF;
|
||||||
packet[last_packet_idx]=val;
|
packet[last_packet_idx]=val;
|
||||||
|
|
||||||
if ( IS_BIND_IN_PROGRESS && sub_protocol == FX_BM26 ) packet[7] = packet[6];
|
|
||||||
|
|
||||||
//Debug
|
//Debug
|
||||||
#if 0
|
#if 0
|
||||||
for(uint8_t i=0;i<packet_length;i++)
|
for(uint8_t i=0;i<packet_length;i++)
|
||||||
@@ -222,7 +168,6 @@ static void __attribute__((unused)) FX_send_packet()
|
|||||||
static void __attribute__((unused)) FX_RF_init()
|
static void __attribute__((unused)) FX_RF_init()
|
||||||
{
|
{
|
||||||
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
|
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
|
||||||
packet_length = FX9630_PAYLOAD_SIZE; // default
|
|
||||||
if(sub_protocol == FX816)
|
if(sub_protocol == FX816)
|
||||||
{
|
{
|
||||||
XN297_SetTXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc", 5);
|
XN297_SetTXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc", 5);
|
||||||
@@ -237,23 +182,12 @@ static void __attribute__((unused)) FX_RF_init()
|
|||||||
packet_period = FX620_BIND_PACKET_PERIOD;
|
packet_period = FX620_BIND_PACKET_PERIOD;
|
||||||
packet_length = FX620_PAYLOAD_SIZE;
|
packet_length = FX620_PAYLOAD_SIZE;
|
||||||
}
|
}
|
||||||
else if (sub_protocol == FX_BM26)
|
else // FX9630 & FX_Q560
|
||||||
{
|
|
||||||
XN297_SetTXAddr((uint8_t *)"\x12\x34\x10\x10", 4);
|
|
||||||
XN297_RFChannel(FX_BM26_BIND_CHANNEL);
|
|
||||||
packet_period = FX_BM26_PACKET_PERIOD;
|
|
||||||
}
|
|
||||||
else if(sub_protocol == FX_A570)
|
|
||||||
{
|
|
||||||
XN297_SetTXAddr((uint8_t *)"\x56\x78\x92\x13", 4);
|
|
||||||
XN297_RFChannel(FX9630_BIND_CHANNEL);
|
|
||||||
packet_period = FX_A570_PACKET_PERIOD;
|
|
||||||
}
|
|
||||||
else // FX9630 & FX_Q560 & FX_QF012
|
|
||||||
{
|
{
|
||||||
XN297_SetTXAddr((uint8_t *)"\x56\x78\x90\x12", 4);
|
XN297_SetTXAddr((uint8_t *)"\x56\x78\x90\x12", 4);
|
||||||
XN297_RFChannel(FX9630_BIND_CHANNEL);
|
XN297_RFChannel(FX9630_BIND_CHANNEL);
|
||||||
packet_period = sub_protocol == FX_QF012 ? FX_QF012_PACKET_PERIOD : FX9630_PACKET_PERIOD;
|
packet_period = FX9630_BIND_PACKET_PERIOD;
|
||||||
|
packet_length = FX9630_PAYLOAD_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,17 +214,15 @@ static void __attribute__((unused)) FX_initialize_txid()
|
|||||||
for(uint8_t i=1;i<FX_NUM_CHANNELS;i++)
|
for(uint8_t i=1;i<FX_NUM_CHANNELS;i++)
|
||||||
hopping_frequency[i] = i*10 + hopping_frequency[0];
|
hopping_frequency[i] = i*10 + hopping_frequency[0];
|
||||||
}
|
}
|
||||||
else // FX9630 & FX_Q560 & FX_QF012 & FX_BM26 & FX_A570
|
else // FX9630 & FX_Q560
|
||||||
{
|
{
|
||||||
//??? Need to find out how the first RF channel is calculated ???
|
|
||||||
hopping_frequency[0] = sub_protocol == FX_BM26? 0x0C : 0x13;
|
|
||||||
if (sub_protocol == FX_A570) hopping_frequency[0] = 0x0E;
|
|
||||||
//Other 2 RF channels are sent during the bind phase so they can be whatever
|
|
||||||
hopping_frequency[1] = RX_num & 0x0F + 0x1A;
|
|
||||||
hopping_frequency[2] = rx_tx_addr[3] & 0x0F + 0x38;
|
|
||||||
#ifdef FORCE_FX9630_ID
|
#ifdef FORCE_FX9630_ID
|
||||||
memcpy(rx_tx_addr,(uint8_t*)"\xCE\x31\x9B\x73", 4);
|
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
|
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
|
#endif
|
||||||
#ifdef FORCE_QIDI_ID
|
#ifdef FORCE_QIDI_ID
|
||||||
memcpy(rx_tx_addr,(uint8_t*)"\x23\xDC\x76\xA2", 4);
|
memcpy(rx_tx_addr,(uint8_t*)"\x23\xDC\x76\xA2", 4);
|
||||||
@@ -300,101 +232,26 @@ static void __attribute__((unused)) FX_initialize_txid()
|
|||||||
//memcpy(rx_tx_addr,(uint8_t*)"\x38\xC7\x6D\x8D", 4);
|
//memcpy(rx_tx_addr,(uint8_t*)"\x38\xC7\x6D\x8D", 4);
|
||||||
//memcpy(hopping_frequency,"\x0D\x20\x3A", FX9630_NUM_CHANNELS);
|
//memcpy(hopping_frequency,"\x0D\x20\x3A", FX9630_NUM_CHANNELS);
|
||||||
#endif
|
#endif
|
||||||
// BM26 rx_tx_addr: "\x17\x03\x00\x00", hopping_frequency: 0x0C,0x30,0x43(12,48,67)
|
//??? Need to find out how the first RF channel is calculated ???
|
||||||
#ifdef FORCE_FX_A570_ID
|
}
|
||||||
memcpy(rx_tx_addr,(uint8_t*)"\xA9\x56\xFC\x1C", 4);
|
|
||||||
memcpy(hopping_frequency,"\x0E\x1F\x39", FX9630_NUM_CHANNELS); //Original dump=>14=0x0E,31=0x1F,57=0x39
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t FX_callback()
|
uint16_t FX_callback()
|
||||||
{
|
{
|
||||||
#ifdef FX_HUB_TELEMETRY
|
#ifdef MULTI_SYNC
|
||||||
bool rx=false;
|
telemetry_set_input_sync(packet_period);
|
||||||
static uint8_t telem_count = 0;
|
#endif
|
||||||
switch(phase)
|
if(bind_counter)
|
||||||
|
if(--bind_counter==0)
|
||||||
{
|
{
|
||||||
case FX_DATA:
|
BIND_DONE;
|
||||||
rx = XN297_IsRX();
|
if(sub_protocol == FX620)
|
||||||
XN297_SetTxRxMode(TXRX_OFF);
|
{
|
||||||
#endif
|
XN297_SetTXAddr(rx_tx_addr, 3);
|
||||||
#ifdef MULTI_SYNC
|
packet_period = FX620_PACKET_PERIOD;
|
||||||
telemetry_set_input_sync(packet_period);
|
}
|
||||||
#endif
|
|
||||||
if(bind_counter)
|
|
||||||
if(--bind_counter==0)
|
|
||||||
{
|
|
||||||
BIND_DONE;
|
|
||||||
if(sub_protocol == FX620)
|
|
||||||
{
|
|
||||||
XN297_SetTXAddr(rx_tx_addr, 3);
|
|
||||||
packet_period = FX620_PACKET_PERIOD;
|
|
||||||
}
|
|
||||||
else if(sub_protocol >= FX9630)
|
|
||||||
{ // FX9630 & FX_Q560 & FX_QF012
|
|
||||||
XN297_SetTXAddr(rx_tx_addr, 4);
|
|
||||||
#ifdef FX_HUB_TELEMETRY
|
|
||||||
XN297_SetRXAddr(rx_tx_addr, FX_QF012_RX_PAYLOAD_SIZE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FX_send_packet();
|
|
||||||
#ifdef FX_HUB_TELEMETRY
|
|
||||||
if (sub_protocol == FX816 || sub_protocol == FX620 || sub_protocol == FX_A570)
|
|
||||||
break;
|
|
||||||
if(rx)
|
|
||||||
{
|
|
||||||
debug("RX");
|
|
||||||
if(XN297_ReadPayload(packet_in, FX_QF012_RX_PAYLOAD_SIZE))
|
|
||||||
{//Good CRC
|
|
||||||
telemetry_link = 1;
|
|
||||||
telemetry_lost = 0;
|
|
||||||
telem_count = 0;
|
|
||||||
if ( sub_protocol == FX_BM26 )
|
|
||||||
v_lipo1 = packet_in[0] < packet_in[2] ? 60:81; // packets: AA 00 55 -> 55 00 AA = low voltage 3.7V
|
|
||||||
else
|
|
||||||
v_lipo1 = packet_in[1] ? 60:81; // packets: A5 00 11 -> A5 01 11 = low voltage 3.7V
|
|
||||||
#if 0
|
|
||||||
for(uint8_t i=0; i < FX_QF012_RX_PAYLOAD_SIZE; i++)
|
|
||||||
debug(" %02X", packet_in[i]);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
debugln();
|
|
||||||
}
|
|
||||||
if(telem_count > 4*63) // Around 3.5 sec with no telemetry
|
|
||||||
telemetry_lost = 1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
telem_count++;
|
|
||||||
if(!telemetry_lost && (telem_count & 0x3F) == 0)
|
|
||||||
{// Should have received a telem packet but... Send telem to the radio to keep it alive
|
|
||||||
telemetry_link = 1;
|
|
||||||
#if 0
|
|
||||||
debugln("Miss");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
phase++;
|
|
||||||
return FX9630_WRITE_TIME;
|
|
||||||
default: //FX_RX
|
|
||||||
/* { // Wait for packet to be sent before switching to receive mode
|
|
||||||
uint16_t start=(uint16_t)micros(), count=0;
|
|
||||||
while ((uint16_t)((uint16_t)micros()-(uint16_t)start) < 500)
|
|
||||||
{
|
|
||||||
if(XN297_IsPacketSent())
|
|
||||||
break;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
debug("%d",count);
|
|
||||||
} */
|
|
||||||
//Switch to RX
|
|
||||||
XN297_SetTxRxMode(TXRX_OFF);
|
|
||||||
XN297_SetTxRxMode(RX_EN);
|
|
||||||
phase = FX_DATA;
|
|
||||||
return packet_period - FX9630_WRITE_TIME;
|
|
||||||
}
|
}
|
||||||
#endif
|
FX_send_packet();
|
||||||
return packet_period;
|
return packet_period;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,11 +262,6 @@ void FX_init()
|
|||||||
FX_RF_init();
|
FX_RF_init();
|
||||||
hopping_frequency_no = 0;
|
hopping_frequency_no = 0;
|
||||||
bind_counter=FX_BIND_COUNT;
|
bind_counter=FX_BIND_COUNT;
|
||||||
#ifdef FX_HUB_TELEMETRY
|
|
||||||
RX_RSSI = 100; // Dummy value
|
|
||||||
telemetry_lost = 1;
|
|
||||||
phase = FX_DATA;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -78,8 +78,7 @@ static void __attribute__((unused)) HONTAI_send_packet()
|
|||||||
packet[i+3] = convert_channel_16b_limit(CH_TAER[i],0x28,0xD8);
|
packet[i+3] = convert_channel_16b_limit(CH_TAER[i],0x28,0xD8);
|
||||||
packet[6] ^= 0xFF; //Reverse rudder
|
packet[6] ^= 0xFF; //Reverse rudder
|
||||||
//flags
|
//flags
|
||||||
packet[1] = GET_FLAG(CH8_SW, 0x04) //Gyro calibration (momentary)
|
packet[1] = GET_FLAG(CH8_SW, 0x04); //Gyro calibration (momentary)
|
||||||
|GET_FLAG(CH11_SW, 0x10); //XK K270 optical flow switch
|
|
||||||
// |GET_FLAG(CH_SW, 0x08) //Unk long press second top right button (momentary)
|
// |GET_FLAG(CH_SW, 0x08) //Unk long press second top right button (momentary)
|
||||||
// |GET_FLAG(CH_SW, 0x10) //Unk short press second top right button (toggle)
|
// |GET_FLAG(CH_SW, 0x10) //Unk short press second top right button (toggle)
|
||||||
// |GET_FLAG(CH_SW, 0x40) //Unk short press second top left button (momentary)
|
// |GET_FLAG(CH_SW, 0x40) //Unk short press second top left button (momentary)
|
||||||
|
|||||||
@@ -48,19 +48,32 @@ static void __attribute__((unused)) KF606_send_packet()
|
|||||||
hopping_frequency_no ^= 1; // 2 RF channels
|
hopping_frequency_no ^= 1; // 2 RF channels
|
||||||
|
|
||||||
packet[0] = 0x55;
|
packet[0] = 0x55;
|
||||||
if(sub_protocol == KF606_ZCZ50) len--;
|
packet[1] = convert_channel_8b(THROTTLE); // 0..255
|
||||||
packet[len-3] = convert_channel_8b(THROTTLE); // 0..255
|
|
||||||
// Deadband is needed on aileron, 40 gives +-6%
|
// Deadband is needed on aileron, 40 gives +-6%
|
||||||
packet[len-2] = convert_channel_8b_limit_deadband(AILERON,0x00,0x80,0xFF,40); // Aileron: High rate:2B..80..DA
|
switch(sub_protocol)
|
||||||
uint8_t p3;
|
{
|
||||||
p3 = convert_channel_8b(CH5)>>3; // Aileron trim must be on a separated channel 01..10..1F
|
case KF606_KF606:
|
||||||
p3 += (packet[2]-0x80)>>3; // Drive trims for more aileron authority
|
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
|
||||||
if(p3 > 0x80)
|
packet[3] = convert_channel_16b_limit(CH5,0xC1,0xDF); // Aileron trim must be on a separated channel C1..D0..DF
|
||||||
p3 = 0x01;
|
break;
|
||||||
else if(p3 > 0x1F)
|
case KF606_MIG320:
|
||||||
p3 = 0x1F;
|
packet[2] = convert_channel_8b_limit_deadband(AILERON,0x00,0x80,0xFF,40); // Aileron: High rate:2B..80..DA
|
||||||
p3 |= GET_FLAG(CH6_SW, 0xC0); // 0xC0 and 0xE0 are both turning the LED off, not sure if there is another hidden feature
|
packet[3] = convert_channel_16b_limit(CH5,0x01,0x1F); // Aileron trim must be on a separated channel 01..10..1F
|
||||||
packet[len-1] = p3;
|
packet[3] += (packet[2]-0x80)>>3; // Drive trims for more aileron authority
|
||||||
|
if(packet[3] > 0x80)
|
||||||
|
packet[3] = 0x01;
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sub_protocol == KF606_MIG320)
|
if(sub_protocol == KF606_MIG320)
|
||||||
|
|||||||
@@ -136,13 +136,10 @@ uint16_t KAMTOM_callback()
|
|||||||
{
|
{
|
||||||
BIND_DONE;
|
BIND_DONE;
|
||||||
if(packet_in[0] == 0xA0 && packet_in[14] == rx_tx_addr[2] && packet_in[15] == rx_tx_addr[3])
|
if(packet_in[0] == 0xA0 && packet_in[14] == rx_tx_addr[2] && packet_in[15] == rx_tx_addr[3])
|
||||||
{//Good packet with our TXID
|
{
|
||||||
rx_tx_addr[0] = packet_in[9];
|
rx_tx_addr[0] = packet_in[9];
|
||||||
rx_tx_addr[1] = packet_in[10];
|
rx_tx_addr[1] = packet_in[10];
|
||||||
#ifdef KAMTOM_HUB_TELEMETRY
|
//if(packet_in[1] == 0x03) // low voltage
|
||||||
v_lipo1 = packet_in[1] == 0x03 ? 0x00:0xFF; // low voltage
|
|
||||||
telemetry_link = 1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
for(uint8_t i=0; i < KAMTOM_PAYLOAD_SIZE; i++)
|
for(uint8_t i=0; i < KAMTOM_PAYLOAD_SIZE; i++)
|
||||||
@@ -177,9 +174,6 @@ void KAMTOM_init()
|
|||||||
bind_counter = KAMTOM_BIND_COUNT;
|
bind_counter = KAMTOM_BIND_COUNT;
|
||||||
phase = KAMTOM_DATA;
|
phase = KAMTOM_DATA;
|
||||||
hopping_frequency_no = 0;
|
hopping_frequency_no = 0;
|
||||||
#ifdef KAMTOM_HUB_TELEMETRY
|
|
||||||
RX_RSSI = 100; // Dummy value
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -112,10 +112,7 @@ void KYOSHO3_init()
|
|||||||
debugln("RF CH: %02X",hopping_frequency[0]);
|
debugln("RF CH: %02X",hopping_frequency[0]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(IS_BIND_IN_PROGRESS)
|
CYRF_ConfigRFChannel(hopping_frequency[0]);
|
||||||
CYRF_ConfigRFChannel(0x04);
|
|
||||||
else
|
|
||||||
CYRF_ConfigRFChannel(hopping_frequency[0]);
|
|
||||||
|
|
||||||
bind_counter = 8217;
|
bind_counter = 8217;
|
||||||
phase = 0;
|
phase = 0;
|
||||||
|
|||||||
@@ -189,8 +189,8 @@ static void __attribute__((unused)) MT99XX_send_packet()
|
|||||||
packet[1] = convert_channel_16b_limit(RUDDER ,0x00,0xE1); // rudder
|
packet[1] = convert_channel_16b_limit(RUDDER ,0x00,0xE1); // rudder
|
||||||
packet[2] = convert_channel_16b_limit(AILERON ,0xE1,0x00); // aileron
|
packet[2] = convert_channel_16b_limit(AILERON ,0xE1,0x00); // aileron
|
||||||
packet[3] = convert_channel_16b_limit(ELEVATOR,0x00,0xE1); // elevator
|
packet[3] = convert_channel_16b_limit(ELEVATOR,0x00,0xE1); // elevator
|
||||||
packet[4] = (convert_channel_8b(CH10) ^ 0xFF) >> 2; // aileron trim (3F..20..00)
|
packet[4] = 0x20; // pitch trim (0x3f-0x20-0x00)
|
||||||
packet[5] = convert_channel_8b(CH11) >> 2; // elevator trim (00..20..3F)
|
packet[5] = 0x20; // roll trim (0x00-0x20-0x3f)
|
||||||
packet[6] = GET_FLAG( CH5_SW, FLAG_MT_FLIP );
|
packet[6] = GET_FLAG( CH5_SW, FLAG_MT_FLIP );
|
||||||
if(sub_protocol != PA18+8)
|
if(sub_protocol != PA18+8)
|
||||||
packet[7] = h7_mys_byte[hopping_frequency_no]; // next rf channel index ?
|
packet[7] = h7_mys_byte[hopping_frequency_no]; // next rf channel index ?
|
||||||
@@ -337,7 +337,7 @@ static void __attribute__((unused)) MT99XX_send_packet()
|
|||||||
XN297_SetTxRxMode(TX_EN);
|
XN297_SetTxRxMode(TX_EN);
|
||||||
XN297_WritePayload(packet, MT99XX_PACKET_SIZE);
|
XN297_WritePayload(packet, MT99XX_PACKET_SIZE);
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
for(uint8_t i=0; i<MT99XX_PACKET_SIZE; i++)
|
for(uint8_t i=0; i<MT99XX_PACKET_SIZE; i++)
|
||||||
debug(" %02X",packet[i]);
|
debug(" %02X",packet[i]);
|
||||||
debugln();
|
debugln();
|
||||||
@@ -530,7 +530,7 @@ void MT99XX_init(void)
|
|||||||
bind_counter = MT99XX_BIND_COUNT;
|
bind_counter = MT99XX_BIND_COUNT;
|
||||||
if(IS_BIND_DONE)
|
if(IS_BIND_DONE)
|
||||||
{
|
{
|
||||||
if(sub_protocol != A180 && sub_protocol != DRAGON && sub_protocol != F949G && sub_protocol != PA18+8 && sub_protocol != SU35+8)
|
if(sub_protocol != A180 && sub_protocol != DRAGON && sub_protocol != F949G && sub_protocol != PA18+8)
|
||||||
BIND_IN_PROGRESS; // autobind protocol
|
BIND_IN_PROGRESS; // autobind protocol
|
||||||
else
|
else
|
||||||
bind_counter = 1;
|
bind_counter = 1;
|
||||||
|
|||||||
@@ -50,19 +50,12 @@ static void __attribute__((unused)) MOULDKG_send_packet()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint8_t n = num_ch<<2;
|
uint8_t n = num_ch<<2;
|
||||||
if(sub_protocol == MOULDKG_ANALOG4 || sub_protocol == MOULDKG_ANALOG6 )
|
if(sub_protocol == MOULDKG_ANALOG)
|
||||||
{
|
{
|
||||||
packet[0] = 0x36;
|
packet[0] = 0x36;
|
||||||
const uint8_t ch[]={ 1,0,2,3,5,4 };
|
uint8_t ch[]={ 1,0,2,3 };
|
||||||
if(sub_protocol == MOULDKG_ANALOG6)
|
for(uint8_t i=0;i<4;i++)
|
||||||
n += num_ch<<1;
|
packet[i+4] = convert_channel_8b(ch[i]+n);
|
||||||
for(uint8_t i=0;i<6;i++)
|
|
||||||
{
|
|
||||||
if( (i > 3 && sub_protocol == MOULDKG_ANALOG4) || i + n > 15)
|
|
||||||
packet[i+4] = 0x80; //Centered channel
|
|
||||||
else
|
|
||||||
packet[i+4] = convert_channel_8b(ch[i]+n);
|
|
||||||
}
|
|
||||||
len = MOULDKG_PAYLOAD_SIZE_ANALOG;
|
len = MOULDKG_PAYLOAD_SIZE_ANALOG;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -20,12 +20,12 @@
|
|||||||
20,FY326,FY326,FY319
|
20,FY326,FY326,FY319
|
||||||
21,Futaba,SFHSS
|
21,Futaba,SFHSS
|
||||||
22,J6PRO
|
22,J6PRO
|
||||||
23,FQ777,124,XBM37
|
23,FQ777
|
||||||
24,ASSAN
|
24,ASSAN
|
||||||
25,FrskyV
|
25,FrskyV
|
||||||
26,HONTAI,HONTAI,JJRCX1,X5C1,FQ777_951,XKK170
|
26,HONTAI,HONTAI,JJRCX1,X5C1,FQ777_951,XKK170
|
||||||
27,OpnLrs
|
27,OpnLrs
|
||||||
28,AFHDS2A,PWM_IBUS,PPM_IBUS,PWM_SBUS,PPM_SBUS,Gyro_Off,Gyro_On,G_On_Rev
|
28,AFHDS2A,PWM_IBUS,PPM_IBUS,PWM_SBUS,PPM_SBUS,PWM_IB16,PPM_IB16,PWM_SB16,PPM_SB16
|
||||||
29,Q2X2,Q222,Q242,Q282
|
29,Q2X2,Q222,Q242,Q282
|
||||||
30,WK2x01,WK2801,WK2401,W6_5_1,W6_6_1,W6_HEL,W6_HEL_I
|
30,WK2x01,WK2801,WK2401,W6_5_1,W6_6_1,W6_HEL,W6_HEL_I
|
||||||
31,Q303,Q303,CX35,CX10D,CX10WD
|
31,Q303,Q303,CX35,CX10D,CX10WD
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
55,Frsky_RX,Multi,CloneTX,EraseTX,CPPM
|
55,Frsky_RX,Multi,CloneTX,EraseTX,CPPM
|
||||||
56,AFHDS2A_RX,Multi,CPPM
|
56,AFHDS2A_RX,Multi,CPPM
|
||||||
57,HoTT,Sync,No_Sync
|
57,HoTT,Sync,No_Sync
|
||||||
58,FX,FX816,FX620,9630,Q560,QF012,BM26,A570
|
58,FX,816,620,9630,Q560
|
||||||
59,Bayang_RX,Multi,CPPM
|
59,Bayang_RX,Multi,CPPM
|
||||||
60,Pelikan,Pro,Lite,SCX24
|
60,Pelikan,Pro,Lite,SCX24
|
||||||
61,EazyRC
|
61,EazyRC
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
71,JJRC345,JJRC345,SkyTmblr
|
71,JJRC345,JJRC345,SkyTmblr
|
||||||
72,Q90C
|
72,Q90C
|
||||||
73,Kyosho,FHSS,Hype
|
73,Kyosho,FHSS,Hype
|
||||||
74,RadioLink,Surface,Air,DumboRC,RC4G,Dumbo_P
|
74,RadioLink,Surface,Air,DumboRC,RC4G
|
||||||
75,---
|
75,---
|
||||||
76,Realacc
|
76,Realacc
|
||||||
77,OMP
|
77,OMP
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
87,IKEA
|
87,IKEA
|
||||||
88,WILLIFM
|
88,WILLIFM
|
||||||
89,Losi
|
89,Losi
|
||||||
90,MouldKg,A4444,D4444,A664
|
90,MouldKg,Analog,Digit
|
||||||
91,Xerall
|
91,Xerall
|
||||||
92,MT99xx,PA18,SU35
|
92,MT99xx,PA18,SU35
|
||||||
93,Kyosho2,KT-17
|
93,Kyosho2,KT-17
|
||||||
@@ -99,7 +99,4 @@
|
|||||||
100,YuXiang
|
100,YuXiang
|
||||||
102,JIABAILE,STD,GYRO
|
102,JIABAILE,STD,GYRO
|
||||||
103,H36
|
103,H36
|
||||||
104,KAMTOM
|
104,KAMTOM
|
||||||
105,Shenqi2
|
|
||||||
106,WL91x
|
|
||||||
107,WPL
|
|
||||||
@@ -36,7 +36,6 @@ const char STR_MT99XX[] ="MT99XX";
|
|||||||
const char STR_MT99XX2[] ="MT99XX2";
|
const char STR_MT99XX2[] ="MT99XX2";
|
||||||
const char STR_MJXQ[] ="MJXq";
|
const char STR_MJXQ[] ="MJXq";
|
||||||
const char STR_SHENQI[] ="Shenqi";
|
const char STR_SHENQI[] ="Shenqi";
|
||||||
const char STR_SHENQI2[] ="Shenqi2";
|
|
||||||
const char STR_FY326[] ="FY326";
|
const char STR_FY326[] ="FY326";
|
||||||
const char STR_FUTABA[] ="Futaba";
|
const char STR_FUTABA[] ="Futaba";
|
||||||
const char STR_J6PRO[] ="J6 Pro";
|
const char STR_J6PRO[] ="J6 Pro";
|
||||||
@@ -117,8 +116,6 @@ const char STR_YUXIANG[] ="YuXiang";
|
|||||||
const char STR_UDIRC[] ="UDIRC";
|
const char STR_UDIRC[] ="UDIRC";
|
||||||
const char STR_JIABAILE[] ="JIABAILE";
|
const char STR_JIABAILE[] ="JIABAILE";
|
||||||
const char STR_KAMTOM[] ="KAMTOM";
|
const char STR_KAMTOM[] ="KAMTOM";
|
||||||
const char STR_WL91X[] ="WL91x";
|
|
||||||
const char STR_WPL[] ="WPL";
|
|
||||||
|
|
||||||
const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20";
|
const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20";
|
||||||
const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501";
|
const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501";
|
||||||
@@ -147,9 +144,8 @@ const char STR_SUBTYPE_MT99[] = "\x06""MT99\0 ""H7\0 ""YZ\0 ""LS\0 "
|
|||||||
const char STR_SUBTYPE_MT992[] = "\x04""PA18""SU35";
|
const char STR_SUBTYPE_MT992[] = "\x04""PA18""SU35";
|
||||||
const char STR_SUBTYPE_MJXQ[] = "\x07""WLH08\0 ""X600\0 ""X800\0 ""H26D\0 ""E010\0 ""H26WH\0 ""Phoenix";
|
const char STR_SUBTYPE_MJXQ[] = "\x07""WLH08\0 ""X600\0 ""X800\0 ""H26D\0 ""E010\0 ""H26WH\0 ""Phoenix";
|
||||||
const char STR_SUBTYPE_FY326[] = "\x05""Std\0 ""FY319";
|
const char STR_SUBTYPE_FY326[] = "\x05""Std\0 ""FY319";
|
||||||
const char STR_SUBTYPE_FQ777[] = "\x05""124\0 ""XBM37";
|
|
||||||
const char STR_SUBTYPE_HONTAI[] = "\x06""Std\0 ""JJRCX1""X5C1\0 ""FQ_951""XKK170";
|
const char STR_SUBTYPE_HONTAI[] = "\x06""Std\0 ""JJRCX1""X5C1\0 ""FQ_951""XKK170";
|
||||||
const char STR_SUBTYPE_AFHDS2A[] = "\x08""PWM,IBUS""PPM,IBUS""PWM,SBUS""PPM,SBUS""Gyro_Off""Gyro_On\0""G_On_Rev";
|
const char STR_SUBTYPE_AFHDS2A[] = "\x08""PWM,IBUS""PPM,IBUS""PWM,SBUS""PPM,SBUS""PWM,IB16""PPM,IB16""PWM,SB16""PPM,SB16";
|
||||||
const char STR_SUBTYPE_Q2X2[] = "\x04""Q222""Q242""Q282";
|
const char STR_SUBTYPE_Q2X2[] = "\x04""Q222""Q242""Q282";
|
||||||
const char STR_SUBTYPE_WK2x01[] = "\x06""WK2801""WK2401""W6_5_1""W6_6_1""W6_HeL""W6_HeI";
|
const char STR_SUBTYPE_WK2x01[] = "\x06""WK2801""WK2401""W6_5_1""W6_6_1""W6_HeL""W6_HeI";
|
||||||
const char STR_SUBTYPE_Q303[] = "\x06""Std\0 ""CX35\0 ""CX10D\0""CX10WD";
|
const char STR_SUBTYPE_Q303[] = "\x06""Std\0 ""CX35\0 ""CX10D\0""CX10WD";
|
||||||
@@ -180,17 +176,17 @@ const char STR_SUBTYPE_WFLY2[] = "\x05""RF20x";
|
|||||||
const char STR_SUBTYPE_HOTT[] = "\x07""Sync\0 ""No_Sync";
|
const char STR_SUBTYPE_HOTT[] = "\x07""Sync\0 ""No_Sync";
|
||||||
const char STR_SUBTYPE_PELIKAN[] = "\x05""Pro\0 ""Lite\0""SCX24";
|
const char STR_SUBTYPE_PELIKAN[] = "\x05""Pro\0 ""Lite\0""SCX24";
|
||||||
const char STR_SUBTYPE_V761[] = "\x05""3ch\0 ""4ch\0 ""TOPRC";
|
const char STR_SUBTYPE_V761[] = "\x05""3ch\0 ""4ch\0 ""TOPRC";
|
||||||
const char STR_SUBTYPE_RLINK[] = "\x07""Surface""Air\0 ""DumboRC""RC4G\0 ""Dumbo_P";
|
const char STR_SUBTYPE_RLINK[] = "\x07""Surface""Air\0 ""DumboRC""RC4G\0 ";
|
||||||
const char STR_SUBTYPE_KYOSHO[] = "\x04""FHSS""Hype";
|
const char STR_SUBTYPE_KYOSHO[] = "\x04""FHSS""Hype";
|
||||||
const char STR_SUBTYPE_KYOSHO2[] = "\x05""KT-17";
|
const char STR_SUBTYPE_KYOSHO2[] = "\x05""KT-17";
|
||||||
const char STR_SUBTYPE_KYOSHO3[] = "\x03""ASF";
|
const char STR_SUBTYPE_KYOSHO3[] = "\x03""ASF";
|
||||||
const char STR_SUBTYPE_FUTABA[] = "\x05""SFHSS";
|
const char STR_SUBTYPE_FUTABA[] = "\x05""SFHSS";
|
||||||
const char STR_SUBTYPE_JJRC345[] = "\x08""JJRC345\0""SkyTmblr";
|
const char STR_SUBTYPE_JJRC345[] = "\x08""JJRC345\0""SkyTmblr";
|
||||||
const char STR_SUBTYPE_MOULDKG[] = "\x05""A4444""D4444""A664\0";
|
const char STR_SUBTYPE_MOULDKG[] = "\x06""Analog""Digit\0";
|
||||||
const char STR_SUBTYPE_KF606[] = "\x06""KF606\0""MIG320""ZCZ50\0";
|
const char STR_SUBTYPE_KF606[] = "\x06""KF606\0""MIG320""ZCZ50\0";
|
||||||
const char STR_SUBTYPE_E129[] = "\x04""E129""C186";
|
const char STR_SUBTYPE_E129[] = "\x04""E129""C186";
|
||||||
const char STR_SUBTYPE_FX[] = "\x05""FX816""FX620""9630\0""Q560\0""QF012""BM26\0""A570\0";
|
const char STR_SUBTYPE_FX[] = "\x04""816\0""620\0""9630""Q560";
|
||||||
const char STR_SUBTYPE_SGF22[] = "\x04""F22\0""F22S""J20\0""CX10";
|
const char STR_SUBTYPE_SGF22[] = "\x04""F22\0""F22S""J20\0";
|
||||||
const char STR_SUBTYPE_JIABAILE[] = "\x04""Std\0""Gyro";
|
const char STR_SUBTYPE_JIABAILE[] = "\x04""Std\0""Gyro";
|
||||||
#define NO_SUBTYPE nullptr
|
#define NO_SUBTYPE nullptr
|
||||||
|
|
||||||
@@ -309,13 +305,13 @@ const mm_protocol_definition multi_protocols[] = {
|
|||||||
{PROTO_FLYSKY, STR_FLYSKY, STR_SUBTYPE_FLYSKY, 5, OPTION_NONE, 0, 1, SW_A7105, FLYSKY_init, FLYSKY_callback },
|
{PROTO_FLYSKY, STR_FLYSKY, STR_SUBTYPE_FLYSKY, 5, OPTION_NONE, 0, 1, SW_A7105, FLYSKY_init, FLYSKY_callback },
|
||||||
#endif
|
#endif
|
||||||
#if defined(AFHDS2A_A7105_INO)
|
#if defined(AFHDS2A_A7105_INO)
|
||||||
{PROTO_AFHDS2A, STR_AFHDS2A, STR_SUBTYPE_AFHDS2A, 7, OPTION_SRVFREQ, 1, 1, SW_A7105, AFHDS2A_init, AFHDS2A_callback },
|
{PROTO_AFHDS2A, STR_AFHDS2A, STR_SUBTYPE_AFHDS2A, 8, OPTION_SRVFREQ, 1, 1, SW_A7105, AFHDS2A_init, AFHDS2A_callback },
|
||||||
#endif
|
#endif
|
||||||
#if defined(AFHDS2A_RX_A7105_INO)
|
#if defined(AFHDS2A_RX_A7105_INO)
|
||||||
{PROTO_AFHDS2A_RX, STR_AFHDS2A_RX,STR_CPPM, NBR_CPPM, OPTION_NONE, 0, 0, SW_A7105, AFHDS2A_RX_init, AFHDS2A_RX_callback },
|
{PROTO_AFHDS2A_RX, STR_AFHDS2A_RX,STR_CPPM, NBR_CPPM, OPTION_NONE, 0, 0, SW_A7105, AFHDS2A_RX_init, AFHDS2A_RX_callback },
|
||||||
#endif
|
#endif
|
||||||
#if defined(FQ777_NRF24L01_INO)
|
#if defined(FQ777_NRF24L01_INO)
|
||||||
{PROTO_FQ777, STR_FQ777, STR_SUBTYPE_FQ777, 2, OPTION_NONE, 0, 0, SW_NRF, FQ777_init, FQ777_callback },
|
{PROTO_FQ777, STR_FQ777, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, FQ777_init, FQ777_callback },
|
||||||
#endif
|
#endif
|
||||||
//OpenTX 2.3.x issue: DO NOT CHANGE ORDER below
|
//OpenTX 2.3.x issue: DO NOT CHANGE ORDER below
|
||||||
#if defined(FRSKY_RX_CC2500_INO)
|
#if defined(FRSKY_RX_CC2500_INO)
|
||||||
@@ -346,7 +342,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 },
|
{PROTO_FUTABA, STR_FUTABA, STR_SUBTYPE_FUTABA, 1, OPTION_RFTUNE, 1, 1, SW_CC2500, SFHSS_init, SFHSS_callback },
|
||||||
#endif
|
#endif
|
||||||
#if defined(FX_NRF24L01_INO)
|
#if defined(FX_NRF24L01_INO)
|
||||||
{PROTO_FX, STR_FX, STR_SUBTYPE_FX, 7, OPTION_NONE, 0, 0, SW_NRF, FX_init, FX_callback },
|
{PROTO_FX, STR_FX, STR_SUBTYPE_FX, 4, OPTION_NONE, 0, 0, SW_NRF, FX_init, FX_callback },
|
||||||
#endif
|
#endif
|
||||||
#if defined(FY326_NRF24L01_INO)
|
#if defined(FY326_NRF24L01_INO)
|
||||||
{PROTO_FY326, STR_FY326, STR_SUBTYPE_FY326, 2, OPTION_NONE, 0, 0, SW_NRF, FY326_init, FY326_callback },
|
{PROTO_FY326, STR_FY326, STR_SUBTYPE_FY326, 2, OPTION_NONE, 0, 0, SW_NRF, FY326_init, FY326_callback },
|
||||||
@@ -427,7 +423,7 @@ const mm_protocol_definition multi_protocols[] = {
|
|||||||
{PROTO_MLINK, STR_MLINK, NO_SUBTYPE, 0, OPTION_NONE, 1, 0, SW_CYRF, MLINK_init, MLINK_callback },
|
{PROTO_MLINK, STR_MLINK, NO_SUBTYPE, 0, OPTION_NONE, 1, 0, SW_CYRF, MLINK_init, MLINK_callback },
|
||||||
#endif
|
#endif
|
||||||
#if defined(MOULDKG_NRF24L01_INO)
|
#if defined(MOULDKG_NRF24L01_INO)
|
||||||
{PROTO_MOULDKG, STR_MOULDKG, STR_SUBTYPE_MOULDKG, 3, OPTION_OPTION, 0, 0, SW_NRF, MOULDKG_init, MOULDKG_callback },
|
{PROTO_MOULDKG, STR_MOULDKG, STR_SUBTYPE_MOULDKG, 2, OPTION_OPTION, 0, 0, SW_NRF, MOULDKG_init, MOULDKG_callback },
|
||||||
#endif
|
#endif
|
||||||
#if defined(MT99XX_CCNRF_INO)
|
#if defined(MT99XX_CCNRF_INO)
|
||||||
{PROTO_MT99XX, STR_MT99XX, STR_SUBTYPE_MT99, 8, OPTION_NONE, 0, 0, SW_NRF, MT99XX_init, MT99XX_callback },
|
{PROTO_MT99XX, STR_MT99XX, STR_SUBTYPE_MT99, 8, OPTION_NONE, 0, 0, SW_NRF, MT99XX_init, MT99XX_callback },
|
||||||
@@ -460,7 +456,7 @@ const mm_protocol_definition multi_protocols[] = {
|
|||||||
{PROTO_Q90C, STR_Q90C, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, Q90C_init, Q90C_callback },
|
{PROTO_Q90C, STR_Q90C, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, Q90C_init, Q90C_callback },
|
||||||
#endif
|
#endif
|
||||||
#if defined(RLINK_CC2500_INO)
|
#if defined(RLINK_CC2500_INO)
|
||||||
{PROTO_RLINK, STR_RLINK, STR_SUBTYPE_RLINK, 5, OPTION_RFTUNE, 0, 0, SW_CC2500, RLINK_init, RLINK_callback },
|
{PROTO_RLINK, STR_RLINK, STR_SUBTYPE_RLINK, 4, OPTION_RFTUNE, 0, 0, SW_CC2500, RLINK_init, RLINK_callback },
|
||||||
#endif
|
#endif
|
||||||
#if defined(REALACC_NRF24L01_INO)
|
#if defined(REALACC_NRF24L01_INO)
|
||||||
{PROTO_REALACC, STR_REALACC, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, REALACC_init, REALACC_callback },
|
{PROTO_REALACC, STR_REALACC, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, REALACC_init, REALACC_callback },
|
||||||
@@ -475,14 +471,11 @@ const mm_protocol_definition multi_protocols[] = {
|
|||||||
{PROTO_SCORPIO, STR_SCORPIO, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_CYRF, SCORPIO_init, SCORPIO_callback },
|
{PROTO_SCORPIO, STR_SCORPIO, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_CYRF, SCORPIO_init, SCORPIO_callback },
|
||||||
#endif
|
#endif
|
||||||
#if defined(SGF22_NRF24L01_INO)
|
#if defined(SGF22_NRF24L01_INO)
|
||||||
{PROTO_SGF22, STR_SGF22, STR_SUBTYPE_SGF22, 4, OPTION_NONE, 0, 0, SW_NRF, SGF22_init, SGF22_callback },
|
{PROTO_SGF22, STR_SGF22, STR_SUBTYPE_SGF22, 3, OPTION_NONE, 0, 0, SW_NRF, SGF22_init, SGF22_callback },
|
||||||
#endif
|
#endif
|
||||||
#if defined(SHENQI_NRF24L01_INO)
|
#if defined(SHENQI_NRF24L01_INO)
|
||||||
{PROTO_SHENQI, STR_SHENQI, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, SHENQI_init, SHENQI_callback },
|
{PROTO_SHENQI, STR_SHENQI, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, SHENQI_init, SHENQI_callback },
|
||||||
#endif
|
#endif
|
||||||
#if defined(SHENQI2_NRF24L01_INO)
|
|
||||||
{PROTO_SHENQI2, STR_SHENQI2, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, SHENQI2_init, SHENQI2_callback },
|
|
||||||
#endif
|
|
||||||
#if defined(SKYARTEC_CC2500_INO)
|
#if defined(SKYARTEC_CC2500_INO)
|
||||||
{PROTO_SKYARTEC, STR_SKYARTEC, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 1, SW_CC2500, SKYARTEC_init, SKYARTEC_callback },
|
{PROTO_SKYARTEC, STR_SKYARTEC, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 1, SW_CC2500, SKYARTEC_init, SKYARTEC_callback },
|
||||||
#endif
|
#endif
|
||||||
@@ -507,6 +500,9 @@ const mm_protocol_definition multi_protocols[] = {
|
|||||||
#if defined(V911S_CCNRF_INO)
|
#if defined(V911S_CCNRF_INO)
|
||||||
{PROTO_V911S, STR_V911S, STR_SUBTYPE_V911S, 2, OPTION_RFTUNE, 0, 0, SW_NRF, V911S_init, V911S_callback },
|
{PROTO_V911S, STR_V911S, STR_SUBTYPE_V911S, 2, OPTION_RFTUNE, 0, 0, SW_NRF, V911S_init, V911S_callback },
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(WK2x01_CYRF6936_INO)
|
||||||
|
{PROTO_WK2x01, STR_WK2x01, STR_SUBTYPE_WK2x01, 6, OPTION_NONE, 1, 1, SW_CYRF, WK_init, WK_callback },
|
||||||
|
#endif
|
||||||
#if defined(WFLY_CYRF6936_INO)
|
#if defined(WFLY_CYRF6936_INO)
|
||||||
{PROTO_WFLY, STR_WFLY, STR_SUBTYPE_WFLY, 1, OPTION_NONE, 1, 0, SW_CYRF, WFLY_init, WFLY_callback },
|
{PROTO_WFLY, STR_WFLY, STR_SUBTYPE_WFLY, 1, OPTION_NONE, 1, 0, SW_CYRF, WFLY_init, WFLY_callback },
|
||||||
#endif
|
#endif
|
||||||
@@ -514,15 +510,6 @@ const mm_protocol_definition multi_protocols[] = {
|
|||||||
{PROTO_WFLY2, STR_WFLY2, STR_SUBTYPE_WFLY2, 1, OPTION_OPTION, 1, 0, SW_A7105, WFLY2_init, WFLY2_callback },
|
{PROTO_WFLY2, STR_WFLY2, STR_SUBTYPE_WFLY2, 1, OPTION_OPTION, 1, 0, SW_A7105, WFLY2_init, WFLY2_callback },
|
||||||
// {PROTO_WFLY2, STR_WFLY2, STR_SUBTYPE_WFLY2, 1, OPTION_WBUS, 1, 0, SW_A7105, WFLY2_init, WFLY2_callback },// crash OpenTX...
|
// {PROTO_WFLY2, STR_WFLY2, STR_SUBTYPE_WFLY2, 1, OPTION_WBUS, 1, 0, SW_A7105, WFLY2_init, WFLY2_callback },// crash OpenTX...
|
||||||
#endif
|
#endif
|
||||||
#if defined(WK2x01_CYRF6936_INO)
|
|
||||||
{PROTO_WK2x01, STR_WK2x01, STR_SUBTYPE_WK2x01, 6, OPTION_NONE, 1, 1, SW_CYRF, WK_init, WK_callback },
|
|
||||||
#endif
|
|
||||||
#if defined(WL91X_CCNRF_INO)
|
|
||||||
{PROTO_WL91X, STR_WL91X, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, WL91X_init, WL91X_callback },
|
|
||||||
#endif
|
|
||||||
#if defined(WPL_NRF24L01_INO)
|
|
||||||
{PROTO_WPL, STR_WPL, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, WPL_init, WPL_callback },
|
|
||||||
#endif
|
|
||||||
#if defined(XERALL_NRF24L01_INO)
|
#if defined(XERALL_NRF24L01_INO)
|
||||||
{PROTO_XERALL, STR_XERALL, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, XERALL_init, XERALL_callback },
|
{PROTO_XERALL, STR_XERALL, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, XERALL_init, XERALL_callback },
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
#define VERSION_MAJOR 1
|
#define VERSION_MAJOR 1
|
||||||
#define VERSION_MINOR 3
|
#define VERSION_MINOR 3
|
||||||
#define VERSION_REVISION 4
|
#define VERSION_REVISION 4
|
||||||
#define VERSION_PATCH_LEVEL 58
|
#define VERSION_PATCH_LEVEL 34
|
||||||
|
|
||||||
#define MODE_SERIAL 0
|
#define MODE_SERIAL 0
|
||||||
|
|
||||||
@@ -132,9 +132,6 @@ enum PROTOCOLS
|
|||||||
PROTO_JIABAILE = 102, // =>NRF24L01
|
PROTO_JIABAILE = 102, // =>NRF24L01
|
||||||
PROTO_H36 = 103, // =>NRF24L01
|
PROTO_H36 = 103, // =>NRF24L01
|
||||||
PROTO_KAMTOM = 104, // =>NRF24L01
|
PROTO_KAMTOM = 104, // =>NRF24L01
|
||||||
PROTO_SHENQI2 = 105, // =>NRF24L01
|
|
||||||
PROTO_WL91X = 106, // =>CC2500 & NRF24L01
|
|
||||||
PROTO_WPL = 107, // =>NRF24L01
|
|
||||||
|
|
||||||
PROTO_NANORF = 126, // =>NRF24L01
|
PROTO_NANORF = 126, // =>NRF24L01
|
||||||
PROTO_TEST = 127, // =>CC2500
|
PROTO_TEST = 127, // =>CC2500
|
||||||
@@ -160,13 +157,14 @@ enum Hubsan
|
|||||||
};
|
};
|
||||||
enum AFHDS2A
|
enum AFHDS2A
|
||||||
{
|
{
|
||||||
PWM_IBUS = 0,
|
PWM_IBUS = 0,
|
||||||
PPM_IBUS = 1,
|
PPM_IBUS = 1,
|
||||||
PWM_SBUS = 2,
|
PWM_SBUS = 2,
|
||||||
PPM_SBUS = 3,
|
PPM_SBUS = 3,
|
||||||
AFHDS2A_GYRO_OFF = 4,
|
PWM_IB16 = 4,
|
||||||
AFHDS2A_GYRO_ON = 5,
|
PPM_IB16 = 5,
|
||||||
AFHDS2A_GYRO_ON_REV = 6,
|
PWM_SB16 = 6,
|
||||||
|
PPM_SB16 = 7,
|
||||||
};
|
};
|
||||||
enum Hisky
|
enum Hisky
|
||||||
{
|
{
|
||||||
@@ -418,11 +416,6 @@ enum ESKY
|
|||||||
ESKY_STD = 0,
|
ESKY_STD = 0,
|
||||||
ESKY_ET4 = 1,
|
ESKY_ET4 = 1,
|
||||||
};
|
};
|
||||||
enum FQ777
|
|
||||||
{
|
|
||||||
FQ777 = 0,
|
|
||||||
XBM37 = 1,
|
|
||||||
};
|
|
||||||
enum FRSKY_RX
|
enum FRSKY_RX
|
||||||
{
|
{
|
||||||
FRSKY_RX = 0,
|
FRSKY_RX = 0,
|
||||||
@@ -473,13 +466,11 @@ enum RLINK
|
|||||||
RLINK_AIR = 1,
|
RLINK_AIR = 1,
|
||||||
RLINK_DUMBORC = 2,
|
RLINK_DUMBORC = 2,
|
||||||
RLINK_RC4G = 3,
|
RLINK_RC4G = 3,
|
||||||
RLINK_DUMBORC_P = 4,
|
|
||||||
};
|
};
|
||||||
enum MOULDKG
|
enum MOULDKG
|
||||||
{
|
{
|
||||||
MOULDKG_ANALOG4 = 0,
|
MOULDKG_ANALOG = 0,
|
||||||
MOULDKG_DIGIT4 = 1,
|
MOULDKG_DIGIT = 1,
|
||||||
MOULDKG_ANALOG6 = 2,
|
|
||||||
};
|
};
|
||||||
enum KF606
|
enum KF606
|
||||||
{
|
{
|
||||||
@@ -498,16 +489,12 @@ enum FX
|
|||||||
FX620 = 1,
|
FX620 = 1,
|
||||||
FX9630 = 2,
|
FX9630 = 2,
|
||||||
FX_Q560 = 3,
|
FX_Q560 = 3,
|
||||||
FX_QF012 = 4,
|
|
||||||
FX_BM26 = 5,
|
|
||||||
FX_A570 = 6,
|
|
||||||
};
|
};
|
||||||
enum SGF22
|
enum SGF22
|
||||||
{
|
{
|
||||||
SGF22_F22 = 0,
|
SGF22_F22 = 0,
|
||||||
SGF22_F22S = 1,
|
SGF22_F22S = 1,
|
||||||
SGF22_J20 = 2,
|
SGF22_J20 = 2,
|
||||||
SGF22_CX10 = 3,
|
|
||||||
};
|
};
|
||||||
enum JIABAILE
|
enum JIABAILE
|
||||||
{
|
{
|
||||||
@@ -585,7 +572,6 @@ enum MultiPacketTypes
|
|||||||
MULTI_TELEMETRY_MLINK = 15,
|
MULTI_TELEMETRY_MLINK = 15,
|
||||||
MULTI_TELEMETRY_CONFIG = 16,
|
MULTI_TELEMETRY_CONFIG = 16,
|
||||||
MULTI_TELEMETRY_PROTO = 17,
|
MULTI_TELEMETRY_PROTO = 17,
|
||||||
MULTI_TELEMETRY_RLINK = 18,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Macros
|
// Macros
|
||||||
@@ -1202,8 +1188,6 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
|||||||
RLINK_SURFACE 0
|
RLINK_SURFACE 0
|
||||||
RLINK_AIR 1
|
RLINK_AIR 1
|
||||||
RLINK_DUMBORC 2
|
RLINK_DUMBORC 2
|
||||||
RLINK_RC4G 3
|
|
||||||
RLINK_DUMBORC_P 4
|
|
||||||
|
|
||||||
Power value => 0x80 0=High/1=Low
|
Power value => 0x80 0=High/1=Low
|
||||||
Stream[3] = option_protocol;
|
Stream[3] = option_protocol;
|
||||||
@@ -1231,7 +1215,6 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
|||||||
FrSkyX and FrSkyX2: Stream[27..34] during normal operation unstuffed SPort data to be sent
|
FrSkyX and FrSkyX2: Stream[27..34] during normal operation unstuffed SPort data to be sent
|
||||||
HoTT: Stream[27] 1 byte for telemetry type
|
HoTT: Stream[27] 1 byte for telemetry type
|
||||||
DSM: Stream[27..33] Forward Programming
|
DSM: Stream[27..33] Forward Programming
|
||||||
RadioLink/DumboRC P: Stream[27..35] raw command payload, used to send failsafe and gyro settings
|
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
Multiprotocol telemetry/command definition for OpenTX and erskyTX
|
Multiprotocol telemetry/command definition for OpenTX and erskyTX
|
||||||
@@ -1382,9 +1365,5 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
|||||||
data[n+2] = number of sub protocols
|
data[n+2] = number of sub protocols
|
||||||
data[n+3] = sub protocols text length, only sent if nbr_sub != 0
|
data[n+3] = sub protocols text length, only sent if nbr_sub != 0
|
||||||
data[n+4..] = sub protocol names, only sent if nbr_sub != 0
|
data[n+4..] = sub protocol names, only sent if nbr_sub != 0
|
||||||
|
|
||||||
Type 0x12 RadioLink/DumboRC P raw command payload
|
|
||||||
length: variable
|
|
||||||
data[0..] = raw command payload, used to send failsafe and gyro settings
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -265,11 +265,6 @@ uint8_t packet_in[TELEMETRY_BUFFER_SIZE];//telemetry receiving packets
|
|||||||
uint8_t CONFIG_SerialRX_val[7];
|
uint8_t CONFIG_SerialRX_val[7];
|
||||||
bool CONFIG_SerialRX=false;
|
bool CONFIG_SerialRX=false;
|
||||||
#endif
|
#endif
|
||||||
#ifdef RLINK_HUB_TELEMETRY
|
|
||||||
uint8_t RLINK_SerialRX_val[8];
|
|
||||||
uint8_t RLINK_SerialRX_len=0;
|
|
||||||
bool RLINK_SerialRX=false;
|
|
||||||
#endif
|
|
||||||
#endif // TELEMETRY
|
#endif // TELEMETRY
|
||||||
|
|
||||||
uint8_t multi_protocols_index=0xFF;
|
uint8_t multi_protocols_index=0xFF;
|
||||||
@@ -1582,15 +1577,6 @@ void update_serial_data()
|
|||||||
CONFIG_SerialRX=true;
|
CONFIG_SerialRX=true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef RLINK_HUB_TELEMETRY
|
|
||||||
if(protocol==PROTO_RLINK && sub_protocol==RLINK_DUMBORC_P
|
|
||||||
&& rx_len>27 && rx_len<=27+sizeof(RLINK_SerialRX_val))
|
|
||||||
{//DumboRC P raw command payload from Lua/multiBuffer bridge
|
|
||||||
RLINK_SerialRX_len=rx_len-27;
|
|
||||||
memcpy(RLINK_SerialRX_val, (const void *)&rx_ok_buff[27], RLINK_SerialRX_len);
|
|
||||||
RLINK_SerialRX=true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RX_DONOTUPDATE_off;
|
RX_DONOTUPDATE_off;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
// Radiolink surface protocol. TXs: RC4GS,RC6GS. Compatible RXs:R7FG(Std),R6FG,R6F,R8EF,R8FM,R8F,R4FGM
|
// Radiolink surface protocol. TXs: RC4GS,RC6GS. Compatible RXs:R7FG(Std),R6FG,R6F,R8EF,R8FM,R8F,R4FGM
|
||||||
|
|
||||||
#if defined(RLINK_CC2500_INO)
|
#if defined(RLINK_CC2500_INO)
|
||||||
|
|
||||||
@@ -37,7 +37,6 @@ enum {
|
|||||||
|
|
||||||
uint32_t RLINK_rand1;
|
uint32_t RLINK_rand1;
|
||||||
uint32_t RLINK_rand2;
|
uint32_t RLINK_rand2;
|
||||||
uint32_t RLINK_pseudo;
|
|
||||||
|
|
||||||
static uint32_t __attribute__((unused)) RLINK_prng_next(uint32_t r)
|
static uint32_t __attribute__((unused)) RLINK_prng_next(uint32_t r)
|
||||||
{
|
{
|
||||||
@@ -85,7 +84,7 @@ static void __attribute__((unused)) RLINK_shuffle_freqs(uint32_t seed)
|
|||||||
static void __attribute__((unused)) RLINK_hop()
|
static void __attribute__((unused)) RLINK_hop()
|
||||||
{
|
{
|
||||||
uint8_t inc=3*(rx_tx_addr[0]&3);
|
uint8_t inc=3*(rx_tx_addr[0]&3);
|
||||||
|
|
||||||
// init hop table
|
// init hop table
|
||||||
for(uint8_t i=0; i<RLINK_HOP; i++)
|
for(uint8_t i=0; i<RLINK_HOP; i++)
|
||||||
hopping_frequency[i] = (12*i) + inc;
|
hopping_frequency[i] = (12*i) + inc;
|
||||||
@@ -94,79 +93,12 @@ static void __attribute__((unused)) RLINK_hop()
|
|||||||
RLINK_shuffle_freqs(RLINK_compute_start_id(rx_tx_addr[0] + (rx_tx_addr[1] << 8)));
|
RLINK_shuffle_freqs(RLINK_compute_start_id(rx_tx_addr[0] + (rx_tx_addr[1] << 8)));
|
||||||
RLINK_shuffle_freqs(RLINK_compute_start_id(rx_tx_addr[2] + (rx_tx_addr[3] << 8)));
|
RLINK_shuffle_freqs(RLINK_compute_start_id(rx_tx_addr[2] + (rx_tx_addr[3] << 8)));
|
||||||
|
|
||||||
// replace one of the channel randomly
|
// replace one of the channel randomely
|
||||||
rf_ch_num=random(0xfefefefe)%0x11; // 0x00..0x10
|
rf_ch_num=random(0xfefefefe)%0x11; // 0x00..0x10
|
||||||
if(inc==9) inc=6; // frequency exception
|
if(inc==9) inc=6; // frequency exception
|
||||||
hopping_frequency[rf_ch_num]=12*16+inc;
|
hopping_frequency[rf_ch_num]=12*16+inc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __attribute__((unused)) RLINK_hop_RC4G()
|
|
||||||
{
|
|
||||||
// Find 2 unused channels
|
|
||||||
// first channel is a multiple of 3 between 00 and 5D
|
|
||||||
// second channel is a multiple of 3 between 63 and BD
|
|
||||||
CC2500_Strobe(CC2500_SIDLE);
|
|
||||||
CC2500_WriteReg(CC2500_17_MCSM1,0x3C);
|
|
||||||
CC2500_Strobe(CC2500_SFRX);
|
|
||||||
CC2500_SetTxRxMode(RX_EN);
|
|
||||||
CC2500_Strobe(CC2500_SRX);
|
|
||||||
delayMilliseconds(1); //wait for RX mode
|
|
||||||
uint16_t val;
|
|
||||||
uint8_t val_low = 0xFF;
|
|
||||||
hopping_frequency[0] = 0x00;
|
|
||||||
hopping_frequency[1] = 0x63;
|
|
||||||
for(uint8_t ch=0; ch<=0xBD; ch+=3)
|
|
||||||
{
|
|
||||||
if(ch==0x63)
|
|
||||||
val_low = 0xFF; //init for second block
|
|
||||||
if(ch==0x60)
|
|
||||||
continue; //skip channel
|
|
||||||
CC2500_WriteReg(CC2500_0A_CHANNR, ch); //switch channel
|
|
||||||
delayMicroseconds(370); //wait to read
|
|
||||||
val = 0;
|
|
||||||
for(uint8_t i=0;i<16;i++)
|
|
||||||
val += CC2500_ReadReg(CC2500_34_RSSI | CC2500_READ_BURST);
|
|
||||||
val >>= 4;
|
|
||||||
debug("C:%02X RSSI:%02X",ch,val);
|
|
||||||
if(val_low > val)
|
|
||||||
{
|
|
||||||
debug(" OK");
|
|
||||||
val_low = val;
|
|
||||||
hopping_frequency[ch<0x63?0:1]=ch; //save best channel
|
|
||||||
}
|
|
||||||
debugln("");
|
|
||||||
}
|
|
||||||
CC2500_WriteReg(CC2500_17_MCSM1,0x30);
|
|
||||||
CC2500_Strobe(CC2500_SIDLE);
|
|
||||||
CC2500_SetTxRxMode(TX_EN);
|
|
||||||
#ifdef RLINK_RC4G_FORCE_ID
|
|
||||||
hopping_frequency[0] = 0x03;
|
|
||||||
hopping_frequency[1] = 0x6F;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// calc next pseudo random value
|
|
||||||
static void __attribute__((unused)) RLINK_next_pseudo()
|
|
||||||
{
|
|
||||||
RLINK_pseudo = ((RLINK_pseudo * 0xAA) + 0x03) % 0x7673;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((unused)) RLINK_set_next_channel()
|
|
||||||
{
|
|
||||||
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[RLINK_pseudo & 0x0F]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t __attribute__((unused)) RLINK_checksum(const uint8_t *data, uint8_t payload_len, bool include_id=false)
|
|
||||||
{
|
|
||||||
uint8_t sum=0;
|
|
||||||
for(uint8_t i=0;i<payload_len;i++)
|
|
||||||
sum+=data[i];
|
|
||||||
if(include_id)
|
|
||||||
for(uint8_t i=0;i<RLINK_TX_ID_LEN;i++)
|
|
||||||
sum+=rx_tx_addr[i];
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((unused)) RLINK_TXID_init()
|
static void __attribute__((unused)) RLINK_TXID_init()
|
||||||
{
|
{
|
||||||
#ifdef RLINK_RC4G_FORCE_ID
|
#ifdef RLINK_RC4G_FORCE_ID
|
||||||
@@ -185,10 +117,52 @@ static void __attribute__((unused)) RLINK_TXID_init()
|
|||||||
memcpy(rx_tx_addr,"\xFC\x11\x0D\x20",RLINK_TX_ID_LEN); //air T8FB
|
memcpy(rx_tx_addr,"\xFC\x11\x0D\x20",RLINK_TX_ID_LEN); //air T8FB
|
||||||
#endif
|
#endif
|
||||||
// channels order depend on ID
|
// channels order depend on ID
|
||||||
if(sub_protocol==RLINK_RC4G)
|
if(sub_protocol!=RLINK_RC4G)
|
||||||
RLINK_hop_RC4G();
|
RLINK_hop();
|
||||||
else
|
else
|
||||||
RLINK_hop();
|
{//RLINK_RC4G
|
||||||
|
// Find 2 unused channels
|
||||||
|
// first channel is a multiple of 3 between 00 and 5D
|
||||||
|
// second channel is a multiple of 3 between 63 and BD
|
||||||
|
CC2500_Strobe(CC2500_SIDLE);
|
||||||
|
CC2500_WriteReg(CC2500_17_MCSM1,0x3C);
|
||||||
|
CC2500_Strobe(CC2500_SFRX);
|
||||||
|
CC2500_SetTxRxMode(RX_EN);
|
||||||
|
CC2500_Strobe(CC2500_SRX);
|
||||||
|
delayMilliseconds(1); //wait for RX mode
|
||||||
|
uint16_t val;
|
||||||
|
uint8_t val_low = 0xFF;
|
||||||
|
hopping_frequency[0] = 0x00;
|
||||||
|
hopping_frequency[1] = 0x63;
|
||||||
|
for(uint8_t ch=0; ch<=0xBD; ch+=3)
|
||||||
|
{
|
||||||
|
if(ch==0x63)
|
||||||
|
val_low = 0xFF; //init for second block
|
||||||
|
if(ch==0x60)
|
||||||
|
continue; //skip channel
|
||||||
|
CC2500_WriteReg(CC2500_0A_CHANNR, ch); //switch channel
|
||||||
|
delayMicroseconds(370); //wait to read
|
||||||
|
val = 0;
|
||||||
|
for(uint8_t i=0;i<16;i++)
|
||||||
|
val += CC2500_ReadReg(CC2500_34_RSSI | CC2500_READ_BURST);
|
||||||
|
val >>= 4;
|
||||||
|
debug("C:%02X RSSI:%02X",ch,val);
|
||||||
|
if(val_low > val)
|
||||||
|
{
|
||||||
|
debug(" OK");
|
||||||
|
val_low = val;
|
||||||
|
hopping_frequency[ch<0x63?0:1]=ch; //save best channel
|
||||||
|
}
|
||||||
|
debugln("");
|
||||||
|
}
|
||||||
|
CC2500_WriteReg(CC2500_17_MCSM1,0x30);
|
||||||
|
CC2500_Strobe(CC2500_SIDLE);
|
||||||
|
CC2500_SetTxRxMode(TX_EN);
|
||||||
|
#ifdef RLINK_RC4G_FORCE_ID
|
||||||
|
hopping_frequency[0] = 0x03;
|
||||||
|
hopping_frequency[1] = 0x6F;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef RLINK_DEBUG
|
#ifdef RLINK_DEBUG
|
||||||
debug("ID:");
|
debug("ID:");
|
||||||
@@ -217,21 +191,22 @@ static void __attribute__((unused)) RLINK_rf_init()
|
|||||||
for (uint8_t i = 0; i < 39; ++i)
|
for (uint8_t i = 0; i < 39; ++i)
|
||||||
CC2500_WriteReg(i, pgm_read_byte_near(&RLINK_init_values[i]));
|
CC2500_WriteReg(i, pgm_read_byte_near(&RLINK_init_values[i]));
|
||||||
|
|
||||||
if(sub_protocol == RLINK_DUMBORC || sub_protocol == RLINK_DUMBORC_P)
|
if(sub_protocol==RLINK_DUMBORC)
|
||||||
{
|
{
|
||||||
CC2500_WriteReg(4, 0xBA);
|
CC2500_WriteReg(4, 0xBA);
|
||||||
CC2500_WriteReg(5, 0xDC);
|
CC2500_WriteReg(5, 0xDC);
|
||||||
}
|
}
|
||||||
else if(sub_protocol==RLINK_RC4G)
|
else if(sub_protocol==RLINK_RC4G)
|
||||||
CC2500_WriteReg(5, 0xA5);
|
CC2500_WriteReg(5, 0xA5);
|
||||||
|
|
||||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||||
|
|
||||||
CC2500_SetTxRxMode(TX_EN);
|
CC2500_SetTxRxMode(TX_EN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __attribute__((unused)) RLINK_send_packet()
|
static void __attribute__((unused)) RLINK_send_packet()
|
||||||
{
|
{
|
||||||
|
static uint32_t pseudo=0;
|
||||||
uint32_t bits = 0;
|
uint32_t bits = 0;
|
||||||
uint8_t bitsavailable = 0;
|
uint8_t bitsavailable = 0;
|
||||||
uint8_t idx = 6;
|
uint8_t idx = 6;
|
||||||
@@ -250,18 +225,17 @@ static void __attribute__((unused)) RLINK_send_packet()
|
|||||||
{
|
{
|
||||||
case RLINK_SURFACE:
|
case RLINK_SURFACE:
|
||||||
packet[1] |= 0x01;
|
packet[1] |= 0x01;
|
||||||
//radiolink additional ID which is working only on a small set of RXs
|
//radiolink additionnal ID which is working only on a small set of RXs
|
||||||
//if(RX_num) packet[1] |= ((RX_num+2)<<4)+4; // RX number limited to 10 values, 0 is a wildcard
|
//if(RX_num) packet[1] |= ((RX_num+2)<<4)+4; // RX number limited to 10 values, 0 is a wildcard
|
||||||
break;
|
break;
|
||||||
case RLINK_AIR:
|
case RLINK_AIR:
|
||||||
packet[1] |= 0x21; //air 0x21 on dump but it looks to support telemetry at least RSSI
|
packet[1] |= 0x21; //air 0x21 on dump but it looks to support telemetry at least RSSI
|
||||||
break;
|
break;
|
||||||
case RLINK_DUMBORC:
|
case RLINK_DUMBORC:
|
||||||
case RLINK_DUMBORC_P:
|
packet[1] = 0x00; //always 0x00 on dump
|
||||||
packet[1] |= 0x01; //always 0x00 on dump but does appear to support telemtry on newer transmitters
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID
|
// ID
|
||||||
memcpy(&packet[2],rx_tx_addr,RLINK_TX_ID_LEN);
|
memcpy(&packet[2],rx_tx_addr,RLINK_TX_ID_LEN);
|
||||||
|
|
||||||
@@ -282,28 +256,31 @@ static void __attribute__((unused)) RLINK_send_packet()
|
|||||||
bitsavailable -= 8;
|
bitsavailable -= 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// hop
|
// hop
|
||||||
RLINK_next_pseudo();
|
pseudo=((pseudo * 0xAA) + 0x03) % 0x7673; // calc next pseudo random value
|
||||||
RLINK_set_next_channel();
|
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[pseudo & 0x0F]);
|
||||||
packet[28]= RLINK_pseudo;
|
packet[28]= pseudo;
|
||||||
packet[29]= RLINK_pseudo >> 8;
|
packet[29]= pseudo >> 8;
|
||||||
packet[30]= 0x00; // unknown
|
packet[30]= 0x00; // unknown
|
||||||
packet[31]= 0x00; // unknown
|
packet[31]= 0x00; // unknown
|
||||||
packet[32]= rf_ch_num; // index of value changed in the RF table
|
packet[32]= rf_ch_num; // index of value changed in the RF table
|
||||||
|
|
||||||
// check
|
// check
|
||||||
packet[33]=RLINK_checksum(&packet[1], RLINK_TX_PACKET_LEN-1);
|
uint8_t sum=0;
|
||||||
|
for(uint8_t i=1;i<33;i++)
|
||||||
|
sum+=packet[i];
|
||||||
|
packet[33]=sum;
|
||||||
|
|
||||||
// send packet
|
// send packet
|
||||||
CC2500_WriteData(packet, RLINK_TX_PACKET_LEN+1);
|
CC2500_WriteData(packet, RLINK_TX_PACKET_LEN+1);
|
||||||
|
|
||||||
// packets type
|
// packets type
|
||||||
packet_count++;
|
packet_count++;
|
||||||
if(packet_count>5) packet_count=0;
|
if(packet_count>5) packet_count=0;
|
||||||
|
|
||||||
#ifdef RLINK_DEBUG
|
#ifdef RLINK_DEBUG
|
||||||
debugln("C= 0x%02X",hopping_frequency[RLINK_pseudo & 0x0F]);
|
debugln("C= 0x%02X",hopping_frequency[pseudo & 0x0F]);
|
||||||
debug("P=");
|
debug("P=");
|
||||||
for(uint8_t i=1;i<RLINK_TX_PACKET_LEN+1;i++)
|
for(uint8_t i=1;i<RLINK_TX_PACKET_LEN+1;i++)
|
||||||
debug(" 0x%02X",packet[i]);
|
debug(" 0x%02X",packet[i]);
|
||||||
@@ -311,78 +288,6 @@ static void __attribute__((unused)) RLINK_send_packet()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RLINK_HUB_TELEMETRY
|
|
||||||
|
|
||||||
static bool __attribute__((unused)) RLINK_DUMBORC_send_command()
|
|
||||||
{
|
|
||||||
if(!RLINK_SerialRX || sub_protocol != RLINK_DUMBORC_P)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
RLINK_SerialRX=false;
|
|
||||||
|
|
||||||
if(RLINK_SerialRX_len > sizeof(RLINK_SerialRX_val))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CC2500_Strobe(CC2500_SIDLE);
|
|
||||||
|
|
||||||
RLINK_next_pseudo();
|
|
||||||
RLINK_set_next_channel();
|
|
||||||
|
|
||||||
packet[0] = RLINK_SerialRX_len;
|
|
||||||
memcpy(&packet[1], RLINK_SerialRX_val, RLINK_SerialRX_len);
|
|
||||||
packet[2] = RLINK_pseudo;
|
|
||||||
packet[3] = RLINK_pseudo >> 8;
|
|
||||||
// special packages have id check embedded in checksum
|
|
||||||
packet[RLINK_SerialRX_len] = RLINK_checksum(&packet[1], RLINK_SerialRX_len - 1, true);
|
|
||||||
|
|
||||||
CC2500_WriteData(packet, RLINK_SerialRX_len + 1);
|
|
||||||
|
|
||||||
packet_count++;
|
|
||||||
if(packet_count>5) packet_count=0;
|
|
||||||
|
|
||||||
#ifdef RLINK_DEBUG
|
|
||||||
debugln("C= 0x%02X",hopping_frequency[RLINK_pseudo & 0x0F]);
|
|
||||||
debug("DumboRC P command=");
|
|
||||||
for(uint8_t i=1;i<packet[0]+1;i++)
|
|
||||||
debug(" 0x%02X",packet[i]);
|
|
||||||
debugln("");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// logic is rougly copied from ddf-350, which in itself seems to be based on cc2500 docs
|
|
||||||
static uint8_t __attribute__((unused)) RLINK_DUMBORC_tele_rssi_as_percent(uint8_t rssi)
|
|
||||||
{
|
|
||||||
if(rssi < 15)
|
|
||||||
rssi=15;
|
|
||||||
else if(rssi > 90)
|
|
||||||
rssi=90;
|
|
||||||
return ((90 - rssi) * 100) / 75;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool __attribute__((unused)) RLINK_DUMBORC_validate_telemetry_packet(const uint8_t *data)
|
|
||||||
{
|
|
||||||
const uint8_t declaredLen = data[0];
|
|
||||||
|
|
||||||
if(data[1] == 0x00)
|
|
||||||
{
|
|
||||||
// telemetry package follows base radiolink procotol with slightly less rules
|
|
||||||
if(declaredLen != RLINK_RX_PACKET_LEN || memcmp(&data[2], rx_tx_addr, RLINK_TX_ID_LEN) != 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// telemetry packages do not have id check embeeded in checksum, just like base RadioLink
|
|
||||||
return data[RLINK_RX_PACKET_LEN] == RLINK_checksum(&data[1], RLINK_RX_PACKET_LEN - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sub_protocol != RLINK_DUMBORC_P)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// special packages have id check embedded in checksum
|
|
||||||
return data[declaredLen] == RLINK_checksum(&data[1], declaredLen - 1, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef MULTI_AIR
|
#ifndef MULTI_AIR
|
||||||
static void __attribute__((unused)) RLINK_RC4G_send_packet()
|
static void __attribute__((unused)) RLINK_RC4G_send_packet()
|
||||||
{
|
{
|
||||||
@@ -406,7 +311,7 @@ static void __attribute__((unused)) RLINK_RC4G_send_packet()
|
|||||||
packet[5+i*2] = val;
|
packet[5+i*2] = val;
|
||||||
packet[8+i ] |= (val>>4) & 0xF0;
|
packet[8+i ] |= (val>>4) & 0xF0;
|
||||||
}
|
}
|
||||||
//special channel which is linked to gyro on the original TX but allocating it on CH5 here
|
//special channel which is linked to gyro on the orginal TX but allocating it on CH5 here
|
||||||
packet[10] = convert_channel_16b_limit(CH5,0,100);
|
packet[10] = convert_channel_16b_limit(CH5,0,100);
|
||||||
//failsafe
|
//failsafe
|
||||||
for(uint8_t i=0;i<4;i++)
|
for(uint8_t i=0;i<4;i++)
|
||||||
@@ -427,15 +332,10 @@ static void __attribute__((unused)) RLINK_RC4G_send_packet()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined RLINK_HUB_TELEMETRY
|
|
||||||
uint16_t RLINK_timing_last_rfsend = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define RLINK_TIMING_PROTO 20000-100 // -100 for compatibility with R8EF
|
#define RLINK_TIMING_PROTO 20000-100 // -100 for compatibility with R8EF
|
||||||
#define RLINK_TIMING_RFSEND 10500
|
#define RLINK_TIMING_RFSEND 10500
|
||||||
#define RLINK_TIMING_CHECK 2000
|
#define RLINK_TIMING_CHECK 2000
|
||||||
#define RLINK_RC4G_TIMING_PROTO 14460
|
#define RLINK_RC4G_TIMING_PROTO 14460
|
||||||
#define RLINK_DUMBORC_COMMAND_RFSEND 5000
|
|
||||||
uint16_t RLINK_callback()
|
uint16_t RLINK_callback()
|
||||||
{
|
{
|
||||||
if(sub_protocol == RLINK_RC4G)
|
if(sub_protocol == RLINK_RC4G)
|
||||||
@@ -460,92 +360,47 @@ uint16_t RLINK_callback()
|
|||||||
#endif
|
#endif
|
||||||
CC2500_SetPower();
|
CC2500_SetPower();
|
||||||
CC2500_SetFreqOffset();
|
CC2500_SetFreqOffset();
|
||||||
|
RLINK_send_packet();
|
||||||
#if not defined RLINK_HUB_TELEMETRY
|
#if not defined RLINK_HUB_TELEMETRY
|
||||||
RLINK_send_packet();
|
return RLINK_TIMING_PROTO;
|
||||||
return RLINK_TIMING_PROTO; // RLINK_DATA
|
|
||||||
#else
|
#else
|
||||||
if(RLINK_DUMBORC_send_command())
|
|
||||||
{
|
|
||||||
phase++; // RX1
|
|
||||||
RLINK_timing_last_rfsend = RLINK_DUMBORC_COMMAND_RFSEND;
|
|
||||||
return RLINK_timing_last_rfsend;
|
|
||||||
}
|
|
||||||
|
|
||||||
RLINK_send_packet();
|
|
||||||
|
|
||||||
if(!(packet[1]&0x02))
|
if(!(packet[1]&0x02))
|
||||||
return RLINK_TIMING_PROTO; // Normal packet -> RLINK_DATA
|
return RLINK_TIMING_PROTO; //Normal packet
|
||||||
// Telemetry packet
|
//Telemetry packet
|
||||||
phase++; // RX1
|
phase++; // RX1
|
||||||
RLINK_timing_last_rfsend = RLINK_TIMING_RFSEND;
|
return RLINK_TIMING_RFSEND;
|
||||||
return RLINK_timing_last_rfsend;
|
|
||||||
case RLINK_RX1:
|
case RLINK_RX1:
|
||||||
CC2500_Strobe(CC2500_SIDLE);
|
CC2500_Strobe(CC2500_SIDLE);
|
||||||
CC2500_Strobe(CC2500_SFRX);
|
CC2500_Strobe(CC2500_SFRX);
|
||||||
CC2500_SetTxRxMode(RX_EN);
|
CC2500_SetTxRxMode(RX_EN);
|
||||||
CC2500_Strobe(CC2500_SRX);
|
CC2500_Strobe(CC2500_SRX);
|
||||||
phase++; // RX2
|
phase++; // RX2
|
||||||
return RLINK_TIMING_PROTO-RLINK_timing_last_rfsend-RLINK_TIMING_CHECK;
|
return RLINK_TIMING_PROTO-RLINK_TIMING_RFSEND-RLINK_TIMING_CHECK;
|
||||||
case RLINK_RX2:
|
case RLINK_RX2:
|
||||||
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||||
const bool dumborc_family = sub_protocol == RLINK_DUMBORC || sub_protocol == RLINK_DUMBORC_P;
|
if (len == RLINK_RX_PACKET_LEN + 1 + 2) //Telemetry frame is 15 bytes + 1 byte for length + 2 bytes for RSSI&LQI&CRC
|
||||||
//Telemetry frame is 15 bytes + 1 byte for length + 2 bytes for RSSI&LQI&CRC
|
|
||||||
const bool rlink_telem_len = !dumborc_family && len == RLINK_RX_PACKET_LEN + 1 + 2;
|
|
||||||
// length byte + type byte + checksum byte + RSSI/LQI/CRC
|
|
||||||
const bool dumborc_len = dumborc_family && len >= 5 && len <= sizeof(packet_in);
|
|
||||||
if (rlink_telem_len || dumborc_len)
|
|
||||||
{
|
{
|
||||||
#ifdef RLINK_DEBUG_TELEM
|
#ifdef RLINK_DEBUG_TELEM
|
||||||
debug("Telem:");
|
debug("Telem:");
|
||||||
#endif
|
#endif
|
||||||
CC2500_ReadData(packet_in, len);
|
CC2500_ReadData(packet_in, len);
|
||||||
if(len >= 3 && packet_in[0] == len - 3 && (packet_in[len-1] & 0x80))
|
if(packet_in[0]==RLINK_RX_PACKET_LEN && (packet_in[len-1] & 0x80) && memcmp(&packet[2],rx_tx_addr,RLINK_TX_ID_LEN)==0 && packet_in[6]==packet[1])
|
||||||
{//Telemetry received with correct length and CC2500 CRC
|
{//Correct telemetry received: length, CRC, ID and type
|
||||||
#ifdef RLINK_DEBUG_TELEM
|
#ifdef RLINK_DEBUG_TELEM
|
||||||
for(uint8_t i=0;i<len;i++)
|
for(uint8_t i=0;i<len;i++)
|
||||||
debug(" %02X",packet_in[i]);
|
debug(" %02X",packet_in[i]);
|
||||||
#endif
|
#endif
|
||||||
bool valid_telem=false;
|
TX_RSSI = packet_in[len-2];
|
||||||
if(dumborc_family)
|
if(TX_RSSI >=128)
|
||||||
{
|
TX_RSSI -= 128;
|
||||||
if(RLINK_DUMBORC_validate_telemetry_packet(packet_in))
|
else
|
||||||
{
|
TX_RSSI += 128;
|
||||||
if(packet_in[1] == 0x00)
|
RX_RSSI=packet_in[7]&0x7F; //Should be packet_in[7]-256 but since it's an uint8_t...
|
||||||
{
|
v_lipo1=packet_in[8]<<1; //RX Batt
|
||||||
uint8_t tele_rssi = RLINK_DUMBORC_tele_rssi_as_percent(packet_in[7]);
|
v_lipo2=packet_in[9]; //Batt
|
||||||
uint16_t ext_v = packet_in[9] | (((uint16_t)packet_in[10]) << 8);
|
telemetry_link=1; //Send telemetry out
|
||||||
uint16_t direct_rssi = packet_in[11] | (((uint16_t)packet_in[12]) << 8);
|
pps_counter++;
|
||||||
direct_rssi = direct_rssi > 100 ? 100 : direct_rssi;
|
packet_count=0;
|
||||||
RX_RSSI = direct_rssi ? direct_rssi : tele_rssi;
|
|
||||||
v_lipo1 = 0; //Has no RX batt
|
|
||||||
v_lipo2 = ext_v > 255 ? 255 : ext_v; //Batt in same position as base radiolink
|
|
||||||
valid_telem=true;
|
|
||||||
}
|
|
||||||
else if(sub_protocol == RLINK_DUMBORC_P)
|
|
||||||
{
|
|
||||||
telemetry_link=2; // Raw DumboRC P packet to Lua/multiBuffer handling.
|
|
||||||
pps_counter++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(packet_in[0] == RLINK_RX_PACKET_LEN && memcmp(&packet[2],rx_tx_addr,RLINK_TX_ID_LEN)==0 && packet_in[6]==packet[1])
|
|
||||||
{
|
|
||||||
RX_RSSI=packet_in[7]&0x7F; //Should be packet_in[7]-256 but since it's an uint8_t...
|
|
||||||
v_lipo1=packet_in[8]<<1; //RX Batt
|
|
||||||
v_lipo2=packet_in[9]; //Batt
|
|
||||||
valid_telem=true;
|
|
||||||
}
|
|
||||||
if(valid_telem)
|
|
||||||
{
|
|
||||||
TX_RSSI = packet_in[len-2];
|
|
||||||
if(TX_RSSI >=128)
|
|
||||||
TX_RSSI -= 128;
|
|
||||||
else
|
|
||||||
TX_RSSI += 128;
|
|
||||||
telemetry_link=1; //Send telemetry out
|
|
||||||
pps_counter++;
|
|
||||||
packet_count=0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#ifdef RLINK_DEBUG_TELEM
|
#ifdef RLINK_DEBUG_TELEM
|
||||||
debugln("");
|
debugln("");
|
||||||
@@ -579,4 +434,4 @@ void RLINK_init()
|
|||||||
phase = RLINK_DATA;
|
phase = RLINK_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -19,24 +19,22 @@ Multiprotocol is distributed in the hope that it will be useful,
|
|||||||
#include "iface_xn297.h"
|
#include "iface_xn297.h"
|
||||||
|
|
||||||
//#define FORCE_SGF22_ORIGINAL_ID
|
//#define FORCE_SGF22_ORIGINAL_ID
|
||||||
#define FORCE_SGF22_CX10_ORIGINAL_ID
|
|
||||||
|
|
||||||
#define SGF22_PACKET_PERIOD 11950 //10240
|
#define SGF22_PACKET_PERIOD 11950 //10240
|
||||||
#define SGF22_PAYLOAD_SIZE 12
|
#define SGF22_BIND_RF_CHANNEL 78
|
||||||
#define SGF22_BIND_COUNT 50
|
#define SGF22_PAYLOAD_SIZE 12
|
||||||
#define SGF22_RF_NUM_CHANNELS 4
|
#define SGF22_BIND_COUNT 50
|
||||||
#define SGF22_BIND_RF_CHANNEL 78
|
#define SGF22_RF_NUM_CHANNELS 4
|
||||||
#define SGF22_F22S_BIND_RF_CHANNEL 10
|
#define SGF22_F22S_BIND_RF_CHANNEL 10
|
||||||
#define SGF22_J20_BIND_RF_CHANNEL 28
|
#define SGF22_J20_BIND_RF_CHANNEL 28
|
||||||
#define SGF22_CX10_BIND_RF_CHANNEL 48
|
|
||||||
|
|
||||||
//packet[8]
|
//packet[8]
|
||||||
#define SGF22_FLAG_3D 0x00
|
#define SGF22_FLAG_3D 0x00
|
||||||
#define SGF22_FLAG_LIGHT 0x04
|
#define SGF22_FLAG_LIGHT 0x04
|
||||||
#define SGF22_FLAG_ROLL 0x08
|
#define SGF22_FLAG_ROLL 0x08
|
||||||
#define SGF22_FLAG_VIDEO 0x10
|
#define SGF22_FLAG_VIDEO 0x10
|
||||||
#define SGF22_FLAG_6G 0x40
|
#define SGF22_FLAG_6G 0x40
|
||||||
#define SGF22_FLAG_VERTICAL 0xC0
|
#define SGF22_FLAG_VERTICAL 0xC0
|
||||||
|
|
||||||
#define SGF22_J20_FLAG_HORIZONTAL 0x80
|
#define SGF22_J20_FLAG_HORIZONTAL 0x80
|
||||||
//#define SGF22_J20_FLAG_SPEED 0x01 // Up/Down trim, not implemented
|
//#define SGF22_J20_FLAG_SPEED 0x01 // Up/Down trim, not implemented
|
||||||
@@ -46,18 +44,9 @@ Multiprotocol is distributed in the hope that it will be useful,
|
|||||||
|
|
||||||
|
|
||||||
//packet[9]
|
//packet[9]
|
||||||
#define SGF22_FLAG_TRIMRESET 0x04
|
#define SGF22_FLAG_TRIMRESET 0x04
|
||||||
#define SGF22_FLAG_PHOTO 0x40 // #define SGF22_J20_FLAG_INVERT 0x40
|
#define SGF22_FLAG_PHOTO 0x40 // #define SGF22_J20_FLAG_INVERT 0x40
|
||||||
#define SGF22_J20_FLAG_FIXHEIGHT 0x80
|
#define SGF22_J20_FLAG_FIXHEIGHT 0x80
|
||||||
|
|
||||||
#define SGF22_WRITE_TIME 1000
|
|
||||||
|
|
||||||
enum {
|
|
||||||
SGF22_DATA1,
|
|
||||||
SGF22_DATA2,
|
|
||||||
SGF22_DATA3,
|
|
||||||
SGF22_RX,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void __attribute__((unused)) SGF22_send_packet()
|
static void __attribute__((unused)) SGF22_send_packet()
|
||||||
{
|
{
|
||||||
@@ -81,43 +70,26 @@ static void __attribute__((unused)) SGF22_send_packet()
|
|||||||
packet_sent = 0;
|
packet_sent = 0;
|
||||||
//packet
|
//packet
|
||||||
packet[0] = 0x1B;
|
packet[0] = 0x1B;
|
||||||
if (sub_protocol != SGF22_CX10)
|
packet[8] = SGF22_FLAG_3D // CH5 -100%, F22 & F22S - 3D mode, J20 - Gyro off
|
||||||
{//SGF22_F22,SGF22_F22S,SGF22_J20
|
| GET_FLAG(CH6_SW, SGF22_FLAG_ROLL) // roll
|
||||||
packet[8] = SGF22_FLAG_3D // CH5 -100%, F22 & F22S - 3D mode, J20 - Gyro off
|
| GET_FLAG(CH7_SW, SGF22_FLAG_LIGHT) // push up throttle trim for light in the stock TX
|
||||||
| GET_FLAG(CH6_SW, SGF22_FLAG_ROLL) // roll
|
| GET_FLAG(CH9_SW, SGF22_FLAG_VIDEO) // push down throttle trim for video in the stock TX
|
||||||
| GET_FLAG(CH7_SW, SGF22_FLAG_LIGHT) // push up throttle trim for light in the stock TX
|
| GET_FLAG(CH11_SW, SGF22_FX922_FLAG_BALANCE)
|
||||||
| GET_FLAG(CH9_SW, SGF22_FLAG_VIDEO) // push down throttle trim for video in the stock TX
|
| GET_FLAG(CH12_SW, SGF22_FX922_FLAG_BALANCEHIGH);
|
||||||
| GET_FLAG(CH11_SW, SGF22_FX922_FLAG_BALANCE)
|
if(Channel_data[CH5] > CHANNEL_MAX_COMMAND)
|
||||||
| GET_FLAG(CH12_SW, SGF22_FX922_FLAG_BALANCEHIGH);
|
packet[8] |= SGF22_FLAG_VERTICAL; // CH5 100%, vertical mode (torque)
|
||||||
if(Channel_data[CH5] > CHANNEL_MAX_COMMAND)
|
else if(Channel_data[CH5] > CHANNEL_MIN_COMMAND )
|
||||||
packet[8] |= SGF22_FLAG_VERTICAL; // CH5 100%, vertical mode (torque)
|
|
||||||
else if(Channel_data[CH5] > CHANNEL_MIN_COMMAND )
|
|
||||||
packet[8] |= ( sub_protocol == SGF22_J20 ? SGF22_J20_FLAG_HORIZONTAL : SGF22_FLAG_6G ); // CH5 0%, F22 & F22S - 6G mode, J20 - Horizontal mode
|
packet[8] |= ( sub_protocol == SGF22_J20 ? SGF22_J20_FLAG_HORIZONTAL : SGF22_FLAG_6G ); // CH5 0%, F22 & F22S - 6G mode, J20 - Horizontal mode
|
||||||
}
|
packet[9] = GET_FLAG(CH8_SW, SGF22_FLAG_PHOTO) // F22: photo, press in throttle trim in the stock TX, J20: invert flight
|
||||||
else //SGF22_CX10 114548
|
|
||||||
{
|
|
||||||
if(CH6_SW)
|
|
||||||
flags = 0x06; // high rate
|
|
||||||
else
|
|
||||||
if(Channel_data[CH6] < CHANNEL_MIN_COMMAND)
|
|
||||||
flags = 0x04; // low rate
|
|
||||||
else
|
|
||||||
flags = 0x05; // mid rate
|
|
||||||
packet[8] = flags
|
|
||||||
| GET_FLAG(CH5_SW, 0x08); // flip
|
|
||||||
}
|
|
||||||
packet[9] = GET_FLAG(CH8_SW, SGF22_FLAG_PHOTO) // F22: photo, press in throttle trim in the stock TX, J20: invert flight
|
|
||||||
| GET_FLAG(CH10_SW, ( sub_protocol == SGF22_J20 ? SGF22_J20_FLAG_FIXHEIGHT : SGF22_FLAG_TRIMRESET )) ; // F22: Both sticks down inwards in the stock TX, J20: Altitude hold
|
| GET_FLAG(CH10_SW, ( sub_protocol == SGF22_J20 ? SGF22_J20_FLAG_FIXHEIGHT : SGF22_FLAG_TRIMRESET )) ; // F22: Both sticks down inwards in the stock TX, J20: Altitude hold
|
||||||
packet[10] = 0x42; // no fine tune
|
packet[10] = 0x42; // no fine tune
|
||||||
packet[11] = 0x10; // no fine tune
|
packet[11] = 0x10; // no fine tune
|
||||||
}
|
}
|
||||||
if(sub_protocol == SGF22_F22S)
|
if(sub_protocol == SGF22_F22S)
|
||||||
packet[0] += 6;
|
packet[0] += 6;
|
||||||
else if (sub_protocol == SGF22_J20)
|
else if (sub_protocol == SGF22_J20)
|
||||||
packet[0] += 3;
|
packet[0] += 3;
|
||||||
else if (sub_protocol == SGF22_CX10)
|
packet[1] = packet_count; // sequence
|
||||||
packet[0] += 0x6A;
|
|
||||||
packet[1] = packet_count; // sequence
|
|
||||||
packet[2] = rx_tx_addr[2];
|
packet[2] = rx_tx_addr[2];
|
||||||
packet[3] = rx_tx_addr[3];
|
packet[3] = rx_tx_addr[3];
|
||||||
packet[4] = convert_channel_8b(THROTTLE);
|
packet[4] = convert_channel_8b(THROTTLE);
|
||||||
@@ -127,10 +99,7 @@ static void __attribute__((unused)) SGF22_send_packet()
|
|||||||
|
|
||||||
XN297_SetPower();
|
XN297_SetPower();
|
||||||
XN297_SetTxRxMode(TX_EN);
|
XN297_SetTxRxMode(TX_EN);
|
||||||
if (sub_protocol != SGF22_CX10)
|
XN297_WriteEnhancedPayload(packet, SGF22_PAYLOAD_SIZE,0);
|
||||||
XN297_WriteEnhancedPayload(packet, SGF22_PAYLOAD_SIZE,0);
|
|
||||||
else
|
|
||||||
XN297_WritePayload(packet, SGF22_PAYLOAD_SIZE);
|
|
||||||
#if 0
|
#if 0
|
||||||
debug_time("");
|
debug_time("");
|
||||||
for(uint8_t i=0; i<SGF22_PAYLOAD_SIZE; i++)
|
for(uint8_t i=0; i<SGF22_PAYLOAD_SIZE; i++)
|
||||||
@@ -154,7 +123,7 @@ static void __attribute__((unused)) SGF22_initialize_txid()
|
|||||||
{ 0x18, 0x37, 0x27, 0x47 } };
|
{ 0x18, 0x37, 0x27, 0x47 } };
|
||||||
memcpy(hopping_frequency, &hop[val], SGF22_RF_NUM_CHANNELS);
|
memcpy(hopping_frequency, &hop[val], SGF22_RF_NUM_CHANNELS);
|
||||||
|
|
||||||
/*//Same code size...
|
/*//Same code sze...
|
||||||
hopping_frequency[0] = 0x0C + 3 * val;
|
hopping_frequency[0] = 0x0C + 3 * val;
|
||||||
hopping_frequency[1] = hopping_frequency[0] + 0x1E;
|
hopping_frequency[1] = hopping_frequency[0] + 0x1E;
|
||||||
if(val > 1) hopping_frequency[1]++;
|
if(val > 1) hopping_frequency[1]++;
|
||||||
@@ -167,23 +136,6 @@ static void __attribute__((unused)) SGF22_initialize_txid()
|
|||||||
rx_tx_addr[3] = 0x61; // TX2:51 TX3:0C
|
rx_tx_addr[3] = 0x61; // TX2:51 TX3:0C
|
||||||
memcpy(hopping_frequency,"\x15\x34\x24\x44", SGF22_RF_NUM_CHANNELS); //Original dump=>21=0x15,52=0x34,36=0x24,68=0x44
|
memcpy(hopping_frequency,"\x15\x34\x24\x44", SGF22_RF_NUM_CHANNELS); //Original dump=>21=0x15,52=0x34,36=0x24,68=0x44
|
||||||
#endif
|
#endif
|
||||||
#ifdef FORCE_SGF22_CX10_ORIGINAL_ID
|
|
||||||
if(sub_protocol == SGF22_CX10)
|
|
||||||
{
|
|
||||||
if(rx_tx_addr[3] & 1)
|
|
||||||
{
|
|
||||||
rx_tx_addr[2] = 0x4C;
|
|
||||||
rx_tx_addr[3] = 0xD7;
|
|
||||||
memcpy(hopping_frequency, "\x37\x42\x47\x3c", SGF22_RF_NUM_CHANNELS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rx_tx_addr[2] = 0x50;
|
|
||||||
rx_tx_addr[3] = 0xE1;
|
|
||||||
memcpy(hopping_frequency, "\x3b\x4b\x46\x41", SGF22_RF_NUM_CHANNELS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if 0
|
#if 0
|
||||||
debug("ID: %02X %02X, C: ",rx_tx_addr[2],rx_tx_addr[3]);
|
debug("ID: %02X %02X, C: ",rx_tx_addr[2],rx_tx_addr[3]);
|
||||||
for(uint8_t i=0; i<SGF22_RF_NUM_CHANNELS; i++)
|
for(uint8_t i=0; i<SGF22_RF_NUM_CHANNELS; i++)
|
||||||
@@ -196,97 +148,34 @@ static void __attribute__((unused)) SGF22_RF_init()
|
|||||||
{
|
{
|
||||||
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
|
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
|
||||||
XN297_SetTXAddr((uint8_t*)"\xC7\x95\x3C\xBB\xA5", 5);
|
XN297_SetTXAddr((uint8_t*)"\xC7\x95\x3C\xBB\xA5", 5);
|
||||||
#ifdef SGF22_HUB_TELEMETRY
|
const uint8_t bind_chan[] = {SGF22_BIND_RF_CHANNEL, SGF22_F22S_BIND_RF_CHANNEL, SGF22_J20_BIND_RF_CHANNEL};
|
||||||
XN297_SetRXAddr((uint8_t*)"\xC7\x95\x3C\xBB\xA5", SGF22_PAYLOAD_SIZE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const uint8_t bind_chan[] = {SGF22_BIND_RF_CHANNEL, SGF22_F22S_BIND_RF_CHANNEL, SGF22_J20_BIND_RF_CHANNEL, SGF22_CX10_BIND_RF_CHANNEL};
|
|
||||||
XN297_RFChannel(bind_chan[sub_protocol]); // Set bind channel
|
XN297_RFChannel(bind_chan[sub_protocol]); // Set bind channel
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t SGF22_callback()
|
uint16_t SGF22_callback()
|
||||||
{
|
{
|
||||||
#ifdef SGF22_HUB_TELEMETRY
|
if(phase == 0)
|
||||||
bool rx = false;
|
|
||||||
static uint8_t telem_count = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch(phase)
|
|
||||||
{
|
{
|
||||||
case SGF22_DATA1:
|
phase++;
|
||||||
#ifdef MULTI_SYNC
|
#ifdef MULTI_SYNC
|
||||||
telemetry_set_input_sync(SGF22_PACKET_PERIOD);
|
telemetry_set_input_sync(SGF22_PACKET_PERIOD);
|
||||||
#endif
|
#endif
|
||||||
#ifdef SGF22_HUB_TELEMETRY
|
SGF22_send_packet();
|
||||||
rx = XN297_IsRX();
|
if(IS_BIND_IN_PROGRESS)
|
||||||
XN297_SetTxRxMode(TXRX_OFF);
|
{
|
||||||
#endif
|
if(--bind_counter==0)
|
||||||
SGF22_send_packet();
|
BIND_DONE;
|
||||||
if(IS_BIND_IN_PROGRESS)
|
}
|
||||||
{
|
}
|
||||||
if(--bind_counter==0)
|
else
|
||||||
BIND_DONE;
|
{//send 3 times in total the same packet
|
||||||
}
|
XN297_ReSendPayload();
|
||||||
#ifdef SGF22_HUB_TELEMETRY
|
phase++;
|
||||||
if(rx)
|
if(phase > 2)
|
||||||
{
|
{
|
||||||
uint8_t p_len = XN297_ReadEnhancedPayload(packet_in, SGF22_PAYLOAD_SIZE);
|
phase = 0;
|
||||||
if(p_len == 3 && packet_in[0] == rx_tx_addr[2] && packet_in[1] == rx_tx_addr[3])
|
return SGF22_PACKET_PERIOD - 2*1550;
|
||||||
{//packets: 00 0B 00 -> 00 0B 01
|
}
|
||||||
telemetry_link = 1;
|
|
||||||
v_lipo1 = packet_in[2] ? 0 : 255; //2.9V for 1S, 7.0V for 2S
|
|
||||||
telemetry_lost = 0;
|
|
||||||
telem_count = 0;
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
debug("L %d ",p_len);
|
|
||||||
debug("RX");
|
|
||||||
for(uint8_t i=0; i<SGF22_PAYLOAD_SIZE; i++)
|
|
||||||
debug(" %02X",packet_in[i]);
|
|
||||||
debugln("");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if(telem_count > 4*63) // Around 3.5sec with no telemetry
|
|
||||||
telemetry_lost = 1;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
telem_count++;
|
|
||||||
if(!telemetry_lost && (telem_count & 0x3F) == 0)
|
|
||||||
{// Should have received a telem packet but... Send telem to the radio to keep it alive
|
|
||||||
telemetry_link = 1;
|
|
||||||
#if 0
|
|
||||||
debugln("Miss");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
phase++;
|
|
||||||
break;
|
|
||||||
case SGF22_DATA2:
|
|
||||||
case SGF22_DATA3:
|
|
||||||
//send 3 times in total the same packet
|
|
||||||
XN297_ReSendPayload();
|
|
||||||
phase++;
|
|
||||||
break;
|
|
||||||
default: //SGF22_RX
|
|
||||||
#ifdef SGF22_HUB_TELEMETRY
|
|
||||||
/*{ // Wait for packet to be sent before switching to receive mode
|
|
||||||
uint16_t start=(uint16_t)micros(), count=0;
|
|
||||||
while ((uint16_t)((uint16_t)micros()-(uint16_t)start) < 500)
|
|
||||||
{
|
|
||||||
if(XN297_IsPacketSent())
|
|
||||||
break;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
debugln("%d",count);
|
|
||||||
}*/
|
|
||||||
//Switch to RX
|
|
||||||
XN297_SetTxRxMode(TXRX_OFF);
|
|
||||||
XN297_SetTxRxMode(RX_EN);
|
|
||||||
#endif
|
|
||||||
phase = SGF22_DATA1;
|
|
||||||
return SGF22_PACKET_PERIOD - 3*1550;
|
|
||||||
}
|
}
|
||||||
return 1550;
|
return 1550;
|
||||||
}
|
}
|
||||||
@@ -298,11 +187,7 @@ void SGF22_init()
|
|||||||
SGF22_RF_init();
|
SGF22_RF_init();
|
||||||
bind_counter=SGF22_BIND_COUNT;
|
bind_counter=SGF22_BIND_COUNT;
|
||||||
packet_sent = packet_count = 0x26; // TX2:26 TX3:26
|
packet_sent = packet_count = 0x26; // TX2:26 TX3:26
|
||||||
phase = SGF22_DATA1;
|
phase = 0;
|
||||||
#ifdef SGF22_HUB_TELEMETRY
|
|
||||||
RX_RSSI = 100; // Dummy value
|
|
||||||
telemetry_lost = 1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,232 +0,0 @@
|
|||||||
/*
|
|
||||||
This project is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Multiprotocol 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.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#if defined(SHENQI2_NRF24L01_INO)
|
|
||||||
|
|
||||||
#include "iface_xn297.h"
|
|
||||||
|
|
||||||
//#define FORCE_SHENQI2_ORIGINAL_ID
|
|
||||||
|
|
||||||
#define SHENQI2_PAYLOAD_SIZE 8
|
|
||||||
#define SHENQI2_RF_NUM_CHANNELS 16
|
|
||||||
#define SHENQI2_BIND_COUNT 2000
|
|
||||||
#define SHENQI2_WRITE_TIME 650
|
|
||||||
#define SHENQI2_BIND_CHANNEL 44
|
|
||||||
#define SHENQI2_PACKET_PERIOD 8210
|
|
||||||
|
|
||||||
|
|
||||||
enum {
|
|
||||||
SHENQI2_BIND = 0,
|
|
||||||
SHENQI2_BIND_RX,
|
|
||||||
SHENQI2_DATA,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void __attribute__((unused)) SHENQI2_send_packet()
|
|
||||||
{
|
|
||||||
if(bind_counter)
|
|
||||||
{
|
|
||||||
bind_counter--;
|
|
||||||
if(!bind_counter)
|
|
||||||
BIND_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(packet, 0x00, SHENQI2_PAYLOAD_SIZE);
|
|
||||||
|
|
||||||
packet_count &= 0x0F;
|
|
||||||
packet[0] = packet_count;
|
|
||||||
|
|
||||||
memcpy(&packet[1],rx_tx_addr,5);
|
|
||||||
|
|
||||||
if(IS_BIND_DONE)
|
|
||||||
{//Normal
|
|
||||||
uint8_t val = convert_channel_8b(CH2);
|
|
||||||
if(val < 0x70)
|
|
||||||
val = 0x30;
|
|
||||||
else if(val < 0x80)
|
|
||||||
val = 0x00;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
val &= 0x7F;
|
|
||||||
val >>= 2;
|
|
||||||
}
|
|
||||||
if(Channel_data[CH1] > 1024+50)
|
|
||||||
val |= 0x40;
|
|
||||||
else if(Channel_data[CH1] < 1024-50)
|
|
||||||
val |= 0x80;
|
|
||||||
packet[6] = val;
|
|
||||||
//packet[7] = 0x00; // ??
|
|
||||||
}
|
|
||||||
else
|
|
||||||
packet[0] |= 0x30;
|
|
||||||
|
|
||||||
// Send
|
|
||||||
XN297_SetPower();
|
|
||||||
XN297_SetTxRxMode(TX_EN);
|
|
||||||
XN297_WriteEnhancedPayload(packet, SHENQI2_PAYLOAD_SIZE, false);
|
|
||||||
#ifdef DEBUG_SERIAL
|
|
||||||
for(uint8_t i=0; i < SHENQI2_PAYLOAD_SIZE; i++)
|
|
||||||
debug("%02X ", packet[i]);
|
|
||||||
debugln();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((unused)) SHENQI2_initialize_txid()
|
|
||||||
{
|
|
||||||
#ifdef FORCE_SHENQI2_ORIGINAL_ID
|
|
||||||
//TXID
|
|
||||||
rx_tx_addr[0] = 0x51;
|
|
||||||
rx_tx_addr[1] = 0x70;
|
|
||||||
rx_tx_addr[2] = 0x02;
|
|
||||||
//RXID
|
|
||||||
rx_tx_addr[3] = 0x46;
|
|
||||||
rx_tx_addr[4] = 0xBE;
|
|
||||||
#endif
|
|
||||||
rx_tx_addr[3] = 0x00;
|
|
||||||
rx_tx_addr[4] = 0x00;
|
|
||||||
//Freq
|
|
||||||
memcpy(hopping_frequency,(uint8_t*)"\x05\x09\x0E\x0F\x17\x1C\x21\x27\x2A\x2C\x33\x39\x3D\x42\x48\x4C",16);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((unused)) SHENQI2_RF_init()
|
|
||||||
{
|
|
||||||
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
|
|
||||||
//Address
|
|
||||||
XN297_SetTXAddr((uint8_t*)"\x74\xD1\x3A\xF5\x6C", 5);
|
|
||||||
XN297_SetRXAddr((uint8_t*)"\x74\xD1\x3A\xF5\x6C", SHENQI2_PAYLOAD_SIZE);
|
|
||||||
XN297_RFChannel(SHENQI2_BIND_CHANNEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t SHENQI2_callback()
|
|
||||||
{
|
|
||||||
static bool rx=false;
|
|
||||||
|
|
||||||
switch(phase)
|
|
||||||
{
|
|
||||||
case SHENQI2_BIND:
|
|
||||||
rx = XN297_IsRX();
|
|
||||||
XN297_SetTxRxMode(TXRX_OFF);
|
|
||||||
SHENQI2_send_packet();
|
|
||||||
packet_count++;
|
|
||||||
if(rx)
|
|
||||||
{
|
|
||||||
uint8_t val=XN297_ReadEnhancedPayload(packet_in, SHENQI2_PAYLOAD_SIZE);
|
|
||||||
if(val == SHENQI2_PAYLOAD_SIZE)
|
|
||||||
{
|
|
||||||
if(memcmp(rx_tx_addr, packet_in, 3) == 0)
|
|
||||||
{//Good packet with our TXID
|
|
||||||
BIND_DONE;
|
|
||||||
rx_tx_addr[3] = packet_in[3];
|
|
||||||
rx_tx_addr[4] = packet_in[4];
|
|
||||||
packet_count = 0;
|
|
||||||
phase = SHENQI2_DATA;
|
|
||||||
}
|
|
||||||
#ifdef DEBUG_SERIAL
|
|
||||||
for(uint8_t i=0; i < SHENQI2_PAYLOAD_SIZE; i++)
|
|
||||||
debug(" %02X", packet_in[i]);
|
|
||||||
debugln();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
phase++;
|
|
||||||
return SHENQI2_WRITE_TIME;
|
|
||||||
case SHENQI2_BIND_RX:
|
|
||||||
XN297_SetTxRxMode(TXRX_OFF);
|
|
||||||
XN297_SetTxRxMode(RX_EN);
|
|
||||||
phase = SHENQI2_BIND;
|
|
||||||
return SHENQI2_PACKET_PERIOD - SHENQI2_WRITE_TIME;
|
|
||||||
default: //SHENQI2_DATA
|
|
||||||
//Since I don't know the order of the channels, I'm hopping on all the channels quickly
|
|
||||||
//Refresh rate from the motorcycle perspective is 32ms instead of 8ms...
|
|
||||||
XN297_Hopping(hopping_frequency_no);
|
|
||||||
hopping_frequency_no++;
|
|
||||||
hopping_frequency_no &= 0x0F;
|
|
||||||
SHENQI2_send_packet();
|
|
||||||
if(hopping_frequency_no%4 == 0)
|
|
||||||
packet_count++;
|
|
||||||
return SHENQI2_PACKET_PERIOD/4;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SHENQI2_init()
|
|
||||||
{
|
|
||||||
BIND_IN_PROGRESS;
|
|
||||||
SHENQI2_initialize_txid();
|
|
||||||
SHENQI2_RF_init();
|
|
||||||
|
|
||||||
bind_counter = SHENQI2_BIND_COUNT;
|
|
||||||
phase = SHENQI2_BIND;
|
|
||||||
hopping_frequency_no = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
XN297 1Mb Enhanced,Acked,Scrambled
|
|
||||||
|
|
||||||
Bind
|
|
||||||
---
|
|
||||||
RX on channel: 44, Time: 2890us P: 34 51 70 02 00 00 00 00
|
|
||||||
RX on channel: 44, Time: 1780us P: 34 51 70 02 00 00 00 00
|
|
||||||
RX on channel: 44, Time: 1773us P: 34 51 70 02 00 00 00 00
|
|
||||||
RX on channel: 44, Time: 1772us P: 34 51 70 02 00 00 00 00
|
|
||||||
RX on channel: 44, Time: 2889us P: 35 51 70 02 00 00 00 00
|
|
||||||
RX on channel: 44, Time: 1769us P: 35 51 70 02 00 00 00 00
|
|
||||||
RX on channel: 44, Time: 1774us P: 35 51 70 02 00 00 00 00
|
|
||||||
RX on channel: 44, Time: 1771us P: 35 51 70 02 00 00 00 00
|
|
||||||
RX on channel: 44, Time: 2894us P: 36 51 70 02 00 00 00 00
|
|
||||||
|
|
||||||
A= 74 D1 3A F5 6C
|
|
||||||
RF:44
|
|
||||||
Timing: 1772µs between the same 4 packets, 2892µs to the next packet, 8208µs between 2 packets
|
|
||||||
Request ack, if no ack repeat the packet 4 times
|
|
||||||
|
|
||||||
P[0] = counter 00..0F | 30 bind
|
|
||||||
P[1] = TXID[0]
|
|
||||||
P[2] = TXID[1]
|
|
||||||
P[3] = TXID[2]
|
|
||||||
P[4] = RXID[0]
|
|
||||||
P[5] = RXID[1]
|
|
||||||
P[6] = TH 00..1F, Break 30, 40 ST_right, 80 ST_left
|
|
||||||
P[7] = 00?
|
|
||||||
|
|
||||||
Answer from motorcycle:
|
|
||||||
P: 51 70 02 46 BE 00 00 00
|
|
||||||
P[0] = TXID[0]
|
|
||||||
P[1] = TXID[1]
|
|
||||||
P[2] = TXID[2]
|
|
||||||
P[3] = RXID[0]
|
|
||||||
P[4] = RXID[1]
|
|
||||||
P[5] = 00
|
|
||||||
P[6] = 00
|
|
||||||
P[7] = 00
|
|
||||||
|
|
||||||
Normal packets
|
|
||||||
---
|
|
||||||
A= 74 D1 3A F5 6C
|
|
||||||
RF:5,9,14,15,23,28,33,39,42,44,51,57,61,66,72,76
|
|
||||||
RF:\x05\x09\x0E\x0F\x17\x1C\x21\x27\x2A\x2C\x33\x39\x3D\x42\x48\x4C
|
|
||||||
- order of the channels is unknown and vary over time
|
|
||||||
- send 16 times on each channel and switch (counter 00..0F)
|
|
||||||
Timing:1772µs between the same 4 packets, 2892µs to the next packet, 8208µs between 2 packets
|
|
||||||
Timing:8208 between packets if acked
|
|
||||||
P: 00 51 70 02 46 BE 00 00
|
|
||||||
P[0] = counter 00..0F
|
|
||||||
P[1] = TXID[0]
|
|
||||||
P[2] = TXID[1]
|
|
||||||
P[3] = TXID[2]
|
|
||||||
P[4] = RXID[0]
|
|
||||||
P[5] = RXID[1]
|
|
||||||
P[6] = TH 00..1F, Break 30, 40 ST_right, 80 ST_left
|
|
||||||
P[7] = 00?
|
|
||||||
*/
|
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
#include "iface_nrf250k.h"
|
#include "iface_nrf250k.h"
|
||||||
|
|
||||||
//#define SLT_Q200_FORCE_ID
|
//#define SLT_Q200_FORCE_ID
|
||||||
//#define SLT_V1_4_FORCE_ID
|
|
||||||
|
|
||||||
// For code readability
|
// For code readability
|
||||||
#define SLT_PAYLOADSIZE_V1 7
|
#define SLT_PAYLOADSIZE_V1 7
|
||||||
@@ -74,12 +73,12 @@ static void __attribute__((unused)) SLT_set_freq(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unique freq
|
// Unique freq
|
||||||
uint8_t max_freq = 0x50; //V1 and V2
|
uint8_t max_freq=0x50; //V1 and V2
|
||||||
if(sub_protocol == Q200)
|
if(sub_protocol==Q200)
|
||||||
max_freq=45;
|
max_freq=45;
|
||||||
for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i)
|
for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i)
|
||||||
{
|
{
|
||||||
if(sub_protocol == Q200 && hopping_frequency[i] >= max_freq)
|
if(sub_protocol==Q200 && hopping_frequency[i] >= max_freq)
|
||||||
hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03;
|
hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03;
|
||||||
uint8_t done = 0;
|
uint8_t done = 0;
|
||||||
while (!done)
|
while (!done)
|
||||||
@@ -95,15 +94,15 @@ static void __attribute__((unused)) SLT_set_freq(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_SERIAL
|
#if 0
|
||||||
debug("CH:");
|
debug("CH:");
|
||||||
for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i)
|
for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i)
|
||||||
debug(" %02X(%d)", hopping_frequency[i], hopping_frequency[i]);
|
debug(" %02X", hopping_frequency[i]);
|
||||||
debugln();
|
debugln();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Bind channel
|
//Bind channel
|
||||||
hopping_frequency[SLT_NFREQCHANNELS] = SLT_BIND_CHANNEL;
|
hopping_frequency[SLT_NFREQCHANNELS]=SLT_BIND_CHANNEL;
|
||||||
|
|
||||||
//Calib all channels
|
//Calib all channels
|
||||||
NRF250K_HoppingCalib(SLT_NFREQCHANNELS+1);
|
NRF250K_HoppingCalib(SLT_NFREQCHANNELS+1);
|
||||||
@@ -154,38 +153,35 @@ static void __attribute__((unused)) SLT_build_packet()
|
|||||||
|
|
||||||
//->V1 stops here
|
//->V1 stops here
|
||||||
|
|
||||||
if(sub_protocol == Q200)
|
if(sub_protocol==Q200)
|
||||||
packet[6] = GET_FLAG(CH9_SW , FLAG_Q200_FMODE)
|
packet[6] = GET_FLAG(CH9_SW , FLAG_Q200_FMODE)
|
||||||
|GET_FLAG(CH10_SW, FLAG_Q200_FLIP)
|
|GET_FLAG(CH10_SW, FLAG_Q200_FLIP)
|
||||||
|GET_FLAG(CH11_SW, FLAG_Q200_VIDON)
|
|GET_FLAG(CH11_SW, FLAG_Q200_VIDON)
|
||||||
|GET_FLAG(CH12_SW, FLAG_Q200_VIDOFF);
|
|GET_FLAG(CH12_SW, FLAG_Q200_VIDOFF);
|
||||||
else if(sub_protocol == MR100 || sub_protocol == Q100)
|
else if(sub_protocol==MR100 || sub_protocol==Q100)
|
||||||
packet[6] = GET_FLAG(CH9_SW , FLAG_MR100_FMODE)
|
packet[6] = GET_FLAG(CH9_SW , FLAG_MR100_FMODE)
|
||||||
|GET_FLAG(CH10_SW, FLAG_MR100_FLIP)
|
|GET_FLAG(CH10_SW, FLAG_MR100_FLIP)
|
||||||
|GET_FLAG(CH11_SW, FLAG_MR100_VIDEO) // Does not exist on the Q100 but...
|
|GET_FLAG(CH11_SW, FLAG_MR100_VIDEO) // Does not exist on the Q100 but...
|
||||||
|GET_FLAG(CH12_SW, FLAG_MR100_PICTURE); // Does not exist on the Q100 but...
|
|GET_FLAG(CH12_SW, FLAG_MR100_PICTURE); // Does not exist on the Q100 but...
|
||||||
packet[7] = convert_channel_8b(CH7);
|
packet[7]=convert_channel_8b(CH7);
|
||||||
packet[8] = convert_channel_8b(CH8);
|
packet[8]=convert_channel_8b(CH8);
|
||||||
if(sub_protocol == RF_SIM)
|
if(sub_protocol==RF_SIM) {
|
||||||
{
|
packet[9]=convert_channel_8b(CH9);
|
||||||
packet[9] = convert_channel_8b(CH9);
|
packet[10]=convert_channel_8b(CH10);
|
||||||
packet[10] = convert_channel_8b(CH10);
|
} else {
|
||||||
}
|
packet[9]=0xAA; //normal mode for Q100/Q200, unknown for V2/MR100
|
||||||
else
|
packet[10]=0x00; //normal mode for Q100/Q200, unknown for V2/MR100
|
||||||
{
|
}
|
||||||
packet[9] = 0xAA; //normal mode for Q100/Q200, unknown for V2/MR100
|
if((sub_protocol==Q100 || sub_protocol==Q200) && CH13_SW)
|
||||||
packet[10] = 0x00; //normal mode for Q100/Q200, unknown for V2/MR100
|
|
||||||
}
|
|
||||||
if((sub_protocol == Q100 || sub_protocol == Q200) && CH13_SW)
|
|
||||||
{//Calibrate
|
{//Calibrate
|
||||||
packet[9] = 0x77; //enter calibration
|
packet[9]=0x77; //enter calibration
|
||||||
if(calib_counter >= 20 && calib_counter <= 25) // 7 packets for Q100 / 3 packets for Q200
|
if(calib_counter>=20 && calib_counter<=25) // 7 packets for Q100 / 3 packets for Q200
|
||||||
packet[10] = 0x20; //launch calibration
|
packet[10]=0x20; //launch calibration
|
||||||
calib_counter++;
|
calib_counter++;
|
||||||
if(calib_counter > 250) calib_counter = 250;
|
if(calib_counter>250) calib_counter=250;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
calib_counter = 0;
|
calib_counter=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __attribute__((unused)) SLT_send_bind_packet()
|
static void __attribute__((unused)) SLT_send_bind_packet()
|
||||||
@@ -196,8 +192,8 @@ static void __attribute__((unused)) SLT_send_bind_packet()
|
|||||||
NRF250K_SetPower();
|
NRF250K_SetPower();
|
||||||
BIND_DONE;
|
BIND_DONE;
|
||||||
NRF250K_SetTXAddr((uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
|
NRF250K_SetTXAddr((uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
|
||||||
memcpy((void*)packet, (void*)rx_tx_addr, SLT_TXID_SIZE);
|
memcpy((void*)packet,(void*)rx_tx_addr,SLT_TXID_SIZE);
|
||||||
if(phase == SLT_BIND2)
|
if(phase==SLT_BIND2)
|
||||||
SLT_send_packet(SLT_TXID_SIZE);
|
SLT_send_packet(SLT_TXID_SIZE);
|
||||||
else // SLT_BIND1
|
else // SLT_BIND1
|
||||||
SLT_send_packet(SLT_PAYLOADSIZE_V2);
|
SLT_send_packet(SLT_PAYLOADSIZE_V2);
|
||||||
@@ -228,9 +224,9 @@ uint16_t SLT_callback()
|
|||||||
case SLT_DATA2:
|
case SLT_DATA2:
|
||||||
phase++;
|
phase++;
|
||||||
SLT_send_packet(packet_length);
|
SLT_send_packet(packet_length);
|
||||||
if(sub_protocol == SLT_V1)
|
if(sub_protocol==SLT_V1)
|
||||||
return SLT_V1_TIMING_PACKET;
|
return SLT_V1_TIMING_PACKET;
|
||||||
if(sub_protocol == SLT_V1_4)
|
if(sub_protocol==SLT_V1_4)
|
||||||
{
|
{
|
||||||
phase++; //Packets are sent two times only
|
phase++; //Packets are sent two times only
|
||||||
return SLT_V1_4_TIMING_PACKET;
|
return SLT_V1_4_TIMING_PACKET;
|
||||||
@@ -242,24 +238,24 @@ uint16_t SLT_callback()
|
|||||||
if (++packet_count >= 100)
|
if (++packet_count >= 100)
|
||||||
{// Send bind packet
|
{// Send bind packet
|
||||||
packet_count = 0;
|
packet_count = 0;
|
||||||
if(sub_protocol == SLT_V1 || sub_protocol == SLT_V1_4)
|
if(sub_protocol==SLT_V1||sub_protocol==SLT_V1_4)
|
||||||
{
|
{
|
||||||
phase = SLT_BIND2;
|
phase=SLT_BIND2;
|
||||||
return SLT_V1_TIMING_BIND2;
|
return SLT_V1_TIMING_BIND2;
|
||||||
}
|
}
|
||||||
//V2
|
//V2
|
||||||
phase = SLT_BIND1;
|
phase=SLT_BIND1;
|
||||||
return SLT_V2_TIMING_BIND1;
|
return SLT_V2_TIMING_BIND1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{// Continue to send normal packets
|
{// Continue to send normal packets
|
||||||
phase = SLT_BUILD;
|
phase = SLT_BUILD;
|
||||||
if(sub_protocol == SLT_V1)
|
if(sub_protocol==SLT_V1)
|
||||||
return 20000 - SLT_TIMING_BUILD;
|
return 20000-SLT_TIMING_BUILD;
|
||||||
if(sub_protocol==SLT_V1_4)
|
if(sub_protocol==SLT_V1_4)
|
||||||
return 18000 - SLT_TIMING_BUILD - SLT_V1_4_TIMING_PACKET;
|
return 18000-SLT_TIMING_BUILD-SLT_V1_4_TIMING_PACKET;
|
||||||
//V2
|
//V2
|
||||||
return 13730 - SLT_TIMING_BUILD;
|
return 13730-SLT_TIMING_BUILD;
|
||||||
}
|
}
|
||||||
case SLT_BIND1:
|
case SLT_BIND1:
|
||||||
SLT_send_bind_packet();
|
SLT_send_bind_packet();
|
||||||
@@ -268,12 +264,12 @@ uint16_t SLT_callback()
|
|||||||
case SLT_BIND2:
|
case SLT_BIND2:
|
||||||
SLT_send_bind_packet();
|
SLT_send_bind_packet();
|
||||||
phase = SLT_BUILD;
|
phase = SLT_BUILD;
|
||||||
if(sub_protocol == SLT_V1)
|
if(sub_protocol==SLT_V1)
|
||||||
return 20000 - SLT_TIMING_BUILD - SLT_V1_TIMING_BIND2;
|
return 20000-SLT_TIMING_BUILD-SLT_V1_TIMING_BIND2;
|
||||||
if(sub_protocol == SLT_V1_4)
|
if(sub_protocol==SLT_V1_4)
|
||||||
return 18000 - SLT_TIMING_BUILD - SLT_V1_TIMING_BIND2 - SLT_V1_4_TIMING_PACKET;
|
return 18000-SLT_TIMING_BUILD-SLT_V1_TIMING_BIND2-SLT_V1_4_TIMING_PACKET;
|
||||||
//V2
|
//V2
|
||||||
return 13730 - SLT_TIMING_BUILD - SLT_V2_TIMING_BIND1 - SLT_V2_TIMING_BIND2;
|
return 13730-SLT_TIMING_BUILD-SLT_V2_TIMING_BIND1-SLT_V2_TIMING_BIND2;
|
||||||
}
|
}
|
||||||
return 19000;
|
return 19000;
|
||||||
}
|
}
|
||||||
@@ -284,36 +280,7 @@ void SLT_init()
|
|||||||
packet_count = 0;
|
packet_count = 0;
|
||||||
packet_sent = 0;
|
packet_sent = 0;
|
||||||
hopping_frequency_no = 0;
|
hopping_frequency_no = 0;
|
||||||
|
if(sub_protocol==Q200)
|
||||||
if(sub_protocol == SLT_V1)
|
|
||||||
{
|
|
||||||
packet_length = SLT_PAYLOADSIZE_V1;
|
|
||||||
#ifdef MULTI_SYNC
|
|
||||||
packet_period = 20000+2*SLT_V1_TIMING_PACKET; //22ms
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else if(sub_protocol == SLT_V1_4)
|
|
||||||
{
|
|
||||||
packet_length = SLT_PAYLOADSIZE_V1_4;
|
|
||||||
#ifdef MULTI_SYNC
|
|
||||||
packet_period = 18000; //18ms
|
|
||||||
#endif
|
|
||||||
//Force high part of the ID otherwise the RF frequencies do not match, only tested the 2 last bytes...
|
|
||||||
rx_tx_addr[0]=0xF4;
|
|
||||||
rx_tx_addr[1]=0x71;
|
|
||||||
#ifdef SLT_V1_4_FORCE_ID // ID taken from TX dumps
|
|
||||||
memcpy(rx_tx_addr,"\xF4\x71\x8D\x01",SLT_TXID_SIZE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else //V2
|
|
||||||
{
|
|
||||||
packet_length = SLT_PAYLOADSIZE_V2;
|
|
||||||
#ifdef MULTI_SYNC
|
|
||||||
packet_period = 13730+2*SLT_V2_TIMING_PACKET; //~18ms
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sub_protocol == Q200)
|
|
||||||
{ //Q200: Force high part of the ID otherwise it won't bind
|
{ //Q200: Force high part of the ID otherwise it won't bind
|
||||||
rx_tx_addr[0]=0x01;
|
rx_tx_addr[0]=0x01;
|
||||||
rx_tx_addr[1]=0x02;
|
rx_tx_addr[1]=0x02;
|
||||||
@@ -322,11 +289,34 @@ void SLT_init()
|
|||||||
/* rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x0B;rx_tx_addr[3]=0x57;*/
|
/* rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x0B;rx_tx_addr[3]=0x57;*/
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SLT_RF_init();
|
SLT_RF_init();
|
||||||
SLT_set_freq();
|
SLT_set_freq();
|
||||||
|
|
||||||
phase = SLT_BUILD;
|
phase = SLT_BUILD;
|
||||||
|
if(sub_protocol==SLT_V1)
|
||||||
|
{
|
||||||
|
packet_length = SLT_PAYLOADSIZE_V1;
|
||||||
|
#ifdef MULTI_SYNC
|
||||||
|
packet_period = 20000+2*SLT_V1_TIMING_PACKET; //22ms
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if(sub_protocol==SLT_V1_4)
|
||||||
|
{
|
||||||
|
packet_length = SLT_PAYLOADSIZE_V1_4;
|
||||||
|
#ifdef MULTI_SYNC
|
||||||
|
packet_period = 18000; //18ms
|
||||||
|
#endif
|
||||||
|
//Test IDs
|
||||||
|
MProtocol_id = MProtocol_id_master ^ (1<<RX_num);
|
||||||
|
set_rx_tx_addr(MProtocol_id);
|
||||||
|
debugln("Try ID: %lx", MProtocol_id);
|
||||||
|
}
|
||||||
|
else //V2
|
||||||
|
{
|
||||||
|
packet_length = SLT_PAYLOADSIZE_V2;
|
||||||
|
#ifdef MULTI_SYNC
|
||||||
|
packet_period = 13730+2*SLT_V2_TIMING_PACKET; //~18ms
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -404,7 +404,7 @@ RX: 0x02 0x4A 0xA3 0x2D 0x1A 0x49 0xFE 0x06 0x00 0x00 0x02 0x01 0x06 0x06 0x00 0
|
|||||||
TX: 0x02 0x65 0xE2 0x5E 0x55 0x4D 0xFE 0xEE 0x00 0x00 0x01 0x01 0x06 0x05 0x00 0x00
|
TX: 0x02 0x65 0xE2 0x5E 0x55 0x4D 0xFE 0xEE 0x00 0x00 0x01 0x01 0x06 0x05 0x00 0x00
|
||||||
Notes:
|
Notes:
|
||||||
- RX cyrfmfg_id is 0x4A,0xA3,0x2D,0x1A,0x49,0xFE and TX cyrfmfg_id is 0x65,0xE2,0x5E,0x55,0x4D,0xFE
|
- RX cyrfmfg_id is 0x4A,0xA3,0x2D,0x1A,0x49,0xFE and TX cyrfmfg_id is 0x65,0xE2,0x5E,0x55,0x4D,0xFE
|
||||||
- P[7] = RX SOP code index, changes from 0x06 to 0xEE but not needed to complete the bind -> doesn't care??
|
- P[7] changes from 0x06 to 0xEE but not needed to complete the bind -> doesn't care??
|
||||||
- P[8] RF channel - 1 (on packets type 0x03)
|
- P[8] RF channel - 1 (on packets type 0x03)
|
||||||
- P[9] 0x00 unchanged??
|
- P[9] 0x00 unchanged??
|
||||||
- P[10] needs to be set to 0x01 to complete the bind -> normal packet P[0]??
|
- P[10] needs to be set to 0x01 to complete the bind -> normal packet P[0]??
|
||||||
@@ -474,123 +474,4 @@ Traxxas TQ 1st generation
|
|||||||
-------------------------
|
-------------------------
|
||||||
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/issues/967#issuecomment-2079038576
|
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/issues/967#issuecomment-2079038576
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
Traxxas TQi
|
|
||||||
-------------------------
|
|
||||||
Unknown 3 first packets:
|
|
||||||
CHANNEL: 0x2B
|
|
||||||
SOP_CODE: 0x3C 0x37 0xCC 0x91 0xE2 0xF8 0xCC 0x91
|
|
||||||
CRC_SEED_LSB: 0x5A
|
|
||||||
CRC_SEED_MSB: 0x5A
|
|
||||||
RX: 0xA0 0x1F 0x60 0x58 0x34 0x44 0x1C 0x11 0xA5 0x72 0x8D 0x9D 0xEA 0x49 0x2B 0xE2
|
|
||||||
RX: 0xD3 0x53 0xD4 0x45 0x1B 0x6F 0x75 0x42 0xEF 0x8A 0xD2 0x24 0x8E 0xF0 0x05 0x6C
|
|
||||||
RX: 0xAA 0xD7 0xD7 0x43 0x0F 0x2F 0x02 0x8F 0x06 0x54 0x3A 0x35 0xF5 0xCF 0x0F 0x82
|
|
||||||
|
|
||||||
Packets 0x02: Bind learn TX/RX addresses same as TQ 2nd:
|
|
||||||
CHANNEL: 0x2B
|
|
||||||
SOP_CODE: 0x3C 0x37 0xCC 0x91 0xE2 0xF8 0xCC 0x91
|
|
||||||
CRC_SEED_LSB: 0x5A
|
|
||||||
CRC_SEED_MSB: 0x5A
|
|
||||||
RX: 0x02 0x5B 0xE9 0x7E 0x14 0xF1 0xFE 0x0D 0x00 0x00 0x02 0x02 0x00 0x26 0x00 0x00
|
|
||||||
TX: 0x02 0xE0 0xAC 0x7F 0x14 0xF1 0xFE 0x00 0x00 0x00 0x01 0x02 0x00 0x51 0x00 0x00
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
- P[1..6] = RX cyrfmfg_id is 0x5B,0xE9,0x7E,0x14,0xF1,0xFE and TX cyrfmfg_id is 0xE0,0xAC,0x7F,0x14,0xF1,0xFE
|
|
||||||
- P[7] RX SOP code index, changes from 0x0D to 0x00 (but not needed to complete the bind -> doesn't care??)
|
|
||||||
- P[8] RF channel - 1 (on packets type 0x03)
|
|
||||||
- P[9] 0x00 unchanged??
|
|
||||||
- P[10] needs to be set to 0x01 to complete the bind -> normal packet P[0]??
|
|
||||||
- P[11] unchanged ?? (-> no bind if set to 0x00 or 0x81)
|
|
||||||
- P[12] unchanged ?? (-> no bind if set to 0x05 or 0x86)
|
|
||||||
- P[13] changes from 0x26 to 0x51 (but not needed to complete the bind -> doesn't care??)
|
|
||||||
- P[14..15]=0x00 unchanged??
|
|
||||||
|
|
||||||
Next steps:
|
|
||||||
Packets 0x08: ???
|
|
||||||
TX: 0x08 0x00 0x03 0x14 0xFD 0x3E 0x28 0xB9 0xCA 0x48 0x76 0x4E 0x00 0x51 0x00 0x00
|
|
||||||
TX: 0x08 0x00 0x02 0x14 0xFD 0x3E 0x28 0xB9 0xCA 0x48 0x76 0x4E 0x00 0x51 0x00 0x00
|
|
||||||
TX: 0x08 0x00 0x01 0x14 0xFD 0x3E 0x28 0xB9 0xCA 0x48 0x76 0x4E 0x00 0x51 0x00 0x00
|
|
||||||
RX: 0x08 0x00 0x03 0x14 0xFD 0x24 0x20 0xB8 0xCA 0x48 0x76 0x4E 0x00 0x26 0x00 0x00
|
|
||||||
RX: 0x08 0x00 0x01 0x14 0xFD 0x24 0x20 0xB8 0xCA 0x48 0x76 0x4E 0x00 0x26 0x00 0x00
|
|
||||||
P[1] index
|
|
||||||
P[2] sequence number
|
|
||||||
|
|
||||||
Packets 0x09: ???
|
|
||||||
TX: 0x09 0x00 0x03 0xEE 0x12 0x49 0x57 0x1F 0x4B 0x60 0x6B 0x4D 0x14 0xEF 0x69 0xC4
|
|
||||||
TX: 0x09 0x00 0x02 0xEE 0x12 0x49 0x57 0x1F 0x4B 0x60 0x6B 0x4D 0x14 0xEF 0x69 0xC4
|
|
||||||
TX: 0x09 0x00 0x01 0xEE 0x12 0x49 0x57 0x1F 0x4B 0x60 0x6B 0x4D 0x14 0xEF 0x69 0xC4
|
|
||||||
TX: 0x09 0x01 0x03 0xB2 0x63 0x43 0x25 0x22 0x4D 0xA1 0x15 0xFE 0xBA 0x7D 0x67 0x3E
|
|
||||||
TX: 0x09 0x01 0x02 0xB2 0x63 0x43 0x25 0x22 0x4D 0xA1 0x15 0xFE 0xBA 0x7D 0x67 0x3E
|
|
||||||
TX: 0x09 0x01 0x01 0xB2 0x63 0x43 0x25 0x22 0x4D 0xA1 0x15 0xFE 0xBA 0x7D 0x67 0x3E
|
|
||||||
TX: 0x09 0x02 0x03 0xCB 0xBE 0xA6 0xD1 0xCD 0x23 0xA1 0x15 0xFE 0xBA 0x7D 0x67 0x3E
|
|
||||||
TX: 0x09 0x02 0x02 0xCB 0xBE 0xA6 0xD1 0xCD 0x23 0xA1 0x15 0xFE 0xBA 0x7D 0x67 0x3E
|
|
||||||
TX: 0x09 0x02 0x01 0xCB 0xBE 0xA6 0xD1 0xCD 0x23 0xA1 0x15 0xFE 0xBA 0x7D 0x67 0x3E
|
|
||||||
RX: 0x09 0x00 0x03 0x90 0x24 0x93 0x08 0x41 0xC7 0x7F 0x59 0xB4 0xE3 0x25 0x77 0xB5
|
|
||||||
RX: 0x09 0x00 0x01 0x90 0x24 0x93 0x08 0x41 0xC7 0x7F 0x59 0xB4 0xE3 0x25 0x77 0xB5
|
|
||||||
RX: 0x09 0x01 0x02 0x88 0xFA 0x4D 0xFB 0x33 0xD4 0xFE 0x5F 0x1C 0xA9 0x0B 0x7A 0xE6
|
|
||||||
RX: 0x09 0x02 0x03 0x86 0xAF 0xD0 0x91 0xF6 0xDD 0xFE 0x5F 0x1C 0xA9 0x0B 0x7A 0xE6
|
|
||||||
RX: 0x09 0x02 0x01 0x86 0xAF 0xD0 0x91 0xF6 0xDD 0xFE 0x5F 0x1C 0xA9 0x0B 0x7A 0xE6
|
|
||||||
P[1] index
|
|
||||||
P[2] sequence number
|
|
||||||
|
|
||||||
Switch to normal mode:
|
|
||||||
SOP_CODE: 0xD2 0x8F 0xB1 0x2A 0xEF 0x64 0xB0 0x2A
|
|
||||||
CRC_SEED_LSB: 0x85
|
|
||||||
CRC_SEED_MSB: 0xC3
|
|
||||||
CHANNEL: 0x05
|
|
||||||
TX: 0x01 0x00 0x02 0xF5 0x02 0x9E 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x99 0x67 0x3E
|
|
||||||
Normal content except P[14]&P[15] = 0x67&0x3E from previous packet sent
|
|
||||||
|
|
||||||
SOP_CODE: 0x97 0xE5 0x14 0x72 0x7F 0x1A 0x14 0x72
|
|
||||||
CRC_SEED_LSB: 0xA5
|
|
||||||
CRC_SEED_MSB: 0xA5
|
|
||||||
CHANNEL: 0x22
|
|
||||||
RX: 0x04 0x5B 0xE9 0x7E 0x14 0xF1 0xFE 0x0D 0xDD 0xFE 0x02 0x02 0x00 0x26 0x7A 0xE6
|
|
||||||
RX packets 0x04: RX identity ?
|
|
||||||
P[1..6] = RX cyrfmfg_id 0x5B,0xE9,0x7E,0x14,0xF1,0xFE
|
|
||||||
P[7] = SOP index
|
|
||||||
P[8] = unknown
|
|
||||||
P[9] = unknown
|
|
||||||
P[10] = same value as bind 0x02
|
|
||||||
P[11] = same value as bind 0x02
|
|
||||||
P[12] = same value as bind 0x00
|
|
||||||
P[13] = same value as bind 0x26
|
|
||||||
P[14] = unknown
|
|
||||||
P[15] = unknown
|
|
||||||
|
|
||||||
SOP_CODE: 0xD2 0x8F 0xB1 0x2A 0xEF 0x64 0xB0 0x2A
|
|
||||||
CRC_SEED_LSB: 0x85
|
|
||||||
CRC_SEED_MSB: 0xC3
|
|
||||||
CHANNEL: 0x05
|
|
||||||
TX: 0x14 0x00 0x03 0xF5 0x02 0x9E 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x99 0x67 0x3E
|
|
||||||
TX: 0x14 0x00 0x02 0xF5 0x02 0x9E 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x99 0x67 0x3E
|
|
||||||
TX: 0x14 0x00 0x01 0xF5 0x02 0x9E 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x99 0x67 0x3E
|
|
||||||
RX: 0x14 0x00 0x03 0x22 0xEC 0x42 0x9B 0xD7 0x99 0x3B 0xBB 0x85 0x17 0x41 0x67 0xA0
|
|
||||||
RX: 0x14 0x00 0x01 0x22 0xEC 0x42 0x9B 0xD7 0x99 0x3B 0xBB 0x85 0x17 0x41 0x67 0xA0
|
|
||||||
RX: 0x14 0x01 0x02 0x22 0xEF 0x42 0x9C 0xCA 0xFB 0x39 0xBB 0x85 0x17 0x41 0x67 0xA0
|
|
||||||
TX packets 0x14 same as packets 0x01 with a sequence number on P[2]
|
|
||||||
RX packets 0x14 unknown content
|
|
||||||
|
|
||||||
Packets 0x01 & 0x07: normal and telemetry request/answer
|
|
||||||
TX: 0x01 0x00 0x02 0xF5 0x02 0x9E 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x99 0x00 0x00
|
|
||||||
TX: 0x07 0x00 0x02 0xF5 0x02 0x9E 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x99 0x00 0x00
|
|
||||||
RX: 0x07 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0xFB 0x00 0x00 0x85 0x17 0x41 0x67 0xA0
|
|
||||||
TX: 0x01 0x00 0x02 0xF5 0x02 0x9E 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x99 0x00 0x00
|
|
||||||
TX: 0x07 0x00 0x02 0xF5 0x02 0x9E 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x99 0x00 0x00
|
|
||||||
RX: 0x07 0x01 0x00 0x00 0x00 0x11 0x49 0xC8 0xFB 0x00 0x00 0x85 0x17 0x41 0x67 0xA0
|
|
||||||
TX: 0x01 0x00 0x02 0xF5 0x02 0x9E 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x99 0x00 0x00
|
|
||||||
TX: 0x07 0x00 0x02 0xF5 0x02 0x9E 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x99 0x00 0x00
|
|
||||||
RX: 0x07 0x01 0x00 0x00 0x00 0x12 0xDC 0x20 0xFB 0x00 0x00 0x85 0x17 0x41 0x67 0xA0
|
|
||||||
TX packets 0x07: request for telemetry
|
|
||||||
RX packets 0x07: unknown
|
|
||||||
|
|
||||||
CRC calc same as TQ 2nd:
|
|
||||||
TX ID: 0xE0,0xAC,0x7F,0x14,0xF1,0xFE
|
|
||||||
RX ID: 0x5B,0xE9,0x7E,0x14,0xF1,0xFE CRC 0x85 0xC3 => CRC: E0-5B=85 AC-E9=C3
|
|
||||||
SOP index same as TQ 2nd:
|
|
||||||
SOP index=0x0D, SOP code= 0xD2, 0x8F, 0xB1, 0x2A, 0xEF, 0x64, 0xB0, 0x2A
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -315,15 +315,6 @@ static void multi_send_status()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef RLINK_HUB_TELEMETRY
|
|
||||||
void RLINK_raw_frame()
|
|
||||||
{
|
|
||||||
multi_send_header(MULTI_TELEMETRY_RLINK, packet_in[0]);
|
|
||||||
for (uint8_t i = 1; i <= packet_in[0]; i++) // raw DumboRC reply payload
|
|
||||||
Serial_write(packet_in[i]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void multi_send_frskyhub()
|
static void multi_send_frskyhub()
|
||||||
{
|
{
|
||||||
multi_send_header(MULTI_TELEMETRY_HUB, 9);
|
multi_send_header(MULTI_TELEMETRY_HUB, 9);
|
||||||
@@ -896,7 +887,7 @@ void TelemetryUpdate()
|
|||||||
t += TXBUFFER_SIZE - h ;
|
t += TXBUFFER_SIZE - h ;
|
||||||
else
|
else
|
||||||
t -= h ;
|
t -= h ;
|
||||||
if ( t < 48 ) //32 )
|
if ( t < 32 )
|
||||||
{
|
{
|
||||||
debugln("TEL_BUF_FULL %d",t);
|
debugln("TEL_BUF_FULL %d",t);
|
||||||
return ;
|
return ;
|
||||||
@@ -1001,14 +992,6 @@ void TelemetryUpdate()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined RLINK_HUB_TELEMETRY
|
|
||||||
if(telemetry_link == 2 && protocol == PROTO_RLINK)
|
|
||||||
{
|
|
||||||
RLINK_raw_frame();
|
|
||||||
telemetry_link=0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if defined SCANNER_TELEMETRY
|
#if defined SCANNER_TELEMETRY
|
||||||
if (telemetry_link && protocol == PROTO_SCANNER)
|
if (telemetry_link && protocol == PROTO_SCANNER)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ uint16_t V761_callback()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
packet_count++;
|
packet_count++;
|
||||||
if(!telemetry_lost && !rx && (packet_count & 0x3F) == 0)
|
if(!telemetry_lost && !rx && (packet_count%64) == 0)
|
||||||
{// Should have received a telem packet but... Send telem to the radio to keep it alive
|
{// Should have received a telem packet but... Send telem to the radio to keep it alive
|
||||||
telemetry_link = 1;
|
telemetry_link = 1;
|
||||||
#ifdef V761_TELEM_DEBUG
|
#ifdef V761_TELEM_DEBUG
|
||||||
|
|||||||
@@ -337,11 +337,9 @@
|
|||||||
#undef REALACC_NRF24L01_INO
|
#undef REALACC_NRF24L01_INO
|
||||||
#undef SGF22_NRF24L01_INO
|
#undef SGF22_NRF24L01_INO
|
||||||
#undef SHENQI_NRF24L01_INO
|
#undef SHENQI_NRF24L01_INO
|
||||||
#undef SHENQI2_NRF24L01_INO
|
|
||||||
#undef SYMAX_NRF24L01_INO
|
#undef SYMAX_NRF24L01_INO
|
||||||
#undef V2X2_NRF24L01_INO
|
#undef V2X2_NRF24L01_INO
|
||||||
#undef V761_NRF24L01_INO
|
#undef V761_NRF24L01_INO
|
||||||
#undef WPL_NRF24L01_INO
|
|
||||||
#undef XERALL_NRF24L01_INO
|
#undef XERALL_NRF24L01_INO
|
||||||
#undef YD717_NRF24L01_INO
|
#undef YD717_NRF24L01_INO
|
||||||
#undef YUXIANG_NRF24L01_INO
|
#undef YUXIANG_NRF24L01_INO
|
||||||
@@ -360,7 +358,6 @@
|
|||||||
#undef SLT_CCNRF_INO
|
#undef SLT_CCNRF_INO
|
||||||
#undef UDIRC_CCNRF_INO
|
#undef UDIRC_CCNRF_INO
|
||||||
#undef V911S_CCNRF_INO
|
#undef V911S_CCNRF_INO
|
||||||
#undef WL91X_CCNRF_INO
|
|
||||||
#undef XK_CCNRF_INO
|
#undef XK_CCNRF_INO
|
||||||
#undef XK2_CCNRF_INO
|
#undef XK2_CCNRF_INO
|
||||||
#endif
|
#endif
|
||||||
@@ -391,19 +388,13 @@
|
|||||||
#undef LOSI_CYRF6936_INO //Need DSM to be enabled
|
#undef LOSI_CYRF6936_INO //Need DSM to be enabled
|
||||||
#undef TRAXXAS_CYRF6936_INO
|
#undef TRAXXAS_CYRF6936_INO
|
||||||
#undef EAZYRC_NRF24L01_INO
|
#undef EAZYRC_NRF24L01_INO
|
||||||
//#undef KYOSHO2_NRF24L01_INO
|
#undef KYOSHO2_NRF24L01_INO
|
||||||
#undef KYOSHO3_CYRF6936_INO
|
#undef KYOSHO3_CYRF6936_INO
|
||||||
#undef MOULDKG_NRF24L01_INO
|
#undef MOULDKG_NRF24L01_INO
|
||||||
#undef SHENQI_NRF24L01_INO
|
#undef SHENQI_NRF24L01_INO
|
||||||
#undef SHENQI2_NRF24L01_INO
|
|
||||||
#undef JIABAILE_NRF24L01_INO
|
#undef JIABAILE_NRF24L01_INO
|
||||||
#undef UDIRC_CCNRF_INO
|
#undef UDIRC_CCNRF_INO
|
||||||
#undef KAMTOM_NRF24L01_INO
|
#undef KAMTOM_NRF24L01_INO
|
||||||
#undef WL91X_CCNRF_INO
|
|
||||||
#undef WPL_NRF24L01_INO
|
|
||||||
//Save flash space...
|
|
||||||
#undef CABELL_NRF24L01_INO
|
|
||||||
#undef REDPINE_CC2500_INO
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MULTI_SURFACE
|
#ifdef MULTI_SURFACE
|
||||||
@@ -499,10 +490,6 @@
|
|||||||
#undef PROPEL_HUB_TELEMETRY
|
#undef PROPEL_HUB_TELEMETRY
|
||||||
#undef OMP_HUB_TELEMETRY
|
#undef OMP_HUB_TELEMETRY
|
||||||
#undef V761_HUB_TELEMETRY
|
#undef V761_HUB_TELEMETRY
|
||||||
#undef FX_HUB_TELEMETRY
|
|
||||||
#undef XK2_HUB_TELEMETRY
|
|
||||||
#undef SGF22_HUB_TELEMETRY
|
|
||||||
#undef KAMTOM_HUB_TELEMETRY
|
|
||||||
#undef YUXIANG_HUB_TELEMETRY
|
#undef YUXIANG_HUB_TELEMETRY
|
||||||
#undef RLINK_HUB_TELEMETRY
|
#undef RLINK_HUB_TELEMETRY
|
||||||
#undef DSM_RX_CYRF6936_INO
|
#undef DSM_RX_CYRF6936_INO
|
||||||
@@ -542,18 +529,6 @@
|
|||||||
#if not defined(V761_NRF24L01_INO)
|
#if not defined(V761_NRF24L01_INO)
|
||||||
#undef V761_HUB_TELEMETRY
|
#undef V761_HUB_TELEMETRY
|
||||||
#endif
|
#endif
|
||||||
#if not defined(FX_NRF24L01_INO)
|
|
||||||
#undef FX_HUB_TELEMETRY
|
|
||||||
#endif
|
|
||||||
#if not defined(XK2_CCNRF_INO)
|
|
||||||
#undef XK2_HUB_TELEMETRY
|
|
||||||
#endif
|
|
||||||
#if not defined(SGF22_NRF24L01_INO)
|
|
||||||
#undef SGF22_HUB_TELEMETRY
|
|
||||||
#endif
|
|
||||||
#if not defined(KAMTOM_NRF24L01_INO)
|
|
||||||
#undef KAMTOM_HUB_TELEMETRY
|
|
||||||
#endif
|
|
||||||
#if not defined(YUXIANG_NRF24L01_INO)
|
#if not defined(YUXIANG_NRF24L01_INO)
|
||||||
#undef YUXIANG_HUB_TELEMETRY
|
#undef YUXIANG_HUB_TELEMETRY
|
||||||
#endif
|
#endif
|
||||||
@@ -614,7 +589,7 @@
|
|||||||
//protocols using FRSKYD user frames
|
//protocols using FRSKYD user frames
|
||||||
#undef HUB_TELEMETRY
|
#undef HUB_TELEMETRY
|
||||||
#endif
|
#endif
|
||||||
#if not defined(HOTT_FW_TELEMETRY) && not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BUGS_HUB_TELEMETRY) && not defined(NCC1701_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(RLINK_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS) && not defined(HITEC_HUB_TELEMETRY) && not defined(HITEC_FW_TELEMETRY) && not defined(SCANNER_TELEMETRY) && not defined(FRSKY_RX_TELEMETRY) && not defined(AFHDS2A_RX_TELEMETRY) && not defined(BAYANG_RX_TELEMETRY) && not defined(DEVO_HUB_TELEMETRY) && not defined(PROPEL_HUB_TELEMETRY) && not defined(OMP_HUB_TELEMETRY) && not defined(V761_HUB_TELEMETRY) && not defined(SGF22_HUB_TELEMETRY) && not defined(XK2_HUB_TELEMETRY) && not defined(FX_HUB_TELEMETRY) && not defined(KAMTOM_HUB_TELEMETRY) && not defined(YUXIANG_HUB_TELEMETRY) && not defined(WFLY2_HUB_TELEMETRY) && not defined(LOLI_HUB_TELEMETRY) && not defined(MLINK_HUB_TELEMETRY) && not defined(MLINK_FW_TELEMETRY) && not defined(MT99XX_HUB_TELEMETRY) && not defined(MULTI_CONFIG_INO)
|
#if not defined(HOTT_FW_TELEMETRY) && not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BUGS_HUB_TELEMETRY) && not defined(NCC1701_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(RLINK_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS) && not defined(HITEC_HUB_TELEMETRY) && not defined(HITEC_FW_TELEMETRY) && not defined(SCANNER_TELEMETRY) && not defined(FRSKY_RX_TELEMETRY) && not defined(AFHDS2A_RX_TELEMETRY) && not defined(BAYANG_RX_TELEMETRY) && not defined(DEVO_HUB_TELEMETRY) && not defined(PROPEL_HUB_TELEMETRY) && not defined(OMP_HUB_TELEMETRY) && not defined(V761_HUB_TELEMETRY) && not defined(YUXIANG_HUB_TELEMETRY) && not defined(WFLY2_HUB_TELEMETRY) && not defined(LOLI_HUB_TELEMETRY) && not defined(MLINK_HUB_TELEMETRY) && not defined(MLINK_FW_TELEMETRY) && not defined(MT99XX_HUB_TELEMETRY) && not defined(MULTI_CONFIG_INO)
|
||||||
#undef TELEMETRY
|
#undef TELEMETRY
|
||||||
#undef INVERT_TELEMETRY
|
#undef INVERT_TELEMETRY
|
||||||
#undef MULTI_TELEMETRY
|
#undef MULTI_TELEMETRY
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
This project is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Multiprotocol 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.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(WL91X_CCNRF_INO)
|
|
||||||
|
|
||||||
#include "iface_xn297.h"
|
|
||||||
|
|
||||||
//#define FORCE_WL91X_ORIGINAL_ID
|
|
||||||
|
|
||||||
#define WL91X_PAYLOAD_SIZE 9
|
|
||||||
#define WL91X_RF_NUM_CHANNELS 3
|
|
||||||
#define WL91X_PACKET_PERIOD 2594
|
|
||||||
|
|
||||||
static void __attribute__((unused)) WL91X_send_packet()
|
|
||||||
{
|
|
||||||
uint8_t val;
|
|
||||||
|
|
||||||
//RF freq
|
|
||||||
XN297_Hopping(hopping_frequency_no++);
|
|
||||||
hopping_frequency_no %= WL91X_RF_NUM_CHANNELS;
|
|
||||||
|
|
||||||
//Sticks
|
|
||||||
val = convert_channel_16b_limit(CH2,0x21,0xE0); //THR forward 00..5F, backward 80..DF
|
|
||||||
if(val < 128) val = 127 - val;
|
|
||||||
packet[0] = val - 0x80;
|
|
||||||
val = convert_channel_s8b(CH1); //ST right 00..7F, left 80..FF
|
|
||||||
packet[1] = val - 0x80;
|
|
||||||
//Trims
|
|
||||||
val = convert_channel_s8b(CH3); //ST_Trim centered=80, increment/decrement=4, right 04..7C, left 84..FC
|
|
||||||
packet[2] = val - 0x80;
|
|
||||||
packet[3] = convert_channel_16b_limit(CH4,0x00,0x70); //TH_Trim increment/decrement=3, 00..39..6F
|
|
||||||
//TX_ID
|
|
||||||
memcpy(&packet[4], rx_tx_addr, 4);
|
|
||||||
//Checksum
|
|
||||||
val = 0;
|
|
||||||
for(uint8_t i=0; i<WL91X_PAYLOAD_SIZE-1; i++)
|
|
||||||
val += packet[i];
|
|
||||||
packet[8] = val;
|
|
||||||
|
|
||||||
//Send
|
|
||||||
XN297_SetPower();
|
|
||||||
XN297_SetFreqOffset();
|
|
||||||
XN297_SetTxRxMode(TX_EN);
|
|
||||||
XN297_WritePayload(packet, WL91X_PAYLOAD_SIZE);
|
|
||||||
#ifdef DEBUG_SERIAL
|
|
||||||
for(uint8_t i=0; i < WL91X_PAYLOAD_SIZE; i++)
|
|
||||||
debug("%02X ", packet[i]);
|
|
||||||
debugln();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((unused)) WL91X_RF_init()
|
|
||||||
{
|
|
||||||
XN297_Configure(XN297_CRCEN, XN297_UNSCRAMBLED, XN297_250K);
|
|
||||||
XN297_HoppingCalib(WL91X_RF_NUM_CHANNELS);
|
|
||||||
XN297_SetTXAddr((uint8_t*)"\x46\x14\x7B\x08", 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((unused)) WL91X_initialize_txid()
|
|
||||||
{
|
|
||||||
#ifdef FORCE_WL91X_ORIGINAL_ID
|
|
||||||
memcpy(rx_tx_addr, (uint8_t*)"\x00\x1E\x33\x02",4);
|
|
||||||
#endif
|
|
||||||
memcpy(hopping_frequency, (uint8_t*)"\x1A\x3B\x3B",3); //26,59,59
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t WL91X_callback()
|
|
||||||
{
|
|
||||||
#ifdef MULTI_SYNC
|
|
||||||
telemetry_set_input_sync(WL91X_PACKET_PERIOD);
|
|
||||||
#endif
|
|
||||||
WL91X_send_packet();
|
|
||||||
return WL91X_PACKET_PERIOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WL91X_init()
|
|
||||||
{
|
|
||||||
BIND_DONE; //No bind for this protocol
|
|
||||||
WL91X_initialize_txid();
|
|
||||||
WL91X_RF_init();
|
|
||||||
hopping_frequency_no = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,158 +0,0 @@
|
|||||||
/*
|
|
||||||
This project is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Multiprotocol 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.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
// Compatible with WPL "Basic" TX models D12, D12KM, D22, D32, D42, D14
|
|
||||||
|
|
||||||
#if defined(WPL_NRF24L01_INO)
|
|
||||||
|
|
||||||
#include "iface_xn297.h"
|
|
||||||
|
|
||||||
#define FORCE_WPL_ORIGINAL_ID
|
|
||||||
|
|
||||||
#define WPL_PACKET_PERIOD 9875
|
|
||||||
#define WPL_RF_NUM_CHANNELS 4
|
|
||||||
#define WPL_PAYLOAD_SIZE 16
|
|
||||||
#define WPL_BIND_COUNT 303 //3sec
|
|
||||||
|
|
||||||
static void __attribute__((unused)) WPL_send_packet()
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
debug("no:%d, rf:%d, ",hopping_frequency_no + (IS_BIND_IN_PROGRESS?0:4),hopping_frequency[hopping_frequency_no + (IS_BIND_IN_PROGRESS?0:4)]);
|
|
||||||
#endif
|
|
||||||
XN297_Hopping(hopping_frequency_no + (IS_BIND_IN_PROGRESS?0:4) );
|
|
||||||
hopping_frequency_no++;
|
|
||||||
hopping_frequency_no &= WPL_RF_NUM_CHANNELS-1; // 4 RF channels
|
|
||||||
|
|
||||||
memset(&packet[8],0,7);
|
|
||||||
packet[0] = 0x94; //??
|
|
||||||
packet[1] = 0x16; //??
|
|
||||||
packet[2] = 0xCC; //??
|
|
||||||
|
|
||||||
if(IS_BIND_IN_PROGRESS)
|
|
||||||
{
|
|
||||||
memcpy(&packet[3],rx_tx_addr,5);
|
|
||||||
packet[9] = 0x08; // ?? Not bound + Headlights on
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
packet[3 ] = convert_channel_s8b(CH1); // Throttle
|
|
||||||
packet[4 ] = convert_channel_s8b(CH2); // Steering
|
|
||||||
packet[5 ] = convert_channel_16b_limit(CH3,0x22,0x5E); // Steering trim
|
|
||||||
packet[6 ] = rx_tx_addr[3]; // 0x32??
|
|
||||||
packet[7 ] = convert_channel_s8b(CH4); // Aux
|
|
||||||
packet[9 ] = 0x80 // ?? Bound
|
|
||||||
| GET_FLAG(CH5_SW, 0x08) // Headlights 100%=on
|
|
||||||
| GET_FLAG(CH6_SW, 0x04) // Throttle rate 100%=high
|
|
||||||
| GET_FLAG(CH7_SW, 0x02); // Steering rate 100%=high
|
|
||||||
}
|
|
||||||
uint8_t sum = 0x66;
|
|
||||||
for(uint8_t i=0;i<WPL_PAYLOAD_SIZE-1;i++)
|
|
||||||
sum += packet[i];
|
|
||||||
packet[WPL_PAYLOAD_SIZE-1] = sum;
|
|
||||||
// Send
|
|
||||||
XN297_SetPower();
|
|
||||||
XN297_SetTxRxMode(TX_EN);
|
|
||||||
XN297_WritePayload(packet, WPL_PAYLOAD_SIZE);
|
|
||||||
#if 0
|
|
||||||
for(uint8_t i=0; i<WPL_PAYLOAD_SIZE; i++)
|
|
||||||
debug(" %02X",packet[i]);
|
|
||||||
debugln("");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((unused)) WPL_RF_init()
|
|
||||||
{
|
|
||||||
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
|
|
||||||
XN297_SetTXAddr((uint8_t*)"\x69\xA5\x37\x4D\x8B", 5);
|
|
||||||
XN297_HoppingCalib(WPL_RF_NUM_CHANNELS*2); // Calibrate bind and normal channels
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((unused)) WPL_initialize_txid()
|
|
||||||
{
|
|
||||||
//Bind frequencies
|
|
||||||
memcpy(hopping_frequency ,"\x17\x25\x46\x36", WPL_RF_NUM_CHANNELS); //23=17, 37=25, 70=46, 54=36
|
|
||||||
#ifdef FORCE_WPL_ORIGINAL_ID
|
|
||||||
//Original ID
|
|
||||||
memcpy(rx_tx_addr,"\x96\x2A\xA9\x32\xB4",5);
|
|
||||||
//Normal frequencies
|
|
||||||
memcpy(hopping_frequency+4,"\x0C\x2A\x3D\x1D", WPL_RF_NUM_CHANNELS); //12=0C, 42=2A, 61=3D, 29=1D
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t WPL_callback()
|
|
||||||
{
|
|
||||||
#ifdef MULTI_SYNC
|
|
||||||
telemetry_set_input_sync(WPL_PACKET_PERIOD);
|
|
||||||
#endif
|
|
||||||
if(bind_counter)
|
|
||||||
if(--bind_counter==0)
|
|
||||||
{
|
|
||||||
BIND_DONE;
|
|
||||||
XN297_SetTXAddr(rx_tx_addr, 5);
|
|
||||||
}
|
|
||||||
WPL_send_packet();
|
|
||||||
return WPL_PACKET_PERIOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WPL_init()
|
|
||||||
{
|
|
||||||
BIND_IN_PROGRESS; // autobind protocol
|
|
||||||
WPL_initialize_txid();
|
|
||||||
WPL_RF_init();
|
|
||||||
hopping_frequency_no = 0;
|
|
||||||
bind_counter=WPL_BIND_COUNT;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
/* https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/issues/1120
|
|
||||||
Bind packet
|
|
||||||
-----------
|
|
||||||
XN297 1Mb Scrambled
|
|
||||||
Bind address: 69 A5 37 4D 8B
|
|
||||||
RF channels: 23, 37, 70, 54
|
|
||||||
Timing: 9875µs
|
|
||||||
Payload 16 bytes: 94 16 CC 96 2A A9 32 B4 00 08 00 00 00 00 00 33
|
|
||||||
|
|
||||||
P[0] = 94 ??
|
|
||||||
P[1] = 16 ??
|
|
||||||
P[2] = CC ??
|
|
||||||
P[3..7] = Normal address
|
|
||||||
P[8] = 00 ??
|
|
||||||
P[9] = 08 ?? not bound?, Throttle and Steering rate low, Headlights on
|
|
||||||
P[10..14] = 00 ??
|
|
||||||
P[15] = sum(P[0..14])+66 why 66? 66=(94+16)^CC...
|
|
||||||
|
|
||||||
Normal packet
|
|
||||||
-----------
|
|
||||||
XN297 1Mb Scrambled
|
|
||||||
Normal address: 96 2A A9 32 B4
|
|
||||||
RF channels: 12=0C, 42=2A, 61=3D, 29=1D -> no idea where they come from...
|
|
||||||
Timing: 9875µs
|
|
||||||
Payload 16 bytes: 94 16 CC 80 80 38 32 80 00 88 00 00 00 00 00 4E
|
|
||||||
P[0] = 94 ??
|
|
||||||
P[1] = 16 ??
|
|
||||||
P[2] = CC ??
|
|
||||||
P[3] = Throttle, not enough data on dumps... Same coding as Steering?
|
|
||||||
P[4] = Steering, not enough data on dumps, looks like one side goes from 7F to 00 and the other 80 to FF which would be s8b
|
|
||||||
P[5] = Steering trim 22..5E, mid gives 40 not 38... Was the trim centered on the other dumps with value 38?
|
|
||||||
P[6] = 32 ?? Left over from the bind packet TX_ADDR[3]?
|
|
||||||
P[7] = 80 ?? Additional channel? It moves at the same time as the trim but my guess is that it is an unconnected channel.
|
|
||||||
P[8] = 00 ??
|
|
||||||
P[9] = 80 ?? bound?, Throttle and Steering rate low, Headlights off
|
|
||||||
|02 -> Steering rate high
|
|
||||||
|04 -> Throttle rate high
|
|
||||||
|08 -> Headlights on
|
|
||||||
P[10..14] = 00 ??
|
|
||||||
P[15] = sum(P[0..14])+66 why 66? 66=(94+16)^CC...
|
|
||||||
*/
|
|
||||||
@@ -21,30 +21,19 @@ Multiprotocol is distributed in the hope that it will be useful,
|
|||||||
//#define FORCE_XK2_ID
|
//#define FORCE_XK2_ID
|
||||||
//#define FORCE_XK2_P10_ID
|
//#define FORCE_XK2_P10_ID
|
||||||
|
|
||||||
#define XK2_RF_BIND_CHANNEL 71
|
#define XK2_RF_BIND_CHANNEL 71
|
||||||
#define XK2_P10_RF_BIND_CHANNEL 69
|
#define XK2_P10_RF_BIND_CHANNEL 69
|
||||||
#define XK2_PAYLOAD_SIZE 9
|
#define XK2_PAYLOAD_SIZE 9
|
||||||
#define XK2_PACKET_PERIOD 4911
|
#define XK2_PACKET_PERIOD 4911
|
||||||
#define XK2_RF_NUM_CHANNELS 4
|
#define XK2_RF_NUM_CHANNELS 4
|
||||||
#define XK2_WRITE_TIME 1000
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
XK2_BIND1,
|
XK2_BIND1,
|
||||||
XK2_BIND2,
|
XK2_BIND2,
|
||||||
XK2_DATA_PREP,
|
XK2_DATA_PREP,
|
||||||
XK2_DATA,
|
XK2_DATA
|
||||||
XK2_RX,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint8_t __attribute__((unused)) XK2_checksum(uint8_t init)
|
|
||||||
{
|
|
||||||
for(uint8_t i=0; i<XK2_PAYLOAD_SIZE-1; i++)
|
|
||||||
init += packet[i];
|
|
||||||
if(sub_protocol == XK2_P10)
|
|
||||||
init += 0x10;
|
|
||||||
return init;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __attribute__((unused)) XK2_send_packet()
|
static void __attribute__((unused)) XK2_send_packet()
|
||||||
{
|
{
|
||||||
static uint8_t trim_ch=0;
|
static uint8_t trim_ch=0;
|
||||||
@@ -58,6 +47,8 @@ static void __attribute__((unused)) XK2_send_packet()
|
|||||||
//memcpy(&packet[4], rx_id , 3);
|
//memcpy(&packet[4], rx_id , 3);
|
||||||
//Unknown
|
//Unknown
|
||||||
packet[7] = 0x00;
|
packet[7] = 0x00;
|
||||||
|
//Checksum seed
|
||||||
|
packet[8] = 0xC0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -80,20 +71,21 @@ static void __attribute__((unused)) XK2_send_packet()
|
|||||||
}
|
}
|
||||||
//Flags
|
//Flags
|
||||||
packet[5] = GET_FLAG(CH5_SW, 0x01) //Rate
|
packet[5] = GET_FLAG(CH5_SW, 0x01) //Rate
|
||||||
|
| GET_FLAG(CH6_SW, 0x08) //Mode
|
||||||
| GET_FLAG(CH7_SW, 0x20) //Hover
|
| GET_FLAG(CH7_SW, 0x20) //Hover
|
||||||
| GET_FLAG(CH8_SW, 0x40); //Light
|
| GET_FLAG(CH8_SW, 0x40); //Light
|
||||||
if(CH6_SW)
|
//Telemetry not received=00, Telemetry received=01 but sometimes switch to 1 even if telemetry is not there...
|
||||||
packet[5] |= 0x10; //Gyro off (senior mode)
|
packet[6] = 0x00;
|
||||||
else if(Channel_data[CH6] > CHANNEL_MIN_COMMAND)
|
|
||||||
packet[5] |= 0x08; //3D
|
|
||||||
packet[5] |= GET_FLAG(CH9_SW, 0x04); //Sky Viper Vector stunt flag
|
|
||||||
//Request telemetry flag
|
|
||||||
packet[6] = 0x01;
|
|
||||||
//RXID checksum
|
//RXID checksum
|
||||||
packet[7] = crc8; //Sum RX_ID[0..2]
|
packet[7] = crc8; //Sum RX_ID[0..2]
|
||||||
|
//Checksum seed
|
||||||
|
packet[8] = num_ch; //Based on TX ID
|
||||||
}
|
}
|
||||||
//Checksum
|
//Checksum
|
||||||
packet[8] = XK2_checksum(IS_BIND_IN_PROGRESS ? 0xC0 : num_ch);
|
for(uint8_t i=0; i<XK2_PAYLOAD_SIZE-1; i++)
|
||||||
|
packet[8] += packet[i];
|
||||||
|
if(sub_protocol == XK2_P10)
|
||||||
|
packet[8] += 0x10;
|
||||||
|
|
||||||
// Send
|
// Send
|
||||||
XN297_SetFreqOffset();
|
XN297_SetFreqOffset();
|
||||||
@@ -164,8 +156,6 @@ static void __attribute__((unused)) XK2_initialize_txid()
|
|||||||
|
|
||||||
uint16_t XK2_callback()
|
uint16_t XK2_callback()
|
||||||
{
|
{
|
||||||
static bool rx = false;
|
|
||||||
|
|
||||||
switch(phase)
|
switch(phase)
|
||||||
{
|
{
|
||||||
case XK2_BIND1:
|
case XK2_BIND1:
|
||||||
@@ -184,8 +174,13 @@ uint16_t XK2_callback()
|
|||||||
debug(" %02X",packet[i]);
|
debug(" %02X",packet[i]);
|
||||||
debugln("");
|
debugln("");
|
||||||
#endif
|
#endif
|
||||||
if(XK2_checksum(0xBF) != packet[8])
|
crc8 = 0xBF;
|
||||||
{//Wrong checksum
|
for(uint8_t i=0; i<XK2_PAYLOAD_SIZE-1; i++)
|
||||||
|
crc8 += packet[i];
|
||||||
|
if(sub_protocol == XK2_P10)
|
||||||
|
crc8 += 0x10;
|
||||||
|
if(crc8 != packet[8])
|
||||||
|
{
|
||||||
phase = XK2_BIND1;
|
phase = XK2_BIND1;
|
||||||
return 1000;
|
return 1000;
|
||||||
}
|
}
|
||||||
@@ -205,72 +200,28 @@ uint16_t XK2_callback()
|
|||||||
}
|
}
|
||||||
return 1000;
|
return 1000;
|
||||||
case XK2_DATA_PREP:
|
case XK2_DATA_PREP:
|
||||||
crc8 = eeprom_read_byte((EE_ADDR)(XK2_EEPROM_OFFSET+RX_num));
|
crc8=eeprom_read_byte((EE_ADDR)(XK2_EEPROM_OFFSET+RX_num));
|
||||||
debugln("R:RX_ID=%02X",crc8);
|
debugln("R:RX_ID=%02X",crc8);
|
||||||
XN297_SetTxRxMode(TXRX_OFF);
|
XN297_SetTxRxMode(TXRX_OFF);
|
||||||
XN297_SetTxRxMode(TX_EN);
|
XN297_SetTxRxMode(TX_EN);
|
||||||
XN297_SetTXAddr(rx_tx_addr, 5);
|
XN297_SetTXAddr(rx_tx_addr, 5);
|
||||||
#ifdef XK2_HUB_TELEMETRY
|
|
||||||
XN297_SetRXAddr(rx_tx_addr, XK2_PAYLOAD_SIZE);
|
|
||||||
#endif
|
|
||||||
BIND_DONE;
|
BIND_DONE;
|
||||||
phase++;
|
phase++;
|
||||||
case XK2_DATA:
|
case XK2_DATA:
|
||||||
#ifdef MULTI_SYNC
|
#ifdef MULTI_SYNC
|
||||||
telemetry_set_input_sync(XK2_PACKET_PERIOD);
|
telemetry_set_input_sync(XK2_PACKET_PERIOD);
|
||||||
#endif
|
#endif
|
||||||
#ifdef XK2_HUB_TELEMETRY
|
|
||||||
rx = XN297_IsRX();
|
|
||||||
XN297_SetTxRxMode(TXRX_OFF);
|
|
||||||
#endif
|
|
||||||
XK2_send_packet();
|
|
||||||
#ifdef XK2_HUB_TELEMETRY
|
|
||||||
if(rx)
|
|
||||||
{
|
|
||||||
XN297_ReadPayload(packet, XK2_PAYLOAD_SIZE);
|
|
||||||
#if 0
|
|
||||||
debug("RX");
|
|
||||||
for(uint8_t i=0; i<XK2_PAYLOAD_SIZE; i++)
|
|
||||||
debug(" %02X",packet[i]);
|
|
||||||
debugln("");
|
|
||||||
#endif
|
|
||||||
if(XK2_checksum(0xCC) == packet[8] && memcmp(packet, rx_tx_addr, 3) == 0)
|
|
||||||
{//Good checksum and TXID
|
|
||||||
//packets: E5 20 F2 00 00 00 00 00 C3 -> E5 20 F2 80 00 00 00 00 43
|
|
||||||
telemetry_link = 1;
|
|
||||||
v_lipo1 = packet[3] ? 137:162; // low voltage 7.1V
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(bind_counter)
|
if(bind_counter)
|
||||||
{
|
{
|
||||||
bind_counter--;
|
bind_counter--;
|
||||||
if(bind_counter == 0)
|
if(bind_counter == 0)
|
||||||
phase = XK2_DATA_PREP;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#ifndef XK2_HUB_TELEMETRY
|
|
||||||
break;
|
|
||||||
#else
|
|
||||||
phase++;
|
|
||||||
return XK2_WRITE_TIME;
|
|
||||||
default: //XK2_RX
|
|
||||||
/*{ // Wait for packet to be sent before switching to receive mode
|
|
||||||
uint16_t start=(uint16_t)micros(), count=0;
|
|
||||||
while ((uint16_t)((uint16_t)micros()-(uint16_t)start) < 500)
|
|
||||||
{
|
{
|
||||||
if(XN297_IsPacketSent())
|
phase = XK2_DATA_PREP;
|
||||||
break;
|
//phase = XK2_BIND1;
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
debugln("%d",count);
|
}
|
||||||
}*/
|
XK2_send_packet();
|
||||||
//Switch to RX
|
break;
|
||||||
XN297_SetTxRxMode(TXRX_OFF);
|
|
||||||
XN297_SetTxRxMode(RX_EN);
|
|
||||||
phase = XK2_DATA;
|
|
||||||
return XK2_PACKET_PERIOD-XK2_WRITE_TIME;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return XK2_PACKET_PERIOD;
|
return XK2_PACKET_PERIOD;
|
||||||
}
|
}
|
||||||
@@ -287,9 +238,6 @@ void XK2_init()
|
|||||||
phase = XK2_DATA_PREP;
|
phase = XK2_DATA_PREP;
|
||||||
bind_counter = 0;
|
bind_counter = 0;
|
||||||
hopping_frequency_no = 0;
|
hopping_frequency_no = 0;
|
||||||
#ifdef XK2_HUB_TELEMETRY
|
|
||||||
RX_RSSI = 100; // Dummy value
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -22,9 +22,7 @@
|
|||||||
#include "iface_xn297.h"
|
#include "iface_xn297.h"
|
||||||
|
|
||||||
// Parameters which can be modified
|
// Parameters which can be modified
|
||||||
#define XN297DUMP_PERIOD_FAST_SCAN 50000 // 50000
|
#define XN297DUMP_PERIOD_SCAN 50000 // 25000
|
||||||
#define XN297DUMP_PERIOD_SLOW_SCAN 100000 // 75000
|
|
||||||
#define XN297DUMP_MAX_PACKET 50 // 20
|
|
||||||
#define XN297DUMP_MAX_RF_CHANNEL 84 // Default 84
|
#define XN297DUMP_MAX_RF_CHANNEL 84 // Default 84
|
||||||
|
|
||||||
// Do not touch from there
|
// Do not touch from there
|
||||||
@@ -40,7 +38,6 @@ boolean ack;
|
|||||||
uint8_t pid;
|
uint8_t pid;
|
||||||
uint8_t bitrate;
|
uint8_t bitrate;
|
||||||
uint8_t old_option;
|
uint8_t old_option;
|
||||||
uint32_t scan_counter;
|
|
||||||
|
|
||||||
static void __attribute__((unused)) XN297Dump_RF_init()
|
static void __attribute__((unused)) XN297Dump_RF_init()
|
||||||
{
|
{
|
||||||
@@ -198,10 +195,10 @@ static uint16_t XN297Dump_callback()
|
|||||||
{
|
{
|
||||||
if(sub_protocol<XN297DUMP_AUTO)
|
if(sub_protocol<XN297DUMP_AUTO)
|
||||||
{
|
{
|
||||||
if(option==0xFF && scan_counter>XN297DUMP_PERIOD_SLOW_SCAN)
|
if(option==0xFF && bind_counter>XN297DUMP_PERIOD_SCAN)
|
||||||
{ // Scan frequencies
|
{ // Scan frequencies
|
||||||
hopping_frequency_no++;
|
hopping_frequency_no++;
|
||||||
scan_counter=0;
|
bind_counter=0;
|
||||||
}
|
}
|
||||||
if(hopping_frequency_no!=rf_ch_num)
|
if(hopping_frequency_no!=rf_ch_num)
|
||||||
{ // Channel has changed
|
{ // Channel has changed
|
||||||
@@ -297,10 +294,10 @@ static uint16_t XN297Dump_callback()
|
|||||||
phase++;
|
phase++;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if(scan_counter>XN297DUMP_PERIOD_FAST_SCAN)
|
if(bind_counter>XN297DUMP_PERIOD_SCAN)
|
||||||
{ // Scan frequencies
|
{ // Scan frequencies
|
||||||
hopping_frequency_no++;
|
hopping_frequency_no++;
|
||||||
scan_counter=0;
|
bind_counter=0;
|
||||||
if(hopping_frequency_no>XN297DUMP_MAX_RF_CHANNEL)
|
if(hopping_frequency_no>XN297DUMP_MAX_RF_CHANNEL)
|
||||||
{
|
{
|
||||||
hopping_frequency_no=0;
|
hopping_frequency_no=0;
|
||||||
@@ -370,7 +367,7 @@ static uint16_t XN297Dump_callback()
|
|||||||
debugln("\r\n--------------------------------");
|
debugln("\r\n--------------------------------");
|
||||||
phase=2;
|
phase=2;
|
||||||
debugln("Identifying all RF channels in use.");
|
debugln("Identifying all RF channels in use.");
|
||||||
scan_counter=0;
|
bind_counter=0;
|
||||||
hopping_frequency_no=0;
|
hopping_frequency_no=0;
|
||||||
rf_ch_num=0;
|
rf_ch_num=0;
|
||||||
packet_count=0;
|
packet_count=0;
|
||||||
@@ -392,11 +389,11 @@ static uint16_t XN297Dump_callback()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if(scan_counter>XN297DUMP_PERIOD_SLOW_SCAN)
|
if(bind_counter>XN297DUMP_PERIOD_SCAN)
|
||||||
{ // Scan frequencies
|
{ // Scan frequencies
|
||||||
hopping_frequency_no++;
|
hopping_frequency_no++;
|
||||||
scan_counter=0;
|
bind_counter=0;
|
||||||
if(packet_count && packet_count<=XN297DUMP_MAX_PACKET)
|
if(packet_count && packet_count<=20)
|
||||||
debug("\r\nTrying RF channel: ");
|
debug("\r\nTrying RF channel: ");
|
||||||
packet_count=0;
|
packet_count=0;
|
||||||
if(hopping_frequency_no>XN297DUMP_MAX_RF_CHANNEL)
|
if(hopping_frequency_no>XN297DUMP_MAX_RF_CHANNEL)
|
||||||
@@ -441,7 +438,7 @@ static uint16_t XN297Dump_callback()
|
|||||||
hopping_frequency_no=0;
|
hopping_frequency_no=0;
|
||||||
phase=3;
|
phase=3;
|
||||||
packet_count=0;
|
packet_count=0;
|
||||||
scan_counter=0;
|
bind_counter=0;
|
||||||
debugln("Time between CH:%d and CH:%d",hopping_frequency[compare_channel],hopping_frequency[hopping_frequency_no]);
|
debugln("Time between CH:%d and CH:%d",hopping_frequency[compare_channel],hopping_frequency[hopping_frequency_no]);
|
||||||
time_rf[hopping_frequency_no]=0xFFFFFFFF;
|
time_rf[hopping_frequency_no]=0xFFFFFFFF;
|
||||||
XN297_RFChannel(hopping_frequency[compare_channel]);
|
XN297_RFChannel(hopping_frequency[compare_channel]);
|
||||||
@@ -498,9 +495,9 @@ static uint16_t XN297Dump_callback()
|
|||||||
debug(" %02X",packet[i]);
|
debug(" %02X",packet[i]);
|
||||||
packet_count++;
|
packet_count++;
|
||||||
nbr_rf[rf_ch_num-1]=packet_count;
|
nbr_rf[rf_ch_num-1]=packet_count;
|
||||||
if(packet_count>XN297DUMP_MAX_PACKET)
|
if(packet_count>20)
|
||||||
{//change channel
|
{//change channel
|
||||||
scan_counter=XN297DUMP_PERIOD_SLOW_SCAN+1;
|
bind_counter=XN297DUMP_PERIOD_SCAN+1;
|
||||||
debug("\r\nTrying RF channel: ");
|
debug("\r\nTrying RF channel: ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -512,10 +509,10 @@ static uint16_t XN297Dump_callback()
|
|||||||
XN297Dump_overflow();
|
XN297Dump_overflow();
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if(scan_counter>XN297DUMP_PERIOD_SLOW_SCAN)
|
if(bind_counter>XN297DUMP_PERIOD_SCAN)
|
||||||
{ // Scan frequencies
|
{ // Scan frequencies
|
||||||
hopping_frequency_no++;
|
hopping_frequency_no++;
|
||||||
scan_counter=0;
|
bind_counter=0;
|
||||||
if(hopping_frequency_no>=rf_ch_num)
|
if(hopping_frequency_no>=rf_ch_num)
|
||||||
{
|
{
|
||||||
uint8_t next=0;
|
uint8_t next=0;
|
||||||
@@ -599,7 +596,7 @@ static uint16_t XN297Dump_callback()
|
|||||||
packet_count++;
|
packet_count++;
|
||||||
if(packet_count>24)
|
if(packet_count>24)
|
||||||
{
|
{
|
||||||
scan_counter=XN297DUMP_PERIOD_SLOW_SCAN+1;
|
bind_counter=XN297DUMP_PERIOD_SCAN+1;
|
||||||
packet_count=0;
|
packet_count=0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -944,7 +941,7 @@ static uint16_t XN297Dump_callback()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scan_counter++;
|
bind_counter++;
|
||||||
if(IS_RX_FLAG_on) // Let the radio update the protocol
|
if(IS_RX_FLAG_on) // Let the radio update the protocol
|
||||||
{
|
{
|
||||||
if(Update_All()) return 10000; // New protocol selected
|
if(Update_All()) return 10000; // New protocol selected
|
||||||
@@ -970,7 +967,7 @@ void XN297Dump_init(void)
|
|||||||
if(address_length<3||address_length>5)
|
if(address_length<3||address_length>5)
|
||||||
address_length=5; //default
|
address_length=5; //default
|
||||||
XN297Dump_RF_init();
|
XN297Dump_RF_init();
|
||||||
scan_counter=0;
|
bind_counter=0;
|
||||||
rf_ch_num=0xFF;
|
rf_ch_num=0xFF;
|
||||||
prev_option=option^0x55;
|
prev_option=option^0x55;
|
||||||
phase=0; // init
|
phase=0; // init
|
||||||
|
|||||||
@@ -211,7 +211,7 @@
|
|||||||
#define FRSKYL_CC2500_INO
|
#define FRSKYL_CC2500_INO
|
||||||
#define FRSKYD_CC2500_INO
|
#define FRSKYD_CC2500_INO
|
||||||
#define FRSKYV_CC2500_INO
|
#define FRSKYV_CC2500_INO
|
||||||
#define FRSKYX_CC2500_INO //Include FRSKYX2 protocol
|
#define FRSKYX_CC2500_INO
|
||||||
#define FRSKY_RX_CC2500_INO
|
#define FRSKY_RX_CC2500_INO
|
||||||
#define HITEC_CC2500_INO
|
#define HITEC_CC2500_INO
|
||||||
#define HOTT_CC2500_INO
|
#define HOTT_CC2500_INO
|
||||||
@@ -257,11 +257,9 @@
|
|||||||
#define REALACC_NRF24L01_INO
|
#define REALACC_NRF24L01_INO
|
||||||
#define SGF22_NRF24L01_INO
|
#define SGF22_NRF24L01_INO
|
||||||
#define SHENQI_NRF24L01_INO
|
#define SHENQI_NRF24L01_INO
|
||||||
#define SHENQI2_NRF24L01_INO
|
|
||||||
#define SYMAX_NRF24L01_INO
|
#define SYMAX_NRF24L01_INO
|
||||||
#define V2X2_NRF24L01_INO
|
#define V2X2_NRF24L01_INO
|
||||||
#define V761_NRF24L01_INO
|
#define V761_NRF24L01_INO
|
||||||
#define WPL_NRF24L01_INO
|
|
||||||
#define XERALL_NRF24L01_INO
|
#define XERALL_NRF24L01_INO
|
||||||
#define YD717_NRF24L01_INO
|
#define YD717_NRF24L01_INO
|
||||||
#define YUXIANG_NRF24L01_INO
|
#define YUXIANG_NRF24L01_INO
|
||||||
@@ -278,7 +276,6 @@
|
|||||||
#define SLT_CCNRF_INO
|
#define SLT_CCNRF_INO
|
||||||
#define UDIRC_CCNRF_INO
|
#define UDIRC_CCNRF_INO
|
||||||
#define V911S_CCNRF_INO
|
#define V911S_CCNRF_INO
|
||||||
#define WL91X_CCNRF_INO
|
|
||||||
#define XK_CCNRF_INO
|
#define XK_CCNRF_INO
|
||||||
#define XK2_CCNRF_INO
|
#define XK2_CCNRF_INO
|
||||||
|
|
||||||
@@ -303,6 +300,11 @@
|
|||||||
//Enable DSM Forward Programming
|
//Enable DSM Forward Programming
|
||||||
#define DSM_FWD_PGM
|
#define DSM_FWD_PGM
|
||||||
|
|
||||||
|
//AFHDS2A specific settings
|
||||||
|
//-------------------------
|
||||||
|
//When enabled (remove the "//"), the below setting makes LQI (Link Quality Indicator) available on one of the RX ouput channel (5-14).
|
||||||
|
//#define AFHDS2A_LQI_CH 14
|
||||||
|
|
||||||
/**************************/
|
/**************************/
|
||||||
/*** FAILSAFE SETTINGS ***/
|
/*** FAILSAFE SETTINGS ***/
|
||||||
/**************************/
|
/**************************/
|
||||||
@@ -349,18 +351,14 @@
|
|||||||
#define NCC1701_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
#define NCC1701_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||||
#define OMP_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
#define OMP_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||||
#define V761_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
#define V761_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||||
#define KAMTOM_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
#define YUXIANG_HUB_TELEMETRY
|
||||||
#define FX_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
|
||||||
#define XK2_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
|
||||||
#define SGF22_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
|
||||||
#define YUXIANG_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
|
||||||
#define PROPEL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
#define PROPEL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||||
#define CABELL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
#define CABELL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||||
#define RLINK_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
#define RLINK_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||||
#define WFLY2_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
#define WFLY2_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||||
#define LOLI_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
#define LOLI_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||||
#define MT99XX_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
#define MT99XX_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||||
//#define MLINK_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
//#define MLINK_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||||
#define MLINK_FW_TELEMETRY // Forward received telemetry packet directly to TX to be decoded by erskyTX and OpenTX
|
#define MLINK_FW_TELEMETRY // Forward received telemetry packet directly to TX to be decoded by erskyTX and OpenTX
|
||||||
//#define HITEC_HUB_TELEMETRY // Use FrSkyD Hub format to send basic telemetry to the radios which can decode it like er9x, erskyTX and OpenTX
|
//#define HITEC_HUB_TELEMETRY // Use FrSkyD Hub format to send basic telemetry to the radios which can decode it like er9x, erskyTX and OpenTX
|
||||||
#define HITEC_FW_TELEMETRY // Forward received telemetry packets to be decoded by erskyTX and OpenTX
|
#define HITEC_FW_TELEMETRY // Forward received telemetry packets to be decoded by erskyTX and OpenTX
|
||||||
@@ -566,9 +564,10 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
|||||||
PPM_IBUS
|
PPM_IBUS
|
||||||
PWM_SBUS
|
PWM_SBUS
|
||||||
PPM_SBUS
|
PPM_SBUS
|
||||||
AFHDS2A_GYRO_OFF
|
PWM_IB16
|
||||||
AFHDS2A_GYRO_ON
|
PPM_IB16
|
||||||
AFHDS2A_GYRO_ON_REV
|
PWM_SB16
|
||||||
|
PPM_SB16
|
||||||
PROTO_AFHDS2A_RX
|
PROTO_AFHDS2A_RX
|
||||||
NONE
|
NONE
|
||||||
PROTO_ASSAN
|
PROTO_ASSAN
|
||||||
@@ -654,8 +653,7 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
|||||||
V912
|
V912
|
||||||
CX20
|
CX20
|
||||||
PROTO_FQ777
|
PROTO_FQ777
|
||||||
FQ777
|
NONE
|
||||||
XBM37
|
|
||||||
PROTO_FRSKY_RX
|
PROTO_FRSKY_RX
|
||||||
FRSKY_RX
|
FRSKY_RX
|
||||||
FRSKY_CLONE
|
FRSKY_CLONE
|
||||||
@@ -698,10 +696,7 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
|||||||
FX816
|
FX816
|
||||||
FX620
|
FX620
|
||||||
FX9630
|
FX9630
|
||||||
FX_Q560
|
Q560
|
||||||
FX_QF012
|
|
||||||
FX_BM26
|
|
||||||
FX_A570
|
|
||||||
PROTO_FY326
|
PROTO_FY326
|
||||||
FY326
|
FY326
|
||||||
FY319
|
FY319
|
||||||
@@ -782,9 +777,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
|||||||
PROTO_MLINK
|
PROTO_MLINK
|
||||||
NONE
|
NONE
|
||||||
PROTO_MOULDKG
|
PROTO_MOULDKG
|
||||||
MOULDKG_ANALOG4
|
MOULDKG_ANALOG
|
||||||
MOULDKG_DIGIT4
|
MOULDKG_DIGIT
|
||||||
MOULDKG_ANALOG6
|
|
||||||
PROTO_MT99XX
|
PROTO_MT99XX
|
||||||
MT99
|
MT99
|
||||||
H7
|
H7
|
||||||
@@ -830,7 +824,6 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
|||||||
RLINK_AIR
|
RLINK_AIR
|
||||||
RLINK_DUMBORC
|
RLINK_DUMBORC
|
||||||
RLINK_RC4G
|
RLINK_RC4G
|
||||||
RLINK_DUMBORC_P
|
|
||||||
PROTO_SCANNER
|
PROTO_SCANNER
|
||||||
NONE
|
NONE
|
||||||
PROTO_SCORPIO
|
PROTO_SCORPIO
|
||||||
@@ -839,11 +832,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
|||||||
SGF22
|
SGF22
|
||||||
F22S
|
F22S
|
||||||
J20
|
J20
|
||||||
CX10
|
|
||||||
PROTO_SHENQI
|
PROTO_SHENQI
|
||||||
NONE
|
NONE
|
||||||
PROTO_SHENQI2
|
|
||||||
NONE
|
|
||||||
PROTO_SKYARTEC
|
PROTO_SKYARTEC
|
||||||
NONE
|
NONE
|
||||||
PROTO_SLT
|
PROTO_SLT
|
||||||
@@ -882,8 +872,6 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
|||||||
W6_6_1
|
W6_6_1
|
||||||
W6_HEL
|
W6_HEL
|
||||||
W6_HEL_I
|
W6_HEL_I
|
||||||
PROTO_WPL
|
|
||||||
NONE
|
|
||||||
PROTO_XERALL
|
PROTO_XERALL
|
||||||
NONE
|
NONE
|
||||||
PROTO_XK
|
PROTO_XK
|
||||||
|
|||||||
@@ -61,108 +61,104 @@ You've upgraded the module but the radio does not display the name of the protoc
|
|||||||
|
|
||||||
# Available Protocol Table of Contents (Listed Alphabetically)
|
# Available Protocol Table of Contents (Listed Alphabetically)
|
||||||
|
|
||||||
Protocol Name|Build|Protocol Number|Sub_Proto 0|Sub_Proto 1|Sub_Proto 2|Sub_Proto 3|Sub_Proto 4|Sub_Proto 5|Sub_Proto 6|Sub_Proto 7|RF Module|Emulation
|
Protocol Name|Protocol Number|Sub_Proto 0|Sub_Proto 1|Sub_Proto 2|Sub_Proto 3|Sub_Proto 4|Sub_Proto 5|Sub_Proto 6|Sub_Proto 7|RF Module|Emulation
|
||||||
---|---|---|---|---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---|---|---|---|---|---|---
|
||||||
[Assan](Protocols_Details.md#ASSAN---24)|AIR/SFC|24|||||||||NRF24L01|
|
[Assan](Protocols_Details.md#ASSAN---24)|24|||||||||NRF24L01|
|
||||||
[Bayang](Protocols_Details.md#BAYANG---14)|AIR/SFC|14|Bayang|H8S3D|X16_AH|IRDRONE|DHD_D4|QX100|||NRF24L01|XN297
|
[Bayang](Protocols_Details.md#BAYANG---14)|14|Bayang|H8S3D|X16_AH|IRDRONE|DHD_D4|QX100|||NRF24L01|XN297
|
||||||
[Bayang RX](Protocols_Details.md#BAYANG-RX---59)|AIR/SFC|59|Multi|CPPM|||||||NRF24L01|XN297
|
[Bayang RX](Protocols_Details.md#BAYANG-RX---59)|59|Multi|CPPM|||||||NRF24L01|XN297
|
||||||
[BlueFly](Protocols_Details.md#BLUEFLY---95)||95|||||||||NRF24L01|
|
[BlueFly](Protocols_Details.md#BLUEFLY---95)|95|||||||||NRF24L01|
|
||||||
[Bugs](Protocols_Details.md#BUGS---41)|AIR|41|||||||||A7105|
|
[Bugs](Protocols_Details.md#BUGS---41)|41|||||||||A7105|
|
||||||
[BugsMini](Protocols_Details.md#BUGSMINI---42)|AIR|42|BUGSMINI|BUGS3H|||||||NRF24L01|XN297
|
[BugsMini](Protocols_Details.md#BUGSMINI---42)|42|BUGSMINI|BUGS3H|||||||NRF24L01|XN297
|
||||||
[Cabell](Protocols_Details.md#Cabell---34)||34|Cabell_V3|C_TELEM|-|-|-|-|F_SAFE|UNBIND|NRF24L01|
|
[Cabell](Protocols_Details.md#Cabell---34)|34|Cabell_V3|C_TELEM|-|-|-|-|F_SAFE|UNBIND|NRF24L01|
|
||||||
CFlie|AIR|38|CFlie||||||||NRF24L01|
|
CFlie|38|CFlie||||||||NRF24L01|
|
||||||
[CG023](Protocols_Details.md#CG023---13)|AIR|13|CG023|YD829|||||||NRF24L01|XN297
|
[CG023](Protocols_Details.md#CG023---13)|13|CG023|YD829|||||||NRF24L01|XN297
|
||||||
[Corona](Protocols_Details.md#CORONA---37)|AIR/SFC|37|COR_V1|COR_V2|FD_V3||||||CC2500|
|
[Corona](Protocols_Details.md#CORONA---37)|37|COR_V1|COR_V2|FD_V3||||||CC2500|
|
||||||
[CX10](Protocols_Details.md#CX10---12)|AIR|12|GREEN|BLUE|DM007|-|J3015_1|J3015_2|MK33041||NRF24L01|XN297
|
[CX10](Protocols_Details.md#CX10---12)|12|GREEN|BLUE|DM007|-|J3015_1|J3015_2|MK33041||NRF24L01|XN297
|
||||||
[Devo](Protocols_Details.md#DEVO---7)|AIR/SFC|7|Devo|8CH|10CH|12CH|6CH|7CH|||CYRF6936|
|
[Devo](Protocols_Details.md#DEVO---7)|7|Devo|8CH|10CH|12CH|6CH|7CH|||CYRF6936|
|
||||||
[DM002](Protocols_Details.md#DM002---33)|AIR|33|||||||||NRF24L01|XN297
|
[DM002](Protocols_Details.md#DM002---33)|33|||||||||NRF24L01|XN297
|
||||||
[DSM](Protocols_Details.md#DSM---6)|AIR/SFC|6|DSM2_1F|DSM2_2F|DSMX_1F|DSMX_2F|AUTO|DSMR_1F|DSM2SFC||CYRF6936|
|
[DSM](Protocols_Details.md#DSM---6)|6|DSM2_1F|DSM2_2F|DSMX_1F|DSMX_2F|AUTO|DSMR_1F|DSM2SFC||CYRF6936|
|
||||||
[DSM_RX](Protocols_Details.md#DSM_RX---70)|AIR/SFC|70|Multi|CPPM|||||||CYRF6936|
|
[DSM_RX](Protocols_Details.md#DSM_RX---70)|70|Multi|CPPM|||||||CYRF6936|
|
||||||
[E010R5](Protocols_Details.md#E010R5---81)|AIR|81|||||||||CYRF6936|RF2500
|
[E010R5](Protocols_Details.md#E010R5---81)|81|||||||||CYRF6936|RF2500
|
||||||
[E016H](Protocols_Details.md#E016H---85)||85|||||||||NRF24L01|XN297
|
[E016H](Protocols_Details.md#E016H---85)|85|||||||||NRF24L01|XN297
|
||||||
[E016HV2](Protocols_Details.md#E016HV2---80)||80|||||||||CC2500/NRF24L01|unknown
|
[E016HV2](Protocols_Details.md#E016HV2---80)|80|||||||||CC2500/NRF24L01|unknown
|
||||||
[E01X](Protocols_Details.md#E01X---45)||45|E012|E015|||||||CYRF6936|HS6200
|
[E01X](Protocols_Details.md#E01X---45)|45|E012|E015|||||||CYRF6936|HS6200
|
||||||
[E129](Protocols_Details.md#E129---83)||83|E129|C186|||||||CYRF6936|RF2500
|
[E129](Protocols_Details.md#E129---83)|83|E129|C186|||||||CYRF6936|RF2500
|
||||||
[EazyRC](Protocols_Details.md#EazyRC---61)||61|||||||||NRF24L01|XN297L
|
[EazyRC](Protocols_Details.md#EazyRC---61)|61|||||||||NRF24L01|XN297L
|
||||||
[ESky](Protocols_Details.md#ESKY---16)||16|ESky|ET4|||||||NRF24L01|
|
[ESky](Protocols_Details.md#ESKY---16)|16|ESky|ET4|||||||NRF24L01|
|
||||||
[ESky150](Protocols_Details.md#ESKY150---35)||35|||||||||NRF24L01|
|
[ESky150](Protocols_Details.md#ESKY150---35)|35|||||||||NRF24L01|
|
||||||
[ESky150V2](Protocols_Details.md#ESKY150V2---69)||69|||||||||CC2500|NRF51822
|
[ESky150V2](Protocols_Details.md#ESKY150V2---69)|69|||||||||CC2500|NRF51822
|
||||||
[Flysky](Protocols_Details.md#FLYSKY---1)||1|Flysky|V9x9|V6x6|V912|CX20||||A7105|
|
[Flysky](Protocols_Details.md#FLYSKY---1)|1|Flysky|V9x9|V6x6|V912|CX20||||A7105|
|
||||||
[Flysky AFHDS2A](Protocols_Details.md#FLYSKY-AFHDS2A---28)||28|PWM_IBUS|PPM_IBUS|PWM_SBUS|PPM_SBUS|Gyro_Off|Gyro_On|Gyro_On_Rev||A7105|
|
[Flysky AFHDS2A](Protocols_Details.md#FLYSKY-AFHDS2A---28)|28|PWM_IBUS|PPM_IBUS|PWM_SBUS|PPM_SBUS|PWM_IBUS16|PPM_IBUS16|PWM_SBUS16|PPM_SBUS16|A7105|
|
||||||
[Flysky AFHDS2A RX](Protocols_Details.md#FLYSKY-AFHDS2A-RX---56)||56|Multi|CPPM|||||||A7105|
|
[Flysky AFHDS2A RX](Protocols_Details.md#FLYSKY-AFHDS2A-RX---56)|56|Multi|CPPM|||||||A7105|
|
||||||
[FQ777](Protocols_Details.md#FQ777---23)||23|124|XBM37|||||||NRF24L01|SSV7241
|
[FQ777](Protocols_Details.md#FQ777---23)|23|||||||||NRF24L01|SSV7241
|
||||||
[FrskyD](Protocols_Details.md#FRSKYD---3)||3|D8|Cloned|||||||CC2500|
|
[FrskyD](Protocols_Details.md#FRSKYD---3)|3|D8|Cloned|||||||CC2500|
|
||||||
[FrskyL](Protocols_Details.md#FRSKYL---67)||67|LR12|LR12 6CH|||||||CC2500|
|
[FrskyL](Protocols_Details.md#FRSKYL---67)|67|LR12|LR12 6CH|||||||CC2500|
|
||||||
[FrskyR9](Protocols_Details.md#FRSKYR9---65)||65|FrskyR9|R9_915|R9_868||||||SX1276|
|
[FrskyR9](Protocols_Details.md#FRSKYR9---65)|65|FrskyR9|R9_915|R9_868||||||SX1276|
|
||||||
[FrskyV](Protocols_Details.md#FRSKYV---25)||25|||||||||CC2500|
|
[FrskyV](Protocols_Details.md#FRSKYV---25)|25|||||||||CC2500|
|
||||||
[FrskyX](Protocols_Details.md#FRSKYX---15)||15|CH_16|CH_8|EU_16|EU_8|Cloned|Cloned_8|||CC2500|
|
[FrskyX](Protocols_Details.md#FRSKYX---15)|15|CH_16|CH_8|EU_16|EU_8|Cloned|Cloned_8|||CC2500|
|
||||||
[FrskyX2](Protocols_Details.md#FRSKYX2---64)||64|CH_16|CH_8|EU_16|EU_8|Cloned|Cloned_8|||CC2500|
|
[FrskyX2](Protocols_Details.md#FRSKYX2---64)|64|CH_16|CH_8|EU_16|EU_8|Cloned|Cloned_8|||CC2500|
|
||||||
[Frsky_RX](Protocols_Details.md#FRSKY_RX---55)||55|Multi|CloneTX|EraseTX|CPPM|||||CC2500|
|
[Frsky_RX](Protocols_Details.md#FRSKY_RX---55)|55|Multi|CloneTX|EraseTX|CPPM|||||CC2500|
|
||||||
[Futaba/SFHSS](Protocols_Details.md#Futaba---21)||21|SFHSS||||||||CC2500|
|
[Futaba/SFHSS](Protocols_Details.md#Futaba---21)|21|SFHSS||||||||CC2500|
|
||||||
[FX](Protocols_Details.md#FX---58)||58|FX816|FX620|9630|Q560|QF012|BM26|A570||NRF24L01|
|
[FX](Protocols_Details.md#FX---58)|28|816|620|9630|Q560|||||NRF24L01|
|
||||||
[FY326](Protocols_Details.md#FY326---20)||20|FY326|FY319|||||||NRF24L01|
|
[FY326](Protocols_Details.md#FY326---20)|20|FY326|FY319|||||||NRF24L01|
|
||||||
[GD00X](Protocols_Details.md#GD00X---47)||47|GD_V1*|GD_V2*|||||||NRF24L01|XN297L
|
[GD00X](Protocols_Details.md#GD00X---47)|47|GD_V1*|GD_V2*|||||||NRF24L01|XN297L
|
||||||
[GW008](Protocols_Details.md#GW008---32)||32|||||||||NRF24L01|XN297
|
[GW008](Protocols_Details.md#GW008---32)|32|||||||||NRF24L01|XN297
|
||||||
[H36](Protocols_Details.md#H36---103)||H36|||||||||NRF24L01|XN297
|
[H36](Protocols_Details.md#H36---103)|H36|||||||||NRF24L01|XN297
|
||||||
[H8_3D](Protocols_Details.md#H8_3D---36)||36|H8_3D|H20H|H20Mini|H30Mini|||||NRF24L01|XN297
|
[H8_3D](Protocols_Details.md#H8_3D---36)|36|H8_3D|H20H|H20Mini|H30Mini|||||NRF24L01|XN297
|
||||||
[Height](Protocols_Details.md#HEIGHT---53)||53|5ch|8ch|||||||A7105|
|
[Height](Protocols_Details.md#HEIGHT---53)|53|5ch|8ch|||||||A7105|
|
||||||
[Hisky](Protocols_Details.md#HISKY---4)||4|Hisky|HK310|||||||NRF24L01|
|
[Hisky](Protocols_Details.md#HISKY---4)|4|Hisky|HK310|||||||NRF24L01|
|
||||||
[Hitec](Protocols_Details.md#HITEC---39)||39|OPT_FW|OPT_HUB|MINIMA||||||CC2500|
|
[Hitec](Protocols_Details.md#HITEC---39)|39|OPT_FW|OPT_HUB|MINIMA||||||CC2500|
|
||||||
[Hontai](Protocols_Details.md#HONTAI---26)||26|HONTAI|JJRCX1|X5C1|FQ777_951|XKK170||||NRF24L01|XN297
|
[Hontai](Protocols_Details.md#HONTAI---26)|26|HONTAI|JJRCX1|X5C1|FQ777_951|XKK170||||NRF24L01|XN297
|
||||||
[HoTT](Protocols_Details.md#HoTT---57)||57|Sync|No_Sync|||||||CC2500|
|
[HoTT](Protocols_Details.md#HoTT---57)|57|Sync|No_Sync|||||||CC2500|
|
||||||
[Hubsan](Protocols_Details.md#HUBSAN---2)||2|H107|H301|H501||||||A7105|
|
[Hubsan](Protocols_Details.md#HUBSAN---2)|2|H107|H301|H501||||||A7105|
|
||||||
[J6Pro](Protocols_Details.md#J6Pro---22)||22|||||||||CYRF6936|
|
[J6Pro](Protocols_Details.md#J6Pro---22)|22|||||||||CYRF6936|
|
||||||
[JIABAILE](Protocols_Details.md#JIABAILE---102)||102|Std|Gyro|||||||NRF24L01|XN297
|
[JIABAILE](Protocols_Details.md#JIABAILE---102)|102|Std|Gyro|||||||NRF24L01|XN297
|
||||||
[JJRC345](Protocols_Details.md#JJRC345---71)||71|JJRC345|SkyTmblr|||||||NRF24L01|XN297
|
[JJRC345](Protocols_Details.md#JJRC345---71)|71|JJRC345|SkyTmblr|||||||NRF24L01|XN297
|
||||||
[JOYSWAY](Protocols_Details.md#JOYSWAY---84)||84|||||||||NRF24L01|XN297
|
[JOYSWAY](Protocols_Details.md#JOYSWAY---84)|84|||||||||NRF24L01|XN297
|
||||||
[KAMTOM](Protocols_Details.md#KAMTOM---104)||104|||||||||NRF24L01|XN297
|
[KF606](Protocols_Details.md#KF606---49)|49|KF606|MIG320|ZCZ50||||||NRF24L01|XN297
|
||||||
[KF606](Protocols_Details.md#KF606---49)||49|KF606|MIG320|ZCZ50||||||NRF24L01|XN297
|
[KN](Protocols_Details.md#KN---9)|9|WLTOYS|FEILUN|||||||NRF24L01|
|
||||||
[KN](Protocols_Details.md#KN---9)||9|WLTOYS|FEILUN|||||||NRF24L01|
|
[Kyosho](Protocols_Details.md#Kyosho---73)|73|FHSS|Hype|||||||A7105|
|
||||||
[Kyosho](Protocols_Details.md#Kyosho---73)||73|FHSS|Hype|||||||A7105|
|
[Kyosho2](Protocols_Details.md#Kyosho2---93)|93|KT-17||||||||NRF24L01|
|
||||||
[Kyosho2](Protocols_Details.md#Kyosho2---93)||93|KT-17||||||||NRF24L01|
|
[Kyosho3](Protocols_Details.md#Kyosho3---98)|98|ASF||||||||CYRF6936|
|
||||||
[Kyosho3](Protocols_Details.md#Kyosho3---98)||98|ASF||||||||CYRF6936|
|
[LOLI](Protocols_Details.md#LOLI---82)|82|||||||||NRF24L01|
|
||||||
[LOLI](Protocols_Details.md#LOLI---82)||82|||||||||NRF24L01|
|
[Losi](Protocols_Details.md#Losi---89)|89|||||||||CYRF6936|
|
||||||
[Losi](Protocols_Details.md#Losi---89)||89|||||||||CYRF6936|
|
[MJXq](Protocols_Details.md#MJXQ---18)|18|WLH08|X600|X800|H26D|E010*|H26WH|PHOENIX*||NRF24L01|XN297
|
||||||
[MJXq](Protocols_Details.md#MJXQ---18)||18|WLH08|X600|X800|H26D|E010*|H26WH|PHOENIX*||NRF24L01|XN297
|
[MLINK](Protocols_Details.md#MLINK---78)|78|||||||||CYRF6936|
|
||||||
[MLINK](Protocols_Details.md#MLINK---78)||78|||||||||CYRF6936|
|
[MouldKg](Protocols_Details.md#mouldkg---90)|90|Analog|Digit|||||||NRF24L01|XN297
|
||||||
[MouldKg](Protocols_Details.md#mouldkg---90)||90|A4444|D4444|A664||||||NRF24L01|XN297
|
[MT99xx](Protocols_Details.md#MT99XX---17)|17|MT|H7|YZ|LS|FY805|A180|DRAGON|F949G|NRF24L01|XN297
|
||||||
[MT99xx](Protocols_Details.md#MT99XX---17)||17|MT|H7|YZ|LS|FY805|A180|DRAGON|F949G|NRF24L01|XN297
|
[MT99xx2](Protocols_Details.md#MT99XX2---92)|92|PA18|SU35|||||||NRF24L01|XN297
|
||||||
[MT99xx2](Protocols_Details.md#MT99XX2---92)||92|PA18|SU35|||||||NRF24L01|XN297
|
[NCC1701](Protocols_Details.md#NCC1701---44)|44|||||||||NRF24L01|
|
||||||
[NCC1701](Protocols_Details.md#NCC1701---44)||44|||||||||NRF24L01|
|
[OMP](Protocols_Details.md#OMP---77)|77|||||||||CC2500&NRF24L01|XN297L
|
||||||
[OMP](Protocols_Details.md#OMP---77)||77|||||||||CC2500&NRF24L01|XN297L
|
[OpenLRS](Protocols_Details.md#OpenLRS---27)|27|||||||||None|
|
||||||
[OpenLRS](Protocols_Details.md#OpenLRS---27)||27|||||||||None|
|
[Pelikan](Protocols_Details.md#Pelikan---60)|60|Pro|Lite|SCX24||||||A7105|
|
||||||
[Pelikan](Protocols_Details.md#Pelikan---60)||60|Pro|Lite|SCX24||||||A7105|
|
[Potensic](Protocols_Details.md#Potensic---51)|51|A20||||||||NRF24L01|XN297
|
||||||
[Potensic](Protocols_Details.md#Potensic---51)||51|A20||||||||NRF24L01|XN297
|
[PROPEL](Protocols_Details.md#PROPEL---66)|66|74-Z||||||||NRF24L01|
|
||||||
[PROPEL](Protocols_Details.md#PROPEL---66)||66|74-Z||||||||NRF24L01|
|
[Q2X2](Protocols_Details.md#Q2X2---29)|29|Q222|Q242|Q282||||||NRF24L01|
|
||||||
[Q2X2](Protocols_Details.md#Q2X2---29)||29|Q222|Q242|Q282||||||NRF24L01|
|
[Q303](Protocols_Details.md#Q303---31)|31|Q303|CX35|CX10D|CX10WD|||||NRF24L01|XN297
|
||||||
[Q303](Protocols_Details.md#Q303---31)||31|Q303|CX35|CX10D|CX10WD|||||NRF24L01|XN297
|
[Q90C](Protocols_Details.md#Q90C---72)|72|Q90C*||||||||NRF24L01|XN297
|
||||||
[Q90C](Protocols_Details.md#Q90C---72)||72|Q90C*||||||||NRF24L01|XN297
|
[RadioLink](Protocols_Details.md#RadioLink---74)|74|Surface|Air|DumboRC|RC4G|||||CC2500|
|
||||||
[RadioLink](Protocols_Details.md#RadioLink---74)||74|Surface|Air|DumboRC|RC4G|Dumbo_P||||CC2500|
|
[Realacc](Protocols_Details.md#Realacc---76)|76|R11||||||||NRF24L01|
|
||||||
[Realacc](Protocols_Details.md#Realacc---76)||76|R11||||||||NRF24L01|
|
[Redpine](Protocols_Details.md#Redpine---50)|50|FAST|SLOW|||||||NRF24L01|XN297
|
||||||
[Redpine](Protocols_Details.md#Redpine---50)||50|FAST|SLOW|||||||NRF24L01|XN297
|
[Scanner](Protocols_Details.md#Scanner---54)|54|||||||||CC2500|
|
||||||
[Scanner](Protocols_Details.md#Scanner---54)||54|||||||||CC2500|
|
[Scorpio](Protocols_Details.md#Scorpio---94)|94|||||||||CYRF6936|
|
||||||
[Scorpio](Protocols_Details.md#Scorpio---94)||94|||||||||CYRF6936|
|
[SGF22](Protocols_Details.md#SGF22---97)|97|F22|F22S|J20||||||NRF24L01|XN297
|
||||||
[SGF22](Protocols_Details.md#SGF22---97)||97|F22|F22S|J20|CX10|||||NRF24L01|XN297
|
[Shenqi](Protocols_Details.md#Shenqi---19)|19|Shenqi||||||||NRF24L01|LT8900
|
||||||
[Shenqi](Protocols_Details.md#Shenqi---19)||19|Shenqi||||||||NRF24L01|LT8900
|
[Skyartec](Protocols_Details.md#Skyartec---68)|68|||||||||CC2500|CC2500
|
||||||
[Shenqi2](Protocols_Details.md#Shenqi2---105)||105|Shenqi2||||||||NRF24L01|XN297
|
[SLT](Protocols_Details.md#SLT---11)|11|SLT_V1|SLT_V2|Q100|Q200|MR100|V1_4CH|RF_SIM||NRF24L01|CC2500
|
||||||
[Skyartec](Protocols_Details.md#Skyartec---68)||68|||||||||CC2500|CC2500
|
[SymaX](Protocols_Details.md#Symax---10)|10|SYMAX|SYMAX5C|||||||NRF24L01|
|
||||||
[SLT](Protocols_Details.md#SLT---11)||11|SLT_V1|SLT_V2|Q100|Q200|MR100|V1_4CH|RF_SIM||NRF24L01|CC2500
|
[Traxxas](Protocols_Details.md#Traxxas---43)|43|TQ2|TQ1|||||||CYRF6936|
|
||||||
[SymaX](Protocols_Details.md#Symax---10)||10|SYMAX|SYMAX5C|||||||NRF24L01|
|
[V2x2](Protocols_Details.md#V2X2---5)|5|V2x2|JXD506|MR101||||||NRF24L01|
|
||||||
[Traxxas](Protocols_Details.md#Traxxas---43)||43|TQ2|TQ1|||||||CYRF6936|
|
[V761](Protocols_Details.md#V761---48)|48|3CH|4CH|TOPRC||||||NRF24L01|XN297
|
||||||
[V2x2](Protocols_Details.md#V2X2---5)||5|V2x2|JXD506|MR101||||||NRF24L01|
|
[V911S](Protocols_Details.md#V911S---46)|46|V911S*|E119*|||||||NRF24L01|XN297
|
||||||
[V761](Protocols_Details.md#V761---48)||48|3CH|4CH|TOPRC||||||NRF24L01|XN297
|
[WFLY](Protocols_Details.md#WFLY---40)|40|WFR0x||||||||CYRF6936|
|
||||||
[V911S](Protocols_Details.md#V911S---46)||46|V911S*|E119*|||||||NRF24L01|XN297
|
[WFLY2](Protocols_Details.md#WFLY2---79)|79|RF20x||||||||A7105|
|
||||||
[WFLY](Protocols_Details.md#WFLY---40)||40|WFR0x||||||||CYRF6936|
|
[WK2x01](Protocols_Details.md#WK2X01---30)|30|WK2801|WK2401|W6_5_1|W6_6_1|W6_HEL|W6_HEL_I|||CYRF6936|
|
||||||
[WFLY2](Protocols_Details.md#WFLY2---79)||79|RF20x||||||||A7105|
|
[XERALL](Protocols_Details.md#XERALL---91)|91|Tank||||||||NRF24L01|XN297
|
||||||
[WK2x01](Protocols_Details.md#WK2X01---30)||30|WK2801|WK2401|W6_5_1|W6_6_1|W6_HEL|W6_HEL_I|||CYRF6936|
|
[XK](Protocols_Details.md#XK---62)|62|X450|X420|Cars||||||NRF24L011&CC2500|XN297
|
||||||
[WL91X](Protocols_Details.md#WL91X---106)||106|||||||||NRF24L01&CC2500|XN297
|
[XK2](Protocols_Details.md#XK2---99)|99|X4|P10|||||||NRF24L01&CC2500|XN297
|
||||||
[WPL](Protocols_Details.md#WPL---107)||107|||||||||NRF24L01|XN297
|
[YD717](Protocols_Details.md#YD717---8)|8|YD717|SKYWLKR|SYMAX4|XINXUN|NIHUI||||NRF24L01|
|
||||||
[XERALL](Protocols_Details.md#XERALL---91)||91|Tank||||||||NRF24L01|XN297
|
[YuXiang](Protocols_Details.md#YuXiang---100)|100|||||||||NRF24L01|XN297
|
||||||
[XK](Protocols_Details.md#XK---62)||62|X450|X420|Cars||||||NRF24L01&CC2500|XN297
|
[ZSX](Protocols_Details.md#ZSX---52)|52|280||||||||NRF24L01|XN297
|
||||||
[XK2](Protocols_Details.md#XK2---99)||99|X4|P10|||||||NRF24L01&CC2500|XN297
|
|
||||||
[YD717](Protocols_Details.md#YD717---8)||8|YD717|SKYWLKR|SYMAX4|XINXUN|NIHUI||||NRF24L01|
|
|
||||||
[YuXiang](Protocols_Details.md#YuXiang---100)||100|||||||||NRF24L01|XN297
|
|
||||||
[ZSX](Protocols_Details.md#ZSX---52)||52|280||||||||NRF24L01|XN297
|
|
||||||
* "*" Sub Protocols designated by * suffix are using a XN297L@250kbps which will be emulated by default with the NRF24L01. If option (freq tune) is diffrent from 0, the CC2500 module (if installed) will be used instead. Each specific sub protocol has a more detailed explanation.
|
* "*" Sub Protocols designated by * suffix are using a XN297L@250kbps which will be emulated by default with the NRF24L01. If option (freq tune) is diffrent from 0, the CC2500 module (if installed) will be used instead. Each specific sub protocol has a more detailed explanation.
|
||||||
|
|
||||||
# A7105 RF Module
|
# A7105 RF Module
|
||||||
@@ -228,59 +224,36 @@ Telemetry enabled protocol:
|
|||||||
- if using erskyTX and OpenTX: full telemetry information available
|
- if using erskyTX and OpenTX: full telemetry information available
|
||||||
- if telemetry is incomplete (missing RX RSSI for example), it means that you have to upgrade your RX firmware to version 1.6 or later. You can do it from an original Flysky TX or using a STLink like explained in [this tutorial](https://www.rcgroups.com/forums/showthread.php?2677694-How-to-upgrade-Flysky-Turnigy-iA6B-RX-to-firmware-1-6-with-a-ST-Link).
|
- if telemetry is incomplete (missing RX RSSI for example), it means that you have to upgrade your RX firmware to version 1.6 or later. You can do it from an original Flysky TX or using a STLink like explained in [this tutorial](https://www.rcgroups.com/forums/showthread.php?2677694-How-to-upgrade-Flysky-Turnigy-iA6B-RX-to-firmware-1-6-with-a-ST-Link).
|
||||||
|
|
||||||
LQI: Link Quality Indicator which is sent back to the RX on CH17
|
|
||||||
|
|
||||||
Option is used to change the servo refresh rate. A value of 0 gives 50Hz (min), 70 gives 400Hz (max). Specific refresh rate value can be calculated like this option=(refresh_rate-50)/5.
|
Option is used to change the servo refresh rate. A value of 0 gives 50Hz (min), 70 gives 400Hz (max). Specific refresh rate value can be calculated like this option=(refresh_rate-50)/5.
|
||||||
|
|
||||||
**RX_Num is used to give a number a given RX. You must use a different RX_Num per RX. A maximum of 64 AFHDS2A RXs are supported.**
|
**RX_Num is used to give a number a given RX. You must use a different RX_Num per RX. A maximum of 64 AFHDS2A RXs are supported.**
|
||||||
|
|
||||||
|
AFHDS2A_LQI_CH is a feature which is disabled by defaut in the _config.h file. When enabled, it makes LQI (Link Quality Indicator) available on one of the RX ouput channel (5-14).
|
||||||
|
|
||||||
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14
|
||||||
|
---|---|---|---|---|---|---|---|---|---|---|---|---|---
|
||||||
|
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14
|
||||||
|
|
||||||
|
RX output will match the Flysky standard AETR independently of the input configuration AETR, RETA... unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
|
||||||
|
|
||||||
### Sub_protocol PWM_IBUS - *0*
|
### Sub_protocol PWM_IBUS - *0*
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16|CH17
|
|
||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---
|
|
||||||
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14CH15|CH16|LQI
|
|
||||||
|
|
||||||
RX output will match the Flysky standard AETR.
|
|
||||||
|
|
||||||
### Sub_protocol PPM_IBUS - *1*
|
### Sub_protocol PPM_IBUS - *1*
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16|CH17
|
|
||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---
|
|
||||||
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14CH15|CH16|LQI
|
|
||||||
|
|
||||||
RX output will match the Flysky standard AETR.
|
|
||||||
|
|
||||||
### Sub_protocol PWM_SBUS - *2*
|
### Sub_protocol PWM_SBUS - *2*
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16|CH17
|
### Sub_protocol PPM_SBUS - *3*
|
||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---
|
As stated above.
|
||||||
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14CH15|CH16|LQI
|
|
||||||
|
|
||||||
RX output will match the Flysky standard AETR.
|
### Sub_protocol PWM_IBUS16 - *4*
|
||||||
|
### Sub_protocol PPM_IBUS16 - *5*
|
||||||
|
### Sub_protocol PWM_SBUS16 - *6*
|
||||||
|
### Sub_protocol PPM_SBUS16 - *7*
|
||||||
|
|
||||||
### Sub_protocol Gyro_Off - *3*
|
3 additional channels. Need recent or updated RXs.
|
||||||
RXs: FS-BS6, FS-BS4
|
|
||||||
|
|
||||||
Gyro is off
|
CH15|CH16|CH17
|
||||||
|
---|---|---
|
||||||
|
CH15|CH16|LQI
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16|CH17
|
LQI: Link Quality Indicator
|
||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|-|-|-|-|LQI
|
|
||||||
|
|
||||||
### Sub_protocol Gyro_On - *4*
|
|
||||||
RXs: FS-BS6, FS-BS4
|
|
||||||
|
|
||||||
Gyro is on
|
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16|CH17
|
|
||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|ST_Gain|TH_Gain|Priority|Calib|LQI
|
|
||||||
|
|
||||||
### Sub_protocol Gyro_On_Rev - *5*
|
|
||||||
RXs: FS-BS6, FS-BS4
|
|
||||||
|
|
||||||
Gyro is on and reversed
|
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16|CH17
|
|
||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|ST_Gain|TH_Gain|Priority|Calib|LQI
|
|
||||||
|
|
||||||
## FLYSKY AFHDS2A RX - *56*
|
## FLYSKY AFHDS2A RX - *56*
|
||||||
The Flysky AFHDS2A receiver protocol enables master/slave trainning, separate access from 2 different radios to the same model,...
|
The Flysky AFHDS2A receiver protocol enables master/slave trainning, separate access from 2 different radios to the same model,...
|
||||||
@@ -1063,21 +1036,7 @@ Air protocol. TXs: T8FB,T8S. Compatible RXs: R8EF,R8FM,R8SM,R4FG,R4F
|
|||||||
Telemetry: RX_RSSI (for the original value add -256), TX_RSSI, TX_QLY (0..100%)
|
Telemetry: RX_RSSI (for the original value add -256), TX_RSSI, TX_QLY (0..100%)
|
||||||
|
|
||||||
### Sub_protocol DumboRC - *2*
|
### Sub_protocol DumboRC - *2*
|
||||||
Compatible RXs:
|
Compatible RXs: X6/X6F/X6FG
|
||||||
* X6/X6F/X6FG/X6DC/X6DCG/X10F/X10FG (Other X Series should work as well)
|
|
||||||
* P6F/P6FG/P6DC/P6DCG/P6FP/P10F/P10FG (Other P Series should work as well)
|
|
||||||
|
|
||||||
For P series specific features, see subprotocol 4 below.
|
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
|
|
||||||
---|---|---|---|---|---|---|---|---|----
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8/Gyro gain|CH9|CH10
|
|
||||||
|
|
||||||
Telemetry:
|
|
||||||
* RX_RSSI uses the receiver's direct percentage when available
|
|
||||||
* TX_RSSI is the module-side received RSSI
|
|
||||||
* TX_QLY is 0..100%
|
|
||||||
* A2=external battery voltage in 0.1V units (set the ratio to 25.5 and adjust with offset)
|
|
||||||
|
|
||||||
### Sub_protocol RC4G - *3*
|
### Sub_protocol RC4G - *3*
|
||||||
Compatible RXs: R4EH-G(/R4EH-H)
|
Compatible RXs: R4EH-G(/R4EH-H)
|
||||||
@@ -1090,21 +1049,6 @@ FS=FailSafe
|
|||||||
|
|
||||||
CH5 is driven by CH3 on the original TX, gyro sensitivity?
|
CH5 is driven by CH3 on the original TX, gyro sensitivity?
|
||||||
|
|
||||||
### Sub_protocol Dumbo_P - *4*
|
|
||||||
Compatible RXs: P6F/P6FG/P6DC/P6DCG/P6FP/P10F/P10FG (Other P Series should work as well)
|
|
||||||
|
|
||||||
P series supports configuring receiver from transmitter. Originally, this logic appeared on DumboRC DDF-350 transmitter in 1.1.5 firmware version.
|
|
||||||
|
|
||||||
You can adjust these settings by using "DumboRC P Series.lua" script.
|
|
||||||
|
|
||||||
Settings include:
|
|
||||||
* gyro on/off
|
|
||||||
* gyro phase
|
|
||||||
* gyro tuning
|
|
||||||
* gyro gain channel
|
|
||||||
* setting gyro endpoints
|
|
||||||
* setting failsafe values
|
|
||||||
|
|
||||||
## Futaba - *21*
|
## Futaba - *21*
|
||||||
Also called SFHSS depending on radio version.
|
Also called SFHSS depending on radio version.
|
||||||
|
|
||||||
@@ -1173,9 +1117,9 @@ New generation of GD models
|
|||||||
### Sub_protocol KF606 - *0*
|
### Sub_protocol KF606 - *0*
|
||||||
Model: KF606
|
Model: KF606
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6
|
CH1|CH2|CH3|CH4|CH5
|
||||||
---|---|---|---|---|---
|
---|---|---|---|---
|
||||||
A||T||TRIM|LED
|
A||T||TRIM
|
||||||
|
|
||||||
### Sub_protocol MIG320 - *1*
|
### Sub_protocol MIG320 - *1*
|
||||||
Model: Zhiyang MIG-320
|
Model: Zhiyang MIG-320
|
||||||
@@ -1238,22 +1182,16 @@ If only a NRF24L01 is installed then this sub protocol might be problematic beca
|
|||||||
## MT99XX - *17*
|
## MT99XX - *17*
|
||||||
Autobind protocol
|
Autobind protocol
|
||||||
|
|
||||||
CC2500: only YZ and F949G are supported.
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
|
||||||
|
---|---|---|---|---|---|---|---|---
|
||||||
|
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS
|
||||||
|
|
||||||
|
CC2500: only YZ is supported.
|
||||||
|
|
||||||
### Sub_protocol MT99 - *0*
|
### Sub_protocol MT99 - *0*
|
||||||
Models: MT99xx
|
Models: MT99xx
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
|
||||||
---|---|---|---|---|---|---|---|---|---|---
|
|
||||||
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS|ATrim|ETrim
|
|
||||||
|
|
||||||
### Sub_protocol H7 - *1*
|
### Sub_protocol H7 - *1*
|
||||||
Models: Eachine H7, Cheerson CX023
|
Models: Eachine H7, Cheerson CX023
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
|
||||||
---|---|---|---|---|---|---|---|---|---|---
|
|
||||||
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS|ATrim|ETrim
|
|
||||||
|
|
||||||
### Sub_protocol YZ - *2*
|
### Sub_protocol YZ - *2*
|
||||||
Model: Yi Zhan i6S
|
Model: Yi Zhan i6S
|
||||||
|
|
||||||
@@ -1263,71 +1201,63 @@ If a CC2500 is installed it will be used for this sub protocol. Option in this c
|
|||||||
|
|
||||||
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
|
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
|
||||||
---|---|---|---|---|---|---|---|---|---|---
|
|
||||||
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS|ATrim|ETrim
|
|
||||||
|
|
||||||
### Sub_protocol LS - *3*
|
### Sub_protocol LS - *3*
|
||||||
Models: LS114, 124, 215
|
Models: LS114, 124, 215
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
|
||||||
---|---|---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---|---|---|---
|
||||||
A|E|T|R|FLIP|INVERT|PICTURE|VIDEO|HEADLESS|ATrim|ETrim
|
A|E|T|R|FLIP|INVERT|PICTURE|VIDEO|HEADLESS
|
||||||
|
|
||||||
### Sub_protocol FY805 - *4*
|
### Sub_protocol FY805 - *4*
|
||||||
Model: FY805
|
Model: FY805
|
||||||
|
|
||||||
**Only 1 ID available**
|
**Only 1 ID available**
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
|
||||||
---|---|---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---|---|---|---
|
||||||
A|E|T|R|FLIP||||HEADLESS|ATrim|ETrim
|
A|E|T|R|FLIP||||HEADLESS
|
||||||
|
|
||||||
### Sub_protocol A180 - *5*
|
### Sub_protocol A180 - *5*
|
||||||
Model: XK A180, A120, F949S, F959
|
Model: XK A180, A120, F949S, F959
|
||||||
|
|
||||||
A180:
|
A180:
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
CH1|CH2|CH3|CH4|CH5|CH6
|
||||||
---|---|---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---
|
||||||
A|E|T|R|3D6G|RATE||||ATrim|ETrim
|
A|E|T|R|3D6G|RATE
|
||||||
|
|
||||||
A120:
|
A120:
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
CH1|CH2|CH3|CH4|CH5|CH6
|
||||||
---|---|---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---
|
||||||
A|E|T|R|RATE|LED||||ATrim|ETrim
|
A|E|T|R|RATE|LED
|
||||||
|
|
||||||
F949S:
|
F949S:
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7
|
||||||
---|---|---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---|---
|
||||||
A|E|T|R|RATE|RXLED|3D6G|||ATrim|ETrim
|
A|E|T|R|RATE|RXLED|3D6G
|
||||||
|
|
||||||
### Sub_protocol DRAGON - *6*
|
### Sub_protocol DRAGON - *6*
|
||||||
Model: Eachine Mini Wing Dragon, Eachine Mini Cessna
|
Model: Eachine Mini Wing Dragon, Eachine Mini Cessna
|
||||||
|
|
||||||
Telemetry is supported: A1 = battery voltage with a Ratio of 25.5, A2=battery low flag (0=off,>0=on) and RSSI = dummy value of 100
|
Telemetry is supported: A1 = battery voltage with a Ratio of 25.5, A2=battery low flag (0=off,>0=on) and RSSI = dummy value of 100
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
CH1|CH2|CH3|CH4|CH5|CH6
|
||||||
---|---|---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---
|
||||||
A|E|T|R|MODE|RTH||||ATrim|ETrim
|
A|E|T|R|MODE|RTH
|
||||||
|
|
||||||
MODE: -100%=Beginner, 0%=Intermediate, +100%=Advanced
|
MODE: -100%=Beginner, 0%=Intermediate, +100%=Advanced
|
||||||
|
|
||||||
### Sub_protocol F949G - *7*
|
### Sub_protocol F949G - *7*
|
||||||
If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
|
|
||||||
|
|
||||||
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
|
|
||||||
|
|
||||||
Model: F949G
|
Model: F949G
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
CH1|CH2|CH3|CH4|CH5|CH6
|
||||||
---|---|---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---
|
||||||
A|E|T|R|6G3D|Light||||ATrim|ETrim
|
A|E|T|R|6G3D|Light
|
||||||
|
|
||||||
Model: KFPLAN Z-Series like Z61 BF109, Z54 A380,...
|
Model: KFPLAN Z-Series like Z61 BF109, Z54 A380,...
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
|
||||||
---|---|---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---|---|---|---
|
||||||
A|E|T|R||Rate|Light|Unk1|Unk2|ATrim|ETrim
|
A|E|T|R|-|Rate|Light|Unk1|Unk2
|
||||||
|
|
||||||
Unk1&2: long press right/left
|
Unk1&2: long press right/left
|
||||||
|
|
||||||
@@ -1336,18 +1266,20 @@ Unk1&2: long press right/left
|
|||||||
### Sub_protocol PA18 - *0*
|
### Sub_protocol PA18 - *0*
|
||||||
Model: PA18 mini
|
Model: PA18 mini
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7
|
||||||
---|---|---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---|---
|
||||||
A|E|T|R|MODE|FLIP|RTH|||ATrim|ETrim
|
A|E|T|R|MODE|FLIP|RTH
|
||||||
|
|
||||||
MODE: -100% beginner, 0% intermediate, +100% Expert
|
MODE: -100% beginner, 0% intermediate, +100% Expert
|
||||||
|
|
||||||
### Sub_protocol SU35 - *1*
|
### Sub_protocol SU35 - *1*
|
||||||
Model: QF009 SU35
|
Model: QF009 SU35
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
CH6 - LED, CH7 - LED Flash, CH8 - Invert, CH9 - Rate
|
||||||
---|---|---|---|---|---|---|---|---|---|---
|
|
||||||
A|E|T|R|MODE|LED|LED_FLASH|INVERT|RATE|ATrim|ETrim
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
|
||||||
|
---|---|---|---|---|---|---|---|---
|
||||||
|
A|E|T|R|MODE|LED|LED_FLASH|INVERT|RATE
|
||||||
|
|
||||||
MODE: -100% 6G, +100% 3D
|
MODE: -100% 6G, +100% 3D
|
||||||
|
|
||||||
@@ -1507,14 +1439,11 @@ FLIP: sets model into flip mode for approx 5 seconds at each throw of switch (re
|
|||||||
MODE: -100% level, +100% acro
|
MODE: -100% level, +100% acro
|
||||||
|
|
||||||
### Sub_protocol V1_4CH - *5*
|
### Sub_protocol V1_4CH - *5*
|
||||||
Transmitters: SLT2 and SLT2 DLC, Receivers: SPMXSE2825RX, SPMXSBER1025G, SPMXSE4510RX, ...
|
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4
|
CH1|CH2|CH3|CH4
|
||||||
---|---|---|---
|
---|---|---|---
|
||||||
CH1|CH2|CH3|CH4
|
CH1|CH2|CH3|CH4
|
||||||
|
|
||||||
CH4 is used for DSC settings: -35% off to +15% full
|
|
||||||
|
|
||||||
### Sub_protocol RF_SIM - *6*
|
### Sub_protocol RF_SIM - *6*
|
||||||
Models: the SLT-dongle included in RealFlight 7.5
|
Models: the SLT-dongle included in RealFlight 7.5
|
||||||
|
|
||||||
@@ -1552,14 +1481,6 @@ A|E|T|R|CALIB|RATE|6G_3D|6GSENIOR|LIGHT
|
|||||||
|
|
||||||
A280 -> 6GSENIOR: -100% - 6G, +100% - Senior mode (turn off gyro), LIGHT: cycle the light through on-flash-off when the CH9 value is changed from -100% to 100%
|
A280 -> 6GSENIOR: -100% - 6G, +100% - Senior mode (turn off gyro), LIGHT: cycle the light through on-flash-off when the CH9 value is changed from -100% to 100%
|
||||||
|
|
||||||
## WL91X - *106*
|
|
||||||
|
|
||||||
Models: WLtoys WL911, WL913, WL915 and may be others...
|
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4
|
|
||||||
---|---|---|---
|
|
||||||
ST|TH|ST_TR|TH_TR
|
|
||||||
|
|
||||||
## XK - *62*
|
## XK - *62*
|
||||||
|
|
||||||
CC2500: only X450 is supported.
|
CC2500: only X450 is supported.
|
||||||
@@ -1603,25 +1524,17 @@ If a CC2500 is installed it will be used for this sub protocol. Option in this c
|
|||||||
|
|
||||||
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
|
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
|
||||||
---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---|---|---
|
||||||
A|E|T|R|Rate|Mode|Hover|Light|Stunt
|
A|E|T|R|Rate|Mode|Hover|Light
|
||||||
|
|
||||||
The plane does not need to be bound each time if it is powered on **after** the radio/protocol is on.
|
The plane does not need to be bound each time if it is powered on **after** the radio/protocol is on.
|
||||||
|
|
||||||
Telemetry is supported. The plane sends a battery status of good->empty which is visible in A1 (good=8.4V->empty=7.1V) and RSSI gets a dummy value of 100. For the Sky Viper Vector, the battery telemetry will still appear in A1 with good=8.4V->empty=7.1V despite being a 1S plane with a switch good/bad in reality at 3.3V.
|
|
||||||
|
|
||||||
The rudder trim is driven from the rudder channel to increase the range (Original TX rudder has no range once the motor has been turned on...).
|
The rudder trim is driven from the rudder channel to increase the range (Original TX rudder has no range once the motor has been turned on...).
|
||||||
|
|
||||||
Mode: -100%=6G, 0%=3D, +100%=Gyro off (Senior mode)
|
|
||||||
|
|
||||||
Stunt: Sky Viper Vector
|
|
||||||
|
|
||||||
### Sub_protocol X4 - *0*
|
### Sub_protocol X4 - *0*
|
||||||
Transmitter: XK X4-A160, X5S, model: XK A160S, XK A280, XK A300
|
Transmitter: XK X4-A160, X5S, model: XK A160S, XK A280, XK A300
|
||||||
|
|
||||||
Model: Sky Viper Vector
|
|
||||||
|
|
||||||
### Sub_protocol P10 - *1*
|
### Sub_protocol P10 - *1*
|
||||||
Model: Park10 J3-CUB
|
Model: Park10 J3-CUB
|
||||||
|
|
||||||
@@ -1872,22 +1785,18 @@ FMODE and AUX7 have 4 positions: -100%..-50%=>0, -50%..5%=>1, 5%..50%=>2, 50%..1
|
|||||||
## FX - *58*
|
## FX - *58*
|
||||||
FEI XIONG
|
FEI XIONG
|
||||||
|
|
||||||
### Sub_protocol FX816 - *0*
|
CH1|CH2|CH3|CH4
|
||||||
|
---|---|---|---
|
||||||
|
A|-|T|-
|
||||||
|
|
||||||
|
### Sub_protocol 816 - *0*
|
||||||
Model: FX816 P38, B17
|
Model: FX816 P38, B17
|
||||||
|
|
||||||
Only 8 TX IDs available
|
Only 8 TX IDs available
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4
|
### Sub_protocol 620 - *1*
|
||||||
---|---|---|---
|
|
||||||
A|-|T|-
|
|
||||||
|
|
||||||
### Sub_protocol FX620 - *1*
|
|
||||||
Model: FX620 SU35
|
Model: FX620 SU35
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4
|
|
||||||
---|---|---|---
|
|
||||||
A|-|T|-
|
|
||||||
|
|
||||||
### Sub_protocol 9630 - *2*
|
### Sub_protocol 9630 - *2*
|
||||||
Model: FX9630, FX9603, QIDI-550
|
Model: FX9630, FX9603, QIDI-550
|
||||||
|
|
||||||
@@ -1900,7 +1809,7 @@ FX9630 and FX9603 Gyro: -100%=6G small throw, 0%=6G large throw, +100%=3D
|
|||||||
QIDI-550 Gyro: -100%=3D, 0%=6G, +100%=Torque
|
QIDI-550 Gyro: -100%=3D, 0%=6G, +100%=Torque
|
||||||
|
|
||||||
### Sub_protocol Q560 - *3*
|
### Sub_protocol Q560 - *3*
|
||||||
Model: QIDI-560, QIDI-580 (Cirrus SR22)
|
Model: QIDI-560
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7
|
||||||
---|---|---|---|---|---|---
|
---|---|---|---|---|---|---
|
||||||
@@ -1908,52 +1817,8 @@ A|E|T|R|FLIP|GYRO|LEDs
|
|||||||
|
|
||||||
FLIP is a toggle channel meaning that -100% to +100% is a command and +100% to -100% is also a command
|
FLIP is a toggle channel meaning that -100% to +100% is a command and +100% to -100% is also a command
|
||||||
|
|
||||||
- GYRO QIDI-560: -100%=6G, 0%=3D+Gyro, +100%=3D
|
|
||||||
- GYRO QIDI-580: -100%=6G, 0%=6G+Inverted, +100%=3D+Gyro
|
|
||||||
|
|
||||||
### Sub_protocol QF012 - *4*
|
|
||||||
Model: QF012 SBD Dauntless
|
|
||||||
|
|
||||||
Telemetry supported. The plane sends a battery status of good->empty which is visible in A1 (good=4.2V->empty=3.1V) and RSSI gets a dummy value of 100.
|
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
|
|
||||||
---|---|---|---|---|---|---|---
|
|
||||||
A|E|T|R|FLIP|GYRO|Invert|Reset
|
|
||||||
|
|
||||||
Gyro: -100%=6G, 0%=3D+Gyro, +100%=3D
|
Gyro: -100%=6G, 0%=3D+Gyro, +100%=3D
|
||||||
|
|
||||||
Reset: Restore fine tunning midpoint
|
|
||||||
|
|
||||||
### Sub_protocol BM26 - *5*
|
|
||||||
Model: BM26 P51
|
|
||||||
|
|
||||||
Telemetry supported. The plane sends a battery status of good->empty which is visible in A1 (good=4.2V->empty=3.1V) and RSSI gets a dummy value of 100.
|
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
|
|
||||||
---|---|---|---|---|---|---|---|---
|
|
||||||
A|E|T|R|FLIP|GYRO|LEDs|Turning Light switch|Calib
|
|
||||||
|
|
||||||
Gyro: -100%=6G, 0%=3D+Gyro, +100%=3D
|
|
||||||
|
|
||||||
### Sub_protocol A570 - *6*
|
|
||||||
VTOL Model: Kootai A570, QIDI-570
|
|
||||||
|
|
||||||
This model has no telemetry. Low battery indicated by model LED's turning flashing red.
|
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
|
|
||||||
---|---|---|---|---|---|---|---|---|---|---|---
|
|
||||||
A|E|T|R|STOP|MODE|Rate|Color|LED-Off|TrimR|TrimA|TrimE
|
|
||||||
|
|
||||||
- STOP: -100% allows standard start / sticks moved down and center (Mode 2), +100% all motors stop
|
|
||||||
- MODE: -100%=Vertical hover, 0%=Flat flight, +100%=Vertical flight (Original TX will not allow motor start in Flat flight)
|
|
||||||
- Rate: -100%=Low Rate, +100%=High Rate
|
|
||||||
- Color: -100% / +100% toggles LED lights through color choices
|
|
||||||
- LED-Off: +100% switches lights OFF, -100% allows lights ON after a toggle of the color channel
|
|
||||||
- Trims: -100%=Rud-L,Ail-L,Ele-Back, +100%=Rud-R,Ail-R,Ele-Fwd, if used must be tied to momentary 3-pos switches
|
|
||||||
- (trim switches disabled in FM tab, added to trim channels 10,11,12 in mixes tab)
|
|
||||||
|
|
||||||
Calibration: Same as original TX, model on level surface, TX bound, sticks lower left corners, LED's flashing
|
|
||||||
|
|
||||||
## FY326 - *20*
|
## FY326 - *20*
|
||||||
|
|
||||||
### Sub_protocol FY326 - *0*
|
### Sub_protocol FY326 - *0*
|
||||||
@@ -1967,29 +1832,12 @@ A|E|T|R|FLIP|RTH|HEADLESS|EXPERT|CALIBRATE
|
|||||||
Model: X6 FY319 Quadcopter (Needs Testing)
|
Model: X6 FY319 Quadcopter (Needs Testing)
|
||||||
|
|
||||||
## FQ777 - *23*
|
## FQ777 - *23*
|
||||||
Autobind protocol
|
|
||||||
|
|
||||||
### Sub_protocol 124 - *0*
|
|
||||||
Model: FQ777-124 (with SV7241A)
|
Model: FQ777-124 (with SV7241A)
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
|
||||||
---|---|---|---|---|---|---|---
|
---|---|---|---|---|---|---|---
|
||||||
A|E|T|R|FLIP|RTH|HEADLESS|EXPERT
|
A|E|T|R|FLIP|RTH|HEADLESS|EXPERT
|
||||||
|
|
||||||
### Sub_protocol XBM37 - *1*
|
|
||||||
Model: T-Smart XBM-37 (with SV7241A)
|
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14
|
|
||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---
|
|
||||||
A|E|T|R|RATE|FLIP|HEADLESS|LED|PICTURE|VIDEO|RTH|OK|ETrim|Atrim
|
|
||||||
|
|
||||||
- RATE: -100% Low, 0% Mid, +100% High
|
|
||||||
- CH6 to CH12 are OFF/-100 and ON/+100 exception LED is OFF/+100
|
|
||||||
- Receiver numbers (0-63) available for model match, MPM global ID used for unique module identifier.
|
|
||||||
- Changing the TX module or RX number will require re-binding the receiver.
|
|
||||||
|
|
||||||
Calibration: Set quad on level surface, pull both sticks down in outer corners until LED's flash (Mode-2 TX)
|
|
||||||
|
|
||||||
## GW008 - *32*
|
## GW008 - *32*
|
||||||
Model: Global Drone GW008 from Banggood
|
Model: Global Drone GW008 from Banggood
|
||||||
|
|
||||||
@@ -2084,16 +1932,14 @@ ARM|
|
|||||||
|
|
||||||
### Sub_protocol XKK170 - *3*
|
### Sub_protocol XKK170 - *3*
|
||||||
|
|
||||||
Model: XK K170 UH-60L Black hawk, XK K270 UH-60L
|
Model: XK K170 UH-60L Black hawk
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
|
||||||
---|---|---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---|---|---|---|---
|
||||||
A|E|T|R|RATE|EMERGENCY|TAKE_OFF/LANDING|CALIB|TrimA|TrimE|Optical
|
A|E|T|R|RATE|EMERGENCY|TAKE_OFF/LANDING|CALIB|TrimA|TrimE
|
||||||
|
|
||||||
RATE: -100% Low, 0% Mid, +100% High
|
RATE: -100% Low, 0% Mid, +100% High
|
||||||
|
|
||||||
Optic: enable/disable the optical flow sensor for K270
|
|
||||||
|
|
||||||
## JIABAILE - *102*
|
## JIABAILE - *102*
|
||||||
|
|
||||||
### Sub_protocol Std - *0*
|
### Sub_protocol Std - *0*
|
||||||
@@ -2136,13 +1982,13 @@ Model: DF-Models SkyTumbler
|
|||||||
RTH not supported
|
RTH not supported
|
||||||
|
|
||||||
## KAMTOM - *104*
|
## KAMTOM - *104*
|
||||||
Models: KAMTOM RC Racing KM24xx (KM32xx?), Pinecone SG-24xx
|
Models: KAMTOM KM24xx (KM32xx?), Pinecone SG-24xx
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7
|
||||||
---|---|---|---|---|---|---
|
---|---|---|---|---|---|---
|
||||||
ST|TH|UNK1|UNK2|ST_TR|TH_TR|TH_DR
|
ST|TH|UNK1|UNK2|ST_TR|TH_TR|TH_DR
|
||||||
|
|
||||||
Low battery telemetry in A1 with 0 = low batt
|
Low batt telemetry is not yet added.
|
||||||
|
|
||||||
## KYOSHO2 - *93*
|
## KYOSHO2 - *93*
|
||||||
Model: TX KT-17, Minium Edge 540, Minium Citabria
|
Model: TX KT-17, Minium Edge 540, Minium Citabria
|
||||||
@@ -2180,9 +2026,6 @@ CH16| CH8 | -100% | 0% | - | - | -
|
|||||||
## MouldKg - *90*
|
## MouldKg - *90*
|
||||||
Mould King 2.4GHz TX: Technic Brick models
|
Mould King 2.4GHz TX: Technic Brick models
|
||||||
|
|
||||||
### Sub_protocol A4444 - *0*
|
|
||||||
Model: 4 analog ports brick
|
|
||||||
|
|
||||||
Up to 4 bricks can be controlled at the same time.
|
Up to 4 bricks can be controlled at the same time.
|
||||||
|
|
||||||
Option field | Value
|
Option field | Value
|
||||||
@@ -2198,52 +2041,17 @@ To associate a brick to a RX number (RX_num above), set this RX number under the
|
|||||||
Example: I want to control 2 bricks. I select RX number 1, set option to 1 and launch a bind on the first brick. I select RX number 2, set option to 1 and launch a bind on the second brick. Now to control both bricks I set RX number to 1 and option to 2. Therefore brick1 will react to channels CH1 to CH4 and brick2 to channel CH5 to CH8.
|
Example: I want to control 2 bricks. I select RX number 1, set option to 1 and launch a bind on the first brick. I select RX number 2, set option to 1 and launch a bind on the second brick. Now to control both bricks I set RX number to 1 and option to 2. Therefore brick1 will react to channels CH1 to CH4 and brick2 to channel CH5 to CH8.
|
||||||
On another model I can control 4 other bricks, bind each brick to RX number 3 to 6 and then finaly set RX number to 3 and option to 4 to contol the 4 bricks with CH1 to CH16.
|
On another model I can control 4 other bricks, bind each brick to RX number 3 to 6 and then finaly set RX number to 3 and option to 4 to contol the 4 bricks with CH1 to CH16.
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
|
### Sub_protocol Analog - *0*
|
||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---
|
|
||||||
Brick1_A|Brick1_B|Brick1_C|Brick1_D|Brick2_A|Brick2_B|Brick2_C|Brick2_D|Brick3_A|Brick3_B|Brick3_C|Brick3_D|Brick4_A|Brick4_B|Brick4_C|Brick4_D
|
|
||||||
|
|
||||||
### Sub_protocol D4444 - *1*
|
|
||||||
Model: 4 digital ports brick and Integrated power module
|
|
||||||
|
|
||||||
Up to 4 bricks can be controlled at the same time.
|
|
||||||
|
|
||||||
Option field | Value
|
|
||||||
-------------|------
|
|
||||||
0|The module will act like the original radio which will bind every time and attach to the first brick in bind mode
|
|
||||||
1|The module will control the brick number RX_num
|
|
||||||
2|The module will control the brick number RX_num and RX_num+1
|
|
||||||
3|The module will control the brick number RX_num, RX_num+1 and RX_num+2
|
|
||||||
4|The module will control the brick number RX_num, RX_num+1, RX_num+2 and RX_num+3
|
|
||||||
|
|
||||||
To associate a brick to a RX number (RX_num above), set this RX number under the protocol, set option to 1, launch a bind and power on the brick you want to control. Repeat this for every brick using a different RX number each time and then indicate the number of bricks to be controlled using the Option field.
|
|
||||||
|
|
||||||
Example: I want to control 2 bricks. I select RX number 1, set option to 1 and launch a bind on the first brick. I select RX number 2, set option to 1 and launch a bind on the second brick. Now to control both bricks I set RX number to 1 and option to 2. Therefore brick1 will react to channels CH1 to CH4 and brick2 to channel CH5 to CH8.
|
|
||||||
On another model I can control 4 other bricks, bind each brick to RX number 3 to 6 and then finaly set RX number to 3 and option to 4 to contol the 4 bricks with CH1 to CH16.
|
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
|
||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---
|
||||||
Brick1_A|Brick1_B|Brick1_C|Brick1_D|Brick2_A|Brick2_B|Brick2_C|Brick2_D|Brick3_A|Brick3_B|Brick3_C|Brick3_D|Brick4_A|Brick4_B|Brick4_C|Brick4_D
|
Brick1_A|Brick1_B|Brick1_C|Brick1_D|Brick2_A|Brick2_B|Brick2_C|Brick2_D|Brick3_A|Brick3_B|Brick3_C|Brick3_D|Brick4_A|Brick4_B|Brick4_C|Brick4_D
|
||||||
|
|
||||||
### Sub_protocol A664 - *2*
|
### Sub_protocol Digit - *1*
|
||||||
Model: 4/6 analog ports brick
|
|
||||||
|
|
||||||
Up to 3 bricks can be controlled at the same time. The bricks can be either 4 or 6 ports but only the 2 first bricks will be sent 6 channels, the last brick will only be sent 4 channels.
|
|
||||||
|
|
||||||
Option field | Value
|
|
||||||
-------------|------
|
|
||||||
0|The module will act like the original radio which will bind every time and attach to the first brick in bind mode
|
|
||||||
1|The module will control the brick number RX_num
|
|
||||||
2|The module will control the brick number RX_num and RX_num+1
|
|
||||||
3|The module will control the brick number RX_num, RX_num+1 and RX_num+2
|
|
||||||
|
|
||||||
To associate a brick to a RX number (RX_num above), set this RX number under the protocol, set option to 1, launch a bind and power on the brick you want to control. Repeat this for every brick using a different RX number each time and then indicate the number of bricks to be controlled using the Option field.
|
|
||||||
|
|
||||||
Example: I want to control 2 bricks. I select RX number 1, set option to 1 and launch a bind on the first brick. I select RX number 2, set option to 1 and launch a bind on the second brick. Now to control both bricks I set RX number to 1 and option to 2. Therefore brick1 will react to channels CH1 to CH4 and brick2 to channel CH5 to CH8.
|
|
||||||
On another model I can control 3 other bricks, bind each brick to RX number 3 to 5 and then finaly set RX number to 3 and option to 3 to contol the 4 bricks with CH1 to CH16.
|
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
|
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
|
||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---
|
||||||
Brick1_A|Brick1_B|Brick1_C|Brick1_D|Brick1_E|Brick1_F|Brick2_A|Brick2_B|Brick2_C|Brick2_D|Brick2_E|Brick2_F|Brick3_A|Brick3_B|Brick3_C|Brick3_D
|
Brick1_A|Brick1_B|Brick1_C|Brick1_D|Brick2_A|Brick2_B|Brick2_C|Brick2_D|Brick3_A|Brick3_B|Brick3_C|Brick3_D|Brick4_A|Brick4_B|Brick4_C|Brick4_D
|
||||||
|
|
||||||
## NCC1701 - *44*
|
## NCC1701 - *44*
|
||||||
Model: Air Hogs Star Trek USS Enterprise NCC-1701-A
|
Model: Air Hogs Star Trek USS Enterprise NCC-1701-A
|
||||||
@@ -2322,8 +2130,6 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
|
|||||||
---|---|---|---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---|---|---|---|---|---|---
|
||||||
A|E|T|R|MODE|FLIP|LIGHT|PHOTO|VIDEO|TRIMRESET|BAL|BALHIG
|
A|E|T|R|MODE|FLIP|LIGHT|PHOTO|VIDEO|TRIMRESET|BAL|BALHIG
|
||||||
|
|
||||||
Telemetry is supported. The plane sends a battery status of good->empty which is visible in A1 (good=13.2V->empty=0V) and RSSI gets a dummy value of 100.
|
|
||||||
|
|
||||||
### Sub_protocol F22
|
### Sub_protocol F22
|
||||||
Model: SG F22
|
Model: SG F22
|
||||||
|
|
||||||
@@ -2336,19 +2142,12 @@ Manual CH11=-100% & CH12=-100%, Balance CH11=+100% & CH12=-100%, Large Angle Bal
|
|||||||
### Sub_protocol F22S
|
### Sub_protocol F22S
|
||||||
Model: ParkTen F22S
|
Model: ParkTen F22S
|
||||||
|
|
||||||
Mode -100% = 3D, 0% = 6G
|
F22S: Mode -100% = 3D, 0% = 6G
|
||||||
|
|
||||||
### Sub_protocol J20
|
### Sub_protocol J20
|
||||||
Model: KF700 J20
|
Model: KF700 J20
|
||||||
|
|
||||||
Mode -100% = Gyro off, 0% = Horizontal, 100% = Vertical. CH8 - Invert, CH10 - Fix Height (Altitude hold)
|
J20: Mode -100% = Gyro off, 0% = Horizontal, 100% = Vertical. CH8 - Invert, CH10 - Fix Height (Altitude hold)
|
||||||
|
|
||||||
### Sub_protocol CX10
|
|
||||||
Model: Cheerson CX-10 with red PCB
|
|
||||||
|
|
||||||
**Only 2 IDs available**, use RX num to cycle through them.
|
|
||||||
|
|
||||||
Mode -100% = Low, 0% = Medium, 100% = High
|
|
||||||
|
|
||||||
## Shenqi - *19*
|
## Shenqi - *19*
|
||||||
Autobind protocol
|
Autobind protocol
|
||||||
@@ -2361,15 +2160,6 @@ CH1|CH2|CH3|CH4
|
|||||||
|
|
||||||
Throttle +100%=full forward,0%=stop,-100%=full backward.
|
Throttle +100%=full forward,0%=stop,-100%=full backward.
|
||||||
|
|
||||||
## Shenqi2 - *105*
|
|
||||||
Autobind protocol
|
|
||||||
|
|
||||||
Model: Shenqiwei 1/20 Mini Motorcycle
|
|
||||||
|
|
||||||
CH1|CH2
|
|
||||||
---|---
|
|
||||||
ST|TH
|
|
||||||
|
|
||||||
## Symax - *10*
|
## Symax - *10*
|
||||||
Autobind protocol
|
Autobind protocol
|
||||||
|
|
||||||
@@ -2454,19 +2244,6 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
|
|||||||
---|---|---|---|---|---|---|---|---
|
---|---|---|---|---|---|---|---|---
|
||||||
A|E|T|R|GYRO|CALIB|FLIP|RTN_ACT|RTN
|
A|E|T|R|GYRO|CALIB|FLIP|RTN_ACT|RTN
|
||||||
|
|
||||||
## WPL - *107*
|
|
||||||
TX: "Basic", Models: D12 / D12KM / D22 / D32 / D42 / D14
|
|
||||||
|
|
||||||
**Only 1 ID** available. If you have a TX contact me on GitHub or RCGroups.
|
|
||||||
|
|
||||||
Autobind protocol
|
|
||||||
|
|
||||||
CH1|CH2|CH3|CH4|CH5|CH6|CH7
|
|
||||||
---|---|---|---|---|---|---
|
|
||||||
TH|ST|ST_Trim|Aux|Light|TH_Rate|ST_Rate
|
|
||||||
|
|
||||||
Light: -100%=Off, +100%=On, Rate: -100%=Low, +100%=High
|
|
||||||
|
|
||||||
## XERALL - *91*
|
## XERALL - *91*
|
||||||
Model: Xerall TankCopter
|
Model: Xerall TankCopter
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ mv build/Multiprotocol.ino.bin ./binaries/mm-avr-txflash-aetr-A7105-inv-v$MULTI_
|
|||||||
printf "\e[33;1mBuilding mm-avr-txflash-aetr-CC2500-inv-v$MULTI_VERSION.bin\e[0m\n";
|
printf "\e[33;1mBuilding mm-avr-txflash-aetr-CC2500-inv-v$MULTI_VERSION.bin\e[0m\n";
|
||||||
opt_disable $ALL_PROTOCOLS;
|
opt_disable $ALL_PROTOCOLS;
|
||||||
opt_enable $CC2500_PROTOCOLS;
|
opt_enable $CC2500_PROTOCOLS;
|
||||||
opt_disable HITEC_CC2500_INO REDPINE_CC2500_INO OMP_CC2500_INO SKYARTEC_CC2500_INO SCANNER_CC2500_INO FRSKYL_CC2500_INO RLINK_CC2500_INO;
|
opt_disable HITEC_CC2500_INO REDPINE_CC2500_INO OMP_CC2500_INO SKYARTEC_CC2500_INO SCANNER_CC2500_INO FRSKYL_CC2500_INO;
|
||||||
buildMulti;
|
buildMulti;
|
||||||
exitcode=$((exitcode+$?));
|
exitcode=$((exitcode+$?));
|
||||||
mv build/Multiprotocol.ino.bin ./binaries/mm-avr-txflash-aetr-CC2500-inv-v$MULTI_VERSION.bin;
|
mv build/Multiprotocol.ino.bin ./binaries/mm-avr-txflash-aetr-CC2500-inv-v$MULTI_VERSION.bin;
|
||||||
|
|||||||
@@ -1,670 +0,0 @@
|
|||||||
# XBM-37 Quad SPI Capture Analysis
|
|
||||||
|
|
||||||
**Manufacturer:** T-Smart
|
|
||||||
**Model:** XBM-37 (toy quadcopter)
|
|
||||||
**TX/RX RF Chip:** SV7241A (QFN-20, NRF24L01+ clone / BK2425 derivative)
|
|
||||||
**Protocol Basis:** Closely related to FQ777 (same RF chip family, same bind address, same ssv ESB air encoding)
|
|
||||||
**Capture Tool:** Logic analyzer – digital (02a) and SPI-decoded (all "b" files)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
|
|
||||||
1. [Capture File Inventory](#1-capture-file-inventory)
|
|
||||||
2. [Key Protocol Parameters](#2-key-protocol-parameters)
|
|
||||||
3. [SPI Initialization Sequence](#3-spi-initialization-sequence)
|
|
||||||
4. [Bind Sequence – Deep Analysis (02a + 02b)](#4-bind-sequence--deep-analysis-02a--02b)
|
|
||||||
5. [Bind vs No-RX Comparison (01b vs 02b)](#5-bind-vs-no-rx-comparison-01b-vs-02b)
|
|
||||||
6. [Normal Data Packet Format](#6-normal-data-packet-format)
|
|
||||||
7. [Per-Channel Control Analysis (03b – 24b)](#7-per-channel-control-analysis-03b--24b)
|
|
||||||
8. [RF Timing Summary](#8-rf-timing-summary)
|
|
||||||
9. [MPM Implementation Notes](#9-mpm-implementation-notes)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. Capture File Inventory
|
|
||||||
|
|
||||||
All captures are located in `Captures_XBM-37/`. The **"b" files** are SPI-decoded exports
|
|
||||||
(columns: `Time [s], Packet ID, MOSI, MISO`). The **"a" file** is the raw digital export
|
|
||||||
(columns: `Time[s], MOSI, MISO, SCK, CSN, CE, IRQ`).
|
|
||||||
|
|
||||||
| File | Type | Description | SPI Transactions | TX Payloads | Duration |
|
|
||||||
|------|------|-------------|-----------------|-------------|----------|
|
|
||||||
| `01b-XBM-37_Quad_TX-PowerOn-NoRX.csv` | SPI | TX power-on, **no RX present** | 5,437 | 1,352 | 2.963 s |
|
|
||||||
| `02a-XBM-37_Quad_TX-PowerOn-withRX-Bind.csv` | **Digital** | TX power-on + bind **with RX** (all 6 lines) | 405,271 samples | 1,345 payloads | 4.380 s |
|
|
||||||
| `02b-XBM-37_Quad_TX-PowerOn-withRX-Bind.csv` | SPI | TX power-on + bind **with RX** | 5,409 | 1,345 | 2.949 s |
|
|
||||||
| `03b-XBM-37_Quad_Aileron-Center-Left-Center-Right-Center.csv` | SPI | Aileron stick: center → left → center → right → center | 6,039 | 1,509 | 3.127 s |
|
|
||||||
| `04b-XBM-37_Quad_Elevator-Center-Back-Center-Forward-Center.csv` | SPI | Elevator stick: center → back → center → fwd → center | 6,035 | 1,509 | 3.123 s |
|
|
||||||
| `05b-XBM-37_Quad_Throttle-Low-High-Low.csv` | SPI | Throttle: low → high → low | 6,034 | 1,509 | 3.122 s |
|
|
||||||
| `06b-XBM-37_Quad_Rudder-Center-Left-Center-Right-Center.csv` | SPI | Rudder (yaw): center → left → center → right → center | 6,034 | 1,509 | 3.122 s |
|
|
||||||
| `07b-XBM-37_Quad_RateModeSwitch-1-2-3.csv` | SPI | Rate/speed mode switch: 1 → 2 → 3 | 6,034 | 1,509 | 3.122 s |
|
|
||||||
| `08b-XBM-37_Quad_FlipSwitch-PushButton_Off-On.csv` | SPI | Flip trick button: off → on | 6,034 | 1,509 | 3.122 s |
|
|
||||||
| `09b-XBM-37_Quad_VideoSwitch-Off-On-Off-On.csv` | SPI | Video record toggle: off → on → off → on | 6,023 | 1,506 | 3.116 s |
|
|
||||||
| `10b-XBM-37_Quad_PictureSwitch-PushButton-3X.csv` | SPI | Photo/picture button: pressed 3 times | 6,019 | 1,505 | 3.113 s |
|
|
||||||
| `11b-XBM-37_Quad_HeadlessSwitch-PushButton-Off-On.csv` | SPI | Headless mode button: off → on | 6,022 | 1,506 | 3.116 s |
|
|
||||||
| `12b-XBM-37_Quad_ReturnToHomeSwitch-PushButton-Off-On.csv` | SPI | RTH button: off → on | 6,034 | 1,508 | 3.127 s |
|
|
||||||
| `13b-XBM-37_Quad_LED-LightsSwitch-PushButton-On-Off.csv` | SPI | LED lights toggle: on → off | 6,019 | 1,505 | 3.113 s |
|
|
||||||
| `14b-XBM-37_Quad_OK-Switch-PushButton-Off-On.csv` | SPI | OK button: off → on | 6,027 | 1,507 | 3.120 s |
|
|
||||||
| `20b-XBM-37_Quad_Elevator-Trim-Center-Forward-Max_32-Clicks.csv` | SPI | Elevator trim: center → forward max (32 clicks) | 38,683 | 9,671 | 20.004 s |
|
|
||||||
| `21b-XBM-37_Quad_Elevator-Trim-Center-Back-Max_31-Clicks.csv` | SPI | Elevator trim: center → back max (31 clicks) | 33,215 | 8,304 | 17.191 s |
|
|
||||||
| `22b-XBM-37_Quad_Aileron-Trim-Center-Left-Max_32-Clicks.csv` | SPI | Aileron trim: center → left max (32 clicks) | 32,315 | 8,079 | 16.730 s |
|
|
||||||
| `23b-XBM-37_Quad_Aileron-Trim-Center-Right-Max_31-Clicks.csv` | SPI | Aileron trim: center → right max (31 clicks) | 28,495 | 7,124 | 14.756 s |
|
|
||||||
| `24b-XBM-37_Quad_Ail-Trim-Forward-Max_Ele-Trim-Right-Max_Push-OK-Button-2X.csv` | SPI | Elevator trim at forward max, aileron trim at right max, OK button pressed 2× | 29,275 | 7,319 | 15.176 s |
|
|
||||||
|
|
||||||
### Notes
|
|
||||||
- The "b" SPI files each contain one SPI byte per row. Multiple rows sharing the same `Packet ID` belong to one CSN-low SPI transaction.
|
|
||||||
- Files 03b–24b were all captured in **normal (post-bind) flight mode**. The TX had previously
|
|
||||||
completed a successful bind.
|
|
||||||
- File 01b and 02b are functionally **identical** captures (confirmed by direct payload comparison)
|
|
||||||
except for a tiny time offset (~7 µs between corresponding packets). This confirms the TX
|
|
||||||
transmits identically whether or not an RX is present; see Section 5.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. Key Protocol Parameters
|
|
||||||
|
|
||||||
| Parameter | Value |
|
|
||||||
|-----------|-------|
|
|
||||||
| RF transceiver chip | SV7241A (QFN-20, NRF24L01+ / BK2425 derivative) |
|
|
||||||
| RF frequency band | 2.4 GHz ISM |
|
|
||||||
| Air data rate (SV7241A) | 2 Mbps (RF_SETUP = 0x26, bit5 = RF_DR = 1) |
|
|
||||||
| Air data rate (nRF24L01+ equivalent) | **250 kbps** via `ssv_pack_dpl()` method |
|
|
||||||
| Packet size (raw, pre-pack) | 8 bytes |
|
|
||||||
| Packet size (after ssv_pack_dpl) | 12 bytes |
|
|
||||||
| Enhanced ShockBurst | Yes (dynamic payload length, no auto-ACK) |
|
|
||||||
| SPI clock frequency | ~143 kHz (7 µs period) |
|
|
||||||
| Bind packet count | **400** |
|
|
||||||
| Bind address (broadcast) | `E7 E7 E7 E7 67` |
|
|
||||||
| Data address format | `[TX_ID₀ TX_ID₁ TX_ID₂ E7 67]` |
|
|
||||||
| Bind channel (first packet) | 0x00 (universal) |
|
|
||||||
| Hop channels (bind + data) | **0x49, 0x34, 0x26, 0x07** (4 channels) |
|
|
||||||
| Packet period (steady state) | **~2,070 µs** (~2.07 ms) |
|
|
||||||
| CE high pulse width | ~1,172 µs |
|
|
||||||
| CE low gap (inter-packet) | ~896 µs |
|
|
||||||
| TX-only mode | Yes — EN_RXADDR = 0x00; TX never listens |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. SPI Initialization Sequence
|
|
||||||
|
|
||||||
The sequence below is from `02b` (PIDs 0–24), occurring over the first ~5 ms after the SPI
|
|
||||||
bus becomes active (~150–335 ms after TX power-on due to startup delays).
|
|
||||||
|
|
||||||
### 3.1 SV7241A Private Bank Registers
|
|
||||||
|
|
||||||
The SV7241A (like BK2425) has bank-switched extended registers at addresses 0x18–0x1B.
|
|
||||||
Register 0x1F selects the bank. These registers hold RF/analog calibration constants specific
|
|
||||||
to the chip and **do not exist on nRF24L01+** — they are ignored when implementing with MPM.
|
|
||||||
|
|
||||||
| PID | Register | Data Written | Purpose |
|
|
||||||
|-----|----------|-------------|---------|
|
|
||||||
| 0 | 0x1F | `00` | Select bank 0 |
|
|
||||||
| 1 | 0x1B | `10 E1 D3 3D` | Bank 0 – RF calibration reg 1 |
|
|
||||||
| 2 | 0x19 | `06 AA A2 DB` | Bank 0 – RF calibration reg 2 |
|
|
||||||
| 3 | 0x1F | `01` | Select bank 1 |
|
|
||||||
| 4 | 0x19 | `77 48 9A E8` | Bank 1 – internal reg |
|
|
||||||
| 5 | 0x1B | `76 87 CA 01` | Bank 1 – internal reg |
|
|
||||||
| 6 | 0x1F | `02` | Select bank 2 |
|
|
||||||
| 7 | 0x1B | `A0 00 18 A0` | Bank 2 – internal reg |
|
|
||||||
| 8 | 0x1F | `04` | Select bank 4 |
|
|
||||||
| 9 | 0x18 | `01 00 F0 00` | Bank 4 – internal reg |
|
|
||||||
| 10 | 0x1F | `05` | Select bank 5 |
|
|
||||||
| 11 | 0x18 | `84 03 2A 03` | Bank 5 – internal reg |
|
|
||||||
| 12 | 0x19 | `90 BF 00 00` | Bank 5 – internal reg |
|
|
||||||
| 13 | 0x1A | `A0 0F 00 00` | Bank 5 – internal reg |
|
|
||||||
|
|
||||||
### 3.2 Standard NRF24L01-Compatible Registers
|
|
||||||
|
|
||||||
Written immediately after the private registers (PIDs 14–24):
|
|
||||||
|
|
||||||
| PID | Register | Written Value | Decoded Meaning |
|
|
||||||
|-----|----------|--------------|-----------------|
|
|
||||||
| 14 | CONFIG (0x00) | `0x0C` | EN_CRC=1, CRCO=1 (2-byte CRC), PWR_UP=0, PRIM_RX=0 (TX) |
|
|
||||||
| 15 | CONFIG (0x00) | *read back* `0x0C` | Verify CONFIG |
|
|
||||||
| 16 | TX_ADDR (0x10) | `E7 E7 E7 E7 67` | Bind broadcast address |
|
|
||||||
| 17 | RX_ADDR_P0 (0x0A) | `E7 E7 E7 E7 67` | Matches TX_ADDR for bind |
|
|
||||||
| 18 | EN_AA (0x01) | `0x00` | Auto-ACK **disabled** on all pipes |
|
|
||||||
| 19 | EN_RXADDR (0x02) | `0x00` | All RX pipes **disabled** – TX only |
|
|
||||||
| 20 | RF_CH (0x05) | `0x49` | Initial RF channel (73 MHz offset) |
|
|
||||||
| 21 | FEATURE (0x1D) | `0x04` | EN_DPL = 1 (dynamic payload length) |
|
|
||||||
| 22 | DYNPD (0x1C) | `0x01` | DPL enabled on pipe 0 |
|
|
||||||
| 23 | RF_SETUP (0x06) | `0x26` | SV7241A: 2 Mbps, max power |
|
|
||||||
| 24 | CONFIG (0x00) | `0x0E` | PWR_UP=1 → TX powered up |
|
|
||||||
|
|
||||||
**RF_SETUP = 0x26 mapping:**
|
|
||||||
|
|
||||||
| Chip | Bit 5 meaning | Value 0x26 decodes as |
|
|
||||||
|------|--------------|----------------------|
|
|
||||||
| SV7241A | RF_DR (0=1Mbps, 1=2Mbps) | **2 Mbps**, max power |
|
|
||||||
| nRF24L01+ | RF_DR_LOW (0=normal, 1=250kbps) | **250 kbps**, max power |
|
|
||||||
|
|
||||||
→ On nRF24L01+, writing 0x26 would set **250 kbps** (not 2 Mbps). For MPM emulation the
|
|
||||||
correct approach (same as FQ777) is `NRF24L01_SetBitrate(NRF24L01_BR_250K)` combined with
|
|
||||||
`ssv_pack_dpl()` to produce a compatible air packet.
|
|
||||||
|
|
||||||
**Startup timing:**
|
|
||||||
|
|
||||||
The TX power-on to first SPI transaction takes ~150 ms (CE is held high from
|
|
||||||
t = –72 ms until t = 0, then the ~150 ms wait elapses before SPI activity at t ≈ +181 ms in the
|
|
||||||
02b file). The entire init register sequence completes in ~6 ms.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. Bind Sequence – Deep Analysis (02a + 02b)
|
|
||||||
|
|
||||||
### 4.1 Overview
|
|
||||||
|
|
||||||
After the ~150 ms startup wait, the TX sends exactly **400 bind packets** before switching to
|
|
||||||
normal data mode.
|
|
||||||
|
|
||||||
| Property | Value |
|
|
||||||
|----------|-------|
|
|
||||||
| Total bind packets | **400** |
|
|
||||||
| Bind address | `E7 E7 E7 E7 67` (fixed broadcast) |
|
|
||||||
| First bind packet channel | `0x00` (universal channel) |
|
|
||||||
| Remaining 399 bind packet channels | Cycling: `0x49 → 0x34 → 0x26 → 0x07 → 0x49 → …` |
|
|
||||||
| Bind packet payload | `20 14 07 03 TX_ID₀ TX_ID₁ TX_ID₂ CKSUM` |
|
|
||||||
| Bind packet content | Identical across all 400 transmissions |
|
|
||||||
|
|
||||||
The first bind packet is sent on RF channel **0x00**, ensuring a newly powered-on RX (sitting
|
|
||||||
on its default channel) can hear the bind announcement regardless of any prior state. Subsequent
|
|
||||||
bind packets cycle through the four data-hopping channels.
|
|
||||||
|
|
||||||
### 4.2 Bind Packet Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
Byte 0 1 2 3 4 5 6 7
|
|
||||||
[20 14 07 03 TX_ID₀ TX_ID₁ TX_ID₂ CKSUM]
|
|
||||||
```
|
|
||||||
|
|
||||||
| Byte | Value (this TX) | Description |
|
|
||||||
|------|----------------|-------------|
|
|
||||||
| B0 | `0x20` | Bind identifier byte (constant — marks this as a bind packet) |
|
|
||||||
| B1 | `0x14` | Protocol variant constant (XBM-37 specific; FQ777 uses `0x15`) |
|
|
||||||
| B2 | `0x07` | Protocol variant constant (XBM-37 specific; FQ777 uses `0x05`) |
|
|
||||||
| B3 | `0x03` | Protocol variant constant (XBM-37 specific; FQ777 uses `0x06`) |
|
|
||||||
| B4 | `0x91` | TX_ID byte 0 — unique per TX unit |
|
|
||||||
| B5 | `0x05` | TX_ID byte 1 — unique per TX unit |
|
|
||||||
| B6 | `0x05` | TX_ID byte 2 — unique per TX unit |
|
|
||||||
| B7 | `0x9B` | Checksum = (TX_ID₀ + TX_ID₁ + TX_ID₂) & 0xFF = (0x91+0x05+0x05) & 0xFF |
|
|
||||||
|
|
||||||
**Checksum formula for bind packet:** `B7 = (B4 + B5 + B6) & 0xFF`
|
|
||||||
(This differs from the data packet checksum which sums B0–B6.)
|
|
||||||
|
|
||||||
### 4.3 TX ID
|
|
||||||
|
|
||||||
TX ID is **3 bytes** embedded in B4–B6 of the bind packet. This TX unit has:
|
|
||||||
|
|
||||||
```
|
|
||||||
TX_ID = [0x91, 0x05, 0x05]
|
|
||||||
```
|
|
||||||
|
|
||||||
After bind, the TX_ADDR is set to: `[TX_ID₀ TX_ID₁ TX_ID₂ 0xE7 0x67]`
|
|
||||||
= `[91 05 05 E7 67]`
|
|
||||||
|
|
||||||
The RX extracts TX_ID from the bind packet and uses it to construct the matching address for
|
|
||||||
normal data reception.
|
|
||||||
|
|
||||||
### 4.4 Bind Channel Sequence (from 02b SPI decoded)
|
|
||||||
|
|
||||||
```
|
|
||||||
Packet #1: ch=0x00 [20 14 07 03 91 05 05 9B] ← universal announce
|
|
||||||
Packet #2: ch=0x49 [20 14 07 03 91 05 05 9B]
|
|
||||||
Packet #3: ch=0x34 [20 14 07 03 91 05 05 9B]
|
|
||||||
Packet #4: ch=0x26 [20 14 07 03 91 05 05 9B]
|
|
||||||
Packet #5: ch=0x07 [20 14 07 03 91 05 05 9B]
|
|
||||||
Packet #6: ch=0x49 [20 14 07 03 91 05 05 9B]
|
|
||||||
...continues cycling 0x49→0x34→0x26→0x07...
|
|
||||||
Packet #400: ch=0x26 [20 14 07 03 91 05 05 9B] ← last bind
|
|
||||||
```
|
|
||||||
|
|
||||||
Channel usage across all 400 bind packets:
|
|
||||||
|
|
||||||
| Channel | Count | Notes |
|
|
||||||
|---------|-------|-------|
|
|
||||||
| 0x00 | 1 | First packet only |
|
|
||||||
| 0x49 (73 MHz) | 100 | Regular cycle |
|
|
||||||
| 0x34 (52 MHz) | 100 | Regular cycle |
|
|
||||||
| 0x26 (38 MHz) | 100 | Regular cycle (includes last bind packet) |
|
|
||||||
| 0x07 (7 MHz) | 99 | Regular cycle |
|
|
||||||
|
|
||||||
### 4.5 Bind-to-Normal Transition
|
|
||||||
|
|
||||||
After the 400th bind packet the TX:
|
|
||||||
|
|
||||||
1. Completes the 400th transmission (CE pulse ~1,172 µs, then CE low).
|
|
||||||
2. Waits **~16.6 ms** (no SPI activity; firmware processing time).
|
|
||||||
3. Writes the new TX_ADDR: `W_TX_ADDR [91 05 05 E7 67]` (SPI pid=1625 at t=1.175882 s).
|
|
||||||
4. Immediately clears STATUS and starts normal data mode.
|
|
||||||
5. First normal packet: ch=**0x07** (continuation of the hop sequence from where bind ended).
|
|
||||||
|
|
||||||
```
|
|
||||||
Last bind (400th): t=1.159258 s, ch=0x26
|
|
||||||
TX_ADDR change: t=1.175882 s (+16.6 ms gap)
|
|
||||||
First data packet: t=1.176619 s, ch=0x07 [E1 70 70 70 20 20 00 71]
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.6 IRQ / STATUS Analysis (from 02a Digital Capture)
|
|
||||||
|
|
||||||
The IRQ line (active-low) is asserted by the SV7241A for every successfully transmitted packet
|
|
||||||
(TX_DS interrupt):
|
|
||||||
|
|
||||||
| Observation | Value |
|
|
||||||
|-------------|-------|
|
|
||||||
| Total IRQ assertions | 1,340 (matching 1,340 normal CE pulses) |
|
|
||||||
| IRQ pulse duration (typical) | ~600 µs |
|
|
||||||
| IRQ source | TX_DS only (TX complete) |
|
|
||||||
| RX_DR interrupts | **Zero** — no data ever received |
|
|
||||||
|
|
||||||
The SPI confirms there are **no `R_RX_PAYLOAD` (0x61) commands** in either 01b or 02b.
|
|
||||||
Combined with `EN_RXADDR = 0x00` (all RX pipes disabled), it is impossible for the TX to
|
|
||||||
receive data from the RX. This is confirmed by the STATUS register never showing bit6
|
|
||||||
(RX_DR) = 1.
|
|
||||||
|
|
||||||
One extended IRQ assertion of **15.9 ms** occurs at t=1.160476 s (immediately after the 400th
|
|
||||||
bind packet). This is not an RX event — it is simply the TX_DS interrupt remaining uncleared
|
|
||||||
while the firmware processes the bind-completion event and updates TX_ADDR. The IRQ is
|
|
||||||
cleared when `W_STATUS [70]` is written at t=1.176254 s (pid=1626).
|
|
||||||
|
|
||||||
### 4.7 CE Pulse Timing (from 02a)
|
|
||||||
|
|
||||||
| Measurement | Value |
|
|
||||||
|-------------|-------|
|
|
||||||
| Normal CE pulse duration | min 1,165 µs, max 1,178 µs, **avg 1,172 µs** |
|
|
||||||
| CE inter-pulse gap (end to start) | **~896 µs** |
|
|
||||||
| Total cycle (CE high + gap) | **~2,068 µs** |
|
|
||||||
| Pulse-to-pulse interval (high to high) | min 2.063 ms, max 20.686 ms, **avg 2.084 ms** |
|
|
||||||
|
|
||||||
The 20.686 ms outlier corresponds to the bind-to-normal transition pause (~16.6 ms).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. Bind vs No-RX Comparison (01b vs 02b)
|
|
||||||
|
|
||||||
**Finding: The TX transmits identically whether or not an RX is present.**
|
|
||||||
|
|
||||||
| Metric | 01b (No RX) | 02b (With RX) |
|
|
||||||
|--------|------------|----------------|
|
|
||||||
| Total TX payloads | 1,352 | 1,345 |
|
|
||||||
| Bind packets | 400 | 400 |
|
|
||||||
| Bind packet content | `20 14 07 03 91 05 05 9B` | `20 14 07 03 91 05 05 9B` (identical) |
|
|
||||||
| TX_ADDR change time | t=1.175899 s | t=1.175882 s |
|
|
||||||
| TX_ADDR after bind | `[91 05 05 E7 67]` | `[91 05 05 E7 67]` (identical) |
|
|
||||||
| Normal data payload (idle) | `E1 70 70 70 20 20 00 71` | `E1 70 70 70 20 20 00 71` (identical) |
|
|
||||||
| Time offset between captures | — | ~7 µs per packet |
|
|
||||||
|
|
||||||
The TX performs an automatic timed bind sequence (400 packets) and then switches to data mode
|
|
||||||
unconditionally, regardless of RX acknowledgment. The TX **never knows** whether the RX
|
|
||||||
accepted the bind. Bind is one-sided: the RX passively listens for the bind packet on ch=0x00
|
|
||||||
(or the cycling channels), extracts the TX_ID and hop channels, and then follows the TX's
|
|
||||||
normal data transmissions.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. Normal Data Packet Format
|
|
||||||
|
|
||||||
### 6.1 Packet Structure (8 bytes)
|
|
||||||
|
|
||||||
```
|
|
||||||
Byte 0 1 2 3 4 5 6 7
|
|
||||||
[Throttle Rudder Aileron Elevator Flags1 Flags2 Flags3 CKSUM]
|
|
||||||
```
|
|
||||||
|
|
||||||
**Checksum (B7):** `B7 = (B0 + B1 + B2 + B3 + B4 + B5 + B6) & 0xFF`
|
|
||||||
|
|
||||||
All 8-byte checksum values have been verified against this formula across all capture files.
|
|
||||||
|
|
||||||
### 6.2 Stick Channels (B0–B3)
|
|
||||||
|
|
||||||
| Byte | Channel | Min | Center | Max | Notes |
|
|
||||||
|------|---------|-----|--------|-----|-------|
|
|
||||||
| B0 | Throttle | `0xE1` | `0x70` | `0x00` | Non-return throttle |
|
|
||||||
| B1 | Rudder (Yaw) | `0x00` | `0x70` | `0xE1` | |
|
|
||||||
| B2 | Aileron (Roll) | `0xE1` | `0x70` | `0x00` | |
|
|
||||||
| B3 | Elevator (Pitch) | `0xE1` | `0x70` | `0x00` | |
|
|
||||||
|
|
||||||
All analog channels use the same range: **0x00 – 0xE1** (0 – 225 decimal) with center at
|
|
||||||
**0x70** (112 decimal).
|
|
||||||
- Throttle, Aileron, and Elevator use reversed state (0xE1...0x70...0x00).
|
|
||||||
|
|
||||||
### 6.3 Flags Byte 1 (B4)
|
|
||||||
|
|
||||||
| Value | Meaning | Description |
|
|
||||||
|-------|---------|-------------|
|
|
||||||
| `0x20` | **Trim Elevator Center** | Resets at TX start |
|
|
||||||
| `0x21 up to 0x40` | Trim elevator **forward** | 32 Clicks to max |
|
|
||||||
| `0x1F downto 0x01` | Trim elevator **back** | 31 Clicks to max |
|
|
||||||
|
|
||||||
### 6.4 Flags Byte 2 (B5)
|
|
||||||
|
|
||||||
| Value | Meaning | Description |
|
|
||||||
|-----|------|-------------|
|
|
||||||
| `0x20` | **Trim Aileron Center** | Resets at TX start |
|
|
||||||
| `0x21 up to 0x40` | Trim aileron **left** | 32 Clicks to max |
|
|
||||||
| `0x1F down to 0x01` | Trim aileron **right** | 31 Clicks to max |
|
|
||||||
| `0x80` | OK button | OK pressed (`0x20` → `0xA0`) |
|
|
||||||
|
|
||||||
`B5 bit7` is an OR mask on top of trim value (`B5_with_OK = B5_trim | 0x80`), e.g.
|
|
||||||
center `0x20 -> 0xA0`, right-max `0x01 -> 0x81`.
|
|
||||||
|
|
||||||
### 6.5 Flags Byte 3 (B6)
|
|
||||||
|
|
||||||
| Bits | Mask | Name | Description |
|
|
||||||
|------|------|------|-------------|
|
|
||||||
| [1:0] | `0x03` | Rate mode | `0x00`=rate 1 (slow), `0x01`=rate 2, `0x02`=rate 3 (fast) |
|
|
||||||
| 2 | `0x04` | LED off | `0`=LED lights ON, `1`=LED lights OFF |
|
|
||||||
| 3 | `0x08` | RTH | `1`=return-to-home active |
|
|
||||||
| 4 | `0x10` | Headless | `1`=headless mode active |
|
|
||||||
| 5 | `0x20` | Video | `1`=video recording active |
|
|
||||||
| 6 | `0x40` | Picture | `1`=photo capture triggered |
|
|
||||||
| 7 | `0x80` | Flip | `1`=3D flip command |
|
|
||||||
|
|
||||||
Normal state: `B6 = 0x00` (rate 1, LED on, no special modes)
|
|
||||||
|
|
||||||
### 6.6 Return-to-Home (RTH)
|
|
||||||
|
|
||||||
Updated analysis of **file 12b** (RTH OFF in first half, ON in second half):
|
|
||||||
|
|
||||||
- RTH-OFF payload is steady at `7E 70 70 70 20 20 00 0E`.
|
|
||||||
- After the OFF→ON transition, the payload changes to `7E 70 70 70 20 20 08 16`.
|
|
||||||
- The persistent functional change in this capture is `B6: 0x00 -> 0x08`
|
|
||||||
(bit3 asserted when RTH is ON).
|
|
||||||
|
|
||||||
In this export, RTH is represented in the steady 8-byte payload by `B6 bit3`.
|
|
||||||
|
|
||||||
### 6.7 Example Payloads
|
|
||||||
|
|
||||||
| Payload | Meaning |
|
|
||||||
|---------|---------|
|
|
||||||
| `E1 70 70 70 20 20 00 71` | Throttle low `0xE1`, all sticks center `0x70`, LED on, no special modes `0x00` |
|
|
||||||
| `82 70 70 70 20 20 00 12` | Throttle ~mid `0x82`, all sticks center, LED on, no special modes |
|
|
||||||
| `00 70 70 70 20 20 00 90` | Throttle max `0x00`, all sticks center, LED on, no special modes |
|
|
||||||
| `E1 70 00 70 20 20 00 01` | Throttle low, aileron full right `0x00`, LED on, no special modes |
|
|
||||||
| `E1 70 E1 70 20 20 00 E2` | Throttle low, aileron full left `0xE1`, LED on, no special modes |
|
|
||||||
| `E1 70 70 00 20 20 00 01` | Throttle low, elevator full back `0x00`,LED on, no special modes |
|
|
||||||
| `82 70 70 70 20 20 80 92` | Throttle ~mid, all sticks center, flip command active `0x80` |
|
|
||||||
| `82 70 70 70 20 20 10 22` | Throttle ~mid, all sticks center, headless mode active `0x10` |
|
|
||||||
| `82 70 70 70 20 20 01 13` | Throttle ~mid, all sticks center, rate mode 2 `0x01` |
|
|
||||||
| `82 70 70 70 20 20 02 14` | Throttle ~mid, all sticks center, rate mode 3 `0x02` |
|
|
||||||
| `00 70 70 70 20 A0 00 F1` | Throttle max, all sticks center, OK button pressed `0xA0` |
|
|
||||||
| `00 70 70 70 20 20 04 75` | Throttle max, all sticks center, LED lights OFF `0x04` |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. Per-Channel Control Analysis (03b – 24b)
|
|
||||||
|
|
||||||
All control captures were taken in post-bind normal mode. Hopping channels confirmed active:
|
|
||||||
`0x07, 0x49, 0x34, 0x26` (cyclic). Average packet interval: **~2.07 ms** across all files.
|
|
||||||
|
|
||||||
### 03b – Aileron (Roll)
|
|
||||||
|
|
||||||
- **Affected byte:** B2
|
|
||||||
- Range observed: `0xE1` (full left) → `0x70` (center) → `0x00` (full right)
|
|
||||||
|
|
||||||
### 04b – Elevator (Pitch)
|
|
||||||
|
|
||||||
- **Affected byte:** B3
|
|
||||||
- Range observed: `0x00` (full back) → `0x70` (center) → `0xE1` (full forward)
|
|
||||||
|
|
||||||
### 05b – Throttle
|
|
||||||
|
|
||||||
- **Affected byte:** B0
|
|
||||||
- Range observed: `0xE1` (low minimum) ↔ `0x70` (center) ↔ `0x00` (full maximum)
|
|
||||||
- Non-return throttle (stick does not spring back to center)
|
|
||||||
|
|
||||||
### 06b – Rudder (Yaw)
|
|
||||||
|
|
||||||
- **Affected byte:** B1
|
|
||||||
- Range observed: `0x00` (full left) → `0x70` (center) → `0xE1` (full right)
|
|
||||||
- Note: B0 (throttle) also varies in this capture because left stick controls both
|
|
||||||
throttle (up/down) and rudder (left/right) Mode 2 transmitter
|
|
||||||
|
|
||||||
### 07b – Rate Mode Switch
|
|
||||||
|
|
||||||
- **Affected byte:** B6 bits[1:0]
|
|
||||||
- `B6 = 0x00`: Rate 1 (slowest/beginner)
|
|
||||||
- `B6 = 0x01`: Rate 2 (intermediate)
|
|
||||||
- `B6 = 0x02`: Rate 3 (fastest/expert)
|
|
||||||
|
|
||||||
### 08b – Flip Switch
|
|
||||||
|
|
||||||
- **Affected byte:** B6 bit7
|
|
||||||
- `B6 = 0x00`: No flip; `B6 = 0x80`: 3D flip command active
|
|
||||||
- While flip is held: throttle (B0) increments slightly (`0x82` → `0x83`)
|
|
||||||
|
|
||||||
### 09b – Video Switch
|
|
||||||
|
|
||||||
- **Affected byte:** B6 bit5
|
|
||||||
- `B6 = 0x00`: Video off; `B6 = 0x20`: Video recording active
|
|
||||||
- Toggle on/off: transitions between these two states
|
|
||||||
|
|
||||||
### 10b – Picture Switch (3×)
|
|
||||||
|
|
||||||
- **Affected byte:** B6 bit6
|
|
||||||
- `B6 = 0x00`: Idle; `B6 = 0x40`: Photo capture triggered (momentary)
|
|
||||||
|
|
||||||
### 11b – Headless Switch
|
|
||||||
|
|
||||||
- **Affected byte:** B6 bit4
|
|
||||||
- `B6 = 0x00`: Headless off; `B6 = 0x10`: Headless mode active
|
|
||||||
|
|
||||||
### 12b – Return to Home Switch
|
|
||||||
|
|
||||||
- **Capture split tested:** first half RTH OFF, second half RTH ON.
|
|
||||||
- **RTH OFF payload:** `7E 70 70 70 20 20 00 0E`
|
|
||||||
- **RTH ON payload:** `7E 70 70 70 20 20 08 16`
|
|
||||||
- **Primary byte change:** `B6: 0x00 -> 0x08`
|
|
||||||
- `B6 bit3` is asserted when RTH is active in this capture
|
|
||||||
- **Minor secondary variation while ON:** `B0` occasionally increments `0x7E -> 0x7F`,
|
|
||||||
producing checksum `0x16 -> 0x17`
|
|
||||||
- All other payload bytes remain unchanged across the OFF→ON transition in this file.
|
|
||||||
|
|
||||||
### 13b – LED Lights Switch
|
|
||||||
|
|
||||||
- **Affected byte:** B6 bit2
|
|
||||||
- `B6 = 0x00`: LED lights **ON** (default)
|
|
||||||
- `B6 = 0x04`: LED lights **OFF**
|
|
||||||
- Note: Inverted logic — bit2=1 means OFF
|
|
||||||
|
|
||||||
### 14b – OK Switch
|
|
||||||
|
|
||||||
- **Affected byte:** B5 bit7
|
|
||||||
- `B5 = 0x20`: OK button not pressed
|
|
||||||
- `B5 = 0xA0`: OK button pressed (0x20 | 0x80)
|
|
||||||
|
|
||||||
### 20b – Elevator Trim Center → Forward Max (32 clicks)
|
|
||||||
|
|
||||||
- **Affected byte:** B4 (elevator trim)
|
|
||||||
- Observed progression: `0x20 -> ... -> 0x40`
|
|
||||||
- Endpoint in this capture: `B4 = 0x40` (forward max)
|
|
||||||
- `B5` remains `0x20`; `B6` remains `0x00`
|
|
||||||
|
|
||||||
### 21b – Elevator Trim Center → Back Max (31 clicks)
|
|
||||||
|
|
||||||
- **Affected byte:** B4 (elevator trim)
|
|
||||||
- Observed progression: `0x20 -> ... -> 0x01`
|
|
||||||
- Endpoint in this capture: `B4 = 0x01` (back max)
|
|
||||||
- `B5` remains `0x20`; `B6` remains `0x00`
|
|
||||||
|
|
||||||
### 22b – Aileron Trim Center → Left Max (32 clicks)
|
|
||||||
|
|
||||||
- **Affected byte:** B5 (aileron trim)
|
|
||||||
- Observed progression: `0x20 -> ... -> 0x40`
|
|
||||||
- Endpoint in this capture: `B5 = 0x40` (left max)
|
|
||||||
- `B4` remains `0x20`; `B6` remains `0x00`
|
|
||||||
|
|
||||||
### 23b – Aileron Trim Center → Right Max (31 clicks)
|
|
||||||
|
|
||||||
- **Affected byte:** B5 (aileron trim)
|
|
||||||
- Observed progression: `0x20 -> ... -> 0x01`
|
|
||||||
- Endpoint in this capture: `B5 = 0x01` (right max)
|
|
||||||
- `B4` remains `0x20`; `B6` remains `0x00`
|
|
||||||
|
|
||||||
### 24b – Trim Endpoints + OK Button (2 presses)
|
|
||||||
|
|
||||||
- Fixed trim baseline in this capture:
|
|
||||||
- `B4 = 0x40` (elevator forward max)
|
|
||||||
- `B5 trim = 0x01` (aileron right max)
|
|
||||||
- **OK effect:** `B5 bit7` toggles over trim baseline:
|
|
||||||
- not pressed: `B5 = 0x01`
|
|
||||||
- pressed: `B5 = 0x81` (`0x01 | 0x80`)
|
|
||||||
- `B6` remains `0x00` throughout.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8. RF Timing Summary
|
|
||||||
|
|
||||||
### 8.1 Per-Packet SPI Cycle (02b decoded)
|
|
||||||
|
|
||||||
Each packet transmission consists of 4 SPI transactions:
|
|
||||||
|
|
||||||
```
|
|
||||||
1. W_STATUS [27] = 0x70 → Clear TX_DS / MAX_RT / RX_DR interrupt flags
|
|
||||||
2. FLUSH_TX [E1] → Empty TX FIFO
|
|
||||||
3. W_RF_CH [25] = <ch> → Set hop channel
|
|
||||||
4. W_TX_PAYLOAD [A0] = 8B → Write 8-byte payload to TX FIFO
|
|
||||||
[CE pulse ~1,172 µs to transmit]
|
|
||||||
[~896 µs gap before next cycle]
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8.2 Bind Phase Timing
|
|
||||||
|
|
||||||
| Event | Timestamp (02b) |
|
|
||||||
|-------|----------------|
|
|
||||||
| Init register writes complete | t = 0.186 s |
|
|
||||||
| Startup wait completes | t = 0.335 s (~150 ms) |
|
|
||||||
| First bind packet (ch=0x00) | t = 0.335838 s |
|
|
||||||
| 400th (last) bind packet (ch=0x26) | t = 1.159258 s |
|
|
||||||
| TX_ADDR change to data address | t = 1.175882 s (+16.6 ms) |
|
|
||||||
| First normal data packet | t = 1.176619 s |
|
|
||||||
|
|
||||||
Total bind phase duration: **~0.824 s** (150 ms wait + ~674 ms for 400 packets at 2.07 ms each)
|
|
||||||
|
|
||||||
### 8.3 Normal Data Phase Timing
|
|
||||||
|
|
||||||
| Event | Interval |
|
|
||||||
|-------|---------|
|
|
||||||
| Packet 1 → 2 (startup) | 0.918 ms |
|
|
||||||
| Packet 2 → 3 (startup) | 0.916 ms |
|
|
||||||
| Packet 3 → 4 (startup) | 1.491 ms |
|
|
||||||
| Steady state (4+) | **~2.070 ms** per packet |
|
|
||||||
|
|
||||||
The first 3 packets after bind-to-data transition have shorter intervals, then settle into the
|
|
||||||
steady 2.07 ms period.
|
|
||||||
|
|
||||||
### 8.4 STATUS Byte Values Observed
|
|
||||||
|
|
||||||
| STATUS | Meaning | When seen |
|
|
||||||
|--------|---------|-----------|
|
|
||||||
| `0x0E` | TX FIFO not full, RX FIFO empty, all interrupts clear | Normal/idle |
|
|
||||||
| `0x2E` | TX_DS = 1 (TX complete interrupt), TX FIFO not full | After each TX packet |
|
|
||||||
|
|
||||||
RX_DR (bit6) is **never set** in any STATUS byte — confirming no data is ever received.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 9. MPM Implementation Notes
|
|
||||||
|
|
||||||
### 9.1 Comparison with FQ777
|
|
||||||
|
|
||||||
The XBM-37 protocol is closely related to FQ777 but has the following differences:
|
|
||||||
|
|
||||||
| Property | FQ777 | XBM-37 | Comment|
|
|
||||||
|----------|-------|---------|---------|
|
|
||||||
| Bind count | 1,000 | **400** | works with either |
|
|
||||||
| Bind packet B1 | `0x15` | `0x14` | different |
|
|
||||||
| Bind packet B2 | `0x05` | `0x07` | different |
|
|
||||||
| Bind packet B3 | `0x06` | `0x03` | different |
|
|
||||||
| Hop channels | `4D 43 27 07` | **`49 34 26 07`** | different |
|
|
||||||
| Data range | 0x00–0x64 | **0x00–0xE1** | different |
|
|
||||||
| Bind address | `E7 E7 E7 E7 67` | `E7 E7 E7 E7 67` | (same) |
|
|
||||||
| Checksum method | Sum B0–B6 | Sum B0–B6 | (same) |
|
|
||||||
| Bind checksum | Sum B4–B6 | Sum B4–B6 | (same) |
|
|
||||||
| ssv_pack_dpl encoding | Yes | Yes | (same) |
|
|
||||||
| Air bitrate (nRF24L01+) | 250 kbps | 250 kbps | (same) |
|
|
||||||
|
|
||||||
### 9.2 Required Implementation Constants
|
|
||||||
|
|
||||||
```c
|
|
||||||
static const uint8_t XBM37_bind_addr[] = {0xE7, 0xE7, 0xE7, 0xE7, 0x67};
|
|
||||||
static const uint8_t XBM37_hop_channels[] = {0x49, 0x34, 0x26, 0x07};
|
|
||||||
```
|
|
||||||
|
|
||||||
### 9.3 Bind Packet Builder
|
|
||||||
|
|
||||||
```c
|
|
||||||
// Bind packet (bytes 4–6 = TX ID; B7 = checksum of B4+B5+B6)
|
|
||||||
packet[0] = 0x20;
|
|
||||||
packet[1] = 0x14;
|
|
||||||
packet[2] = 0x07;
|
|
||||||
packet[3] = 0x03;
|
|
||||||
packet[4] = rx_tx_addr[0]; // TX_ID byte 0
|
|
||||||
packet[5] = rx_tx_addr[1]; // TX_ID byte 1
|
|
||||||
packet[6] = rx_tx_addr[2]; // TX_ID byte 2
|
|
||||||
packet[7] = packet[4] + packet[5] + packet[6];
|
|
||||||
```
|
|
||||||
|
|
||||||
### 9.4 Data Packet Builder
|
|
||||||
|
|
||||||
```c
|
|
||||||
packet[0] = convert_channel_16b_limit(THROTTLE, 0xE1, 0x00);
|
|
||||||
packet[1] = convert_channel_16b_limit(RUDDER, 0x00, 0xE1);
|
|
||||||
packet[2] = convert_channel_16b_limit(AILERON, 0xE1, 0x00);
|
|
||||||
packet[3] = convert_channel_16b_limit(ELEVATOR, 0xE1, 0x00);
|
|
||||||
packet[4] = ((convert_channel_8b(CH13) * 63) / 255) + 1; // ele trim (01..20..40)
|
|
||||||
packet[5] = 64 - (((uint32_t)convert_channel_8b(CH14) * 63 + 127) / 255); // ail trim (40..20..01)
|
|
||||||
packet[5] |= GET_FLAG(OK_SW, 0x80); // OK button
|
|
||||||
packet[6] = (rate_mode & 0x03) // bits[1:0] = rate (0/1/2)
|
|
||||||
| GET_FLAG(LED_SW, 0x04) // bit2=1 = LED off
|
|
||||||
| GET_FLAG(RTH_SW, 0x08) // bit3 = RTH
|
|
||||||
| GET_FLAG(HEADLESS_SW, 0x10) // bit4 = headless
|
|
||||||
| GET_FLAG(VIDEO_SW, 0x20) // bit5 = video
|
|
||||||
| GET_FLAG(PHOTO_SW, 0x40) // bit6 = picture
|
|
||||||
| GET_FLAG(FLIP_SW, 0x80); // bit7 = flip
|
|
||||||
packet[7] = 0;
|
|
||||||
for (uint8_t i = 0; i < 7; i++) packet[7] += packet[i]; // checksum
|
|
||||||
```
|
|
||||||
|
|
||||||
### 9.5 Address Management
|
|
||||||
|
|
||||||
```c
|
|
||||||
// TX init:
|
|
||||||
rx_tx_addr[2] = 0x00; // original hardcoded value now changes for model match capability (see below)
|
|
||||||
rx_tx_addr[3] = 0xE7;
|
|
||||||
rx_tx_addr[4] = 0x67;
|
|
||||||
// rx_tx_addr[0] and [1] are random/unique to the TX
|
|
||||||
// rx_tx_addr[2] now varies by changing receiver number (0-63) for model match
|
|
||||||
|
|
||||||
// Bind address (used during bind):
|
|
||||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, XBM37_bind_addr, 5);
|
|
||||||
|
|
||||||
// After 400th bind packet, switch to data address:
|
|
||||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 9.6 RF Init
|
|
||||||
|
|
||||||
```c
|
|
||||||
void XBM37_RF_init() {
|
|
||||||
NRF24L01_Initialize();
|
|
||||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, XBM37_bind_addr, 5);
|
|
||||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // no auto-ACK
|
|
||||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x00); // no RX pipes
|
|
||||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x04); // EN_DPL
|
|
||||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x01); // DPL pipe 0
|
|
||||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250 kbps on nRF24L01+
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 9.7 Air Encoding
|
|
||||||
|
|
||||||
Because both the XBM-37 TX and RX use SV7241A (a BK2425 derivative), the air packet format is
|
|
||||||
the SV7241A Enhanced ShockBurst encoding. When implementing with nRF24L01+, the same
|
|
||||||
`ssv_pack_dpl()` function used in the FQ777 protocol must be applied to convert the raw 8-byte
|
|
||||||
payload into the 12-byte packed representation that nRF24L01+ transmits at 250 kbps to produce
|
|
||||||
a compatible on-air signal.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Analysis completed using Python scripts against the raw CSV captures. All packet checksums,
|
|
||||||
channel sequences, bind counts, and register values verified programmatically.*
|
|
||||||
Reference in New Issue
Block a user