Compare commits

...

54 Commits

Author SHA1 Message Date
pascallanger
2bd50f4c8c V761/TOPRC: new sub protocol
Top RC Hobby mini planes
2022-09-26 12:02:38 +02:00
yakulis
4c2ddcbe48 Update DSM FwdPrg.lua (#733)
Reversing 'Off' and 'On' text values in lines #555 and #556.  They are used in the SAFE and AS3X menu items in the DSM Forward Programming section, and they are functioning backwards. This will correct the issue. This is the fix for Issue #728
2022-09-11 06:01:02 -04:00
Ben Lye
d7f9ef6967 Use devel boards in CI workflow (#709) 2022-07-21 10:20:16 +02:00
pascallanger
bfc8c2f9fd Kyosho2/KT-17: only 1 ID 2022-07-20 17:20:27 +02:00
pascallanger
ce6243d6e3 FX/620: IDs 2022-07-17 09:07:28 +02:00
pascallanger
80f9ff4163 Update FX_nrf24l01.ino 2022-07-15 15:44:10 +02:00
pascallanger
d9f8a3989a FX/FX620: only 1 ID 2022-07-15 15:43:04 +02:00
pascallanger
416f7d5c19 FX/FX620 another try 2022-07-12 08:05:41 +02:00
pascallanger
eb24dd5549 FX/FX620
I messed up the hopping, I must have looked at the wrong file.
2022-07-11 11:12:20 +02:00
pascallanger
ba19592973 FX/FX620 debug off 2022-07-11 09:11:11 +02:00
pascallanger
98d8d7fb5f FX/FX620 new protocol 2022-07-11 09:03:31 +02:00
pascallanger
ad0947b0b7 Updated MT99xx/PA18: need someone to test... 2022-07-09 00:43:28 +02:00
pascallanger
c093f21b31 Update README.md 2022-07-08 10:38:13 +02:00
pascallanger
c5a3e305f9 Update Protocols_Details.md 2022-07-08 09:46:58 +02:00
pascallanger
e085602a6c FX816 is not limited to the P38 2022-07-08 09:46:28 +02:00
pascallanger
dee25215cf Update Protocols_Details.md 2022-07-08 09:41:16 +02:00
Michael
ef1bb1ead7 adjusted comment according to change in commit da33df43 (#696) 2022-07-07 11:44:46 +02:00
pascallanger
90170493c0 Update doc 2022-06-30 17:40:55 +02:00
pascallanger
00a9057186 Update Protocols_Details.md 2022-06-28 14:24:19 +02:00
pascallanger
05c300e979 Update Protocols_Details.md 2022-06-28 10:23:20 +02:00
pascallanger
6730ed6246 Update Protocols_Details.md 2022-06-27 17:20:55 +02:00
pascallanger
0a0463652b E129/C186 protocol
C186/E120 models
2022-06-27 16:59:48 +02:00
pascallanger
4f580a4286 Update Hardware.md 2022-06-16 10:36:34 +02:00
Michael
0616cab386 Fixes a problem where setting failsafe values was only possible once after bind and only set values for the first 12 channels. This fix allows setting failsafe values without having to rebind and sets failsafe values correctly for all possible 16 channels. (#695)
Notes for OpenTX/EdgeTX:
This fix doesn't exhibit servo jitter if failsafe mode was left on Custom, however it is still recommended to set failsafe mode back to Receiver after setting failsafe values.
It is still necessary to wait at least 8 seconds switching back from failsafe mode Custom to failsafe mode Receiver as OpenTX/EdgeTX will trigger the data transfer in Custom mode only every 7 seconds.

Bench tested with HoTT receivers GR-16, GR-24pro, GR-32
Flight tested with HoTT receiver GR-24
2022-06-13 14:28:21 +02:00
Michael
175cfa5e93 This is the Graupner HoTT adapted version of the Model Locator script. It uses the Graupner HoTT telemetry sensor "Rssi" instead of the OpenTX sensor "RSSI". (#693)
Reasoning: The OpenTX sensor "RSSI" is populated by the individual OpenTX telemetry protocol implementations and returns a value from 0..100 (percent) originating from the early FrSky implementation. It turns out that FrSky did not really provide a genuine signal strength indicator in units of dbm but a link quality indicator in 0..100%. With Graupner HoTT the link quality indicator is not a good basis for the model locator as it is very non-linear and doesn't change much with distance. Using the Graupner HoTT telemetry sensor "Rssi" which is a true signal strength indicator serves the purpose of locating a model much better as it varies much more with distance.
2022-06-07 10:51:26 +02:00
Pascal Langer
dbfccad568 Update DSM FwdPrg.lua 2022-04-25 10:33:16 +02:00
Pascal Langer
3fe6dc64fa KF606/MIG320: Added LED control 2022-04-15 17:29:25 +02:00
Peter Feerick
49068af59f fix: MultiConfig lua set and reset subProtocol (#672) 2022-03-25 09:12:14 +01:00
pascallanger
fbd81c6e26 Update Protocols_Details.md 2022-02-07 18:49:38 +01:00
Ryan5732
9cac96d6a7 Small Readme Typos (#661) 2022-02-03 14:11:26 +01:00
Pascal Langer
5987aa40a6 Another try on PA18 2022-01-25 15:21:22 +01:00
Pascal Langer
30cb812549 Try PA18 2022-01-24 08:36:00 +01:00
Pascal Langer
0fd2e36046 test PA18 2022-01-23 19:08:46 +01:00
Pascal Langer
8b05e55ebd MT99xx2/PA18: new protocol 2022-01-23 17:56:00 +01:00
Pascal Langer
af71a208fd Ready for release 2022-01-16 11:00:50 +01:00
mheimlich
7e5cb8e884 mention XK A800 in V911S/E119 details (#654) 2022-01-16 10:54:04 +01:00
MattCarothers
8c669ea015 Updated several text fields (#651) 2022-01-09 17:25:11 +01:00
Anders Höglund
acd8379077 A few more Spektrum Fwd Programming text updates (#632)
* DSM FP, Added AR8360T

* DSM FP, Added a few unkown empty lines
2021-11-19 08:37:28 +01:00
Pascal Langer
97c6088715 fix compilation? 2021-11-13 19:08:38 +01:00
Pascal Langer
db017c73b6 HS6200 emulation using CYRF for E01X protocol 2021-11-13 19:03:01 +01:00
Anders Höglund
24aaa0dd0c Text updates in Spektrum Fwd Prog LUA script (#630)
* DSM FP, Added AR636B

* DSM FP, Added AR637TA

* DSM FP, Added On, conflict with AR636B

* DSM FP, Rx name conflict resolved.
2021-11-12 18:37:52 +01:00
Michael
da33df4346 added packet_in[14] to transfer HoTT device warnings to OpenTx (#627) 2021-11-04 14:57:25 +01:00
Pascal Langer
22590ed4f7 Update DSM FwdPrg.lua 2021-10-26 16:34:38 +02:00
Pascal Langer
c0bc64c2aa V911S: increased bind time 2021-10-24 12:03:09 +02:00
Pascal Langer
694d968e8c Update Propel_nrf24l01.ino 2021-10-24 11:04:57 +02:00
Pascal Langer
fff3b8830e MT99xx/A180: F949S flags for RATE, RXLED and 3D6G 2021-10-24 11:04:44 +02:00
Pascal Langer
b740f4cd24 V911S/E119: add 6G_3D channel for P40 plane 2021-10-24 09:57:24 +02:00
Pascal Langer
e247b8b9c1 DSM Fwd Pgm updated 2021-10-20 15:13:56 +02:00
Pascal Langer
4f7af553d1 Update doc 2021-09-17 17:07:15 +02:00
Pascal Langer
570e6f8c64 Update Protocols_Details.md 2021-09-17 09:48:35 +02:00
Pascal Langer
b6e665b567 Devo: fix typo 2021-09-16 16:13:39 +02:00
Pascal Langer
48e82304a0 Update Devo_cyrf6936.ino 2021-09-16 00:30:46 +02:00
Pascal Langer
7b58b9aca0 Devo: support for 2 GPS formats
Use the Fixed ID field, 0/1 first GPS format, +2 for the other format -> 2/3
2021-09-16 00:11:25 +02:00
Pascal Langer
dfcf3f533c Update NRF24l01_SPI.ino 2021-09-16 00:08:47 +02:00
34 changed files with 1490 additions and 635 deletions

View File

@@ -40,14 +40,14 @@ jobs:
fail-fast: false
matrix:
board: [
"multi4in1:avr:multiatmega328p:bootloader=none",
"multi4in1:avr:multiatmega328p:bootloader=optiboot",
"multi4in1:avr:multixmega32d4",
"multi4in1:STM32F1:multi5in1t18int",
"multi4in1:STM32F1:multistm32f103cb:debug_option=none",
"multi4in1:STM32F1:multistm32f103cb:debug_option=native",
"multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi",
"multi4in1:STM32F1:multistm32f103c8:debug_option=none"
"multi4in1-devel:avr:multiatmega328p:bootloader=none",
"multi4in1-devel:avr:multiatmega328p:bootloader=optiboot",
"multi4in1-devel:avr:multixmega32d4",
"multi4in1-devel:STM32F1:multi5in1t18int",
"multi4in1-devel:STM32F1:multistm32f103cb:debug_option=none",
"multi4in1-devel:STM32F1:multistm32f103cb:debug_option=native",
"multi4in1-devel:STM32F1:multistm32f103cb:debug_option=ftdi",
"multi4in1-devel:STM32F1:multistm32f103c8:debug_option=none"
]
# Set the environment variables
@@ -67,15 +67,22 @@ jobs:
echo "Event action: ${{ github.event.action }}"
echo "Tag name: ${{ github.event.release.tag_name }}"
arduino-cli config init --additional-urls https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/master/package_multi_4in1_board_index.json
arduino-cli config init --additional-urls https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/master/package_multi_4in1_board_index.json,https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/devel/source/package_multi_4in1_board_devel_index.json
arduino-cli core update-index
if [[ "$BOARD" =~ "multi4in1:avr:" ]]; then
if [[ "$BOARD" =~ ":avr:" ]]; then
arduino-cli core install arduino:avr;
fi
if [[ "$BOARD" =~ "multi4in1-devel:avr" ]]; then
arduino-cli core install multi4in1-devel:avr
elif [[ "$BOARD" =~ "multi4in1:avr" ]]; then
arduino-cli core install multi4in1:avr
fi
if [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
if [[ "$BOARD" =~ "multi4in1-devel:STM32F1:" ]]; then
arduino-cli core install multi4in1-devel:STM32F1
elif [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
arduino-cli core install multi4in1:STM32F1
fi
@@ -109,18 +116,18 @@ jobs:
echo "ALL_RFMODULES=$(echo $ALL_RFMODULES)" >> $GITHUB_ENV
# Disable CHECK_FOR_BOOTLOADER when not needed
if [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=none" ]]; then
if [[ "$BOARD" =~ ":avr:multiatmega328p:bootloader=none" ]]; then
opt_disable CHECK_FOR_BOOTLOADER;
fi
# Trim the build down for the Atmega328p board
if [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:" ]]; then
if [[ "$BOARD" =~ ":avr:multiatmega328p:" ]]; then
opt_disable $ALL_PROTOCOLS
opt_enable FRSKYX_CC2500_INO AFHDS2A_A7105_INO MJXQ_NRF24L01_INO DSM_CYRF6936_INO;
fi
# Trim the enabled protocols down for the STM32F103CB board with debugging or the STM32F103C8 board in general
if [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi" ]] || [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=native" ]] || [[ "$BOARD" =~ "multi4in1:STM32F1:multistm32f103c8" ]]; then
if [[ "$BOARD" =~ ":STM32F1:multistm32f103cb:debug_option=ftdi" ]] || [[ "$BOARD" =~ ":STM32F1:multistm32f103cb:debug_option=native" ]] || [[ "$BOARD" =~ ":STM32F1:multistm32f103c8" ]]; then
opt_disable $ALL_PROTOCOLS;
opt_enable FRSKYX_CC2500_INO AFHDS2A_A7105_INO MJXQ_NRF24L01_INO DSM_CYRF6936_INO;
fi
@@ -133,7 +140,7 @@ jobs:
- name: Build default configuration
run: |
# Skip the default build for boards where it's too large now
if [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=none" ]] || [[ "$BOARD" == "multi4in1:STM32F1:multi5in1t18int" ]]; then
if [[ "$BOARD" =~ ":STM32F1:multistm32f103cb:debug_option=none" ]] || [[ "$BOARD" =~ ":STM32F1:multi5in1t18int" ]]; then
printf "Not testing default build for $BOARD.";
else
source ./buildroot/bin/buildFunctions;

317
Lua_scripts/DSM FwdPrg.lua Normal file → Executable file
View File

@@ -1,4 +1,4 @@
local toolName = "TNS|DSM Forward Programming|TNE"
local toolName = "TNS|DSM Forward Programming v0.2|TNE"
---- #########################################################################
---- # #
@@ -31,11 +31,12 @@ local toolName = "TNS|DSM Forward Programming|TNE"
-- 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 RX_VERSION, WAIT_CMD, MENU_TITLE, MENU_LINES, MENU_VALUES, VALUE_CHANGING, VALUE_CHANGING_WAIT, VALUE_CHANGED, EXIT, EXIT_DONE = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
local MENU, LIST_MENU_NOCHANGING, LIST_MENU1, LIST_MENU2, VALUE_NOCHANGING = 0x1C, 0x6C, 0x0C, 0x4C, 0x60
local Phase = RX_VERSION
local Waiting_RX = 0
local Text = {}
local RxName = {}
local Retry=100
local Blink = 0
local Value_Changed=0
@@ -44,13 +45,30 @@ local Menu = { Cur=nil, Id=nil, Title="", Prev=nil, PrevId=nil, Next=nil, NextId
local Line = {}
local RX = { Name="", Version="" }
-- used for debug
local rxAnswer = ""
local debugLine = 0
------------------------------------------------------------------------------------------------------------
local function GetDebugInfo(lineNr) -- used for debug
local i
debugLine = lineNr
rxAnswer = "RX:"
for i=10, 25 do
rxAnswer = rxAnswer.." "..string.format("%02X", multiBuffer(i))
end
end
------------------------------------------------------------------------------------------------------------
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...
@@ -58,11 +76,20 @@ local function Get_Text(index)
end
return out
end
------------------------------------------------------------------------------------------------------------
local function Get_RxName(index)
out = RxName[index]
if out == nil then -- unknown...
out = "Unknown_"..string.format("%X",index)
end
return out
end
------------------------------------------------------------------------------------------------------------
local function DSM_Release()
multiBuffer( 0, 0 )
Phase = EXIT_DONE
end
------------------------------------------------------------------------------------------------------------
local function DSM_Send(...)
local arg = {...}
for i = 1 , #arg do
@@ -70,7 +97,7 @@ local function DSM_Send(...)
end
multiBuffer( 3, 0x70+#arg)
end
------------------------------------------------------------------------------------------------------------
local function Value_Add(dir)
local line=Line[Menu.SelLine]
Speed = getRotEncSpeed()
@@ -91,17 +118,25 @@ local function Value_Add(dir)
Waiting_RX = 0
end
end
------------------------------------------------------------------------------------------------------------
local function DSM_Menu(event)
local Speed = 0
if event == EVT_VIRTUAL_NEXT then
if event == EVT_VIRTUAL_EXIT then
if Phase == RX_VERSION then
DSM_Release()
else
Phase = EXIT
Waiting_RX = 0
end
elseif 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
if Line[i].Type ~= nil and Line[i].Next ~= nil and Line[i].Type ~= VALUE_NOCHANGING then
Menu.SelLine=i
break
end
@@ -131,7 +166,7 @@ local function DSM_Menu(event)
end
local num = Menu.SelLine
for i = Menu.SelLine-1, 0, -1 do
if Line[i].Type ~= nil and Line[i].Next ~= nil then
if Line[i].Type ~= nil and Line[i].Next ~= nil and Line[i].Type ~= VALUE_NOCHANGING then
Menu.SelLine=i
break
end
@@ -146,6 +181,15 @@ local function DSM_Menu(event)
else -- need to dec the value
Value_Add(-1)
end
elseif event == EVT_VIRTUAL_ENTER_LONG then
if Menu.EditLine ~= nil then
-- reset the value to default
if Line[Menu.SelLine].Type ~= LIST_MENU_NOCHANGING then
Line[Menu.SelLine].Val = Line[Menu.SelLine].Def
Phase = VALUE_CHANGING
Waiting_RX = 0
end
end
elseif event == EVT_VIRTUAL_ENTER then
if Menu.SelLine == -1 then -- Back
Menu.Cur = Menu.Back
@@ -185,23 +229,27 @@ local function DSM_Menu(event)
end
end
end
------------------------------------------------------------------------------------------------------------
local function DSM_Send_Receive()
if Waiting_RX == 0 then
Waiting_RX = 1
-- Need to send a request
-- 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
elseif Phase == WAIT_CMD then -- keep connection open
DSM_Send(0x00,0x04,0x00,0x00)
elseif Phase == MENU_TITLE then -- request menu title
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
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
@@ -210,46 +258,59 @@ local function DSM_Send_Receive()
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
elseif Phase == MENU_VALUES then -- request menu values
DSM_Send(0x15,0x06,Menu.Id,Menu.Cur,Line[Menu.CurLine].ValId,Line[Menu.CurLine].Next) -- 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
DSM_Send(0x18,0x06,Line[Menu.SelLine].ValId,Line[Menu.SelLine].Next,bit32.rshift(value,8),bit32.band(value,0xFF)) -- send current value
Phase = VALUE_CHANGING_WAIT
elseif Phase == VALUE_CHANGED then -- send value
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
DSM_Send(0x18,0x06,Line[Menu.SelLine].ValId,Line[Menu.SelLine].Next,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
DSM_Send(0x19,0x06,Line[Menu.SelLine].ValId,Line[Menu.SelLine].Next) -- 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
elseif Phase == VALUE_CHANGING_WAIT then
DSM_Send(0x1A,0x06,Line[Menu.SelLine].ValId,Line[Menu.SelLine].Next)
elseif Phase == EXIT then
DSM_Send(0x1F,0x02,0xAA)
end
multiBuffer(10,0x00);
Retry = 50
-- -- -- -- -- -- -- -- -- -- -- -- receive part -- -- -- -- -- -- -- -- -- -- -- -- --
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))
-- GetDebugInfo(292) -- used for debug
--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_RxName(multiBuffer(13))
RX.Version = multiBuffer(14).."."..multiBuffer(15).."."..multiBuffer(16)
Phase = MENU_TITLE
elseif multiBuffer(11) == 0x02 then -- read 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)
@@ -271,7 +332,8 @@ local function DSM_Send_Receive()
end
Blink = 0
Phase = MENU_LINES
elseif multiBuffer(11) == 0x03 then -- read 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
@@ -279,13 +341,13 @@ local function DSM_Send_Receive()
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.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, 0C new list type
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 multiBuffer(18) == Menu.Cur then
-- line.Next = nil
--else
line.Next = multiBuffer(18) -- not quite sure yet: 1C=text menu=>next menu, others=>identifier of 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
@@ -297,7 +359,7 @@ local function DSM_Send_Receive()
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
elseif line.Type == LIST_MENU_NOCHANGING or line.Type == LIST_MENU1 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
@@ -305,43 +367,66 @@ local function DSM_Send_Receive()
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
if line.Type ~= MENU and line.Type ~= VALUE_NOCHANGING then -- updatable value to follow
line.Text = line.Text..":"
end
Phase = MENU_LINES
elseif multiBuffer(11) == 0x04 then -- read menu values
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)
-- Identify the line and update the value
for i = 0, 6 do
if Line[i] ~= nil and Line[i].Type ~= nil then
if Line[i].Type ~= MENU and Line[i].Next == multiBuffer(14) then -- identifier of line number stored in .Next
Line[i].Val = conv_int16(multiBuffer(16)+multiBuffer(17)*256)
Menu.CurLine = i
break
end
end
end
Phase = MENU_VALUES
elseif multiBuffer(11) == 0x05 then -- unknown... need to get through the lines...
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
elseif multiBuffer(11) == 0xA7 then -- answer to EXIT command
DSM_Release()
elseif multiBuffer(11) == 0x00 and Phase == VALUE_CHANGING then
Phase = VALUE_CHANGING_WAIT
end
-- Data processed
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 == EXIT then
DSM_Release()
end
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
--lcd.drawText(10,55,debugLine.." "..rxAnswer) -- draw debug info
--Draw title
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
lcd.drawText(1, 5, "DSM Forward Programming", MENU_TITLE_COLOR)
@@ -362,12 +447,13 @@ local function DSM_Display()
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
if Line[i].Type == LIST_MENU_NOCHANGING or Line[i].Type == LIST_MENU1 or Line[i].Type == LIST_MENU2 then
text = Get_Text(Line[i].Val+Line[i].Def)
elseif Line[i].Type == PERCENTAGE_VALUE then
elseif ( Line[i].Min == 0 and Line[i].Max == 100) or ( Line[i].Min == -100 and Line[i].Max == 100) or ( Line[i].Min == 0 and Line[i].Max == 150) or ( Line[i].Min == -150 and Line[i].Max == 150) then
text = Line[i].Val.." %"
else
text = Line[i].Val
--text = Line[i].Val .." T="..Line[i].Type -- used for debug
text = Line[i].Val
end
if Menu.EditLine == Menu.SelLine then -- blink edited entry
Blink = Blink + 1
@@ -437,7 +523,7 @@ local function DSM_Display()
-- end
end
end
------------------------------------------------------------------------------------------------------------
-- Init
local function DSM_Init()
--Set protocol to talk to
@@ -456,11 +542,30 @@ local function DSM_Init()
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"
RxName[0x0001]="AR636B"
RxName[0x0014]="SPM4651T"
RxName[0x0015]="AR637T"
RxName[0x0016]="AR637TA"
RxName[0x0018]="FC6250HX"
RxName[0x001A]="AR8360T"
RxName[0x001E]="AR631"
--Text to be displayed -> need to use a file instead?
Text[0x0001]="Off"
Text[0x0002]="On"
Text[0x0003]="Inh"
Text[0x0004]="Act"
Text[0x000C]="Inhibit?" --?
Text[0x000D]="Gear"
--Lists--
Text[0x002E]="11ms"
Text[0x002F]="22ms"
Text[0x0032]="1 X"
Text[0x0033]="2 X"
Text[0x0034]="4 X"
Text[0x0035]="Inhibit?" --?
Text[0x0036]="Throttle"
Text[0x0037]="Aileron"
Text[0x0038]="Elevator"
@@ -479,9 +584,12 @@ local function DSM_Init()
Text[0x0040]="Roll"
Text[0x0041]="Pitch"
Text[0x0042]="Yaw"
Text[0x0043]="Gain" -- FC6250HX
Text[0x0045]="Differential"
Text[0x0046]="Priority"
Text[0x0049]="Output Setup" -- FC6250HX
--******
Text[0x004A]="Failsafe"
Text[0x004B]="Main Menu"
Text[0x004E]="Position"
@@ -497,21 +605,33 @@ local function DSM_Init()
Text[0x0060]="Preset"
--Text[0x0061]="Custom"
--Messages--
Text[0x0071]="Proportional"
Text[0x0072]="Integral"
Text[0x0073]="Derivate"
Text[0x0078]="FM Channel"
Text[0x0080]="Orientation"
Text[0x0082]="Heading"
Text[0x0085]="Frame Rate"
Text[0x0086]="System Setup"
Text[0x0087]="F-Mode Setup"
Text[0x0088]="Enabled F-Modes"
Text[0x0089]="Gain Channel"
Text[0x008A]="Gain Sensitivity"
Text[0x008B]="Panic"
Text[0x0090]="Apply"
Text[0x0092]="Start"
Text[0x0093]="Complete"
Text[0x0094]="Done"
Text[0x0097]="Factory Reset"
Text[0x0099]="Advanced Setup"
Text[0x009A]="Capture Failsafe Positions"
Text[0x009C]="Custom Failsafe"
Text[0x00A5]="First Time Setup"
Text[0x00AA]="Capture Gyro Gains"
Text[0x00AD]="Gain Channel Select"
Text[0x00B0]="Self-Level/Angle Dem"
Text[0x00B1]="Envelope"
Text[0x00B5]="Inhibit"
Text[0x00B6]="FM1"
Text[0x00B7]="FM2"
Text[0x00B8]="FM3"
@@ -522,78 +642,125 @@ local function DSM_Init()
Text[0x00BD]="FM8"
Text[0x00BE]="FM9"
Text[0x00BF]="FM10"
Text[0x00C7]="Calibrate Sensor"
Text[0x00CA]="SAFE/Panic Mode Setup"
Text[0x00D3]="Swashplate"
Text[0x00D5]="Agility"
Text[0x00D8]="Stop"
Text[0x00DA]="SAFE"
Text[0x00DB]="Stability"
Text[0x00DC]="@ per sec"
Text[0x00DD]="Tail rotor"
Text[0x00DE]="Setup"
Text[0x00DF]="AFR"
Text[0x00E0]="Collective"
Text[0x00E1]="Subtrim"
Text[0x00E2]="Phasing"
Text[0x00E4]="E-Ring"
Text[0x00E7]="Left"
Text[0x00E8]="Right"
Text[0x00F2]="Fixed"
Text[0x00F3]="Adjustable"
Text[0x00F9]="Gyro settings"
Text[0x00FE]="Stick Priority"
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]="0104"
Text[0x0105]="0105"
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]="010A"
Text[0x010B]="010B"
Text[0x0190]="Relearn Servo Settings"
Text[0x019C]="Enter Receiver Bind Mode"
Text[0x01D7]="SAFE Select Channel"
Text[0x01DC]="AS3X"
Text[0x01DD]="AS3X Settings"
Text[0x01DE]="AS3X Gains"
Text[0x01E0]="Rate Gains"
Text[0x020A]="Restore from Backup"
Text[0x01E2]="SAFE Settings"
Text[0x01E3]="SAFE Gains"
Text[0x01E6]="Attitude Trim"
Text[0x01E7]="Envelope"
Text[0x01E9]="Roll Right"
Text[0x01EA]="Roll Left"
Text[0x01EB]="Pitch Down"
Text[0x01EC]="Pitch Up"
Text[0x01EE]="Throttle to Pitch"
Text[0x01EF]="Low Thr to Pitch"
Text[0x01F0]="High Thr to Pitch"
Text[0x01F3]="Threshold"
Text[0x01F4]="Angle"
Text[0x01F6]="Failsafe Angles"
Text[0x01F8]="Safe Mode"
Text[0x01F9]="SAFE Select"
Text[0x01FD]="SAFE Failsafe FMode"
Text[0x0208]="Decay"
Text[0x0209]="Save to Backup"
Text[0x020A]="Restore from Backup"
Text[0x020D]="First Time SAFE Setup"
Text[0x021A]="Set the model level,"
Text[0x021B]="and press Continue."
Text[0x021C]="021C"
Text[0x021D]="021D"
Text[0x021C]="" -- empty??
Text[0x021D]="" -- empty??
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[0x0226]="Angle Limits"
Text[0x0227]="Other settings"
Text[0x0229]="Set Orientation Manually"
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]="0230"
Text[0x0230]="" -- empty??
Text[0x0231]="This will overwrite the"
Text[0x0232]="backup memory with your"
Text[0x0233]="current configuartion."
Text[0x0234]="0234"
Text[0x0235]="0235"
Text[0x0234]="" -- blank line
Text[0x0235]="" -- blank line
Text[0x0236]="This will overwrite the"
Text[0x0237]="current config with"
Text[0x0238]="that which is in"
Text[0x0239]="the backup memory."
Text[0x023A]="023A"
Text[0x023A]="" -- blank line
Text[0x023D]="Copy Flight Mode Settings"
Text[0x0240]="Utilities"
Text[0x024C]="Gains will be captured on"
Text[0x024D]="Captured gains will be"
Text[0x024E]="Gains on"
Text[0x024F]="were captured and changed"
Text[0x0250]="from Adjustable to Fixed"
Text[0x0254]="Postive = Up, Negative = Down"
Text[0x0263]="Fixed/Adjustable Gains"
Text[0x0266]="Heading Gain"
Text[0x0267]="Positive = Nose Up/Roll Right"
Text[0x0268]="Negative = Nose Down/Roll Left"
Text[0x0269]="SAFE - Throttle to Pitch"
Text[0x026A]="Use CAUTION for Yaw gain!"
Text[0x8000]="FLIGHT MODE"
Text[0x8001]="Flight Mode 1"
Text[0x8002]="Flight Mode 2"
Text[0x8003]="Flight Mode 3"
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()
end
if Phase == EXIT_DONE then
return 2
else
return 0
end
end

View File

@@ -0,0 +1,167 @@
---- #########################################################################
---- # #
---- # Telemetry Widget script for FrSky Horus/Radio Master TX16s #
---- # Copyright (C) EdgeTX #
-----# #
---- # 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. #
---- # #
---- #########################################################################
-- Model Locator by RSSI
-- Offer Shmuely (based on code from Scott Bauer 6/21/2015)
-- Date: 2021
-- ver: 0.1
-- MHA (based on code from Offer Shmuely)
-- Date: 2022
-- ver: 0.11
-- changes: made version for Graupner HoTT. Uses real Rssi data scaled -15db to -115db to 100..0
-- This widget help to find a lost/crashed model based on the RSSI (if still available)
-- The widget produce audio representation (variometer style) of the RSSI from the lost model
-- The widget also display the RSSI in a visible colorized bar (0-100%)
-- There are two way to use it
-- 1. The simple way:
-- walk toward the quad/plane that crashed,
-- as you get closer to your model the beeps will become more frequent with higher pitch (and a visual bar graph as well)
-- until you get close enough to find it visually
-- 2. the more accurate way:
-- turn the antenna straight away (i.e. to point from you, straight away)
-- try to find the weakest signal! (not the highest), i.e. the lowest RSSI you can find, this is the direction to the model.
-- now walk to the side (not toward the model), find again the weakest signal, this is also the direction to your model
-- triangulate the two lines, and it will be :-)
local delayMillis = 100
local nextPlayTime = getTime()
local img = Bitmap.open("/SCRIPTS/TOOLS/Model Locator (by RSSI).png")
--------------------------------------------------------------
local function log(s)
--return;
print("locator: " .. s)
end
--------------------------------------------------------------
-- init_func is called once when model is loaded
local function init()
return 0
end
-- bg_func is called periodically when screen is not visible
local function bg()
return 0
end
-- This function returns green at gvalue, red at rvalue and graduate in between
local function getRangeColor(value, red_value, green_value)
local range = math.abs(green_value - red_value)
if range == 0 then
return lcd.RGB(0, 0xdf, 0)
end
if value == nil then
return lcd.RGB(0, 0xdf, 0)
end
if green_value > red_value then
if value > green_value then
return lcd.RGB(0, 0xdf, 0)
end
if value < red_value then
return lcd.RGB(0xdf, 0, 0)
end
g = math.floor(0xdf * (value - red_value) / range)
r = 0xdf - g
return lcd.RGB(r, g, 0)
else
if value > green_value then
return lcd.RGB(0, 0xdf, 0)
end
if value < red_value then
return lcd.RGB(0xdf, 0, 0)
end
r = math.floor(0xdf * (value - green_value) / range)
g = 0xdf - r
return lcd.RGB(r, g, 0)
end
end
local function main(event)
lcd.clear()
-- fetch uplink rssi (HoTT sensor Rssi)
local rssi = getValue("Rssi")
-- calculate a percentage for the color bar (range -115db to -15db)
local rssiP = rssi
if(rssi ~= 0) then -- rssi < 0 -> telemtry data received
if(rssi >= -15) then -- -15db to -1db => 100%
rssiP = 100
else
if(rssi >= -115) then -- between -115db and -15db => 0% to 100%
rssiP = 100+rssi+15
else
rssiP = 0 -- less than -115 => 0%
end
end
end
lcd.drawBitmap(img, 250, 50, 40)
-- Title
lcd.drawText(3, 3, "Graupner HoTT Rssi Model Locator", 0)
myColor = getRangeColor(rssi, 0, 100)
lcd.setColor(CUSTOM_COLOR, myColor)
-- draw current value
local dx = 0
if rssi < -99 then
dx = -33
end
if rssi == 0 then
lcd.drawText(115, 73, "no telemetry", DBLSIZE + CUSTOM_COLOR)
else
lcd.drawNumber(180+dx, 30, rssi, XXLSIZE + CUSTOM_COLOR)
lcd.drawText(275, 73, "db", 0 + CUSTOM_COLOR)
end
-- draw main bar
lcd.setColor(CUSTOM_COLOR, YELLOW) -- RED / YELLOW
local xMin = 0
local yMin = 270
local xMax = 480
local yMax = 200
local h = 0
local rssiAsX = (rssiP * xMax) / 100
for xx = xMin, rssiAsX, 20 do
lcd.setColor(CUSTOM_COLOR, getRangeColor(xx, xMin, xMax - 40))
h = h + 10
lcd.drawFilledRectangle(xx, yMin - h, 15, h, CUSTOM_COLOR)
end
-- beep
if getTime() >= nextPlayTime then
playFile("/SCRIPTS/TOOLS/Model Locator (by RSSI).wav")
nextPlayTime = getTime() + delayMillis - rssiP
end
return 0
end
return {init = init,run = main,background = bg}

View File

@@ -86,7 +86,8 @@
55,1,FrSkyRX,CloneTX,0
55,2,FrSkyRX,EraseTX,0
55,3,FrSkyRX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
58,0,FX816,P38,1
58,0,FX,816,1
58,1,FX,620,1
20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
23,0,FY326,FY326,1,Flip,RTH,HLess,Expert
@@ -115,7 +116,7 @@
71,0,JJRC345,JJRC345,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
49,1,KF606,MIG320,1,Trim
49,1,KF606,MIG320,1,Trim,LED
9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
73,0,Kyosho,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
@@ -171,8 +172,9 @@
5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD
48,0,V761,3CH,0,Gyro,Calib,Flip,RtnAct,Rtn
48,1,V761,4CH,0,Gyro,Calib,Flip,RtnAct,Rtn
48,2,V761,TOPRC,0,Gyro,Calib,Flip,RtnAct,Rtn
46,0,V911s,V911s,1,Calib,Rate
46,1,V911s,E119,1,Calib,Rate
46,1,V911s,E119,1,Calib,Rate,6G_3D
22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8
30,1,WK2x01,WK2401,0
@@ -194,6 +196,7 @@
81,0,E010r5,E010r5,1,Flip,LED,CALIB,HLess,RTH,GLIDE
82,0,LOLI,Std,0,CH5,CH6,CH7,CH8,1SwSePpPw,2SwSePw,3SwSe,4SwSe,5SwSeSb,6SwSe,7SwSePw,8SwSe
83,0,E129,E129,1,TakLan,EmStop,TrimA,TrimE,TrimR
83,1,E129,C186,1,TakLan,EmStop,TrimA,TrimE,TrimR
84,0,JOYSWAY,Std,0
85,0,E016H,Std,1,Stop,Flip,n-a,HLess,RTH
87,0,IKEA
@@ -201,3 +204,5 @@
90,0,MouldKg,Analog,0
90,1,MouldKg,Digit,0
91,0,Xerall,Tank,0,FlTa,TakLan,Rate,HLess,Photo,Video,TrimR,TrimE,TrimA
92,0,MT99xx2,PA18,0,MODE,FLIP,RTH
93,0,Kyosho2,KT-17,0

View File

@@ -48,6 +48,7 @@ local ModuleNumber = 0
local ModuleType = ""
local Module = {}
local InitialProtocol = 0
local InitialSubProtocol = 0
function bitand(a, b)
local result = 0
@@ -76,6 +77,7 @@ end
local function Config_Release()
--Set the protocol back to what it was
Module.protocol = InitialProtocol
Module.subProtocol = InitialSubProtocol
model.setModule(ModuleNumber, Module)
--Stop requesting updates
@@ -422,7 +424,9 @@ local function Config_Init()
--Get Module settings and set it to config protocol
Module = model.getModule(ModuleNumber)
InitialProtocol = Module.protocol
InitialSubProtocol = Module.subProtocol
Module.protocol = 86
Module.subProtocol = 0
model.setModule(ModuleNumber, Module)
--pause while waiting for the module to switch to config
for i = 0, 10, 1 do end

View File

@@ -52,8 +52,16 @@ Notes:
[![Text mode video](https://img.youtube.com/vi/81wd8NlF3Qw/0.jpg)](https://www.youtube.com/watch?v=81wd8NlF3Qw)
## Graupner HoTT Model Locator
This is the Graupner HoTT adapted version of the Model Locator script using RSSI.
The OpenTX sensor "RSSI" is populated by the individual OpenTX telemetry protocol implementations and returns a value from 0..100 (percent) originating from the early FrSky implementation. It turns out that FrSky did not really provide a genuine signal strength indicator in units of dbm but a link quality indicator in 0..100%. With Graupner HoTT the link quality indicator is not a good basis for the model locator as it is very non-linear and doesn't change much with distance. Using the Graupner HoTT telemetry sensor "Rssi" which is a true signal strength indicator serves the purpose of locating a model much better as it varies much more with distance.
## DSM Forward Programming
Navigation is mainly done using the scroll wheel and ENT. Short press on ENT will edit a value. When editing a value a long ENT press will restore the value to its default. To exit the script and terminate all current operations correctly short press RTN (if you don't do this the RX might not store the changes).
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.

View File

@@ -55,14 +55,14 @@ static void __attribute__((unused)) DEVO_add_pkt_suffix()
{
uint8_t bind_state;
#ifdef ENABLE_PPM
if(mode_select && option==0 && IS_BIND_DONE) //PPM mode and option not already set and bind is finished
if(mode_select && (option&0x01)==0 && IS_BIND_DONE) //PPM mode and option not already set and bind is finished
{
BIND_SET_INPUT;
BIND_SET_PULLUP; // set pullup
if(IS_BIND_BUTTON_on)
{
eeprom_write_byte((EE_ADDR)(MODELMODE_EEPROM_OFFSET+RX_num),0x01); // Set fixed id mode for the current model
option=1;
option |= 0x01;
}
BIND_SET_OUTPUT;
}
@@ -72,7 +72,7 @@ static void __attribute__((unused)) DEVO_add_pkt_suffix()
MProtocol_id = RX_num + MProtocol_id_master;
bind_counter=DEVO_BIND_COUNT;
}
if (option)
if (option&0x01)
{
if (bind_counter > 0)
bind_state = 0xc0;
@@ -220,6 +220,7 @@ static void __attribute__((unused)) DEVO_parse_telemetry_packet()
#if defined HUB_TELEMETRY
//Telemetry https://github.com/DeviationTX/deviation/blob/5efb6a28bea697af9a61b5a0ed2528cc8d203f90/src/protocol/devo_cyrf6936.c#L232
uint16_t val, dec;
uint32_t val32;
switch(packet[0])
{
case 0x30: // Volt and RPM packet
@@ -255,18 +256,30 @@ static void __attribute__((unused)) DEVO_parse_telemetry_packet()
break;
// GPS Data
case 0x32: // Longitude
//memcpy(&packet[1],"\x30\x33\x30\x32\x30\x2e\x38\x32\x37\x30\x45\xfb",12); // 030°20.8270E
val = DEVO_text_to_int(&packet[1], 3)*100 + DEVO_text_to_int(&packet[4], 2); // dddmm
//memcpy(&packet[1],"\x30\x33\x30\x32\x30\x2e\x38\x32\x37\x30\x45\xfb",12); // 030°20.8270E in ddmm.mmmm
//memcpy(&packet[1],"\x31\x31\x37\x31\x31\x2e\x35\x39\x34\x37\x57\xfb",12); // RX705 sends 117°11.5947W which should be 11706.95685W in ddmm.mmmm
val = DEVO_text_to_int(&packet[1], 3)*100; // dd00
val32 = DEVO_text_to_int(&packet[4], 2) * 10000 + DEVO_text_to_int(&packet[7], 4); // mmmmmm
if(option&0x02) // if RX705 GPS format
val32 = (val32*3)/5; // then * 6/10 correction
dec = val32/10000;
val = val + dec; // dddmm
frsky_send_user_frame(0x12 , val, val>>8);
val = DEVO_text_to_int(&packet[7], 4); // .mmmm
val = val32 - dec*10000; // .mmmm
frsky_send_user_frame(0x12+8, val, val>>8);
frsky_send_user_frame(0x1A+8, packet[11], 0x00); // 'E'/'W'
break;
case 0x33: // Latitude
//memcpy(&packet[1],"\x35\x39\x35\x34\x2e\x37\x37\x37\x36\x4e\x07\x00",12); // 59°54.776N
val = DEVO_text_to_int(&packet[1], 2)*100 + DEVO_text_to_int(&packet[3], 2); // ddmm
//memcpy(&packet[1],"\x35\x39\x35\x34\x2e\x37\x37\x37\x36\x4e\x07\x00",12); // 59°54.776N in ddmm.mmmm
//memcpy(&packet[1],"\x31\x37\x31\x31\x2e\x35\x39\x34\x37\x4e\xfb\x00",12); // RX705 sends 17°11.5947N which should be 1706.95685N in ddmm.mmmm
val = DEVO_text_to_int(&packet[1], 2)*100; // dd00
val32 = DEVO_text_to_int(&packet[3], 2) * 10000 + DEVO_text_to_int(&packet[6], 4); // mmmmmm
if(option&0x02) // if RX705 GPS format
val32 = (val32*3)/5; // then * 6/10 correction
dec = val32/10000;
val = val + dec; // dddmm
frsky_send_user_frame(0x13 , val, val>>8);
val = DEVO_text_to_int(&packet[6], 4); // .mmmm
val = val32 - dec*10000; // .mmmm
frsky_send_user_frame(0x13+8, val, val>>8);
frsky_send_user_frame(0x1B+8, packet[10], 0x00); // 'N'/'S'
break;
@@ -530,13 +543,13 @@ void DEVO_init()
{
if(IS_BIND_BUTTON_FLAG_on)
{
eeprom_write_byte((EE_ADDR)(MODELMODE_EEPROM_OFFSET+RX_num),0x00); // reset to autobind mode for the current model
option=0;
option &= 0xFE;
eeprom_write_byte((EE_ADDR)(MODELMODE_EEPROM_OFFSET+RX_num),option); // reset to autobind mode for the current model
}
else
{
option=eeprom_read_byte((EE_ADDR)(MODELMODE_EEPROM_OFFSET+RX_num)); // load previous mode: autobind or fixed id
if(option!=1) option=0; // if not fixed id mode then it should be autobind
option=eeprom_read_byte((EE_ADDR)(MODELMODE_EEPROM_OFFSET+RX_num)); // load previous mode: autobind or fixed id
if(option > 3) option = 0; // if invalid then it should be autobind
}
}
#endif //ENABLE_PPM
@@ -570,8 +583,13 @@ void DEVO_init()
packet_count = 0;
prev_option=option;
if(option==0)
if(option&0x01)
{
phase = DEVO_BOUND_1;
bind_counter = 0;
DEVO_cyrf_set_bound_sop_code();
}
else
{
MProtocol_id = ((uint32_t)(hopping_frequency[0] ^ cyrfmfg_id[0] ^ cyrfmfg_id[3]) << 16)
| ((uint32_t)(hopping_frequency[1] ^ cyrfmfg_id[1] ^ cyrfmfg_id[4]) << 8)
@@ -581,12 +599,6 @@ void DEVO_init()
phase = DEVO_BIND;
BIND_IN_PROGRESS;
}
else
{
phase = DEVO_BOUND_1;
bind_counter = 0;
DEVO_cyrf_set_bound_sop_code();
}
}
#endif

View File

@@ -14,9 +14,9 @@
*/
// compatible with E012 and E015
#if defined(E01X_NRF24L01_INO)
#if defined(E01X_CYRF6936_INO)
#include "iface_nrf24l01.h"
#include "iface_hs6200.h"
//Protocols constants
#define E01X_BIND_COUNT 500
@@ -28,7 +28,8 @@
#define E012_NUM_RF_CHANNELS 4
#define E012_PACKET_SIZE 15
#define E015_PACKET_PERIOD 4500 // stock Tx=9000, but let's send more packets ...
//#define E015_FORCE_ID
#define E015_PACKET_PERIOD 9000
#define E015_RF_CHANNEL 0x2d // 2445 MHz
#define E015_PACKET_SIZE 10
#define E015_BIND_PACKET_SIZE 9
@@ -87,13 +88,15 @@ static void __attribute__((unused)) E01X_send_packet()
packet[0] = rx_tx_addr[1];
if(IS_BIND_IN_PROGRESS)
{
rf_ch_num = E012_RF_BIND_CHANNEL;
packet[1] = 0xaa;
memcpy(&packet[2], hopping_frequency, E012_NUM_RF_CHANNELS);
memcpy(&packet[6], rx_tx_addr, E01X_ADDRESS_LENGTH);
rf_ch_num=E012_RF_BIND_CHANNEL;
}
else
{
rf_ch_num = hopping_frequency[hopping_frequency_no++];
hopping_frequency_no %= E012_NUM_RF_CHANNELS;
packet[1] = 0x01
| GET_FLAG(E01X_RTH_SW, E012_FLAG_RTH)
| GET_FLAG(E01X_HEADLESS_SW, E012_FLAG_HEADLESS)
@@ -107,8 +110,6 @@ static void __attribute__((unused)) E01X_send_packet()
packet[8] = 0x00;
packet[9] = 0x00;
packet[10]= 0x00;
rf_ch_num=hopping_frequency[hopping_frequency_no++];
hopping_frequency_no %= E012_NUM_RF_CHANNELS;
}
packet[11] = 0x00;
packet[12] = 0x00;
@@ -117,6 +118,7 @@ static void __attribute__((unused)) E01X_send_packet()
}
else
{ // E015
rf_ch_num = E015_RF_CHANNEL;
if(IS_BIND_IN_PROGRESS)
{
packet[0] = 0x18;
@@ -124,10 +126,11 @@ static void __attribute__((unused)) E01X_send_packet()
packet[2] = 0x06;
// data phase address
memcpy(&packet[3], rx_tx_addr, E01X_ADDRESS_LENGTH);
packet[8] = 0x63; // unknown calculation
// checksum
packet[8] = packet[3];
for(uint8_t i=4; i<8; i++)
packet[8] += packet[i];
//packet[8] = packet[3];
//for(uint8_t i=4; i<8; i++)
// packet[8] += packet[i];
packet_length=E015_BIND_PACKET_SIZE;
}
else
@@ -154,24 +157,15 @@ static void __attribute__((unused)) E01X_send_packet()
}
}
HS6200_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch_num);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
HS6200_WritePayload(packet, packet_length);
// Check and adjust transmission power. We do this after
// transmission to not bother with timeout after power
// settings change - we have plenty of time until next
// packet.
NRF24L01_SetPower();
HS6200_RFChannel(rf_ch_num);
HS6200_SetPower();
delayMicroseconds(270); // Wait for RF channel to settle
HS6200_SendPayload(packet, packet_length);
}
static void __attribute__((unused)) E01X_RF_init()
{
NRF24L01_Initialize();
HS6200_Init(true); // CRC enabled
if(sub_protocol==E012)
HS6200_SetTXAddr((uint8_t *)"\x55\x42\x9C\x8F\xC9", E01X_ADDRESS_LENGTH);
@@ -218,8 +212,21 @@ void E01X_init()
}
else //E015
{
#ifdef E015_FORCE_ID
rx_tx_addr[0] = 0x06;
rx_tx_addr[1] = 0xC6;
rx_tx_addr[2] = 0xB7;
rx_tx_addr[3] = 0x56;
rx_tx_addr[4] = 0x8A;
#endif
//force the sum to give 0x63 since the id calculation is unknown
uint8_t sum=0x63;
for(uint8_t i=0; i < 4; i++)
sum -= rx_tx_addr[i];
rx_tx_addr[4] = sum;
packet_period=E015_PACKET_PERIOD;
rf_ch_num=E015_RF_CHANNEL;
armed = 0;
arm_flags = 0;
arm_channel_previous = E01X_ARM_SW;

View File

@@ -18,15 +18,17 @@
#include "iface_rf2500.h"
//#define E129_FORCE_ID
//#define C186_FORCE_ID
#define E129_BIND_CH 0x2D //45
#define E129_PAYLOAD_SIZE 16
#define C186_PAYLOAD_SIZE 19
static void __attribute__((unused)) E129_build_data_packet()
{
//Build the packet
memset(packet,0,E129_PAYLOAD_SIZE);
packet[ 0] = 0x0F; // Packet length
memset(packet,0,packet_length);
packet[ 0] = packet_length - 1; // Packet length
if(IS_BIND_IN_PROGRESS)
{
packet[ 1] = 0xA4;
@@ -40,11 +42,21 @@ static void __attribute__((unused)) E129_build_data_packet()
else
{
packet[ 1] = 0xA6;
packet[ 2] = 0xF7; // High rate 0xF7, low rate 0xF4
//packet[ 3] = 0x00; // Mode: short press=0x20->0x00->0x20->..., long press=0x10->0x30->0x10->...
//Flags
if(sub_protocol == E129_E129)
packet[ 2] = 0xF7; // High rate 0xF7, low 0xF4
else //C186
{
packet[ 2] = 0xFA; // High rate 0xFA, medium 0xF7, low 0xF4
packet[13] = bit_reverse(rx_tx_addr[2]);
packet[14] = bit_reverse(rx_tx_addr[3]);
packet[15] = bit_reverse(rx_tx_addr[0]);
packet[16] = bit_reverse(rx_tx_addr[1]);
}
//packet[ 3] = 0x00; // E129 Mode: short press=0x20->0x00->0x20->..., long press=0x10->0x30->0x10->... => C186 throttle trim is doing the same:up=short press and down=long press
packet[ 4] = GET_FLAG(CH5_SW, 0x20) // Take off/Land 0x20
| GET_FLAG(CH6_SW, 0x04); // Emergency stop 0x04
| GET_FLAG(CH6_SW, 0x04); // Emergency stop 0x04
//Channels and trims
uint16_t val = convert_channel_10b(AILERON,false);
uint8_t trim = convert_channel_8b(CH7) & 0xFC;
packet[ 5] = trim | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8
@@ -67,10 +79,14 @@ static void __attribute__((unused)) E129_build_data_packet()
packet[11] = trim | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8
packet[12] = val; // channel (0x000...0x200...0x3FF)
}
packet[14] = 0x00; // Check
for(uint8_t i=0;i<14;i++)
packet[14] += packet[i];
//Check
if(sub_protocol == E129_E129)
packet[packet_length-2] = packet[0] + packet[1];
else
packet[packet_length-2] = 0x24 + packet[0] + (packet[1]&0x03); // ??
for(uint8_t i=2;i<packet_length-2;i++)
packet[packet_length-2] += packet[i];
RF2500_BuildPayload(packet);
}
@@ -83,7 +99,7 @@ uint16_t E129_callback()
//Send packet
RF2500_SendPayload();
//Send twice on same channel
//E129 sends twice on same channel, not the C186 but there is a bug somewhere if I don't send the packets back to back
if(phase==0)
{
phase++;
@@ -109,7 +125,9 @@ uint16_t E129_callback()
hopping_frequency_no &= 3;
phase=0;
return 5200-1260;
if(sub_protocol==E129_E129)
return 5200-1260;
return 5500-1260; //E129_C186
}
void E129_init()
@@ -117,8 +135,9 @@ void E129_init()
BIND_IN_PROGRESS; // Autobind protocol
bind_counter = 384; // ~2sec
//RF2500 emu init
RF2500_Init(E129_PAYLOAD_SIZE, true); // 16 bytes, Scrambled
//RF2500 emu init
packet_length = sub_protocol == E129_E129?E129_PAYLOAD_SIZE:C186_PAYLOAD_SIZE;
RF2500_Init(packet_length, true); // 16/19 bytes, Scrambled
//Freq hopping
calc_fh_channels(4);
@@ -136,6 +155,16 @@ void E129_init()
hopping_frequency[2]=0x4B; //75
hopping_frequency[3]=0x41; //65
#endif
#ifdef C186_FORCE_ID
rx_tx_addr[0]=0x91;
rx_tx_addr[1]=0x02;
rx_tx_addr[2]=0x5D;
rx_tx_addr[3]=0x33;
hopping_frequency[0]=0x44 + 2;
hopping_frequency[1]=0x41 + 2;
hopping_frequency[2]=0x43 + 2;
hopping_frequency[3]=0x49 + 2;
#endif
RF2500_SetTXAddr((uint8_t*)"\xE2\x32\xE0\xC8"); // 4 bytes of bind address

View File

@@ -1,100 +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 FEI XIONG P38 plane.
#if defined(FX816_NRF24L01_INO)
#include "iface_xn297.h"
#define FX816_INITIAL_WAIT 500
#define FX816_PACKET_PERIOD 10000
#define FX816_RF_BIND_CHANNEL 0x28 //40
#define FX816_RF_NUM_CHANNELS 4
#define FX816_PAYLOAD_SIZE 6
#define FX816_BIND_COUNT 300 //3sec
static void __attribute__((unused)) FX816_send_packet()
{
if(IS_BIND_IN_PROGRESS)
packet[0] = 0x55;
else
{
XN297_Hopping(hopping_frequency_no++);
hopping_frequency_no%=FX816_RF_NUM_CHANNELS;
packet[0] = 0xAA;
}
packet[1] = rx_tx_addr[0];
packet[2] = rx_tx_addr[1];
uint8_t val=convert_channel_8b(AILERON);
#define FX816_SWITCH 20
if(val>127+FX816_SWITCH)
packet[3] = 1;
else if(val<127-FX816_SWITCH)
packet[3] = 2;
else
packet[3] = 0;
packet[4] = convert_channel_16b_limit(THROTTLE,0,100);
val=0;
for(uint8_t i=0;i<FX816_PAYLOAD_SIZE-1;i++)
val+=packet[i];
packet[5]=val;
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, FX816_PAYLOAD_SIZE);
}
static void __attribute__((unused)) FX816_RF_init()
{
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc", 5);
//XN297_HoppingCalib(FX816_RF_NUM_CHANNELS);
XN297_RFChannel(FX816_RF_BIND_CHANNEL);
}
static void __attribute__((unused)) FX816_initialize_txid()
{
//Only 8 IDs: the RX led does not indicate frame loss.
//I didn't open the plane to find out if I could connect there so this is the best I came up with with few trial and errors...
rx_tx_addr[0]=0x35+(rx_tx_addr[3]&0x07); //Original dump=0x35
rx_tx_addr[1]=0x09; //Original dump=0x09
memcpy(hopping_frequency,"\x09\x1B\x30\x42",FX816_RF_NUM_CHANNELS); //Original dump=9=0x09,27=0x1B,48=0x30,66=0x42
for(uint8_t i=0;i<FX816_RF_NUM_CHANNELS;i++)
hopping_frequency[i]+=rx_tx_addr[3]&0x07;
}
uint16_t FX816_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(FX816_PACKET_PERIOD);
#endif
if(bind_counter)
if(--bind_counter==0)
BIND_DONE;
FX816_send_packet();
return FX816_PACKET_PERIOD;
}
void FX816_init()
{
BIND_IN_PROGRESS; // autobind protocol
FX816_initialize_txid();
FX816_RF_init();
hopping_frequency_no = 0;
bind_counter=FX816_BIND_COUNT;
}
#endif

View File

@@ -0,0 +1,177 @@
/*
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 FEI XIONG P38 plane.
#if defined(FX_NRF24L01_INO)
#include "iface_xn297.h"
#define FX_BIND_COUNT 300 //3sec
#define FX_SWITCH 20
#define FX_NUM_CHANNELS 4
#define FX816_PACKET_PERIOD 10000
#define FX816_BIND_CHANNEL 40
#define FX816_PAYLOAD_SIZE 6
#define FX816_CH_OFFSET 3
#define FX620_PACKET_PERIOD 3250
#define FX620_BIND_PACKET_PERIOD 4500
#define FX620_BIND_CHANNEL 18
#define FX620_PAYLOAD_SIZE 7
#define FX620_CH_OFFSET 1
//#define FORCE_FX620_ID
static void __attribute__((unused)) FX_send_packet()
{
//Hopp
if(IS_BIND_DONE)
{
XN297_Hopping(hopping_frequency_no++);
hopping_frequency_no &= 0x03;
}
memset(packet,0x00,packet_length);
//Channels
uint8_t offset=sub_protocol == FX816 ? FX816_CH_OFFSET:FX620_CH_OFFSET;
uint8_t val=convert_channel_8b(AILERON);
if(val>127+FX_SWITCH)
packet[offset] = sub_protocol == FX816 ? 1:0xFF;
else if(val<127-FX_SWITCH)
packet[offset] = sub_protocol == FX816 ? 2:0x00;
else
packet[offset] = sub_protocol == FX816 ? 0:0x7F;
packet[offset+1] = convert_channel_16b_limit(THROTTLE,0,100); //FX816:0x00..0x63, FX620:0x00..0x5E but that should work
//Bind and specifics
if(sub_protocol == FX816)
{
if(IS_BIND_IN_PROGRESS)
packet[0] = 0x55;
else
packet[0] = 0xAA;
packet[1] = rx_tx_addr[0];
packet[2] = rx_tx_addr[1];
}
else //FX620
{
if(IS_BIND_IN_PROGRESS)
{
memcpy(packet,rx_tx_addr,3);
packet[3] = hopping_frequency[0];
if(bind_counter > (FX_BIND_COUNT >> 1))
packet[5] = 0x78;
}
else
{
packet[0] = 0x1F; // Is it based on ID??
packet[5] = 0xAB; // Is it based on ID??
}
}
//Check
val=0;
for(uint8_t i=0;i<packet_length-1;i++)
val+=packet[i];
packet[packet_length-1]=val;
//Debug
#if 0
for(uint8_t i=0;i<packet_length;i++)
debug("%02X ",packet[i]);
debugln("");
#endif
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, packet_length);
}
static void __attribute__((unused)) FX_RF_init()
{
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
if(sub_protocol == FX816)
{
XN297_SetTXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc", 5);
XN297_RFChannel(FX816_BIND_CHANNEL);
packet_period = FX816_PACKET_PERIOD;
packet_length = FX816_PAYLOAD_SIZE;
}
else //FX620
{
XN297_SetTXAddr((uint8_t *)"\xaa\xbb\xcc", 3);
XN297_RFChannel(FX620_BIND_CHANNEL);
packet_period = FX620_BIND_PACKET_PERIOD;
packet_length = FX620_PAYLOAD_SIZE;
}
}
static void __attribute__((unused)) FX_initialize_txid()
{
if(sub_protocol == FX816)
{
//Only 8 IDs: the RX led does not indicate frame loss.
//I didn't open the plane to find out if I could connect there so this is the best I came up with with few trial and errors...
rx_tx_addr[0]=0x35+(rx_tx_addr[3]&0x07); //Original dump=0x35
rx_tx_addr[1]=0x09; //Original dump=0x09
memcpy(hopping_frequency,"\x09\x1B\x30\x42",FX_NUM_CHANNELS); //Original dump=9=0x09,27=0x1B,48=0x30,66=0x42
for(uint8_t i=0;i<FX_NUM_CHANNELS;i++)
hopping_frequency[i]+=rx_tx_addr[3]&0x07;
}
else//FX620
{
rx_tx_addr[0] = rx_tx_addr[3];
hopping_frequency[0] = 0x18 + rx_tx_addr[3]&0x07; // just to try something
#ifdef FORCE_FX620_ID
memcpy(rx_tx_addr,(uint8_t*)"\x34\xA9\x32",3);
hopping_frequency[0] = 0x18; //on dump: 24 34 44 54
#endif
for(uint8_t i=1;i<FX_NUM_CHANNELS;i++)
hopping_frequency[i] = i*10 + hopping_frequency[0];
}
}
uint16_t FX_callback()
{
#ifdef MULTI_SYNC
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;
}
}
FX_send_packet();
return packet_period;
}
void FX_init()
{
BIND_IN_PROGRESS; // autobind protocol
FX_initialize_txid();
FX_RF_init();
hopping_frequency_no = 0;
bind_counter=FX_BIND_COUNT;
}
#endif

View File

@@ -169,66 +169,77 @@ static void __attribute__((unused)) HOTT_TXID_init()
}
}
static void __attribute__((unused)) HOTT_prep_data_packet()
{
static uint8_t upper=0;
static void __attribute__((unused)) HOTT_prep_data_packet() {
static uint8_t upper = 0; // toggles between sending channels 1..8,9..12 and 1..8,13..16
packet[2] = hopping_frequency_no; // send next frequency to be used
packet[3] = upper; // indicate upper or lower channels (only supporting 16 channels)
packet[2] = hopping_frequency_no;
packet[3] = upper; // used for failsafe and upper channels (only supporting 16 channels)
#ifdef FAILSAFE_ENABLE
static uint8_t failsafe_count=0;
if(IS_FAILSAFE_VALUES_on && IS_BIND_DONE)
{
failsafe_count++;
if(failsafe_count>=3)
{
FAILSAFE_VALUES_off;
failsafe_count=0;
static uint8_t failsafe_count = 0; // failsafe packet state machine (need to send two packets)
if(IS_FAILSAFE_VALUES_on && IS_BIND_DONE) { // if TX wants to send failsafe data and RX is connected
failsafe_count++; // prepare to send next packet
if(failsafe_count >= 3) { // done sending two failsafe channel data packets
FAILSAFE_VALUES_off;
failsafe_count = 0;
}
}
else
failsafe_count=0;
failsafe_count = 0;
#endif
// Channels value are PPM*2, -100%=1100µs, +100%=1900µs, order TAER
//
// Note: failsafe packets are differnt to normal operation packets
// normal operation toggles between sending channels 1..8,9..12 and 1..8,13..16 using bit0 as high/low indicator in packet[3]
// while failsafe packets send channels 1..12, 13..24 (and probably 25..32) using bit0 in packet[3] as packet type indicator
// packet[3] = 0x40 -> failsafe packet with data for channels 1..12
// packet[3] = 0x41 -> failsafe packet with data for channels 13..24
//
uint16_t val;
for(uint8_t i=4;i<28;i+=2)
{
uint8_t ch=(i-4)>>1;
if(upper && ch >= 8)
ch+=4; // when upper swap CH9..CH12 by CH13..16
val=Channel_data[ch];
val=(((val<<2)+val)>>2)+860*2; // value range 860<->2140 *2 <-> -125%<->+125%
for(uint8_t i = 0 ; i < 12*2 ; i += 2) { // working 12 channels (using 2 bytes per channel)
uint8_t chIndex = i >> 1 ; // normal operation channel number
uint8_t fschIndex = chIndex; // linear channel number for failsafe
if(upper && chIndex >= 8) chIndex += 4; // for normal operation toggle between channels 1..8,9..12 and 1..8,13..16
val = Channel_data[chIndex]; // get normal operation channel data
val = (((val << 2) + val) >> 2)+ 860*2; // convert channel data 0..2047 to 1720..4278 <-> -125%<->+125%
// val = (val*5/4+860*2)
#ifdef FAILSAFE_ENABLE
if(failsafe_count==1)
{ // first failsafe packet
packet[3] |= 0x40;
uint16_t fs=Failsafe_data[ch];
if( fs == FAILSAFE_CHANNEL_HOLD || fs == FAILSAFE_CHANNEL_NOPULSES)
val|=0x8000; // channel hold flag
else
{
val=(((fs<<2)+fs)>>2)+860*2; // value range 860<->2140 *2 <-> -125%<->+125%
val|=0x4000; // channel specific position flag
if(failsafe_count == 1 || failsafe_count == 2) {// failsafe data needs to be sent to RX
uint16_t fs = 0x8000; // default failsafe mode is hold
if(failsafe_count == 1) { // send fail safe packet containing channels 1..12
packet[3] = 0x40; // indicate packet has failsafe values for channels 1..12
fs = Failsafe_data[fschIndex]; // get failsafe channel data
} else { // send fail safe packet containing channels 13..24
packet[3] = 0x41; // indicate packet has failsafe values for channels 13..24
if(fschIndex < 4) // we only work 16 channels so send channels 13..16, rest default
fs = Failsafe_data[fschIndex+12]; // get failsafe channel data 13..16
}
if( fs == FAILSAFE_CHANNEL_HOLD || // treat HOLD and NOPULSES as channel hold
fs == FAILSAFE_CHANNEL_NOPULSES)
val = 0x8000; // set channel failsafe mode hold flag
else {
val = (((fs << 2) + fs) >> 2) +860*2; // convert channel data 0..2047 to 1720..4278 <-> -125%<->+125%
val |= 0x4000; // set channel failsafe mode position flag
}
}
else if(failsafe_count==2)
{ // second failsafe packet=timing?
packet[3] |= 0x50;
if(i==4)
val=2;
else
val=0;
}
}
#endif
packet[i] = val;
packet[i+1] = val>>8;
packet[i + 4] = val; // first channel data at packet[4] and packet[5]
packet[i + 4+1] = val >> 8;
}
upper ^= 0x01; // toggle between CH9..CH12 and CH13..16
packet[28] = 0x80; // no sensor
packet[29] = 0x02; // 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets, 0x01->text config menu, 0x0A->no more RX telemetry
upper ^= 0x01; // toggle to upper and lower channels
packet[28] = 0x80; // no sensor
packet[29] = 0x02; // 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets, 0x01->text config menu, 0x0A->no more RX telemetry
#ifdef HOTT_FW_TELEMETRY
if(IS_BIND_DONE)
{
@@ -390,7 +401,7 @@ uint16_t HOTT_callback()
{ //Telemetry
// [0..4] = TXID
// [5..9] = RXID
// [10] = 0x40 bind, 0x00 normal, 0x80 config menu
// [10] = holds warnings issued by hott devices
// [11] = telmetry pages. For sensors 0x00 to 0x04, for config mennu 0x00 to 0x12.
// Normal telem page 0 = 0x55, 0x32, 0x38, 0x55, 0x64, 0x32, 0xD0, 0x07, 0x00, 0x55
// Page 0 [12] = [21] = [15]
@@ -400,7 +411,7 @@ uint16_t HOTT_callback()
// Page 0 [16] = RX_LQI in %
// Page 0 [17] = RX_Voltage Min*10 in V
// Page 0 [18,19] = [19]<<8+[18]=max lost packet time in ms, max value seems 2s=0x7D0
// Page 0 [20] = 0x00 ??
// Page 0 [20] = rx events
//
// Config menu consists of the different telem pages put all together
// Page X [12] = seems like all the telem pages with the same value are going together to make the full config menu text. Seen so far 'a', 'b', 'c', 'd'
@@ -412,6 +423,7 @@ uint16_t HOTT_callback()
// Reduce telemetry to 14 bytes
packet_in[0]= packet_in[HOTT_RX_PACKET_LEN];
packet_in[1]= TX_LQI;
uint8_t hott_warnings = packet_in[10]; // save warnings from hott devices
bool send_telem=true;
HOTT_sensor_seq++; // Increment RX sequence counter
if(packet[29] & 1)
@@ -464,6 +476,7 @@ uint16_t HOTT_callback()
packet_in[i-8]=packet_in[i];
debug(" %02X",packet_in[i]);
}
packet_in[14] = hott_warnings; // restore saved warnings from hott devices
debugln("");
if(send_telem)
telemetry_link=2;

View File

@@ -0,0 +1,112 @@
/*
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/>.
*/
#ifdef CYRF6936_INSTALLED
#include "iface_hs6200.h"
static bool HS6200_crc;
static uint16_t HS6200_crc_init;
static uint8_t HS6200_address_length, HS6200_tx_addr[5];
static void __attribute__((unused)) HS6200_Init(bool crc_en)
{
CYRF_GFSK1M_Init(32, 1); //Dummy number of bytes for now
HS6200_crc = crc_en;
}
static void __attribute__((unused)) HS6200_SetTXAddr(const uint8_t* addr, uint8_t addr_len)
{
// precompute address crc
crc = 0xffff;
for(uint8_t i=0; i<addr_len; i++)
crc16_update(addr[addr_len-1-i], 8);
HS6200_crc_init=crc;
memcpy(HS6200_tx_addr, addr, addr_len);
HS6200_address_length = addr_len;
}
static uint16_t __attribute__((unused)) HS6200_calc_crc(uint8_t* msg, uint8_t len)
{
uint8_t pos;
crc = HS6200_crc_init;
// pcf + payload
for(pos=0; pos < len-1; pos++)
crc16_update(msg[pos], 8);
// last byte (1 bit only)
if(len > 0)
crc16_update(msg[pos+1], 1);
return crc;
}
static void __attribute__((unused)) HS6200_SendPayload(uint8_t* msg, uint8_t len)
{
static const uint8_t HS6200_scramble[] = { 0x80,0xf5,0x3b,0x0d,0x6d,0x2a,0xf9,0xbc,0x51,0x8e,0x4c,0xfd,0xc1,0x65,0xd0 }; // todo: find all 32 bytes ...
uint8_t payload[32];
const uint8_t no_ack = 1; // never ask for an ack
static uint8_t pid;
uint8_t pos = 0;
if(len > sizeof(HS6200_scramble))
len = sizeof(HS6200_scramble);
// address
for(int8_t i=HS6200_address_length-1; i>=0; i--)
payload[pos++] = HS6200_tx_addr[i];
// guard bytes
payload[pos++] = HS6200_tx_addr[0];
payload[pos++] = HS6200_tx_addr[0];
// packet control field
payload[pos++] = ((len & 0x3f) << 2) | (pid & 0x03);
payload[pos] = (no_ack & 0x01) << 7;
pid++;
// scrambled payload
if(len > 0)
{
payload[pos++] |= (msg[0] ^ HS6200_scramble[0]) >> 1;
for(uint8_t i=1; i<len; i++)
payload[pos++] = ((msg[i-1] ^ HS6200_scramble[i-1]) << 7) | ((msg[i] ^ HS6200_scramble[i]) >> 1);
payload[pos] = (msg[len-1] ^ HS6200_scramble[len-1]) << 7;
}
// crc
if(HS6200_crc)
{
uint16_t crc = HS6200_calc_crc(&payload[HS6200_address_length+2], len+2);
uint8_t hcrc = crc >> 8;
uint8_t lcrc = crc & 0xff;
payload[pos++] |= (hcrc >> 1);
payload[pos++] = (hcrc << 7) | (lcrc >> 1);
payload[pos++] = lcrc << 7;
}
#if 0
debug("E:");
for(uint8_t i=0; i<pos; i++)
debug(" %02X",payload[i]);
debugln("");
#endif
//CYRF wants LSB first
for(uint8_t i=0; i<pos; i++)
payload[i]=bit_reverse(payload[i]);
//Send
CYRF_WriteRegister(CYRF_01_TX_LENGTH, pos);
CYRF_GFSK1M_SendPayload(payload, pos);
}
#endif

View File

@@ -46,7 +46,7 @@ static void __attribute__((unused)) KF606_send_packet()
if(sub_protocol == KF606_KF606)
{
packet[2] = convert_channel_8b_limit_deadband(AILERON,0x20,0x80,0xE0,40); // Aileron: Max values:20..80..E0, Low rates:50..80..AF, High rates:3E..80..C1
packet[3] = convert_channel_16b_limit(CH5,0xC1,0xDF); // Aileron trim must be on a separated channel C1..D0..DF
packet[3] = convert_channel_16b_limit(CH5,0xC1,0xDF); // Aileron trim must be on a separated channel C1..D0..DF
}
else
{
@@ -57,6 +57,7 @@ static void __attribute__((unused)) KF606_send_packet()
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
}
}

View File

@@ -0,0 +1,137 @@
/*
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(KYOSHO2_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define KYOSHO2_PACKET_PERIOD 1120 // 1600 for bind, let's see
#define KYOSHO2_BIND_COUNT 2000 // about 3sec
#define KYOSHO2_BIND_CHANNEL 0x50
#define KYOSHO2_PAYLOAD_SIZE 28
#define KYOSHO2_RF_CHANNELS 15
#define KYOSHO2_START_RF_CHANNEL 0x13 // No idea where it comes from... ID or unknown bytes during the bind?
#define KYOSHO2_NUM_CHANNEL 10 // Only 4 on the dumps but there is space for 10 channels in the payload...
#define FORCE_KYOSHO2_ID
bool KYOSHO2_resend;
//
static void __attribute__((unused)) KYOSHO2_send_packet()
{
if(KYOSHO2_resend == true)
{
NRF24L01_Strobe(NRF24L01_E3_REUSE_TX_PL);
if(IS_BIND_DONE)
KYOSHO2_resend = false;
return;
}
memset(packet,0x00,KYOSHO2_PAYLOAD_SIZE);
if(IS_BIND_IN_PROGRESS)
{
memcpy(packet, (uint8_t*)"\x01\x02\x05\x08\x1A\x2B\x3C\x4D", 8); // unknown bytes, parameters on how to build the rf channels?
memcpy(&packet[8], rx_tx_addr, 4);
}
else
{
memcpy(packet, rx_tx_addr, 4);
//Hopp
packet[6] = hopping_frequency_no + KYOSHO2_START_RF_CHANNEL;
packet[7] = hopping_frequency[hopping_frequency_no];
NRF24L01_WriteReg(NRF24L01_05_RF_CH, packet[6+(rf_ch_num&0x01)]);
rf_ch_num++;
//Channels
uint16_t temp;
for (uint8_t i = 0; i< KYOSHO2_NUM_CHANNEL; i++)
{
temp=convert_channel_16b_limit(i,0,0x3FF);
packet[8+i*2] = temp >> 8;
packet[9+i*2] = temp;
}
}
//Send
NRF24L01_WriteReg(NRF24L01_07_STATUS, (_BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT))); // Reset flags
NRF24L01_FlushTx();
NRF24L01_WritePayload(packet,KYOSHO2_PAYLOAD_SIZE);
NRF24L01_SetPower();
KYOSHO2_resend = true;
#if 0
for(uint8_t i=0;i<KYOSHO2_PAYLOAD_SIZE;i++)
debug("%02X ", packet[i]);
debugln("");
#endif
}
static void __attribute__((unused)) KYOSHO2_RF_init()
{
NRF24L01_Initialize();
NRF24L01_WriteReg(NRF24L01_05_RF_CH, KYOSHO2_BIND_CHANNEL);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\x69\x53\x10\xAC\xEF", 5);
}
static void __attribute__((unused)) KYOSHO2_initialize_tx_id()
{
hopping_frequency_no = rx_tx_addr[3]%KYOSHO2_RF_CHANNELS;
hopping_frequency[0] = 0x4A;
#ifdef FORCE_KYOSHO2_ID
memcpy(rx_tx_addr, (uint8_t*)"\x0A\xBD\x31\xDF", 4);
hopping_frequency[0] = 0x4A; // No idea where it comes from... ID or unknown bytes during the bind?
#endif
for(uint8_t i=1;i<KYOSHO2_RF_CHANNELS;i++)
{
if(hopping_frequency[i-1]+5 < 0x50)
hopping_frequency[i] = hopping_frequency[i-1]+5;
else
hopping_frequency[i] = hopping_frequency[i-1]-0x21;
}
#if 0
for(uint8_t i=0;i<KYOSHO2_RF_CHANNELS;i++)
debugln("1:%02X, 2: %02X", i + KYOSHO2_START_RF_CHANNEL, hopping_frequency[i]);
debugln("Selected 1:%02X, 2: %02X", hopping_frequency_no + KYOSHO2_START_RF_CHANNEL, hopping_frequency[hopping_frequency_no]);
#endif
}
uint16_t KYOSHO2_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(KYOSHO2_PACKET_PERIOD);
#endif
if(bind_counter)
if(--bind_counter==0)
{
BIND_DONE;
KYOSHO2_resend = false;
}
KYOSHO2_send_packet();
return KYOSHO2_PACKET_PERIOD;
}
void KYOSHO2_init()
{
KYOSHO2_initialize_tx_id();
KYOSHO2_RF_init();
rf_ch_num = 0;
if(IS_BIND_IN_PROGRESS)
bind_counter = KYOSHO2_BIND_COUNT;
else
bind_counter = 0;
KYOSHO2_resend = false;
}
#endif

View File

@@ -27,12 +27,15 @@
#define MT99XX_PACKET_PERIOD_DRAGON 1038 // there is a pause of 2x1038 between two packets, no idea why and how since it is not even stable on a same dump...
#define MT99XX_PACKET_PERIOD_DRAGON_TELEM 10265 // long pause to receive the telemetry packets, 3 are sent by the RX one after the other
#define MT99XX_PACKET_PERIOD_F949G 3450
#define MT99XX_PACKET_PERIOD_PA18 1338
#define MT99XX_INITIAL_WAIT 500
#define MT99XX_PACKET_SIZE 9
//#define FORCE_A180_ID
//#define FORCE_DRAGON_ID
//#define FORCE_F949G_ID
#define FORCE_PA18_ID1
//#define FORCE_PA18_ID2
enum {
MT99XX_DATA,
@@ -82,6 +85,11 @@ enum{
FLAG_F949G_LIGHT = 0x01,
FLAG_F949G_3D6G = 0x20,
};
enum{
// flags going to packet[6] (PA18)
FLAG_PA18_RTH = 0x08,
FLAG_PA18_FLIP = 0x80,
};
const uint8_t h7_mys_byte[] = {
0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14,
@@ -107,11 +115,11 @@ static void __attribute__((unused)) MT99XX_send_packet()
//Set RF freq
if(sub_protocol == LS)
XN297_RFChannel(0x2D); // LS always transmits on the same channel
XN297_RFChannel(0x2D); // LS always transmits on the same channel
else
if(sub_protocol==FY805)
XN297_RFChannel(0x4B); // FY805 always transmits on the same channel
else // MT99 & H7 & YZ & A180 & DRAGON & F949G
XN297_RFChannel(0x4B); // FY805 always transmits on the same channel
else // MT99 & H7 & YZ & A180 & DRAGON & F949G & PA18
XN297_Hopping(hopping_frequency_no);
if(IS_BIND_IN_PROGRESS)
@@ -121,7 +129,6 @@ static void __attribute__((unused)) MT99XX_send_packet()
switch(sub_protocol)
{
case YZ:
packet_period = MT99XX_PACKET_PERIOD_YZ;
packet[1] = 0x15;
packet[2] = 0x05;
packet[3] = 0x06;
@@ -132,15 +139,11 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[3] = 0x11;
break;
case FY805:
packet_period = MT99XX_PACKET_PERIOD_FY805;
packet[1] = 0x15;
packet[2] = 0x12;
packet[3] = 0x17;
break;
case F949G:
case A180:
packet_period = MT99XX_PACKET_PERIOD_A180;
default: // MT99 & H7 & A180 & DRAGON & F949G
default: // MT99 & H7 & A180 & DRAGON & F949G & PA18
packet[1] = 0x14;
packet[2] = 0x03;
packet[3] = 0x25;
@@ -149,16 +152,24 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[4] = rx_tx_addr[0];
packet[5] = rx_tx_addr[1];
packet[6] = rx_tx_addr[2];
packet[7] = crc8; // checksum offset
if(sub_protocol != F949G)
packet[8] = 0xAA; // fixed
if(sub_protocol == PA18+8)
{
packet[7] = num_ch; // checksum offset
packet[8] = 0x55; // fixed
}
else
packet[8] = 0x00;
{ // all others
packet[7] = crc8; // checksum offset
if(sub_protocol != F949G)
packet[8] = 0xAA; // fixed
else
packet[8] = 0x00;
}
}
else
{
if(sub_protocol != YZ)
{ // MT99XX & H7 & LS & FY805 & A180 & DRAGON & F949G
{ // MT99XX & H7 & LS & FY805 & A180 & DRAGON & F949G & PA18
packet[0] = convert_channel_16b_limit(THROTTLE,0xE1,0x00); // throttle
packet[1] = convert_channel_16b_limit(RUDDER ,0x00,0xE1); // rudder
packet[2] = convert_channel_16b_limit(AILERON ,0xE1,0x00); // aileron
@@ -166,8 +177,10 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[4] = 0x20; // pitch trim (0x3f-0x20-0x00)
packet[5] = 0x20; // roll trim (0x00-0x20-0x3f)
packet[6] = GET_FLAG( CH5_SW, FLAG_MT_FLIP );
packet[7] = h7_mys_byte[hopping_frequency_no]; // next rf channel index ?
if(sub_protocol != PA18+8)
packet[7] = h7_mys_byte[hopping_frequency_no]; // next rf channel index ?
else
packet[7] = (packet[7]&0xBF)|0x20;
switch(sub_protocol)
{
case MT99:
@@ -198,15 +211,16 @@ static void __attribute__((unused)) MT99XX_send_packet()
crc8=0;
break;
case A180:
packet[6] = FLAG_A180_RATE
| GET_FLAG( CH5_SW, FLAG_A180_3D6G );
packet[6] = GET_FLAG( !CH6_SW,FLAG_A180_RATE) // 0x02, A180=RATE, F949S=LED
|GET_FLAG( CH5_SW, FLAG_A180_3D6G ) // 0x01, A180=3D_6G, F949S=RATE
|GET_FLAG( CH7_SW, 0x20 ); // 0x20, F949S=3D_6G
packet[7] = 0x00;
break;
case DRAGON:
if(CH5_SW) // Advanced mode
if(CH5_SW) // Advanced mode
packet[5] |= 0x80;
else
if(Channel_data[CH5] > CHANNEL_MIN_COMMAND) // Beginner mode
if(Channel_data[CH5] > CHANNEL_MIN_COMMAND) // Beginner mode
packet[5] |= 0x40;
packet[6] = FLAG_DRAGON_RATE
| GET_FLAG( CH6_SW, FLAG_DRAGON_RTH );
@@ -221,12 +235,12 @@ static void __attribute__((unused)) MT99XX_send_packet()
if(packet_count > 11)
packet_count = 0;
}
if(packet_count > 10) // Telemetry packet request every 10 or 11 packets
if(packet_count > 10) // Telemetry packet request every 10 or 11 packets
{
packet[6] |= 0x04; // Request telemetry flag
packet[6] |= 0x04; // Request telemetry flag
phase = MT99XX_RX;
}
packet[7] = DRAGON_seq[seq_num]; // seq: 20 80 20 60 20 80 20 60... 80 changes to 80+batt from telem
packet[7] = DRAGON_seq[seq_num]; // seq: 20 80 20 60 20 80 20 60... 80 changes to 80+batt from telem
if(seq_num==3)
packet[7] |= v_lipo1;
#else
@@ -239,18 +253,31 @@ static void __attribute__((unused)) MT99XX_send_packet()
| GET_FLAG( CH6_SW, FLAG_F949G_LIGHT );
packet[7] = 0x00;
break;
case PA18+8:
if(Channel_data[CH5] > CHANNEL_MAX_COMMAND) // Expert mode
packet[5] = 0xA0;
else
if(Channel_data[CH5] > CHANNEL_MIN_COMMAND) // Intermediate mode
packet[5] = 0x60;
packet[6] = GET_FLAG( CH6_SW, FLAG_PA18_FLIP ) // Flip
| GET_FLAG( CH7_SW, FLAG_PA18_RTH ); // RTH
if(hopping_frequency_no == 0)
packet[7] ^= 0x40;
break;
}
uint8_t result=crc8;
for(uint8_t i=0; i<8; i++)
result += packet[i];
if(sub_protocol == PA18+8)
result += num_ch;
packet[8] = result;
}
else
{ // YZ
packet[0] = convert_channel_16b_limit(THROTTLE,0x00,0x64); // throttle
packet[1] = convert_channel_16b_limit(RUDDER ,0x64,0x00); // rudder
packet[2] = convert_channel_16b_limit(ELEVATOR,0x00,0x64); // elevator
packet[3] = convert_channel_16b_limit(AILERON ,0x64,0x00); // aileron
packet[0] = convert_channel_16b_limit(THROTTLE,0x00,0x64); // throttle
packet[1] = convert_channel_16b_limit(RUDDER ,0x64,0x00); // rudder
packet[2] = convert_channel_16b_limit(ELEVATOR,0x00,0x64); // elevator
packet[3] = convert_channel_16b_limit(AILERON ,0x64,0x00); // aileron
if(packet_count++ >= 23)
{
seq_num ++;
@@ -260,11 +287,11 @@ static void __attribute__((unused)) MT99XX_send_packet()
}
packet[4] = yz_p4_seq[seq_num];
packet[5] = 0x02 // expert ? (0=unarmed, 1=normal)
| GET_FLAG(CH8_SW, 0x10) //VIDEO
| GET_FLAG(CH5_SW, 0x80) //FLIP
| GET_FLAG(CH9_SW, 0x04) //HEADLESS
| GET_FLAG(CH7_SW, 0x20); //SNAPSHOT
packet[6] = GET_FLAG(CH6_SW, 0x80); //LED
| GET_FLAG(CH8_SW, 0x10) //VIDEO
| GET_FLAG(CH5_SW, 0x80) //FLIP
| GET_FLAG(CH9_SW, 0x04) //HEADLESS
| GET_FLAG(CH7_SW, 0x20); //SNAPSHOT
packet[6] = GET_FLAG(CH6_SW, 0x80); //LED
packet[7] = packet[0];
for(uint8_t idx = 1; idx < MT99XX_PACKET_SIZE-2; idx++)
packet[7] += packet[idx];
@@ -274,7 +301,7 @@ static void __attribute__((unused)) MT99XX_send_packet()
//Hopp
hopping_frequency_no++;
if(sub_protocol == YZ || sub_protocol == A180 || sub_protocol == DRAGON || sub_protocol == F949G)
if(sub_protocol == YZ || sub_protocol == A180 || sub_protocol == DRAGON || sub_protocol == F949G || sub_protocol == PA18+8)
hopping_frequency_no++; // skip every other channel
if(hopping_frequency_no > 15)
hopping_frequency_no = 0;
@@ -284,6 +311,12 @@ static void __attribute__((unused)) MT99XX_send_packet()
XN297_SetFreqOffset();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, MT99XX_PACKET_SIZE);
#if 0
for(uint8_t i=0; i<MT99XX_PACKET_SIZE; i++)
debug(" %02X",packet[i]);
debugln();
#endif
}
static void __attribute__((unused)) MT99XX_RF_init()
@@ -304,9 +337,9 @@ static void __attribute__((unused)) MT99XX_RF_init()
static void __attribute__((unused)) MT99XX_initialize_txid()
{
rx_tx_addr[1] = rx_tx_addr[3]; // RX_Num
switch(protocol)
num_ch = rx_tx_addr[1]; // PA18
rx_tx_addr[1] = rx_tx_addr[3]; // RX_Num
switch(sub_protocol)
{
case YZ:
rx_tx_addr[0] = 0x53; // test (SB id)
@@ -348,8 +381,35 @@ static void __attribute__((unused)) MT99XX_initialize_txid()
//channel_offset = 0x03
break;
#endif
default: //MT99 & H7 & A180 & DRAGON & F949G
#ifdef FORCE_PA18_ID1
case PA18+8:
rx_tx_addr[0] = 0xC9; // zebble ID
rx_tx_addr[1] = 0x02;
rx_tx_addr[2] = 0x13;
num_ch = 0x89; // additional crc init. How is this calculated? or could it be random?
//crc8 = 0xDE
//channel_offset = 0x03
//1Mb C=5 S=Y A= C9 02 13 CC CC P(9)= E1 70 70 70 20 20 00 20 1A -> 0x91 + 0x89 => 0x1A
// S=Y A= C9 02 13 CC CC P(9)= E1 70 70 70 20 A0 00 20 9A -> 0x11 + 0x89 => 0x9A
//bind S=Y A= CC CC CC CC CC P(9)= 20 14 03 25 C9 02 13 89 55
break;
#endif
#ifdef FORCE_PA18_ID2
case PA18+8:
rx_tx_addr[0] = 0x0E;
rx_tx_addr[1] = 0x05;
rx_tx_addr[2] = 0x13;
num_ch = 0xD1; // additional crc init. How is this calculated? or could it be random?
//crc8 = 0x28
//channel_offset = 0x00
//1Mb C=2 S=Y A= 0E 05 13 CC CC P(9)= E1 70 70 70 20 60 00 60 E2 -> 0x11 + 0xD1 => 0xE2
//bind S=Y A= CC CC CC CC CC P(9)= 20 14 03 25 0E 05 13 D1 55
break;
#endif
default: //MT99 & H7 & A180 & DRAGON & F949G & PA18
rx_tx_addr[2] = 0x00;
if(sub_protocol == PA18+8)
rx_tx_addr[2] = 0x13;
break;
}
@@ -439,14 +499,40 @@ uint16_t MT99XX_callback()
void MT99XX_init(void)
{
if(sub_protocol != A180 && sub_protocol != DRAGON && sub_protocol != F949G)
BIND_IN_PROGRESS; // autobind protocol
if(protocol == PROTO_MT99XX2)
sub_protocol|=0x08; // Increase the number of sub_protocols for MT99XX
bind_counter = MT99XX_BIND_COUNT;
if(IS_BIND_DONE)
{
if(sub_protocol != A180 && sub_protocol != DRAGON && sub_protocol != F949G && sub_protocol != PA18+8)
BIND_IN_PROGRESS; // autobind protocol
else
bind_counter = 1;
}
MT99XX_initialize_txid();
MT99XX_RF_init();
packet_period = MT99XX_PACKET_PERIOD_MT;
switch(sub_protocol)
{
case YZ:
packet_period = MT99XX_PACKET_PERIOD_YZ;
break;
case FY805:
packet_period = MT99XX_PACKET_PERIOD_FY805;
break;
case F949G:
case A180:
packet_period = MT99XX_PACKET_PERIOD_A180;
break;
case PA18+8:
packet_period = MT99XX_PACKET_PERIOD_PA18;
break;
default:
packet_period = MT99XX_PACKET_PERIOD_MT;
break;
}
packet_count=0;
phase=MT99XX_DATA;

View File

@@ -45,7 +45,7 @@
45,E01X,E012,E015
46,V911S,V911S,E119
47,GD00x,GD_V1,GD_V2
48,V761,3CH,4CH
48,V761,3CH,4CH,TOPRC
49,KF606,KF606,MIG320
50,Redpine,Fast,Slow
51,Potensic,A20
@@ -55,7 +55,7 @@
55,Frsky_RX,Multi,CloneTX,EraseTX,CPPM
56,AFHDS2A_RX,Multi,CPPM
57,HoTT,Sync,No_Sync
58,FX816,P38
58,FX,816,620
59,Bayang_RX,Multi,CPPM
60,Pelikan,Pro,Lite,SCX24
61,Tiger
@@ -80,11 +80,13 @@
80,E016H,E016Hv2
81,E010r5
82,LOLI
83,E129
83,E129,E129,C186
84,JOYSWAY
85,E016H
87,IKEA
88,WILLIFM
89,Losi
90,MouldKg,Analog,Digit
91,Xerall
91,Xerall
92,MT99xx,PA18
93,Kyosho2,KT-17

View File

@@ -33,6 +33,7 @@ const char STR_FRSKYX[] ="FrSky X";
const char STR_FRSKYX2[] ="FrSkyX2";
const char STR_ESKY[] ="ESky";
const char STR_MT99XX[] ="MT99XX";
const char STR_MT99XX2[] ="MT99XX2";
const char STR_MJXQ[] ="MJXq";
const char STR_SHENQI[] ="Shenqi";
const char STR_FY326[] ="FY326";
@@ -77,7 +78,7 @@ const char STR_SCANNER[] ="Scanner";
const char STR_FRSKY_RX[] ="FrSkyRX";
const char STR_AFHDS2A_RX[] ="FS2A_RX";
const char STR_HOTT[] ="HoTT";
const char STR_FX816[] ="FX816";
const char STR_FX[] ="FX";
const char STR_BAYANG_RX[] ="BayanRX";
const char STR_PELIKAN[] ="Pelikan";
const char STR_TIGER[] ="Tiger";
@@ -87,6 +88,7 @@ const char STR_FRSKYR9[] ="FrSkyR9";
const char STR_PROPEL[] ="Propel";
const char STR_SKYARTEC[] ="Skyartc";
const char STR_KYOSHO[] ="Kyosho";
const char STR_KYOSHO2[] ="Kyosho2";
const char STR_RLINK[] ="RadLink";
const char STR_REALACC[] ="Realacc";
const char STR_OMP[] ="OMP";
@@ -120,6 +122,7 @@ const char STR_SUBTYPE_CX10[] = "\x07""Green\0 ""Blue\0 ""DM007\0 ""-\0
const char STR_SUBTYPE_CG023[] = "\x05""Std\0 ""YD829";
const char STR_SUBTYPE_BAYANG[] = "\x07""Std\0 ""H8S3D\0 ""X16 AH\0""IRDrone""DHD D4\0""QX100\0 ";
const char STR_SUBTYPE_MT99[] = "\x06""MT99\0 ""H7\0 ""YZ\0 ""LS\0 ""FY805\0""A180\0 ""Dragon""F949G\0";
const char STR_SUBTYPE_MT992[] = "\x04""PA18";
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";
@@ -139,7 +142,6 @@ const char STR_SUBTYPE_REDPINE[] = "\x04""Fast""Slow";
const char STR_SUBTYPE_POTENSIC[] = "\x03""A20";
const char STR_SUBTYPE_ZSX[] = "\x07""280JJRC";
const char STR_SUBTYPE_HEIGHT[] = "\x03""5ch""8ch";
const char STR_SUBTYPE_FX816[] = "\x03""P38";
const char STR_SUBTYPE_XN297DUMP[] = "\x07""250Kbps""1Mbps\0 ""2Mbps\0 ""Auto\0 ""NRF\0 ""CC2500\0";
const char STR_SUBTYPE_ESKY150[] = "\x03""4ch""7ch";
const char STR_SUBTYPE_ESKY150V2[] = "\x05""150V2";
@@ -153,15 +155,17 @@ const char STR_SUBTYPE_WFLY[] = "\x05""WFR0x";
const char STR_SUBTYPE_WFLY2[] = "\x05""RF20x";
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_V761[] = "\x03""3ch""4ch";
const char STR_SUBTYPE_V761[] = "\x05""3ch\0 ""4ch\0 ""TOPRC";
const char STR_SUBTYPE_RLINK[] = "\x07""Surface""Air\0 ""DumboRC";
const char STR_SUBTYPE_REALACC[] = "\x03""R11";
const char STR_SUBTYPE_KYOSHO[] = "\x04""FHSS""Hype";
const char STR_SUBTYPE_KYOSHO2[] = "\x05""KT-17";
const char STR_SUBTYPE_FUTABA[] = "\x05""SFHSS";
const char STR_SUBTYPE_JJRC345[] = "\x08""JJRC345\0""SkyTmblr";
const char STR_SUBTYPE_MOULKG[] = "\x06""Analog""Digit\0";
const char STR_SUBTYPE_KF606[] = "\x06""KF606\0""MIG320";
const char STR_SUBTYPE_E129[] = "\x04""E129""C186";
const char STR_SUBTYPE_FX[] = "\x03""816""620";
#define NO_SUBTYPE nullptr
#ifdef SEND_CPPM
@@ -247,11 +251,11 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(E016HV2_CC2500_INO)
{PROTO_E016HV2, STR_E016HV2, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_CC2500, E016HV2_init, E016HV2_callback },
#endif
#if defined(E01X_NRF24L01_INO)
{PROTO_E01X, STR_E01X, STR_SUBTYPE_E01X, 2, OPTION_OPTION, 0, 0, SW_NRF, E01X_init, E01X_callback },
#if defined(E01X_CYRF6936_INO)
{PROTO_E01X, STR_E01X, STR_SUBTYPE_E01X, 2, OPTION_NONE, 0, 0, SW_CYRF, E01X_init, E01X_callback },
#endif
#if defined(E129_CYRF6936_INO)
{PROTO_E129, STR_E129, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_CYRF, E129_init, E129_callback },
{PROTO_E129, STR_E129, STR_SUBTYPE_E129, 2, OPTION_NONE, 0, 0, SW_CYRF, E129_init, E129_callback },
#endif
#if defined(ESKY_NRF24L01_INO)
{PROTO_ESKY, STR_ESKY, STR_SUBTYPE_ESKY, 2, OPTION_NONE, 0, 1, SW_NRF, ESKY_init, ESKY_callback },
@@ -302,8 +306,8 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(FUTABA_CC2500_INO)
{PROTO_FUTABA, STR_FUTABA, STR_SUBTYPE_FUTABA, 1, OPTION_RFTUNE, 1, 1, SW_CC2500, SFHSS_init, SFHSS_callback },
#endif
#if defined(FX816_NRF24L01_INO)
{PROTO_FX816, STR_FX816, STR_SUBTYPE_FX816, 1, OPTION_NONE, 0, 0, SW_NRF, FX816_init, FX816_callback },
#if defined(FX_NRF24L01_INO)
{PROTO_FX, STR_FX, STR_SUBTYPE_FX, 2, OPTION_NONE, 0, 0, SW_NRF, FX_init, FX_callback },
#endif
#if defined(FY326_NRF24L01_INO)
{PROTO_FY326, STR_FY326, STR_SUBTYPE_FY326, 2, OPTION_NONE, 0, 0, SW_NRF, FY326_init, FY326_callback },
@@ -356,6 +360,9 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(KYOSHO_A7105_INO)
{PROTO_KYOSHO, STR_KYOSHO, STR_SUBTYPE_KYOSHO, 2, OPTION_NONE, 0, 1, SW_A7105, KYOSHO_init, KYOSHO_callback },
#endif
#if defined(KYOSHO2_NRF24L01_INO)
{PROTO_KYOSHO2, STR_KYOSHO2, STR_SUBTYPE_KYOSHO2, 1, OPTION_NONE, 0, 0, SW_NRF, KYOSHO2_init, KYOSHO2_callback },
#endif
#if defined(LOLI_NRF24L01_INO)
{PROTO_LOLI, STR_LOLI, NO_SUBTYPE, 0, OPTION_NONE, 1, 0, SW_NRF, LOLI_init, LOLI_callback },
#endif
@@ -374,6 +381,9 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(MT99XX_CCNRF_INO)
{PROTO_MT99XX, STR_MT99XX, STR_SUBTYPE_MT99, 8, OPTION_NONE, 0, 0, SW_NRF, MT99XX_init, MT99XX_callback },
#endif
#if defined(MT99XX_CCNRF_INO)
{PROTO_MT99XX2, STR_MT99XX2, STR_SUBTYPE_MT992, 1, OPTION_NONE, 0, 0, SW_NRF, MT99XX_init, MT99XX_callback },
#endif
#if defined(NCC1701_NRF24L01_INO)
{PROTO_NCC1701, STR_NCC1701, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, NCC_init, NCC_callback },
#endif
@@ -432,7 +442,7 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_V2X2, STR_V2X2, STR_SUBTYPE_V2X2, 3, OPTION_NONE, 0, 0, SW_NRF, V2X2_init, V2X2_callback },
#endif
#if defined(V761_NRF24L01_INO)
{PROTO_V761, STR_V761, STR_SUBTYPE_V761, 2, OPTION_NONE, 0, 0, SW_NRF, V761_init, V761_callback },
{PROTO_V761, STR_V761, STR_SUBTYPE_V761, 3, OPTION_NONE, 0, 0, SW_NRF, V761_init, V761_callback },
#endif
#if defined(V911S_CCNRF_INO)
{PROTO_V911S, STR_V911S, STR_SUBTYPE_V911S, 2, OPTION_RFTUNE, 0, 0, SW_NRF, V911S_init, V911S_callback },

View File

@@ -19,7 +19,7 @@
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_REVISION 3
#define VERSION_PATCH_LEVEL 0
#define VERSION_PATCH_LEVEL 20
#define MODE_SERIAL 0
@@ -73,7 +73,7 @@ enum PROTOCOLS
PROTO_BUGSMINI = 42, // =>NRF24L01
PROTO_TRAXXAS = 43, // =>CYRF6936
PROTO_NCC1701 = 44, // =>NRF24L01
PROTO_E01X = 45, // =>NRF24L01
PROTO_E01X = 45, // =>CYRF6936
PROTO_V911S = 46, // =>NRF24L01
PROTO_GD00X = 47, // =>NRF24L01
PROTO_V761 = 48, // =>NRF24L01
@@ -86,7 +86,7 @@ enum PROTOCOLS
PROTO_FRSKY_RX = 55, // =>CC2500
PROTO_AFHDS2A_RX= 56, // =>A7105
PROTO_HOTT = 57, // =>CC2500
PROTO_FX816 = 58, // =>NRF24L01
PROTO_FX = 58, // =>NRF24L01
PROTO_BAYANG_RX = 59, // =>NRF24L01
PROTO_PELIKAN = 60, // =>A7105
PROTO_TIGER = 61, // =>NRF24L01
@@ -119,6 +119,8 @@ enum PROTOCOLS
PROTO_LOSI = 89, // =>CYRF6936
PROTO_MOULDKG = 90, // =>NRF24L01
PROTO_XERALL = 91, // =>NRF24L01
PROTO_MT99XX2 = 92, // =>NRF24L01, extension of MT99XX protocol
PROTO_KYOSHO2 = 93, // =>NRF24L01
PROTO_NANORF = 126, // =>NRF24L01
PROTO_TEST = 127, // =>CC2500
@@ -236,6 +238,10 @@ enum MT99XX
DRAGON = 6,
F949G = 7,
};
enum MT99XX2
{
PA18 = 0,
};
enum MJXQ
{
WLH08 = 0,
@@ -385,7 +391,6 @@ enum ESKY
ESKY_STD = 0,
ESKY_ET4 = 1,
};
enum FRSKY_RX
{
FRSKY_RX = 0,
@@ -393,68 +398,69 @@ enum FRSKY_RX
FRSKY_ERASE = 2,
FRSKY_CPPM = 3,
};
enum FRSKYL
{
LR12 = 0,
LR12_6CH = 1,
};
enum HOTT
{
HOTT_SYNC = 0,
HOTT_NO_SYNC= 1,
};
enum PELIKAN
{
PELIKAN_PRO = 0,
PELIKAN_LITE= 1,
PELIKAN_SCX24=2,
};
enum V761
{
V761_3CH = 0,
V761_4CH = 1,
V761_TOPRC = 2,
};
enum HEIGHT
{
HEIGHT_5CH = 0,
HEIGHT_8CH = 1,
};
enum KYOSHO
{
KYOSHO_FHSS = 0,
KYOSHO_HYPE = 1,
};
enum JJRC345
{
JJRC345 = 0,
SKYTMBLR = 1,
};
enum RLINK
{
RLINK_SURFACE = 0,
RLINK_AIR = 1,
RLINK_DUMBORC = 2,
};
enum MOULDKG
{
MOULDKG_ANALOG = 0,
MOULDKG_DIGIT = 1,
};
enum KF606
{
KF606_KF606 = 0,
KF606_MIG320 = 1,
};
enum E129
{
E129_E129 = 0,
E129_C186 = 1,
};
enum FX
{
FX816 = 0,
FX620 = 1,
};
#define NONE 0
#define P_HIGH 1
@@ -900,7 +906,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
FRSKY_RX 55
AFHDS2A_RX 56
HOTT 57
FX816 58
FX 58
BAYANG_RX 59
PELIKAN 60
TIGER 61
@@ -1276,12 +1282,12 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
data[4-]= packed channels data, 11 bit per channel
Type 0x0E HoTT telemetry
length: 14
length: 15
data[0] = TX_RSSI
data[1] = TX_LQI
data[2] = type
data[3] = page
data[4-13] = data
data[4-14] = data
Type 0x0F M-Link telemetry
length: 10

View File

@@ -179,7 +179,7 @@ uint8_t option;
uint8_t cur_protocol[3];
uint8_t prev_option;
uint8_t prev_power=0xFD; // unused power value
uint8_t RX_num;
uint8_t RX_num;
//Serial RX variables
#define BAUD 100000

View File

@@ -183,11 +183,9 @@ void NRF24L01_SetPower()
power=NRF_POWER_0;
if(prev_power != power)
{
rf_setup = (rf_setup & 0xF9) | (power << 1);
rf_setup = (rf_setup & 0xF8) | (power << 1);
if(power==3)
rf_setup |=0x01; // Si24r01 full power, unused bit for NRF
else
rf_setup &=0xFE;
rf_setup |= 0x01; // Si24r01 full power, unused bit for NRF
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
prev_power=power;
}
@@ -246,112 +244,6 @@ uint8_t NRF24L01_packet_ack()
return PKT_PENDING;
}
//
// HS6200 emulation layer
///////////////////////////
static uint8_t hs6200_crc;
static uint16_t hs6200_crc_init;
static uint8_t hs6200_tx_addr[5];
static uint8_t hs6200_address_length;
static const uint8_t hs6200_scramble[] = {
0x80,0xf5,0x3b,0x0d,0x6d,0x2a,0xf9,0xbc,
0x51,0x8e,0x4c,0xfd,0xc1,0x65,0xd0 }; // todo: find all 32 bytes ...
void HS6200_SetTXAddr(const uint8_t* addr, uint8_t len)
{
if(len < 4)
len = 4;
else if(len > 5)
len = 5;
// use nrf24 address field as a longer preamble
if(addr[len-1] & 0x80)
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\x55\x55\x55\x55\x55", 5);
else
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\xaa\xaa\xaa\xaa\xaa", 5);
// precompute address crc
crc = 0xffff;
for(int i=0; i<len; i++)
crc16_update(addr[len-1-i], 8);
hs6200_crc_init=crc;
memcpy(hs6200_tx_addr, addr, len);
hs6200_address_length = len;
}
static uint16_t hs6200_calc_crc(uint8_t* msg, uint8_t len)
{
uint8_t pos;
crc = hs6200_crc_init;
// pcf + payload
for(pos=0; pos < len-1; pos++)
crc16_update(msg[pos], 8);
// last byte (1 bit only)
if(len > 0)
crc16_update(msg[pos+1], 1);
return crc;
}
void HS6200_Configure(uint8_t flags)
{
hs6200_crc = !!(flags & _BV(NRF24L01_00_EN_CRC));
flags &= ~(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xff);
}
void HS6200_WritePayload(uint8_t* msg, uint8_t len)
{
uint8_t payload[32];
const uint8_t no_ack = 1; // never ask for an ack
static uint8_t pid;
uint8_t pos = 0;
if(len > sizeof(hs6200_scramble))
len = sizeof(hs6200_scramble);
// address
for(int i=hs6200_address_length-1; i>=0; i--)
payload[pos++] = hs6200_tx_addr[i];
// guard bytes
payload[pos++] = hs6200_tx_addr[0];
payload[pos++] = hs6200_tx_addr[0];
// packet control field
payload[pos++] = ((len & 0x3f) << 2) | (pid & 0x03);
payload[pos] = (no_ack & 0x01) << 7;
pid++;
// scrambled payload
if(len > 0)
{
payload[pos++] |= (msg[0] ^ hs6200_scramble[0]) >> 1;
for(uint8_t i=1; i<len; i++)
payload[pos++] = ((msg[i-1] ^ hs6200_scramble[i-1]) << 7) | ((msg[i] ^ hs6200_scramble[i]) >> 1);
payload[pos] = (msg[len-1] ^ hs6200_scramble[len-1]) << 7;
}
// crc
if(hs6200_crc)
{
uint16_t crc = hs6200_calc_crc(&payload[hs6200_address_length+2], len+2);
uint8_t hcrc = crc >> 8;
uint8_t lcrc = crc & 0xff;
payload[pos++] |= (hcrc >> 1);
payload[pos++] = (hcrc << 7) | (lcrc >> 1);
payload[pos++] = lcrc << 7;
}
NRF24L01_WritePayload(payload, pos);
delayMicroseconds(option+20);
NRF24L01_WritePayload(payload, pos);
}
//
// End of HS6200 emulation
////////////////////////////
///////////////
// LT8900 emulation layer
uint8_t LT8900_buffer[64];

View File

@@ -250,11 +250,16 @@ uint16_t PROPEL_callback()
if (_BV(NRF24L01_07_RX_DR) & NRF24L01_ReadReg(NRF24L01_07_STATUS))
{// data received from the model
NRF24L01_ReadPayload(packet_in, PROPEL_PACKET_SIZE);
#if 1
for(uint8_t i=0; i<PROPEL_PACKET_SIZE; i++)
debug("%02X ",packet_in[i]);
debugln("");
#endif
if (packet_in[0] == 0xa3 && memcmp(&packet_in[1],rx_id,3)==0)
{
telemetry_counter++; //LQI
v_lipo1=packet[5]; //number of life left?
v_lipo2=packet[4]; //bit mask: 0x80=flying, 0x08=taking off, 0x04=landing, 0x00=landed/crashed
v_lipo1=packet_in[5]; //number of life left?
v_lipo2=packet_in[4]; //bit mask: 0x80=flying, 0x08=taking off, 0x04=landing, 0x00=landed/crashed
if(telemetry_lost==0)
telemetry_link=1;
}

View File

@@ -17,7 +17,7 @@
#define RF2500_ADDR_LENGTH 4
uint8_t RF2500_payload_length, RF2500_tx_addr[RF2500_ADDR_LENGTH], RF2500_buf[80];
uint8_t RF2500_payload_length, RF2500_tx_addr[RF2500_ADDR_LENGTH], RF2500_buf[100];
bool RF2500_scramble_enabled;
static void __attribute__((unused)) RF2500_Init(uint8_t payload_length, bool scramble)
@@ -35,9 +35,17 @@ static void __attribute__((unused)) RF2500_SetTXAddr(const uint8_t* addr)
static void __attribute__((unused)) RF2500_BuildPayload(uint8_t* buffer)
{
const uint8_t RF2500_scramble[] = { 0xD0, 0x9E, 0x53, 0x33, 0xD8, 0xBA, 0x98, 0x08, 0x24, 0xCB, 0x3B, 0xFC, 0x71, 0xA3, 0xF4, 0x55 };
const uint16_t RF2500_crc_xorout_scramble = 0xAEE4;
const uint8_t RF2500_scramble[] = { 0xD0, 0x9E, 0x53, 0x33, 0xD8, 0xBA, 0x98, 0x08, 0x24, 0xCB, 0x3B, 0xFC, 0x71, 0xA3, 0xF4, 0x55, 0x68, 0x4F, 0xA9 }; //0x4F: unsure
uint16_t RF2500_crc_xorout_scramble;
if(RF2500_payload_length == 16)
RF2500_crc_xorout_scramble = 0xAEE4;
else //19
RF2500_crc_xorout_scramble = 0xE7C5;
#if 0
for(uint8_t i=0; i<RF2500_payload_length; i++)
debug("%02X ", buffer[i]);
#endif
//Scramble the incoming buffer
if(RF2500_scramble_enabled)
for(uint8_t i=0; i<RF2500_payload_length; i++)
@@ -50,6 +58,10 @@ static void __attribute__((unused)) RF2500_BuildPayload(uint8_t* buffer)
buffer[RF2500_payload_length ] = bit_reverse(crc>>8);
buffer[RF2500_payload_length+1] = bit_reverse(crc);
#if 0
debugln("C:%02X %02X",buffer[RF2500_payload_length ], buffer[RF2500_payload_length+1]);
#endif
if(RF2500_scramble_enabled)
{
buffer[RF2500_payload_length ] ^= RF2500_crc_xorout_scramble>>8;

View File

@@ -309,8 +309,8 @@ static void multi_send_status()
#ifdef HOTT_FW_TELEMETRY
void HOTT_short_frame()
{
multi_send_header(MULTI_TELEMETRY_HOTT, 14);
for (uint8_t i = 0; i < 14; i++) // TX RSSI and TX LQI values followed by frame number and telemetry data
multi_send_header(MULTI_TELEMETRY_HOTT, 15);
for (uint8_t i = 0; i < 15; i++) // TX RSSI and TX LQI values followed by frame number and telemetry data
Serial_write(packet_in[i]);
}
#endif

View File

@@ -25,13 +25,15 @@ Multiprotocol is distributed in the hope that it will be useful,
#define V761_BIND_COUNT 200
#define V761_BIND_FREQ 0x28
#define V761_RF_NUM_CHANNELS 3
#define TOPRC_BIND_FREQ 0x2A
#define TOPRC_PACKET_PERIOD 14120 // Timeout for callback in uSec
enum
{
{
V761_BIND1 = 0,
V761_BIND2,
V761_DATA
};
};
static void __attribute__((unused)) V761_set_checksum()
{
@@ -56,14 +58,11 @@ static void __attribute__((unused)) V761_send_packet()
if(phase != V761_DATA)
{
packet[0] = rx_tx_addr[0];
packet[1] = rx_tx_addr[1];
packet[2] = rx_tx_addr[2];
packet[3] = rx_tx_addr[3];
memcpy(packet, rx_tx_addr, 4);
packet[4] = hopping_frequency[1];
packet[5] = hopping_frequency[2];
if(phase == V761_BIND2)
packet[6] = 0xf0; // ?
packet[6] = 0xF0; // ?
}
else
{
@@ -72,23 +71,22 @@ static void __attribute__((unused)) V761_send_packet()
{
hopping_frequency_no = 0;
packet_count++;
if(packet_count >= 4)
packet_count = 0;
packet_count &= 0x03;
}
packet[0] = convert_channel_8b(THROTTLE); // Throttle
packet[2] = convert_channel_8b(ELEVATOR)>>1; // Elevator
if(sub_protocol==V761_3CH)
{
packet[1] = convert_channel_8b(RUDDER)>>1; // Rudder
packet[3] = convert_channel_8b(AILERON)>>1; // Aileron
}
else
if(sub_protocol == V761_4CH || sub_protocol == V761_TOPRC)
{
packet[1] = convert_channel_8b(AILERON)>>1; // Aileron
packet[3] = convert_channel_8b(RUDDER)>>1; // Rudder
}
else
{
packet[1] = convert_channel_8b(RUDDER)>>1; // Rudder
packet[3] = convert_channel_8b(AILERON)>>1; // Aileron
}
packet[5] = packet_count<<6; // 0X, 4X, 8X, CX
packet[4] = 0x20; // Trims 00..20..40, 0X->20 4X->TrAil 8X->TrEle CX->TrRud
@@ -112,7 +110,7 @@ static void __attribute__((unused)) V761_send_packet()
packet[6] = GET_FLAG(CH7_SW, 0x20) // Flip
|GET_FLAG(CH8_SW, 0x08) // RTH activation
|GET_FLAG(CH9_SW, 0x10); // RTH on/off
if(sub_protocol==V761_3CH)
if(sub_protocol == V761_3CH)
packet[6] |= 0x80; // Unknown, set on original V761-1 dump but not on eachine dumps, keeping for compatibility
}
V761_set_checksum();
@@ -137,28 +135,36 @@ static void __attribute__((unused)) V761_RF_init()
static void __attribute__((unused)) V761_initialize_txid()
{
#ifdef V761_FORCE_ID
switch(RX_num%5)
if(sub_protocol == V761_TOPRC)
{ //Dump from air on TopRCHobby TX
memcpy(rx_tx_addr,(uint8_t *)"\xD5\x01\x00\x00",4);
memcpy(hopping_frequency,(uint8_t *)"\x2E\x41",2);
}
else
{
case 1: //Dump from air on Protonus TX
memcpy(rx_tx_addr,(uint8_t *)"\xE8\xE4\x45\x09",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x21",2);
break;
case 2: //Dump from air on mshagg2 TX
memcpy(rx_tx_addr,(uint8_t *)"\xAE\xD1\x45\x09",4);
memcpy(hopping_frequency,(uint8_t *)"\x13\x1D",2);
break;
case 3: //Dump from air on MikeHRC Eachine TX
memcpy(rx_tx_addr,(uint8_t *)"\x08\x03\x00\xA0",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x21",2);
break;
case 4: //Dump from air on Crashanium Eachine TX
memcpy(rx_tx_addr,(uint8_t *)"\x58\x08\x00\xA0",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x31",2);
break;
default: //Dump from SPI
memcpy(rx_tx_addr,(uint8_t *)"\x6f\x2c\xb1\x93",4);
memcpy(hopping_frequency,(uint8_t *)"\x14\x1e",2);
break;
switch(RX_num%5)
{
case 1: //Dump from air on Protonus TX
memcpy(rx_tx_addr,(uint8_t *)"\xE8\xE4\x45\x09",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x21",2);
break;
case 2: //Dump from air on mshagg2 TX
memcpy(rx_tx_addr,(uint8_t *)"\xAE\xD1\x45\x09",4);
memcpy(hopping_frequency,(uint8_t *)"\x13\x1D",2);
break;
case 3: //Dump from air on MikeHRC Eachine TX
memcpy(rx_tx_addr,(uint8_t *)"\x08\x03\x00\xA0",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x21",2);
break;
case 4: //Dump from air on Crashanium Eachine TX
memcpy(rx_tx_addr,(uint8_t *)"\x58\x08\x00\xA0",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x31",2);
break;
default: //Dump from SPI
memcpy(rx_tx_addr,(uint8_t *)"\x6f\x2c\xb1\x93",4);
memcpy(hopping_frequency,(uint8_t *)"\x14\x1e",2);
break;
}
}
#else
//Tested with Eachine RX
@@ -180,8 +186,8 @@ uint16_t V761_callback()
if(bind_counter)
bind_counter--;
packet_count ++;
XN297_RFChannel(V761_BIND_FREQ);
XN297_SetTXAddr((uint8_t*)"\x34\x43\x10\x10", 4);
XN297_RFChannel(sub_protocol == V761_TOPRC ? TOPRC_BIND_FREQ : V761_BIND_FREQ);
XN297_SetTXAddr(rx_id, 4);
V761_send_packet();
if(packet_count >= 20)
{
@@ -210,17 +216,28 @@ uint16_t V761_callback()
return 15730;
case V761_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(V761_PACKET_PERIOD);
telemetry_set_input_sync(packet_period);
#endif
V761_send_packet();
break;
}
return V761_PACKET_PERIOD;
return packet_period;
}
void V761_init(void)
{
V761_initialize_txid();
if(sub_protocol == V761_TOPRC)
{
memcpy(rx_id,(uint8_t*)"\x20\x21\x05\x0A",4);
packet_period = TOPRC_PACKET_PERIOD;
}
else
{
memcpy(rx_id,(uint8_t*)"\x34\x43\x10\x10",4);
packet_period = V761_PACKET_PERIOD;
}
if(IS_BIND_IN_PROGRESS)
{
bind_counter = V761_BIND_COUNT;
@@ -231,7 +248,7 @@ void V761_init(void)
XN297_SetTXAddr(rx_tx_addr, 4);
phase = V761_DATA;
}
V761_RF_init();
hopping_frequency_no = 0;
packet_count = 0;

View File

@@ -26,7 +26,7 @@
#define V911S_PACKET_SIZE 16
#define V911S_RF_BIND_CHANNEL 35
#define V911S_NUM_RF_CHANNELS 8
#define V911S_BIND_COUNT 200
#define V911S_BIND_COUNT 800
// flags going to packet[1]
#define V911S_FLAG_EXPERT 0x04
@@ -34,6 +34,7 @@
#define E119_FLAG_CALIB 0x40
// flags going to packet[2]
#define V911S_FLAG_CALIB 0x01
#define A220_FLAG_6G3D 0x04
static void __attribute__((unused)) V911S_send_packet()
{
@@ -69,9 +70,12 @@ static void __attribute__((unused)) V911S_send_packet()
packet[ 1]=GET_FLAG(!CH6_SW,V911S_FLAG_EXPERT); // short press on left button
packet[ 2]=GET_FLAG(CH5_SW,V911S_FLAG_CALIB); // long press on right button
}
else
else//E119
{
packet[ 1]=GET_FLAG(!CH6_SW,E119_FLAG_EXPERT) // short press on left button
|GET_FLAG( CH5_SW,E119_FLAG_CALIB); // short press on right button
packet[ 2]=GET_FLAG( CH7_SW,A220_FLAG_6G3D); // short press on right button
}
//packet[3..6]=trims TAER signed
uint16_t ch=convert_channel_16b_limit(THROTTLE ,0,0x7FF);
@@ -90,7 +94,7 @@ static void __attribute__((unused)) V911S_send_packet()
packet[12] = ch>>5;
}
else
{
{//E119
ch=0x7FF-ch;
packet[ 9]|= ch<<6;
packet[10] = ch>>2;
@@ -103,7 +107,7 @@ static void __attribute__((unused)) V911S_send_packet()
if(sub_protocol==V911S_STD)
XN297_WritePayload(packet, V911S_PACKET_SIZE);
else
else//E119
XN297_WriteEnhancedPayload(packet, V911S_PACKET_SIZE, IS_BIND_IN_PROGRESS?0:1);
XN297_SetPower(); // Set tx_power
@@ -115,7 +119,7 @@ static void __attribute__((unused)) V911S_RF_init()
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_250K);
if(sub_protocol==V911S_STD)
XN297_SetTXAddr((uint8_t *)"KNBND",5); // V911S Bind address
else
else//E119
XN297_SetTXAddr((uint8_t *)"XPBND",5); // E119 Bind address
XN297_HoppingCalib(V911S_NUM_RF_CHANNELS); // Calibrate all channels
XN297_RFChannel(V911S_RF_BIND_CHANNEL); // Set bind channel
@@ -171,8 +175,7 @@ void V911S_init(void)
rf_ch_num=0;
}
else
{
//E119
{//E119
rx_tx_addr[0]=0x30;
rx_tx_addr[1]=0xFF;
rx_tx_addr[2]=0xD1;

View File

@@ -242,22 +242,23 @@
//Make sure protocols are selected correctly
#ifndef A7105_INSTALLED
#undef AFHDS2A_A7105_INO
#undef AFHDS2A_RX_A7105_INO
#undef BUGS_A7105_INO
#undef FLYSKY_A7105_INO
#undef HEIGHT_A7105_INO
#undef HUBSAN_A7105_INO
#undef JOYSWAY_A7105_INO
#undef KYOSHO_A7105_INO
#undef PELIKAN_A7105_INO
#undef WFLY2_A7105_INO
#undef AFHDS2A_A7105_INO
#undef AFHDS2A_RX_A7105_INO
#undef BUGS_A7105_INO
#undef FLYSKY_A7105_INO
#undef HEIGHT_A7105_INO
#undef HUBSAN_A7105_INO
#undef JOYSWAY_A7105_INO
#undef KYOSHO_A7105_INO
#undef PELIKAN_A7105_INO
#undef WFLY2_A7105_INO
#endif
#ifndef CYRF6936_INSTALLED
#undef DEVO_CYRF6936_INO
#undef DSM_CYRF6936_INO
#undef DSM_RX_CYRF6936_INO
#undef E010R5_CYRF6936_INO
#undef E01X_CYRF6936_INO
#undef E129_CYRF6936_INO
#undef J6PRO_CYRF6936_INO
#undef LOSI_CYRF6936_INO
@@ -295,11 +296,10 @@
#undef CX10_NRF24L01_INO
#undef DM002_NRF24L01_INO
#undef E016H_NRF24L01_INO
#undef E01X_NRF24L01_INO
#undef ESKY_NRF24L01_INO
#undef ESKY150_NRF24L01_INO
#undef FQ777_NRF24L01_INO
#undef FX816_NRF24L01_INO
#undef FX_NRF24L01_INO
#undef FY326_NRF24L01_INO
#undef GW008_NRF24L01_INO
#undef H8_3D_NRF24L01_INO
@@ -307,6 +307,7 @@
#undef HONTAI_NRF24L01_INO
#undef JJRC345_NRF24L01_INO
#undef KN_NRF24L01_INO
#undef KYOSHO2_NRF24L01_INO
#undef LOLI_NRF24L01_INO
#undef MOULDKG_NRF24L01_INO
#undef NCC1701_NRF24L01_INO

View File

@@ -609,12 +609,12 @@ static uint16_t XN297Dump_callback()
{
if(phase==0)
{
address_length=5;
memcpy(rx_tx_addr, (uint8_t *)"\x61\x94\x17\x27\xED", address_length); //"\xA3\x05\x22\xC1""\x5A\x20\x12\xAC"
address_length=3;
memcpy(rx_tx_addr, (uint8_t *)"\xBD\x54\x78", address_length); //"\x62\xE6\xBD\x54\x78"
bitrate=XN297DUMP_250K;
packet_length=32;
hopping_frequency_no=54; //bind ?, normal 60
bitrate=XN297DUMP_1M;
packet_length=7;
hopping_frequency_no=40; //bind ?, normal 40
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TXRX_OFF);
@@ -622,7 +622,7 @@ static uint16_t XN297Dump_callback()
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, address_length-2); // RX/TX address length
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, address_length); // set up RX address
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, packet_length); // Enable rx pipe 0
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency_no);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, option); //hopping_frequency_no);
debug("NRF dump, len=%d, rf=%d, address length=%d, bitrate=",packet_length,hopping_frequency_no,address_length);
switch(bitrate)
@@ -718,6 +718,7 @@ static uint16_t XN297Dump_callback()
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX)); // _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) |
}
NRF24L01_WriteReg(NRF24L01_05_RF_CH, option); //hopping_frequency_no);
}
}
else if(sub_protocol == XN297DUMP_CC2500)

View File

@@ -188,6 +188,7 @@
#define DSM_CYRF6936_INO
#define DSM_RX_CYRF6936_INO
#define E010R5_CYRF6936_INO
#define E01X_CYRF6936_INO
#define E129_CYRF6936_INO
#define J6PRO_CYRF6936_INO
#define LOSI_CYRF6936_INO
@@ -225,11 +226,10 @@
#define CX10_NRF24L01_INO //Include Q2X2 protocol
#define DM002_NRF24L01_INO
#define E016H_NRF24L01_INO
#define E01X_NRF24L01_INO
#define ESKY_NRF24L01_INO
#define ESKY150_NRF24L01_INO
#define FQ777_NRF24L01_INO
#define FX816_NRF24L01_INO
#define FX_NRF24L01_INO
#define FY326_NRF24L01_INO
#define GW008_NRF24L01_INO
#define HISKY_NRF24L01_INO
@@ -237,6 +237,7 @@
#define H8_3D_NRF24L01_INO
#define JJRC345_NRF24L01_INO
#define KN_NRF24L01_INO
#define KYOSHO2_NRF24L01_INO
#define LOLI_NRF24L01_INO
//#define MOULDKG_NRF24L01_INO
#define NCC1701_NRF24L01_INO
@@ -256,7 +257,7 @@
#define GD00X_CCNRF_INO
#define KF606_CCNRF_INO
#define MJXQ_CCNRF_INO
#define MT99XX_CCNRF_INO
#define MT99XX_CCNRF_INO //Include MT99XX2 protocol
#define OMP_CCNRF_INO
#define Q303_CCNRF_INO
#define Q90C_CCNRF_INO
@@ -612,7 +613,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
E012
E015
PROTO_E129
NONE
E129_E129
E129_C186
PROTO_ESKY
ESKY_STD
ESKY_ET4
@@ -665,8 +667,9 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PROTO_FRSKY_RX
FRSKY_RX
FRSKY_CLONE
PROTO_FX816
NONE
PROTO_FX
FX816
FX620
PROTO_FY326
FY326
FY319
@@ -720,6 +723,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PROTO_KYOSHO
KYOSHO_FHSS
KYOSHO_HYPE
PROTO_KYOSHO2
NONE
PROTO_LOLI
NONE
PROTO_LOSI
@@ -746,6 +751,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
A180
DRAGON
F949G
PROTO_MT99XX2
PA18
PROTO_NCC1701
NONE
PROTO_OMP

View File

@@ -0,0 +1,13 @@
#ifndef _IFACE_HS6200_H_
#define _IFACE_HS6200_H_
#include "iface_cyrf6936.h"
//HS6200
static void __attribute__((unused)) HS6200_Init(bool);
static void __attribute__((unused)) HS6200_SetTXAddr(const uint8_t*, uint8_t);
static void __attribute__((unused)) HS6200_SendPayload(uint8_t*, uint8_t);
#define HS6200_SetPower() CYRF_GFSK1M_SetPower()
#define HS6200_RFChannel(X) CYRF_ConfigRFChannel(X)
#endif

View File

@@ -76,11 +76,11 @@ CFlie|38|CFlie||||||||NRF24L01|
[DM002](Protocols_Details.md#DM002---33)|33|||||||||NRF24L01|XN297
[DSM](Protocols_Details.md#DSM---6)|6|DSM2_1F|DSM2_2F|DSMX_1F|DSMX_2F|AUTO|DSMR_1F|||CYRF6936|
[DSM_RX](Protocols_Details.md#DSM_RX---70)|70|Multi|CPPM|||||||CYRF6936|
[E010R5](Protocols_Details.md#E010R5---81)|81|||||||||CYRF6936/NRF24L01|RF2500
[E010R5](Protocols_Details.md#E010R5---81)|81|||||||||CYRF6936|RF2500
[E016H](Protocols_Details.md#E016H---85)|85|||||||||NRF24L01|XN297
[E016HV2](Protocols_Details.md#E016HV2---80)|80|||||||||CC2500/NRF24L01|unknown
[E01X](Protocols_Details.md#E01X---45)|45|E012|E015|||||||NRF24L01|HS6200
[E129](Protocols_Details.md#E129---83)|83|||||||||CYRF6936/NRF24L01|RF2500
[E01X](Protocols_Details.md#E01X---45)|45|E012|E015|||||||CYRF6936|HS6200
[E129](Protocols_Details.md#E129---83)|83|E129|C186|||||||CYRF6936|RF2500
[ESky](Protocols_Details.md#ESKY---16)|16|ESky|ET4|||||||NRF24L01|
[ESky150](Protocols_Details.md#ESKY150---35)|35|||||||||NRF24L01|
[ESky150V2](Protocols_Details.md#ESKY150V2---69)|69|||||||||CC2500|NRF51822
@@ -96,7 +96,7 @@ CFlie|38|CFlie||||||||NRF24L01|
[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|
[Futaba/SFHSS](Protocols_Details.md#Futaba---21)|21|SFHSS||||||||CC2500|
[FX816](Protocols_Details.md#FX816---58)|28|FX816|P38|||||||NRF24L01|
[FX](Protocols_Details.md#FX---58)|28|816|620|||||||NRF24L01|
[FY326](Protocols_Details.md#FY326---20)|20|FY326|FY319|||||||NRF24L01|
[GD00X](Protocols_Details.md#GD00X---47)|47|GD_V1*|GD_V2*|||||||NRF24L01|XN297L
[GW008](Protocols_Details.md#GW008---32)|32|||||||||NRF24L01|XN297
@@ -113,12 +113,14 @@ CFlie|38|CFlie||||||||NRF24L01|
[KF606](Protocols_Details.md#KF606---49)|49|KF606|MIG320|||||||NRF24L01|XN297
[KN](Protocols_Details.md#KN---9)|9|WLTOYS|FEILUN|||||||NRF24L01|
[Kyosho](Protocols_Details.md#Kyosho---73)|73|FHSS|Hype|||||||A7105|
[Kyosho2](Protocols_Details.md#Kyosho2---93)|93|KT-17||||||||NRF24L01|
[LOLI](Protocols_Details.md#LOLI---82)|82|||||||||NRF24L01|
[Losi](Protocols_Details.md#Losi---89)|89|||||||||CYRF6936|
[MJXq](Protocols_Details.md#MJXQ---18)|18|WLH08|X600|X800|H26D|E010*|H26WH|PHOENIX*||NRF24L01|XN297
[MLINK](Protocols_Details.md#MLINK---78)|78|||||||||CYRF6936|
[MouldKg](Protocols_Details.md#mouldkg---90)|90|Analog|Digit|||||||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||||||||NRF24L01|XN297
[NCC1701](Protocols_Details.md#NCC1701---44)|44|||||||||NRF24L01|
[OMP](Protocols_Details.md#OMP---77)|77|||||||||CC2500&NRF24L01|XN297L
[OpenLRS](Protocols_Details.md#OpenLRS---27)|27|||||||||None|
@@ -139,7 +141,7 @@ CFlie|38|CFlie||||||||NRF24L01|
[Tiger](Protocols_Details.md#Tiger---61)|61|||||||||NRF24L01|XN297
[Traxxas](Protocols_Details.md#Traxxas---43)|43|6519 RX||||||||CYRF6936|
[V2x2](Protocols_Details.md#V2X2---5)|5|V2x2|JXD506|MR101||||||NRF24L01|
[V761](Protocols_Details.md#V761---48)|48|3CH|4CH|||||||NRF24L01|XN297
[V761](Protocols_Details.md#V761---48)|48|3CH|4CH|TOPRC||||||NRF24L01|XN297
[V911S](Protocols_Details.md#V911S---46)|46|V911S*|E119*|||||||NRF24L01|XN297
[WFLY](Protocols_Details.md#WFLY---40)|40|WFR0x||||||||CYRF6936|
[WFLY2](Protocols_Details.md#WFLY2---79)|79|RF20x||||||||A7105|
@@ -396,18 +398,18 @@ A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
RX output will match the Devo standard EATR independently of the input configuration AETR, RETA... unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
Full telemetry is available if the RX supports it: TX_RSSI, A1 (set the ratio to 12.7) and A2 (set the ratio to 12.7), VFAS, RPM, temperature 1&2, GPS position/speed/altitude/time.
Full telemetry is available if the RX supports it: TX_RSSI, A1 (set the ratio to 12.7) and A2 (set the ratio to 12.7), VFAS, RPM, temperature 1&2, GPS position/speed/altitude/time. The GPS coordinates come in two flavors which can't be distinguished programmatically, to switch from one to the other add 2 to the Option/FixedID setting value (0->2, 1->3).
Bind procedure using serial:
- With the TX off, put the binding plug in and power on the RX (RX LED slow blink), then power it down and remove the binding plug. Receiver should now be in autobind mode.
- Turn on the TX, set protocol = Devo with option=0, turn off the TX (TX is now in autobind mode).
- Turn on the TX, set protocol = Devo with Option/FixedID=0, turn off the TX (TX is now in autobind mode).
- Turn on RX (RX LED fast blink).
- Turn on TX (RX LED solid, TX LED fast blink).
- Wait for bind on the TX to complete (TX LED solid).
- Make sure to set a uniq RX_Num value for model match.
- Change option to 1 to use the global ID.
- Do not touch option/RX_Num anymore.
- Note: it might be limited to only the RX705 but to get telemetry, the opion fields has to be set back to 0 at then end of the procedure...
- Change Option/FixedID to 1 to use the global ID.
- Do not touch Option/FixedID and RX_Num anymore.
- Note: it might be limited to only the RX705 but to get telemetry, the Option/FixedID field has to be set back to 0 at then end of the procedure...
Bind procedure using PPM:
- With the TX off, put the binding plug in and power on the RX (RX LED slow blink), then power it down and remove the binding plug. Receiver should now be in autobind mode.
@@ -576,11 +578,29 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LED|CALIB|HEADLESS|RTH|GLIDE
## E129 - *83*
Models: Eachine E129/E130 and Twister Ninja 250
## E01X - *45*
Autobind protocol
Not supported by Atmega328p modules.
### Sub_protocol E012 - *0*
Models: Eachine E012
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R||FLIP||HEADLESS|RTH
### Sub_protocol E015 - *1*
Models: Eachine E015
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|ARM|FLIP|LED|HEADLESS|RTH
## E129 - *83*
**Not supported by Atmega328p modules.**
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|Take off/Land|Emergency|Trim A|Trim E|Trim R
@@ -591,6 +611,14 @@ Take off with a none spring throttle is easier by putting both sticks down outwa
Calib is the same as the original radio with both sticks down and to the left in Mode 1/2, not sure about other modes.
### Sub_protocol E129 - *0*
Models: Eachine E129/E130 and Twister Ninja 250
### Sub_protocol C186 - *1*
Models: C186/E120, C127/E110, K127
The FC of the heli seems to store the trims Trim A/E/R=CH7..9. If you use these trims, make sure to center them after powering off the heli or they will be added to the previous trims and over correct.
## J6Pro - *22*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
@@ -957,15 +985,17 @@ Compatible RXs: X6/X6F/X6FG
Also called SFHSS depending on radio version.
### Sub_protocol SFHSS - *0*
Models: Futaba SFHSS RXs and XK models.
Models: Futaba SFHSS RXs and some XK models.
Extended limits and failsafe supported
Extended limits and failsafe supported.
RX output will match the Futaba standard servo throw, mid point and the channel order AETR independently of the input configuration AETR, RETA... unless if on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
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.
This protocol does not use bind on the TX side. The RX attaches to the first S-FHHSS TX around it when the bind button is pressed.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8
@@ -1005,16 +1035,20 @@ New generation of GD models
## KF606 - *49*
### Sub_protocol KF606 - *0*
Model: KF606
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A||T||TRIM
### Sub_protocol KF606 - *0*
Model: KF606
### Sub_protocol MIG320 - *1*
Model: Zhiyang MIG-320
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A||T||TRIM|LED
## MJXQ - *18*
Autobind protocol
@@ -1096,14 +1130,20 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
A|E|T|R|FLIP||||HEADLESS
### Sub_protocol A180 - *5*
Model: XK A180
Model: XK A180, F949S, F959
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A|E|T|R|3D6G
A180:
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|3D6G|RATE
F949S:
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T|R|RATE|RXLED|3D6G
### Sub_protocol DRAGON - *6*
Model: Eachine Mini Wing Dragon
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
@@ -1120,6 +1160,17 @@ CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|6G3D|Light
## MT99XX2 - *92*
### Sub_protocol PA18 - *92*
Model: PA18 mini
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T|R|MODE|FLIP|RTH
MODE: -100% beginner, 0% intermediate, +100% Expert
## OMP - *77*
Model: OMPHOBBY M1 & M2 Helis, T720 RC Glider
@@ -1287,7 +1338,11 @@ Rate: -100% High, +100% Low
Models: WLtoys V911S, XK A110
### Sub_protocol E119 - *1*
Models: Eachine E119, JJRC W01-J3
Models: Eachine E119, JJRC W01-J3, XK A220 P-40, XK A800 R2, F959S R2, A160 R2, A280
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T|R|CALIB|RATE|6G_3D
## XK - *62*
@@ -1517,27 +1572,6 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|STOP|FLIP|-|HEADLESS|RTH
## E01X - *45*
Autobind protocol
### Sub_protocol E012 - *0*
Models: Eachine E012
This protocol has been reported to not work properly due to the emulation of the HS6200 RF component using the NRF24L01. The option value is used to adjust the timing, try every values between -127 and +127. If it works please report which value you've used.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R||FLIP||HEADLESS|RTH
### Sub_protocol E015 - *1*
Models: Eachine E015
This protocol has been reported to not work properly due to the emulation of the HS6200 RF component using the NRF24L01. The option value is used to adjust the timing, try every values between -127 and +127. If it works please report which value you've used.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|ARM|FLIP|LED|HEADLESS|RTH
## ESKY - *16*
CH1|CH2|CH3|CH4|CH5|CH6
@@ -1567,15 +1601,21 @@ A|E|T|R|FMODE|AUX6|AUX7
FMODE and AUX7 have 4 positions: -100%..-50%=>0, -50%..5%=>1, 5%..50%=>2, 50%..100%=>3
## FX816 - *58*
Model: FEI XIONG FX816 P38
Only 8 TX IDs available
## FX - *58*
FEI XIONG
CH1|CH2|CH3|CH4
---|---|---|---
A|-|T|-
### Sub_protocol 816 - *0*
Model: FX816 P38, B17
Only 8 TX IDs available
### Sub_protocol 620 - *1*
Model: FX620 SU35
## FY326 - *20*
### Sub_protocol FY326 - *0*
@@ -1608,7 +1648,7 @@ A|E|T|R|FLIP
Autobind protocol
### Sub_protocol H8_3D - *0*
Models: EAchine H8 mini 3D, JJRC H20/H22/H11D
Models: Eachine H8 mini 3D,Eachine E10, JJRC H20/H22/H11D
CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
---|---|---|---|---|---|---|---|---
@@ -1657,7 +1697,7 @@ A|E|T|R|DR|THOLD|IDLEUP|GYRO|Ttrim|Atrim|Etrim
Dual Rate: +100%=full range, Throttle Hold: +100%=hold, Idle Up: +100%=3D, GYRO: -100%=6G, +100%=3G
### Sub_protocol WLTOYS - *0*
Models: V966/V977/F959S/...
Models: V966/V977/F959S/A160 J3/...
### Sub_protocol FEILUN - *1*
@@ -1692,6 +1732,13 @@ Model: DF-Models SkyTumbler
RTH not supported
## KYOSHO2 - *93*
Model: TX KT-17, Minium Edge 540, Minium Citabria
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
## LOLI - *82*
LOLI3 receivers: https://github.com/wooddoor/Loli3
@@ -1781,7 +1828,7 @@ Model: PROPEL 74-Z Speeder Bike
Autobind protocol
Telemetry: RSSI is equal to TX_LQI which indicates how well the TX receives the RX (0-100%). A1 voltage should indicate the numbers of life remaining (not tested). A2 is giving the model status using a bit mask: 0x80=flying, 0x08=taking off, 0x04=landing, 0x00=landed/crashed
Telemetry: RSSI is equal to TX_LQI which indicates how well the TX receives the RX (0-100%). A1 (with a ratio of 25.5) voltage should indicate the numbers of life remaining 0.2->0.1->0.0(not tested). A2 (with a ratio of 25.5) is giving the model status: 12.8=flying, 0.8=taking off, 0.4=landing, 0=landed/crashed
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14
---|---|---|---|---|---|---|---|---|----|----|----|----|----
@@ -1895,7 +1942,7 @@ A|E|T|R|FLIP|LIGHT
## V761 - *48*
Gyro: -100%=Beginer mode (Gyro on, yaw and pitch rate limited), 0%=Mid Mode ( Gyro on no rate limits), +100%=Mode Expert Gyro off
Gyro: -100%=Beginner mode (Gyro on, yaw and pitch rate limited), 0%=Mid Mode ( Gyro on no rate limits), +100%=Mode Expert Gyro off
Calib: momentary switch, calib will happen one the channel goes from -100% to +100%
@@ -1904,14 +1951,21 @@ Flip: momentary switch: hold flip(+100%), indicate flip direction with Ele or Ai
RTN_ACT and RTN: -100% disable, +100% enable
### Sub_protocol 3CH - *0*
Model: Volantex V761-1, V761-3 and may be others
Models: Volantex V761-1, V761-3 and may be others
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
-|E|T|R|GYRO|CALIB|FLIP|RTN_ACT|RTN
### Sub_protocol 4CH - *1*
Model: Volantex V761-4+ and Eachine P51-D, F4U, F22 and may be others
Models: Volantex V761-4+ and Eachine P51-D, F4U, F22 and may be others
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|GYRO|CALIB|FLIP|RTN_ACT|RTN
### Sub_protocol TOPRC - *2*
Models: Top RC Hobby Spitfire, P51D, BF-109
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---

View File

@@ -115,14 +115,14 @@ Most of the older FM radios support the PPM interface.
If you are the owner of a transmitter that supports the er9X/erSky9X or OpenTX firmwares (Frsky Taranis, Horus or the FlySky TH9X or the Turnigy 9X family) you have the additional option to use a serial protocol to communicate between your Tx and the MULTI-Module. (Owners of Walkera Devo transmitters should look at the [Deviation Tx](http://www.deviationtx.com) project for how to achieve the same end goal). This serial protocol does not require any hardware modifications, but will likely require updating the firmware on your radio. For those willing to do this, there are some nice advantages:
- The model protocol selection, associated parameters, failsafe and binding is done from the Model Settings menu on the Tx
- For telemetry capable transmitters, the telemetry integration is done seamlessly with the Tx firmware. (Note that FrSky TH9X/Turnigy 9X/R transmitters require a telemetry mod to be done before telemetry can work). Click on the link corressponding to your Tx on the [Transmitters](docs/Transmitters.md) page for more details.
- For telemetry capable transmitters, the telemetry integration is done seamlessly with the Tx firmware. (Note that FrSky TH9X/Turnigy 9X/R transmitters require a telemetry mod to be done before telemetry can work). Click on the link corresponding to your Tx on the [Transmitters](docs/Transmitters.md) page for more details.
# How to get started?
1. Browse the [Protocols](Protocols_Details.md) page to see which protocols you would like on your module
1. Go to the [Hardware Options](docs/Hardware.md) page to decide which of the MULTI-Module hardware options appeals to you and which RF modules you plan to integrate
1. Once you have your module, you should review what jumper settings or modifications are required to the module to support serial communication and possibly telemetry
1. Go to [Compiling and Programming](docs/Compiling.md) page to download, compile and program your MULTI-Module
1. Finally, you should visit the setup page for your transmitter by clicking on the link corressponding to your Tx on the [Transmitters](docs/Transmitters.md) page to configure the last few settings before you can fly to your hearts content!!!!!
1. Finally, you should visit the setup page for your transmitter by clicking on the link corresponding to your Tx on the [Transmitters](docs/Transmitters.md) page to configure the last few settings before you can fly to your hearts content!!!!!
# Troubleshooting
Visit the [Troubleshooting](docs/Troubleshooting.md) page. Please bear in mind that the MULTI-Module is a complex system of hardware and software and it may take some patience to get it up and running. Also remember that the developers of the system are actual users of the system. This means that at any moment in time the system is working perfectly for them. A corollary to this is that if you are struggling there are likely two scenarios. First, that the problem is with your hardware or with your configuration, second, and much more unlikely but not impossible scenario, is that you are struggling with a new undiscovered bug. (The author of this documentation speaks from experience ;-) Please check the RC Groups forum and search for keywords relating to your problem before posting a reply. When you do post a reply please so humbly and respectfully you will find many helpful people there. In your reply please include as much relevant information as possible and attach compilation output and ```_Config.h``` files as text attachments to keep the forum clean.

View File

@@ -9,11 +9,11 @@ getMultiVersion() {
}
getAllRFModules() {
if [[ "$BOARD" =~ "multi4in1:avr:multixmega32d4" ]]; then
if [[ "$BOARD" =~ ":avr:multixmega32d4" ]]; then
ALL_RFMODULES=$(echo CYRF6936_INSTALLED);
elif [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:" ]]; then
elif [[ "$BOARD" =~ ":avr:multiatmega328p:" ]]; then
ALL_RFMODULES=$(echo A7105_INSTALLED CYRF6936_INSTALLED CC2500_INSTALLED NRF24L01_INSTALLED);
elif [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
elif [[ "$BOARD" =~ ":STM32F1:" ]]; then
ALL_RFMODULES=$(echo A7105_INSTALLED CYRF6936_INSTALLED CC2500_INSTALLED NRF24L01_INSTALLED SX1276_INSTALLED);
fi
}
@@ -26,11 +26,11 @@ getAllProtocols() {
CCNRF_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_CCNRF_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
SX1276_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_SX1276_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
if [[ "$BOARD" =~ "multi4in1:avr:multixmega32d4" ]]; then
if [[ "$BOARD" =~ ":avr:multixmega32d4" ]]; then
ALL_PROTOCOLS=$(echo $CYRF6936_PROTOCOLS);
elif [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:" ]]; then
elif [[ "$BOARD" =~ ":avr:multiatmega328p:" ]]; then
ALL_PROTOCOLS=$(echo $A7105_PROTOCOLS $CC2500_PROTOCOLS $CYRF6936_PROTOCOLS $NRF24L01_PROTOCOLS $CCNRF_PROTOCOLS);
elif [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
elif [[ "$BOARD" =~ ":STM32F1:" ]]; then
ALL_PROTOCOLS=$(echo $A7105_PROTOCOLS $CC2500_PROTOCOLS $CYRF6936_PROTOCOLS $NRF24L01_PROTOCOLS $CCNRF_PROTOCOLS $SX1276_PROTOCOLS);
fi
}
@@ -84,21 +84,21 @@ buildEachRFModule() {
}
buildReleaseFiles(){
if [[ "$BOARD" == "multi4in1:avr:multixmega32d4" ]]; then
if [[ "$BOARD" =~ ":avr:multixmega32d4" ]]; then
build_release_orx;
elif [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=none" ]]; then
elif [[ "$BOARD" =~ ":avr:multiatmega328p:bootloader=none" ]]; then
build_release_avr_noboot;
elif [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=optiboot" ]]; then
elif [[ "$BOARD" =~ ":avr:multiatmega328p:bootloader=optiboot" ]]; then
build_release_avr_optiboot;
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=none" ]]; then
elif [[ "$BOARD" =~ ":STM32F1:multistm32f103cb:debug_option=none" ]]; then
build_release_stm32f1_no_debug;
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=native" ]]; then
elif [[ "$BOARD" =~ ":STM32F1:multistm32f103cb:debug_option=native" ]]; then
build_release_stm32f1_native_debug;
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi" ]]; then
elif [[ "$BOARD" =~ ":STM32F1:multistm32f103cb:debug_option=ftdi" ]]; then
build_release_stm32f1_serial_debug;
elif [[ "$BOARD" == "multi4in1:STM32F1:multi5in1t18int" ]]; then
elif [[ "$BOARD" =~ ":STM32F1:multi5in1t18int" ]]; then
build_release_stm32f1_t18int;
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c8:debug_option=none" ]]; then
elif [[ "$BOARD" =~ ":STM32F1:multistm32f103c8:debug_option=none" ]]; then
build_release_stm32f1_64k;
else
printf "No release files for this board.";

View File

@@ -30,7 +30,7 @@ These are examples of the well-known ready-made Multiprotocol modules. Inclusio
| **iRangeX IRX4 STM32** | <img src="images/irx4.jpg" width="200"/> | [STM32F103C](Compiling_STM32.md "Firmware compiling and uploading instructions for STM32") | US$39 | <ul><li>Includes case</li><li>Serial mode only</li></ul> | [Banggood](https://www.banggood.com/IRangeX-IRX4-2_4G-CC2500-NRF24L01-A7105-CTRF6936-4-IN-1-Multiprotocol-STM32-TX-Module-With-Case-p-1197130.html) |
| **iRangeX IRX4 Plus STM32** | <img src="images/irx4-plus.jpg" width="200"/> | [STM32F103C](Compiling_STM32.md "Firmware compiling and uploading instructions for STM32") | US$37 | <ul><li>Includes case</li><li>Has USB port and LED</li><li>Serial and PPM</li></ul> | [Banggood](https://www.banggood.com/IRangeX-IRX4-Plus-2_4G-CC2500-NRF24L01-A7105-CYRF6936-4-IN-1-Multiprotocol-STM32-TX-Module-With-Case-p-1225080.html) |
| **Jumper JP4IN1 Multi Protocol Transmitter Module** | <img src="images/jp4in1.jpg" width="200"/> | [STM32F103](Compiling_STM32.md "Firmware compiling and uploading instructions for STM32") | US$40 | <ul><li>Includes case</li><li>Has USB port and LED</li><li>Serial and PPM</li></ul> | [Hobbyking](https://hobbyking.com/en_us/jumper-jp4in1-multi-protocal-radio-transmitter-module.html) |
| **Vantac MPM Lite 2.4G Transmitter Module for X-Lite** | <img src="images/mpm1n.jpg" width="200" /> | [STM32F103C](Compiling_STM32.md "Firmware compiling and uploading instructions for STM32") | $49 | <ul><li>Specially for Frsky X-Lite (not JR bay compatible)</li><li>USB Bootloader preflashed</li><li>Has USB and LED</li></ul> | [Banggood](https://www.banggood.com/Vantac-MPM-Lite-2_4G-Multiple-Protocol-TX-Module-for-Taranis-X-Lite-Radio-Transmitter-p-1307645.html?p=RN27072889497201510A) [HorusRC](https://www.horusrc.com/en/vantac-mpm-lite-2-4g-transmitter-module-for-x-lite.html?acc=9860) |
| **Vantac MPM Lite 2.4G Transmitter Module for X-Lite** | <img src="images/mpm1n.jpg" width="200" /> | [STM32F103C](Compiling_STM32.md "Firmware compiling and uploading instructions for STM32") | $49 | <ul><li>**64KB flash only, you need to compile the firmware on your own and select only the protocols you need to fit in the space.**</li><li>Specially for Frsky X-Lite (not JR bay compatible)</li><li>USB Bootloader preflashed</li><li>Has USB and LED</li></ul> | [Banggood](https://www.banggood.com/Vantac-MPM-Lite-2_4G-Multiple-Protocol-TX-Module-for-Taranis-X-Lite-Radio-Transmitter-p-1307645.html?p=RN27072889497201510A) [HorusRC](https://www.horusrc.com/en/vantac-mpm-lite-2-4g-transmitter-module-for-x-lite.html?acc=9860) |
*Table last updated June 24th, 2018*