Compare commits

...

46 Commits

Author SHA1 Message Date
Frankie Arzu
fcc4d19430 Frankie dsm fwrd prg enhancements (#755)
* #751 DSM Enhancements

 #751 DSM Forward Programming Enhancements (New GUI, etc)

* Make both work on EdgeTx and OpenTX

* #751 Turn OFF simulation by default

Distribution code with RX simulation OFF
Simulation should be only for Development

* #751 Update Readme Documentation

Updated the Readme.txt documentation
and removed compiled luac file that was check in by mistake

Co-authored-by: pascallanger <pascal_langer@yahoo.fr>
2022-11-17 17:50:36 +01:00
richardclli
c80f705fa2 Added MPM for Flysky PL18 PCB and casing design. (#754) 2022-11-17 11:37:11 +01:00
pascallanger
c95db35b41 Update Protocols_Details.md 2022-11-17 10:58:38 +01:00
pascallanger
35f3548992 Compilation option 2022-11-17 10:29:53 +01:00
pascallanger
58f6716035 Update README.md 2022-11-17 09:49:30 +01:00
pascallanger
2b15de0f90 Update README.md 2022-11-17 09:47:22 +01:00
pascallanger
be91409df9 Delete DSM FwdPrg.lua 2022-11-17 09:44:18 +01:00
Frankie Arzu
4d8e440965 Frankie dsm fwrd prg enhancements (#753)
DSM Forward Programming Enhancements (New GUI for Color+Touch and BW, etc). Work on EdgeTx and OpenTX.
2022-11-17 09:42:04 +01:00
pascallanger
2d469d074e Merge branch 'master' of https://github.com/pascallanger/DIY-Multiprotocol-TX-Module 2022-10-30 11:40:11 +01:00
pascallanger
96405d27b5 Extend Kyosho KT-17 bind time 2022-10-30 11:40:07 +01:00
yakulis
75c9fb40a7 Update DSM FwdPrg.lua (#735)
Panic Text Updates - The following strings were updated:
Text[0x00D2]="Panic Channel"
Text[0x008E]="Panic Delay"
Text[0x01FC]="Panic Flight Mode"
2022-10-12 11:35:09 +02:00
Pieter du Preez
cd1c15a45a Added documentation for using dfu-util for flashing STM32 targets. (#727)
This patch adds documentation, explaining how to flash firmware to DFU
capable multimodules.

A dfu-util command was taken and adapted from:
https://github.com/benlye/flash-multi/blob/master/doc/Troubleshooting.md

Using dfu-util is straight forward, easy and very safe.
2022-10-12 11:34:32 +02:00
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
49 changed files with 106516 additions and 1142 deletions

View File

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

View File

@@ -1,767 +0,0 @@
local toolName = "TNS|DSM Forward Programming v0.2|TNE"
---- #########################################################################
---- # #
---- # Copyright (C) OpenTX #
-----# #
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
---- # #
---- # This program is free software; you can redistribute it and/or modify #
---- # it under the terms of the GNU General Public License version 2 as #
---- # published by the Free Software Foundation. #
---- # #
---- # This program is distributed in the hope that it will be useful #
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
---- # GNU General Public License for more details. #
---- # #
---- #########################################################################
--###############################################################################
-- Multi buffer for DSM description
-- Multi_Buffer[0..2]=="DSM" -> Lua script is running
-- Multi_Buffer[3]==0x70+len -> TX to RX data ready to be sent
-- Multi_Buffer[4..9]=6 bytes of TX to RX data
-- Multi_Buffer[10..25]=16 bytes of RX to TX data
--
-- To start operation:
-- Write 0x00 at address 3
-- Write 0x00 at address 10
-- Write "DSM" at address 0..2
--###############################################################################
local RX_VERSION, WAIT_CMD, MENU_TITLE, MENU_LINES, MENU_VALUES, VALUE_CHANGING, VALUE_CHANGING_WAIT, VALUE_CHANGED, 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
local Menu = { Cur=nil, Id=nil, Title="", Prev=nil, PrevId=nil, Next=nil, NextId=nil, Back=nil, BackId=nil, CurLine=nil, SelLine=nil, EditLine=nil }
local Line = {}
local RX = { Name="", Version="" }
-- 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...
out = "Unknown_"..string.format("%X",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
multiBuffer( 3+i, arg[i])
end
multiBuffer( 3, 0x70+#arg)
end
------------------------------------------------------------------------------------------------------------
local function Value_Add(dir)
local line=Line[Menu.SelLine]
Speed = getRotEncSpeed()
if Speed == ROTENC_MIDSPEED then
line.Val = line.Val + (5 * dir)
elseif Speed == ROTENC_HIGHSPEED then
line.Val = line.Val + (15 * dir)
else
line.Val = line.Val + dir
end
if line.Val > line.Max then
line.Val = line.Max
elseif line.Val < line.Min then
line.Val = line.Min
end
if Line[Menu.SelLine].Type ~= LIST_MENU_NOCHANGING then
Phase = VALUE_CHANGING
Waiting_RX = 0
end
end
------------------------------------------------------------------------------------------------------------
local function DSM_Menu(event)
local Speed = 0
if event == EVT_VIRTUAL_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 and Line[i].Type ~= VALUE_NOCHANGING then
Menu.SelLine=i
break
end
end
if num == Menu.SelLine then
if Menu.Next ~= 0 then -- Next
Menu.SelLine = 7
elseif Menu.Prev ~= 0 then -- Prev
Menu.SelLine = 8
end
end
elseif Menu.Prev ~= 0 then -- Prev
Menu.SelLine = 8
end
end
else -- need to inc the value
Value_Add(1)
end
elseif event == EVT_VIRTUAL_PREV then
if Menu.EditLine == nil then
if Menu.SelLine ~= nil then
if Menu.SelLine == 8 and Menu.Next ~= 0 then
Menu.SelLine = 7
elseif Menu.SelLine > 0 then
if Menu.SelLine > 6 then
Menu.SelLine = 7
end
local num = Menu.SelLine
for i = Menu.SelLine-1, 0, -1 do
if Line[i].Type ~= nil and Line[i].Next ~= nil and Line[i].Type ~= VALUE_NOCHANGING then
Menu.SelLine=i
break
end
end
if num == Menu.SelLine then -- Back
Menu.SelLine = -1
end
else
Menu.SelLine = -1 -- Back
end
end
else -- need to dec the value
Value_Add(-1)
end
elseif event == EVT_VIRTUAL_ENTER_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
Menu.Id = Menu.BackId
Menu.SelLine = 0
Phase = MENU_TITLE
Waiting_RX = 0
elseif Menu.SelLine == 7 then -- Next
Menu.Cur = Menu.Next
Menu.Id = Menu.NextId
Menu.SelLine = 0
Phase = MENU_TITLE
Waiting_RX = 0
elseif Menu.SelLine == 8 then -- Prev
Menu.Cur = Menu.Prev
Menu.Id = Menu.PrevId
Menu.SelLine = 0
Phase = MENU_TITLE
Waiting_RX = 0
elseif Menu.SelLine ~= nil and Line[Menu.SelLine].Next ~= nil then
if Line[Menu.SelLine].Type == MENU then -- Next menu exist
Menu.Cur = Line[Menu.SelLine].Next
Menu.Id = Line[Menu.SelLine].NextId
Phase = MENU_TITLE
Waiting_RX = 0
else
-- value entry
if Menu.EditLine == Menu.SelLine then
Menu.EditLine = nil
Value_Changed = 0
Phase = VALUE_CHANGED
Waiting_RX = 0
else
Menu.EditLine = Menu.SelLine
end
end
end
end
end
------------------------------------------------------------------------------------------------------------
local function DSM_Send_Receive()
if Waiting_RX == 0 then
Waiting_RX = 1
-- Need to send a request
if Phase == RX_VERSION then -- request RX version
DSM_Send(0x11,0x06,0x00,0x14,0x00,0x00)
elseif Phase == WAIT_CMD then -- keep connection open
DSM_Send(0x00,0x04,0x00,0x00)
elseif Phase == MENU_TITLE then -- request menu title
if Menu.Cur == nil then
DSM_Send(0x12,0x06,0x00,0x14,0x00,0x00) -- first menu only
Menu.Cur = 0
else
DSM_Send(0x16,0x06,Menu.Id,Menu.Cur,0x00,Menu.SelLine)
end
elseif Phase == MENU_LINES then -- request menu lines
if Menu.CurLine == nil then
DSM_Send(0x13,0x04,Menu.Id,Menu.Cur) -- line 0
elseif Menu.CurLine >= 0x80 then
local last_byte={0x40,0x01,0x02,0x04,0x00,0x00} -- unknown...
DSM_Send(0x20,0x06,Menu.CurLine-0x80,Menu.CurLine-0x80,0x00,last_byte[Menu.CurLine-0x80+1]) -- line X
else
DSM_Send(0x14,0x06,Menu.Id,Menu.Cur,0x00,Menu.CurLine) -- line X
end
elseif Phase == MENU_VALUES then -- request menu values
DSM_Send(0x15,0x06,Menu.Id,Menu.Cur,Line[Menu.CurLine].ValId,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,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
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,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,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,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
-- 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
--ex: 0x09 0x02 0x4F 0x10 0xA5 0x00 0x00 0x00 0x50 0x10 0x10 0x10 0x00 0x00 0x00 0x00
Menu.Cur = multiBuffer(12)
Menu.Id = multiBuffer(13)
Menu.Title = Get_Text(multiBuffer(14)+multiBuffer(15)*256)
Menu.Prev = multiBuffer(16)
Menu.PrevId = multiBuffer(17)
Menu.Next = multiBuffer(18)
Menu.NextId = multiBuffer(19)
Menu.Back = multiBuffer(20)
Menu.BackId = multiBuffer(21)
for i = 0, 6 do -- clear menu
Line[i] = { Menu = nil, Id = nil, Type = nil, Text="", Next = nil, NextId = nil, ValLine = nil, ValId = nil, Min, Max, Def, Val, Unit, Step }
end
Menu.CurLine = nil
if Menu.Next ~= 0 then
Menu.SelLine = 7 -- highlight Next
else
Menu.SelLine = -1 -- highlight Back
end
Blink = 0
Phase = MENU_LINES
elseif multiBuffer(11) == 0x03 then -- read menu lines
--ex: 0x09 0x03 0x00 0x10 0x00 0x1C 0xF9 0x00 0x10 0x10 0x00 0x00 0x00 0x00 0x03 0x00
-- Menu Id line Type Text_idx Next V_Id Val_Min Val_Max Val_Def
--ex: 0x09 0x03 0x61 0x10 0x00 0x6C 0x50 0x00 0x00 0x10 0x36 0x00 0x49 0x00 0x36 0x00
Menu.CurLine = multiBuffer(14)
local line = Line[Menu.CurLine]
line.Menu = multiBuffer(12)
line.Id = multiBuffer(13) -- not quite sure yet
line.Type = multiBuffer(15) -- not quite sure yet: 1C is text menu only, 4C/6C is text followed by text list, C0 is text followed by percentage value, 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=>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
line.NextId = multiBuffer(19) -- not quite sure yet
line.ValLine = multiBuffer(18) -- not quite sure yet
line.ValId = multiBuffer(19) -- not quite sure yet
line.Min = conv_int16(multiBuffer(20)+multiBuffer(21)*256)
line.Max = conv_int16(multiBuffer(22)+multiBuffer(23)*256)
line.Def = conv_int16(multiBuffer(24)+multiBuffer(25)*256)
if line.Type == MENU then
-- nothing to do on menu entries
elseif line.Type == LIST_MENU_NOCHANGING or line.Type == LIST_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
line.Min = 0 -- min index
else -- default to numerical value
line.Val = nil --line.Def -- use default value not sure if needed
end
if line.Type ~= 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
--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
-- 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...
Menu.CurLine = 0x80 + multiBuffer(12)
Phase = MENU_LINES
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
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)
--Draw RX Menu
if Phase == RX_VERSION then
lcd.drawText(10,50,"No compatible DSM RX...", BLINK)
else
if Menu.Title ~= nil then
local attrib=0;
lcd.drawText(80,32,Menu.Title,MIDSIZE)
for i = 0, 6 do
if i == Menu.SelLine then
attrib = INVERS
else
attrib = 0
end
if Line[i] ~= nil and Line[i].Type ~= nil then
if Line[i].Type ~= MENU then -- list/value
if Line[i].Val ~= nil then
local text=""
if Line[i].Type == LIST_MENU_NOCHANGING or Line[i].Type == LIST_MENU1 or Line[i].Type == LIST_MENU2 then
text = Get_Text(Line[i].Val+Line[i].Def)
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 .." T="..Line[i].Type -- used for debug
text = Line[i].Val
end
if Menu.EditLine == Menu.SelLine then -- blink edited entry
Blink = Blink + 1
if Blink > 25 then
attrib = 0
if Blink > 50 then
Blink = 0
end
end
end
lcd.drawText(240,32+20*(i+2), text, attrib) -- display value
end
attrib = 0
end
lcd.drawText(10,32+20*(i+2), Line[i].Text, attrib) -- display text
end
end
if Menu.SelLine == -1 then
lcd.drawText(437,32, "Back", INVERS)
else
lcd.drawText(437,32, "Back", 0)
end
lcd.drawRectangle(437-5, 32-2, 47, 25)
if Menu.Next ~= 0 then
if Menu.SelLine == 7 then
lcd.drawText(437,220, "Next",INVERS)
else
lcd.drawText(437,220, "Next")
end
lcd.drawRectangle(437-5, 220-2, 47, 25)
end
if Menu.Prev ~= 0 then
if Menu.SelLine == 8 then
lcd.drawText(5,220, "Prev",INVERS)
else
lcd.drawText(5,220, "Prev")
end
lcd.drawRectangle(5-5, 220-2, 47, 25)
end
end
lcd.drawText(170,252, "RX "..RX.Name.." v"..RX.Version) -- display RX info
end
else
-- --Draw RX Menu on LCD_W=128
-- if multiBuffer( 4 ) == 0xFF then
-- lcd.drawText(2,17,"No compatible DSM RX...",SMLSIZE)
-- else
-- if Retry_128 ~= 0 then
-- --Intro page
-- Retry_128 = Retry_128 - 1
-- lcd.drawScreenTitle("DSM Forward Programming",0,0)
-- lcd.drawText(2,17,"Press Prev Page for previous Menu" ,SMLSIZE)
-- else
-- --Menu page
-- for line = 0, 7, 1 do
-- for i = 0, 21-1, 1 do
-- value=multiBuffer( line*21+6+i )
-- if value > 0x80 then
-- value = value - 0x80
-- lcd.drawText(2+i*6,1+8*line,string.char(value).." ",SMLSIZE+INVERS)
-- else
-- lcd.drawText(2+i*6,1+8*line,string.char(value),SMLSIZE)
-- end
-- end
-- end
-- end
-- end
end
end
------------------------------------------------------------------------------------------------------------
-- Init
local function DSM_Init()
--Set protocol to talk to
multiBuffer( 0, string.byte('D') )
--test if value has been written
if multiBuffer( 0 ) ~= string.byte('D') then
error("Not enough memory!")
return 2
end
--Init TX buffer
multiBuffer( 3, 0x00 )
--Init RX buffer
multiBuffer( 10, 0x00 )
--Init telemetry
multiBuffer( 0, string.byte('D') )
multiBuffer( 1, string.byte('S') )
multiBuffer( 2, string.byte('M') )
--RX names--
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]="On"
Text[0x0002]="Off"
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"
Text[0x0039]="Rudder"
Text[0x003A]="Gear"
--******
--This part is strange since the AR637T needs
for i=1,7 do -- 3B..41
Text[0x003A+i]="Aux"..i
end
for i=1,8 do -- 41..49
Text[0x0041+i]="XPlus-"..i
end
--But FOTO-PETE reports that it should be:
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"
Text[0x0050]="Outputs"
Text[0x0051]="Output Channel 1"
Text[0x0052]="Output Channel 2"
Text[0x0053]="Output Channel 3"
Text[0x0054]="Output Channel 4"
Text[0x0055]="Output Channel 5"
Text[0x0056]="Output Channel 6"
--Text[0x005E]="Inhibit"
Text[0x005F]="Hold Last"
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[0x00B5]="Inhibit"
Text[0x00B6]="FM1"
Text[0x00B7]="FM2"
Text[0x00B8]="FM3"
Text[0x00B9]="FM4"
Text[0x00BA]="FM5"
Text[0x00BB]="FM6"
Text[0x00BC]="FM7"
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[0x0106]="Any wing type, channel assignment,"
Text[0x0107]="subtrim, or servo reversing changes"
Text[0x0108]="require running through initial"
Text[0x0109]="setup again."
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[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]="" -- 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[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]="" -- empty??
Text[0x0231]="This will overwrite the"
Text[0x0232]="backup memory with your"
Text[0x0233]="current configuartion."
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]="" -- 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
else
DSM_Menu(event)
DSM_Send_Receive()
DSM_Display()
end
if Phase == EXIT_DONE then
return 2
else
return 0
end
end
return { init=DSM_Init, run=DSM_Run }

View File

@@ -0,0 +1,439 @@
local toolName = "TNS|DSM Forward Prog v0.5 (Text B&W) |TNE"
---- #########################################################################
---- # #
---- # Copyright (C) OpenTX #
-----# #
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
---- # #
---- # This program is free software; you can redistribute it and/or modify #
---- # it under the terms of the GNU General Public License version 2 as #
---- # published by the Free Software Foundation. #
---- # #
---- # This program is distributed in the hope that it will be useful #
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
---- # GNU General Public License for more details. #
---- # #
---- #########################################################################
local SIMULATION_ON = false -- FALSE: use real communication to DSM RX (DEFAULT), TRUE: use a simulated version of RX
local DEBUG_ON = 1 -- 0=NO DEBUG, 1=HIGH LEVEL 2=LOW LEVEL (Debug logged into the /LOGS/dsm.log)
local DEBUG_ON_LCD = false -- Interactive Information on LCD of Menu data from RX
local dsmLib
if (SIMULATION_ON) then
-- library with SIMILATION VERSION. Works really well in Companion for GUI development
dsmLib = loadScript("/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgSIMLib.lua")(DEBUG_ON)
else
dsmLib = loadScript("/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgLib.lua")(DEBUG_ON)
end
local PHASE = dsmLib.PHASE
local LINE_TYPE = dsmLib.LINE_TYPE
local DISP_ATTR = dsmLib.DISP_ATTR
local DSM_Context = dsmLib.DSM_Context
local LCD_W_USABLE = LCD_W-10
-- X for Menu Lines
local LCD_X_LINE_MENU = 10
-- X offsets for (Title: [Value] debugInfo) lines
local LCD_X_LINE_TITLE = 10
local LCD_X_LINE_VALUE = 230
local LCD_X_LINE_DEBUG = 390
-- Line Height: make it smaller debugging info tp LCD (some space buttom)
local LCD_Y_LINE_HEIGHT = (DEBUG_ON_LCD and 23) or 27 -- if DEBUG 23 else 27
-- Y offsets
local LCD_Y_MENU_TITLE = 20
-- Y offet
local LCD_Y_LINE_FIRST = LCD_Y_MENU_TITLE + 30
local LCD_Y_LOWER_BUTTONS = LCD_Y_LINE_FIRST + 7 * LCD_Y_LINE_HEIGHT
local LCD_W_BUTTONS = 47
local LCD_H_BUTTONS = 25
local LCD_X_RIGHT_BUTTONS = LCD_W - LCD_W_BUTTONS - 5
local TEXT_SIZE = 0 -- NORMAL
local lastRefresh=0 -- Last time the screen was refreshed
local REFRESH_GUI_MS = 500/10 -- 500ms.. Screen Refresh Rate.. to not use unneded CPU time (in 10ms units to be compatible with getTime())
local originalValue = nil
------------------------------------------------------------------------------------------------------------
local function GUI_SwitchSimulationOFF()
dsmLib.ReleaseConnection()
dsmLib.LOG_close()
SIMULATION_ON = false
dsmLib = loadScript("/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgLib.lua")(DEBUG_ON)
DSM_Context = dsmLib.DSM_Context
dsmLib.Init(toolName) -- Initialize Library
dsmLib.StartConnection()
DSM_Context.Refresh_Display = true
end
local function openTx_lcd_sizeText(s)
return string.len(s)*5
end
local function GUI_Diplay_Button(x,y,w,h,text,selected)
local attr = (selected) and INVERS or 0 -- INVERS if line Selected
lcd.drawText(x+5,y+2, text, attr + TEXT_SIZE)
lcd.drawRectangle(x, y, w, h, LINE_COLOR)
end
local function GUI_Display_Menu(menu)
local ctx = DSM_Context
local w= LCD_W_USABLE - LCD_W_BUTTONS - 10 -- usable Width for the Menu/Lines
-- Center Header
local tw = openTx_lcd_sizeText(menu.Text)
local x = w/2 - tw/2 -- Center of Screen - Center of Text
local bold = 0
if (TEXT_SIZE~=SMLSIZE) then -- Ignore Bold on small size screens
bold = BOLD
end
lcd.drawText(x,LCD_Y_MENU_TITLE,menu.Text,bold + TEXT_SIZE)
-- Back
if menu.BackId ~= 0 then
GUI_Diplay_Button(LCD_X_RIGHT_BUTTONS,LCD_Y_MENU_TITLE,LCD_W_BUTTONS,LCD_H_BUTTONS,"Back",ctx.SelLine == dsmLib.BACK_BUTTON)
end
-- Next ?
if menu.NextId ~= 0 then
GUI_Diplay_Button(LCD_X_RIGHT_BUTTONS,LCD_Y_LOWER_BUTTONS,LCD_W_BUTTONS,LCD_H_BUTTONS,"Next",ctx.SelLine == dsmLib.NEXT_BUTTON)
end
-- Prev?
if menu.PrevId ~= 0 then
GUI_Diplay_Button(0,LCD_Y_LOWER_BUTTONS,LCD_W_BUTTONS,LCD_H_BUTTONS,"Prev",ctx.SelLine == dsmLib.PREV_BUTTON)
end
-- Debug into LCD
if (DEBUG_ON_LCD) then lcd.drawText(0,LCD_Y_MENU_TITLE,dsmLib.phase2String(ctx.Phase),TEXT_SIZE + WARNING_COLOR) end -- Phase we are in
if (DEBUG_ON_LCD) then lcd.drawText(LCD_X_LINE_MENU,240,dsmLib.menu2String(menu),TEXT_SIZE + WARNING_COLOR) end -- Menu Info
end
local function GUI_Display_Line_Menu(x,y,w,h,line,selected)
local attr = (selected and INVERS) or 0 -- INVERS if line Selected
local bold = 0
local text = line.Text
if dsmLib.isSelectableLine(line) then
-- Menu Line
text = text .. " |>" --OPENTX
else -- SubHeaders and plain text lines
if (TEXT_SIZE~=SMLSIZE) then -- ignore bold on small size screens
bold = (dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.BOLD) and BOLD) or 0
end
if dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.RIGHT) then -- Right Align???
local tw = openTx_lcd_sizeText(line.Text)+4
x = LCD_X_LINE_VALUE - tw -- Right
elseif dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.CENTER) then -- Center??
local tw = openTx_lcd_sizeText(line.Text)
x = x + (LCD_X_LINE_VALUE - LCD_X_LINE_MENU)/2 - tw/2 -- Center - 1/2 Text
end
end
lcd.drawText(x,y, text, attr + bold + TEXT_SIZE)
end
------------------------------------------------------------------------------------------------------------
local function GUI_Display_Line_Value(lineNum, line, value, selected, editing)
local bold = 0
local y = LCD_Y_LINE_FIRST+(LCD_Y_LINE_HEIGHT*lineNum)
local x = LCD_X_LINE_TITLE
---------- NAME Part
local header = line.Text
-- ONLY do this for Flight Mode (Right Align or Centered)
if (dsmLib.isFlightModeText(line.TextId)) then
-- Display Header + Value together
header = header .. " " .. value
-- Flight mode display attributes
if (TEXT_SIZE~=SMLSIZE) then -- ignore bold on small size screens
bold = (dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.BOLD) and BOLD) or 0
end
if dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.RIGHT) then -- Right Align
local tw = openTx_lcd_sizeText(header)+4
x = LCD_X_LINE_VALUE - tw -- Right
elseif dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.CENTER) then -- Centered
local tw = openTx_lcd_sizeText(header)
x = x + (LCD_X_LINE_VALUE - LCD_X_LINE_TITLE)/2 - tw/2 -- Center - 1/2 Text
end
else
-- No Flight Mode, no effects here
header = header .. ":"
end
lcd.drawText(x, y, header, bold + TEXT_SIZE) -- display Line Header
--------- VALUE PART, Skip for Flight Mode since already show the value
if not dsmLib.isFlightModeText(line.TextId) then
local attrib = 0
value = value .. (line.Format or "") -- Append % if needed
if selected then
attrib = INVERS
if editing then -- blink editing entry
attrib = attrib + BLINK
value = "[ " .. value .. " ]"
end
end
lcd.drawText(LCD_X_LINE_VALUE,y, value, attrib + TEXT_SIZE) -- display value
end
if (DEBUG_ON_LCD) then lcd.drawText(LCD_X_LINE_DEBUG,y, line.MinMaxDebug or "", TEXT_SIZE + WARNING_COLOR) end -- display debug
end
------------------------------------------------------------------------------------------------------------
local function GUI_Display()
local ctx = DSM_Context
lcd.clear()
local header = "DSM Fwrd Programming "
if ctx.Phase ~= PHASE.RX_VERSION then
header = header .. "RX "..ctx.RX.Name.." v"..ctx.RX.Version
end
--Draw title
if (TEXT_SIZE~=SMLSIZE) then -- ignore tool title small size screens
lcd.drawFilledRectangle(0, 0, LCD_W, 20, TITLE_BGCOLOR)
lcd.drawText(5, 0, header, MENU_TITLE_COLOR + TEXT_SIZE)
end
--Draw RX Menu
if ctx.Phase == PHASE.RX_VERSION then
lcd.drawText(LCD_X_LINE_TITLE,50,"No compatible DSM RX...", BLINK + TEXT_SIZE)
else
local menu = ctx.Menu
if menu.Text ~= nil then
GUI_Display_Menu(menu)
for i = 0, dsmLib.MAX_MENU_LINES do
local line = ctx.MenuLines[i]
if i == ctx.SelLine then
-- DEBUG: Display Selected Line info for ON SCREEN Debugging
if (DEBUG_ON_LCD) then lcd.drawText(LCD_X_LINE_TITLE,255,dsmLib.menuLine2String(line),TEXT_SIZE + WARNING_COLOR) end
end
if line ~= nil and line.Type ~= 0 then
if line.Type == LINE_TYPE.MENU then
-- Menu Line
GUI_Display_Line_Menu(LCD_X_LINE_MENU,LCD_Y_LINE_FIRST+(LCD_Y_LINE_HEIGHT*i), 350, LCD_Y_LINE_HEIGHT, line, i == ctx.SelLine)
else
-- list/value line
local value = line.Val
if line.Val ~= nil then
if dsmLib.isListLine(line) then -- for Lists of Strings, get the text
value = dsmLib.Get_Text(line.Val + line.TextStart) -- TextStart is the initial offset for text
local imgValue = dsmLib.Get_Text_Img(line.Val + line.TextStart) -- Complentary IMAGE for this value to Display??
if (imgValue) then -- Optional Image for a Value
--TODO: Pending feature.. create images and put bitmap instead of a message
--Display the image/Alternate Text
lcd.drawText(LCD_X_LINE_TITLE, LCD_Y_LINE_FIRST+LCD_Y_LINE_HEIGHT, "Img:"..imgValue)
end
end
GUI_Display_Line_Value(i, line, value, i == ctx.SelLine, i == ctx.EditLine)
end
end -- if ~MENU
end -- if Line[i]~=nil
end -- for
end
end
end
-------------------------------------------------------------------------------------------------------------
local function GUI_RotEncVal(dir) -- return encoder speed to inc or dec values
local inc = 0
local Speed = getRotEncSpeed()
if Speed == ROTENC_MIDSPEED then
inc = (5 * dir)
elseif Speed == ROTENC_HIGHSPEED then
inc = (15 * dir)
else
inc = dir
end
return inc
end
------------------------------------------------------------------------------------------------------------
local function GUI_HandleEvent(event, touchState)
local ctx = DSM_Context
local menu = ctx.Menu
local menuLines = ctx.MenuLines
if event == EVT_VIRTUAL_EXIT then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_EXIT\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.Phase == PHASE.RX_VERSION then
dsmLib.ReleaseConnection()
else
if ctx.isEditing() then -- Editing a Line, need to restore original value
ctx.MenuLines[ctx.EditLine].Val = originalValue
dsmLib.ChangePhase(PHASE.VALUE_CHANGE_END) -- Update+Validate value in RX
ctx.EditLine = nil -- Exit Edit Mode (By clearing the line editing)
else
dsmLib.ChangePhase(PHASE.EXIT)
end
end
return
end
if event == EVT_VIRTUAL_NEXT then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_NEXT\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.isEditing() then -- Editing a Line, need to inc the value
local line=ctx.MenuLines[ctx.EditLine]
dsmLib.Value_Add(line, GUI_RotEncVal(1))
else -- not editing, move selected line to NEXT
dsmLib.MoveSelectionLine(1)
end
return
end
if event == EVT_VIRTUAL_PREV then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_PREV\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.isEditing() then -- Editiing a line, need to dec the value
local line=ctx.MenuLines[ctx.EditLine]
dsmLib.Value_Add(line, GUI_RotEncVal(-1))
else -- not editing, move selected line to PREV
dsmLib.MoveSelectionLine(-1)
end
return
end
if event == EVT_VIRTUAL_ENTER_LONG then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_ENTER_LONG\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.isEditing() then
-- reset the value to default
dsmLib.Value_Default( menuLines[ctx.EditLine]) -- Update RX value as needed
end
return
end
if event == EVT_VIRTUAL_ENTER then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_ENTER\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.SelLine == dsmLib.BACK_BUTTON then -- Back
dsmLib.GotoMenu(menu.BackId)
elseif ctx.SelLine == dsmLib.NEXT_BUTTON then -- Next
dsmLib.GotoMenu(menu.NextId)
elseif ctx.SelLine == dsmLib.PREV_BUTTON then -- Prev
dsmLib.GotoMenu(menu.PrevId)
elseif menuLines[ctx.SelLine].ValId ~= 0 then
if menuLines[ctx.SelLine].Type == LINE_TYPE.MENU then -- Next menu exist
if (SIMULATION_ON and menuLines[ctx.SelLine].ValId==0xFFFF) then
-- SPECIAL Simulation menu to Exit Simulation and
-- comunicate with Real RX
GUI_SwitchSimulationOFF()
else
dsmLib.GotoMenu(menuLines[ctx.SelLine].ValId) -- ValId is the MenuId to navigate to
end
else
-- Editing a Line????
if ctx.isEditing() then
-- Change the Value and exit edit
ctx.EditLine = nil
dsmLib.ChangePhase(PHASE.VALUE_CHANGE_END)
else
-- enter Edit the current line
ctx.EditLine = ctx.SelLine
originalValue = menuLines[ctx.SelLine].Val
end
end
end
end
end
local function init_screen_pos()
if LCD_W == 480 then -- TX16
-- use defaults in the script header
elseif LCD_W == 128 then --TX12 (128x64) -- Still needs some work on the vertical
DEBUG_ON_LCD = false -- no space for this
TEXT_SIZE = SMLSIZE
LCD_W_USABLE = 128
LCD_W_BUTTONS = 30
LCD_H_BUTTONS = 17
LCD_X_RIGHT_BUTTONS = 128 - LCD_W_BUTTONS - 5
LCD_X_LINE_MENU = 0
-- X offsets for (Title: [Value] debugInfo) lines
LCD_X_LINE_TITLE = 0
LCD_X_LINE_VALUE = 90
LCD_X_LINE_DEBUG = 110
LCD_Y_LINE_HEIGHT = 17
LCD_Y_MENU_TITLE = 0
LCD_Y_LINE_FIRST = LCD_Y_MENU_TITLE + 17
LCD_Y_LOWER_BUTTONS = LCD_Y_LINE_FIRST + 7 * LCD_Y_LINE_HEIGHT
end
end
------------------------------------------------------------------------------------------------------------
-- Init
local function DSM_Init()
init_screen_pos()
dsmLib.Init(toolName) -- Initialize Library
return dsmLib.StartConnection()
end
------------------------------------------------------------------------------------------------------------
-- Main
local function DSM_Run(event)
local ctx = DSM_Context
if event == nil then
error("Cannot be run as a model script!")
dsmLib.LOG_close()
return 2
end
GUI_HandleEvent(event)
dsmLib.Send_Receive() -- Handle Send and Receive DSM Forward Programming Messages
local refreshInterval = REFRESH_GUI_MS
-- When using LCD BLINK attribute, we need faster refresh for BLINK to SHOW on LCD
if (ctx.EditLine or (ctx.Phase == PHASE.RX_VERSION)) then -- Editing or Requesting RX Version?
ctx.Refresh_Display=true
refreshInterval = 20 -- 200ms
end
-- Refresh display only if needed and no faster than 500ms, utilize more CPU to speedup DSM communications
if (ctx.Refresh_Display and (getTime()-lastRefresh) > refreshInterval) then --300ms from last refresh
GUI_Display()
ctx.Refresh_Display=false
lastRefresh=getTime()
end
if ctx.Phase == PHASE.EXIT_DONE then
dsmLib.LOG_close()
return 2
else
return 0
end
end
return { init=DSM_Init, run=DSM_Run }

