Compare commits

...

24 Commits

Author SHA1 Message Date
Pascal Langer
4f89721cd0 RadioLink: any id
Need to rebind RXs...
2020-09-23 23:42:03 +02:00
Pascal Langer
43c2843490 Update AFHDS2A_a7105.ino 2020-09-23 23:08:26 +02:00
Pascal Langer
c152265284 OMP: doc 2020-09-23 23:05:05 +02:00
Pascal Langer
b591b92b4e Update OMP documentation 2020-09-23 09:41:26 +02:00
Pascal Langer
090388aa1b OMP: improve telemetry 2020-09-22 15:15:14 +02:00
Pascal Langer
c6ab696949 AFHDS2A: fix X6B telemetry issue? 2020-09-21 10:57:19 +02:00
Pascal Langer
df45a3ff83 OMP: prevent telemetry voltage from rolling over 2020-09-21 10:50:01 +02:00
pascallanger
fedd04b724 Update Troubleshooting.md 2020-09-19 21:23:51 +02:00
pascallanger
d8630da09d Update Troubleshooting.md 2020-09-19 20:35:44 +02:00
pascallanger
6192f7287e Update README.md 2020-09-18 17:15:18 +02:00
Pascal Langer
5b8a08ab22 OMP: added telemetry 2020-09-18 16:13:45 +02:00
Ben Lye
313b03fb84 Disable PPM/serial in builds as needed 2020-09-17 10:13:00 +01:00
Pascal Langer
5639def6fb Update DSM FwdPrg.lua 2020-09-15 12:05:26 +02:00
Pascal Langer
15a254879c DSM_RX: bind with other radio modules off 2020-09-15 12:03:16 +02:00
pascallanger
5baa9bd256 Update README.md 2020-09-13 11:34:23 +02:00
Pascal Langer
d5346c0eaf Add DISABLE_FLASH_SIZE_CHECK 2020-09-09 16:47:32 +02:00
Pascal Langer
a2213fd6dc DSM Forward Programming: work in progress 2020-09-09 10:45:14 +02:00
Pascal Langer
9b07f12f90 AFHDS2A: add sub proto 2020-09-08 08:49:38 +02:00
Pascal Langer
c9b49483e0 NanoRF 2020-09-07 22:58:37 +02:00
Pascal Langer
e2972a5823 AFHDS2A: enable 16 channels on SBUS 2020-09-07 20:31:47 +02:00
Pascal Langer
d5b3ed832d Update Multiprotocol.ino 2020-09-04 10:59:31 +02:00
Pascal Langer
9fcc030c15 STM32: test flash size 2020-09-04 10:39:30 +02:00
pascallanger
fc81b7ee5a Update Protocols_Details.md 2020-09-03 17:28:54 +02:00
Pascal Langer
f168abc2bb Fixed frame size 2020-08-31 22:21:21 +02:00
20 changed files with 1162 additions and 292 deletions

View File