View File

@@ -0,0 +1,627 @@
local toolName = "TNS|DSM Forward Prog v0.5 (Color+Touch) |TNE"
local VERSION = "v0.5"
---- #########################################################################
---- # #
---- # Copyright (C) OpenTX #
-----# #
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
---- # #
---- # This program is free software; you can redistribute it and/or modify #
---- # it under the terms of the GNU General Public License version 2 as #
---- # published by the Free Software Foundation. #
---- # #
---- # This program is distributed in the hope that it will be useful #
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
---- # GNU General Public License for more details. #
---- # #
---- #########################################################################
local SIMULATION_ON = false -- FALSE: use real communication to DSM RX (DEFAULT), TRUE: use a simulated version of RX
local DEBUG_ON = 1 -- 0=NO DEBUG, 1=HIGH LEVEL 2=LOW LEVEL (Debug logged into the /LOGS/dsm.log)
local DEBUG_ON_LCD = false -- Interactive Information on LCD of Menu data from RX
local USE_SPECKTRUM_COLORS = true -- true: Use spectrum colors, false: use theme colors (default on OpenTX)
local dsmLib
if (SIMULATION_ON) then
-- library with SIMILATION VERSION. Works really well in Companion for GUI development
dsmLib = loadScript("/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgSIMLib.lua")(DEBUG_ON)
else
dsmLib = loadScript("/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgLib.lua")(DEBUG_ON)
end
local PHASE = dsmLib.PHASE
local LINE_TYPE = dsmLib.LINE_TYPE
local DISP_ATTR = dsmLib.DISP_ATTR
local DSM_Context = dsmLib.DSM_Context
local lastRefresh=0 -- Last time the screen was refreshed
local REFRESH_GUI_MS = 300/10 -- 300ms.. Screen Refresh Rate.. to not waste CPU time (in 10ms units to be compatible with getTime())
local originalValue = nil
local touchButtonArea = {}
local EDIT_BUTTON = { DEFAULT=1001, DEC_10=1002, DEC_1=1003, INC_1=1004, INC_10=5, OK=1006, ESC=1007 }
local IS_EDGETX = false -- DEFAULT until Init changed it
local LCD_Y_MENU_TITLE = 20
local LCD_W_MENU_TITLE = LCD_W-100
local LCD_X_LINE_MENU = 30
local LCD_W_LINE_MENU = 350
local LCD_X_LINE_TITLE = 30
local LCD_X_LINE_VALUE = 230
local LCD_X_LINE_DEBUG = 390
local LCD_Y_LINE_START = LCD_Y_MENU_TITLE + 30
local LCD_Y_LINE_HEIGHT = (DEBUG_ON_LCD and 23) or 27 -- if DEBUG 23 else 27
local LCD_Y_LOWER_BUTTONS = LCD_Y_LINE_START + 3 + (7 * LCD_Y_LINE_HEIGHT)
-- TOOL HEADER
local LCD_TOOL_HDR_COLOR = MENU_TITLE_COLOR
local LCD_TOOL_HDR_BGCOLOR = TITLE_BGCOLOR
-- MENU HEADER
local LCD_MENU_COLOR = MENU_TITLE_COLOR
local LCD_MENU_BGCOLOR = MENU_TITLE_BGCOLOR
-- LINE SELECTED
local LCD_SELECTED_COLOR = TEXT_INVERTED_COLOR
local LCD_SELECTED_BGCOLOR = TEXT_INVERTED_BGCOLOR
local LCD_EDIT_BGCOLOR = WARNING_COLOR
-- NORMAL TEXT
local LCD_NORMAL_COLOR = TEXT_COLOR
local LCD_DISABLE_COLOR = TEXT_DISABLE_COLOR
local LCD_DEBUG_COLOR = LINE_COLOR
-- NORMAL BOX FRAME COLOR
local LCD_BOX_COLOR = TEXT_DISABLE_COLOR
--------------------- lcd.sizeText replacement -------------------------------------------------
-- EdgeTx dont have lcd.sizeText, so we do an equivalent one using the string length and 5px per character
local function my_lcd_sizeText(s)
print(string.format("EdgeTX=%s",IS_EDGETX))
-- return: If IS_EDGETX then lcd.sizeText() else string.len()
return (IS_EDGETX and lcd.sizeText(s)) or (string.len(s)*10)
end
local function GUI_SwitchSimulationOFF()
dsmLib.ReleaseConnection()
dsmLib.LOG_close()
SIMULATION_ON = false
dsmLib = loadScript("/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgLib.lua")(DEBUG_ON)
DSM_Context = dsmLib.DSM_Context
dsmLib.Init(toolName) -- Initialize Library
dsmLib.StartConnection()
DSM_Context.Refresh_Display = true
end
--------------------- Toucch Button Helpers ------------------------------------------------------------
local function GUI_addTouchButton(x,y,w,h,line)
-- Add new button info to end of the array
touchButtonArea[#touchButtonArea+1] = {x=x, y=y, w=w, h=h, line=line}
end
local function GUI_getTouchButton(x,y)
for i = 1, #touchButtonArea do
local button = touchButtonArea[i]
-- is the coordinate inside the button area??
if (x >= button.x and x <= (button.x+button.w) and y >= button.y and (y <= button.y+button.h)) then
return button.line
end
end
return nil
end
local function GUI_clearTouchButtons()
touchButtonArea = {}
end
---------- Return Color to display Menu Lines ----------------------------------------------------------------
local function GUI_GetTextColor(lineNum)
local ctx = DSM_Context
local txtColor = LCD_NORMAL_COLOR
-- Gray Out any other line except the one been edited
if (ctx.isEditing() and ctx.EditLine~=lineNum) then txtColor=LCD_DISABLE_COLOR end
return txtColor
end
local function GUI_GetFrameColor(lineNum) -- Frame Color for Value/Menu Boxes
local ctx = DSM_Context
local txtColor = LCD_BOX_COLOR
-- Gray Out any other line except the one been edited
if (ctx.EditLine~=lineNum) then txtColor=LCD_DISABLE_COLOR end
return txtColor
end
--------------------------------------------------------------------------------------------------------
-- Display Text inside a Rectangle. Inv: true means solid rectangle, false=only perimeter
local function GUI_Display_Boxed_Text(lineNum,x,y,w,h,text,inv)
local ctx = DSM_Context
local txtColor = GUI_GetTextColor(lineNum)
local frameColor = GUI_GetFrameColor(lineNum)
-- If editing this lineNum, chose EDIT Color, else SELECTED Color
local selectedBGColor = (ctx.EditLine==lineNum and LCD_EDIT_BGCOLOR) or LCD_SELECTED_BGCOLOR
if (inv) then
txtColor = LCD_SELECTED_COLOR
lcd.drawFilledRectangle(x-5, y-2, w, h, selectedBGColor)
else
lcd.drawRectangle(x-5, y-2, w, h, frameColor)
end
lcd.drawText(x , y, text, txtColor)
end
------ Display Pre/Next/Back buttons
local function GUI_Diplay_Button(x,y,w,h,text,selected)
GUI_Display_Boxed_Text(-1,x,y,w,h,text,selected)
end
------ Display MENU type of lines (Navigation, SubHeaders, and plain text comments)
local function GUI_Display_Line_Menu(lineNum,line,selected)
-- Menu Lines can be navidation to other Menus (if Selectable)
-- Or SubHeaders or Messages
local txtColor = GUI_GetTextColor(lineNum)
local y = LCD_Y_LINE_START+(LCD_Y_LINE_HEIGHT*lineNum)
local x = LCD_X_LINE_MENU
if dsmLib.isSelectableLine(line) then -- Draw Selectable Menus in Boxes
GUI_Display_Boxed_Text(lineNum,x, y, LCD_W_LINE_MENU, LCD_Y_LINE_HEIGHT, line.Text,selected)
GUI_addTouchButton(x, y, LCD_W_LINE_MENU, LCD_Y_LINE_HEIGHT,lineNum)
else
-- Non Selectable Menu Lines, plain text
-- Can be use for sub headers or just regular text lines (like warnings)
local bold = (dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.BOLD) and BOLD) or 0
if dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.RIGHT) then -- Right Align???
local tw = my_lcd_sizeText(line.Text)+4
x = LCD_X_LINE_VALUE - tw -- Right
elseif dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.CENTER) then -- Center??
local tw = my_lcd_sizeText(line.Text)
x = x + (LCD_X_LINE_VALUE - LCD_X_LINE_MENU)/2 - tw/2 -- Center - 1/2 Text
end
lcd.drawText(x, y, line.Text, txtColor + bold)
end
end
------ Display NAME : VALUES type of lines
local function GUI_Display_Line_Value(lineNum, line, value, selected, editing)
-- This Displays Name and Value Pairs
local txtColor = GUI_GetTextColor(lineNum)
local bold = 0
local y = LCD_Y_LINE_START+(LCD_Y_LINE_HEIGHT*lineNum)
local x = LCD_X_LINE_TITLE
--if (editing) then -- Any Special color/effect when editing??
-- value = "["..value .. "]"
--end
---------- NAME Part
local header = line.Text
-- ONLY do this for Flight Mode (Right Align or Centered)
if (dsmLib.isFlightModeText(line.TextId)) then
-- Display Header + Value together
header = header .. " " .. value
-- Bold Text???
bold = (dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.BOLD) and BOLD) or 0
if dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.RIGHT) then -- Right Align
local tw = my_lcd_sizeText(header)+4
x = LCD_X_LINE_VALUE - tw -- Right
elseif dsmLib.isDisplayAttr(line.TextAttr,DISP_ATTR.CENTER) then -- Centered
local tw = my_lcd_sizeText(header)
x = x + (LCD_X_LINE_VALUE - LCD_X_LINE_TITLE)/2 - tw/2 -- Center - 1/2 Text
end
else
-- No Flight Mode, no effects here
header = header .. ":"
end
lcd.drawText(x, y, header, txtColor + bold) -- display Line Header
--------- VALUE PART, Skip for Flight Mode since already show the value
if not dsmLib.isFlightModeText(line.TextId) then
value = value .. (line.Format or "") -- Append % if needed
if dsmLib.isSelectableLine(line) then
-- Can select/edit value, Box it
local tw = my_lcd_sizeText(value)+10 -- Width of the Text in the lcd
GUI_Display_Boxed_Text(lineNum,LCD_X_LINE_VALUE,y,tw,LCD_Y_LINE_HEIGHT,value,selected)
GUI_addTouchButton(LCD_X_LINE_VALUE,y,tw,LCD_Y_LINE_HEIGHT,lineNum)
else -- Not Editable, Plain Text
lcd.drawText(LCD_X_LINE_VALUE, y, value, txtColor)
end
end
-- Debug info for line Value RANGE when Debug on LCD
if (DEBUG_ON_LCD) then lcd.drawText(LCD_X_LINE_DEBUG, y, line.MinMaxDebug or "", SMLSIZE + LCD_DEBUG_COLOR) end -- display debug Min/Max
end
local function GUI_Display_Menu(menu)
local ctx = DSM_Context
local w= LCD_W_MENU_TITLE
-- Center Header
local tw = my_lcd_sizeText(menu.Text)
local x = w/2 - tw/2 -- Center of Screen - Center of Text
lcd.drawFilledRectangle(0, LCD_Y_MENU_TITLE-2, w, LCD_Y_LINE_HEIGHT-2, LCD_MENU_BGCOLOR)
lcd.drawText(x,LCD_Y_MENU_TITLE,menu.Text, LCD_MENU_COLOR + BOLD)
-- Back Button
if menu.BackId ~= 0 then
GUI_Diplay_Button(437-5,LCD_Y_MENU_TITLE+3,47,LCD_Y_LINE_HEIGHT,"Back",ctx.SelLine == dsmLib.BACK_BUTTON)
GUI_addTouchButton(437-5,LCD_Y_MENU_TITLE+3,47,LCD_Y_LINE_HEIGHT,dsmLib.BACK_BUTTON)
end
-- Next Button
if menu.NextId ~= 0 then
GUI_Diplay_Button(437-5,LCD_Y_LOWER_BUTTONS,47,LCD_Y_LINE_HEIGHT,"Next",ctx.SelLine == dsmLib.NEXT_BUTTON)
GUI_addTouchButton(437-5,LCD_Y_LOWER_BUTTONS,47,LCD_Y_LINE_HEIGHT,dsmLib.NEXT_BUTTON)
end
-- Prev Button
if menu.PrevId ~= 0 then
GUI_Diplay_Button(10,LCD_Y_LOWER_BUTTONS,47,LCD_Y_LINE_HEIGHT,"Prev",ctx.SelLine == dsmLib.PREV_BUTTON)
GUI_addTouchButton(10,LCD_Y_LOWER_BUTTONS,47,LCD_Y_LINE_HEIGHT,dsmLib.PREV_BUTTON)
end
-- Debug on LCD, Show the menu Indo and Phase we are on
if (DEBUG_ON_LCD) then lcd.drawText(0,LCD_Y_MENU_TITLE,dsmLib.phase2String(ctx.Phase),SMLSIZE+LCD_DEBUG_COLOR) end -- Phase we are in
if (DEBUG_ON_LCD) then lcd.drawText(0,240,dsmLib.menu2String(menu),SMLSIZE+LCD_DEBUG_COLOR) end -- Menu Info
end
------------------------------------------------------------------------------------------------------------
-- Display the EDIT mode buttons when editing a value
local function GUI_Display_Edit_Buttons(line)
GUI_clearTouchButtons() -- Only this buttons can be touched
local x = 15 -- Inittial X position
local w = 55 -- Width of the buttons
local showPrev = line.Val > line.Min
local showNext = line.Val < line.Max
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,"ESC",true)
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.ESC)
x=x+w+10
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," Def",true)
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.DEFAULT)
x=x+w+10
if (not dsmLib.isListLine(line)) then
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," << ",showPrev)
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.DEC_10)
end
x=x+w+10
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," <",showPrev)
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.DEC_1)
x=x+w+10
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," >",showNext)
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.INC_1)
x=x+w+10
if (not dsmLib.isListLine(line)) then
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," >>",showNext)
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.INC_10)
end
x=x+w+10
GUI_Diplay_Button(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT," OK",true)
GUI_addTouchButton(x,LCD_Y_LOWER_BUTTONS,w,LCD_Y_LINE_HEIGHT,EDIT_BUTTON.OK)
end
------------------------------------------------------------------------------------------------------------
local function GUI_Display()
local ctx = DSM_Context
lcd.clear()
GUI_clearTouchButtons()
if LCD_W == 480 then
local header = "DSM Forward Programming "..VERSION.." "
if ctx.Phase ~= PHASE.RX_VERSION then
header = header .. "RX "..ctx.RX.Name.." v"..ctx.RX.Version
end
--Draw title
lcd.drawFilledRectangle(0, 0, LCD_W, 17, LCD_TOOL_HDR_BGCOLOR)
lcd.drawText(5, 0, header, LCD_TOOL_HDR_COLOR + SMLSIZE)
--Draw RX Menu
if ctx.Phase == PHASE.RX_VERSION then
lcd.drawText(LCD_X_LINE_TITLE,100,"No compatible DSM RX...", BLINK)
else
local menu = ctx.Menu
if menu.Text ~= nil then
GUI_Display_Menu(menu)
for i = 0, dsmLib.MAX_MENU_LINES do
local line = ctx.MenuLines[i]
if i == ctx.SelLine then
-- DEBUG: Display Selected Line info for ON SCREEN Debugging
if (DEBUG_ON_LCD) then lcd.drawText(0,255,dsmLib.menuLine2String(line),SMLSIZE + LCD_DEBUG_COLOR) end
end
if line ~= nil and line.Type ~= 0 then
if line.Type == LINE_TYPE.MENU then
GUI_Display_Line_Menu(i, line, i == ctx.SelLine)
else
-- list/value line
local value, imgValue = line.Val, nil
if line.Val ~= nil then
if dsmLib.isListLine(line) then -- for Lists of Strings, get the text
value = dsmLib.Get_Text(line.Val + line.TextStart) -- TextStart is the initial offset for text
imgValue = dsmLib.Get_Text_Img(line.Val + line.TextStart) -- Complentary IMAGE for this value to Display??
if (imgValue) then -- Optional Image for a Value
--TODO: Pending feature.. create images and put bitmap instead of a message
--Display the image/Alternate Text
lcd.drawText(LCD_X_LINE_TITLE, LCD_Y_LINE_START+LCD_Y_LINE_HEIGHT, "Img:"..imgValue)
end
end
GUI_Display_Line_Value(i, line, value, i == ctx.SelLine, i == ctx.EditLine)
end
end -- if ~MENU
end -- if Line[i]~=nil
end -- for
if IS_EDGETX and ctx.isEditing() then
GUI_Display_Edit_Buttons(ctx.MenuLines[ctx.EditLine])
end
end
end
else
-- Different Resolution.. Maybe just adjusting some of the constants will work, adjust it in DSM_Init??
-- LCD_X_LINE_TITLE, LCD_Y_LINE_START, etc
end
end
-------------------------------------------------------------------------------------------------------------
local function GUI_RotEncVal(dir) -- return encoder speed to inc or dec values
local inc = 0
local Speed = getRotEncSpeed()
if Speed == ROTENC_MIDSPEED then inc = (5 * dir)
elseif Speed == ROTENC_HIGHSPEED then inc = (15 * dir)
else inc = dir end
return inc
end
------------------------------------------------------------------------------------
-- Translate Tap/Touch of EDIT buttons to equivalent Key events
local function GUI_Translate_Edit_Buttons(button)
local event = EVT_TOUCH_TAP
local editInc = nil
if (button==EDIT_BUTTON.ESC) then -- ESC
event = EVT_VIRTUAL_EXIT
elseif (button==EDIT_BUTTON.DEFAULT) then -- Default
event = EVT_VIRTUAL_ENTER_LONG
elseif (button==EDIT_BUTTON.DEC_10) then -- -10
event = EVT_VIRTUAL_PREV
editInc = -10
elseif (button==EDIT_BUTTON.DEC_1) then -- -1
event = EVT_VIRTUAL_PREV
editInc = -1
elseif (button==EDIT_BUTTON.INC_1) then -- +1
event = EVT_VIRTUAL_NEXT
editInc = 1
elseif (button==EDIT_BUTTON.INC_10) then -- + 10
event = EVT_VIRTUAL_NEXT
editInc = 10
elseif (button==EDIT_BUTTON.OK) then -- OK
event = EVT_VIRTUAL_ENTER
else
end
return event, editInc
end
------------------------------------------------------------------------------------------------------------
-- Handle Events comming from the GUI
local function GUI_HandleEvent(event, touchState)
local ctx = DSM_Context
local menu = ctx.Menu
local menuLines = ctx.MenuLines
local editInc = nil
if (IS_EDGETX) then
if (event == EVT_TOUCH_TAP and ctx.isEditing()) then -- Touch and Editing
local button = GUI_getTouchButton(touchState.x, touchState.y)
if (button) then
event, editInc = GUI_Translate_Edit_Buttons(button)
end
end
if (event == EVT_TOUCH_TAP or event == EVT_TOUCH_FIRST) and not ctx.isEditing() then -- Touch and NOT editing
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_TOUCH_TAP %d,%d\n",dsmLib.phase2String(ctx.Phase),touchState.x, touchState.y) end
local button = GUI_getTouchButton(touchState.x, touchState.y)
if button then
-- Found a valid line
ctx.SelLine = button
ctx.Refresh_Display=true
if event == EVT_TOUCH_TAP then -- EVT_TOUCH_FIRST only move focus
event = EVT_VIRTUAL_ENTER
end
end
end
end
if event == EVT_VIRTUAL_EXIT then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_EXIT\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.Phase == PHASE.RX_VERSION then
dsmLib.ReleaseConnection() -- Just Exit the Script
else
if ctx.isEditing() then -- Editing a Line, need to restore original value
ctx.MenuLines[ctx.EditLine].Val = originalValue
dsmLib.ChangePhase(PHASE.VALUE_CHANGE_END) -- Update + Validate value in RX
ctx.EditLine = nil -- Exit Edit Mode (By clearing the line editing)
else
dsmLib.ChangePhase(PHASE.EXIT)
end
end
return
end
if event == EVT_VIRTUAL_NEXT then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_NEXT\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.isEditing() then -- Editing a Line, need to inc the value
local line=ctx.MenuLines[ctx.EditLine]
dsmLib.Value_Add(line, editInc or GUI_RotEncVal(1))
else -- not editing, move selected line to NEXT
dsmLib.MoveSelectionLine(1)
end
return
end
if event == EVT_VIRTUAL_PREV then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_PREV\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.isEditing() then -- Editiing a line, need to dec the value
local line=ctx.MenuLines[ctx.EditLine]
dsmLib.Value_Add(line, editInc or GUI_RotEncVal(-1))
else -- not editing, move selected line to PREV
dsmLib.MoveSelectionLine(-1)
end
return
end
if event == EVT_VIRTUAL_ENTER_LONG then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_ENTER_LONG\n",dsmLib.phase2String(ctx.Phase)) end
if ctx.isEditing() then
-- reset the value to default
dsmLib.Value_Default(menuLines[ctx.EditLine]) -- Update value in RX if needed
end
return
end
if event == EVT_VIRTUAL_ENTER then
ctx.Refresh_Display=true
if (DEBUG_ON) then dsmLib.LOG_write("%s: EVT_VIRTUAL_ENTER, SelLine=%d\n",dsmLib.phase2String(ctx.Phase), ctx.SelLine) end
if ctx.SelLine == dsmLib.BACK_BUTTON then -- Back
dsmLib.GotoMenu(menu.BackId)
elseif ctx.SelLine == dsmLib.NEXT_BUTTON then -- Next
dsmLib.GotoMenu(menu.NextId)
elseif ctx.SelLine == dsmLib.PREV_BUTTON then -- Prev
dsmLib.GotoMenu(menu.PrevId)
elseif menuLines[ctx.SelLine].ValId ~= 0 then -- Menu or Value
if menuLines[ctx.SelLine].Type == LINE_TYPE.MENU then -- Navigate to Menu
if (SIMULATION_ON and menuLines[ctx.SelLine].ValId==0xFFFF) then
-- SPECIAL Simulation menu to Exit Simulation
GUI_SwitchSimulationOFF()
else
dsmLib.GotoMenu(menuLines[ctx.SelLine].ValId) -- ValId is the MenuId to navigate to
end
else -- Enter on a Value
if ctx.isEditing() then -- already editing a Line????
ctx.EditLine = nil -- Exit Edit Mode (By clearing the line editing)
dsmLib.ChangePhase(PHASE.VALUE_CHANGE_END) -- Request change the value on RX
else -- Edit the current value
ctx.EditLine = ctx.SelLine
originalValue = menuLines[ctx.SelLine].Val
end
end
end
end
end
local function init_colors()
-- osName in OpenTX is nil, otherwise is EDGETX
local ver, radio, maj, minor, rev, osname = getVersion()
IS_EDGETX = osname~=nil
if (IS_EDGETX and USE_SPECKTRUM_COLORS) then
-- SPECKTRUM COLORS (only works on EDGETX)
-- TOOL HEADER
LCD_TOOL_HDR_COLOR = MENU_TITLE_COLOR
LCD_TOOL_HDR_BGCOLOR = TITLE_BGCOLOR
-- MENU HEADER
LCD_MENU_COLOR = WHITE
LCD_MENU_BGCOLOR = DARKGREY
-- LINE SELECTED
LCD_SELECTED_COLOR = WHITE
LCD_SELECTED_BGCOLOR = ORANGE
LCD_EDIT_BGCOLOR = RED
-- NORMAL TEXT
LCD_NORMAL_COLOR = BLACK
LCD_DISABLE_COLOR = LIGHTGREY
LCD_DEBUG_COLOR = BLUE
-- NORMAL BOX FRAME COLOR
LCD_BOX_COLOR = LIGHTGREY
end
end
------------------------------------------------------------------------------------------------------------
-- Init
local function DSM_Init()
init_colors()
dsmLib.Init(toolName) -- Initialize Library
return dsmLib.StartConnection()
end
------------------------------------------------------------------------------------------------------------
-- Main
local function DSM_Run(event,touchState)
local ctx = DSM_Context
if event == nil then
error("Cannot be run as a model script!")
dsmLib.LOG_close()
return 2
end
GUI_HandleEvent(event,touchState)
dsmLib.Send_Receive() -- Handle Send and Receive DSM Forward Programming Messages
local refreshInterval = REFRESH_GUI_MS
-- When using LCD BLINK attribute, we need faster refresh for BLINK to SHOW on LCD
if (ctx.Phase == PHASE.RX_VERSION) then -- Requesting RX Message Version usea BLINK?
ctx.Refresh_Display=true
refreshInterval = 20 -- 200ms
end
-- Refresh display only if needed and no faster than 300ms, utilize more CPU to speedup DSM communications
if (ctx.Refresh_Display and (getTime()-lastRefresh) > refreshInterval) then --300ms from last refresh
GUI_Display()
ctx.Refresh_Display=false
lastRefresh=getTime()
end
if ctx.Phase == PHASE.EXIT_DONE then
dsmLib.LOG_close()
return 2
else
return 0
end
end
return { init=DSM_Init, run=DSM_Run }

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,53 @@
This script library is a rewrite of the original DSM forward programming Lua
Script. The goal is to make it easier to understand, mantain, and to
separate the GUI from the DSM Forward programming engine/logic
in this way, GUIs can evolve independent. OpenTX Gui, EdgeTx GUI, etc.
Code is based on the code/work by: Pascal Langer (Author of the Multi-Module)
Rewrite/Enhancements By: Francisco Arzu
Deployment:
/SCRIPTS/TOOLS/DsmFwdPrg_05_BaW.lua -- OpenTX/EdgeTx version, no touch (black/white radios)
/SCRIPTS/TOOLS/DsmFwdPrg_05_Color.lua -- EdgeTX/OpenTx Color version, +touch
/SCRIPTS/TOOLS/DSMLIB/ -- Libraries (ALL CAPITALS) to hide them from the Tools menu
/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgLib.lub -- DSM Protocol Message and Menu engine
/SCRIPTS/TOOLS/DSMLIB/DsmFwPrgSIMLib.lub -- Simulation of AR631 for GUI Development in Companion
/LOGS/dsm_log.txt -- Readable log of the last RX session, usefull for debuging new RX
Version 0.5
- Make the code more readable and understadable
- Separate the DSM Forwards Programing logic from the GUI
- Log the comunnication with the RX on a /LOGS/dsm_log.txt to allow to debug it easier
and see the exchange of data between the RX/TX
- Created a black/white version with only Key/Roller Inputs (OTX)
- Created a nicer GUI for EdgeTX touchscreen color Radios
- RX simulation for GUI development: turn on SIMULATION_ON=true in the beginning of the lua file
Some settings that can change (top of Lua file):
SIMULATION_ON = false -- FALSE: use real communication to DSM RX (DEFAULT), TRUE: use a simulated version of RX
DEBUG_ON = 1 -- 0=NO DEBUG, 1=HIGH LEVEL 2=LOW LEVEL (Debug logged into the /LOGS/dsm_log.txt)
DEBUG_ON_LCD = false -- Interactive Information on LCD of Menu data from RX
USE_SPECKTRUM_COLORS = true -- true: Use spectrum colors, false: use theme colors (default on OpenTX)
Known Problems:
1. When trying to Factory Reset an RX, even that navigation to menus seems OK, it did not reset.
Maybe another message needs to be sent to RX when reaching that page
2. When initially setting a new RX, there is a point where a menu navigates to MenuID=0x0001, this seems like a
special Save/Restart type of menu.. but it does not reset the RX. maybe another meesage needs to be send
3. Some Menu List line types (LINE_TYPE.LIST_MENU1 or "L_m1" in logs), the range (min/max) seems to be incorrect, but cannot see in the data how to fix it
Some of the valid values are not even sequential, very spread apart. There has to be a list of valid options somewhere (in RX or config for each field).
4. The RX return unknow lines when requesting the Lines for a menu. Realy don't understand what they are for.
in some menus, seems to stay stuck in the same return line or no response to the request, making the RX reset/close the connection.
Did a fix to stop requesting the same menu line if the response is the same. This gives an empty menu, but does not reset the connection.
Version 0.2
Original Version from Pascal Langer

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