@@ -106,6 +106,7 @@ before_install:
printf "\n\e[33;1mBuilding multi-stm-erskytx-aetr-inv-v$MULTI_VERSION.bin\e[0m";
exitcode=0;
opt_enable CHECK_FOR_BOOTLOADER;
opt_disable ENABLE_PPM;
opt_enable $ALL_PROTOCOLS;
opt_enable MULTI_STATUS;
opt_disable MULTI_TELEMETRY;
@@ -173,6 +174,8 @@ before_install:
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-reta-noinv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-ppm-aetr-noinv-v$MULTI_VERSION.bin\e[0m";
opt_enable ENABLE_PPM;
opt_disable ENABLE_SERIAL;
opt_replace RETA AETR;
opt_disable MULTI_STATUS;
opt_disable MULTI_TELEMETRY;
@@ -238,6 +241,7 @@ before_install:
elif [[ "$BOARD" == "multi4in1:STM32F1:multi5in1t18int" ]]; then
buildReleaseFiles(){
printf "\n\e[33;1mBuilding multi-t18int-opentx-aetr-noinv-v$MULTI_VERSION.bin\e[0m";
opt_disable ENABLE_PPM;
opt_disable INVERT_TELEMETRY;
exitcode=0;
buildMulti;

557
Lua_scripts/DSM FwdPrg.lua Normal file
View File

@@ -0,0 +1,557 @@
local toolName = "TNS|DSM Forward Programming|TNE"
---- #########################################################################
---- # #
---- # Copyright (C) OpenTX #
-----# #
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
---- # #
---- # This program is free software; you can redistribute it and/or modify #
---- # it under the terms of the GNU General Public License version 2 as #
---- # published by the Free Software Foundation. #
---- # #
---- # This program is distributed in the hope that it will be useful #
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
---- # GNU General Public License for more details. #
---- # #
---- #########################################################################
--###############################################################################
-- Multi buffer for DSM description
-- Multi_Buffer[0..2]=="DSM" -> Lua script is running
-- Multi_Buffer[3]==0x70+len -> TX to RX data ready to be sent
-- Multi_Buffer[4..9]=6 bytes of TX to RX data
-- Multi_Buffer[10..25]=16 bytes of RX to TX data
--
-- To start operation:
-- Write 0x00 at address 3
-- Write 0x00 at address 10
-- Write "DSM" at address 0..2
--###############################################################################
local RX_VERSION, WAIT_CMD, MENU_TITLE, MENU_LINES, MENU_VALUES, VALUE_CHANGING, VALUE_CHANGING_WAIT, VALUE_CHANGED = 0, 1, 2, 3, 4, 5, 6, 7
local MENU, LIST_MENU_NOCHANGING, LIST_MENU2, PERCENTAGE_VALUE = 0x1C, 0x6C, 0x4C, 0xC0
local Phase = RX_VERSION
local Waiting_RX = 0
local Text = {}
local Retry=100
local Blink = 0
local Value_Changed=0
local Menu = { Cur=nil, Id=nil, Title="", Prev=nil, PrevId=nil, Next=nil, NextId=nil, Back=nil, BackId=nil, CurLine=nil, SelLine=nil, EditLine=nil }
local Line = {}
local RX = { Name="", Version="" }
local function conv_int16(number)
if number >= 0x8000 then
return number - 0x10000
end
return number
end
local function Get_Text(index)
out = Text[index]
if out == nil then -- unknown...
out = "Unknown_"..string.format("%X",index)
end
return out
end
local function DSM_Release()
multiBuffer( 0, 0 )
end
local function DSM_Send(...)
local arg = {...}
for i = 1 , #arg do
multiBuffer( 3+i, arg[i])
end
multiBuffer( 3, 0x70+#arg)
end
local function Value_Add(dir)
local line=Line[Menu.SelLine]
Speed = getRotEncSpeed()
if Speed == ROTENC_MIDSPEED then
line.Val = line.Val + (5 * dir)
elseif Speed == ROTENC_HIGHSPEED then
line.Val = line.Val + (15 * dir)
else
line.Val = line.Val + dir
end
if line.Val > line.Max then
line.Val = line.Max
elseif line.Val < line.Min then
line.Val = line.Min
end
if Line[Menu.SelLine].Type ~= LIST_MENU_NOCHANGING then
Phase = VALUE_CHANGING
Waiting_RX = 0
end
end
local function DSM_Menu(event)
local Speed = 0
if event == EVT_VIRTUAL_NEXT then
if Menu.EditLine == nil then
-- not changing a value
if Menu.SelLine ~= nil then
if Menu.SelLine < 7 then
local num = Menu.SelLine
for i = Menu.SelLine + 1, 6, 1 do
if Line[i].Type ~= nil and Line[i].Next ~= nil then
Menu.SelLine=i
break
end
end
if num == Menu.SelLine then
if Menu.Next ~= 0 then -- Next
Menu.SelLine = 7
elseif Menu.Prev ~= 0 then -- Prev
Menu.SelLine = 8
end
end
elseif Menu.Prev ~= 0 then -- Prev
Menu.SelLine = 8
end
end
else -- need to inc the value
Value_Add(1)
end
elseif event == EVT_VIRTUAL_PREV then
if Menu.EditLine == nil then
if Menu.SelLine ~= nil then
if Menu.SelLine == 8 and Menu.Next ~= 0 then
Menu.SelLine = 7
elseif Menu.SelLine > 0 then
if Menu.SelLine > 6 then
Menu.SelLine = 7
end
local num = Menu.SelLine
for i = Menu.SelLine-1, 0, -1 do
if Line[i].Type ~= nil and Line[i].Next ~= nil then
Menu.SelLine=i
break
end
end
if num == Menu.SelLine then -- Back
Menu.SelLine = -1
end
else
Menu.SelLine = -1 -- Back
end
end
else -- need to dec the value
Value_Add(-1)
end
elseif event == EVT_VIRTUAL_ENTER then
if Menu.SelLine == -1 then -- Back
Menu.Cur = Menu.Back
Menu.Id = Menu.BackId
Menu.SelLine = 0
Phase = MENU_TITLE
Waiting_RX = 0
elseif Menu.SelLine == 7 then -- Next
Menu.Cur = Menu.Next
Menu.Id = Menu.NextId
Menu.SelLine = 0
Phase = MENU_TITLE
Waiting_RX = 0
elseif Menu.SelLine == 8 then -- Prev
Menu.Cur = Menu.Prev
Menu.Id = Menu.PrevId
Menu.SelLine = 0
Phase = MENU_TITLE
Waiting_RX = 0
elseif Menu.SelLine ~= nil and Line[Menu.SelLine].Next ~= nil then
if Line[Menu.SelLine].Type == MENU then -- Next menu exist
Menu.Cur = Line[Menu.SelLine].Next
Menu.Id = Line[Menu.SelLine].NextId
Phase = MENU_TITLE
Waiting_RX = 0
else
-- value entry
if Menu.EditLine == Menu.SelLine then
Menu.EditLine = nil
Value_Changed = 0
Phase = VALUE_CHANGED
Waiting_RX = 0
else
Menu.EditLine = Menu.SelLine
end
end
end
end
end
local function DSM_Send_Receive()
if Waiting_RX == 0 then
Waiting_RX = 1
-- Need to send a request
if Phase == RX_VERSION then -- request RX version
DSM_Send(0x11,0x06,0x00,0x14,0x00,0x00)
elseif Phase == WAIT_CMD then -- keep connection open
DSM_Send(0x00,0x04,0x00,0x00)
elseif Phase == MENU_TITLE then -- request menu title
if Menu.Cur == nil then
DSM_Send(0x12,0x06,0x00,0x14,0x00,0x00) -- first menu only
Menu.Cur = 0
else
DSM_Send(0x16,0x06,Menu.Id,Menu.Cur,0x00,Menu.SelLine)
end
elseif Phase == MENU_LINES then -- request menu lines
if Menu.CurLine == nil then
DSM_Send(0x13,0x04,Menu.Id,Menu.Cur) -- line 0
elseif Menu.CurLine >= 0x80 then
local last_byte={0x40,0x01,0x02,0x04,0x00,0x00} -- unknown...
DSM_Send(0x20,0x06,Menu.CurLine-0x80,Menu.CurLine-0x80,0x00,last_byte[Menu.CurLine-0x80+1]) -- line X
else
DSM_Send(0x14,0x06,Menu.Id,Menu.Cur,0x00,Menu.CurLine) -- line X
end
elseif Phase == MENU_VALUES then -- request menu values
DSM_Send(0x15,0x06,Menu.Id,Menu.Cur,Line[Menu.CurLine].ValId,Menu.CurLine) -- line X
elseif Phase == VALUE_CHANGING then -- send value
local value=Line[Menu.SelLine].Val
if value < 0 then
value = 0x10000 + value
end
DSM_Send(0x18,0x06,Line[Menu.SelLine].ValId,Menu.SelLine,bit32.rshift(value,8),bit32.band(value,0xFF)) -- send current value
Phase = VALUE_CHANGING_WAIT
elseif Phase == VALUE_CHANGED then -- send value
if Value_Changed == 0 then
local value=Line[Menu.SelLine].Val
if value < 0 then
value = 0x10000 + value
end
DSM_Send(0x18,0x06,Line[Menu.SelLine].ValId,Menu.SelLine,bit32.rshift(value,8),bit32.band(value,0xFF)) -- send current value
Value_Changed = Value_Changed + 1
Waiting_RX = 0
elseif Value_Changed == 1 then
DSM_Send(0x19,0x06,Line[Menu.SelLine].ValId,Menu.SelLine) -- validate
-- Value_Changed = Value_Changed + 1
-- Waiting_RX = 0
--elseif Value_Changed == 2 then
-- DSM_Send(0x1B,0x06,0x10,Menu.SelLine) -- validate again?
-- Value_Changed = Value_Changed + 1
end
elseif Phase == VALUE_CHANGING_WAIT then
DSM_Send(0x1A,0x06,Line[Menu.SelLine].ValId,Menu.SelLine)
end
multiBuffer(10,0x00);
Retry = 50
elseif multiBuffer(10) == 0x09 then
-- Answer received
--if multiBuffer(11) == 0x00 then -- waiting for commands?
if multiBuffer(11) == 0x01 then -- read version
--ex: 0x09 0x01 0x00 0x15 0x02 0x22 0x01 0x00 0x14 0x00 0x00 0x00 0x00 0x00 0x00 0x00
RX.Name = Get_Text(multiBuffer(13))
RX.Version = multiBuffer(14).."."..multiBuffer(15).."."..multiBuffer(16)
Phase = MENU_TITLE
elseif multiBuffer(11) == 0x02 then -- read menu title
--ex: 0x09 0x02 0x4F 0x10 0xA5 0x00 0x00 0x00 0x50 0x10 0x10 0x10 0x00 0x00 0x00 0x00
Menu.Cur = multiBuffer(12)
Menu.Id = multiBuffer(13)
Menu.Title = Get_Text(multiBuffer(14)+multiBuffer(15)*256)
Menu.Prev = multiBuffer(16)
Menu.PrevId = multiBuffer(17)
Menu.Next = multiBuffer(18)
Menu.NextId = multiBuffer(19)
Menu.Back = multiBuffer(20)
Menu.BackId = multiBuffer(21)
for i = 0, 6 do -- clear menu
Line[i] = { Menu = nil, Id = nil, Type = nil, Text="", Next = nil, NextId = nil, ValLine = nil, ValId = nil, Min, Max, Def, Val, Unit, Step }
end
Menu.CurLine = nil
if Menu.Next ~= 0 then
Menu.SelLine = 7 -- highlight Next
else
Menu.SelLine = -1 -- highlight Back
end
Blink = 0
Phase = MENU_LINES
elseif multiBuffer(11) == 0x03 then -- read menu lines
--ex: 0x09 0x03 0x00 0x10 0x00 0x1C 0xF9 0x00 0x10 0x10 0x00 0x00 0x00 0x00 0x03 0x00
-- Menu Id line Type Text_idx Next V_Id Val_Min Val_Max Val_Def
--ex: 0x09 0x03 0x61 0x10 0x00 0x6C 0x50 0x00 0x00 0x10 0x36 0x00 0x49 0x00 0x36 0x00
Menu.CurLine = multiBuffer(14)
local line = Line[Menu.CurLine]
line.Menu = multiBuffer(12)
line.Id = multiBuffer(13) -- not quite sure yet
line.Type = multiBuffer(15) -- not quite sure yet: 1C is text menu only, 4C/6C is text followed by text list, C0 is text followed by percentage value
line.Text = Get_Text(multiBuffer(16)+multiBuffer(17)*256)
if multiBuffer(18) == Menu.Cur then
line.Next = nil
else
line.Next = multiBuffer(18) -- not quite sure yet: 1C=text menu=>next menu, others=>line number of the value
end
if Menu.SelLine == -1 and line.Next ~= nil then -- Auto select first line of the menu
Menu.SelLine = Menu.CurLine
end
line.NextId = multiBuffer(19) -- not quite sure yet
line.ValLine = multiBuffer(18) -- not quite sure yet
line.ValId = multiBuffer(19) -- not quite sure yet
line.Min = conv_int16(multiBuffer(20)+multiBuffer(21)*256)
line.Max = conv_int16(multiBuffer(22)+multiBuffer(23)*256)
line.Def = conv_int16(multiBuffer(24)+multiBuffer(25)*256)
if line.Type == MENU then
-- nothing to do on menu entries
elseif line.Type == LIST_MENU_NOCHANGING or line.Type == LIST_MENU2 then
line.Val = nil --line.Def - line.Min -- use default value not sure if needed
line.Def = line.Min -- pointer to the start of the list in Text
line.Max = line.Max - line.Min -- max index
line.Min = 0 -- min index
else -- default to numerical value
line.Val = nil --line.Def -- use default value not sure if needed
end
if line.Type ~= 0x1C then -- value to follow
line.Text = line.Text..":"
end
Phase = MENU_LINES
elseif multiBuffer(11) == 0x04 then -- read menu values
--ex: 0x09 0x04 0x53 0x10 0x00 0x10 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
-- Menu MeId line VaId Value
--ex: 0x09 0x04 0x61 0x10 0x02 0x10 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Menu.CurLine = multiBuffer(14)
Line[Menu.CurLine].Val = conv_int16(multiBuffer(16)+multiBuffer(17)*256)
Phase = MENU_VALUES
elseif multiBuffer(11) == 0x05 then -- unknown... need to get through the lines...
Menu.CurLine = 0x80 + multiBuffer(12)
Phase = MENU_LINES
elseif multiBuffer(11) == 0x00 and Phase == VALUE_CHANGING then
Phase = VALUE_CHANGING_WAIT
end
-- Data processed
Waiting_RX = 0
multiBuffer(10,0x00)
Retry = 50
else
Retry = Retry - 1
if Retry <= 0 then
-- Retry the RX request
Retry = 50
Waiting_RX = 0
if Phase ~= RX_VERSION and Phase ~= VALUE_CHANGING_WAIT then
Phase = WAIT_CMD
end
end
end
end
local function DSM_Display()
lcd.clear()
if LCD_W == 480 then
--Draw title
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
lcd.drawText(1, 5, "DSM Forward Programming", MENU_TITLE_COLOR)
--Draw RX Menu
if Phase == RX_VERSION then
lcd.drawText(10,50,"No compatible DSM RX...", BLINK)
else
if Menu.Title ~= nil then
local attrib=0;
lcd.drawText(80,32,Menu.Title,MIDSIZE)
for i = 0, 6 do
if i == Menu.SelLine then
attrib = INVERS
else
attrib = 0
end
if Line[i] ~= nil and Line[i].Type ~= nil then
if Line[i].Type ~= MENU then-- list/value
if Line[i].Val ~= nil then
local text=""
if Line[i].Type == LIST_MENU_NOCHANGING or Line[i].Type == LIST_MENU2 then
text = Get_Text(Line[i].Val+Line[i].Def)
elseif Line[i].Type == PERCENTAGE_VALUE then
text = Line[i].Val.." %"
else
text = Line[i].Val
end
if Menu.EditLine == Menu.SelLine then -- blink edited entry
Blink = Blink + 1
if Blink > 25 then
attrib = 0
if Blink > 50 then
Blink = 0
end
end
end
lcd.drawText(240,32+20*(i+2), text, attrib) -- display value
end
attrib = 0
end
lcd.drawText(10,32+20*(i+2), Line[i].Text, attrib) -- display text
end
end
if Menu.SelLine == -1 then
lcd.drawText(437,32, "Back", INVERS)
else
lcd.drawText(437,32, "Back", 0)
end
lcd.drawRectangle(437-5, 32-2, 48, 25)
if Menu.Next ~= 0 then
if Menu.SelLine == 7 then
lcd.drawText(437,220, "Next",INVERS)
else
lcd.drawText(437,220, "Next")
end
lcd.drawRectangle(437-5, 220-2, 48, 25)
end
if Menu.Prev ~= 0 then
if Menu.SelLine == 8 then
lcd.drawText(5,220, "Prev",INVERS)
else
lcd.drawText(5,220, "Prev")
end
lcd.drawRectangle(5-5, 220-2, 48, 25)
end
end
lcd.drawText(170,252, "RX "..RX.Name.." v"..RX.Version) -- display RX info
end
else
-- --Draw RX Menu on LCD_W=128
-- if multiBuffer( 4 ) == 0xFF then
-- lcd.drawText(2,17,"No compatible DSM RX...",SMLSIZE)
-- else
-- if Retry_128 ~= 0 then
-- --Intro page
-- Retry_128 = Retry_128 - 1
-- lcd.drawScreenTitle("DSM Forward Programming",0,0)
-- lcd.drawText(2,17,"Press Prev Page for previous Menu" ,SMLSIZE)
-- else
-- --Menu page
-- for line = 0, 7, 1 do
-- for i = 0, 21-1, 1 do
-- value=multiBuffer( line*21+6+i )
-- if value > 0x80 then
-- value = value - 0x80
-- lcd.drawText(2+i*6,1+8*line,string.char(value).." ",SMLSIZE+INVERS)
-- else
-- lcd.drawText(2+i*6,1+8*line,string.char(value),SMLSIZE)
-- end
-- end
-- end
-- end
-- end
end
end
-- Init
local function DSM_Init()
--Set protocol to talk to
multiBuffer( 0, string.byte('D') )
--test if value has been written
if multiBuffer( 0 ) ~= string.byte('D') then
error("Not enough memory!")
return 2
end
--Init TX buffer
multiBuffer( 3, 0x00 )
--Init RX buffer
multiBuffer( 10, 0x00 )
--Init telemetry
multiBuffer( 0, string.byte('D') )
multiBuffer( 1, string.byte('S') )
multiBuffer( 2, string.byte('M') )
--Text to be displayed -> need to use a file instead?
--RX names--
Text[0x0014]="SPM4651T"
Text[0x0015]="AR637T"
--Lists--
Text[0x0036]="Throttle"
Text[0x0037]="Aileron"
Text[0x0038]="Elevator"
Text[0x0039]="Rudder"
Text[0x003A]="Gear"
for i=1,7 do -- 3B..41
Text[0x003A+i]="Aux"..i
end
for i=1,8 do -- 41..49
Text[0x0041+i]="XPlus-"..i
end
Text[0x004A]="Failsafe"
Text[0x004B]="Main Menu"
Text[0x004E]="Position"
Text[0x0050]="Outputs"
--Text[0x005E]="Inhibit"
Text[0x005F]="Hold Last"
Text[0x0060]="Preset"
--Text[0x0061]="Custom"
--Messages--
Text[0x0090]="Apply"
Text[0x0093]="Complete"
Text[0x0094]="Done"
Text[0x0097]="Factory Reset"
Text[0x009A]="Capture Failsafe Positions"
Text[0x009C]="Custom Failsafe"
Text[0x00A5]="First Time Setup"
Text[0x00F9]="Gyro settings"
Text[0x0100]="Make sure the model has been"
Text[0x0101]="configured, including wing type,"
Text[0x0102]="reversing, travel, trimmed, etc."
Text[0x0103]="before continuing setup."
Text[0x0104]=""
Text[0x0105]=""
Text[0x0106]="Any wing type, channel assignment,"
Text[0x0107]="subtrim, or servo reversing changes"
Text[0x0108]="require running through initial"
Text[0x0109]="setup again."
Text[0x010A]=""
Text[0x010B]=""
Text[0x019C]="Enter Receiver Bind Mode"
Text[0x020A]="Restore from Backup"
Text[0x0209]="Save to Backup"
Text[0x021A]="Set the model level,"
Text[0x021B]="and press Continue."
Text[0x021C]=""
Text[0x021D]=""
Text[0x021F]="Set the model on its nose,"
Text[0x0220]="and press Continue. If the"
Text[0x0221]="orientation on the next"
Text[0x0222]="screen is wrong go back"
Text[0x0223]="and try again."
Text[0x0224]="Continue"
Text[0x0229]="Set Orientation Manually"
Text[0x0227]="Other settings"
Text[0x022B]="WARNING!"
Text[0x022C]="This will reset the"
Text[0x022D]="configuration to factory"
Text[0x022E]="defaults. This does not"
Text[0x022F]="affect the backup config."
Text[0x0230]=""
Text[0x0231]="This will overwrite the"
Text[0x0232]="backup memory with your"
Text[0x0233]="current configuartion."
Text[0x0234]=""
Text[0x0235]=""
Text[0x0236]="This will overwrite the"
Text[0x0237]="current config with"
Text[0x0238]="that which is in"
Text[0x0239]="the backup memory."
Text[0x023A]=""
end
-- Main
local function DSM_Run(event)
if event == nil then
error("Cannot be run as a model script!")
return 2
elseif event == EVT_VIRTUAL_EXIT then
DSM_Release()
return 2
else
DSM_Menu(event)
DSM_Send_Receive()
DSM_Display()
return 0
end
end
return { init=DSM_Init, run=DSM_Run }

View File

@@ -21,6 +21,16 @@ Need OpenTX 2.3.9 or above. Located on the radio SD card under \SCRIPTS\TOOLS. T
[![MultiChannelsUpdater](https://img.youtube.com/vi/L58ayXuewyA/0.jpg)](https://www.youtube.com/watch?v=L58ayXuewyA)
## DSM Forward Programming
This is a work in progress. It's only available for color screens (Horus, TX16S, T16, T18...).
If some text appears as Unknown_xxx, please report xxx and what the exact text display should be.
Need OpenTX 2.3.10 nightly or above. Located on the radio SD card under \SCRIPTS\TOOLS.
[![DSM Forward Programming](https://img.youtube.com/vi/sjIaDw5j9nE/0.jpg)](https://www.youtube.com/watch?v=sjIaDw5j9nE)
## Graupner HoTT.ua
Enable text configuration of the HoTT RX and sensors: Vario, GPS, ESC, GAM and EAM.

View File

@@ -270,11 +270,18 @@ static void AFHDS2A_build_packet(uint8_t type)
}
#define AFHDS2A_WAIT_WRITE 0x80
#ifdef STM32_BOARD
#define AFHDS2A_WRITE_TIME 1550
#else
#define AFHDS2A_WRITE_TIME 1700
#endif
uint16_t ReadAFHDS2A()
{
static uint8_t packet_type;
static uint16_t packet_counter;
uint8_t data_rx;
uint8_t data_rx=0;
uint16_t start;
#ifndef FORCE_AFHDS2A_TUNING
A7105_AdjustLOBaseFreq(1);
@@ -351,10 +358,8 @@ uint16_t ReadAFHDS2A()
telemetry_set_input_sync(3850);
#endif
AFHDS2A_build_packet(packet_type);
if((A7105_ReadReg(A7105_00_MODE) & 0x01)) // Check if something has been received...
data_rx=0;
else
data_rx=1; // Yes
if((A7105_ReadReg(A7105_00_MODE) & 0x01)==0) // Check if something has been received...
data_rx=1; // Yes
A7105_WriteData(AFHDS2A_TXPACKET_SIZE, hopping_frequency[hopping_frequency_no++]);
if(hopping_frequency_no >= AFHDS2A_NUMFREQ)
hopping_frequency_no = 0;
@@ -370,13 +375,13 @@ uint16_t ReadAFHDS2A()
}
else
#endif
packet_type = AFHDS2A_PACKET_STICKS; // todo : check for settings changes
packet_type = AFHDS2A_PACKET_STICKS; // todo : check for settings changes
}
if(!(A7105_ReadReg(A7105_00_MODE) & (1<<5 | 1<<6)) && data_rx==1)
{ // RX+FECF+CRCF Ok
A7105_ReadData(AFHDS2A_RXPACKET_SIZE);
if(packet[0] == 0xAA && packet[9] == 0xFC)
packet_type=AFHDS2A_PACKET_SETTINGS; // RX is asking for settings
packet_type=AFHDS2A_PACKET_SETTINGS; // RX is asking for settings
else
if((packet[0] == 0xAA && packet[9]!=0xFD) || packet[0] == 0xAC)
{// Normal telemetry packet, ignore packets which contain the RX configuration: AA FD FF 32 00 01 00 FF FF FF 05 DC 05 DE FA FF FF FF FF FF FF FF FF FF FF FF FF FF FF
@@ -399,7 +404,7 @@ uint16_t ReadAFHDS2A()
}
packet_counter++;
phase |= AFHDS2A_WAIT_WRITE;
return 1700;
return AFHDS2A_WRITE_TIME;
case AFHDS2A_DATA|AFHDS2A_WAIT_WRITE:
//Wait for TX completion
start=micros();
@@ -410,7 +415,7 @@ uint16_t ReadAFHDS2A()
A7105_SetTxRxMode(RX_EN);
A7105_Strobe(A7105_RX);
phase &= ~AFHDS2A_WAIT_WRITE;
return 2150;
return 3850-AFHDS2A_WRITE_TIME;
}
return 3850; // never reached, please the compiler
}

View File

@@ -17,6 +17,8 @@
#include "iface_cyrf6936.h"
//#define DSM_DEBUG_FWD_PGM
//#define DSM_GR300
#define DSM_BIND_CHANNEL 0x0d //13 This can be any odd channel
@@ -151,6 +153,7 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
if(sub_protocol==DSM2_22)
bits=10; // Only DSM2_22 is using a resolution of 1024
}
#ifdef DSM_THROTTLE_KILL_CH
uint16_t kill_ch=Channel_data[DSM_THROTTLE_KILL_CH-1];
#endif
@@ -189,6 +192,23 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
packet[i*2+2] = (value >> 8) & 0xff;
packet[i*2+3] = (value >> 0) & 0xff;
}
#ifdef DSM_FWD_PGM
if(upper==0 && DSM_SerialRX && (DSM_SerialRX_val[0]&0xF8)==0x70 )
{ // Send forward programming data if available
for(uint8_t i=0; i<(DSM_SerialRX_val[0]&0x07);i++)
{
packet[i*2+4]=0x70+i;
packet[i*2+5]=DSM_SerialRX_val[i+1];
}
DSM_SerialRX=false;
#ifdef DSM_DEBUG_FWD_PGM
debug("FWD=");
for(uint8_t i=4; i<16;i++)
debug(" %02X",packet[i]);
debugln("");
#endif
}
#endif
}
static uint8_t __attribute__((unused)) DSM_Check_RX_packet()
@@ -307,9 +327,9 @@ uint16_t ReadDsm()
telemetry_set_input_sync(11000); // Always request 11ms spacing even if we don't use half of it in 22ms mode
#endif
case DSM_CH1_WRITE_B:
DSM_build_data_packet(phase == DSM_CH1_WRITE_B); // build lower or upper channels
case DSM_CH2_WRITE_A:
case DSM_CH2_WRITE_B:
DSM_build_data_packet(phase == DSM_CH1_WRITE_B||phase == DSM_CH2_WRITE_B); // build lower or upper channels
CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS); // clear IRQ flags
CYRF_WriteDataPacket(packet);
#if 0
@@ -368,6 +388,15 @@ uint16_t ReadDsm()
if(len>TELEMETRY_BUFFER_SIZE-2)
len=TELEMETRY_BUFFER_SIZE-2;
CYRF_ReadDataPacketLen(packet_in+1, len);
#ifdef DSM_DEBUG_FWD_PGM
//debug(" %02X", packet_in[1]);
if(packet_in[1]==9)
{
for(uint8_t i=0;i<len;i++)
debug(" %02X", packet_in[i+1]);
debugln("");
}
#endif
packet_in[0]=CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;// store RSSI of the received telemetry signal
telemetry_link=1;
}