View File

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

View File

@@ -52,18 +52,22 @@ Notes:
[![Text mode video](https://img.youtube.com/vi/81wd8NlF3Qw/0.jpg)](https://www.youtube.com/watch?v=81wd8NlF3Qw) [![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 ## 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 available for color(+touch) and B&W screens.
This is a work in progress. It's only available for color screens (Horus, TX16S, T16, T18...). Work on OpenTX and EdgeTX. Located on the radio SD card under \SCRIPTS\TOOLS, make sure to copy the DSMLIB folder along with DSM FwdPrg_05_Color.lua or DSM FwdPrg_05_BW.lua.
If some text appears as Unknown_xxx, please report xxx and what the exact text display should be.
Need OpenTX 2.3.10 nightly or above. Located on the radio SD card under \SCRIPTS\TOOLS.
[![DSM Forward Programming](https://img.youtube.com/vi/sjIaDw5j9nE/0.jpg)](https://www.youtube.com/watch?v=sjIaDw5j9nE) [![DSM Forward Programming](https://img.youtube.com/vi/sjIaDw5j9nE/0.jpg)](https://www.youtube.com/watch?v=sjIaDw5j9nE)
If some text appears as Unknown_xxx, please report xxx and what the exact text display should be.
## DSM PID Flight log gain parameters for Blade micros ## DSM PID Flight log gain parameters for Blade micros
Lua telemetry script from [feathering on RCGroups](https://www.rcgroups.com/forums/showpost.php?p=46033341&postcount=20728) to facilitate setting the Gain Parameters on the Blade 150S FBL. It doesn't use Forward Programming but instead it just reads telemetry data from the Multi-module and displays it on a telemetry display. Lua telemetry script from [feathering on RCGroups](https://www.rcgroups.com/forums/showpost.php?p=46033341&postcount=20728) to facilitate setting the Gain Parameters on the Blade 150S FBL. It doesn't use Forward Programming but instead it just reads telemetry data from the Multi-module and displays it on a telemetry display.

View File

@@ -249,6 +249,10 @@ static uint8_t __attribute__((unused)) DSM_Check_RX_packet()
uint16_t DSM_callback() uint16_t DSM_callback()
{ {
#if defined MULTI_EU
if(sub_protocol == DSM2_1F || sub_protocol == DSM2_2F)
return 11000;
#endif
#define DSM_CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2 #define DSM_CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2
#ifdef STM32_BOARD #ifdef STM32_BOARD
#define DSM_WRITE_DELAY 1600 // Time after write to verify write complete #define DSM_WRITE_DELAY 1600 // Time after write to verify write complete

View File

@@ -18,15 +18,17 @@
#include "iface_rf2500.h" #include "iface_rf2500.h"
//#define E129_FORCE_ID //#define E129_FORCE_ID
//#define C186_FORCE_ID
#define E129_BIND_CH 0x2D //45 #define E129_BIND_CH 0x2D //45
#define E129_PAYLOAD_SIZE 16 #define E129_PAYLOAD_SIZE 16
#define C186_PAYLOAD_SIZE 19
static void __attribute__((unused)) E129_build_data_packet() static void __attribute__((unused)) E129_build_data_packet()
{ {
//Build the packet //Build the packet
memset(packet,0,E129_PAYLOAD_SIZE); memset(packet,0,packet_length);
packet[ 0] = 0x0F; // Packet length packet[ 0] = packet_length - 1; // Packet length
if(IS_BIND_IN_PROGRESS) if(IS_BIND_IN_PROGRESS)
{ {
packet[ 1] = 0xA4; packet[ 1] = 0xA4;
@@ -40,11 +42,21 @@ static void __attribute__((unused)) E129_build_data_packet()
else else
{ {
packet[ 1] = 0xA6; packet[ 1] = 0xA6;
packet[ 2] = 0xF7; // High rate 0xF7, low rate 0xF4 //Flags
//packet[ 3] = 0x00; // Mode: short press=0x20->0x00->0x20->..., long press=0x10->0x30->0x10->... 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 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); uint16_t val = convert_channel_10b(AILERON,false);
uint8_t trim = convert_channel_8b(CH7) & 0xFC; uint8_t trim = convert_channel_8b(CH7) & 0xFC;
packet[ 5] = trim | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8 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[11] = trim | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8
packet[12] = val; // channel (0x000...0x200...0x3FF) packet[12] = val; // channel (0x000...0x200...0x3FF)
} }
packet[14] = 0x00; // Check //Check
for(uint8_t i=0;i<14;i++) if(sub_protocol == E129_E129)
packet[14] += packet[i]; 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); RF2500_BuildPayload(packet);
} }
@@ -83,7 +99,7 @@ uint16_t E129_callback()
//Send packet //Send packet
RF2500_SendPayload(); 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) if(phase==0)
{ {
phase++; phase++;
@@ -109,7 +125,9 @@ uint16_t E129_callback()
hopping_frequency_no &= 3; hopping_frequency_no &= 3;
phase=0; phase=0;
return 5200-1260; if(sub_protocol==E129_E129)
return 5200-1260;
return 5500-1260; //E129_C186
} }
void E129_init() void E129_init()
@@ -117,8 +135,9 @@ void E129_init()
BIND_IN_PROGRESS; // Autobind protocol BIND_IN_PROGRESS; // Autobind protocol
bind_counter = 384; // ~2sec bind_counter = 384; // ~2sec
//RF2500 emu init //RF2500 emu init
RF2500_Init(E129_PAYLOAD_SIZE, true); // 16 bytes, Scrambled packet_length = sub_protocol == E129_E129?E129_PAYLOAD_SIZE:C186_PAYLOAD_SIZE;
RF2500_Init(packet_length, true); // 16/19 bytes, Scrambled
//Freq hopping //Freq hopping
calc_fh_channels(4); calc_fh_channels(4);
@@ -136,6 +155,16 @@ void E129_init()
hopping_frequency[2]=0x4B; //75 hopping_frequency[2]=0x4B; //75
hopping_frequency[3]=0x41; //65 hopping_frequency[3]=0x41; //65
#endif #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 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 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
static uint8_t upper=0;
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 #ifdef FAILSAFE_ENABLE
static uint8_t 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(IS_FAILSAFE_VALUES_on && IS_BIND_DONE) { // if TX wants to send failsafe data and RX is connected
failsafe_count++; failsafe_count++; // prepare to send next packet
if(failsafe_count>=3)
{ if(failsafe_count >= 3) { // done sending two failsafe channel data packets
FAILSAFE_VALUES_off; FAILSAFE_VALUES_off;
failsafe_count=0; failsafe_count = 0;
} }
} }
else else
failsafe_count=0; failsafe_count = 0;
#endif #endif
// Channels value are PPM*2, -100%=1100µs, +100%=1900µs, order TAER // 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; uint16_t val;
for(uint8_t i=4;i<28;i+=2) 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 ch=(i-4)>>1; uint8_t fschIndex = chIndex; // linear channel number for failsafe
if(upper && ch >= 8)
ch+=4; // when upper swap CH9..CH12 by CH13..16 if(upper && chIndex >= 8) chIndex += 4; // for normal operation toggle between channels 1..8,9..12 and 1..8,13..16
val=Channel_data[ch]; val = Channel_data[chIndex]; // get normal operation channel data
val=(((val<<2)+val)>>2)+860*2; // value range 860<->2140 *2 <-> -125%<->+125% 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 #ifdef FAILSAFE_ENABLE
if(failsafe_count==1) if(failsafe_count == 1 || failsafe_count == 2) {// failsafe data needs to be sent to RX
{ // first failsafe packet uint16_t fs = 0x8000; // default failsafe mode is hold
packet[3] |= 0x40;
uint16_t fs=Failsafe_data[ch]; if(failsafe_count == 1) { // send fail safe packet containing channels 1..12
if( fs == FAILSAFE_CHANNEL_HOLD || fs == FAILSAFE_CHANNEL_NOPULSES) packet[3] = 0x40; // indicate packet has failsafe values for channels 1..12
val|=0x8000; // channel hold flag fs = Failsafe_data[fschIndex]; // get failsafe channel data
else } else { // send fail safe packet containing channels 13..24
{ packet[3] = 0x41; // indicate packet has failsafe values for channels 13..24
val=(((fs<<2)+fs)>>2)+860*2; // value range 860<->2140 *2 <-> -125%<->+125% if(fschIndex < 4) // we only work 16 channels so send channels 13..16, rest default
val|=0x4000; // channel specific position flag 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 #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
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 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 #ifdef HOTT_FW_TELEMETRY
if(IS_BIND_DONE) if(IS_BIND_DONE)
{ {

View File

@@ -46,7 +46,7 @@ static void __attribute__((unused)) KF606_send_packet()
if(sub_protocol == KF606_KF606) 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[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 else
{ {
@@ -57,6 +57,7 @@ static void __attribute__((unused)) KF606_send_packet()
packet[3] = 0x01; packet[3] = 0x01;
else if(packet[3] > 0x1F) else if(packet[3] > 0x1F)
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,141 @@
/*
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
#define KYOSHO2_BIND_PACKET_PERIOD 1600
#define KYOSHO2_BIND_COUNT 6000 // about 9sec
#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
KYOSHO2_send_packet();
if(bind_counter)
{
if(--bind_counter==0)
{
BIND_DONE;
KYOSHO2_resend = false;
}
return KYOSHO2_BIND_PACKET_PERIOD;
}
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 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_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_F949G 3450
#define MT99XX_PACKET_PERIOD_PA18 1338
#define MT99XX_INITIAL_WAIT 500 #define MT99XX_INITIAL_WAIT 500
#define MT99XX_PACKET_SIZE 9 #define MT99XX_PACKET_SIZE 9
//#define FORCE_A180_ID //#define FORCE_A180_ID
//#define FORCE_DRAGON_ID //#define FORCE_DRAGON_ID
//#define FORCE_F949G_ID //#define FORCE_F949G_ID
#define FORCE_PA18_ID1
//#define FORCE_PA18_ID2
enum { enum {
MT99XX_DATA, MT99XX_DATA,
@@ -82,6 +85,11 @@ enum{
FLAG_F949G_LIGHT = 0x01, FLAG_F949G_LIGHT = 0x01,
FLAG_F949G_3D6G = 0x20, 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[] = { const uint8_t h7_mys_byte[] = {
0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14, 0x01, 0x11, 0x02, 0x12, 0x03, 0x13, 0x04, 0x14,
@@ -107,11 +115,11 @@ static void __attribute__((unused)) MT99XX_send_packet()
//Set RF freq //Set RF freq
if(sub_protocol == LS) 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 else
if(sub_protocol==FY805) if(sub_protocol==FY805)
XN297_RFChannel(0x4B); // FY805 always transmits on the same channel XN297_RFChannel(0x4B); // FY805 always transmits on the same channel
else // MT99 & H7 & YZ & A180 & DRAGON & F949G else // MT99 & H7 & YZ & A180 & DRAGON & F949G & PA18
XN297_Hopping(hopping_frequency_no); XN297_Hopping(hopping_frequency_no);
if(IS_BIND_IN_PROGRESS) if(IS_BIND_IN_PROGRESS)
@@ -121,7 +129,6 @@ static void __attribute__((unused)) MT99XX_send_packet()
switch(sub_protocol) switch(sub_protocol)
{ {
case YZ: case YZ:
packet_period = MT99XX_PACKET_PERIOD_YZ;
packet[1] = 0x15; packet[1] = 0x15;
packet[2] = 0x05; packet[2] = 0x05;
packet[3] = 0x06; packet[3] = 0x06;
@@ -132,15 +139,11 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[3] = 0x11; packet[3] = 0x11;
break; break;
case FY805: case FY805:
packet_period = MT99XX_PACKET_PERIOD_FY805;
packet[1] = 0x15; packet[1] = 0x15;
packet[2] = 0x12; packet[2] = 0x12;
packet[3] = 0x17; packet[3] = 0x17;
break; break;
case F949G: default: // MT99 & H7 & A180 & DRAGON & F949G & PA18
case A180:
packet_period = MT99XX_PACKET_PERIOD_A180;
default: // MT99 & H7 & A180 & DRAGON & F949G
packet[1] = 0x14; packet[1] = 0x14;
packet[2] = 0x03; packet[2] = 0x03;
packet[3] = 0x25; packet[3] = 0x25;
@@ -149,16 +152,24 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[4] = rx_tx_addr[0]; packet[4] = rx_tx_addr[0];
packet[5] = rx_tx_addr[1]; packet[5] = rx_tx_addr[1];
packet[6] = rx_tx_addr[2]; packet[6] = rx_tx_addr[2];
packet[7] = crc8; // checksum offset if(sub_protocol == PA18+8)
if(sub_protocol != F949G) {
packet[8] = 0xAA; // fixed packet[7] = num_ch; // checksum offset
packet[8] = 0x55; // fixed
}
else else
packet[8] = 0x00; { // all others
packet[7] = crc8; // checksum offset
if(sub_protocol != F949G)
packet[8] = 0xAA; // fixed
else
packet[8] = 0x00;
}
} }
else else
{ {
if(sub_protocol != YZ) 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[0] = convert_channel_16b_limit(THROTTLE,0xE1,0x00); // throttle
packet[1] = convert_channel_16b_limit(RUDDER ,0x00,0xE1); // rudder packet[1] = convert_channel_16b_limit(RUDDER ,0x00,0xE1); // rudder
packet[2] = convert_channel_16b_limit(AILERON ,0xE1,0x00); // aileron packet[2] = convert_channel_16b_limit(AILERON ,0xE1,0x00); // aileron
@@ -166,8 +177,10 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[4] = 0x20; // pitch trim (0x3f-0x20-0x00) packet[4] = 0x20; // pitch trim (0x3f-0x20-0x00)
packet[5] = 0x20; // roll trim (0x00-0x20-0x3f) packet[5] = 0x20; // roll trim (0x00-0x20-0x3f)
packet[6] = GET_FLAG( CH5_SW, FLAG_MT_FLIP ); packet[6] = GET_FLAG( CH5_SW, FLAG_MT_FLIP );
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) switch(sub_protocol)
{ {
case MT99: case MT99:
@@ -198,16 +211,16 @@ static void __attribute__((unused)) MT99XX_send_packet()
crc8=0; crc8=0;
break; break;
case A180: case A180:
packet[6] = GET_FLAG( !CH6_SW,FLAG_A180_RATE) // 0x02, A180=RATE, F949S=LED 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( CH5_SW, FLAG_A180_3D6G ) // 0x01, A180=3D_6G, F949S=RATE
|GET_FLAG( CH7_SW, 0x20 ); // 0x20, F949S=3D_6G |GET_FLAG( CH7_SW, 0x20 ); // 0x20, F949S=3D_6G
packet[7] = 0x00; packet[7] = 0x00;
break; break;
case DRAGON: case DRAGON:
if(CH5_SW) // Advanced mode if(CH5_SW) // Advanced mode
packet[5] |= 0x80; packet[5] |= 0x80;
else else
if(Channel_data[CH5] > CHANNEL_MIN_COMMAND) // Beginner mode if(Channel_data[CH5] > CHANNEL_MIN_COMMAND) // Beginner mode
packet[5] |= 0x40; packet[5] |= 0x40;
packet[6] = FLAG_DRAGON_RATE packet[6] = FLAG_DRAGON_RATE
| GET_FLAG( CH6_SW, FLAG_DRAGON_RTH ); | GET_FLAG( CH6_SW, FLAG_DRAGON_RTH );
@@ -222,12 +235,12 @@ static void __attribute__((unused)) MT99XX_send_packet()
if(packet_count > 11) if(packet_count > 11)
packet_count = 0; 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; 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) if(seq_num==3)
packet[7] |= v_lipo1; packet[7] |= v_lipo1;
#else #else
@@ -240,18 +253,31 @@ static void __attribute__((unused)) MT99XX_send_packet()
| GET_FLAG( CH6_SW, FLAG_F949G_LIGHT ); | GET_FLAG( CH6_SW, FLAG_F949G_LIGHT );
packet[7] = 0x00; packet[7] = 0x00;
break; 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; uint8_t result=crc8;
for(uint8_t i=0; i<8; i++) for(uint8_t i=0; i<8; i++)
result += packet[i]; result += packet[i];
if(sub_protocol == PA18+8)
result += num_ch;
packet[8] = result; packet[8] = result;
} }
else else
{ // YZ { // YZ
packet[0] = convert_channel_16b_limit(THROTTLE,0x00,0x64); // throttle packet[0] = convert_channel_16b_limit(THROTTLE,0x00,0x64); // throttle
packet[1] = convert_channel_16b_limit(RUDDER ,0x64,0x00); // rudder packet[1] = convert_channel_16b_limit(RUDDER ,0x64,0x00); // rudder
packet[2] = convert_channel_16b_limit(ELEVATOR,0x00,0x64); // elevator packet[2] = convert_channel_16b_limit(ELEVATOR,0x00,0x64); // elevator
packet[3] = convert_channel_16b_limit(AILERON ,0x64,0x00); // aileron packet[3] = convert_channel_16b_limit(AILERON ,0x64,0x00); // aileron
if(packet_count++ >= 23) if(packet_count++ >= 23)
{ {
seq_num ++; seq_num ++;
@@ -261,11 +287,11 @@ static void __attribute__((unused)) MT99XX_send_packet()
} }
packet[4] = yz_p4_seq[seq_num]; packet[4] = yz_p4_seq[seq_num];
packet[5] = 0x02 // expert ? (0=unarmed, 1=normal) packet[5] = 0x02 // expert ? (0=unarmed, 1=normal)
| GET_FLAG(CH8_SW, 0x10) //VIDEO | GET_FLAG(CH8_SW, 0x10) //VIDEO
| GET_FLAG(CH5_SW, 0x80) //FLIP | GET_FLAG(CH5_SW, 0x80) //FLIP
| GET_FLAG(CH9_SW, 0x04) //HEADLESS | GET_FLAG(CH9_SW, 0x04) //HEADLESS
| GET_FLAG(CH7_SW, 0x20); //SNAPSHOT | GET_FLAG(CH7_SW, 0x20); //SNAPSHOT
packet[6] = GET_FLAG(CH6_SW, 0x80); //LED packet[6] = GET_FLAG(CH6_SW, 0x80); //LED
packet[7] = packet[0]; packet[7] = packet[0];
for(uint8_t idx = 1; idx < MT99XX_PACKET_SIZE-2; idx++) for(uint8_t idx = 1; idx < MT99XX_PACKET_SIZE-2; idx++)
packet[7] += packet[idx]; packet[7] += packet[idx];
@@ -275,7 +301,7 @@ static void __attribute__((unused)) MT99XX_send_packet()
//Hopp //Hopp
hopping_frequency_no++; 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 hopping_frequency_no++; // skip every other channel
if(hopping_frequency_no > 15) if(hopping_frequency_no > 15)
hopping_frequency_no = 0; hopping_frequency_no = 0;
@@ -311,9 +337,9 @@ static void __attribute__((unused)) MT99XX_RF_init()
static void __attribute__((unused)) MT99XX_initialize_txid() static void __attribute__((unused)) MT99XX_initialize_txid()
{ {
rx_tx_addr[1] = rx_tx_addr[3]; // RX_Num num_ch = rx_tx_addr[1]; // PA18
rx_tx_addr[1] = rx_tx_addr[3]; // RX_Num
switch(protocol) switch(sub_protocol)
{ {
case YZ: case YZ:
rx_tx_addr[0] = 0x53; // test (SB id) rx_tx_addr[0] = 0x53; // test (SB id)
@@ -355,8 +381,35 @@ static void __attribute__((unused)) MT99XX_initialize_txid()
//channel_offset = 0x03 //channel_offset = 0x03
break; break;
#endif #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; rx_tx_addr[2] = 0x00;
if(sub_protocol == PA18+8)
rx_tx_addr[2] = 0x13;
break; break;
} }
@@ -446,14 +499,40 @@ uint16_t MT99XX_callback()
void MT99XX_init(void) void MT99XX_init(void)
{ {
if(sub_protocol != A180 && sub_protocol != DRAGON && sub_protocol != F949G) if(protocol == PROTO_MT99XX2)
BIND_IN_PROGRESS; // autobind protocol sub_protocol|=0x08; // Increase the number of sub_protocols for MT99XX
bind_counter = MT99XX_BIND_COUNT; 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_initialize_txid();
MT99XX_RF_init(); 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; packet_count=0;
phase=MT99XX_DATA; phase=MT99XX_DATA;

View File

@@ -45,7 +45,7 @@
45,E01X,E012,E015 45,E01X,E012,E015
46,V911S,V911S,E119 46,V911S,V911S,E119
47,GD00x,GD_V1,GD_V2 47,GD00x,GD_V1,GD_V2
48,V761,3CH,4CH 48,V761,3CH,4CH,TOPRC
49,KF606,KF606,MIG320 49,KF606,KF606,MIG320
50,Redpine,Fast,Slow 50,Redpine,Fast,Slow
51,Potensic,A20 51,Potensic,A20
@@ -55,7 +55,7 @@
55,Frsky_RX,Multi,CloneTX,EraseTX,CPPM 55,Frsky_RX,Multi,CloneTX,EraseTX,CPPM
56,AFHDS2A_RX,Multi,CPPM 56,AFHDS2A_RX,Multi,CPPM
57,HoTT,Sync,No_Sync 57,HoTT,Sync,No_Sync
58,FX816,P38 58,FX,816,620
59,Bayang_RX,Multi,CPPM 59,Bayang_RX,Multi,CPPM
60,Pelikan,Pro,Lite,SCX24 60,Pelikan,Pro,Lite,SCX24
61,Tiger 61,Tiger
@@ -80,11 +80,13 @@
80,E016H,E016Hv2 80,E016H,E016Hv2
81,E010r5 81,E010r5
82,LOLI 82,LOLI
83,E129 83,E129,E129,C186
84,JOYSWAY 84,JOYSWAY
85,E016H 85,E016H
87,IKEA 87,IKEA
88,WILLIFM 88,WILLIFM
89,Losi 89,Losi
90,MouldKg,Analog,Digit 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_FRSKYX2[] ="FrSkyX2";
const char STR_ESKY[] ="ESky"; const char STR_ESKY[] ="ESky";
const char STR_MT99XX[] ="MT99XX"; const char STR_MT99XX[] ="MT99XX";
const char STR_MT99XX2[] ="MT99XX2";
const char STR_MJXQ[] ="MJXq"; const char STR_MJXQ[] ="MJXq";
const char STR_SHENQI[] ="Shenqi"; const char STR_SHENQI[] ="Shenqi";
const char STR_FY326[] ="FY326"; const char STR_FY326[] ="FY326";
@@ -77,7 +78,7 @@ const char STR_SCANNER[] ="Scanner";
const char STR_FRSKY_RX[] ="FrSkyRX"; const char STR_FRSKY_RX[] ="FrSkyRX";
const char STR_AFHDS2A_RX[] ="FS2A_RX"; const char STR_AFHDS2A_RX[] ="FS2A_RX";
const char STR_HOTT[] ="HoTT"; const char STR_HOTT[] ="HoTT";
const char STR_FX816[] ="FX816"; const char STR_FX[] ="FX";
const char STR_BAYANG_RX[] ="BayanRX"; const char STR_BAYANG_RX[] ="BayanRX";
const char STR_PELIKAN[] ="Pelikan"; const char STR_PELIKAN[] ="Pelikan";
const char STR_TIGER[] ="Tiger"; const char STR_TIGER[] ="Tiger";
@@ -87,6 +88,7 @@ const char STR_FRSKYR9[] ="FrSkyR9";
const char STR_PROPEL[] ="Propel"; const char STR_PROPEL[] ="Propel";
const char STR_SKYARTEC[] ="Skyartc"; const char STR_SKYARTEC[] ="Skyartc";
const char STR_KYOSHO[] ="Kyosho"; const char STR_KYOSHO[] ="Kyosho";
const char STR_KYOSHO2[] ="Kyosho2";
const char STR_RLINK[] ="RadLink"; const char STR_RLINK[] ="RadLink";
const char STR_REALACC[] ="Realacc"; const char STR_REALACC[] ="Realacc";
const char STR_OMP[] ="OMP"; const char STR_OMP[] ="OMP";
@@ -110,7 +112,11 @@ const char STR_SUBTYPE_FRSKYD[] = "\x06""D8\0 ""Cloned";
const char STR_SUBTYPE_FRSKYX[] = "\x07""D16\0 ""D16 8ch""LBT(EU)""LBT 8ch""Cloned\0""Clo 8ch"; const char STR_SUBTYPE_FRSKYX[] = "\x07""D16\0 ""D16 8ch""LBT(EU)""LBT 8ch""Cloned\0""Clo 8ch";
const char STR_SUBTYPE_HISKY[] = "\x05""Std\0 ""HK310"; const char STR_SUBTYPE_HISKY[] = "\x05""Std\0 ""HK310";
const char STR_SUBTYPE_V2X2[] = "\x06""Std\0 ""JXD506""MR101\0"; const char STR_SUBTYPE_V2X2[] = "\x06""Std\0 ""JXD506""MR101\0";
const char STR_SUBTYPE_DSM[] = "\x04""2 1F""2 2F""X 1F""X 2F""Auto""R 1F"; #ifndef MULTI_EU
const char STR_SUBTYPE_DSM[] = "\x04""2 1F""2 2F""X 1F""X 2F""Auto""R 1F";
#else
const char STR_SUBTYPE_DSM[] = "\x04""--->""--->""X 1F""X 2F""Auto""R 1F";
#endif
const char STR_SUBTYPE_DEVO[] = "\x04""8ch\0""10ch""12ch""6ch\0""7ch\0"; const char STR_SUBTYPE_DEVO[] = "\x04""8ch\0""10ch""12ch""6ch\0""7ch\0";
const char STR_SUBTYPE_YD717[] = "\x07""Std\0 ""SkyWlkr""Syma X4""XINXUN\0""NIHUI\0 "; const char STR_SUBTYPE_YD717[] = "\x07""Std\0 ""SkyWlkr""Syma X4""XINXUN\0""NIHUI\0 ";
const char STR_SUBTYPE_KN[] = "\x06""WLtoys""FeiLun"; const char STR_SUBTYPE_KN[] = "\x06""WLtoys""FeiLun";
@@ -120,6 +126,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_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_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_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_MJXQ[] = "\x07""WLH08\0 ""X600\0 ""X800\0 ""H26D\0 ""E010\0 ""H26WH\0 ""Phoenix";
const char STR_SUBTYPE_FY326[] = "\x05""Std\0 ""FY319"; const char STR_SUBTYPE_FY326[] = "\x05""Std\0 ""FY319";
const char STR_SUBTYPE_HONTAI[] = "\x07""Std\0 ""JJRC X1""X5C1\0 ""FQ_951"; const char STR_SUBTYPE_HONTAI[] = "\x07""Std\0 ""JJRC X1""X5C1\0 ""FQ_951";
@@ -139,7 +146,6 @@ const char STR_SUBTYPE_REDPINE[] = "\x04""Fast""Slow";
const char STR_SUBTYPE_POTENSIC[] = "\x03""A20"; const char STR_SUBTYPE_POTENSIC[] = "\x03""A20";
const char STR_SUBTYPE_ZSX[] = "\x07""280JJRC"; const char STR_SUBTYPE_ZSX[] = "\x07""280JJRC";
const char STR_SUBTYPE_HEIGHT[] = "\x03""5ch""8ch"; 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_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_ESKY150[] = "\x03""4ch""7ch";
const char STR_SUBTYPE_ESKY150V2[] = "\x05""150V2"; const char STR_SUBTYPE_ESKY150V2[] = "\x05""150V2";
@@ -153,15 +159,17 @@ const char STR_SUBTYPE_WFLY[] = "\x05""WFR0x";
const char STR_SUBTYPE_WFLY2[] = "\x05""RF20x"; const char STR_SUBTYPE_WFLY2[] = "\x05""RF20x";
const char STR_SUBTYPE_HOTT[] = "\x07""Sync\0 ""No_Sync"; const char STR_SUBTYPE_HOTT[] = "\x07""Sync\0 ""No_Sync";
const char STR_SUBTYPE_PELIKAN[] = "\x05""Pro\0 ""Lite\0""SCX24"; const char STR_SUBTYPE_PELIKAN[] = "\x05""Pro\0 ""Lite\0""SCX24";
const char STR_SUBTYPE_V761[] = "\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_RLINK[] = "\x07""Surface""Air\0 ""DumboRC";
const char STR_SUBTYPE_REALACC[] = "\x03""R11"; const char STR_SUBTYPE_REALACC[] = "\x03""R11";
const char STR_SUBTYPE_KYOSHO[] = "\x04""FHSS""Hype"; const char STR_SUBTYPE_KYOSHO[] = "\x04""FHSS""Hype";
const char STR_SUBTYPE_KYOSHO2[] = "\x05""KT-17";
const char STR_SUBTYPE_FUTABA[] = "\x05""SFHSS"; const char STR_SUBTYPE_FUTABA[] = "\x05""SFHSS";
const char STR_SUBTYPE_JJRC345[] = "\x08""JJRC345\0""SkyTmblr"; const char STR_SUBTYPE_JJRC345[] = "\x08""JJRC345\0""SkyTmblr";
const char STR_SUBTYPE_MOULKG[] = "\x06""Analog""Digit\0"; const char STR_SUBTYPE_MOULKG[] = "\x06""Analog""Digit\0";
const char STR_SUBTYPE_KF606[] = "\x06""KF606\0""MIG320"; const char STR_SUBTYPE_KF606[] = "\x06""KF606\0""MIG320";
const char STR_SUBTYPE_E129[] = "\x04""E129""C186";
const char STR_SUBTYPE_FX[] = "\x03""816""620";
#define NO_SUBTYPE nullptr #define NO_SUBTYPE nullptr
#ifdef SEND_CPPM #ifdef SEND_CPPM
@@ -251,7 +259,7 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_E01X, STR_E01X, STR_SUBTYPE_E01X, 2, OPTION_NONE, 0, 0, SW_CYRF, E01X_init, E01X_callback }, {PROTO_E01X, STR_E01X, STR_SUBTYPE_E01X, 2, OPTION_NONE, 0, 0, SW_CYRF, E01X_init, E01X_callback },
#endif #endif
#if defined(E129_CYRF6936_INO) #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 #endif
#if defined(ESKY_NRF24L01_INO) #if defined(ESKY_NRF24L01_INO)
{PROTO_ESKY, STR_ESKY, STR_SUBTYPE_ESKY, 2, OPTION_NONE, 0, 1, SW_NRF, ESKY_init, ESKY_callback }, {PROTO_ESKY, STR_ESKY, STR_SUBTYPE_ESKY, 2, OPTION_NONE, 0, 1, SW_NRF, ESKY_init, ESKY_callback },
@@ -302,8 +310,8 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(FUTABA_CC2500_INO) #if defined(FUTABA_CC2500_INO)
{PROTO_FUTABA, STR_FUTABA, STR_SUBTYPE_FUTABA, 1, OPTION_RFTUNE, 1, 1, SW_CC2500, SFHSS_init, SFHSS_callback }, {PROTO_FUTABA, STR_FUTABA, STR_SUBTYPE_FUTABA, 1, OPTION_RFTUNE, 1, 1, SW_CC2500, SFHSS_init, SFHSS_callback },
#endif #endif
#if defined(FX816_NRF24L01_INO) #if defined(FX_NRF24L01_INO)
{PROTO_FX816, STR_FX816, STR_SUBTYPE_FX816, 1, OPTION_NONE, 0, 0, SW_NRF, FX816_init, FX816_callback }, {PROTO_FX, STR_FX, STR_SUBTYPE_FX, 2, OPTION_NONE, 0, 0, SW_NRF, FX_init, FX_callback },
#endif #endif
#if defined(FY326_NRF24L01_INO) #if defined(FY326_NRF24L01_INO)
{PROTO_FY326, STR_FY326, STR_SUBTYPE_FY326, 2, OPTION_NONE, 0, 0, SW_NRF, FY326_init, FY326_callback }, {PROTO_FY326, STR_FY326, STR_SUBTYPE_FY326, 2, OPTION_NONE, 0, 0, SW_NRF, FY326_init, FY326_callback },
@@ -356,6 +364,9 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(KYOSHO_A7105_INO) #if defined(KYOSHO_A7105_INO)
{PROTO_KYOSHO, STR_KYOSHO, STR_SUBTYPE_KYOSHO, 2, OPTION_NONE, 0, 1, SW_A7105, KYOSHO_init, KYOSHO_callback }, {PROTO_KYOSHO, STR_KYOSHO, STR_SUBTYPE_KYOSHO, 2, OPTION_NONE, 0, 1, SW_A7105, KYOSHO_init, KYOSHO_callback },
#endif #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) #if defined(LOLI_NRF24L01_INO)
{PROTO_LOLI, STR_LOLI, NO_SUBTYPE, 0, OPTION_NONE, 1, 0, SW_NRF, LOLI_init, LOLI_callback }, {PROTO_LOLI, STR_LOLI, NO_SUBTYPE, 0, OPTION_NONE, 1, 0, SW_NRF, LOLI_init, LOLI_callback },
#endif #endif
@@ -374,6 +385,9 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(MT99XX_CCNRF_INO) #if defined(MT99XX_CCNRF_INO)
{PROTO_MT99XX, STR_MT99XX, STR_SUBTYPE_MT99, 8, OPTION_NONE, 0, 0, SW_NRF, MT99XX_init, MT99XX_callback }, {PROTO_MT99XX, STR_MT99XX, STR_SUBTYPE_MT99, 8, OPTION_NONE, 0, 0, SW_NRF, MT99XX_init, MT99XX_callback },
#endif #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) #if defined(NCC1701_NRF24L01_INO)
{PROTO_NCC1701, STR_NCC1701, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, NCC_init, NCC_callback }, {PROTO_NCC1701, STR_NCC1701, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, NCC_init, NCC_callback },
#endif #endif
@@ -432,7 +446,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 }, {PROTO_V2X2, STR_V2X2, STR_SUBTYPE_V2X2, 3, OPTION_NONE, 0, 0, SW_NRF, V2X2_init, V2X2_callback },
#endif #endif
#if defined(V761_NRF24L01_INO) #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 #endif
#if defined(V911S_CCNRF_INO) #if defined(V911S_CCNRF_INO)
{PROTO_V911S, STR_V911S, STR_SUBTYPE_V911S, 2, OPTION_RFTUNE, 0, 0, SW_NRF, V911S_init, V911S_callback }, {PROTO_V911S, STR_V911S, STR_SUBTYPE_V911S, 2, OPTION_RFTUNE, 0, 0, SW_NRF, V911S_init, V911S_callback },

View File

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

View File

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

View File

@@ -17,7 +17,7 @@
#define RF2500_ADDR_LENGTH 4 #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; bool RF2500_scramble_enabled;
static void __attribute__((unused)) RF2500_Init(uint8_t payload_length, bool scramble) 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) 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 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
const uint16_t RF2500_crc_xorout_scramble = 0xAEE4; 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 //Scramble the incoming buffer
if(RF2500_scramble_enabled) if(RF2500_scramble_enabled)
for(uint8_t i=0; i<RF2500_payload_length; i++) 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 ] = bit_reverse(crc>>8);
buffer[RF2500_payload_length+1] = bit_reverse(crc); 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) if(RF2500_scramble_enabled)
{ {
buffer[RF2500_payload_length ] ^= RF2500_crc_xorout_scramble>>8; buffer[RF2500_payload_length ] ^= RF2500_crc_xorout_scramble>>8;

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

View File

@@ -241,22 +241,27 @@
#endif #endif
//Make sure protocols are selected correctly //Make sure protocols are selected correctly
#ifndef A7105_INSTALLED #if not defined(A7105_INSTALLED) || defined MULTI_EU
#undef AFHDS2A_A7105_INO #undef AFHDS2A_A7105_INO
#undef AFHDS2A_RX_A7105_INO #if not defined(A7105_INSTALLED)
#undef BUGS_A7105_INO #undef AFHDS2A_RX_A7105_INO
#undef FLYSKY_A7105_INO #endif
#undef HEIGHT_A7105_INO #undef BUGS_A7105_INO
#undef HUBSAN_A7105_INO #undef FLYSKY_A7105_INO
#undef JOYSWAY_A7105_INO #undef HEIGHT_A7105_INO
#undef KYOSHO_A7105_INO #undef HUBSAN_A7105_INO
#undef PELIKAN_A7105_INO #undef JOYSWAY_A7105_INO
#undef WFLY2_A7105_INO #undef KYOSHO_A7105_INO
#undef PELIKAN_A7105_INO
#undef WFLY2_A7105_INO
#endif #endif
#ifndef CYRF6936_INSTALLED
#if not defined(CYRF6936_INSTALLED) || defined MULTI_EU
#undef DEVO_CYRF6936_INO #undef DEVO_CYRF6936_INO
#undef DSM_CYRF6936_INO #if not defined(CYRF6936_INSTALLED)
#undef DSM_RX_CYRF6936_INO #undef DSM_CYRF6936_INO
#undef DSM_RX_CYRF6936_INO
#endif
#undef E010R5_CYRF6936_INO #undef E010R5_CYRF6936_INO
#undef E01X_CYRF6936_INO #undef E01X_CYRF6936_INO
#undef E129_CYRF6936_INO #undef E129_CYRF6936_INO
@@ -267,28 +272,38 @@
#undef WFLY_CYRF6936_INO #undef WFLY_CYRF6936_INO
#undef WK2x01_CYRF6936_INO #undef WK2x01_CYRF6936_INO
#endif #endif
#ifndef CC2500_INSTALLED
#if not defined(CC2500_INSTALLED) || defined MULTI_EU
#undef CORONA_CC2500_INO #undef CORONA_CC2500_INO
#undef E016HV2_CC2500_INO #undef E016HV2_CC2500_INO
#undef ESKY150V2_CC2500_INO #undef ESKY150V2_CC2500_INO
#undef FRSKYD_CC2500_INO #undef FRSKYD_CC2500_INO
#undef FRSKYL_CC2500_INO #undef FRSKYL_CC2500_INO
#undef FRSKYV_CC2500_INO #undef FRSKYV_CC2500_INO
#undef FRSKYX_CC2500_INO #if not defined(CC2500_INSTALLED)
#undef FRSKY_RX_CC2500_INO #undef FRSKYX_CC2500_INO
#undef FRSKY_RX_CC2500_INO
#endif
#undef HITEC_CC2500_INO #undef HITEC_CC2500_INO
#undef HOTT_CC2500_INO #if not defined(CC2500_INSTALLED)
#undef HOTT_CC2500_INO
#endif
#undef IKEAANSLUTA_CC2500_INO #undef IKEAANSLUTA_CC2500_INO
#undef REDPINE_CC2500_INO #undef REDPINE_CC2500_INO
#undef RLINK_CC2500_INO #undef RLINK_CC2500_INO
#undef SCANNER_CC2500_INO #if not defined(CC2500_INSTALLED)
#undef SCANNER_CC2500_INO
#endif
#undef FUTABA_CC2500_INO #undef FUTABA_CC2500_INO
#undef SKYARTEC_CC2500_INO #undef SKYARTEC_CC2500_INO
#endif #endif
#ifndef NRF24L01_INSTALLED
#if not defined(NRF24L01_INSTALLED) || defined MULTI_EU
#undef ASSAN_NRF24L01_INO #undef ASSAN_NRF24L01_INO
#undef BAYANG_NRF24L01_INO #undef BAYANG_NRF24L01_INO
#undef BAYANG_RX_NRF24L01_INO #if not defined(NRF24L01_INSTALLED)
#undef BAYANG_RX_NRF24L01_INO
#endif
#undef BUGSMINI_NRF24L01_INO #undef BUGSMINI_NRF24L01_INO
#undef CABELL_NRF24L01_INO #undef CABELL_NRF24L01_INO
#undef CFLIE_NRF24L01_INO #undef CFLIE_NRF24L01_INO
@@ -299,7 +314,7 @@
#undef ESKY_NRF24L01_INO #undef ESKY_NRF24L01_INO
#undef ESKY150_NRF24L01_INO #undef ESKY150_NRF24L01_INO
#undef FQ777_NRF24L01_INO #undef FQ777_NRF24L01_INO
#undef FX816_NRF24L01_INO #undef FX_NRF24L01_INO
#undef FY326_NRF24L01_INO #undef FY326_NRF24L01_INO
#undef GW008_NRF24L01_INO #undef GW008_NRF24L01_INO
#undef H8_3D_NRF24L01_INO #undef H8_3D_NRF24L01_INO
@@ -307,6 +322,7 @@
#undef HONTAI_NRF24L01_INO #undef HONTAI_NRF24L01_INO
#undef JJRC345_NRF24L01_INO #undef JJRC345_NRF24L01_INO
#undef KN_NRF24L01_INO #undef KN_NRF24L01_INO
#undef KYOSHO2_NRF24L01_INO
#undef LOLI_NRF24L01_INO #undef LOLI_NRF24L01_INO
#undef MOULDKG_NRF24L01_INO #undef MOULDKG_NRF24L01_INO
#undef NCC1701_NRF24L01_INO #undef NCC1701_NRF24L01_INO
@@ -322,7 +338,7 @@
#undef YD717_NRF24L01_INO #undef YD717_NRF24L01_INO
#undef ZSX_NRF24L01_INO #undef ZSX_NRF24L01_INO
#endif #endif
#if not defined(CC2500_INSTALLED) && not defined(NRF24L01_INSTALLED) #if ( not defined(CC2500_INSTALLED) && not defined(NRF24L01_INSTALLED) ) || defined MULTI_EU
#undef GD00X_CCNRF_INO #undef GD00X_CCNRF_INO
#undef KF606_CCNRF_INO #undef KF606_CCNRF_INO
#undef MJXQ_CCNRF_INO #undef MJXQ_CCNRF_INO
@@ -342,7 +358,7 @@
#if not defined(STM32_BOARD) #if not defined(STM32_BOARD)
#undef SX1276_INSTALLED #undef SX1276_INSTALLED
#endif #endif
#ifndef SX1276_INSTALLED #ifndef SX1276_INSTALLED || defined MULTI_EU
#undef FRSKYR9_SX1276_INO #undef FRSKYR9_SX1276_INO
#endif #endif

View File

@@ -609,12 +609,12 @@ static uint16_t XN297Dump_callback()
{ {
if(phase==0) if(phase==0)
{ {
address_length=5; address_length=3;
memcpy(rx_tx_addr, (uint8_t *)"\x61\x94\x17\x27\xED", address_length); //"\xA3\x05\x22\xC1""\x5A\x20\x12\xAC" memcpy(rx_tx_addr, (uint8_t *)"\xBD\x54\x78", address_length); //"\x62\xE6\xBD\x54\x78"
bitrate=XN297DUMP_250K; bitrate=XN297DUMP_1M;
packet_length=32; packet_length=7;
hopping_frequency_no=54; //bind ?, normal 60 hopping_frequency_no=40; //bind ?, normal 40
NRF24L01_Initialize(); NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TXRX_OFF); 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_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_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_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); debug("NRF dump, len=%d, rf=%d, address length=%d, bitrate=",packet_length,hopping_frequency_no,address_length);
switch(bitrate) switch(bitrate)
@@ -718,6 +718,7 @@ static uint16_t XN297Dump_callback()
NRF24L01_FlushRx(); 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_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) else if(sub_protocol == XN297DUMP_CC2500)

View File

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

View File

@@ -76,11 +76,11 @@ CFlie|38|CFlie||||||||NRF24L01|
[DM002](Protocols_Details.md#DM002---33)|33|||||||||NRF24L01|XN297 [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](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| [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 [E016H](Protocols_Details.md#E016H---85)|85|||||||||NRF24L01|XN297
[E016HV2](Protocols_Details.md#E016HV2---80)|80|||||||||CC2500/NRF24L01|unknown [E016HV2](Protocols_Details.md#E016HV2---80)|80|||||||||CC2500/NRF24L01|unknown
[E01X](Protocols_Details.md#E01X---45)|45|E012|E015|||||||CYRF6936|HS6200 [E01X](Protocols_Details.md#E01X---45)|45|E012|E015|||||||CYRF6936|HS6200
[E129](Protocols_Details.md#E129---83)|83|||||||||CYRF6936/NRF24L01|RF2500 [E129](Protocols_Details.md#E129---83)|83|E129|C186|||||||CYRF6936|RF2500
[ESky](Protocols_Details.md#ESKY---16)|16|ESky|ET4|||||||NRF24L01| [ESky](Protocols_Details.md#ESKY---16)|16|ESky|ET4|||||||NRF24L01|
[ESky150](Protocols_Details.md#ESKY150---35)|35|||||||||NRF24L01| [ESky150](Protocols_Details.md#ESKY150---35)|35|||||||||NRF24L01|
[ESky150V2](Protocols_Details.md#ESKY150V2---69)|69|||||||||CC2500|NRF51822 [ESky150V2](Protocols_Details.md#ESKY150V2---69)|69|||||||||CC2500|NRF51822
@@ -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| [FrskyX2](Protocols_Details.md#FRSKYX2---64)|64|CH_16|CH_8|EU_16|EU_8|Cloned|Cloned_8|||CC2500|
[Frsky_RX](Protocols_Details.md#FRSKY_RX---55)|55|Multi|CloneTX|EraseTX|CPPM|||||CC2500| [Frsky_RX](Protocols_Details.md#FRSKY_RX---55)|55|Multi|CloneTX|EraseTX|CPPM|||||CC2500|
[Futaba/SFHSS](Protocols_Details.md#Futaba---21)|21|SFHSS||||||||CC2500| [Futaba/SFHSS](Protocols_Details.md#Futaba---21)|21|SFHSS||||||||CC2500|
[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| [FY326](Protocols_Details.md#FY326---20)|20|FY326|FY319|||||||NRF24L01|
[GD00X](Protocols_Details.md#GD00X---47)|47|GD_V1*|GD_V2*|||||||NRF24L01|XN297L [GD00X](Protocols_Details.md#GD00X---47)|47|GD_V1*|GD_V2*|||||||NRF24L01|XN297L
[GW008](Protocols_Details.md#GW008---32)|32|||||||||NRF24L01|XN297 [GW008](Protocols_Details.md#GW008---32)|32|||||||||NRF24L01|XN297
@@ -113,12 +113,14 @@ CFlie|38|CFlie||||||||NRF24L01|
[KF606](Protocols_Details.md#KF606---49)|49|KF606|MIG320|||||||NRF24L01|XN297 [KF606](Protocols_Details.md#KF606---49)|49|KF606|MIG320|||||||NRF24L01|XN297
[KN](Protocols_Details.md#KN---9)|9|WLTOYS|FEILUN|||||||NRF24L01| [KN](Protocols_Details.md#KN---9)|9|WLTOYS|FEILUN|||||||NRF24L01|
[Kyosho](Protocols_Details.md#Kyosho---73)|73|FHSS|Hype|||||||A7105| [Kyosho](Protocols_Details.md#Kyosho---73)|73|FHSS|Hype|||||||A7105|
[Kyosho2](Protocols_Details.md#Kyosho2---93)|93|KT-17||||||||NRF24L01|
[LOLI](Protocols_Details.md#LOLI---82)|82|||||||||NRF24L01| [LOLI](Protocols_Details.md#LOLI---82)|82|||||||||NRF24L01|
[Losi](Protocols_Details.md#Losi---89)|89|||||||||CYRF6936| [Losi](Protocols_Details.md#Losi---89)|89|||||||||CYRF6936|
[MJXq](Protocols_Details.md#MJXQ---18)|18|WLH08|X600|X800|H26D|E010*|H26WH|PHOENIX*||NRF24L01|XN297 [MJXq](Protocols_Details.md#MJXQ---18)|18|WLH08|X600|X800|H26D|E010*|H26WH|PHOENIX*||NRF24L01|XN297
[MLINK](Protocols_Details.md#MLINK---78)|78|||||||||CYRF6936| [MLINK](Protocols_Details.md#MLINK---78)|78|||||||||CYRF6936|
[MouldKg](Protocols_Details.md#mouldkg---90)|90|Analog|Digit|||||||NRF24L01|XN297 [MouldKg](Protocols_Details.md#mouldkg---90)|90|Analog|Digit|||||||NRF24L01|XN297
[MT99xx](Protocols_Details.md#MT99XX---17)|17|MT|H7|YZ|LS|FY805|A180|DRAGON|F949G|NRF24L01|XN297 [MT99xx](Protocols_Details.md#MT99XX---17)|17|MT|H7|YZ|LS|FY805|A180|DRAGON|F949G|NRF24L01|XN297
[MT99xx2](Protocols_Details.md#MT99XX2---92)|92|PA18||||||||NRF24L01|XN297
[NCC1701](Protocols_Details.md#NCC1701---44)|44|||||||||NRF24L01| [NCC1701](Protocols_Details.md#NCC1701---44)|44|||||||||NRF24L01|
[OMP](Protocols_Details.md#OMP---77)|77|||||||||CC2500&NRF24L01|XN297L [OMP](Protocols_Details.md#OMP---77)|77|||||||||CC2500&NRF24L01|XN297L
[OpenLRS](Protocols_Details.md#OpenLRS---27)|27|||||||||None| [OpenLRS](Protocols_Details.md#OpenLRS---27)|27|||||||||None|
@@ -139,7 +141,7 @@ CFlie|38|CFlie||||||||NRF24L01|
[Tiger](Protocols_Details.md#Tiger---61)|61|||||||||NRF24L01|XN297 [Tiger](Protocols_Details.md#Tiger---61)|61|||||||||NRF24L01|XN297
[Traxxas](Protocols_Details.md#Traxxas---43)|43|6519 RX||||||||CYRF6936| [Traxxas](Protocols_Details.md#Traxxas---43)|43|6519 RX||||||||CYRF6936|
[V2x2](Protocols_Details.md#V2X2---5)|5|V2x2|JXD506|MR101||||||NRF24L01| [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 [V911S](Protocols_Details.md#V911S---46)|46|V911S*|E119*|||||||NRF24L01|XN297
[WFLY](Protocols_Details.md#WFLY---40)|40|WFR0x||||||||CYRF6936| [WFLY](Protocols_Details.md#WFLY---40)|40|WFR0x||||||||CYRF6936|
[WFLY2](Protocols_Details.md#WFLY2---79)|79|RF20x||||||||A7105| [WFLY2](Protocols_Details.md#WFLY2---79)|79|RF20x||||||||A7105|
@@ -526,7 +528,7 @@ DSMX, Resolution 2048, servo refresh rate can only be 22ms
### Sub_protocol DSMX_2F - *3* ### Sub_protocol DSMX_2F - *3*
DSMX, Resolution 2048, servo refresh rate can be 22 or 11ms. 11ms won't be available on all servo outputs when more than 7 channels are used. DSMX, Resolution 2048, servo refresh rate can be 22 or 11ms. 11ms won't be available on all servo outputs when more than 7 channels are used.
### Sub_protocol AUTO - *4* ### Sub_protocol AUTO - *4*
"AUTO" is recommended to automatically select the best settings for your DSM RX. "AUTO" is recommended to automatically select the best settings for your DSM2 and DSMX RXs.
### Sub_protocol DSMR_1F - *5* ### Sub_protocol DSMR_1F - *5*
DSMR receivers DSMR receivers
@@ -596,9 +598,8 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
A|E|T|R|ARM|FLIP|LED|HEADLESS|RTH A|E|T|R|ARM|FLIP|LED|HEADLESS|RTH
## E129 - *83* ## E129 - *83*
Models: Eachine E129/E130 and Twister Ninja 250
Not supported by Atmega328p modules. **Not supported by Atmega328p modules.**
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9 CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|--- ---|---|---|---|---|---|---|---|---
@@ -610,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. 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* ## J6Pro - *22*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12 CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
@@ -976,15 +985,17 @@ Compatible RXs: X6/X6F/X6FG
Also called SFHSS depending on radio version. Also called SFHSS depending on radio version.
### Sub_protocol SFHSS - *0* ### 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. 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. 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. 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 CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|--- ---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8 A|E|T|R|CH5|CH6|CH7|CH8
@@ -1024,16 +1035,20 @@ New generation of GD models
## KF606 - *49* ## KF606 - *49*
### Sub_protocol KF606 - *0*
Model: KF606
CH1|CH2|CH3|CH4|CH5 CH1|CH2|CH3|CH4|CH5
---|---|---|---|--- ---|---|---|---|---
A||T||TRIM A||T||TRIM
### Sub_protocol KF606 - *0*
Model: KF606
### Sub_protocol MIG320 - *1* ### Sub_protocol MIG320 - *1*
Model: Zhiyang MIG-320 Model: Zhiyang MIG-320
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A||T||TRIM|LED
## MJXQ - *18* ## MJXQ - *18*
Autobind protocol Autobind protocol
@@ -1115,7 +1130,7 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
A|E|T|R|FLIP||||HEADLESS A|E|T|R|FLIP||||HEADLESS
### Sub_protocol A180 - *5* ### Sub_protocol A180 - *5*
Model: XK A180, F949S Model: XK A180, F949S, F959
A180: A180:
CH1|CH2|CH3|CH4|CH5|CH6 CH1|CH2|CH3|CH4|CH5|CH6
@@ -1145,6 +1160,17 @@ CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|--- ---|---|---|---|---|---
A|E|T|R|6G3D|Light 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* ## OMP - *77*
Model: OMPHOBBY M1 & M2 Helis, T720 RC Glider Model: OMPHOBBY M1 & M2 Helis, T720 RC Glider
@@ -1312,7 +1338,7 @@ Rate: -100% High, +100% Low
Models: WLtoys V911S, XK A110 Models: WLtoys V911S, XK A110
### Sub_protocol E119 - *1* ### Sub_protocol E119 - *1*
Models: Eachine E119, JJRC W01-J3, XK A220 P-40, newer XK A800 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 CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|--- ---|---|---|---|---|---|---
@@ -1575,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 FMODE and AUX7 have 4 positions: -100%..-50%=>0, -50%..5%=>1, 5%..50%=>2, 50%..100%=>3
## FX816 - *58* ## FX - *58*
Model: FEI XIONG FX816 P38 FEI XIONG
Only 8 TX IDs available
CH1|CH2|CH3|CH4 CH1|CH2|CH3|CH4
---|---|---|--- ---|---|---|---
A|-|T|- A|-|T|-
### Sub_protocol 816 - *0*
Model: FX816 P38, B17
Only 8 TX IDs available
### Sub_protocol 620 - *1*
Model: FX620 SU35
## FY326 - *20* ## FY326 - *20*
### Sub_protocol FY326 - *0* ### Sub_protocol FY326 - *0*
@@ -1616,7 +1648,7 @@ A|E|T|R|FLIP
Autobind protocol Autobind protocol
### Sub_protocol H8_3D - *0* ### 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 CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
---|---|---|---|---|---|---|---|--- ---|---|---|---|---|---|---|---|---
@@ -1700,6 +1732,13 @@ Model: DF-Models SkyTumbler
RTH not supported 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* ## LOLI - *82*
LOLI3 receivers: https://github.com/wooddoor/Loli3 LOLI3 receivers: https://github.com/wooddoor/Loli3
@@ -1903,7 +1942,7 @@ A|E|T|R|FLIP|LIGHT
## V761 - *48* ## 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% Calib: momentary switch, calib will happen one the channel goes from -100% to +100%
@@ -1912,14 +1951,21 @@ Flip: momentary switch: hold flip(+100%), indicate flip direction with Ele or Ai
RTN_ACT and RTN: -100% disable, +100% enable RTN_ACT and RTN: -100% disable, +100% enable
### Sub_protocol 3CH - *0* ### 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 CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|--- ---|---|---|---|---|---|---|---|---
-|E|T|R|GYRO|CALIB|FLIP|RTN_ACT|RTN -|E|T|R|GYRO|CALIB|FLIP|RTN_ACT|RTN
### Sub_protocol 4CH - *1* ### 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 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: 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 - 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? # How to get started?
1. Browse the [Protocols](Protocols_Details.md) page to see which protocols you would like on your module 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. 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. 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. 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 # 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. 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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,130 @@
(kicad_symbol_lib (version 20211014) (generator kicad_symbol_editor)
(symbol "MULTIRF4IN1SMT" (in_bom yes) (on_board yes)
(property "Reference" "M" (id 0) (at -12.7 21.59 0)
(effects (font (size 1.27 1.0795)) (justify left bottom))
)
(property "Value" "MULTIRF4IN1SMT" (id 1) (at -12.7 -16.51 0)
(effects (font (size 1.778 1.5113)) (justify left top))
)
(property "Footprint" "Multi:MULTIRF4IN1-SMT" (id 2) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "" (id 3) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(symbol "MULTIRF4IN1SMT_1_0"
(polyline
(pts
(xy -12.7 -15.24)
(xy 12.7 -15.24)
)
(stroke (width 0.254) (type default) (color 0 0 0 0))
(fill (type none))
)
(polyline
(pts
(xy -12.7 20.32)
(xy -12.7 -15.24)
)
(stroke (width 0.254) (type default) (color 0 0 0 0))
(fill (type none))
)
(polyline
(pts
(xy 12.7 -15.24)
(xy 12.7 20.32)
)
(stroke (width 0.254) (type default) (color 0 0 0 0))
(fill (type none))
)
(polyline
(pts
(xy 12.7 20.32)
(xy -12.7 20.32)
)
(stroke (width 0.254) (type default) (color 0 0 0 0))
(fill (type none))
)
(pin bidirectional line (at 15.24 17.78 180) (length 2.54)
(name "CE_2401" (effects (font (size 1.27 1.27))))
(number "CE_2401" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 2.54 180) (length 2.54)
(name "CS_2401" (effects (font (size 1.27 1.27))))
(number "CS_2401" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 0 180) (length 2.54)
(name "CS_2500" (effects (font (size 1.27 1.27))))
(number "CS_2500" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 5.08 180) (length 2.54)
(name "CS_6936" (effects (font (size 1.27 1.27))))
(number "CS_6936" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 -2.54 180) (length 2.54)
(name "CS_7105" (effects (font (size 1.27 1.27))))
(number "CS_7105" (effects (font (size 0 0))))
)
(pin power_in line (at 15.24 -10.16 180) (length 2.54)
(name "GND" (effects (font (size 1.27 1.27))))
(number "GND" (effects (font (size 0 0))))
)
(pin power_in line (at -15.24 17.78 0) (length 2.54)
(name "GND@1" (effects (font (size 1.27 1.27))))
(number "GND@1" (effects (font (size 0 0))))
)
(pin power_in line (at -15.24 15.24 0) (length 2.54)
(name "GND@2" (effects (font (size 1.27 1.27))))
(number "GND@2" (effects (font (size 0 0))))
)
(pin power_in line (at -15.24 5.08 0) (length 2.54)
(name "GND@3" (effects (font (size 1.27 1.27))))
(number "GND@3" (effects (font (size 0 0))))
)
(pin power_in line (at -15.24 0 0) (length 2.54)
(name "GND@4" (effects (font (size 1.27 1.27))))
(number "GND@4" (effects (font (size 0 0))))
)
(pin power_in line (at -15.24 -10.16 0) (length 2.54)
(name "GND@5" (effects (font (size 1.27 1.27))))
(number "GND@5" (effects (font (size 0 0))))
)
(pin power_in line (at -15.24 -12.7 0) (length 2.54)
(name "GND@6" (effects (font (size 1.27 1.27))))
(number "GND@6" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 12.7 180) (length 2.54)
(name "MISO" (effects (font (size 1.27 1.27))))
(number "MISO" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 10.16 180) (length 2.54)
(name "MOSI" (effects (font (size 1.27 1.27))))
(number "MOSI" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 -7.62 180) (length 2.54)
(name "PE1" (effects (font (size 1.27 1.27))))
(number "PE1" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 -5.08 180) (length 2.54)
(name "PE2" (effects (font (size 1.27 1.27))))
(number "PE2" (effects (font (size 0 0))))
)
(pin output line (at -15.24 2.54 0) (length 2.54)
(name "RF" (effects (font (size 1.27 1.27))))
(number "RF" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 15.24 180) (length 2.54)
(name "RST_CYFR" (effects (font (size 1.27 1.27))))
(number "RST_CYFR" (effects (font (size 0 0))))
)
(pin bidirectional line (at 15.24 7.62 180) (length 2.54)
(name "SCK" (effects (font (size 1.27 1.27))))
(number "SCK" (effects (font (size 0 0))))
)
(pin power_in line (at 15.24 -12.7 180) (length 2.54)
(name "VCC" (effects (font (size 1.27 1.27))))
(number "VCC" (effects (font (size 0 0))))
)
)
)
)

View File

@@ -0,0 +1,42 @@
(footprint "DS-B01F-A-S2" (version 20211014) (generator pcbnew)
(layer "F.Cu")
(tedit 59FED5CC)
(descr "Through hole straight pin header, 1x05, 2.54mm pitch, single row")
(tags "Through hole pin header THT 1x05 2.54mm single row")
(attr through_hole)
(fp_text reference "REF**" (at -0.25 -4.75) (layer "F.SilkS")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp d518c7db-9a4d-4905-902c-7b6d95f659cb)
)
(fp_text value "DS-B01F-A-S2" (at 0 12.49) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 614f538e-5f2b-401d-b0ab-3346d3ff44e4)
)
(fp_text user "${REFERENCE}" (at 0 5.08 90) (layer "F.Fab")
(effects (font (size 1 1) (thickness 0.15)))
(tstamp 9586cda1-48da-45c7-86f7-751657e7c25a)
)
(fp_line (start -4.5 13.5) (end 1.25 13.5) (layer "F.SilkS") (width 0.12) (tstamp 05393a00-de07-40a8-8064-67c0a8a1e9ef))
(fp_line (start 1.25 -3.5) (end 1.25 13.5) (layer "F.SilkS") (width 0.12) (tstamp 09bf1fa9-9ec6-4d5c-bed9-fcd1fe76bd8e))
(fp_line (start -4.5 -3.5) (end 1.25 -3.5) (layer "F.SilkS") (width 0.12) (tstamp 2f1dd441-3cdc-4eed-9839-dc1fa6a931ba))
(fp_line (start -4.5 -3.5) (end -4.5 13.5) (layer "F.SilkS") (width 0.12) (tstamp 35bb1bb5-998b-4ce9-a139-e009425d4e40))
(fp_line (start -4.5 -3.5) (end -4.5 13.5) (layer "F.CrtYd") (width 0.05) (tstamp 346ee0d3-e13a-49f6-8f6c-eb860777d6c4))
(fp_line (start 1.25 13.5) (end 1.25 -3.5) (layer "F.CrtYd") (width 0.05) (tstamp 93808e54-10fb-4c6c-984b-3a91c36dbafa))
(fp_line (start 1.25 -3.5) (end -4.5 -3.5) (layer "F.CrtYd") (width 0.05) (tstamp d7a0888c-6be2-4a97-ac01-de345dcd2919))
(fp_line (start -4.5 13.5) (end 1.25 13.5) (layer "F.CrtYd") (width 0.05) (tstamp ee85719d-9f71-411e-a024-43105a50c262))
(fp_line (start -1.27 11.43) (end -1.27 -0.635) (layer "F.Fab") (width 0.1) (tstamp 085f4818-84f1-415f-823e-e6076d0e732d))
(fp_line (start -1.27 -0.635) (end -0.635 -1.27) (layer "F.Fab") (width 0.1) (tstamp 602c4495-9f5f-4ae3-9800-df18526e3c50))
(fp_line (start 1.27 -1.27) (end 1.27 11.43) (layer "F.Fab") (width 0.1) (tstamp 73eb4832-b804-463c-ae2b-563755d89978))
(fp_line (start -0.635 -1.27) (end 1.27 -1.27) (layer "F.Fab") (width 0.1) (tstamp aed66e63-a453-441e-94eb-3442ef294c72))
(fp_line (start 1.27 11.43) (end -1.27 11.43) (layer "F.Fab") (width 0.1) (tstamp dde86203-069d-47dc-8693-34fe614da099))
(pad "1" thru_hole rect (at 0 0) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask) (tstamp 174ecd2f-6484-485c-a83d-71d6a1dc733a))
(pad "2" thru_hole oval (at 0 2.5) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask) (tstamp 997a59d1-7e2b-4400-b74b-3cb21ad33038))
(pad "3" thru_hole oval (at 0 5) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask) (tstamp 7aa5c04b-5bd3-4c72-bbaf-9ec87c5447e0))
(pad "4" thru_hole oval (at 0 7.5) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask) (tstamp 8a6c42bd-bf44-40be-9e58-41dc76d10644))
(pad "5" thru_hole oval (at 0 10) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask) (tstamp c1741286-ba0e-4f33-8f37-5fd51504bac5))
(model "${KICAD6_3DMODEL_DIR}/Connector_PinHeader_2.54mm.3dshapes/PinHeader_1x05_P2.54mm_Vertical.wrl"
(offset (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)

View File

@@ -0,0 +1,60 @@
(footprint "MULTIRF4IN1-SMT" (version 20211014) (generator pcbnew)
(layer "F.Cu")
(tedit 0)
(fp_text reference "REF**" (at 0 -0.75) (layer "F.SilkS")
(effects (font (size 1.27 1.27) (thickness 0.15)))
(tstamp c70c9e03-6ffa-4ea8-9291-15d2673122a0)
)
(fp_text value "Val**" (at 0 1) (layer "F.Fab")
(effects (font (size 1.27 1.27) (thickness 0.15)))
(tstamp c3246ecf-81bc-4b14-94a2-7b86227cabaf)
)
(fp_line (start -13 11.9) (end -13 17) (layer "F.SilkS") (width 0.12) (tstamp 21d8aff3-5b17-43c7-9d08-4e33edbcbeb9))
(fp_line (start -13 3.4) (end -13 8.1) (layer "F.SilkS") (width 0.12) (tstamp 4a2c9e01-3f0b-4116-a39b-baa7e7b94b8a))
(fp_line (start -13 -8.1) (end -13 -2.4) (layer "F.SilkS") (width 0.12) (tstamp 960baeae-d7ca-4f76-ac15-6cd68f041702))
(fp_line (start 13 -17) (end 13 -13.9) (layer "F.SilkS") (width 0.12) (tstamp a22c44ee-0c9a-42e0-81e0-94f90a0da388))
(fp_line (start 13 11.9) (end 13 17) (layer "F.SilkS") (width 0.12) (tstamp a8050edb-a9eb-479e-abea-105077de87b8))
(fp_line (start -13 -17) (end -13 -11.9) (layer "F.SilkS") (width 0.12) (tstamp dbeb96d9-bbc7-4dae-ba00-6746209bdc43))
(fp_line (start 13 -17) (end -13 -17) (layer "F.SilkS") (width 0.12) (tstamp de173627-aedf-48e0-8674-66cfe17b969a))
(fp_line (start 13 17) (end -13 17) (layer "F.SilkS") (width 0.12) (tstamp edb180b5-b35e-4fa4-8440-d021574908ae))
(pad "CE_2401" smd rect (at 12.49 -13) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 177c8408-9b8a-453c-871a-7a335239833a))
(pad "CS_2401" smd rect (at 12.49 -1) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp deb3cbb7-c404-4161-b154-3014395e2a30))
(pad "CS_2500" smd rect (at 12.49 1) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp e8ecba2d-0746-43bc-b641-9cc180ff9253))
(pad "CS_6936" smd rect (at 12.49 -3) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 90314976-271d-4f34-b2f0-dff6de6b86e7))
(pad "CS_7105" smd rect (at 12.49 3) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 1f154bf6-42ea-456f-89ac-fed01ff7208b))
(pad "GND" smd rect (at 12.49 9) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 14373cb3-8424-453e-b0d3-1a6022ea35b1))
(pad "GND@1" smd rect (at -12.49 -11) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp b15a1378-3e57-41cb-96b2-030f4848402c))
(pad "GND@2" smd rect (at -12.49 -9) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 71e83330-d2fe-4680-bbc4-fbbb511ecf3d))
(pad "GND@3" smd rect (at -12.49 -1.5) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 27f29ad7-d4f7-416a-bc00-7c36c9ffbaca))
(pad "GND@4" smd rect (at -12.49 2.5) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 6b446947-9739-4960-abfc-ef89034a0437))
(pad "GND@5" smd rect (at -12.49 9) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 589b3137-9b71-4e00-93fe-63222c56ecc3))
(pad "GND@6" smd rect (at -12.49 11) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 371c3d69-e48f-46fb-a1b6-b681b17bacb1))
(pad "MISO" smd rect (at 12.49 -9) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp a1ef8d67-bdf4-443e-88f7-406670c2aef9))
(pad "MOSI" smd rect (at 12.49 -7) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp d9f5d5e2-2571-4cc2-800c-f5758bd5695f))
(pad "PE1" smd rect (at 12.49 7) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 06684ce2-c9de-48bf-9621-ada44ca8a12c))
(pad "PE2" smd rect (at 12.49 5) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp bd470244-7da3-4d59-894b-19e4071da146))
(pad "RF" smd rect (at -12.49 0.5) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp e91e6b83-902b-42be-92fa-6ac19487af54))
(pad "RST_CYFR" smd rect (at 12.49 -11) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp dc86e8ca-1f6b-4f0d-9576-5c57346768bf))
(pad "SCK" smd rect (at 12.49 -5) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 483e384c-d6af-490d-b4f9-371490f0e46f))
(pad "VCC" smd rect (at 12.49 11) (size 1.52 1.27) (layers "F.Cu" "F.Paste" "F.Mask")
(solder_mask_margin 0.1) (tstamp 8796d68c-81fa-42ef-ace9-9d8c76827e59))
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,75 @@
{
"board": {
"active_layer": 0,
"active_layer_preset": "All Layers",
"auto_track_width": false,
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"pads": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"ratsnest_display_mode": 0,
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": true,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
0,
1,
2,
3,
4,
5,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
32,
33,
34,
35,
36
],
"visible_layers": "fffffff_ffffffff",
"zone_display_mode": 0
},
"meta": {
"filename": "PL18_multiprotocol.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View File

@@ -0,0 +1,462 @@
{
"board": {
"design_settings": {
"defaults": {
"board_outline_line_width": 0.09999999999999999,
"copper_line_width": 0.19999999999999998,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.049999999999999996,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.15,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.15,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"45_degree_only": false,
"min_clearance": 0.19999999999999998
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
}
],
"drc_exclusions": [
"copper_edge_clearance|34900000|34735000|785ef911-e457-413e-ac63-cf1535b242cb|be0d3c71-0f5b-45b9-9c9b-72866af0f7a2",
"copper_edge_clearance|34900000|36735000|785ef911-e457-413e-ac63-cf1535b242cb|e7b16a25-ec09-4bb5-aa09-fe00038c1f1f",
"copper_edge_clearance|34900000|38735000|785ef911-e457-413e-ac63-cf1535b242cb|e65ad8dc-91cb-4c5d-b0fe-169b84ac0b55",
"copper_edge_clearance|34900000|40735000|785ef911-e457-413e-ac63-cf1535b242cb|95287391-9e27-4475-a375-0f63337ce67a",
"copper_edge_clearance|34900000|42735000|785ef911-e457-413e-ac63-cf1535b242cb|c29c966c-91b2-4b36-b1bc-6673192d38fe",
"copper_edge_clearance|34900000|44735000|785ef911-e457-413e-ac63-cf1535b242cb|4f24c66e-64cb-408b-9295-97d993d96225",
"copper_edge_clearance|34900000|46735000|785ef911-e457-413e-ac63-cf1535b242cb|0ddbf31e-bbeb-43d6-ae3b-cab85e65b36d",
"copper_edge_clearance|34900000|48735000|785ef911-e457-413e-ac63-cf1535b242cb|4dcf731f-2949-4865-b539-ff1e637244c5",
"copper_edge_clearance|34900000|50735000|785ef911-e457-413e-ac63-cf1535b242cb|34e18046-0932-48eb-854b-3707688a2215",
"copper_edge_clearance|34900000|52735000|785ef911-e457-413e-ac63-cf1535b242cb|5c40c44b-70c5-4c30-aafc-a4724555cbb1",
"copper_edge_clearance|34900000|54735000|785ef911-e457-413e-ac63-cf1535b242cb|bb59f967-af06-40a4-adc7-d38dcc40fc54",
"copper_edge_clearance|34900000|56735000|785ef911-e457-413e-ac63-cf1535b242cb|27057d15-87f3-4a5e-bab7-6c1fa0d1954f",
"copper_edge_clearance|34900000|58735000|785ef911-e457-413e-ac63-cf1535b242cb|13a669d2-833b-4c54-a87d-44fb38d91e82",
"copper_edge_clearance|61100000|36735000|b1556ea3-f1cc-4201-b942-480142bd0c54|5bd3edee-4a1d-4d5f-8aae-d7afd4bced8c",
"copper_edge_clearance|61100000|38735000|b1556ea3-f1cc-4201-b942-480142bd0c54|2bcfc76b-5219-4cb8-b24e-4fb83ce73dfb",
"copper_edge_clearance|61100000|46235000|b1556ea3-f1cc-4201-b942-480142bd0c54|ad1d31a9-5733-4b73-be03-a80ca4f16773",
"copper_edge_clearance|61100000|48235000|b1556ea3-f1cc-4201-b942-480142bd0c54|0967fce8-8cdb-4026-bedd-d620a9cd0bad",
"copper_edge_clearance|61100000|50235000|b1556ea3-f1cc-4201-b942-480142bd0c54|7aa764ba-7abe-485a-b859-ce8f0595e5cd",
"copper_edge_clearance|61100000|56735000|b1556ea3-f1cc-4201-b942-480142bd0c54|7dbb4403-9304-4fc0-8912-17af08ce6248",
"copper_edge_clearance|61100000|58735000|b1556ea3-f1cc-4201-b942-480142bd0c54|425646f1-4301-496a-bd77-d52b64168923"
],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"copper_edge_clearance": "error",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint_type_mismatch": "error",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "error",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zone_has_empty_net": "error",
"zones_intersect": "error"
},
"rules": {
"allow_blind_buried_vias": false,
"allow_microvias": false,
"max_error": 0.005,
"min_clearance": 0.0,
"min_copper_edge_clearance": 0.0,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.19999999999999998,
"min_microvia_drill": 0.09999999999999999,
"min_silk_clearance": 0.0,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.19999999999999998,
"min_via_annular_width": 0.049999999999999996,
"min_via_diameter": 0.39999999999999997,
"solder_mask_clearance": 0.0,
"solder_mask_min_width": 0.0,
"use_height_for_length_calcs": true
},
"track_widths": [
0.0,
0.4,
0.6,
0.603595,
1.0
],
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
},
{
"diameter": 1.2,
"drill": 0.6
}
],
"zones_allow_external_fillets": false,
"zones_use_no_outline": true
},
"layer_presets": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_label_syntax": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "PL18_multiprotocol.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12.0,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.25,
"via_diameter": 0.8,
"via_drill": 0.4,
"wire_width": 6.0
}
],
"meta": {
"version": 2
},
"net_colors": null
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"specctra_dsn": "",
"step": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"drawing": {
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"ngspice": {
"fix_include_paths": true,
"fix_passive_vals": false,
"meta": {
"version": 0
},
"model_mode": 0,
"workbook_filename": ""
},
"page_layout_descr_file": "",
"plot_directory": "",
"spice_adjust_passive_values": false,
"spice_external_command": "spice \"%I\"",
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"e6b36db3-d652-4d66-bbfe-8c61f998d4b2",
""
]
],
"text_variables": {}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
(fp_lib_table
(lib (name "Multi")(type "KiCad")(uri "${KIPRJMOD}/Multi.pretty")(options "")(descr ""))
)

View File

@@ -0,0 +1,3 @@
(sym_lib_table
(lib (name "Multi")(type "KiCad")(uri "${KIPRJMOD}/Multi.kicad_sym")(options "")(descr ""))
)

View File

@@ -0,0 +1,5 @@
# MPM for Flysky PL18
The PCB design is located in PL18_multiprotocol folder and is designed using KiCad 6.0.
The casing is located in Casing folder and is designed using Blender 3.3.1. The model included 2 pieces, T is the top piece and B is the bottom pieces. These 2 pieces is cloned into TF and BF respectively to apply all modifiers and make manifold for 3D printing. I have included the stl files generated for simplity.

View File

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

View File

@@ -20,6 +20,7 @@ Multiprotocol modules can be flashed with a precompiled firmware file (Option 1
1. [USB Port](#usb-port) 1. [USB Port](#usb-port)
1. [USB-to-Serial adapter](#usb-to-serial-adapter) 1. [USB-to-Serial adapter](#usb-to-serial-adapter)
1. [Upload the firmware](#upload-the-firmware) 1. [Upload the firmware](#upload-the-firmware)
1. [Option 4 - Flash via USB, using dfu-util (on Linux)](#option-4---flash-via-usb-using-dfu-util-on-linux)
1. [Troubleshooting](#troubleshooting) 1. [Troubleshooting](#troubleshooting)
## Tools required ## Tools required
@@ -172,6 +173,98 @@ In order to flash the bootloader the **BOOT0** jumper must be installed connecti
### Upload the firmware ### Upload the firmware
1. In the Arduino IDE click **Sketch -> Upload**, or press **Ctrl+U** 1. In the Arduino IDE click **Sketch -> Upload**, or press **Ctrl+U**
## Option 4 - Flash via USB, using dfu-util (on Linux)
This upgrade method is only for modules that have USB connectors and
that have the ability to enter DFU mode when plugged into a Linux
machine.
[dfu-util](http://dfu-util.sourceforge.net/) is a command line tool that
can be used to write firmware to a processor that is in the DFU
state. Pre-built dfu-util packages are available for almost any Linux
distribution, so simply install the dfu-util package via your system's
package manager.
You now need to get your multimodule connected to your Linux machine
and make sure that it is in DFU mode. Usually the multimodule should
enter the DFU mode if you remove it from your radio and simply connect
it to your Linux machine via a _proper_ USB cable. Note: Some cheap,
loading USB cables sometimes have no data lines connected, and these
will no work.
Once your multimodule is connected, run the following command in order
to see if the DFU interface had been discovered:
```shell
# dfu-util -l -v
dfu-util 0.11
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2021 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
libusb version 1.0.26 (11724)
Found DFU: [1eaf:0003] ver=0201, devnum=69, cfg=1, intf=0, path="1-4", alt=2, name="STM32duino bootloader v1.0 Upload to Flash 0x8002000", serial="LLM 003"
Found DFU: [1eaf:0003] ver=0201, devnum=69, cfg=1, intf=0, path="1-4", alt=1, name="STM32duino bootloader v1.0 Upload to Flash 0x8005000", serial="LLM 003"
Found DFU: [1eaf:0003] ver=0201, devnum=69, cfg=1, intf=0, path="1-4", alt=0, name="STM32duino bootloader v1.0 ERROR. Upload to RAM not supported.", serial="LLM 003"
```
If you the above didn't succeed, your module is not in DFU mode and it
would not make any sense to continue.
Now that your Linux machine discovered the device with id, 1eaf:0003,
you can can start the update process, which will take around 8 to 10
seconds. Once done, your multimodule will be updated and you can
simply unplug it and start using it.
The example below, uses a pre-compiled binary available from
[here](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/releases).
```shell
# dfu-util -v -R -a 2 -d 1EAF:0003 -D mm-stm-serial-aetr-v1.3.3.14.bin
dfu-util 0.11
Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2021 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/
libusb version 1.0.26 (11724)
dfu-util: Warning: Invalid DFU suffix signature
dfu-util: A valid DFU suffix will be required in a future dfu-util release
Opening DFU capable USB device...
Device ID 1eaf:0003
Device DFU version 0110
DFU attributes: (0x03) bitCanDnload bitCanUpload
Detach timeout 255 ms
Claiming USB DFU Interface...
Setting Alternate Interface #2 ...
Determining device status...
DFU state(2) = dfuIDLE, status(0) = No error condition is present
DFU mode device DFU version 0110
Device returned transfer size 1024
Copying data from PC to DFU device
Download [=========================] 100% 118668 bytes
Download done.
Sent a total of 118668 bytes
DFU state(8) = dfuMANIFEST-WAIT-RESET, status(0) = No error condition is present
Resetting USB to switch back to runtime mode
Done!
```
NOTE: The above command was taken and adapted from
[here](https://github.com/benlye/flash-multi/blob/master/doc/Troubleshooting.md).
As you can see, the above process is really extremely straight
forward. You basically only need to have dfu-util installed and you need to
run one single command for updating your multimodule.
As a bonus, the dfu-util method could also be used under Mac or
Windows, as dfu-util binaries also exist for those operating systems.
# Troubleshooting # Troubleshooting
You can report your problem using the [GitHub issue](https://github.com/midelic/DIY-Multiprotocol-TX-Module/issues) system or go to the [Main thread on RCGROUPS](http://www.rcgroups.com/forums/showthread.php?t=2165676) to ask your question. You can report your problem using the [GitHub issue](https://github.com/midelic/DIY-Multiprotocol-TX-Module/issues) system or go to the [Main thread on RCGROUPS](http://www.rcgroups.com/forums/showthread.php?t=2165676) to ask your question.
Please provide the following information: Please provide the following information:

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 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) | | **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) | | **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* *Table last updated June 24th, 2018*