View File

@@ -71,6 +71,7 @@
71,JJRC345
72,Q90C
73,Kyosho
74,RadioLink,Surface
74,RadioLink,Surface,Air
75,---
76,Realacc,R11
77,OMP

View File

@@ -91,7 +91,7 @@ const char STR_RLINK[] ="RadLink";
const char STR_REALACC[] ="Realacc";
const char STR_OMP[] ="OMP";
const char STR_TEST[] ="Test";
const char STR_FAKE[] ="Fake";
const char STR_NANORF[] ="NanoRF";
const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20";
const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501";
@@ -112,7 +112,7 @@ const char STR_SUBTYPE_MT99[] = "\x06""MT99\0 ""H7\0 ""YZ\0 ""LS\0 "
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_HONTAI[] = "\x07""Std\0 ""JJRC X1""X5C1\0 ""FQ_951";
const char STR_SUBTYPE_AFHDS2A[] = "\x08""PWM,IBUS""PPM,IBUS""PWM,SBUS""PPM,SBUS""PWM,IB16""PPM,IB16";
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_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";
@@ -222,13 +222,13 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_FLYSKY, STR_FLYSKY, 5, STR_SUBTYPE_FLYSKY, OPTION_NONE },
#endif
#if defined(AFHDS2A_A7105_INO)
{PROTO_AFHDS2A, STR_AFHDS2A, 6, STR_SUBTYPE_AFHDS2A, OPTION_SRVFREQ },
{PROTO_AFHDS2A, STR_AFHDS2A, 8, STR_SUBTYPE_AFHDS2A, OPTION_SRVFREQ },
#endif
#if defined(AFHDS2A_RX_A7105_INO)
{PROTO_AFHDS2A_RX, STR_AFHDS2A_RX,0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(HEIGHT_A7105_INO)
{PROTO_HEIGHT, STR_HEIGHT, 2, STR_SUBTYPE_HEIGHT, OPTION_NONE },
{PROTO_HEIGHT, STR_HEIGHT, 2, STR_SUBTYPE_HEIGHT, OPTION_NONE },
#endif
#if defined(FQ777_NRF24L01_INO)
{PROTO_FQ777, STR_FQ777, 0, NO_SUBTYPE, OPTION_NONE },
@@ -308,7 +308,7 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(NCC1701_NRF24L01_INO)
{PROTO_NCC1701, STR_NCC1701, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(OMP_NRF24L01_INO)
#if defined(OMP_CC2500_INO)
{PROTO_OMP, STR_OMP, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(PELIKAN_A7105_INO)
@@ -392,8 +392,8 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(TEST_CC2500_INO)
{PROTO_TEST, STR_TEST, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(FAKE_NRF24L01_INO)
{PROTO_FAKE, STR_FAKE, 0, NO_SUBTYPE, OPTION_NONE },
#if defined(NANORF_NRF24L01_INO)
{PROTO_NANORF, STR_NANORF, 0, NO_SUBTYPE, OPTION_NONE },
#endif
{0x00, nullptr, 0, nullptr, 0 }
};

View File

@@ -19,7 +19,7 @@
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_REVISION 1
#define VERSION_PATCH_LEVEL 59
#define VERSION_PATCH_LEVEL 69
//******************
// Protocols
@@ -102,9 +102,9 @@ enum PROTOCOLS
PROTO_KYOSHO = 73, // =>A7105
PROTO_RLINK = 74, // =>CC2500
PROTO_REALACC = 76, // =>NRF24L01
PROTO_OMP = 77, // =>NRF24L01
PROTO_OMP = 77, // =>CC2500 & NRF24L01
PROTO_FAKE = 126, // =>CC2500+NRF24L01
PROTO_NANORF = 126, // =>NRF24L01
PROTO_TEST = 127, // =>CC2500
};
@@ -1032,6 +1032,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
FrSkyX and FrSkyX2: Stream[27] during bind Telem on=0x00,off=0x01 | CH1-8=0x00,CH9-16=0x02
FrSkyX and FrSkyX2: Stream[27..34] during normal operation unstuffed SPort data to be sent
HoTT: Stream[27] 1 byte for telemetry type
DSM: Stream[27..33] Forward Programming
*/
/*
Multimodule Status

View File

@@ -256,6 +256,10 @@ uint8_t packet_in[TELEMETRY_BUFFER_SIZE];//telemetry receiving packets
uint8_t HoTT_SerialRX_val=0;
bool HoTT_SerialRX=false;
#endif
#ifdef DSM_FWD_PGM
uint8_t DSM_SerialRX_val[7];
bool DSM_SerialRX=false;
#endif
#endif // TELEMETRY
// Callback
@@ -311,6 +315,7 @@ void setup()
#elif defined STM32_BOARD
//STM32
afio_cfg_debug_ports(AFIO_DEBUG_NONE);
pinMode(LED_pin,OUTPUT);
pinMode(LED2_pin,OUTPUT);
pinMode(A7105_CSN_pin,OUTPUT);
pinMode(CC25_CSN_pin,OUTPUT);
@@ -364,6 +369,38 @@ void setup()
//Timers
init_HWTimer(); //0.5us
//Read module flash size
#ifndef DISABLE_FLASH_SIZE_CHECK
unsigned short *flashSize = (unsigned short *) (0x1FFFF7E0);// Address register
debugln("Module Flash size: %dKB",(int)(*flashSize & 0xffff));
if((int)(*flashSize & 0xffff) < 128) // Not supported by this project
while (true) { //SOS
for(uint8_t i=0; i<3;i++)
{
LED_on;
delay(100);
LED_off;
delay(100);
}
for(uint8_t i=0; i<3;i++)
{
LED_on;
delay(500);
LED_off;
delay(100);
}
for(uint8_t i=0; i<3;i++)
{
LED_on;
delay(100);
LED_off;
delay(100);
}
LED_off;
delay(1000);
}
#endif
#else
//ATMEGA328p
// all inputs
@@ -502,7 +539,7 @@ void setup()
MProtocol_id_master=random_id(EEPROM_ID_OFFSET,false);
debugln("Module Id: %lx", MProtocol_id_master);
#ifdef ENABLE_PPM
//Protocol and interrupts initialization
if(mode_select != MODE_SERIAL)
@@ -773,7 +810,7 @@ bool Update_All()
update_led_status();
#if defined(TELEMETRY)
#if ( !( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) ) )
if((protocol == PROTO_BAYANG_RX) || (protocol == PROTO_AFHDS2A_RX) || (protocol == PROTO_FRSKY_RX) || (protocol == PROTO_SCANNER) || (protocol==PROTO_FRSKYD) || (protocol==PROTO_BAYANG) || (protocol==PROTO_NCC1701) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_FRSKYX) || (protocol==PROTO_FRSKYX2) || (protocol==PROTO_DSM) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_HOTT) || (protocol==PROTO_PROPEL) || (protocol==PROTO_DEVO) || (protocol==PROTO_DSM_RX) || (protocol==PROTO_FRSKY_R9) || (protocol==PROTO_RLINK))
if((protocol == PROTO_BAYANG_RX) || (protocol == PROTO_AFHDS2A_RX) || (protocol == PROTO_FRSKY_RX) || (protocol == PROTO_SCANNER) || (protocol==PROTO_FRSKYD) || (protocol==PROTO_BAYANG) || (protocol==PROTO_NCC1701) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_FRSKYX) || (protocol==PROTO_FRSKYX2) || (protocol==PROTO_DSM) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_HOTT) || (protocol==PROTO_PROPEL) || (protocol==PROTO_OMP) || (protocol==PROTO_DEVO) || (protocol==PROTO_DSM_RX) || (protocol==PROTO_FRSKY_R9) || (protocol==PROTO_RLINK))
#endif
if(IS_DISABLE_TELEM_off)
TelemetryUpdate();
@@ -1604,7 +1641,7 @@ static void protocol_init()
remote_callback = REALACC_callback;
break;
#endif
#if defined(OMP_NRF24L01_INO)
#if defined(OMP_CC2500_INO)
case PROTO_OMP:
next_callback=initOMP();
remote_callback = OMP_callback;
@@ -1616,10 +1653,10 @@ static void protocol_init()
remote_callback = TEST_callback;
break;
#endif
#if defined(FAKE_NRF24L01_INO)
case PROTO_FAKE:
next_callback=initFAKE();
remote_callback = FAKE_callback;
#if defined(NANORF_NRF24L01_INO)
case PROTO_NANORF:
next_callback=initNANORF();
remote_callback = NANORF_callback;
break;
#endif
#endif
@@ -1927,7 +1964,7 @@ void update_serial_data()
}
#endif
#ifdef SPORT_SEND
if((protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKY_R9) && rx_len==35)
if((protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKY_R9) && rx_len==27+8)
{//Protocol waiting for 8 bytes
#define BYTE_STUFF 0x7D
#define STUFF_MASK 0x20
@@ -1971,12 +2008,19 @@ void update_serial_data()
}
#endif //SPORT_SEND
#ifdef HOTT_FW_TELEMETRY
if(protocol==PROTO_HOTT && rx_len==28)
if(protocol==PROTO_HOTT && rx_len==27+1)
{//Protocol waiting for 1 byte
HoTT_SerialRX_val=rx_ok_buff[27];
HoTT_SerialRX=true;
}
#endif
#ifdef DSM_FWD_PGM
if(protocol==PROTO_DSM && rx_len==27+7)
{//Protocol waiting for 7 bytes
memcpy(DSM_SerialRX_val, (const void *)&rx_ok_buff[27],7);
DSM_SerialRX=true;
}
#endif
}
RX_DONOTUPDATE_off;
@@ -2221,7 +2265,7 @@ void pollBoot()
#if defined(TELEMETRY)
void PPM_Telemetry_serial_init()
{
if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_BAYANG)|| (protocol==PROTO_NCC1701) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_PROPEL) || (protocol==PROTO_RLINK)
if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_BAYANG)|| (protocol==PROTO_NCC1701) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_PROPEL) || (protocol==PROTO_OMP) || (protocol==PROTO_RLINK)
#ifdef TELEMETRY_FRSKYX_TO_FRSKYD
|| (protocol==PROTO_FRSKYX) || (protocol==PROTO_FRSKYX2)
#endif
@@ -2484,7 +2528,7 @@ static void __attribute__((unused)) calc_fh_channels(uint8_t num_ch)
ISR(TIMER1_COMPB_vect)
#endif
{ // Timer1 compare B interrupt
if(rx_idx>=26 && rx_idx<RXBUFFER_SIZE)
if(rx_idx>=26 && rx_idx<=RXBUFFER_SIZE)
{
// A full frame has been received
if(!IS_RX_DONOTUPDATE_on)
@@ -2503,7 +2547,7 @@ static void __attribute__((unused)) calc_fh_channels(uint8_t num_ch)
}
#ifdef DEBUG_SERIAL
else
debugln("RX frame too short");
debugln("RX frame size incorrect");
#endif
discard_frame=true;
#ifdef STM32_BOARD

View File

@@ -529,7 +529,7 @@ boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
}
uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
{ //!!! Don't forget do a +2 and if using CRC add +2 on any of the used NRF24L01_11_RX_PW_Px !!!
{ //!!! Don't forget do a +2 and if using CRC add +4 on any of the used NRF24L01_11_RX_PW_Px !!!
uint8_t buffer[32];
uint8_t pcf_size; // pcf payload size
if (xn297_crc)

View File

@@ -0,0 +1,73 @@
/*
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(NANORF_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define NANORF_PACKET_PERIOD 40000
#define NANORF_INITIAL_WAIT 500
#define NANORF_RF_CHANNEL 40
#define NANORF_PAYLOADSIZE 7
static void __attribute__((unused)) NANORF_send_packet()
{
packet[0] = convert_channel_8b(AILERON);
packet[1] = convert_channel_8b(ELEVATOR);
packet[2] = convert_channel_8b(THROTTLE);
packet[3] = convert_channel_8b(RUDDER);
packet[4] = convert_channel_8b(CH5);
packet[5] = convert_channel_8b(CH6);
packet[6] = 0;
for (uint8_t i=0; i < NANORF_PAYLOADSIZE-1; i++)
packet[6] += packet[i];
packet[6] += 0x55;
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
NRF24L01_WritePayload(packet, NANORF_PAYLOADSIZE);
}
static void __attribute__((unused)) NANORF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR , (uint8_t *)"Nano1",5);
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable all data pipes (even though not used?)
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // 4mS retransmit t/o, 15 tries (retries w/o AA?)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, NANORF_RF_CHANNEL);
NRF24L01_SetBitrate(NRF24L01_BR_1M);
NRF24L01_SetPower(); // Set tx_power
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP)); //
}
uint16_t NANORF_callback()
{
NANORF_send_packet();
return NANORF_PACKET_PERIOD;
}
uint16_t initNANORF()
{
BIND_DONE;
NANORF_init();
return NANORF_INITIAL_WAIT;
}
#endif

View File

@@ -0,0 +1,298 @@
/*
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(OMP_CC2500_INO)
#include "iface_nrf250k.h"
//#define FORCE_OMP_ORIGINAL_ID
//#define OMP_TELEM_DEBUG
#define OMP_INITIAL_WAIT 500
#define OMP_PACKET_PERIOD 5000
#define OMP_RF_BIND_CHANNEL 35
#define OMP_RF_NUM_CHANNELS 8
#define OMP_PAYLOAD_SIZE 16
#define OMP_BIND_COUNT 600 //3sec
static void __attribute__((unused)) OMP_send_packet()
{
#ifdef OMP_HUB_TELEMETRY
if(option==0) option=1; // Select the CC2500 by default
PE1_off; PE2_on; // CC2500 antenna RF2
#endif
if(IS_BIND_IN_PROGRESS)
{
memcpy(packet,"BND",3);
memcpy(&packet[3],rx_tx_addr,5);
memcpy(&packet[8],hopping_frequency,8);
}
else
{
memset(packet,0x00,OMP_PAYLOAD_SIZE);
#ifdef OMP_HUB_TELEMETRY
//RX telem request every 7*5=35ms
packet_sent++;
packet_sent %= OMP_RF_NUM_CHANNELS-1; // Change telem RX channels every time
if(packet_sent==0)
{
packet[0] |= 0x40; // |0x40 to request RX telemetry
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
}
#endif
//hopping frequency
packet[0 ] |= hopping_frequency_no;
XN297L_Hopping(hopping_frequency_no);
hopping_frequency_no++;
hopping_frequency_no &= OMP_RF_NUM_CHANNELS-1; // 8 RF channels
//flags
packet[1 ] = 0x08 //unknown
| GET_FLAG(CH5_SW, 0x20); // HOLD
packet[2 ] = 0x40; //unknown
if(Channel_data[CH6] > CHANNEL_MAX_COMMAND)
packet[2 ] |= 0x20; // IDLE2
else if(Channel_data[CH6] > CHANNEL_MIN_COMMAND)
packet[1 ] |= 0x40; // IDLE1
if(Channel_data[CH7] > CHANNEL_MAX_COMMAND)
packet[2 ] |= 0x08; // 3D
else if(Channel_data[CH7] > CHANNEL_MIN_COMMAND)
packet[2 ] |= 0x04; // ATTITUDE
//trims??
//packet[3..6]
//channels TAER packed 11bits
uint16_t channel=convert_channel_16b_limit(THROTTLE,0,2047);
packet[7 ] = channel;
packet[8 ] = channel>>8;
channel=convert_channel_16b_limit(AILERON,2047,0);
packet[8 ] |= channel<<3;
packet[9 ] = channel>>5;
channel=convert_channel_16b_limit(ELEVATOR,0,2047);
packet[9] |= channel<<6;
packet[10] = channel>>2;
packet[11] = channel>>10;
channel=convert_channel_16b_limit(RUDDER,2047,0);
packet[11] |= channel<<1;
packet[12] = channel>>7;
//unknown
//packet[13..15]
packet[15] = 0x04;
}
XN297L_SetPower(); // Set tx_power
XN297L_SetFreqOffset(); // Set frequency offset
XN297L_WriteEnhancedPayload(packet, OMP_PAYLOAD_SIZE, packet_sent!=0);
}
static void __attribute__((unused)) OMP_init()
{
//Config CC2500
#ifdef OMP_HUB_TELEMETRY
if(option==0)
option=1; // Select the CC2500
#endif
XN297L_Init();
XN297L_SetTXAddr((uint8_t*)"FLPBD", 5);
XN297L_HoppingCalib(OMP_RF_NUM_CHANNELS); // Calibrate all channels
XN297L_RFChannel(OMP_RF_BIND_CHANNEL); // Set bind channel
#ifdef OMP_HUB_TELEMETRY
//Config NRF
option=0; // Select the NRF
XN297L_Init();
XN297_Configure(_BV(NRF24L01_00_EN_CRC));
XN297_SetRXAddr(rx_tx_addr, 5); // Set the RX address
NRF24L01_SetTxRxMode(TXRX_OFF); // Turn it off for now
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, OMP_PAYLOAD_SIZE + 4); // packet length +4 bytes of PCF+CRC
#endif
}
static void __attribute__((unused)) OMP_initialize_txid()
{
calc_fh_channels(OMP_RF_NUM_CHANNELS);
#ifdef FORCE_OMP_ORIGINAL_ID
rx_tx_addr[0]=0x4E;
rx_tx_addr[1]=0x72;
rx_tx_addr[2]=0x8E;
rx_tx_addr[3]=0x70;
rx_tx_addr[4]=0x62;
for(uint8_t i=0; i<OMP_RF_NUM_CHANNELS;i++)
hopping_frequency[i]=(i+3)*5;
#endif
}
static void __attribute__((unused)) OMP_Send_Telemetry(uint8_t v)
{
v_lipo1=v;
telemetry_counter++; //LQI
telemetry_link=1;
if(telemetry_lost)
{
telemetry_lost = 0;
packet_count = 100;
telemetry_counter = 100;
}
}
enum {
OMP_BIND = 0x00,
OMP_PREPDATA = 0x01,
OMP_DATA = 0x02,
OMP_RX = 0x03,
};
#define OMP_WRITE_TIME 850
uint16_t OMP_callback()
{
switch(phase)
{
case OMP_BIND:
if(--bind_counter==0)
phase++; // OMP_PREPDATA
OMP_send_packet();
return OMP_PACKET_PERIOD;
case OMP_PREPDATA:
BIND_DONE;
XN297L_SetTXAddr(rx_tx_addr, 5);
phase++; // OMP_DATA
case OMP_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(OMP_PACKET_PERIOD);
#endif
OMP_send_packet();
#ifdef OMP_HUB_TELEMETRY
if(packet_sent == 0)
{
phase++; // OMP_RX
return OMP_WRITE_TIME;
}
else if(packet_sent == 1)
{
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // a packet has been received
if(XN297_ReadEnhancedPayload(packet_in, OMP_PAYLOAD_SIZE) == OMP_PAYLOAD_SIZE)
{ // packet with good CRC and length
#ifdef OMP_TELEM_DEBUG
debug("OK :");
for(uint8_t i=0;i<OMP_PAYLOAD_SIZE;i++)
debug(" %02X",packet_in[i]);
#endif
// packet_in = 01 00 98 2C 03 19 19 F0 49 02 00 00 00 00 00 00
// all bytes are fixed and unknown except 2 and 3 which represent the battery voltage: packet_in[3]*256+packet_in[2]=lipo voltage*100 in V
uint16_t v=((packet_in[3]<<8)+packet_in[2]-400)/50;
if(v>255) v=255;
v_lipo2=v;
OMP_Send_Telemetry(v);
}
else
{ // As soon as the motor spins the telem packets are becoming really bad and the CRC throws most of them in error as it should but...
#ifdef OMP_TELEM_DEBUG
debug("NOK:");
for(uint8_t i=0;i<OMP_PAYLOAD_SIZE;i++)
debug(" %02X",packet_in[i]);
#endif
if(packet_in[0]==0x01 && packet_in[1]==0x00)
{// the start of the packet looks ok...
uint16_t v=((packet_in[3]<<8)+packet_in[2]-400)/50;
if(v<260 && v>180)
{ //voltage is less than 13V and more than 9V (3V/element)
if(v>255) v=255;
uint16_t v1=v-v_lipo2;
if(v1&0x8000) v1=-v1;
if(v1<20) // the batt voltage is within 1V from a good reading...
{
OMP_Send_Telemetry(v); // ok to send
#ifdef OMP_TELEM_DEBUG
debug(" OK");
#endif
}
}
}
else
telemetry_counter++; //LQI
}
#ifdef OMP_TELEM_DEBUG
debugln("");
#endif
}
NRF24L01_SetTxRxMode(TXRX_OFF);
packet_count++;
if(packet_count>=100)
{//LQI calculation
packet_count=0;
TX_LQI=telemetry_counter;
RX_RSSI=telemetry_counter;
if(telemetry_counter==0)
telemetry_lost = 1;
telemetry_counter = 0;
}
}
#endif
return OMP_PACKET_PERIOD;
#ifdef OMP_HUB_TELEMETRY
case OMP_RX:
NRF24L01_WriteReg(NRF24L01_07_STATUS, (1 << NRF24L01_07_RX_DR) //reset the flag(s)
| (1 << NRF24L01_07_TX_DS)
| (1 << NRF24L01_07_MAX_RT));
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_PWR_UP) | (1 << NRF24L01_00_PRIM_RX) ); // Start RX
{
uint16_t start=(uint16_t)micros();
while ((uint16_t)((uint16_t)micros()-(uint16_t)start) < 500)
{
if(CC2500_ReadReg(CC2500_35_MARCSTATE | CC2500_READ_BURST) != 0x13)
break;
}
}
NRF_CE_on;
PE1_on;PE2_off; // NRF24L01 antenna RF3
phase = OMP_DATA;
return OMP_PACKET_PERIOD-OMP_WRITE_TIME;
#endif
}
return OMP_PACKET_PERIOD;
}
uint16_t initOMP()
{
OMP_initialize_txid();
OMP_init();
hopping_frequency_no = 0;
packet_sent = 0;
#ifdef OMP_HUB_TELEMETRY
packet_count = 0;
telemetry_lost = 1;
#endif
if(IS_BIND_IN_PROGRESS)
{
bind_counter = OMP_BIND_COUNT;
phase = OMP_BIND;
}
else
phase = OMP_PREPDATA;
return OMP_INITIAL_WAIT;
}
#endif

View File

@@ -1,140 +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(OMP_NRF24L01_INO)
#include "iface_nrf250k.h"
//#define FORCE_OMP_ORIGINAL_ID
#define OMP_INITIAL_WAIT 500
#define OMP_PACKET_PERIOD 5000
#define OMP_RF_BIND_CHANNEL 35
#define OMP_RF_NUM_CHANNELS 8
#define OMP_PAYLOAD_SIZE 16
#define OMP_BIND_COUNT 600 //3sec
static void __attribute__((unused)) OMP_send_packet()
{
if(IS_BIND_IN_PROGRESS)
{
memcpy(packet,"BND",3);
memcpy(&packet[3],rx_tx_addr,5);
memcpy(&packet[8],hopping_frequency,8);
}
else
{
memset(packet,0x00,OMP_PAYLOAD_SIZE);
//hopping frequency
packet[0 ] = hopping_frequency_no; // |0x40 to request RX telemetry
XN297L_Hopping(hopping_frequency_no);
hopping_frequency_no++;
hopping_frequency_no &= OMP_RF_NUM_CHANNELS-1; // 8 RF channels
//flags
packet[1 ] = 0x08 //unknown
| GET_FLAG(CH5_SW, 0x20); // HOLD
packet[2 ] = 0x40; //unknown
if(Channel_data[CH6] > CHANNEL_MAX_COMMAND)
packet[2 ] |= 0x20; // IDLE2
else if(Channel_data[CH6] > CHANNEL_MIN_COMMAND)
packet[1 ] |= 0x40; // IDLE1
if(Channel_data[CH7] > CHANNEL_MAX_COMMAND)
packet[2 ] |= 0x08; // 3D
else if(Channel_data[CH7] > CHANNEL_MIN_COMMAND)
packet[2 ] |= 0x04; // ATTITUDE
//trims??
//packet[3..6]
//channels TAER packed 11bits
uint16_t channel=convert_channel_16b_limit(THROTTLE,0,2047);
packet[7 ] = channel;
packet[8 ] = channel>>8;
channel=convert_channel_16b_limit(AILERON,2047,0);
packet[8 ] |= channel<<3;
packet[9 ] = channel>>5;
channel=convert_channel_16b_limit(ELEVATOR,0,2047);
packet[9] |= channel<<6;
packet[10] = channel>>2;
packet[11] = channel>>10;
channel=convert_channel_16b_limit(RUDDER,2047,0);
packet[11] |= channel<<1;
packet[12] = channel>>7;
//unknown
//packet[13..15]
packet[15] = 0x04;
}
XN297L_SetPower(); // Set tx_power
XN297L_SetFreqOffset(); // Set frequency offset
XN297L_WriteEnhancedPayload(packet, OMP_PAYLOAD_SIZE, IS_BIND_IN_PROGRESS);
}
static void __attribute__((unused)) OMP_init()
{
XN297L_Init();
XN297L_SetTXAddr((uint8_t*)"FLPBD", 5);
XN297L_HoppingCalib(OMP_RF_NUM_CHANNELS); // Calibrate all channels
XN297L_RFChannel(OMP_RF_BIND_CHANNEL); // Set bind channel
}
static void __attribute__((unused)) OMP_initialize_txid()
{
calc_fh_channels(OMP_RF_NUM_CHANNELS);
#ifdef FORCE_OMP_ORIGINAL_ID
rx_tx_addr[0]=0x4E;
rx_tx_addr[1]=0x72;
rx_tx_addr[2]=0x8E;
rx_tx_addr[3]=0x70;
rx_tx_addr[4]=0x62;
for(uint8_t i=0; i<OMP_RF_NUM_CHANNELS;i++)
hopping_frequency[i]=(i+3)*5;
#endif
}
uint16_t OMP_callback()
{
if(IS_BIND_IN_PROGRESS)
if(--bind_counter==0)
{
BIND_DONE;
XN297L_SetTXAddr(rx_tx_addr, 5);
}
OMP_send_packet();
#ifdef MULTI_SYNC
telemetry_set_input_sync(OMP_PACKET_PERIOD);
#endif
return OMP_PACKET_PERIOD;
}
uint16_t initOMP()
{
OMP_initialize_txid();
OMP_init();
hopping_frequency_no = 0;
if(IS_BIND_IN_PROGRESS)
bind_counter=OMP_BIND_COUNT;
else
XN297L_SetTXAddr(rx_tx_addr, 5);
return OMP_INITIAL_WAIT;
}
#endif

View File

@@ -31,87 +31,63 @@ enum {
RLINK_RX2 = 0x02,
};
const PROGMEM uint8_t RLINK_hopping[][8] = {
/* 4C494E4B */ { 0xBC, 0x5A, 0x70, 0x4E, 0xDF, 0x32, 0x16, 0x89 },
/* 4D494E4B */ { 0x4C, 0xF3, 0xEA, 0x5B, 0x62, 0x9D, 0x01, 0x87 },
/* 4E494E4B */ { 0x86, 0xEA, 0xD0, 0xC9, 0x2B, 0x53, 0x7F, 0x41 },
/* 4F494E4B */ { 0xAC, 0x91, 0x7D, 0x48, 0xE0, 0xB5, 0x32, 0xF6 },
/* 50494E4B */ { 0xD6, 0x7C, 0xA4, 0x93, 0x5F, 0xE1, 0x02, 0xB8 },
/* 51494E4B */ { 0xED, 0x04, 0x73, 0xC8, 0x56, 0xB9, 0x1F, 0xA2 },
/* 52494E4B */ { 0xA7, 0xF0, 0x36, 0xB2, 0x95, 0x4E, 0x1C, 0xD8 },
/* 53494E4B */ { 0x76, 0x8B, 0xA0, 0x3E, 0x51, 0x4C, 0x9D, 0x2F },
/* 54494E4B */ { 0x07, 0x23, 0x16, 0xFD, 0xC9, 0x5B, 0x84, 0xAE },
/* 55494E4B */ { 0xD3, 0xA0, 0x69, 0xBF, 0x12, 0x8C, 0x4E, 0x57 },
/* 56494E4B */ { 0xA6, 0xBE, 0x91, 0xD3, 0x7C, 0x4F, 0x82, 0x50 },
/* 57494E4B */ { 0x91, 0xDA, 0xBC, 0x75, 0x82, 0x36, 0x4E, 0xF0 },
/* 58494E4B */ { 0x9A, 0x27, 0x5C, 0xF4, 0xD8, 0xB0, 0x36, 0xE1 },
/* 59494E4B */ { 0x92, 0xF1, 0x34, 0xA7, 0x5B, 0x0C, 0xED, 0x86 },
/* 5A494E4B */ { 0x8C, 0x2B, 0x51, 0xF9, 0x3E, 0x4A, 0x67, 0xD0 },
/* 5B494E4B */ { 0x5E, 0x3D, 0x67, 0x9B, 0xA2, 0x84, 0xFC, 0x01 },
/* 5C494E4B */ { 0xF9, 0x35, 0xBD, 0x78, 0x26, 0x1C, 0x0E, 0xA4 },
/* 5D494E4B */ { 0xD9, 0x7B, 0x48, 0x0E, 0x2A, 0xCF, 0x13, 0x65 },
/* 5E494E4B */ { 0x07, 0xE4, 0xF9, 0x8A, 0x3C, 0x21, 0xB5, 0xD6 },
/* 5F494E4B */ { 0xEB, 0xFA, 0x29, 0xD1, 0x54, 0x3C, 0x07, 0x86 },
/* 60494E4B */ { 0xDF, 0xCE, 0x0A, 0x32, 0x71, 0x5B, 0x96, 0x48 },
/* 61494E4B */ { 0x19, 0x86, 0xF5, 0x3A, 0x27, 0xDC, 0x0E, 0xB4 },
/* 62494E4B */ { 0xF8, 0x47, 0x9C, 0xE0, 0x2D, 0xBA, 0x15, 0x36 },
/* 63494E4B */ { 0xED, 0x78, 0x01, 0xA3, 0x2B, 0x6C, 0x45, 0xF9 },
/* 64494E4B */ { 0xE0, 0xA2, 0xD4, 0x6B, 0xF5, 0x18, 0x3C, 0x79 },
/* 65494E4B */ { 0x26, 0x90, 0x8B, 0x5D, 0x31, 0xCF, 0xE7, 0x4A },
/* 66494E4B */ { 0x7B, 0x12, 0xA8, 0x4F, 0xC0, 0x65, 0xD9, 0x3E },
/* 67494E4B */ { 0x35, 0xA2, 0x14, 0xBE, 0x06, 0x7D, 0x98, 0xFC },
/* 68494E4B */ { 0xD2, 0xA9, 0x7E, 0x40, 0x6F, 0x83, 0x5C, 0xB1 },
/* 69494E4B */ { 0xE5, 0xB9, 0xC1, 0x04, 0x83, 0x27, 0xA6, 0xFD },
/* 6A494E4B */ { 0x8E, 0x0C, 0x4A, 0x51, 0xFB, 0x63, 0x92, 0x7D },
/* 6B494E4B */ { 0xC7, 0x1D, 0x02, 0x93, 0x45, 0xF8, 0xA6, 0xBE },
/* 6C494E4B */ { 0xC1, 0x64, 0x59, 0x0A, 0x7D, 0x3F, 0x28, 0xEB },
/* 6D494E4B */ { 0xEF, 0x75, 0xAB, 0x94, 0xD2, 0x83, 0x1C, 0x60 },
/* 6E494E4B */ { 0xA1, 0x20, 0x54, 0x68, 0x9E, 0x7B, 0x3D, 0xFC },
/* 6F494E4B */ { 0x3E, 0x60, 0x28, 0xFC, 0xDA, 0x45, 0x9B, 0x71 },
/* 70494E4B */ { 0xB7, 0x0E, 0xA8, 0x23, 0xFC, 0x65, 0x4D, 0x91 },
/* 71494E4B */ { 0x29, 0x34, 0x51, 0x7C, 0xB8, 0xFD, 0x0E, 0x6A },
/* 72494E4B */ { 0x1B, 0x06, 0x3C, 0x89, 0xF5, 0x2A, 0x7E, 0xD4 },
/* 73494E4B */ { 0xF2, 0xC9, 0x63, 0x57, 0x0A, 0xB1, 0x48, 0xDE },
/* 74494E4B */ { 0x24, 0xAE, 0x0C, 0x19, 0x53, 0x7B, 0xF6, 0x8D },
/* 75494E4B */ { 0xEC, 0xD8, 0xF2, 0x4B, 0xA3, 0x51, 0x09, 0x76 },
/* 76494E4B */ { 0x98, 0x71, 0x5E, 0xAD, 0xFC, 0x04, 0x3B, 0x62 },
/* 77494E4B */ { 0xAE, 0xF6, 0xB7, 0x01, 0x52, 0x34, 0x9D, 0x8C },
/* 78494E4B */ { 0x69, 0x48, 0xF1, 0x3C, 0xDB, 0x0E, 0x25, 0xA7 },
/* 79494E4B */ { 0xCF, 0x60, 0x94, 0xAD, 0xB1, 0x82, 0x73, 0xE5 },
/* 7A494E4B */ { 0xFA, 0xC1, 0xD7, 0xB0, 0x53, 0x92, 0x6E, 0x48 },
/* 7B494E4B */ { 0xAC, 0x7D, 0xE5, 0x8B, 0x41, 0x96, 0x2F, 0x30 },
/* 7C494E4B */ { 0xFD, 0xC1, 0xB9, 0x02, 0xE4, 0x87, 0x56, 0x3A },
/* 7D494E4B */ { 0x30, 0xDA, 0x4F, 0x8E, 0x5C, 0xB9, 0x26, 0x71 },
/* 7E494E4B */ { 0xDC, 0xF9, 0x57, 0x30, 0x82, 0x1E, 0x6A, 0x4B },
/* 7F494E4B */ { 0x84, 0x1D, 0x7E, 0x29, 0x3C, 0x65, 0xA0, 0xBF },
/* 80494E4B */ { 0x01, 0xA3, 0xF6, 0xE2, 0x4C, 0x8B, 0x5D, 0x79 },
/* 81494E4B */ { 0xA1, 0x32, 0xE7, 0x08, 0x4D, 0x5B, 0x9F, 0x6C },
/* 82494E4B */ { 0x31, 0x40, 0x67, 0x8F, 0xBA, 0x95, 0x2C, 0xED },
/* 83494E4B */ { 0x91, 0x76, 0xFA, 0x83, 0x20, 0x4B, 0xEC, 0x5D },
/* 84494E4B */ { 0xDB, 0x54, 0xC2, 0x61, 0xF0, 0xA9, 0x87, 0x3E },
/* 85494E4B */ { 0xC0, 0xB4, 0x61, 0xD3, 0x7A, 0x5F, 0x82, 0x9E },
/* 86494E4B */ { 0xD6, 0xCF, 0x9B, 0x75, 0xE1, 0x42, 0x3A, 0x80 },
/* 87494E4B */ { 0xFE, 0xA2, 0xB4, 0x9C, 0x10, 0x7D, 0x56, 0x83 },
/* 88494E4B */ { 0xD2, 0x79, 0x54, 0xEF, 0xC8, 0x0B, 0x36, 0xA1 },
/* 89494E4B */ { 0x8D, 0xCF, 0x23, 0x64, 0xE5, 0x0B, 0x1A, 0x97 },
/* 8A494E4B */ { 0x07, 0xC4, 0xEF, 0x9A, 0x61, 0xD8, 0xB3, 0x52 },
/* 8B494E4B */ { 0x45, 0x6E, 0xBF, 0x8C, 0x9A, 0x2D, 0x31, 0x70 },
#ifdef RLINK_FORCE_ID
/* 3A99223A */ { 0x1F, 0x89, 0x25, 0x06, 0x4E, 0xBD, 0x3A, 0xC7 },
/* FC110D20 */ { 0xBC, 0xFE, 0x59, 0x84, 0x37, 0xA1, 0xD0, 0x62 }
#endif
};
uint32_t RLINK_rand1;
uint32_t RLINK_rand2;
static void __attribute__((unused)) RLINK_load_hopp(uint8_t num)
static uint32_t __attribute__((unused)) RLINK_prng_next(uint32_t r)
{
return 0xA5E2A705 * r + 0x754DB79B;
}
static void __attribute__((unused)) RLINK_init_random(uint32_t id)
{
uint32_t result = id;
RLINK_rand2 = result;
for (uint8_t i=0; i<31; i++)
result = RLINK_prng_next(result);
RLINK_rand1 = result;
}
static uint8_t __attribute__((unused)) RLINK_next_random_swap()
{
uint8_t result = (RLINK_rand2 >> 16) + RLINK_rand2 + (RLINK_rand1 >> 16) + RLINK_rand1;
RLINK_rand2 = RLINK_prng_next(RLINK_rand2);
RLINK_rand1 = RLINK_prng_next(RLINK_rand1);
return result & 0x0F;
}
static uint32_t __attribute__((unused)) RLINK_compute_start_id(uint32_t id)
{
return id * 0xF65EF9F9u + 0x2EDDF6CAu;
}
static void __attribute__((unused)) RLINK_shuffle_freqs(uint32_t seed)
{
RLINK_init_random(seed);
for(uint8_t i=0; i<RLINK_HOP; i++)
{
uint8_t r = RLINK_next_random_swap();
uint8_t tmp = hopping_frequency[r];
hopping_frequency[r] = hopping_frequency[i];
hopping_frequency[i] = tmp;
}
}
static void __attribute__((unused)) RLINK_hop()
{
uint8_t inc=3*(rx_tx_addr[0]&3);
for (uint8_t i = 0; i < RLINK_HOP>>1; i++)
{
uint8_t val=pgm_read_byte_near(&RLINK_hopping[num][i]);
hopping_frequency[ i<<1 ]=12*(val>>4 )+inc;
hopping_frequency[(i<<1)+1]=12*(val&0x0F)+inc;
}
// init hop table
for(uint8_t i=0; i<RLINK_HOP; i++)
hopping_frequency[i] = (12*i) + inc;
// shuffle
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)));
// replace one of the channel randomely
rf_ch_num=random(0xfefefefe)%0x11; // 0x00..0x10
@@ -121,30 +97,25 @@ static void __attribute__((unused)) RLINK_load_hopp(uint8_t num)
static void __attribute__((unused)) RLINK_init()
{
// channels order depend on ID and currently unknown so using a table of 64 entries...
uint8_t id=rx_tx_addr[3]&0x3F;
memcpy(rx_tx_addr,"\x4C\x49\x4E\x4B",RLINK_TX_ID_LEN);
rx_tx_addr[0] += id;
RLINK_load_hopp(id);
#ifdef RLINK_FORCE_ID
//surface RC6GS
memcpy(rx_tx_addr,"\x3A\x99\x22\x3A",RLINK_TX_ID_LEN);
RLINK_load_hopp(64);
//air T8FB
//memcpy(rx_tx_addr,"\xFC\x11\x0D\x20",RLINK_TX_ID_LEN);
//RLINK_load_hopp(65);
#endif
// channels order depend on ID
RLINK_hop();
/* debug("ID:");
for(uint8_t i=0;i<RLINK_TX_ID_LEN;i++)
debug(" 0x%02X",rx_tx_addr[i]);
debugln("");
debug("Hop(%d):", rf_ch_num);
for(uint8_t i=0;i<RLINK_HOP;i++)
debug(" 0x%02X",hopping_frequency[i]);
debugln("");
*/
#if 0
debug("ID:");
for(uint8_t i=0;i<RLINK_TX_ID_LEN;i++)
debug(" 0x%02X",rx_tx_addr[i]);
debugln("");
debug("Hop(%d):", rf_ch_num);
for(uint8_t i=0;i<RLINK_HOP;i++)
debug(" 0x%02X",hopping_frequency[i]);
debugln("");
#endif
}
const PROGMEM uint8_t RLINK_init_values[] = {

View File

@@ -531,7 +531,7 @@ void frsky_link_frame()
telemetry_link |= 2 ; // Send hub if available
}
else
{//PROTO_HUBSAN, PROTO_AFHDS2A, PROTO_BAYANG, PROTO_NCC1701, PROTO_CABELL, PROTO_HITEC, PROTO_BUGS, PROTO_BUGSMINI, PROTO_FRSKYX, PROTO_FRSKYX2, PROTO_PROPEL, PROTO_DEVO, PROTO_RLINK
{//PROTO_HUBSAN, PROTO_AFHDS2A, PROTO_BAYANG, PROTO_NCC1701, PROTO_CABELL, PROTO_HITEC, PROTO_BUGS, PROTO_BUGSMINI, PROTO_FRSKYX, PROTO_FRSKYX2, PROTO_PROPEL, PROTO_DEVO, PROTO_RLINK, PROTO_OMP
frame[1] = v_lipo1;
frame[2] = v_lipo2;
frame[3] = RX_RSSI;
@@ -952,7 +952,7 @@ void TelemetryUpdate()
#endif
if( telemetry_link & 1 )
{ // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs + BugsMini + NCC1701 + PROPEL + RLINK
{ // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs + BugsMini + NCC1701 + PROPEL + RLINK + OMP
// FrSkyX telemetry if in PPM
frsky_link_frame();
return;

View File

@@ -247,6 +247,7 @@
#undef FRSKY_RX_CC2500_INO
#undef HITEC_CC2500_INO
#undef HOTT_CC2500_INO
#undef OMP_CC2500_INO
#undef REDPINE_CC2500_INO
#undef RLINK_CC2500_INO
#undef SCANNER_CC2500_INO
@@ -281,7 +282,7 @@
#undef MJXQ_NRF24L01_INO
#undef MT99XX_NRF24L01_INO
#undef NCC1701_NRF24L01_INO
#undef OMP_NRF24L01_INO
#undef OMP_CC2500_INO
#undef POTENSIC_NRF24L01_INO
#undef PROPEL_NRF24L01_INO
#undef Q303_NRF24L01_INO
@@ -340,6 +341,7 @@
#undef BAYANG_RX_NRF24L01_INO
#undef DEVO_HUB_TELEMETRY
#undef PROPEL_HUB_TELEMETRY
#undef OMP_HUB_TELEMETRY
#undef RLINK_HUB_TELEMETRY
#undef DSM_RX_CYRF6936_INO
#else
@@ -368,6 +370,9 @@
#if not defined(DEVO_CYRF6936_INO)
#undef DEVO_HUB_TELEMETRY
#endif
#if not defined(OMP_CC2500_INO)
#undef OMP_HUB_TELEMETRY
#endif
#if not defined(PROPEL_NRF24L01_INO)
#undef PROPEL_HUB_TELEMETRY
#endif
@@ -410,7 +415,7 @@
#if not defined(HOTT_CC2500_INO)
#undef HOTT_FW_TELEMETRY
#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)
#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)
#undef TELEMETRY
#undef INVERT_TELEMETRY
#undef MULTI_TELEMETRY

View File

@@ -194,6 +194,7 @@
#define FRSKY_RX_CC2500_INO
#define HITEC_CC2500_INO
#define HOTT_CC2500_INO
#define OMP_CC2500_INO //Need both CC2500 and NRF
#define SCANNER_CC2500_INO
#define SFHSS_CC2500_INO
#define SKYARTEC_CC2500_INO
@@ -227,7 +228,6 @@
#define MJXQ_NRF24L01_INO
#define MT99XX_NRF24L01_INO
#define NCC1701_NRF24L01_INO
#define OMP_NRF24L01_INO
#define POTENSIC_NRF24L01_INO
#define PROPEL_NRF24L01_INO
#define Q303_NRF24L01_INO
@@ -262,6 +262,9 @@
// For example, a value of -80% applied on channel 14 will instantly kill the motors on the X-Vert.
#define DSM_THROTTLE_KILL_CH 14
//Enable DSM Forward Programming
#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).
@@ -315,6 +318,7 @@
#define DEVO_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define HUBSAN_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 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 RLINK_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX

View File

@@ -110,7 +110,7 @@ CFlie|38|CFlie||||||||NRF24L01|
[MJXq](Protocols_Details.md#MJXQ---18)|18|WLH08|X600|X800|H26D|E010*|H26WH|PHOENIX*||NRF24L01|XN297
[MT99xx](Protocols_Details.md#MT99XX---17)|17|MT|H7|YZ|LS|FY805||||NRF24L01|XN297
[NCC1701](Protocols_Details.md#NCC1701---44)|44|NCC1701||||||||NRF24L01|
[OMP](Protocols_Details.md#OMP---77)|77|||||||||NRF24L01|XN297L
[OMP](Protocols_Details.md#OMP---77)|77|||||||||CC2500&NRF24L01|XN297L
[OpenLRS](Protocols_Details.md#OpenLRS---27)|27|||||||||None|
[Pelikan](Protocols_Details.md#Pelikan---60)|60|Pro|Lite|||||||A7105|
[Potensic](Protocols_Details.md#Potensic---51)|51|A20||||||||NRF24L01|XN297
@@ -552,6 +552,28 @@ Recommended for best telemetry performance.
Telemetry compatibility mode when Sync does not work due to an old firmware on the RX.
You should definitively upgrade your receivers/sensors to the latest firmware versions: https://www.rcgroups.com/forums/showpost.php?p=44668015&postcount=18022
## OMP - *77*
Model: OMPHOBBY M2 Heli, T720 RC Glider
Telemetry supported:
- A1 = battery voltage including "recovered" battery voltage from bad telemetry packets
- A2 = battery voltage from only good packets
- You must adjust the offset with a voltmeter since there are some large differences between the models
- RX_RSSI = TQly = percentage of received telemetry packets (good and bad) received from the model which has nothing to do with well the RX is receiving the TX
- Telemetry is using the NRF24L01 RF component @250K so depending on your module it might not work so well
Option for this protocol corresponds to the CC2500 fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T_PITCH|R|T_HOLD|IDLE|MODE
IDLE= 3 pos switch: -100% Normal, 0% Idle1, +100% Idle2
From the TX manual: MODE= 3 pos switch -100% Attitude, 0% Attitude(?), +100% 3D
For M2: MODE= 3 pos switch -100% 6G, 0% 3D, +100% 3D
## Scanner - *54*
2.4GHz scanner accessible using the OpenTX 2.3 Spectrum Analyser tool.
@@ -559,8 +581,6 @@ You should definitively upgrade your receivers/sensors to the latest firmware ve
Extended limits
**64 IDs available, use RX num to scroll through them**
Option for this protocol corresponds to fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
@@ -752,6 +772,7 @@ The DSM receiver protocol enables master/slave trainning, separate access from 2
Notes:
- Automatically detect DSM 2/X 11/22ms 1024/2048res
- Bind should be done with all other modules off in the radio
- Available in OpenTX 2.3.3+, Trainer Mode Master/Multi
- Channels 1..4 are remapped to the module default channel order unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
- Extended limits supported
@@ -1279,21 +1300,6 @@ CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A|E|T|R|Warp
## OMP - *77*
Model: OMPHOBBY M2
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T_PITCH|R|T_HOLD|IDLE|MODE
IDLE= 3 pos switch: -100% Normal, 0% Idle1, +100% Idle2
MODE= 3 pos switch -100% Attitude(?), 0% Attitude, +100% 3D
## Potensic - *51*
Model: Potensic A20

View File

@@ -19,11 +19,12 @@ If you like this project and want to support further development please consider
## Development status
Multiprotocol downloads: <img src=https://img.shields.io/github/downloads/pascallanger/DIY-Multiprotocol-TX-Module/total.svg>
Current Multiprotocol code check status: [![Travis Build Status for Multi](https://api.travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module.svg?branch=master)](https://travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module)
Current Multiprotocol boards check status: [![Travis Build Status for Multi Boards](https://api.travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module-Boards.svg?branch=master)](https://travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module-Boards)
## Quicklinks
* [Download latest releases of the firmware](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/releases) and [instructions to upload .hex files](docs/Advanced_Manually_Setting_ATmega328_Fuses.md)
* [Forum on rcgroups](http://www.rcgroups.com/forums/showthread.php?t=2165676)

View File

@@ -17,6 +17,7 @@
- **_Slower blink(on=1s,off=1s)_**: PPM has been selected but no valid signal is being seen on the PPM pin.
- **_Fast double blink(on=0.1s,off=0.1s,on=0.1s,off=0.5s)_**: serial debugging is enabled and is waiting for a serial connection
- **_On_**: Module is in normal operation mode (transmitting control signals).
- **_SOS_**: Module's CPU does not match the minimum requirement of a full 128KB available/good flash. The module won't boot further. This has been introduced after finding out that some module's manufacturers are using wrong components which are causing unexpected behaviors with bad consequences...
## Protocol selection