Compare commits

..

94 Commits

Author SHA1 Message Date
Pascal Langer
4c14925b4f Bump version for release 2021-09-12 19:35:11 +02:00
Pascal Langer
4c74bc869d Update _Config.h 2021-09-11 00:08:09 +02:00
Pascal Langer
45edfa1ec0 AFHDS2A doc update 2021-09-10 23:58:12 +02:00
Pascal Langer
88343b7424 Proto list: fix flags 2021-09-09 08:40:09 +02:00
Pascal Langer
13197840c2 V761: code cleanup 2021-09-09 08:39:37 +02:00
Pascal Langer
ffe4ac68fd Proto list: add number of protocols in the list 2021-09-08 14:30:01 +02:00
Pascal Langer
5bab5f03db Update Multi_Protos.ino 2021-09-08 13:38:25 +02:00
Pascal Langer
ae748e25f8 Update XN297Dump_nrf24l01.ino 2021-09-07 23:17:21 +02:00
Pascal Langer
e9c7959ecb Update V761_nrf24l01.ino 2021-09-07 23:17:11 +02:00
Pascal Langer
bf09855014 Another attempt 2021-09-07 16:59:06 +02:00
Pascal Langer
32bd39f209 Save space in the 5in1 modules 2021-09-07 15:07:37 +02:00
Pascal Langer
940f241b9d Fix compilation issues 2021-09-07 14:29:35 +02:00
Pascal Langer
5c00ce6b88 New 0 protocol: enable to list all protocols and sub protocols 2021-09-07 14:08:24 +02:00
Pascal Langer
016b282246 Multi Status: send frame as soon as a new protocol is selected 2021-09-05 22:15:56 +02:00
Pascal Langer
d6ecac1302 Xerall: few improvements 2021-09-04 11:48:41 +02:00
Ben Lye
901f8ca6b0 Disable some protocols for the DIY 5-in-1 (#618) 2021-09-01 15:20:10 +02:00
Pascal Langer
9c3b6ba9f6 Update Validate.h 2021-09-01 09:45:38 +02:00
Pascal Langer
53ec484028 Update Validate.h 2021-09-01 01:39:26 +02:00
Pascal Langer
246e808cb4 Xerall protocol 2021-09-01 01:21:38 +02:00
Pascal Langer
a7b68dc2aa F949G: will it work? 2021-08-27 10:22:47 +02:00
Pascal Langer
08404f9223 F949G: another try... 2021-08-26 23:43:42 +02:00
Pascal Langer
149554e61c Update MT99xx_ccnrf.ino 2021-08-26 23:23:38 +02:00
Pascal Langer
7b71425db2 F949G test with original radio ID 2021-08-26 23:19:59 +02:00
Pascal Langer
f9cfb7f20f Update Protocols_Details.md 2021-08-26 22:51:57 +02:00
Pascal Langer
506ee43d41 Update _Config.h 2021-08-26 22:35:42 +02:00
Pascal Langer
ebde0915cd MT99xx/F949G: new sub protocol 2021-08-26 22:33:38 +02:00
Pascal Langer
2501656bf4 Update XN297Dump_nrf24l01.ino 2021-08-26 11:52:36 +02:00
Pascal Langer
9356e7654e XN297EMU: allows to send and receive 0 payload length in enhanced mode 2021-08-25 19:07:36 +02:00
Pascal Langer
4f1e5d2452 BUGSMINI: fix
No one has reported an issue but from the look of the code it was broken since some time...
2021-08-25 19:05:24 +02:00
Ben Lye
64c75414d8 Add release build for 64KB CC2500-only module (#615) 2021-08-24 20:54:46 +02:00
Pascal Langer
5147833487 DSM RX: use directly the TX type and channels 2021-08-21 10:14:05 +02:00
Ben Lye
324419241f Prefix release binaries with mm instead of multi (#596)
Better for radios with 128x64 LCDs.
2021-08-16 17:59:07 +02:00
Pascal Langer
1a921b1cdb Disable multi config if telemetry is disabled 2021-07-05 17:08:57 +02:00
Pascal Langer
25c052c0a3 KF606: new sub protocol MIG320 2021-07-04 14:05:42 +02:00
Pascal Langer
a02586cca9 RadioLink: RSSI correction 2021-07-03 14:09:28 +02:00
Pascal Langer
226e082c5a E129 and E010R5 not supported on atmega328p 2021-06-30 09:45:25 +02:00
Pascal Langer
5afdff8477 V911S: Rate channel on CH6 (default is high) 2021-06-28 18:10:44 +02:00
Pascal Langer
c52ac2cefc Fix XN297Dump enhanced payload detection 2021-06-28 18:04:17 +02:00
pascallanger
09f39ea60f Update README.md 2021-06-27 12:38:53 +02:00
Harry Phillips
41e31eae6d Set reserved field in CABELL packet to current channel (#593) 2021-06-24 11:49:47 +02:00
Pascal Langer
dcf20951ba Update Protocols_Details.md 2021-06-20 18:51:23 +02:00
Pascal Langer
6e9ebfd695 Mould King: control up to 4 bricks at the same time 2021-06-20 18:39:27 +02:00
Pascal Langer
c36b112437 Update Multi_Config.ino 2021-06-17 15:42:09 +02:00
Pascal Langer
24fbd44f5b Multi Config: eeprom format for atmega 2021-06-17 15:40:28 +02:00
Pascal Langer
d0db7829e5 Multi config: enabled by default, LUA script update 2021-06-17 15:30:46 +02:00
Pascal Langer
58ed8ca60f Mould King: Analog and digital sub protocols 2021-05-27 19:01:08 +02:00
Pascal Langer
4d2c8ef04e Fix RadioLink: request telemetry every time to time like original instead of all the time 2021-05-25 14:54:17 +02:00
Pascal Langer
438e85c551 MouldKing: match original 2021-05-09 03:36:42 +02:00
Pascal Langer
06b336ee59 Mould King: fix frequencies 2021-05-04 14:58:40 +02:00
pascallanger
a93adeb75e Update Protocols_Details.md 2021-05-04 11:29:44 +02:00
Pascal Langer
802e69563e ... 2021-05-04 10:53:38 +02:00
Pascal Langer
a8897df3f2 New protocol: Mould King 2021-05-04 10:39:13 +02:00
Pascal Langer
7157d3d906 Losi: optimization 2021-05-03 16:57:08 +02:00
Pascal Langer
96b8a500b4 New protocol: Losi 2021-05-03 15:29:24 +02:00
Pascal Langer
51a3ef8ee9 Update XN297Dump_nrf24l01.ino 2021-05-01 18:45:20 +02:00
Pascal Langer
652d6604e7 Update Multiprotocol.h 2021-05-01 18:35:47 +02:00
Pascal Langer
b9028ab4b4 XN297Dump: CC2500 dump @250K 2021-05-01 18:15:34 +02:00
Konstantin Tretyakov
62c509b03c Add the IKEA Ansluta remote-controllable lighting protocol (#566)
* Add the IKEA Ansluta remote-controllable lighting protocol

* Fixes to IKEA Ansluta implementation
2021-04-24 21:46:29 +02:00
Pascal Langer
1648a0780a XK: fix twitch on other channels than rudder 2021-04-24 12:54:17 +02:00
pascallanger
3b1af68ed6 Update FUNDING.yml 2021-04-21 13:17:46 +02:00
pascallanger
aeed7bac57 Create FUNDING.yml 2021-04-20 23:17:50 +02:00
Pascal Langer
2bb76a40f3 Pelikan/SCX24: add second hopping table 2021-04-20 22:24:01 +02:00
Pascal Langer
0c129a45aa SCX24 IDs 2021-04-18 16:41:49 +02:00
Pascal Langer
2a383c7285 Pelikan/SCX24: fix? 2021-04-17 22:55:43 +02:00
Pascal Langer
34f16b0b66 MT99XX/Dragon: batt telemetry correction & low batt flag 2021-04-17 18:31:41 +02:00
Pascal Langer
a9d9c4cdfa Update A7105_SPI.ino 2021-04-17 11:57:00 +02:00
Pascal Langer
4a1c986dd0 Kyosho/FHSS fix? 2021-04-17 11:52:21 +02:00
Pascal Langer
756e9b3213 Update Protocols_Details.md 2021-04-16 15:00:33 +02:00
Pascal Langer
61a284863e Update Protocols_Details.md 2021-04-16 14:59:10 +02:00
Pascal Langer
39410c290b Pelikan/SCX24: new sub protocol 2021-04-16 14:50:53 +02:00
Pascal Langer
9e0684b6cb CABELL: code optimization 2021-04-07 09:02:50 +02:00
Pascal Langer
13add5b9f2 Devo: fix GPS year 2021-04-06 18:15:34 +02:00
Pascal Langer
475cd1af98 Atmega CC2500 build: remove FRSKYL to fit 2021-04-06 10:36:15 +02:00
Pascal Langer
04d08c6d67 FrSkyX2: changed bind bytes 2021-04-06 10:18:48 +02:00
Pascal Langer
6295bb1bbc Packed protocols definition to save space 2021-04-05 17:43:42 +02:00
Pascal Langer
931ba2bd68 Hitec: fix freq tune 2021-04-02 17:42:44 +02:00
Pascal Langer
769fb4ff94 Update Protocols_Details.md 2021-03-30 16:41:29 +02:00
Pascal Langer
aa7c18a2bd FrSkyX: fix the need to rebind RXs 2021-03-30 15:13:00 +02:00
Pascal Langer
f95cfa1261 Update Protocols_Details.md 2021-03-30 14:13:18 +02:00
Pascal Langer
8c12aaf2c1 DSMR: new surface protocol 2021-03-30 12:10:29 +02:00
Pascal Langer
94f73bd54f MT99xx: Added voltage telemetry for the Dragon sub protocol 2021-03-27 11:51:53 +01:00
Pascal Langer
9b3549d4a9 FrSkyX: code review 2021-03-25 10:10:53 +01:00
Pascal Langer
7bc05cb63c Update Multiprotocol.h 2021-03-19 17:11:06 +01:00
Pascal Langer
84780a9d90 Multi Config 2021-03-19 17:06:58 +01:00
Pascal Langer
37e029c612 Bug fix in XN297 emu layer when address is 3 bytes and CC2500 in use 2021-03-17 19:24:42 +01:00
Pascal Langer
c47ed8aca8 E016H has its own protocol now 2021-03-17 18:46:48 +01:00
Pascal Langer
5bb0752d5e Update include to xn297... 2021-03-17 17:19:41 +01:00
Pascal Langer
4a626eaf14 Change XN297 emulation layer
Loads of protocols have been touched by this change. Some testing has been done but please test on all your models.
The XN297 emulation selects in this order:
 - the CC2500 if it is available and bitrate=250K. Configure the option field automatically for RF tune.
 - the NRF for all bitrates if it is available
 - if NRF is not available and bitrate=1M then an invalid protocol is sent automatically to the radio.
CC2500 @250K can now receive normal and enhanced payloads.
OMP protocol supports telemetry on CC2500 and is also for NRF only modules including telemetry.
Separation of E016H (new protocol) from E01X due to different structure.
MJXQ, MT99XX, Q303 and XK: some sub protocols available on CC2500 only.
2021-03-17 17:05:42 +01:00
pascallanger
47de19c8a5 DSM RX output ranges 2021-03-15 08:45:27 +01:00
Pascal Langer
3d4cfa30ac Remove spaces 2021-03-15 08:43:25 +01:00
pascallanger
d658bee05a Add files via upload 2021-03-15 08:39:06 +01:00
pascallanger
820c181394 Update CPPM_HW_Mod.md 2021-03-15 08:07:42 +01:00
pascallanger
c9774f557e Add files via upload 2021-03-15 08:06:24 +01:00
Pascal Langer
b17618a5a8 Update Protocols_Details.md 2021-03-14 19:22:49 +01:00
78 changed files with 4375 additions and 2007 deletions

12
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: [pascallanger]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=VF2K9T23DRY56&lc=US&item_name=DIY%20Multiprotocol&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted

View File

@@ -29,16 +29,16 @@
7,3,Devo,6CH,0,CH5,CH6
7,4,Devo,7CH,0,CH5,CH6,CH7
33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow
6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,0,DSM,2_1F,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,1,DSM,2_2F,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,2,DSM,X_1F,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,3,DSM,X_2F,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,4,DSM,AUTO,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,5,DSM,R_1F,0,AUX3,AUX4,AUX5
70,0,DSM_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
70,1,DSM_RX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH
45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH
45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH
16,0,ESKY,Std,0,Gyro,Pitch
16,1,ESKY,ET4,0,Gyro,Pitch
35,0,ESKY150,4CH,0
@@ -55,6 +55,8 @@
28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
28,4,Flysky_AFHDS2A,PWM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
28,5,Flysky_AFHDS2A,PPM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
28,6,Flysky_AFHDS2A,PWM_SB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
28,7,Flysky_AFHDS2A,PPM_SB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
56,1,Flysky2A_RX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
53,0,Height,5ch,0,Gear
@@ -112,7 +114,8 @@
22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
71,0,JJRC345,JJRC345,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
71,1,JJRC345,SkyTmblr,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
49,0,KF606,Std,1,Trim
49,0,KF606,KF606,1,Trim
49,1,KF606,MIG320,1,Trim
9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
73,0,Kyosho,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
@@ -130,10 +133,12 @@
17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess
17,5,MT99XX,A180,0,3D_6G
17,6,MT99XX,Dragon,0,Mode,RTH
17,7,MT99XX,F949G,0,6G_3D,Light
44,0,NCC1701,Std,1,Warp
77,0,OMP,M2,0,THold,IdleUp,6G_3D
60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
60,1,Pelikan,LITE_V4,0,CH5,CH6,CH7,CH8
60,2,Pelikan,SCX24,0
51,0,Potensic,A20,1,TakLan,Emerg,Mode,HLess
66,0,Propel,74-Z,1,LEDs,RollCW,RolCCW,Fire,Weapon,Calib,AltHol,TakeOf,Land,Train
29,0,Q2x2,Q222,1,Flip,LED,Mod2,Mod1,HLess,RTH,XCal,YCal
@@ -166,8 +171,8 @@
5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD
48,0,V761,3CH,0,Gyro,Calib,Flip,RtnAct,Rtn
48,1,V761,4CH,0,Gyro,Calib,Flip,RtnAct,Rtn
46,0,V911s,V911s,1,Calib
46,1,V911s,E119,1,Calib
46,0,V911s,V911s,1,Calib,Rate
46,1,V911s,E119,1,Calib,Rate
22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8
30,1,WK2x01,WK2401,0
@@ -190,3 +195,9 @@
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
84,0,JOYSWAY,Std,0
85,0,E016H,Std,1,Stop,Flip,n-a,HLess,RTH
87,0,IKEA
89,0,LOSI
90,0,MouldKg,Analog,0
90,1,MouldKg,Digit,0
91,0,Xerall,Tank,0,FlTa,TakLan,Rate,HLess,Photo,Video,TrimR,TrimE,TrimA

View File

@@ -280,11 +280,27 @@ local function Multi_Init()
end
--Exceptions on first 4 channels...
if ( protocol == 73 or (protocol == 74 and sub_protocol == 0) ) then -- Kyosho or RadioLink Surface
if ( protocol == 73 or (protocol == 74 and sub_protocol == 0) or (protocol == 60 and sub_protocol == 2) or protocol == 89) then -- Kyosho or RadioLink Surface or Pelikan/SCX24 or Losi
channel_names[1] = "ST"
channel_names[2] = "THR"
channel_names[3] = "CH3"
channel_names[4] = "CH4"
if(protocol == 60 and sub_protocol == 2) then
channel_names[4] = "n-a"
else
channel_names[4] = "CH4"
end
end
if ( protocol == 6 and sub_protocol == 5 ) then -- DSMR
channel_names[1] = "ST"
channel_names[2] = "THR"
channel_names[3] = "AUX1"
channel_names[4] = "AUX2"
end
if ( protocol == 90 ) then -- Mould King
channel_names[1] = "A"
channel_names[2] = "B"
channel_names[3] = "C"
channel_names[4] = "D"
end
--Check MultiChan.txt

525
Lua_scripts/MultiConfig.lua Normal file
View File

@@ -0,0 +1,525 @@
---- #########################################################################
---- # #
---- # 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 Config description
-- To start operation:
-- Write 0xFF at address 4 will request the buffer to be cleared
-- Write "Conf" at address 0..3
-- Read
-- Read at address 12 gives the current config page
-- Read at address 13..172 gives the current data of the page = 8 lines * 20 caracters
-- Write
-- Write at address 5..11 the command
-- Write 0x01 at address 4 will send the command to the module
-- !! Before exiting the script must write 0 at address 0 for normal operation !!
--###############################################################################
local Version = "v0.2"
local Focus = -1
local Page = 0
local Edit = -1
local Edit_pos = 1
local Menu = { {text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""},
{text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""},
{text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""},
{text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""},
{text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""},
{text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""},
{text = "", field_type = 0, field_len = 0, field_value = {}, field_text = ""} }
local Menu_value = {}
local Blink = 0
local ModuleNumber = 0
local ModuleType = ""
local Module = {}
local InitialProtocol = 0
function bitand(a, b)
local result = 0
local bitval = 1
while a > 0 and b > 0 do
if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits
result = result + bitval -- set the current bit
end
bitval = bitval * 2 -- shift left
a = math.floor(a/2) -- shift right
b = math.floor(b/2)
end
return result
end
local function Config_Send(page, line, value)
local i
i = (page*16) + line
multiBuffer( 5, i )
for i = 1 , 6 , 1 do
multiBuffer( 5+i, value[i] )
end
multiBuffer( 4, 1 )
end
local function Config_Release()
--Set the protocol back to what it was
Module.protocol = InitialProtocol
model.setModule(ModuleNumber, Module)
--Stop requesting updates
local i
for i = 3 , 0 , -1 do
multiBuffer( i, 0 )
end
end
local function Config_Page( )
Config_Send(Page, 0, { 0, 0, 0, 0, 0, 0 })
end
local function Config_Draw_Edit( event )
local i
local text
if Menu[Focus].field_type == 0xD0 then
-- Editable Hex value
if Edit == -1 then
-- Init
Edit = 0
Edit_pos = 1
Blink = 0
for i = 1, Menu[Focus].field_len, 1 do
Menu_value[i] = Menu[Focus].field_value[i]
end
end
if Edit == 0 then
-- Not editing value
if event == EVT_VIRTUAL_ENTER then
if Edit_pos > Menu[Focus].field_len then
-- Save or Cancel
Edit = -1
if Edit_pos == Menu[Focus].field_len + 1 then
-- Save
Config_Send(Page, Focus, Menu_value)
end
return
else
-- Switch to edit mode
Edit = 1
end
elseif event == EVT_VIRTUAL_PREV and Edit_pos > 1 then
-- Move cursor
Edit_pos = Edit_pos - 1
elseif event == EVT_VIRTUAL_NEXT and Edit_pos < Menu[Focus].field_len + 2 then
-- Move cursor
Edit_pos = Edit_pos + 1
end
else
-- Editing value
if event == EVT_VIRTUAL_ENTER then
-- End edit
Edit = 0
elseif event == EVT_VIRTUAL_PREV then
-- Change value
Menu_value[Edit_pos] = Menu_value[Edit_pos] - 1
elseif event == EVT_VIRTUAL_NEXT then
-- Change value
Menu_value[Edit_pos] = Menu_value[Edit_pos] + 1
end
--Blink
Blink = Blink + 1
if Blink > 30 then
Blink = 0
end
end
--Display
if LCD_W == 480 then
lcd.drawRectangle(160-1, 100-1, 160+2, 55+2, TEXT_COLOR)
lcd.drawFilledRectangle(160, 100, 160, 55, TEXT_BGCOLOR)
else
lcd.clear()
end
for i = 1, Menu[Focus].field_len, 1 do
if i==Edit_pos and (Edit ~= 1 or Blink > 15) then
attrib = INVERS
else
attrib = 0
end
if LCD_W == 480 then
lcd.drawText(170+12*2*(i-1), 110, string.format('%02X', Menu_value[i]), attrib)
else
lcd.drawText(17+6*2*(i-1), 10, string.format('%02X', Menu_value[i]), attrib + SMLSIZE)
end
end
if Edit_pos == Menu[Focus].field_len + 1 then
attrib = INVERS
else
attrib = 0
end
if LCD_W == 480 then
lcd.drawText(170, 130, "Save", attrib)
else
lcd.drawText(17, 30, "Save", attrib + SMLSIZE)
end
if Edit_pos == Menu[Focus].field_len + 2 then
attrib = INVERS
else
attrib = 0
end
if LCD_W == 480 then
lcd.drawText(260, 130, "Cancel", attrib)
else
lcd.drawText(77, 30, "Cancel", attrib + SMLSIZE)
end
elseif Menu[Focus].field_type == 0x90 then
-- Action text
if Edit == -1 then
-- Init
Edit = 0
Edit_pos = 2
end
if event == EVT_VIRTUAL_ENTER then
-- Exit
Edit = -1
if Edit_pos == 1 then
-- Yes
Config_Send(Page, Focus, { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA } )
end
return
elseif event == EVT_VIRTUAL_PREV and Edit_pos > 1 then
-- Switch to Yes
Edit_pos = Edit_pos - 1
elseif event == EVT_VIRTUAL_NEXT and Edit_pos < 2 then
-- Switch to No
Edit_pos = Edit_pos + 1
end
-- Display
if LCD_W == 480 then
lcd.drawRectangle(160-1, 100-1, 160+2, 55+2, TEXT_COLOR)
lcd.drawFilledRectangle(160, 100, 160, 55, TEXT_BGCOLOR)
else
lcd.clear()
end
if LCD_W == 480 then
lcd.drawText(170, 110, Menu[Focus].field_text .. "?")
else
lcd.drawText(17, 10, Menu[Focus].field_text .. "?", SMLSIZE)
end
if Edit_pos == 1 then
attrib = INVERS
else
attrib = 0
end
if LCD_W == 480 then
lcd.drawText(170, 130, "Yes", attrib)
else
lcd.drawText(17, 30, "Yes", attrib + SMLSIZE)
end
if Edit_pos == 2 then
attrib = INVERS
else
attrib = 0
end
if LCD_W == 480 then
lcd.drawText(260, 130, "No", attrib)
else
lcd.drawText(77, 30, "No", attrib)
end
end
end
local function Config_Next_Prev( event )
-- Next Prev on main menu
local line
if event == EVT_VIRTUAL_PREV then
for line = Focus - 1, 1, -1 do
if Menu[line].field_type >= 0x80 and Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 then
Focus = line
break
end
end
elseif event == EVT_VIRTUAL_NEXT then
for line = Focus + 1, 7, 1 do
if Menu[line].field_type >= 0x80 and Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 then
Focus = line
break
end
end
end
end
local function Config_Draw_Menu()
-- Main menu
local i
local value
local line
local length
local text
lcd.clear()
if LCD_W == 480 then
--Draw title
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
lcd.drawText(1, 5, "Multi Config " .. Version, MENU_TITLE_COLOR)
if multiBuffer(13) == 0x00 then
lcd.drawText(10,50,"No Config telemetry...", BLINK)
end
else
--Draw on LCD_W=128
lcd.drawText(1, 0, "Multi Config " .. Version, SMLSIZE)
if multiBuffer(13) == 0x00 then
lcd.drawText(2,17,"No Config telemetry...",SMLSIZE)
end
end
if multiBuffer(13) ~= 0x00 then
if LCD_W == 480 then
--Draw firmware version and channels order
local ch_order = multiBuffer(17)
local channel_names = {}
channel_names[bitand(ch_order,3)+1] = "A"
ch_order = math.floor(ch_order/4)
channel_names[bitand(ch_order,3)+1] = "E"
ch_order = math.floor(ch_order/4)
channel_names[bitand(ch_order,3)+1] = "T"
ch_order = math.floor(ch_order/4)
channel_names[bitand(ch_order,3)+1] = "R"
lcd.drawText(150, 5, ModuleType.." v" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16) .. " " .. channel_names[1] .. channel_names[2] .. channel_names[3] .. channel_names[4], MENU_TITLE_COLOR)
else
lcd.drawText(76, 0, "/Fw" .. multiBuffer(13) .. "." .. multiBuffer(14) .. "." .. multiBuffer(15) .. "." .. multiBuffer(16),SMLSIZE) -- .. " " .. channel_names[1] .. channel_names[2] .. channel_names[3] .. channel_names[4])
end
--Draw Menu
for line = 1, 7, 1 do
--Clear line info
Menu[line].text = ""
Menu[line].field_type = 0
Menu[line].field_len = 0
for i = 1, 7, 1 do
Menu[line].field_value[i] = 0
end
Menu[line].field_text = ""
length = 0
--Read line from buffer
for i = 0, 20-1, 1 do
value=multiBuffer( line*20+13+i )
if value == 0 then
break -- end of line
end
if value > 0x80 and Menu[line].field_type == 0 then
-- Read field type
Menu[line].field_type = bitand(value, 0xF0)
Menu[line].field_len = bitand(value, 0x0F)
length = Menu[line].field_len
if Menu[line].field_type ~= 0xA0 and Menu[line].field_type ~= 0xC0 and Focus == -1 then
-- First actionnable field if nothing was selected
Focus = line;
end
else
if Menu[line].field_type == 0 then
-- Text
Menu[line].text = Menu[line].text .. string.char(value)
else
-- Menu specific fields
length = length - 1
if Menu[line].field_type == 0x80 or Menu[line].field_type == 0x90 then
Menu[line].field_text = Menu[line].field_text .. string.char(value)
else
Menu[line].field_value[Menu[line].field_len-length] = value
end
if length == 0 then
-- End of fields
break
end
end
end
end
-- Display menu text
if Menu[line].text ~= "" then
if Menu[line].field_type == 0xA0 or Menu[line].field_type == 0xB0 or Menu[line].field_type == 0xC0 or Menu[line].field_type == 0xD0 then
Menu[line].text = Menu[line].text .. ":"
end
if LCD_W == 480 then
lcd.drawText(10,32+20*line,Menu[line].text )
else
lcd.drawText(2,1+8*line,Menu[line].text,SMLSIZE)
end
end
-- Display specific fields
if line == Focus then
attrib = INVERS
else
attrib = 0
end
if Menu[line].field_type == 0x80 or Menu[line].field_type == 0x90 then
-- Text
if LCD_W == 480 then
lcd.drawText(10+9*#Menu[line].text, 32+20*line, Menu[line].field_text, attrib)
else
lcd.drawText(2+5*#Menu[line].text, 1+8*line, Menu[line].field_text, SMLSIZE + attrib)
end
elseif Menu[line].field_type == 0xA0 or Menu[line].field_type == 0xB0 then
-- Decimal value
value = 0
for i = 1, Menu[line].field_len, 1 do
value = value*256 + value
end
if LCD_W == 480 then
lcd.drawText(10+9*#Menu[line].text, 32+20*line, value, attrib)
else
lcd.drawText(2+5*#Menu[line].text, 1+8*line, value, SMLSIZE + attrib)
end
elseif Menu[line].field_type == 0xC0 or Menu[line].field_type == 0xD0 then
-- Hex value
text=""
for i = 1, Menu[line].field_len, 1 do
text = text .. string.format('%02X ', Menu[line].field_value[i])
end
if LCD_W == 480 then
lcd.drawText(10+9*#Menu[line].text, 32+20*line, text, attrib)
else
lcd.drawText(2+5*#Menu[line].text, 1+8*line, text, SMLSIZE + attrib)
end
end
end
end
end
-- Init
local function Config_Init()
--Find Multi module
Module_int = model.getModule(0)
Module_ext = model.getModule(1)
if Module_int["Type"] ~= 6 and Module_ext["Type"] ~= 6 then
error("No Multi module detected...")
return 2
end
if Module_int["Type"] == 6 and Module_ext["Type"] == 6 then
error("Two Multi modules detected, turn on only the one to be configured.")
return 2
end
if Module_int["Type"] == 6 then
ModuleNumber = 0
ModuleType = "Internal"
else
ModuleNumber = 1
ModuleType = "External"
end
--Get Module settings and set it to config protocol
Module = model.getModule(ModuleNumber)
InitialProtocol = Module.protocol
Module.protocol = 86
model.setModule(ModuleNumber, Module)
--pause while waiting for the module to switch to config
for i = 0, 10, 1 do end
--Set protocol to talk to
multiBuffer( 0, string.byte('C') )
--test if value has been written
if multiBuffer( 0 ) ~= string.byte('C') then
error("Not enough memory!")
return 2
end
--Request init of the buffer
multiBuffer( 4, 0xFF )
multiBuffer(13, 0x00 )
--Continue buffer init
multiBuffer( 1, string.byte('o') )
multiBuffer( 2, string.byte('n') )
multiBuffer( 3, string.byte('f') )
-- Test set
-- multiBuffer( 12, 0 )
-- multiBuffer( 13, 1 )
-- multiBuffer( 14, 3 )
-- multiBuffer( 15, 2 )
-- multiBuffer( 16, 62 )
-- multiBuffer( 17, 0 + 1*4 + 2*16 + 3*64)
-- multiBuffer( 33, string.byte('G') )
-- multiBuffer( 34, string.byte('l') )
-- multiBuffer( 35, string.byte('o') )
-- multiBuffer( 36, string.byte('b') )
-- multiBuffer( 37, string.byte('a') )
-- multiBuffer( 38, string.byte('l') )
-- multiBuffer( 39, string.byte(' ') )
-- multiBuffer( 40, string.byte('I') )
-- multiBuffer( 41, string.byte('D') )
-- multiBuffer( 42, 0xD0 + 4 )
-- multiBuffer( 43, 0x12 )
-- multiBuffer( 44, 0x34 )
-- multiBuffer( 45, 0x56 )
-- multiBuffer( 46, 0x78 )
-- multiBuffer( 47, 0x9A )
-- multiBuffer( 48, 0xBC )
-- multiBuffer( 53, 0x90 + 9 )
-- multiBuffer( 54, string.byte('R') )
-- multiBuffer( 55, string.byte('e') )
-- multiBuffer( 56, string.byte('s') )
-- multiBuffer( 57, string.byte('e') )
-- multiBuffer( 58, string.byte('t') )
-- multiBuffer( 59, string.byte(' ') )
-- multiBuffer( 60, string.byte('G') )
-- multiBuffer( 61, string.byte('I') )
-- multiBuffer( 62, string.byte('D') )
-- multiBuffer( 63, 0x00 )
end
-- Main
local function Config_Run(event)
if event == nil then
error("Cannot be run as a model script!")
return 2
elseif event == EVT_VIRTUAL_EXIT then
Config_Release()
return 2
else
Config_Draw_Menu()
if ( event == EVT_VIRTUAL_PREV_PAGE or event == EVT_VIRTUAL_NEXT_PAGE ) and Edit < 1 then
-- Not editing, ok to change page
if event == EVT_VIRTUAL_PREV_PAGE then
killEvents(event)
if Page > 0 then
--Page = Page - 1
--Config_Page()
end
else
--Page = Page + 1
--Config_Page()
end
end
if Focus > 0 then
-- At least one line has an action
if Edit >= 0 then
-- Currently editing
Config_Draw_Edit( event )
elseif event == EVT_VIRTUAL_ENTER then
-- Switch to edit
Config_Draw_Edit( 0 )
elseif event == EVT_VIRTUAL_PREV or event == EVT_VIRTUAL_NEXT then
-- Main menu selection
Config_Next_Prev( event )
end
end
return 0
end
end
return { init=Config_Init, run=Config_Run }

View File

@@ -13,6 +13,19 @@ If you like this project and want to support further development please consider
</tr>
</table>
## MultiConfig
Enables to modify on a Multi module the Global ID, Cyrf ID or format the EEPROM.
Matching the ID of 2 Multi modules enable them to control the same receivers without rebinding. Be carefull the 2 modules should not be used at the same time unless you know what you are doing.
Notes:
- Supported from Multi v1.3.2.85 or above and OpenTX 2.3.12 or above
- The Multi module to be configured must be active, if there is a second Multi module in the radio it must be off
- Located on the radio SD card under \SCRIPTS\TOOLS
[![MultiCconfig](https://img.youtube.com/vi/lGyCV2kpqHU/0.jpg)](https://www.youtube.com/watch?v=lGyCV2kpqHU)
## MultiChannelsUpdater
Automatically name the channels based on the loaded Multi protocol and sub protocol including the module channel order convention.

View File

@@ -29,7 +29,7 @@ void A7105_WriteData(uint8_t len, uint8_t channel)
A7105_CSN_on;
if(protocol!=PROTO_WFLY2)
{
if(!(protocol==PROTO_FLYSKY || protocol==PROTO_KYOSHO))
if(!(protocol==PROTO_FLYSKY || (protocol==PROTO_KYOSHO && sub_protocol==KYOSHO_HYPE)))
{
A7105_Strobe(A7105_STANDBY); //Force standby mode, ie cancel any TX or RX...
A7105_SetTxRxMode(TX_EN); //Switch to PA
@@ -499,6 +499,11 @@ void A7105_Init(void)
vco_calibration1=0x02;
break;
case PROTO_PELIKAN:
if(sub_protocol == PELIKAN_SCX24)
{
vco_calibration1=0x0A;
break;
}
case PROTO_KYOSHO: //sub_protocol Hype
vco_calibration1=0x0C;
break;

View File

@@ -16,7 +16,7 @@
#if defined(BUGSMINI_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
#define BUGSMINI_INITIAL_WAIT 500
#define BUGSMINI_PACKET_INTERVAL 6840
@@ -59,9 +59,8 @@ enum {
static void __attribute__((unused)) BUGSMINI_RF_init()
{
NRF24L01_Initialize();
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, BUGSMINI_RX_PAYLOAD_SIZE); // bytes of data payload for rx pipe 1
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
//XN297_HoppingCalib(BUGSMINI_NUM_RF_CHANNELS*2);
}
static void __attribute__((unused)) BUGSMINI_check_arming()
@@ -148,15 +147,14 @@ static void __attribute__((unused)) BUGSMINI_send_packet()
hopping_frequency_no++;
if(hopping_frequency_no >= BUGSMINI_NUM_RF_CHANNELS)
hopping_frequency_no = 0;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? hopping_frequency[hopping_frequency_no+BUGSMINI_NUM_RF_CHANNELS] : hopping_frequency[hopping_frequency_no]);
XN297_Hopping(IS_BIND_IN_PROGRESS ? hopping_frequency_no+BUGSMINI_NUM_RF_CHANNELS : hopping_frequency_no);
}
// Power on, TX mode, 2byte CRC
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
// Send
XN297_SetPower();
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, BUGSMINI_TX_PAYLOAD_SIZE);
NRF24L01_SetPower();
}
// compute final address for the rxid received during bind
@@ -220,37 +218,37 @@ static void __attribute__((unused)) BUGSMINI_make_address()
// Something wrong happened if we arrive here....
}
#if defined(BUGS_HUB_TELEMETRY)
static void __attribute__((unused)) BUGSMINI_update_telemetry()
{
#if defined(BUGS_HUB_TELEMETRY)
uint8_t checksum = 0x6d;
for(uint8_t i=1; i<12; i++)
checksum += packet[i];
if(packet[0] == checksum)
checksum += packet_in[i];
if(packet_in[0] == checksum)
{
RX_RSSI = packet[3];
RX_RSSI = packet_in[3];
if(sub_protocol==BUGS3H)
{
if(packet[11] & 0x40)
if(packet_in[11] & 0x40)
v_lipo1 = 0x40; // Warning
else if(packet[11] & 0x80)
else if(packet_in[11] & 0x80)
v_lipo1 = 0x20; // Critical
else
v_lipo1 = 0x80; // Ok
}
else
{
if(packet[11] & 0x80)
if(packet_in[11] & 0x80)
v_lipo1 = 0x80; // Ok
else if(packet[11] & 0x40)
else if(packet_in[11] & 0x40)
v_lipo1 = 0x40; // Warning
else
v_lipo1 = 0x20; // Critical
}
telemetry_link=1;
}
#endif
}
#endif
uint16_t BUGSMINI_callback()
{
@@ -258,58 +256,52 @@ uint16_t BUGSMINI_callback()
switch(phase)
{
case BUGSMINI_BIND1:
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
if( XN297_IsRX() )
{ // RX fifo data ready
XN297_ReadPayload(packet, BUGSMINI_RX_PAYLOAD_SIZE);
XN297_ReadPayload(packet, BUGSMINI_RX_PAYLOAD_SIZE); // Not checking the CRC??
base_adr=BUGSMINI_EEPROM_OFFSET+(RX_num&0x0F)*2;
eeprom_write_byte((EE_ADDR)(base_adr+0),packet[1]); // Save rxid in EEPROM
eeprom_write_byte((EE_ADDR)(base_adr+1),packet[2]); // Save rxid in EEPROM
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
eeprom_write_byte((EE_ADDR)(base_adr+0),packet[1]); // Save rxid in EEPROM
eeprom_write_byte((EE_ADDR)(base_adr+1),packet[2]); // Save rxid in EEPROM
BUGSMINI_make_address();
XN297_SetTXAddr(rx_tx_addr, 5);
XN297_SetRXAddr(rx_tx_addr, 5);
XN297_SetRXAddr(rx_tx_addr, BUGSMINI_RX_PAYLOAD_SIZE);
phase = BUGSMINI_DATA1;
BIND_DONE;
return BUGSMINI_PACKET_INTERVAL;
break;
}
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
BUGSMINI_send_packet();
phase = BUGSMINI_BIND2;
return BUGSMINI_WRITE_WAIT;
case BUGSMINI_BIND2:
// switch to RX mode
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(RX_EN);
NRF24L01_FlushRx();
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO)
| _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
phase = BUGSMINI_BIND1;
return BUGSMINI_PACKET_INTERVAL - BUGSMINI_WRITE_WAIT;
case BUGSMINI_DATA1:
#ifdef MULTI_SYNC
telemetry_set_input_sync(BUGSMINI_PACKET_INTERVAL);
#endif
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // RX fifo data ready => read only 12 bytes to not overwrite channel change flag
XN297_ReadPayload(packet, 12);
BUGSMINI_update_telemetry();
}
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
#if defined(BUGS_HUB_TELEMETRY)
if( XN297_IsRX() )
{
XN297_ReadPayload(packet_in, BUGSMINI_RX_PAYLOAD_SIZE); // Not checking the CRC??
BUGSMINI_update_telemetry();
}
#endif
BUGSMINI_send_packet();
#if not defined(BUGS_HUB_TELEMETRY)
break;
#else
phase = BUGSMINI_DATA2;
return BUGSMINI_WRITE_WAIT;
case BUGSMINI_DATA2:
// switch to RX mode
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();
NRF24L01_SetTxRxMode(RX_EN);
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO)
| _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
phase = BUGSMINI_DATA1;
return BUGSMINI_PACKET_INTERVAL - BUGSMINI_WRITE_WAIT;
#endif
}
return BUGSMINI_PACKET_INTERVAL;
}
@@ -349,19 +341,19 @@ static void __attribute__((unused)) BUGSMINI_initialize_txid()
void BUGSMINI_init()
{
BUGSMINI_initialize_txid();
memset(packet, (uint8_t)0, BUGSMINI_TX_PAYLOAD_SIZE);
BUGSMINI_RF_init();
memset(packet, (uint8_t)0, BUGSMINI_TX_PAYLOAD_SIZE);
if(IS_BIND_IN_PROGRESS)
{
XN297_SetTXAddr((const uint8_t*)"mjxRC", 5);
XN297_SetRXAddr((const uint8_t*)"mjxRC", 5);
XN297_SetRXAddr((const uint8_t*)"mjxRC", BUGSMINI_RX_PAYLOAD_SIZE);
phase = BUGSMINI_BIND1;
}
else
{
BUGSMINI_make_address();
XN297_SetTXAddr(rx_tx_addr, 5);
XN297_SetRXAddr(rx_tx_addr, 5);
XN297_SetRXAddr(rx_tx_addr, BUGSMINI_RX_PAYLOAD_SIZE);
phase = BUGSMINI_DATA1;
}
armed = 0;

View File

@@ -15,7 +15,7 @@ Multiprotocol is distributed in the hope that it will be useful,
#if defined(BAYANG_RX_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
#define BAYANG_RX_PACKET_SIZE 15
#define BAYANG_RX_RF_NUM_CHANNELS 4
@@ -27,18 +27,15 @@ enum {
BAYANG_RX_DATA
};
static void __attribute__((unused)) Bayang_Rx_init_nrf24l01()
static void __attribute__((unused)) Bayang_Rx_RF_init()
{
const uint8_t bind_address[BAYANG_RX_ADDRESS_LENGTH] = { 0,0,0,0,0 };
NRF24L01_Initialize();
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr(bind_address, BAYANG_RX_ADDRESS_LENGTH);
XN297_SetRXAddr(bind_address, BAYANG_RX_ADDRESS_LENGTH);
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, BAYANG_RX_PACKET_SIZE + 2); // 2 extra bytes for xn297 crc
NRF24L01_WriteReg(NRF24L01_05_RF_CH, BAYANG_RX_RF_BIND_CHANNEL);
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();
NRF24L01_SetTxRxMode(RX_EN);
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
XN297_SetRXAddr(bind_address, BAYANG_RX_PACKET_SIZE);
XN297_RFChannel(BAYANG_RX_RF_BIND_CHANNEL);
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
}
static uint8_t __attribute__((unused)) Bayang_Rx_check_validity() {
@@ -91,7 +88,7 @@ static void __attribute__((unused)) Bayang_Rx_build_telemetry_packet()
void BAYANG_RX_init()
{
uint8_t i;
Bayang_Rx_init_nrf24l01();
Bayang_Rx_RF_init();
hopping_frequency_no = 0;
rx_data_started = false;
rx_data_received = false;
@@ -105,8 +102,9 @@ void BAYANG_RX_init()
rx_tx_addr[i] = eeprom_read_byte((EE_ADDR)temp++);
for (i = 0; i < BAYANG_RX_RF_NUM_CHANNELS; i++)
hopping_frequency[i] = eeprom_read_byte((EE_ADDR)temp++);
//XN297_HoppingCalib(BAYANG_RX_RF_NUM_CHANNELS);
XN297_SetTXAddr(rx_tx_addr, BAYANG_RX_ADDRESS_LENGTH);
XN297_SetRXAddr(rx_tx_addr, BAYANG_RX_ADDRESS_LENGTH);
XN297_SetRXAddr(rx_tx_addr, BAYANG_RX_PACKET_SIZE);
phase = BAYANG_RX_DATA;
}
}
@@ -116,86 +114,89 @@ uint16_t BAYANG_RX_callback()
uint8_t i;
static int8_t read_retry;
switch (phase) {
case BAYANG_RX_BIND:
if(IS_BIND_DONE)
{
BAYANG_RX_init(); // Abort bind
break;
}
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) {
// data received from TX
if (XN297_ReadPayload(packet, BAYANG_RX_PACKET_SIZE) && ( packet[0] == 0xA4 || packet[0] == 0xA2 ) && Bayang_Rx_check_validity()) {
// store tx info into eeprom
uint16_t temp = BAYANG_RX_EEPROM_OFFSET;
for (i = 0; i < 5; i++) {
rx_tx_addr[i] = packet[i + 1];
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[i]);
}
for (i = 0; i < 4; i++) {
hopping_frequency[i] = packet[i + 6];
eeprom_write_byte((EE_ADDR)temp++, hopping_frequency[i]);
}
XN297_SetTXAddr(rx_tx_addr, BAYANG_RX_ADDRESS_LENGTH);
XN297_SetRXAddr(rx_tx_addr, BAYANG_RX_ADDRESS_LENGTH);
BIND_DONE;
phase = BAYANG_RX_DATA;
}
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
}
break;
case BAYANG_RX_DATA:
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) {
if (XN297_ReadPayload(packet, BAYANG_RX_PACKET_SIZE) && packet[0] == 0xA5 && Bayang_Rx_check_validity()) {
if ((telemetry_link & 0x7F) == 0) {
Bayang_Rx_build_telemetry_packet();
telemetry_link = 1;
#ifdef SEND_CPPM
if(sub_protocol>0)
telemetry_link |= 0x80; // Disable telemetry output
#endif
}
rx_data_started = true;
rx_data_received = true;
read_retry = 8;
pps_counter++;
}
}
// packets per second
if (millis() - pps_timer >= 1000) {
pps_timer = millis();
debugln("%d pps", pps_counter);
RX_LQI = pps_counter >> 1;
pps_counter = 0;
}
// frequency hopping
if (read_retry++ >= 8) {
hopping_frequency_no++;
if (hopping_frequency_no >= BAYANG_RX_RF_NUM_CHANNELS)
hopping_frequency_no = 0;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
if (rx_data_started)
switch (phase)
{
case BAYANG_RX_BIND:
if(IS_BIND_DONE)
{
if(rx_data_received)
{ // In sync
rx_data_received = false;
read_retry = 5;
return 1500;
BAYANG_RX_init(); // Abort bind
break;
}
if ( XN297_IsRX() )
{
debugln("RX");
// data received from TX
if (XN297_ReadPayload(packet, BAYANG_RX_PACKET_SIZE) && ( packet[0] == 0xA4 || packet[0] == 0xA2 ) && Bayang_Rx_check_validity())
{
// store tx info into eeprom
uint16_t temp = BAYANG_RX_EEPROM_OFFSET;
for (i = 0; i < 5; i++) {
rx_tx_addr[i] = packet[i + 1];
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[i]);
}
for (i = 0; i < 4; i++) {
hopping_frequency[i] = packet[i + 6];
eeprom_write_byte((EE_ADDR)temp++, hopping_frequency[i]);
}
//XN297_HoppingCalib(BAYANG_RX_RF_NUM_CHANNELS);
XN297_SetTXAddr(rx_tx_addr, BAYANG_RX_ADDRESS_LENGTH);
XN297_SetRXAddr(rx_tx_addr, BAYANG_RX_PACKET_SIZE);
BIND_DONE;
phase = BAYANG_RX_DATA;
}
XN297_SetTxRxMode(RX_EN);
}
break;
case BAYANG_RX_DATA:
if ( XN297_IsRX() ) {
if (XN297_ReadPayload(packet, BAYANG_RX_PACKET_SIZE) && packet[0] == 0xA5 && Bayang_Rx_check_validity()) {
if ((telemetry_link & 0x7F) == 0) {
Bayang_Rx_build_telemetry_packet();
telemetry_link = 1;
#ifdef SEND_CPPM
if(sub_protocol>0)
telemetry_link |= 0x80; // Disable telemetry output
#endif
}
rx_data_started = true;
rx_data_received = true;
read_retry = 8;
pps_counter++;
}
}
// packets per second
if (millis() - pps_timer >= 1000) {
pps_timer = millis();
debugln("%d pps", pps_counter);
RX_LQI = pps_counter >> 1;
pps_counter = 0;
}
// frequency hopping
if (read_retry++ >= 8) {
hopping_frequency_no++;
if (hopping_frequency_no >= BAYANG_RX_RF_NUM_CHANNELS)
hopping_frequency_no = 0;
XN297_Hopping(hopping_frequency_no);
XN297_SetTxRxMode(RX_EN);
if (rx_data_started)
{
if(rx_data_received)
{ // In sync
rx_data_received = false;
read_retry = 5;
return 1500;
}
else
{ // packet lost
read_retry = 0;
if(RX_LQI==0) // communication lost
rx_data_started=false;
}
}
else
{ // packet lost
read_retry = 0;
if(RX_LQI==0) // communication lost
rx_data_started=false;
}
read_retry = -16; // retry longer until first packet is caught
}
else
read_retry = -16; // retry longer until first packet is caught
}
return 250;
return 250;
}
return 1000;
}

View File

@@ -17,7 +17,7 @@ Multiprotocol is distributed in the hope that it will be useful,
#if defined(BAYANG_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
#define BAYANG_BIND_COUNT 1000
#define BAYANG_PACKET_PERIOD 2000
@@ -97,6 +97,8 @@ static void __attribute__((unused)) BAYANG_send_packet()
}
else
{
XN297_Hopping(hopping_frequency_no++);
hopping_frequency_no%=BAYANG_RF_NUM_CHANNELS;
uint16_t val;
uint8_t dyntrim = 1;
switch (sub_protocol)
@@ -192,28 +194,18 @@ static void __attribute__((unused)) BAYANG_send_packet()
for (uint8_t i=0; i < BAYANG_PACKET_SIZE-1; i++)
packet[14] += packet[i];
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? rf_ch_num:hopping_frequency[hopping_frequency_no++]);
hopping_frequency_no%=BAYANG_RF_NUM_CHANNELS;
// Power on, TX mode, 2byte CRC
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
NRF24L01_FlushTx();
NRF24L01_SetTxRxMode(TX_EN);
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, BAYANG_PACKET_SIZE);
NRF24L01_SetPower(); // Set tx_power
}
#ifdef BAYANG_HUB_TELEMETRY
static void __attribute__((unused)) BAYANG_check_rx(void)
{
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
if( XN297_IsRX() )
{ // data received from model
XN297_ReadPayload(packet, BAYANG_PACKET_SIZE);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 255);
NRF24L01_FlushRx();
XN297_ReadPayload(packet, BAYANG_PACKET_SIZE); // Strange can't test the CRC since it seems to be disabled on telemetry packets...
uint8_t check = packet[0];
for (uint8_t i=1; i < BAYANG_PACKET_SIZE-1; i++)
check += packet[i];
@@ -233,8 +225,8 @@ static void __attribute__((unused)) BAYANG_check_rx(void)
telemetry_link=1;
#if defined HUB_TELEMETRY
// Multiplexed P, I, D values in packet[8] and packet[9].
// The two most significant bits specify which term is sent.
// Remaining 14 bits represent the value: 0 .. 16383
// The two most significant bits specify which term is sent.
// Remaining 14 bits represent the value: 0 .. 16383
frsky_send_user_frame(0x24+(packet[8]>>6), packet[9], packet[8] & 0x3F ); //0x24 = ACCEL_X_ID, so ACCEL_X_ID=P, ACCEL_Y_ID=I, ACCEL_Z_ID=D
#endif
telemetry_counter++;
@@ -242,27 +234,21 @@ static void __attribute__((unused)) BAYANG_check_rx(void)
telemetry_link=0; // Don't send anything yet
}
}
NRF24L01_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(TXRX_OFF);
}
#endif
static void __attribute__((unused)) BAYANG_RF_init()
{
NRF24L01_Initialize();
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr((uint8_t *)"\x00\x00\x00\x00\x00", BAYANG_ADDRESS_LENGTH);
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, BAYANG_PACKET_SIZE);
//XN297_HoppingCalib(BAYANG_RF_NUM_CHANNELS);
switch (sub_protocol)
{
case X16_AH:
case IRDRONE:
rf_ch_num = BAYANG_RF_BIND_CHANNEL_X16_AH;
break;
default:
rf_ch_num = BAYANG_RF_BIND_CHANNEL;
break;
}
//Set bind channel
uint8_t ch = BAYANG_RF_BIND_CHANNEL;
if(sub_protocol == X16_AH || sub_protocol == IRDRONE)
ch = BAYANG_RF_BIND_CHANNEL_X16_AH;
XN297_RFChannel(ch);
}
enum {
@@ -287,7 +273,7 @@ uint16_t BAYANG_callback()
{
XN297_SetTXAddr(rx_tx_addr, BAYANG_ADDRESS_LENGTH);
#ifdef BAYANG_HUB_TELEMETRY
XN297_SetRXAddr(rx_tx_addr, BAYANG_ADDRESS_LENGTH);
XN297_SetRXAddr(rx_tx_addr, BAYANG_PACKET_SIZE);
#endif
BIND_DONE;
phase++; //WRITE
@@ -322,9 +308,9 @@ uint16_t BAYANG_callback()
// switch radio to rx as soon as packet is sent
start=(uint16_t)micros();
while ((uint16_t)((uint16_t)micros()-(uint16_t)start) < 1000) // Wait max 1ms
if((NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)))
if(XN297_IsPacketSent())
break;
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x03);
XN297_SetTxRxMode(RX_EN);
phase++; // READ
return BAYANG_PACKET_TELEM_PERIOD - BAYANG_CHECK_DELAY - BAYANG_READ_DELAY;
case BAYANG_READ:

View File

@@ -190,7 +190,9 @@ static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode)
}
TxPacket.option = (bindMode) ? (option & (~CABELL_OPTION_MASK_CHANNEL_REDUCTION)) : option; //remove channel reduction if in bind mode
}
TxPacket.reserved = 0;
rf_ch_num = CABELL_getNextChannel (hopping_frequency,CABELL_RADIO_CHANNELS, rf_ch_num);
TxPacket.reserved = rf_ch_num & 0x3F;
TxPacket.modelNum = RX_num;
uint16_t checkSum = TxPacket.modelNum + TxPacket.option + TxPacket.RxMode + TxPacket.reserved; // Start Calculate checksum
@@ -244,7 +246,6 @@ static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode)
TxPacket.checkSum_LSB = checkSum & 0x00FF;
// Set channel for next transmission
rf_ch_num = CABELL_getNextChannel (hopping_frequency,CABELL_RADIO_CHANNELS, rf_ch_num);
NRF24L01_WriteReg(NRF24L01_05_RF_CH,rf_ch_num);
//NRF24L01_FlushTx(); //just in case things got hung up
@@ -279,39 +280,44 @@ static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode)
static void __attribute__((unused)) CABELL_getChannelSequence (uint8_t outArray[], uint8_t numChannels, uint64_t permutation)
{
/* This procedure initializes an array with the sequence progression of channels.
* This is not the actual channels itself, but the sequence base to be used within bands of
* This is not the actual channels itself, but the sequence base to be used within bands of
* channels.
*
*
* There are numChannels! permutations for arranging the channels
* one of these permutations will be calculated based on the permutation input
* permutation should be between 1 and numChannels! but the routine will constrain it
* if these bounds are exceeded. Typically the radio's unique TX ID should be used.
*
*
* The maximum numChannels is 20. Anything larger than this will cause the uint64_t
* variables to overflow, yielding unknown results (possibly infinite loop?). Therefor
* this routine constrains the value.
*/
*/
uint8_t i; //iterator counts numChannels
uint64_t indexOfNextSequenceValue;
uint64_t numChannelsFactorial=1;
uint32_t indexOfNextSequenceValue;
uint32_t numChannelsFactorial=1;
uint32_t perm32 ;
uint8_t sequenceValue;
numChannels = constrain(numChannels,1,20);
numChannels = constrain(numChannels,1,9);
for (i = 1; i <= numChannels;i++)
{
numChannelsFactorial *= i; // Calculate n!
outArray[i-1] = i-1; // Initialize array with the sequence
numChannelsFactorial *= i; // Calculate n!
outArray[i-1] = i-1; // Initialize array with the sequence
}
permutation = (permutation % numChannelsFactorial) + 1; // permutation must be between 1 and n! or this algorithm will infinite loop
perm32 = permutation >> 8 ; // Shift 40 bit input to 32 bit
perm32 = (perm32 % numChannelsFactorial); // permutation must be between 1 and n! or this algorithm will infinite loop
perm32 <<= 8 ; // Shift back 8 bits
perm32 += permutation & 0x00FF ; // Tack on least 8 bits
perm32 = (perm32 % numChannelsFactorial) + 1; // permutation must be between 1 and n! or this algorithm will infinite loop
//Rearrange the array elements based on the permutation selected
for (i=0, permutation--; i<numChannels; i++ )
for (i=0, perm32--; i<numChannels; i++ )
{
numChannelsFactorial /= ((uint64_t)numChannels)-i;
indexOfNextSequenceValue = i+(permutation/numChannelsFactorial);
permutation %= numChannelsFactorial;
numChannelsFactorial /= numChannels-i;
indexOfNextSequenceValue = i+(perm32/numChannelsFactorial);
perm32 %= numChannelsFactorial;
//Copy the value in the selected array position
sequenceValue = outArray[indexOfNextSequenceValue];

View File

@@ -195,6 +195,7 @@ void __attribute__((unused)) CC2500_250K_Init()
// TX Power = 0
// Whitening = false
// Fast Frequency Hopping - no PLL auto calibration
/* //Previous config
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x01); // Packet Automation Control
CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0A); // Frequency Synthesizer Control
CC2500_WriteReg(CC2500_0C_FSCTRL0, option); // Frequency offset hack
@@ -217,6 +218,42 @@ void __attribute__((unused)) CC2500_250K_Init()
CC2500_WriteReg(CC2500_23_FSCAL3, 0xEA); // Frequency Synthesizer Calibration
CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // Frequency Synthesizer Calibration
CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // Frequency Synthesizer Calibration
*/
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05); // Packet Automation Control, address check true auto append RSSI & LQI
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x00); // Packet Automation Control, fixed packet len
CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0A); // Frequency Synthesizer Control (IF Frequency)
CC2500_WriteReg(CC2500_0C_FSCTRL0, 0x00); // Frequency Synthesizer Control
CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // Frequency Control Word, High Byte
CC2500_WriteReg(CC2500_0E_FREQ1, 0x4E); // Frequency Control Word, Middle Byte
CC2500_WriteReg(CC2500_0F_FREQ0, 0xC5); // Frequency Control Word, Low Byte
CC2500_WriteReg(CC2500_10_MDMCFG4, 0x3D); // Modem Configuration Set to 406kHz BW filter
CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration
CC2500_WriteReg(CC2500_12_MDMCFG2, 0x10); // Modem Configuration, GFSK, no preambule and no sync word -> TX by default
CC2500_WriteReg(CC2500_13_MDMCFG1, 0x03); // Modem Configuration, 2 bytes of preamble
CC2500_WriteReg(CC2500_14_MDMCFG0, 0xA4); // Modem Configuration
CC2500_WriteReg(CC2500_15_DEVIATN, 0x62); // Modem Deviation Setting
CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // Main Radio Control State Machine Configuration
CC2500_WriteReg(CC2500_19_FOCCFG, 0x1D); // Frequency Offset Compensation Configuration
CC2500_WriteReg(CC2500_1A_BSCFG, 0x1C); // Bit Synchronization Configuration
CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xC7); // AGC Control
CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x00); // AGC Control
CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0xB0); // AGC Control
CC2500_WriteReg(CC2500_21_FREND1, 0xB6); // Front End RX Configuration
CC2500_WriteReg(CC2500_23_FSCAL3, 0xEA); // Frequency Synthesizer Calibration
CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // Frequency Synthesizer Calibration
CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // Frequency Synthesizer Calibration
//Prep RX
// Set first 3 bytes of rx addr in [0]->SYNC1, [1]->SYNC0 and [2]->ADDR
// CC2500_WriteReg(CC2500_04_SYNC1, [0]); // Sync word, high byte
// CC2500_WriteReg(CC2500_05_SYNC0, [1]); // Sync word, low byte
// CC2500_WriteReg(CC2500_09_ADDR, [2]); // Set addr
//RX
// CC2500_WriteReg(CC2500_12_MDMCFG2, 0x12); // Modem Configuration, GFSK, 16/16 Sync Word TX&RX
//TX
// CC2500_WriteReg(CC2500_12_MDMCFG2, 0x10); // Modem Configuration, GFSK, no preambule and no sync word
// need to set packet length before sending/receiving
// CC2500_WriteReg(CC2500_06_PKTLEN, cc2500_packet_len); // Packet len, fix packet len
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
@@ -250,87 +287,4 @@ void __attribute__((unused)) CC2500_250K_RFChannel(uint8_t number)
CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);
}
//NRF emulation layer with CRC16 enabled
uint8_t cc2500_nrf_tx_addr[5], cc2500_nrf_addr_len;
void __attribute__((unused)) CC2500_250K_NRF_SetTXAddr(uint8_t* addr, uint8_t len)
{
cc2500_nrf_addr_len = len;
memcpy(cc2500_nrf_tx_addr, addr, len);
}
void __attribute__((unused)) CC2500_250K_NRF_WritePayload(uint8_t* msg, uint8_t len)
{
#if defined(ESKY150V2_CC2500_INO)
uint8_t buf[158];
#else
uint8_t buf[35];
#endif
uint8_t last = 0;
uint8_t i;
//nrf preamble
if(cc2500_nrf_tx_addr[cc2500_nrf_addr_len - 1] & 0x80)
buf[0]=0xAA;
else
buf[0]=0x55;
last++;
// address
for (i = 0; i < cc2500_nrf_addr_len; ++i)
buf[last++] = cc2500_nrf_tx_addr[cc2500_nrf_addr_len - i - 1];
// payload
for (i = 0; i < len; ++i)
buf[last++] = msg[i];
// crc
crc = 0xffff;
for (uint8_t i = 1; i < last; ++i)
crc16_update( buf[i], 8);
buf[last++] = crc >> 8;
buf[last++] = crc & 0xff;
buf[last++] = 0;
//for(uint8_t i=0;i<last;i++)
// debug("%02X ",buf[i]);
//debugln("");
// stop TX/RX
CC2500_Strobe(CC2500_SIDLE);
// flush tx FIFO
CC2500_Strobe(CC2500_SFTX);
// packet length
CC2500_WriteReg(CC2500_3F_TXFIFO, last);
// transmit nrf packet
uint8_t *buff=buf;
uint8_t status;
if(last>63)
{
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, 63);
CC2500_Strobe(CC2500_STX);
last-=63;
buff+=63;
while(last)
{//Loop until all the data is sent
do
{// Wait for the FIFO to become available
status=CC2500_ReadReg(CC2500_3A_TXBYTES | CC2500_READ_BURST);
}
while((status&0x7F)>31 && (status&0x80)==0);
if(last>31)
{//Send 31 bytes
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, 31);
last-=31;
buff+=31;
}
else
{//Send last bytes
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, last);
last=0;
}
}
}
else
{//Send packet
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, last);
CC2500_Strobe(CC2500_STX);
}
}
#endif

View File

@@ -16,7 +16,7 @@
#if defined(CG023_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
#define CG023_PACKET_PERIOD 8200 // Timeout for callback in uSec
#define CG023_INITIAL_WAIT 500
@@ -63,9 +63,15 @@ static void __attribute__((unused)) CG023_send_packet()
aileron = convert_channel_16b_limit(AILERON, 0x43, 0xBB);
if (IS_BIND_IN_PROGRESS)
{
packet[0]= 0xaa;
XN297_RFChannel(CG023_RF_BIND_CHANNEL);
}
else
{
packet[0]= 0x55;
XN297_RFChannel(hopping_frequency_no);
}
// transmitter id
packet[1] = rx_tx_addr[0];
packet[2] = rx_tx_addr[1];
@@ -85,7 +91,7 @@ static void __attribute__((unused)) CG023_send_packet()
if(sub_protocol==CG023)
{
// rate
packet[13] = CG023_FLAG_RATE_HIGH
packet[13] = CG023_FLAG_RATE_HIGH
| GET_FLAG(CH5_SW,CG023_FLAG_FLIP)
| GET_FLAG(CH6_SW,CG023_FLAG_LED_OFF)
| GET_FLAG(CH7_SW,CG023_FLAG_STILL)
@@ -95,7 +101,7 @@ static void __attribute__((unused)) CG023_send_packet()
else
{// YD829
// rate
packet[13] = YD829_FLAG_RATE_HIGH
packet[13] = YD829_FLAG_RATE_HIGH
| GET_FLAG(CH5_SW,YD829_FLAG_FLIP)
| GET_FLAG(CH7_SW,YD829_FLAG_STILL)
| GET_FLAG(CH8_SW,YD829_FLAG_VIDEO)
@@ -103,25 +109,15 @@ static void __attribute__((unused)) CG023_send_packet()
}
packet[14] = 0;
// Power on, TX mode, 2byte CRC
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
if (IS_BIND_IN_PROGRESS)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, CG023_RF_BIND_CHANNEL);
else
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency_no);
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
// Send
XN297_SetTxRxMode(TX_EN);
XN297_SetPower();
XN297_WritePayload(packet, CG023_PACKET_SIZE);
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) CG023_RF_init()
{
NRF24L01_Initialize();
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr((uint8_t *)"\x26\xA8\x67\x35\xCC", 5);
}
@@ -144,7 +140,7 @@ uint16_t CG023_callback()
static void __attribute__((unused)) CG023_initialize_txid()
{
rx_tx_addr[0]= 0x80 | (rx_tx_addr[0] % 0x40);
if( rx_tx_addr[0] == 0xAA) // avoid using same freq for bind and data channel
if( rx_tx_addr[0] == 0xAA) // avoid using same freq for bind and data channel
rx_tx_addr[0] ++;
hopping_frequency_no = rx_tx_addr[0] - 0x7D; // rf channel for data packets
}

View File

@@ -17,7 +17,7 @@
#if defined(CX10_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
#define CX10_BIND_COUNT 4360 // 6 seconds
#define CX10_PACKET_SIZE 15
@@ -46,12 +46,12 @@ enum {
CX10_DATA
};
static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
static void __attribute__((unused)) CX10_Write_Packet()
{
uint8_t offset = 0;
if(sub_protocol == CX10_BLUE)
offset = 4;
packet[0] = bind ? 0xAA : 0x55;
packet[0] = IS_BIND_IN_PROGRESS ? 0xAA : 0x55;
packet[1] = rx_tx_addr[0];
packet[2] = rx_tx_addr[1];
packet[3] = rx_tx_addr[2];
@@ -62,57 +62,57 @@ static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
uint16_t throttle=convert_channel_16b_limit(THROTTLE,1000,2000);
uint16_t rudder= convert_channel_16b_limit(RUDDER ,2000,1000);
// Channel 5 - flip flag
packet[12+offset] = GET_FLAG(CH5_SW,CX10_FLAG_FLIP); // flip flag applied on rudder
packet[12+offset] = GET_FLAG(CH5_SW,CX10_FLAG_FLIP); // flip flag applied on rudder
// Channel 6 - rate mode is 2 lsb of packet 13
if(CH6_SW) // rate 3 / headless on CX-10A
if(CH6_SW) // rate 3 / headless on CX-10A
flags = 0x02;
else
if(Channel_data[CH6] < CHANNEL_MIN_COMMAND)
flags = 0x00; // rate 1
flags = 0x00; // rate 1
else
flags = 0x01; // rate 2
uint8_t flags2=0; // packet 14
flags = 0x01; // rate 2
uint8_t flags2=0; // packet 14
uint8_t video_state=packet[14] & 0x21;
switch(sub_protocol)
{
case CX10_BLUE:
flags |= GET_FLAG(!CH7_SW, 0x10) // Channel 7 - picture
|GET_FLAG( CH8_SW, 0x08); // Channel 8 - video
flags |= GET_FLAG(!CH7_SW, 0x10) // Channel 7 - picture
|GET_FLAG( CH8_SW, 0x08); // Channel 8 - video
break;
case F_Q282:
case F_Q242:
case F_Q222:
memcpy(&packet[15], "\x10\x10\xaa\xaa\x00\x00", 6);
//FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|XCAL|YCAL
flags2 = GET_FLAG(CH5_SW, 0x80) // Channel 5 - FLIP
|GET_FLAG(!CH6_SW, 0x40) // Channel 6 - LED
|GET_FLAG(CH9_SW, 0x08) // Channel 9 - HEADLESS
|GET_FLAG(CH11_SW, 0x04) // Channel 11 - XCAL
|GET_FLAG(CH12_SW, 0x02); // Channel 12 - YCAL or Start/Stop motors on JXD 509
flags2 = GET_FLAG(CH5_SW, 0x80) // Channel 5 - FLIP
|GET_FLAG(!CH6_SW, 0x40) // Channel 6 - LED
|GET_FLAG(CH9_SW, 0x08) // Channel 9 - HEADLESS
|GET_FLAG(CH11_SW, 0x04) // Channel 11 - XCAL
|GET_FLAG(CH12_SW, 0x02); // Channel 12 - YCAL or Start/Stop motors on JXD 509
if(sub_protocol==F_Q242)
{
flags=2;
flags2|= GET_FLAG(CH7_SW,0x01) // Channel 7 - picture
|GET_FLAG(CH8_SW,0x10); // Channel 8 - video
flags2|= GET_FLAG(CH7_SW,0x01) // Channel 7 - picture
|GET_FLAG(CH8_SW,0x10); // Channel 8 - video
packet[17]=0x00;
packet[18]=0x00;
}
else
{ // F_Q282 & F_Q222
flags=3; // expert
if(CH8_SW) // Channel 8 - F_Q282 video / F_Q222 Module 1
flags=3; // expert
if(CH8_SW) // Channel 8 - F_Q282 video / F_Q222 Module 1
{
if (!(video_state & 0x20)) video_state ^= 0x21;
}
else
if (video_state & 0x20) video_state &= 0x01;
flags2 |= video_state
|GET_FLAG(CH7_SW,0x10); // Channel 7 - F_Q282 picture / F_Q222 Module 2
|GET_FLAG(CH7_SW,0x10); // Channel 7 - F_Q282 picture / F_Q222 Module 2
}
if(CH10_SW) flags |=0x80; // Channel 10 - RTH
if(CH10_SW) flags |=0x80; // Channel 10 - RTH
break;
case DM007:
aileron = 3000 - aileron;
@@ -128,16 +128,16 @@ static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
if(CH8_SW) packet[12] &= ~CX10_FLAG_FLIP;
case JC3015_1:
//FLIP|MODE|PICTURE|VIDEO
flags2= GET_FLAG(CH7_SW,_BV(3)) // Channel 7
|GET_FLAG(CH8_SW,_BV(4)); // Channel 8
flags2= GET_FLAG(CH7_SW,_BV(3)) // Channel 7
|GET_FLAG(CH8_SW,_BV(4)); // Channel 8
break;
case MK33041:
elevator = 3000 - elevator;
//FLIP|MODE|PICTURE|VIDEO|HEADLESS|RTH
flags|=GET_FLAG(CH7_SW,_BV(7)) // Channel 7 - picture
|GET_FLAG(CH10_SW,_BV(2)); // Channel 10 - rth
flags2=GET_FLAG(CH8_SW,_BV(0)) // Channel 8 - video
|GET_FLAG(CH9_SW,_BV(5)); // Channel 9 - headless
flags|=GET_FLAG(CH7_SW,_BV(7)) // Channel 7 - picture
|GET_FLAG(CH10_SW,_BV(2)); // Channel 10 - rth
flags2=GET_FLAG(CH8_SW,_BV(0)) // Channel 8 - video
|GET_FLAG(CH9_SW,_BV(5)); // Channel 9 - headless
break;
}
packet[5+offset] = lowByte(aileron);
@@ -151,32 +151,23 @@ static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
packet[13+offset]=flags;
packet[14+offset]=flags2;
// Power on, TX mode, 2byte CRC
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
if (bind)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, CX10_RF_BIND_CHANNEL);
else
// Send
if(IS_BIND_DONE)
{
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]);
XN297_Hopping(hopping_frequency_no++);
hopping_frequency_no %= CX10_NUM_RF_CHANNELS;
}
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, packet_length);
NRF24L01_SetPower();
}
static void __attribute__((unused)) CX10_RF_init()
{
NRF24L01_Initialize();
XN297_SetTXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc",5);
XN297_SetRXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc",5);
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, packet_length); // rx pipe 0 (used only for blue board)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, CX10_RF_BIND_CHANNEL);
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc", 5);
XN297_SetRXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc", packet_length);
XN297_RFChannel(CX10_RF_BIND_CHANNEL);
}
uint16_t CX10_callback()
@@ -190,43 +181,39 @@ uint16_t CX10_callback()
}
else
{
CX10_Write_Packet(1);
CX10_Write_Packet();
bind_counter--;
}
break;
case CX10_BIND2:
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
// switch to TX mode
if( XN297_IsRX() )
{ // RX fifo data ready
XN297_ReadPayload(packet, packet_length);
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
if(packet[9] == 1)
debugln("RX");
if(XN297_ReadPayload(packet, packet_length) && packet[9] == 1)
{
BIND_DONE;
XN297_SetTxRxMode(TXRX_OFF);
phase = CX10_DATA;
break;
}
}
else
{
// switch to TX mode
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushTx();
NRF24L01_SetTxRxMode(TX_EN);
CX10_Write_Packet(1);
XN297_SetTxRxMode(TXRX_OFF);
CX10_Write_Packet();
// wait for packet to be sent
while( (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)) == 0); //delayMicroseconds(400);
// switch to RX mode
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();
NRF24L01_SetTxRxMode(RX_EN);
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
while( !XN297_IsPacketSent()); //delayMicroseconds(400);
}
// switch to RX mode
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
break;
case CX10_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
CX10_Write_Packet(0);
CX10_Write_Packet();
break;
}
return packet_period;

View File

@@ -79,13 +79,24 @@ uint8_t CYRF_Reset()
void CYRF_GetMfgData(uint8_t data[])
{
#ifndef FORCE_CYRF_ID
/* Fuses power on */
CYRF_WriteRegister(CYRF_25_MFG_ID, 0xFF);
if(eeprom_read_byte((EE_ADDR)EEPROM_CID_INIT_OFFSET)==0xf0)
{//read Cyrf ID from EEPROM
for(uint8_t i=0;i<6;i++)
data[i] = eeprom_read_byte((EE_ADDR)EEPROM_CID_OFFSET+i);
}
else
{//read Cyrf ID and store it EEPROM
/* Fuses power on */
CYRF_WriteRegister(CYRF_25_MFG_ID, 0xFF);
CYRF_ReadRegisterMulti(CYRF_25_MFG_ID, data, 6);
CYRF_ReadRegisterMulti(CYRF_25_MFG_ID, data, 6);
for(uint8_t i=0;i<6;i++)
eeprom_write_byte((EE_ADDR)EEPROM_CID_OFFSET+i, data[i]);
eeprom_write_byte((EE_ADDR)EEPROM_CID_INIT_OFFSET, 0xf0);
/* Fuses power off */
CYRF_WriteRegister(CYRF_25_MFG_ID, 0x00);
/* Fuses power off */
CYRF_WriteRegister(CYRF_25_MFG_ID, 0x00);
}
#else
memcpy(data,FORCE_CYRF_ID,6);
#endif
@@ -258,7 +269,7 @@ void CYRF_FindBestChannels(uint8_t *channels, uint8_t len, uint8_t minspace, uin
delayMilliseconds(1);
for(i = 0; i < NUM_FREQ; i++)
{
CYRF_ConfigRFChannel(i);
CYRF_ConfigRFChannel(protocol==PROTO_LOSI?i|1:i);
delayMicroseconds(270); //slow channel require 270usec for synthesizer to settle
if( !(CYRF_ReadRegister(CYRF_05_RX_CTRL) & 0x80)) {
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x80); //Prepare to receive

View File

@@ -16,7 +16,7 @@
#if defined(DM002_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
#define DM002_PACKET_PERIOD 6100 // Timeout for callback in uSec
#define DM002_INITIAL_WAIT 500
@@ -24,7 +24,6 @@
#define DM002_RF_BIND_CHANNEL 0x27
#define DM002_BIND_COUNT 655 // 4 seconds
enum DM002_FLAGS {
// flags going to packet[9]
DM002_FLAG_FLIP = 0x01,
@@ -75,28 +74,23 @@ static void __attribute__((unused)) DM002_send_packet()
packet_count&=0x0F;
packet[10] = packet_count;
packet_count++;
XN297_Hopping(hopping_frequency_no);
}
//CRC
for(uint8_t i=0;i<DM002_PACKET_SIZE-1;i++)
packet[11]+=packet[i];
// Power on, TX mode, 2byte CRC
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? DM002_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no]);
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
//Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, DM002_PACKET_SIZE);
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) DM002_RF_init()
{
NRF24L01_Initialize();
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr((uint8_t *)"\x26\xA8\x67\x35\xCC", 5);
XN297_RFChannel(DM002_RF_BIND_CHANNEL);
}
uint16_t DM002_callback()

View File

@@ -117,7 +117,9 @@ static void __attribute__((unused)) DSM_cyrf_configdata()
static uint8_t __attribute__((unused)) DSM_get_pn_row(uint8_t channel, bool dsmx)
{
return (dsmx ? (channel - 2) % 5 : channel % 5);
if(protocol == PROTO_DSM && sub_protocol == DSMR)
return (channel + 2) % 5;
return (dsmx ? (channel - 2) % 5 : channel % 5);
}
static void __attribute__((unused)) DSM_set_sop_data_crc(bool ch2, bool dsmx)
@@ -127,10 +129,14 @@ static void __attribute__((unused)) DSM_set_sop_data_crc(bool ch2, bool dsmx)
if(ch2)
CYRF_ConfigCRCSeed(seed); //CH2
else
CYRF_ConfigCRCSeed(~seed); //CH1
CYRF_ConfigCRCSeed(~seed); //CH1, DSMR only use CH1
uint8_t pn_row = DSM_get_pn_row(hopping_frequency[hopping_frequency_no], dsmx);
uint8_t code[16];
#if 0
debug_time();
debug(" crc:%04X,row:%d,col:%d,rf:%02X",(~seed)&0xffff,pn_row,sop_col,hopping_frequency[hopping_frequency_no]);
#endif
DSM_read_code(code,pn_row,sop_col,8); // pn_row between 0 and 4, sop_col between 1 and 7
CYRF_ConfigSOPCode(code);
DSM_read_code(code,pn_row,7 - sop_col,8); // 7-sop_col between 0 and 6

View File

@@ -247,10 +247,9 @@ uint16_t DSM_RX_callback()
eeprom_write_byte((EE_ADDR)temp++, cyrfmfg_id[i]);
debug(" %02X", cyrfmfg_id[i]);
}
// check num_ch
// save num_ch
num_ch=packet_in[11];
if(num_ch>12) num_ch=12;
//check DSM_rx_type
// store DSM_rx_type
/*packet[12] 1 byte -> max DSM type allowed:
0x01 => 22ms 1024 DSM2 1 packet => number of channels is <8
0x02 => 22ms 1024 DSM2 2 packets => either a number of channel >7
@@ -262,22 +261,6 @@ uint16_t DSM_RX_callback()
&0xF0 => false=1024, true=2048 */
DSM_rx_type=packet_in[12];
debugln(", num_ch=%d, type=%02X",num_ch, DSM_rx_type);
switch(DSM_rx_type)
{
case 0x01:
if(num_ch>7) DSM_rx_type = 0x02; // Can't be 0x01 with this number of channels
break;
case 0xA2:
if(num_ch>7) DSM_rx_type = 0xB2; // Can't be 0xA2 with this number of channels
break;
case 0x02:
case 0x12:
case 0xB2:
break;
default: // Unknown type, default to DSMX 11ms
DSM_rx_type = 0xB2;
break;
}
eeprom_write_byte((EE_ADDR)temp, DSM_rx_type);
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
CYRF_SetTxRxMode(TX_EN); // Force end state TX

View File

@@ -86,12 +86,14 @@ static void __attribute__((unused)) DSM_build_bind_packet()
if(sub_protocol==DSM_AUTO)
packet[11] = 12;
else
packet[11] = num_ch;
packet[11] = num_ch; // DX5 DSMR sends 0x48...
if (sub_protocol==DSM2_1F)
packet[12]=num_ch<8?0x01:0x02; // DSM2/1024 1 or 2 packets depending on the number of channels
if (sub_protocol==DSMR)
packet[12] = 0xa2;
else if (sub_protocol==DSM2_1F)
packet[12] = num_ch<8?0x01:0x02; // DSM2/1024 1 or 2 packets depending on the number of channels
else if(sub_protocol==DSM2_2F)
packet[12]=0x12; // DSM2/2048 2 packets
packet[12] = 0x12; // DSM2/2048 2 packets
else if(sub_protocol==DSMX_1F)
#if defined DSM_TELEMETRY
packet[12] = 0xb2; // DSMX/2048 2 packets
@@ -99,8 +101,9 @@ static void __attribute__((unused)) DSM_build_bind_packet()
packet[12] = num_ch<8? 0xa2 : 0xb2; // DSMX/2048 1 or 2 packets depending on the number of channels
#endif
else // DSMX_2F && DSM_AUTO
packet[12]=0xb2; // DSMX/2048 2 packets
packet[12] = 0xb2; // DSMX/2048 2 packets
packet[13] = 0x00; //???
for(i = 8; i < 14; i++)
sum += packet[i];
@@ -126,6 +129,9 @@ static void __attribute__((unused)) DSM_update_channels()
if(num_ch<3 || num_ch>12)
num_ch=6; // Default to 6 channels if invalid choice...
if(sub_protocol==DSMR && num_ch>7)
num_ch=7; // Max 7 channels in DSMR
// Create channel map based on number of channels and refresh rate
uint8_t idx=num_ch-3;
if((option & 0x40) && num_ch>7 && num_ch<12)
@@ -141,19 +147,32 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
if(prev_option!=option)
DSM_update_channels();
if (sub_protocol==DSMX_2F || sub_protocol==DSMX_1F )
if (sub_protocol==DSMX_2F || sub_protocol==DSMX_1F)
{//DSMX
packet[0] = cyrfmfg_id[2];
packet[1] = cyrfmfg_id[3];
}
else
{//DSM2
{//DSM2 && DSMR
packet[0] = (0xff ^ cyrfmfg_id[2]);
packet[1] = (0xff ^ cyrfmfg_id[3]);
if(sub_protocol==DSM2_1F)
bits=10; // Only DSM2_1F is using a resolution of 1024
}
if(sub_protocol == DSMR)
{
for (uint8_t i = 0; i < 7; i++)
{
uint16_t value = 0x0000;
if(i < num_ch)
value=Channel_data[i]<<1;
packet[i*2+2] = (value >> 8) & 0xff;
packet[i*2+3] = (value >> 0) & 0xff;
}
return;
}
#ifdef DSM_THROTTLE_KILL_CH
uint16_t kill_ch=Channel_data[DSM_THROTTLE_KILL_CH-1];
#endif
@@ -189,8 +208,8 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
if(bits==10) value>>=1;
value |= (upper && i==0 ? 0x8000 : 0) | (idx << bits);
}
packet[i*2+2] = (value >> 8) & 0xff;
packet[i*2+3] = (value >> 0) & 0xff;
packet[i*2+2] = value >> 8;
packet[i*2+3] = value;
}
#ifdef DSM_FWD_PGM
if(upper==0 && DSM_SerialRX && (DSM_SerialRX_val[0]&0xF8)==0x70 )
@@ -319,26 +338,32 @@ uint16_t DSM_callback()
DSM_cyrf_configdata();
CYRF_SetTxRxMode(TX_EN);
hopping_frequency_no = 0;
phase = DSM_CH1_WRITE_A; // in fact phase++
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_2F||sub_protocol==DSMX_1F);
phase = DSM_CH1_WRITE_A; // in fact phase++
if(sub_protocol == DSMR)
DSM_set_sop_data_crc(false, true);
else
DSM_set_sop_data_crc(true, sub_protocol==DSMX_2F||sub_protocol==DSMX_1F); //prep CH1
return 10000;
case DSM_CH1_WRITE_A:
#ifdef MULTI_SYNC
telemetry_set_input_sync(11000); // Always request 11ms spacing even if we don't use half of it in 22ms mode
telemetry_set_input_sync(11000); // Always request 11ms spacing even if we don't use half of it in 22ms mode
#endif
CYRF_SetPower(0x28); //Keep transmit power in sync
if(sub_protocol == DSMR)
CYRF_SetPower(0x08); //Keep transmit power in sync
else
CYRF_SetPower(0x28); //Keep transmit power in sync
case DSM_CH1_WRITE_B:
DSM_build_data_packet(phase == DSM_CH1_WRITE_B); // build lower or upper channels
case DSM_CH2_WRITE_A:
case DSM_CH2_WRITE_B:
CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS); // clear IRQ flags
CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS); // clear IRQ flags
CYRF_WriteDataPacket(packet);
#if 0
for(uint8_t i=0;i<16;i++)
debug(" %02X", packet[i]);
debugln("");
#endif
phase++; // change from WRITE to CHECK mode
phase++; // change from WRITE to CHECK mode
return DSM_WRITE_DELAY;
case DSM_CH1_CHECK_A:
case DSM_CH1_CHECK_B:
@@ -349,7 +374,7 @@ uint16_t DSM_callback()
if((CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80) == 0x00)
break;
if(phase==DSM_CH1_CHECK_A || phase==DSM_CH1_CHECK_B)
if((phase==DSM_CH1_CHECK_A || phase==DSM_CH1_CHECK_B) && sub_protocol!=DSMR)
{
#if defined DSM_TELEMETRY
// reset cyrf6936 if freezed after switching from TX to RX
@@ -361,14 +386,19 @@ uint16_t DSM_callback()
CYRF_SetTxRxMode(TX_EN);
}
#endif
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_2F || sub_protocol==DSMX_1F);
phase++; // change from CH1_CHECK to CH2_WRITE
DSM_set_sop_data_crc(true, sub_protocol==DSMX_2F||sub_protocol==DSMX_1F); // prep CH2
phase++; // change from CH1_CHECK to CH2_WRITE
return DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY;
}
#if defined DSM_TELEMETRY
phase++; // change from CH2_CHECK to CH2_READ
CYRF_SetTxRxMode(RX_EN); //Receive mode
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //0x80??? //Prepare to receive
if(sub_protocol==DSMR)
{
phase = DSM_CH2_READ_B;
return 11000 - DSM_WRITE_DELAY - DSM_READ_DELAY;
}
#ifdef DSM_GR300
if(num_ch==3)
return timing - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY;
@@ -418,7 +448,7 @@ uint16_t DSM_callback()
phase = DSM_CH1_WRITE_A; //Transmit lower
CYRF_SetTxRxMode(TX_EN); //TX mode
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); //Clear abort RX operation
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_2F||sub_protocol==DSMX_1F);
DSM_set_sop_data_crc(false, sub_protocol==DSMX_2F||sub_protocol==DSMX_1F||sub_protocol==DSMR);
return DSM_READ_DELAY;
#else
// No telemetry
@@ -449,25 +479,65 @@ uint16_t DSM_callback()
return 0;
}
const uint8_t PROGMEM DSMR_ID_FREQ[][4 + 23] = {
{ 0x71, 0x74, 0x1c, 0xe4, 0x11, 0x2f, 0x17, 0x3d, 0x23, 0x3b, 0x0f, 0x21, 0x25, 0x49, 0x1d, 0x13, 0x4d, 0x1f, 0x41, 0x4b, 0x47, 0x05, 0x27, 0x15, 0x19, 0x3f, 0x07 },
{ 0xfe, 0xfe, 0xfe, 0xfe, 0x45, 0x31, 0x33, 0x4b, 0x11, 0x29, 0x49, 0x3f, 0x09, 0x13, 0x47, 0x21, 0x1d, 0x43, 0x1f, 0x05, 0x41, 0x19, 0x1b, 0x2d, 0x15, 0x4d, 0x0f },
{ 0xfe, 0xff, 0xff, 0xff, 0x2a, 0x06, 0x22, 0x28, 0x16, 0x24, 0x38, 0x0e, 0x32, 0x2e, 0x14, 0x3a, 0x04, 0x44, 0x0c, 0x42, 0x1c, 0x4a, 0x10, 0x36, 0x3c, 0x48, 0x26 },
{ 0xff, 0xfe, 0xff, 0xff, 0x28, 0x34, 0x48, 0x46, 0x3a, 0x12, 0x18, 0x32, 0x14, 0x42, 0x16, 0x40, 0x22, 0x44, 0x1c, 0x0a, 0x36, 0x20, 0x10, 0x0c, 0x3c, 0x26, 0x2e },
{ 0xff, 0xff, 0xfe, 0xff, 0x3c, 0x16, 0x04, 0x48, 0x1e, 0x4a, 0x10, 0x18, 0x22, 0x28, 0x38, 0x40, 0x20, 0x06, 0x3e, 0x42, 0x30, 0x1a, 0x2c, 0x1c, 0x46, 0x14, 0x34 },
{ 0xff, 0xff, 0xff, 0xfe, 0x4d, 0x39, 0x1b, 0x13, 0x45, 0x2f, 0x0d, 0x3d, 0x0b, 0x11, 0x47, 0x2d, 0x19, 0x1d, 0x23, 0x35, 0x33, 0x3b, 0x21, 0x31, 0x17, 0x0f, 0x43 },
{ 0xff, 0xff, 0xff, 0xff, 0x14, 0x28, 0x2e, 0x32, 0x3e, 0x10, 0x38, 0x0e, 0x12, 0x06, 0x2c, 0x26, 0x30, 0x4c, 0x34, 0x16, 0x04, 0x3a, 0x42, 0x48, 0x36, 0x46, 0x1a },
{ 0x00, 0xff, 0xff, 0xff, 0x3e, 0x30, 0x42, 0x24, 0x06, 0x0e, 0x14, 0x1c, 0x08, 0x10, 0x20, 0x22, 0x04, 0x32, 0x0c, 0x44, 0x3c, 0x46, 0x4a, 0x26, 0x4c, 0x48, 0x1e },
{ 0xff, 0x00, 0xff, 0xff, 0x38, 0x0e, 0x22, 0x2a, 0x44, 0x3a, 0x4a, 0x3e, 0x16, 0x20, 0x36, 0x24, 0x46, 0x18, 0x1e, 0x12, 0x1c, 0x30, 0x2c, 0x14, 0x06, 0x0c, 0x40 },
{ 0x00, 0x00, 0xff, 0xff, 0x06, 0x4c, 0x26, 0x08, 0x46, 0x3e, 0x30, 0x12, 0x38, 0x1c, 0x04, 0x4a, 0x2c, 0x1a, 0x20, 0x3a, 0x18, 0x36, 0x28, 0x2e, 0x22, 0x40, 0x10 },
{ 0xff, 0xff, 0x00, 0xff, 0x12, 0x06, 0x3c, 0x2a, 0x22, 0x38, 0x48, 0x4c, 0x32, 0x44, 0x26, 0x16, 0x0c, 0x28, 0x2c, 0x36, 0x1c, 0x1a, 0x42, 0x10, 0x08, 0x4a, 0x34 },
{ 0x00, 0xff, 0x00, 0xff, 0x04, 0x4c, 0x4a, 0x28, 0x2a, 0x24, 0x14, 0x1e, 0x40, 0x48, 0x44, 0x2c, 0x2e, 0x1a, 0x12, 0x46, 0x3a, 0x0e, 0x18, 0x1c, 0x20, 0x10, 0x42 },
{ 0xff, 0x00, 0x00, 0xff, 0x06, 0x10, 0x14, 0x16, 0x48, 0x18, 0x44, 0x2c, 0x0a, 0x26, 0x24, 0x42, 0x36, 0x30, 0x38, 0x3e, 0x0c, 0x3c, 0x34, 0x46, 0x2a, 0x32, 0x0e },
{ 0x00, 0x00, 0x00, 0xff, 0x2c, 0x0a, 0x46, 0x28, 0x38, 0x24, 0x14, 0x06, 0x04, 0x10, 0x18, 0x30, 0x12, 0x20, 0x3a, 0x1a, 0x32, 0x3c, 0x3e, 0x4a, 0x1e, 0x44, 0x36 },
{ 0x00, 0x00, 0x00, 0x00, 0x45, 0x23, 0x07, 0x37, 0x4b, 0x13, 0x3d, 0x31, 0x19, 0x2b, 0x2f, 0x2d, 0x1f, 0x4d, 0x3f, 0x1b, 0x43, 0x27, 0x3b, 0x11, 0x05, 0x0d, 0x17 },
{ 0xff, 0xff, 0xff, 0x00, 0x0b, 0x4b, 0x1d, 0x39, 0x09, 0x0f, 0x49, 0x25, 0x07, 0x35, 0x3b, 0x05, 0x33, 0x17, 0x2d, 0x11, 0x2b, 0x29, 0x1f, 0x45, 0x1b, 0x41, 0x47 },
{ 0x00, 0xff, 0xff, 0x00, 0x41, 0x35, 0x11, 0x25, 0x29, 0x27, 0x33, 0x47, 0x4d, 0x31, 0x05, 0x37, 0x15, 0x1f, 0x23, 0x07, 0x1b, 0x0f, 0x3b, 0x49, 0x19, 0x3f, 0x0b },
{ 0xff, 0x00, 0xff, 0x00, 0x25, 0x47, 0x05, 0x0b, 0x45, 0x1f, 0x2b, 0x27, 0x2d, 0x09, 0x07, 0x43, 0x49, 0x29, 0x4d, 0x39, 0x33, 0x41, 0x17, 0x0f, 0x15, 0x19, 0x3b },
{ 0x00, 0x00, 0xff, 0x00, 0x3b, 0x05, 0x21, 0x0d, 0x1b, 0x43, 0x17, 0x2d, 0x1d, 0x25, 0x4b, 0x35, 0x4d, 0x3f, 0x07, 0x09, 0x37, 0x41, 0x15, 0x1f, 0x0f, 0x27, 0x29 },
{ 0xff, 0xff, 0x00, 0x00, 0x2b, 0x35, 0x1b, 0x1d, 0x0f, 0x47, 0x09, 0x0d, 0x45, 0x41, 0x21, 0x11, 0x2f, 0x43, 0x27, 0x33, 0x4b, 0x37, 0x13, 0x19, 0x4d, 0x23, 0x17 },
{ 0x00, 0xff, 0x00, 0x00, 0x1b, 0x1d, 0x33, 0x13, 0x2b, 0x27, 0x09, 0x41, 0x25, 0x17, 0x19, 0x2d, 0x4b, 0x37, 0x45, 0x11, 0x21, 0x0d, 0x3d, 0x4d, 0x07, 0x39, 0x43 },
{ 0xff, 0x00, 0x00, 0x00, 0x37, 0x27, 0x43, 0x4b, 0x39, 0x13, 0x07, 0x0d, 0x25, 0x17, 0x29, 0x1b, 0x1d, 0x45, 0x19, 0x2d, 0x0b, 0x3d, 0x15, 0x47, 0x1f, 0x21, 0x4d } };
void DSM_init()
{
CYRF_GetMfgData(cyrfmfg_id);
//Model match
cyrfmfg_id[3]^=RX_num;
if(sub_protocol == DSMR)
{
uint8_t row = rx_tx_addr[3]%22;
for(uint8_t i=0; i< 4; i++)
cyrfmfg_id[i] = pgm_read_byte_near(&DSMR_ID_FREQ[row][i]);
for(uint8_t i=0; i< 23; i++)
hopping_frequency[i] = pgm_read_byte_near(&DSMR_ID_FREQ[row][i+4]);
}
else
{
CYRF_GetMfgData(cyrfmfg_id);
//Model match
cyrfmfg_id[3]^=RX_num;
}
//Calc sop_col
sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;
//Fix for OrangeRX using wrong DSM_pncodes by preventing access to "Col 8"
if(sop_col==0)
if(sop_col==0 && sub_protocol != DSMR)
{
cyrfmfg_id[rx_tx_addr[0]%3]^=0x01; //Change a bit so sop_col will be different from 0
sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;
}
//Calc CRC seed
seed = (cyrfmfg_id[0] << 8) + cyrfmfg_id[1];
//Hopping frequencies
if (sub_protocol == DSMX_2F || sub_protocol == DSMX_1F)
DSM_calc_dsmx_channel();
else
else if(sub_protocol != DSMR)
{
uint8_t tmpch[10];
CYRF_FindBestChannels(tmpch, 10, 5, 3, 75);
@@ -482,6 +552,7 @@ void DSM_init()
}
hopping_frequency[1] = tmpch[idx];
}
//
DSM_cyrf_config();
CYRF_SetTxRxMode(TX_EN);

View File

@@ -283,11 +283,12 @@ static void __attribute__((unused)) DEVO_parse_telemetry_packet()
frsky_send_user_frame(0x11+8, dec, dec>>8);
break;
case 0x36: // Time
//memcpy(&packet[1],"\x31\x38\x32\x35\x35\x32\x31\x35\x31\x30\x31\x32",12); // 2012-10-15 18:25:52 (UTC)
//memcpy(&packet[1],"\x31\x38\x32\x35\x35\x32\x31\x35\x31\x30\x31\x32",12); // "182552151012" = 2012-10-15 18:25:52 (UTC)
if(packet[1]!=0)
{
frsky_send_user_frame(0x15, DEVO_text_to_int(&packet[9], 2), DEVO_text_to_int(&packet[7], 2)); // month, day
frsky_send_user_frame(0x16, DEVO_text_to_int(&packet[11], 2)+24, 0x00); // year
val = 2000 + DEVO_text_to_int(&packet[11], 2); // year
frsky_send_user_frame(0x16, val, val>>8);
frsky_send_user_frame(0x17, DEVO_text_to_int(&packet[1], 2), DEVO_text_to_int(&packet[3], 2)); // hour, min
frsky_send_user_frame(0x18, DEVO_text_to_int(&packet[5], 2), 0x00); // second
}

View File

@@ -0,0 +1,154 @@
/*
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 E016H
#if defined(E016H_NRF24L01_INO)
#include "iface_xn297.h"
//Protocols constants
#define E016H_BIND_COUNT 500
#define E016H_ADDRESS_LENGTH 5
#define E016H_PACKET_PERIOD 4080
#define E016H_PACKET_SIZE 10
#define E016H_BIND_CHANNEL 80
#define E016H_NUM_CHANNELS 4
//Channels
#define E016H_STOP_SW CH5_SW
#define E016H_FLIP_SW CH6_SW
#define E016H_HEADLESS_SW CH8_SW
#define E016H_RTH_SW CH9_SW
// E016H flags packet[1]
#define E016H_FLAG_CALIBRATE 0x80
#define E016H_FLAG_STOP 0x20
#define E016H_FLAG_FLIP 0x04
// E016H flags packet[3]
#define E016H_FLAG_HEADLESS 0x10
#define E016H_FLAG_RTH 0x04
// E016H flags packet[7]
#define E016H_FLAG_TAKEOFF 0x80
#define E016H_FLAG_HIGHRATE 0x08
static void __attribute__((unused)) E016H_send_packet()
{
uint8_t can_flip = 0, calibrate = 1;
if(IS_BIND_IN_PROGRESS)
{
memcpy(packet, &rx_tx_addr[1], 4);
memcpy(&packet[4], hopping_frequency, 4);
packet[8] = 0x23;
}
else
{
// trim commands
packet[0] = 0;
// aileron
uint16_t val = convert_channel_16b_limit(AILERON, 0, 0x3ff);
can_flip |= (val < 0x100) || (val > 0x300);
packet[1] = val >> 8;
packet[2] = val & 0xff;
if(val < 0x300) calibrate = 0;
// elevator
val = convert_channel_16b_limit(ELEVATOR, 0x3ff, 0);
can_flip |= (val < 0x100) || (val > 0x300);
packet[3] = val >> 8;
packet[4] = val & 0xff;
if(val < 0x300) calibrate = 0;
// throttle
val = convert_channel_16b_limit(THROTTLE, 0, 0x3ff);
packet[5] = val >> 8;
packet[6] = val & 0xff;
if(val > 0x100) calibrate = 0;
// rudder
val = convert_channel_16b_limit(RUDDER, 0, 0x3ff);
packet[7] = val >> 8;
packet[8] = val & 0xff;
if(val > 0x100) calibrate = 0;
// flags
packet[1] |= GET_FLAG(E016H_STOP_SW, E016H_FLAG_STOP)
| (can_flip ? GET_FLAG(E016H_FLIP_SW, E016H_FLAG_FLIP) : 0)
| (calibrate ? E016H_FLAG_CALIBRATE : 0);
packet[3] |= GET_FLAG(E016H_HEADLESS_SW, E016H_FLAG_HEADLESS)
| GET_FLAG(E016H_RTH_SW, E016H_FLAG_RTH);
packet[7] |= E016H_FLAG_HIGHRATE;
// frequency hopping
XN297_Hopping(hopping_frequency_no++ & 0x03);
}
// checksum
packet[9] = packet[0];
for (uint8_t i=1; i < E016H_PACKET_SIZE-1; i++)
packet[9] += packet[i];
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, E016H_PACKET_SIZE);
}
static void __attribute__((unused)) E016H_RF_init()
{
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr((uint8_t *)"\x5a\x53\x46\x30\x31", 5); // bind address
//XN297_HoppingCalib(E016H_NUM_CHANNELS);
XN297_RFChannel(E016H_BIND_CHANNEL);
}
uint16_t E016H_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
if(bind_counter)
{
bind_counter--;
if (bind_counter == 0)
{
XN297_SetTXAddr(rx_tx_addr, E016H_ADDRESS_LENGTH);
BIND_DONE;
}
}
E016H_send_packet();
return E016H_PACKET_PERIOD;
}
static void __attribute__((unused)) E016H_initialize_txid()
{
// tx id
rx_tx_addr[0] = 0xa5;
rx_tx_addr[1] = 0x00;
// rf channels
uint32_t lfsr=random(0xfefefefe);
for(uint8_t i=0; i<E016H_NUM_CHANNELS; i++)
{
hopping_frequency[i] = (lfsr & 0xFF) % 80;
lfsr>>=8;
}
}
void E016H_init()
{
BIND_IN_PROGRESS;
E016H_initialize_txid();
E016H_RF_init();
bind_counter = E016H_BIND_COUNT;
hopping_frequency_no = 0;
}
#endif

View File

@@ -33,11 +33,6 @@
#define E015_PACKET_SIZE 10
#define E015_BIND_PACKET_SIZE 9
#define E016H_PACKET_PERIOD 4080
#define E016H_PACKET_SIZE 10
#define E016H_BIND_CHANNEL 80
#define E016H_NUM_CHANNELS 4
//Channels
#define E01X_ARM_SW CH5_SW
#define E016H_STOP_SW CH5_SW
@@ -64,17 +59,6 @@
#define E015_FLAG_EXPERT 0x02
#define E015_FLAG_INTERMEDIATE 0x01
// E016H flags packet[1]
#define E016H_FLAG_CALIBRATE 0x80
#define E016H_FLAG_STOP 0x20
#define E016H_FLAG_FLIP 0x04
// E016H flags packet[3]
#define E016H_FLAG_HEADLESS 0x10
#define E016H_FLAG_RTH 0x04
// E016H flags packet[7]
#define E016H_FLAG_TAKEOFF 0x80
#define E016H_FLAG_HIGHRATE 0x08
static void __attribute__((unused)) E015_check_arming()
{
uint8_t arm_channel = E01X_ARM_SW;
@@ -97,7 +81,6 @@ static void __attribute__((unused)) E015_check_arming()
static void __attribute__((unused)) E01X_send_packet()
{
uint8_t can_flip = 0, calibrate = 1;
if(sub_protocol==E012)
{
packet_length=E012_PACKET_SIZE;
@@ -132,7 +115,7 @@ static void __attribute__((unused)) E01X_send_packet()
packet[13] = 0x56;
packet[14] = rx_tx_addr[2];
}
else if(sub_protocol==E015)
else
{ // E015
if(IS_BIND_IN_PROGRESS)
{
@@ -170,72 +153,14 @@ static void __attribute__((unused)) E01X_send_packet()
packet_length=E015_PACKET_SIZE;
}
}
else
{ // E016H
packet_length=E016H_PACKET_SIZE;
if(IS_BIND_IN_PROGRESS)
{
rf_ch_num=E016H_BIND_CHANNEL;
memcpy(packet, &rx_tx_addr[1], 4);
memcpy(&packet[4], hopping_frequency, 4);
packet[8] = 0x23;
}
else
{
// trim commands
packet[0] = 0;
// aileron
uint16_t val = convert_channel_16b_limit(AILERON, 0, 0x3ff);
can_flip |= (val < 0x100) || (val > 0x300);
packet[1] = val >> 8;
packet[2] = val & 0xff;
if(val < 0x300) calibrate = 0;
// elevator
val = convert_channel_16b_limit(ELEVATOR, 0x3ff, 0);
can_flip |= (val < 0x100) || (val > 0x300);
packet[3] = val >> 8;
packet[4] = val & 0xff;
if(val < 0x300) calibrate = 0;
// throttle
val = convert_channel_16b_limit(THROTTLE, 0, 0x3ff);
packet[5] = val >> 8;
packet[6] = val & 0xff;
if(val > 0x100) calibrate = 0;
// rudder
val = convert_channel_16b_limit(RUDDER, 0, 0x3ff);
packet[7] = val >> 8;
packet[8] = val & 0xff;
if(val > 0x100) calibrate = 0;
// flags
packet[1] |= GET_FLAG(E016H_STOP_SW, E016H_FLAG_STOP)
| (can_flip ? GET_FLAG(E01X_FLIP_SW, E016H_FLAG_FLIP) : 0)
| (calibrate ? E016H_FLAG_CALIBRATE : 0);
packet[3] |= GET_FLAG(E01X_HEADLESS_SW, E016H_FLAG_HEADLESS)
| GET_FLAG(E01X_RTH_SW, E016H_FLAG_RTH);
packet[7] |= E016H_FLAG_HIGHRATE;
// frequency hopping
rf_ch_num=hopping_frequency[hopping_frequency_no++ & 0x03];
}
// checksum
packet[9] = packet[0];
for (uint8_t i=1; i < E016H_PACKET_SIZE-1; i++)
packet[9] += packet[i];
}
// Power on, TX mode, CRC enabled
if(sub_protocol==E016H)
XN297_Configure( _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
else //E012 & E015
HS6200_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
HS6200_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch_num);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
if(sub_protocol==E016H)
XN297_WritePayload(packet, packet_length);
else
HS6200_WritePayload(packet, packet_length);
HS6200_WritePayload(packet, packet_length);
// Check and adjust transmission power. We do this after
// transmission to not bother with timeout after power
@@ -250,10 +175,8 @@ static void __attribute__((unused)) E01X_RF_init()
if(sub_protocol==E012)
HS6200_SetTXAddr((uint8_t *)"\x55\x42\x9C\x8F\xC9", E01X_ADDRESS_LENGTH);
else if(sub_protocol==E015)
else //E015
HS6200_SetTXAddr((uint8_t *)"\x62\x54\x79\x38\x53", E01X_ADDRESS_LENGTH);
else //E016H
XN297_SetTXAddr((uint8_t *)"\x5a\x53\x46\x30\x31", 5); // bind address
}
uint16_t E01X_callback()
@@ -266,10 +189,7 @@ uint16_t E01X_callback()
bind_counter--;
if (bind_counter == 0)
{
if(sub_protocol==E016H)
XN297_SetTXAddr(rx_tx_addr, E01X_ADDRESS_LENGTH);
else
HS6200_SetTXAddr(rx_tx_addr, E01X_ADDRESS_LENGTH);
HS6200_SetTXAddr(rx_tx_addr, E01X_ADDRESS_LENGTH);
BIND_DONE;
}
}
@@ -288,21 +208,6 @@ static void __attribute__((unused)) E012_initialize_txid()
}
}
static void __attribute__((unused)) E016H_initialize_txid()
{
// tx id
rx_tx_addr[0] = 0xa5;
rx_tx_addr[1] = 0x00;
// rf channels
uint32_t lfsr=random(0xfefefefe);
for(uint8_t i=0; i<E016H_NUM_CHANNELS; i++)
{
hopping_frequency[i] = (lfsr & 0xFF) % 80;
lfsr>>=8;
}
}
void E01X_init()
{
BIND_IN_PROGRESS;
@@ -311,7 +216,7 @@ void E01X_init()
E012_initialize_txid();
packet_period=E012_PACKET_PERIOD;
}
else if(sub_protocol==E015)
else //E015
{
packet_period=E015_PACKET_PERIOD;
rf_ch_num=E015_RF_CHANNEL;
@@ -319,11 +224,6 @@ void E01X_init()
arm_flags = 0;
arm_channel_previous = E01X_ARM_SW;
}
else
{ // E016H
E016H_initialize_txid();
packet_period=E016H_PACKET_PERIOD;
}
E01X_RF_init();
bind_counter = E01X_BIND_COUNT;
hopping_frequency_no = 0;

View File

@@ -15,7 +15,7 @@
#if defined(ESKY150V2_CC2500_INO)
#include "iface_cc2500.h"
#include "iface_nrf250k.h"
//#define ESKY150V2_FORCE_ID
@@ -74,7 +74,7 @@ static void __attribute__((unused)) ESKY150V2_send_packet()
packet[4+2*i] = channel;
packet[5+2*i] = channel>>8;
}
CC2500_250K_NRF_WritePayload(packet, ESKY150V2_PAYLOADSIZE);
NRF250K_WritePayload(packet, ESKY150V2_PAYLOADSIZE);
}
uint16_t ESKY150V2_callback()
@@ -91,12 +91,12 @@ uint16_t ESKY150V2_callback()
BIND_DONE; //Need full power for bind to work...
CC2500_SetPower(); //Set power level
BIND_IN_PROGRESS;
CC2500_250K_NRF_WritePayload(packet, ESKY150V2_BINDPAYLOADSIZE);
NRF250K_WritePayload(packet, ESKY150V2_BINDPAYLOADSIZE);
if (--bind_counter == 0)
{
BIND_DONE;
// Change TX address from bind to normal mode
CC2500_250K_NRF_SetTXAddr(rx_tx_addr, ESKY150V2_TXID_SIZE);
NRF250K_SetTXAddr(rx_tx_addr, ESKY150V2_TXID_SIZE);
memset(packet,0x00,ESKY150V2_PAYLOADSIZE);
}
return 30000; //ESKY150V2_BINDING_PACKET_PERIOD;
@@ -118,7 +118,7 @@ void ESKY150V2_init()
if(IS_BIND_IN_PROGRESS)
{
CC2500_250K_NRF_SetTXAddr((uint8_t *)"\x73\x73\x74\x63", ESKY150V2_TXID_SIZE); //Bind address
NRF250K_SetTXAddr((uint8_t *)"\x73\x73\x74\x63", ESKY150V2_TXID_SIZE); //Bind address
CC2500_250K_Hopping(ESKY150V2_NFREQCHANNELS); //Bind channel
memcpy(packet,"\x73\x73\x74\x63", ESKY150V2_TXID_SIZE);
memcpy(&packet[ESKY150V2_TXID_SIZE],rx_tx_addr, ESKY150V2_TXID_SIZE);
@@ -132,7 +132,7 @@ void ESKY150V2_init()
bind_counter=100;
}
else
CC2500_250K_NRF_SetTXAddr(rx_tx_addr, ESKY150V2_TXID_SIZE);
NRF250K_SetTXAddr(rx_tx_addr, ESKY150V2_TXID_SIZE);
}
#endif

View File

@@ -16,7 +16,7 @@ Multiprotocol is distributed in the hope that it will be useful,
#if defined(FX816_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
#define FX816_INITIAL_WAIT 500
#define FX816_PACKET_PERIOD 10000
@@ -27,7 +27,14 @@ Multiprotocol is distributed in the hope that it will be useful,
static void __attribute__((unused)) FX816_send_packet()
{
packet[0] = IS_BIND_IN_PROGRESS?0x55:0xAA;
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);
@@ -44,25 +51,18 @@ static void __attribute__((unused)) FX816_send_packet()
val+=packet[i];
packet[5]=val;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? FX816_RF_BIND_CHANNEL:hopping_frequency[hopping_frequency_no++]);
hopping_frequency_no%=FX816_RF_NUM_CHANNELS;
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, FX816_PAYLOAD_SIZE);
// Power on, TX mode, 2byte CRC
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) FX816_RF_init()
{
NRF24L01_Initialize();
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()

View File

@@ -19,17 +19,14 @@
static void __attribute__((unused)) FrSkyX_build_bind_packet()
{
uint8_t packet_size = 0x1D;
if(protocol==PROTO_FRSKYX && (FrSkyFormat & 2 ))
packet_size=0x20; // FrSkyX V1 LBT
//Header
packet[0] = packet_size; // Number of bytes in the packet (after this one)
packet[1] = 0x03; // Bind packet
packet[2] = 0x01; // Bind packet
packet[0] = packet_length; // Number of bytes in the packet (after this one)
packet[1] = 0x03; // Bind packet
packet[2] = 0x01; // Bind packet
//ID
packet[3] = rx_tx_addr[3]; // ID
packet[4] = rx_tx_addr[2]; // ID
packet[3] = rx_tx_addr[3]; // ID
packet[4] = rx_tx_addr[2]; // ID
if(protocol==PROTO_FRSKYX)
{
@@ -40,10 +37,10 @@ static void __attribute__((unused)) FrSkyX_build_bind_packet()
packet[8] = hopping_frequency[idx++];
packet[9] = hopping_frequency[idx++];
packet[10] = hopping_frequency[idx++];
packet[11] = rx_tx_addr[1]; // Unknown but constant ID?
packet[11] = rx_tx_addr[1]; // ID
packet[12] = RX_num;
//
memset(&packet[13], 0, packet_size - 14);
memset(&packet[13], 0, packet_length - 14);
if(binding_idx&0x01)
memcpy(&packet[13],(void *)"\x55\xAA\x5A\xA5",4); // Telem off
if(binding_idx&0x02)
@@ -52,30 +49,34 @@ static void __attribute__((unused)) FrSkyX_build_bind_packet()
else
{
//packet 1D 03 01 0E 1C 02 00 00 32 0B 00 00 A8 26 28 01 A1 00 00 00 3E F6 87 C7 00 00 00 00 C9 C9
packet[5] = rx_tx_addr[1]; // Unknown but constant ID?
//Unknown bytes
if(state & 0x01)
memcpy(&packet[7],"\x00\x18\x0A\x00\x00\xE0\x02\x0B\x01\xD3\x08\x00\x00\x4C\xFE\x87\xC7",17);
else
memcpy(&packet[7],"\x27\xAD\x02\x00\x00\x64\xC8\x46\x00\x64\x00\x00\x00\xFB\xF6\x87\xC7",17);
//ID
packet[5] = rx_tx_addr[1]; // ID
packet[6] = RX_num;
//Bind flags
packet[7]=0;
if(binding_idx&0x01)
packet[7] |= 0x40; // Telem off
if(binding_idx&0x02)
packet[7] |= 0x80; // CH9-16
//Unknown bytes
memcpy(&packet[8],"\x32\x0B\x00\x00\xA8\x26\x28\x01\xA1\x00\x00\x00\x3E\xF6\x87\xC7",16);
packet[20]^= 0x0E ^ rx_tx_addr[3]; // Update the ID
packet[21]^= 0x1C ^ rx_tx_addr[2]; // Update the ID
//Replace the ID
packet[20] ^= 0x0E ^ rx_tx_addr[3]; // Update the ID
packet[21] ^= 0x1C ^ rx_tx_addr[2]; // Update the ID
//Xor
for(uint8_t i=3; i<packet_size-1; i++)
for(uint8_t i=3; i<packet_length-1; i++)
packet[i] ^= 0xA7;
}
//CRC
uint16_t lcrc = FrSkyX_crc(&packet[3], packet_size-4);
packet[packet_size-1] = lcrc >> 8;
packet[packet_size] = lcrc;
uint16_t lcrc = FrSkyX_crc(&packet[3], packet_length-4);
packet[packet_length-1] = lcrc >> 8;
packet[packet_length] = lcrc;
/*//Debug
debug("Bind:");
for(uint8_t i=0;i<=packet_size;i++)
for(uint8_t i=0;i<=packet_length;i++)
debug(" %02X",packet[i]);
debugln("");*/
}
@@ -85,11 +86,8 @@ static void __attribute__((unused)) FrSkyX_build_packet()
//0x1D 0xB3 0xFD 0x02 0x56 0x07 0x15 0x00 0x00 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x96 0x12
// data frames sent every 9ms; failsafe every 9 seconds
//
uint8_t packet_size = 0x1D;
if(protocol==PROTO_FRSKYX && (FrSkyFormat & 2 ))
packet_size=0x20; // FrSkyX V1 LBT
//Header
packet[0] = packet_size; // Number of bytes in the packet (after this one)
packet[0] = packet_length; // Number of bytes in the packet (after this one)
packet[1] = rx_tx_addr[3]; // ID
packet[2] = rx_tx_addr[2]; // ID
packet[3] = rx_tx_addr[1]; // Unknown but constant ID?
@@ -102,16 +100,16 @@ static void __attribute__((unused)) FrSkyX_build_packet()
FrSkyX_channels(7); // Set packet[7]=failsafe, packet[8]=0?? and packet[9..20]=channels data
//Sequence and send SPort
FrSkyX_seq_sport(21,packet_size-2); //21=RX|TXseq, 22=bytes count, 23..packet_size-2=data
FrSkyX_seq_sport(21,packet_length-2); //21=RX|TXseq, 22=bytes count, 23..packet_length-2=data
//CRC
uint16_t lcrc = FrSkyX_crc(&packet[3], packet_size-4);
packet[packet_size-1] = lcrc >> 8;
packet[packet_size] = lcrc;
uint16_t lcrc = FrSkyX_crc(&packet[3], packet_length-4);
packet[packet_length-1] = lcrc >> 8;
packet[packet_length] = lcrc;
/*//Debug
debug("Norm:");
for(uint8_t i=0;i<=packet_size;i++)
for(uint8_t i=0;i<=packet_length;i++)
debug(" %02X",packet[i]);
debugln("");*/
}
@@ -132,7 +130,7 @@ uint16_t FRSKYX_callback()
state = FRSKY_BIND_DONE;
else
state++;
return 9000;
break;
case FRSKY_BIND_DONE:
FrSkyX_initialize_data(0);
hopping_frequency_no=0;
@@ -238,7 +236,7 @@ uint16_t FRSKYX_callback()
state = FRSKY_DATA1;
return 400; // FCC & LBT
}
return 1;
return 9000;
}
void FRSKYX_init()
@@ -248,22 +246,27 @@ void FRSKYX_init()
if (sub_protocol==XCLONE_16||sub_protocol==XCLONE_8)
Frsky_init_clone();
else if(protocol==PROTO_FRSKYX)
{
Frsky_init_hop();
rx_tx_addr[1]=0x02; // ID related, hw version?
}
else
{
#ifdef FRSKYX2_FORCE_ID
rx_tx_addr[3]=0x0E;
rx_tx_addr[2]=0x1C;
FrSkyX_chanskip=18;
#endif
if(protocol==PROTO_FRSKYX)
Frsky_init_hop();
else
{
#ifdef FRSKYX2_FORCE_ID
rx_tx_addr[3]=0x0E;
rx_tx_addr[2]=0x1C;
FrSkyX_chanskip=18;
#endif
FrSkyX2_init_hop();
}
rx_tx_addr[1]=0x02; // ID related, hw version?
FrSkyX2_init_hop();
}
if(protocol==PROTO_FRSKYX && (FrSkyFormat & 2 ))
packet_length = 0x20; // FrSkyX V1 LBT
else
packet_length = 0x1D;
packet_count=0;
while(!FrSkyX_chanskip)
FrSkyX_chanskip=random(0xfefefefe)%47;
@@ -272,14 +275,12 @@ void FRSKYX_init()
if(IS_BIND_IN_PROGRESS)
{
memset(packet, 0, packet_length);
state = FRSKY_BIND;
FrSkyX_initialize_data(1);
}
else
{
state = FRSKY_DATA1;
FrSkyX_initialize_data(0);
}
state = FRSKY_BIND_DONE;
FrSkyX_telem_init();
}
#endif

View File

@@ -16,7 +16,7 @@ Multiprotocol is distributed in the hope that it will be useful,
#if defined(GD00X_CCNRF_INO)
#include "iface_nrf250k.h"
#include "iface_xn297.h"
//#define FORCE_GD00X_ORIGINAL_ID
@@ -113,7 +113,7 @@ static void __attribute__((unused)) GD00X_send_packet()
if(IS_BIND_DONE)
{
XN297L_Hopping(hopping_frequency_no);
XN297_Hopping(hopping_frequency_no);
if(sub_protocol==GD_V1)
{
hopping_frequency_no++;
@@ -121,21 +121,22 @@ static void __attribute__((unused)) GD00X_send_packet()
}
}
XN297L_WritePayload(packet, packet_length);
XN297L_SetPower(); // Set tx_power
XN297L_SetFreqOffset(); // Set frequency offset
// Send
XN297_SetFreqOffset();
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, packet_length);
}
static void __attribute__((unused)) GD00X_RF_init()
{
XN297L_Init();
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_250K);
if(sub_protocol==GD_V1)
XN297L_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
XN297_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
else
XN297L_SetTXAddr((uint8_t*)"GDKNx", 5);
XN297L_HoppingCalib(sub_protocol==GD_V1?GD00X_RF_NUM_CHANNELS:GD00X_V2_RF_NUM_CHANNELS); // Calibrate all channels
XN297L_RFChannel(sub_protocol==GD_V1?GD00X_RF_BIND_CHANNEL:GD00X_V2_RF_BIND_CHANNEL); // Set bind channel
XN297_SetTXAddr((uint8_t*)"GDKNx", 5);
XN297_HoppingCalib(sub_protocol==GD_V1?GD00X_RF_NUM_CHANNELS:GD00X_V2_RF_NUM_CHANNELS); // Calibrate all channels
XN297_RFChannel(sub_protocol==GD_V1?GD00X_RF_BIND_CHANNEL:GD00X_V2_RF_BIND_CHANNEL); // Set bind channel
}
static void __attribute__((unused)) GD00X_initialize_txid()

View File

@@ -19,7 +19,7 @@ Multiprotocol is distributed in the hope that it will be useful,
#if defined(GW008_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
#define GW008_INITIAL_WAIT 500
#define GW008_PACKET_PERIOD 2400
@@ -47,6 +47,9 @@ static void __attribute__((unused)) GW008_send_packet()
}
else
{
XN297_Hopping((hopping_frequency_no++)/2);
hopping_frequency_no %= 8;
packet[1] = 0x01 | GET_FLAG(CH5_SW, 0x40); // flip
packet[2] = convert_channel_16b_limit(AILERON , 200, 0); // aileron
packet[3] = convert_channel_16b_limit(ELEVATOR, 0, 200); // elevator
@@ -63,25 +66,21 @@ static void __attribute__((unused)) GW008_send_packet()
}
packet[14] = rx_tx_addr[1];
// Power on, TX mode, CRC enabled
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? GW008_RF_BIND_CHANNEL : hopping_frequency[(hopping_frequency_no++)/2]);
hopping_frequency_no %= 8;
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WriteEnhancedPayload(packet, GW008_PAYLOAD_SIZE, 0);
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) GW008_RF_init()
{
NRF24L01_Initialize();
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
XN297_SetRXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, GW008_PAYLOAD_SIZE+2); // payload + 2 bytes for pcf
XN297_SetRXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", GW008_PAYLOAD_SIZE);
//XN297_HoppingCalib(8);
XN297_RFChannel(GW008_RF_BIND_CHANNEL);
}
static void __attribute__((unused)) GW008_initialize_txid()
@@ -96,20 +95,20 @@ uint16_t GW008_callback()
switch(phase)
{
case GW008_BIND1:
if((NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) && // RX fifo data ready
if(XN297_IsRX() && // RX fifo data ready
XN297_ReadEnhancedPayload(packet, GW008_PAYLOAD_SIZE) == GW008_PAYLOAD_SIZE && // check payload size
packet[0] == rx_tx_addr[0] && packet[14] == rx_tx_addr[1]) // check tx id
{
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(TX_EN);
rx_tx_addr[2] = packet[13];
BIND_DONE;
phase = GW008_DATA;
}
else
{
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(TX_EN);
GW008_send_packet();
phase = GW008_BIND2;
return 850; // minimum value 750 for STM32
@@ -117,14 +116,10 @@ uint16_t GW008_callback()
break;
case GW008_BIND2:
// switch to RX mode
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();
NRF24L01_SetTxRxMode(RX_EN);
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO)
| _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
phase = GW008_BIND1;
return 5000;
break;
case GW008_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(GW008_PACKET_PERIOD);

View File

@@ -19,7 +19,7 @@
#if defined(H8_3D_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
#define H8_3D_PACKET_PERIOD 1800
#define H20H_PACKET_PERIOD 9340
@@ -122,17 +122,15 @@ static void __attribute__((unused)) H8_3D_send_packet()
sum += packet[i];
packet[19] = sum; // data checksum
// Power on, TX mode, 2byte CRC
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
// RF channel
if(sub_protocol!=H20H)
{ // H8_3D, H20MINI, H30MINI
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? hopping_frequency[0] : hopping_frequency[hopping_frequency_no++]);
XN297_RFChannel(IS_BIND_IN_PROGRESS ? hopping_frequency[0] : hopping_frequency[hopping_frequency_no++]);
hopping_frequency_no %= H8_3D_RF_NUM_CHANNELS;
}
else
{ //H20H
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? H20H_BIND_RF : hopping_frequency[packet_count>>3]);
{ // H20H
XN297_RFChannel(IS_BIND_IN_PROGRESS ? H20H_BIND_RF : hopping_frequency[packet_count>>3]);
if(IS_BIND_DONE)
{
packet_count++;
@@ -147,17 +145,15 @@ static void __attribute__((unused)) H8_3D_send_packet()
}
}
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, H8_3D_PACKET_SIZE);
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) H8_3D_RF_init()
{
NRF24L01_Initialize();
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
if(sub_protocol==H20H)
XN297_SetTXAddr((uint8_t *)"\xEE\xDD\xCC\xBB\x11", 5);

View File

@@ -527,7 +527,6 @@ void HOTT_init()
packet_count=0;
state=HOTT_SENSOR_SEARCH_PERIOD;
#endif
packet_sent = 0;
phase = HOTT_START;
}

View File

@@ -55,7 +55,8 @@ static void __attribute__((unused)) HITEC_CC2500_init()
CC2500_WriteReg(i, pgm_read_byte_near(&HITEC_init_values[i]));
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
prev_option = option;
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
}

View File

@@ -15,7 +15,7 @@
#if defined(HONTAI_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h" // mix of nrf and xn297 at 1Mb...
#define HONTAI_BIND_COUNT 80
#define HONTAI_PACKET_PERIOD 13500
@@ -44,6 +44,11 @@ static void __attribute__((unused)) HONTAI_send_packet()
}
else
{
/*if(sub_protocol == JJRCX1)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]);
else*/
XN297_Hopping(hopping_frequency_no++);
hopping_frequency_no %= 3;
memset(packet,0,HONTAI_PACKET_SIZE);
packet[3] = convert_channel_16b_limit(THROTTLE, 0, 127) << 1; // Throttle
packet[4] = convert_channel_16b_limit(AILERON, 63, 0); // Aileron
@@ -113,42 +118,44 @@ static void __attribute__((unused)) HONTAI_send_packet()
packet[packet_length-1]=bit_reverse(crc);
// Power on, TX mode, 2byte CRC
if(sub_protocol == JJRCX1)
/*if(sub_protocol == JJRCX1)
{
NRF24L01_SetPower();
NRF24L01_SetTxRxMode(TX_EN);
else
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? HONTAI_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no++]);
hopping_frequency_no %= 3;
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
}
else*/
{
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
}
if(sub_protocol == JJRCX1)
NRF24L01_WritePayload(packet, packet_length);
else
XN297_WritePayload(packet, packet_length);
NRF24L01_SetPower();
}
static void __attribute__((unused)) HONTAI_RF_init()
{
NRF24L01_Initialize();
if(sub_protocol == JJRCX1)
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\xd2\xb5\x99\xb3\x4a", 5);
else
XN297_SetTXAddr((const uint8_t*)"\xd2\xb5\x99\xb3\x4a", 5);
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M); // this will select the nrf and initialize it, therefore both sub protocols can use common instructions
if(sub_protocol == JJRCX1)
{
//NRF24L01_Initialize();
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\xd2\xb5\x99\xb3\x4a", 5);
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0xff); // JJRC uses dynamic payload length
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // match other stock settings even though AA disabled...
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07);
//NRF24L01_WriteReg(NRF24L01_05_RF_CH, HONTAI_RF_BIND_CHANNEL);
}
NRF24L01_SetTxRxMode(TX_EN); // Clear data ready, data sent, retransmit and enable CRC 16bits, ready for TX
else
{
XN297_SetTXAddr((const uint8_t*)"\xd2\xb5\x99\xb3\x4a", 5);
//XN297_HoppingCalib(3);
}
XN297_RFChannel(HONTAI_RF_BIND_CHANNEL);
}
const uint8_t PROGMEM HONTAI_hopping_frequency_nonels[][3] = {
@@ -172,9 +179,9 @@ static void __attribute__((unused)) HONTAI_init2()
data_tx_addr[3] = pgm_read_byte_near( &HONTAI_addr_vals[3][(rx_tx_addr[4] >> 4) & 0x0f]);
data_tx_addr[4] = 0x24;
if(sub_protocol == JJRCX1)
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, data_tx_addr, sizeof(data_tx_addr));
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, data_tx_addr, 5);
else
XN297_SetTXAddr(data_tx_addr, sizeof(data_tx_addr));
XN297_SetTXAddr(data_tx_addr, 5);
//Hopping frequency table
for(uint8_t i=0;i<3;i++)

View File

@@ -0,0 +1,122 @@
/*
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/>.
*/
// This module makes it possible to bind to and control the IKEA "Ansluta" line
// of remote-controlled lights.
// To bind, first switch the receiver into binding mode, then the TX.
// Once bound, the TX can send one of three commands:
// lights off, lights dimmed 50% and lights on.
// Those are mapped to throttle ranges 0..0x55, 0x56..0xAA, 0xAB..0xFF.
#if defined(IKEAANSLUTA_CC2500_INO)
#include "iface_cc2500.h"
#define IKEAANSLUTA_BIND_COUNT 30 // ~ 2sec autobind/65ms per loop = 30 binding packets
// Commands
#define IKEAANSLUTA_LIGHT_OFF 0x01
#define IKEAANSLUTA_LIGHT_DIM 0x02 // 50% dimmed light
#define IKEAANSLUTA_LIGHT_ON 0x03
#define IKEAANSLUTA_PAIR 0xFF
void IKEAANSLUTA_send_command(uint8_t command){
CC2500_Strobe(CC2500_SIDLE);
packet[4] = option;
packet[5] = command;
CC2500_WriteData(packet, 8);
}
uint16_t IKEAANSLUTA_callback(void)
{
if (bind_counter) {
IKEAANSLUTA_send_command(IKEAANSLUTA_PAIR);
if(--bind_counter == 0) {
BIND_DONE;
CC2500_SetPower();
}
}
else {
uint8_t throttle = convert_channel_8b(THROTTLE);
uint8_t cmd = throttle <= 0x55 ? IKEAANSLUTA_LIGHT_OFF :
throttle <= 0xAA ? IKEAANSLUTA_LIGHT_DIM :
IKEAANSLUTA_LIGHT_ON;
IKEAANSLUTA_send_command(cmd);
}
return 65535; // 65ms loop cycle is more than enough here (we could make it even longer if not for uint16_t)
}
// Register initialization values as a continuous memory block (to save on flash memory)
const PROGMEM uint8_t IKEAANSLUTA_init_values[] = {
0xFF, // CC2500_06_PKTLEN
0x04, // CC2500_07_PKTCTRL1
0x05, // CC2500_08_PKTCTRL0
0x00, // CC2500_09_ADDR (unused, default)
0x10, // CC2500_0A_CHANNR
0x09, // CC2500_0B_FSCTRL1
0x00, // CC2500_0C_FSCTRL0
0x5D, // CC2500_0D_FREQ2
0x93, // CC2500_0E_FREQ1
0xB1, // CC2500_0F_FREQ0
0x2D, // CC2500_10_MDMCFG4
0x3B, // CC2500_11_MDMCFG3
0x73, // CC2500_12_MDMCFG2
0xA2, // CC2500_13_MDMCFG1
0xF8, // CC2500_14_MDMCFG0
0x01, // CC2500_15_DEVIATN
0x07, // CC2500_16_MCSM2
0x30, // CC2500_17_MCSM1
0x18, // CC2500_18_MCSM0
0x1D, // CC2500_19_FOCCFG
0x1C, // CC2500_1A_BSCFG
0xC7, // CC2500_1B_AGCCTRL2
0x00, // CC2500_1C_AGCCTRL1
0xB2, // CC2500_1D_AGCCTRL0
0x87, // CC2500_1E_WOREVT1 (unused, default)
0x6b, // CC2500_1F_WOREVT0 (unused, default)
0xf8, // CC2500_20_WORCTRL (unused, default)
0xB6, // CC2500_21_FREND1
0x10, // CC2500_22_FREND0
0xEA, // CC2500_23_FSCAL3
0x0A, // CC2500_24_FSCAL2
0x00, // CC2500_25_FSCAL1
0x11, // CC2500_26_FSCAL0
0x41, // CC2500_27_RCCTRL1
0x00, // CC2500_28_RCCTRL0
};
void IKEAANSLUTA_init(void)
{
if (IS_BIND_DONE) bind_counter = 0;
else bind_counter = IKEAANSLUTA_BIND_COUNT;
// All packets we send are the same
packet[0] = 0x06;
packet[1] = 0x55;
packet[2] = 0x01;
// Bytes 3&4 are the transmitter address (to which the RX binds)
// Byte 5 is the command.
packet[3] = rx_tx_addr[3]; // <pseudorandom tx-fixed value> + <rx_num>
// packet[4] = option;
// packet[5] = 0x00; // Command goes here
packet[6] = 0xAA;
packet[7] = 0xFF;
// Configure & initialize CC2500
for (uint8_t i = 0; i <= CC2500_28_RCCTRL0-CC2500_06_PKTLEN; ++i)
CC2500_WriteReg(CC2500_06_PKTLEN+i, pgm_read_byte_near(&IKEAANSLUTA_init_values[i]));
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
}
#endif

View File

@@ -16,7 +16,7 @@
#if defined(JJRC345_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
//#define JJRC345_FORCE_ID
@@ -71,7 +71,7 @@ static void __attribute__((unused)) JJRC345_send_packet()
}
else
{ //00 41 00 0A 00 80 80 80 00 00 40 46 00 49 F1 18
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
XN297_Hopping(hopping_frequency_no);
hopping_frequency_no++;
hopping_frequency_no %= JJRC345_NUM_CHANNELS;
packet[1] = hopping_frequency[hopping_frequency_no]; // next packet will be sent on this channel
@@ -121,21 +121,18 @@ static void __attribute__((unused)) JJRC345_send_packet()
packet[14] = rx_tx_addr[2];
packet[15] = rx_tx_addr[3];
// Power on, TX mode
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, JJRC345_PACKET_SIZE);
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) JJRC345_RF_init()
{
NRF24L01_Initialize();
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, sub_protocol == JJRC345 ? JJRC345_RF_BIND_CHANNEL:SKYTMBLR_RF_BIND_CHANNEL); // Bind channel
//XN297_HoppingCalib(JJRC345_NUM_CHANNELS);
XN297_RFChannel(sub_protocol == JJRC345 ? JJRC345_RF_BIND_CHANNEL:SKYTMBLR_RF_BIND_CHANNEL); // Bind channel
}
uint16_t JJRC345_callback()

View File

@@ -16,9 +16,10 @@ Multiprotocol is distributed in the hope that it will be useful,
#if defined(KF606_CCNRF_INO)
#include "iface_nrf250k.h"
#include "iface_xn297.h"
//#define FORCE_KF606_ORIGINAL_ID
//#define FORCE_MIG320_ORIGINAL_ID
#define KF606_INITIAL_WAIT 500
#define KF606_PACKET_PERIOD 3000
@@ -36,23 +37,47 @@ static void __attribute__((unused)) KF606_send_packet()
}
else
{
packet[0]= 0x55;
packet[1]= convert_channel_8b(THROTTLE); // 0..255
// Deadband is needed on aileron, 40 gives +-6%
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
// Aileron trim must be on a separated channel C1..D0..DF
packet[3]= convert_channel_16b_limit(CH5,0xC1,0xDF);
}
if(IS_BIND_DONE)
{
XN297L_Hopping(hopping_frequency_no);
XN297_Hopping(hopping_frequency_no);
hopping_frequency_no ^= 1; // 2 RF channels
packet[0] = 0x55;
packet[1] = convert_channel_8b(THROTTLE); // 0..255
// Deadband is needed on aileron, 40 gives +-6%
if(sub_protocol == KF606_KF606)
{
packet[2] = convert_channel_8b_limit_deadband(AILERON,0x20,0x80,0xE0,40); // Aileron: Max values:20..80..E0, Low rates:50..80..AF, High rates:3E..80..C1
packet[3] = convert_channel_16b_limit(CH5,0xC1,0xDF); // Aileron trim must be on a separated channel C1..D0..DF
}
else
{
packet[2] = convert_channel_8b_limit_deadband(AILERON,0x00,0x80,0xFF,40); // Aileron: High rate:2B..80..DA
packet[3] = convert_channel_16b_limit(CH5,0x01,0x1F); // Aileron trim must be on a separated channel 01..10..1F
packet[3] += (packet[2]-0x80)>>3; // Drive trims for more aileron authority
if(packet[3] > 0x80)
packet[3] = 0x01;
else if(packet[3] > 0x1F)
packet[3] = 0x1F;
}
}
XN297L_WritePayload(packet, KF606_PAYLOAD_SIZE);
uint8_t len = KF606_PAYLOAD_SIZE;
if(sub_protocol == KF606_MIG320)
{
len++;
packet[4] = 0; // additional channel?
}
XN297L_SetPower(); // Set tx_power
XN297L_SetFreqOffset(); // Set frequency offset
#if 0
for(uint8_t i=0; i<len; i++)
debug("%02X ",packet[i]);
debugln("");
#endif
// Send
XN297_SetPower();
XN297_SetFreqOffset();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, len);
}
static void __attribute__((unused)) KF606_initialize_txid()
@@ -66,22 +91,29 @@ static void __attribute__((unused)) KF606_initialize_txid()
rx_tx_addr[1]=0x02;
rx_tx_addr[2]=0x00;
hopping_frequency[0]=0x20;
hopping_frequency[0]=0x23;
hopping_frequency[1]=0x23;
//TX2
rx_tx_addr[0]=0x25;
rx_tx_addr[1]=0x04;
rx_tx_addr[2]=0x00;
hopping_frequency[0]=0x2E;
hopping_frequency[0]=0x31;
hopping_frequency[1]=0x31;
#endif
#ifdef FORCE_MIG320_ORIGINAL_ID
rx_tx_addr[0]=0xBB;
rx_tx_addr[1]=0x13;
rx_tx_addr[2]=0x00;
hopping_frequency[0]=68;
hopping_frequency[1]=71;
#endif
}
static void __attribute__((unused)) KF606_RF_init()
{
XN297L_Init();
XN297L_SetTXAddr((uint8_t*)"\xe7\xe7\xe7\xe7\xe7", 5);
XN297L_HoppingCalib(KF606_RF_NUM_CHANNELS); // Calibrate all channels
XN297L_RFChannel(KF606_RF_BIND_CHANNEL); // Set bind channel
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_250K);
XN297_SetTXAddr((uint8_t*)"\xe7\xe7\xe7\xe7\xe7", 5);
XN297_HoppingCalib(KF606_RF_NUM_CHANNELS); // Calibrate all channels
XN297_RFChannel(KF606_RF_BIND_CHANNEL); // Set bind channel
}
uint16_t KF606_callback()
@@ -93,7 +125,7 @@ uint16_t KF606_callback()
if(--bind_counter==0)
{
BIND_DONE;
XN297L_SetTXAddr(rx_tx_addr, 3);
XN297_SetTXAddr(rx_tx_addr, 3);
}
KF606_send_packet();
return KF606_PACKET_PERIOD;
@@ -109,3 +141,14 @@ void KF606_init()
}
#endif
// MIG320 protocol
// Bind
// 250K C=7 S=Y A= E7 E7 E7 E7 E7 P(5)= AA BB 13 00 00
// 3ms on ch7
// Normal
// 250K C=68 S=Y A= BB 13 00 P(5)= 55 00 80 10 00
// P[1] = THR 00..FF
// P[2] = AIL 2B..80..DA
// P[3] = TRIM 01..10..1F
// channels 68=BB&3F+9 and 71

View File

@@ -0,0 +1,147 @@
/*
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(LOSI_CYRF6936_INO)
#include "iface_cyrf6936.h"
#define LOSI_FORCE_ID
const uint8_t PROGMEM LOSI_bind_sop_code[] = {0x62, 0xdf, 0xc1, 0x49, 0xdf, 0xb1, 0xc0, 0x49};
const uint8_t LOSI_data_code[][16] = {
{ 0xD7, 0xA1, 0x54, 0xB1, 0x5E, 0x89, 0xAE, 0x86, 0xC9, 0x2C, 0x06, 0x93, 0x86, 0xB9, 0x9E, 0xD7 }, //bind
/* { 0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93, 0xDC, 0x68, 0x08, 0x99, 0x97, 0xAE, 0xAF, 0x8C },
{ 0xDC, 0x68, 0x08, 0x99, 0x97, 0xAE, 0xAF, 0x8C, 0xC3, 0x0E, 0x01, 0x16, 0x0E, 0x32, 0x06, 0xBA },
{ 0xC3, 0x0E, 0x01, 0x16, 0x0E, 0x32, 0x06, 0xBA, 0xE0, 0x83, 0x01, 0xFA, 0xAB, 0x3E, 0x8F, 0xAC },
{ 0xE0, 0x83, 0x01, 0xFA, 0xAB, 0x3E, 0x8F, 0xAC, 0x5C, 0xD5, 0x9C, 0xB8, 0x46, 0x9C, 0x7D, 0x84 },
{ 0x5C, 0xD5, 0x9C, 0xB8, 0x46, 0x9C, 0x7D, 0x84, 0xF1, 0xC6, 0xFE, 0x5C, 0x9D, 0xA5, 0x4F, 0xB7 },
{ 0xF1, 0xC6, 0xFE, 0x5C, 0x9D, 0xA5, 0x4F, 0xB7, 0x58, 0xB5, 0xB3, 0xDD, 0x0E, 0x28, 0xF1, 0xB0 },
{ 0x58, 0xB5, 0xB3, 0xDD, 0x0E, 0x28, 0xF1, 0xB0, 0x5F, 0x30, 0x3B, 0x56, 0x96, 0x45, 0xF4, 0xA1 },*/
{ 0x5F, 0x30, 0x3B, 0x56, 0x96, 0x45, 0xF4, 0xA1, 0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8 } //normal
};
static uint16_t __attribute__((unused)) LOSI_check(uint16_t val)
{
const uint8_t PROGMEM tab[] = { 0xF1, 0xDA, 0xB6, 0xC8 };
uint8_t res = 0x0B, tmp;
uint16_t calc = val>>2; // don't care about the 2 first bits
for(uint8_t i=0; i<5; i++)
{
tmp=pgm_read_byte_near(&tab[i&0x03]);
if(calc&0x0001)
res ^= tmp>>4;
calc >>= 1;
if(calc&0x0001)
res ^= tmp;
calc >>= 1;
}
return val ^ (res<<12);
}
static void __attribute__((unused)) LOSI_send_packet()
{
memcpy(packet, rx_tx_addr, 4);
if(IS_BIND_IN_PROGRESS)
{
memcpy(&packet[4], rx_tx_addr, 4);
packet[8] = 0x05; // CRC?
packet[9] = 0x52; // CRC?
}
else
{
for(uint8_t i=0; i<3; i++)
{
uint16_t val = LOSI_check(Channel_data[i]<<1);
packet[4+i*2] = val >> 8;
packet[5+i*2] = val;
}
}
CYRF_SetPower(0x38);
CYRF_WriteDataPacketLen(packet, 0x0A);
#if 0
for(uint8_t i=0; i < 0x0A; i++)
debug("%02X ", packet[i]);
debugln();
#endif
}
static void __attribute__((unused)) LOSI_cyrf_init()
{
/* Initialise CYRF chip */
CYRF_WriteRegister(CYRF_28_CLK_EN, 0x02);
CYRF_WriteRegister(CYRF_32_AUTO_CAL_TIME, 0x3C);
CYRF_WriteRegister(CYRF_35_AUTOCAL_OFFSET, 0x14);
CYRF_WriteRegister(CYRF_06_RX_CFG, 0x48);
CYRF_WriteRegister(CYRF_1B_TX_OFFSET_LSB, 0x55);
CYRF_WriteRegister(CYRF_1C_TX_OFFSET_MSB, 0x05);
//CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24);
CYRF_SetPower(0x38);
CYRF_WriteRegister(CYRF_12_DATA64_THOLD, 0x0A);
CYRF_WriteRegister(CYRF_39_ANALOG_CTRL, 0x01);
CYRF_WritePreamble(0x333304);
//CYRF_WriteRegister(CYRF_27_CLK_OVERRIDE, 0x00);
CYRF_WriteRegister(CYRF_10_FRAMING_CFG, 0x4A);
CYRF_WriteRegister(CYRF_1F_TX_OVERRIDE, 0x04); // No CRC
//CYRF_WriteRegister(CYRF_1E_RX_OVERRIDE, 0x14);
//CYRF_WriteRegister(CYRF_14_EOP_CTRL, 0x02);
}
uint16_t LOSI_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(19738);
#endif
LOSI_send_packet();
if(bind_counter)
{
bind_counter--;
if(bind_counter==0)
{
BIND_DONE;
CYRF_ConfigDataCode(LOSI_data_code[1], 16); // Load normal data code
}
return 8763;
}
return 19738;
}
void LOSI_init()
{
LOSI_cyrf_init();
//CYRF_FindBestChannels(hopping_frequency, 1, 0, 0x13, 75); // 75 is unknown since dump stops at 0x27, this routine resets the CRC Seed to 0
//CYRF_ConfigRFChannel(hopping_frequency[0] | 1); // Only odd channels
#ifdef LOSI_FORCE_ID
rx_tx_addr[0] = 0x47;
rx_tx_addr[1] = 0x52;
rx_tx_addr[2] = 0xAE;
rx_tx_addr[3] = 0xAA;
CYRF_ConfigRFChannel(0x27);
#endif
if(IS_BIND_IN_PROGRESS)
{
bind_counter = 300;
CYRF_ConfigDataCode(LOSI_data_code[0], 16); // Load bind data code
}
else
{
CYRF_ConfigDataCode(LOSI_data_code[1], 16); // Load normal data code
bind_counter = 0;
}
}
#endif

View File

@@ -15,10 +15,9 @@
// compatible with MJX WLH08, X600, X800, H26D, Eachine E010
// Last sync with hexfet new_protocols/mjxq_nrf24l01.c dated 2016-01-17
#if defined(MJXQ_NRF24L01_INO)
#if defined(MJXQ_CCNRF_INO)
#include "iface_nrf24l01.h"
#include "iface_nrf250k.h"
#include "iface_xn297.h"
#define MJXQ_BIND_COUNT 150
#define MJXQ_PACKET_PERIOD 4000 // Timeout for callback in uSec
@@ -103,6 +102,12 @@ static uint8_t __attribute__((unused)) MJXQ_pan_tilt_value()
#define MJXQ_CHAN2TRIM(X) (((X) & 0x80 ? (X) : 0x7f - (X)) >> 1)
static void __attribute__((unused)) MJXQ_send_packet(uint8_t bind)
{
//RF freq
hopping_frequency_no++;
XN297_Hopping(hopping_frequency_no / 2);
hopping_frequency_no %= 2 * MJXQ_RF_NUM_CHANNELS; // channels repeated
//Build packet
packet[0] = convert_channel_8b(THROTTLE);
packet[1] = convert_channel_s8b(RUDDER);
packet[4] = 0x40; // rudder does not work well with dyntrim
@@ -192,35 +197,26 @@ static void __attribute__((unused)) MJXQ_send_packet(uint8_t bind)
uint8_t sum = packet[0];
for (uint8_t i=1; i < MJXQ_PACKET_SIZE-1; i++) sum += packet[i];
packet[15] = sum;
hopping_frequency_no++;
if (sub_protocol == E010 || sub_protocol == PHOENIX)
// Send
XN297_SetTxRxMode(TX_EN);
XN297_SetPower();
#ifdef NRF24L01_INSTALLED
if (sub_protocol == H26D || sub_protocol == H26WH)
{
XN297L_Hopping(hopping_frequency_no / 2);
XN297L_SetFreqOffset();
XN297L_SetPower();
XN297L_WritePayload(packet, MJXQ_PACKET_SIZE);
//NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no / 2]);
//NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
//NRF24L01_FlushTx();
//NRF24L01_SetTxRxMode(TX_EN);
//NRF24L01_SetPower();
NRF24L01_WritePayload(packet, MJXQ_PACKET_SIZE);
}
else
{
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no / 2]);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
// Power on, TX mode, 2byte CRC and send packet
if (sub_protocol == H26D || sub_protocol == H26WH)
{
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WritePayload(packet, MJXQ_PACKET_SIZE);
}
else
{
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
XN297_WritePayload(packet, MJXQ_PACKET_SIZE);
}
NRF24L01_SetPower();
#endif
{//E010, PHOENIX, WLH08, X600, X800
XN297_SetFreqOffset();
XN297_WritePayload(packet, MJXQ_PACKET_SIZE);
}
hopping_frequency_no %= 2 * MJXQ_RF_NUM_CHANNELS; // channels repeated
}
static void __attribute__((unused)) MJXQ_RF_init()
@@ -239,22 +235,20 @@ static void __attribute__((unused)) MJXQ_RF_init()
}
if (sub_protocol == E010 || sub_protocol == PHOENIX)
{
XN297L_Init();
XN297L_SetTXAddr(addr, sizeof(addr));
XN297L_HoppingCalib(MJXQ_RF_NUM_CHANNELS);
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_250K);
XN297_SetTXAddr(addr, MJXQ_ADDRESS_LENGTH);
XN297_HoppingCalib(MJXQ_RF_NUM_CHANNELS);
}
else
{
NRF24L01_Initialize();
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M); // this will select the nrf and initialize it, therefore both H26 sub protocols can use common instructions
#ifdef NRF24L01_INSTALLED
if (sub_protocol == H26D || sub_protocol == H26WH)
{
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr, MJXQ_ADDRESS_LENGTH);
}
else
#endif
XN297_SetTXAddr(addr, MJXQ_ADDRESS_LENGTH);
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, MJXQ_PACKET_SIZE);
//NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, MJXQ_PACKET_SIZE); // no RX???
}
}
@@ -275,7 +269,7 @@ static void __attribute__((unused)) MJXQ_init2()
hopping_frequency[i]=pgm_read_byte_near( &E010_map_rfchan[rx_tx_addr[3]&0x0F][i] );
hopping_frequency[i+2]=hopping_frequency[i]+0x10;
}
XN297L_HoppingCalib(MJXQ_RF_NUM_CHANNELS);
XN297_HoppingCalib(MJXQ_RF_NUM_CHANNELS);
break;
case WLH08:
// do nothing

View File

@@ -15,22 +15,30 @@
// compatible with MT99xx, Eachine H7, Yi Zhan i6S and LS114/124
// Last sync with Goebish mt99xx_nrf24l01.c dated 2016-01-29
#if defined(MT99XX_NRF24L01_INO)
#if defined(MT99XX_CCNRF_INO)
#include "iface_nrf24l01.h"
#include "iface_nrf250k.h"
#include "iface_xn297.h"
#define MT99XX_BIND_COUNT 928
#define MT99XX_PACKET_PERIOD_FY805 2460
#define MT99XX_PACKET_PERIOD_MT 2625
#define MT99XX_PACKET_PERIOD_YZ 3125
#define MT99XX_PACKET_PERIOD_A180 3400 // timing changes between the packets 2 x 27220 then 1x 26080, it seems that it is only on the first RF channel which jitters by 1.14ms but hard to pinpoint with XN297dump
#define MT99XX_PACKET_PERIOD_DRAGON 1038 // there is a pause of 2x1038 between the packets 3 and 4 from what XN297dump detects which I think are used for telemetry
#define MT99XX_PACKET_PERIOD_DRAGON 1038 // there is a pause of 2x1038 between two packets, no idea why and how since it is not even stable on a same dump...
#define MT99XX_PACKET_PERIOD_DRAGON_TELEM 10265 // long pause to receive the telemetry packets, 3 are sent by the RX one after the other
#define MT99XX_PACKET_PERIOD_F949G 3450
#define MT99XX_INITIAL_WAIT 500
#define MT99XX_PACKET_SIZE 9
//#define FORCE_A180_ID
//#define FORCE_DRAGON_ID
//#define FORCE_F949G_ID
enum {
MT99XX_DATA,
MT99XX_RX,
MT99XX_CHECK,
};
enum{
// flags going to packet[6] (MT99xx, H7)
@@ -69,10 +77,10 @@ enum{
FLAG_DRAGON_UNK = 0x04,
};
enum {
MT99XX_INIT = 0,
MT99XX_BIND,
MT99XX_DATA
enum{
// flags going to packet[6] (F949G)
FLAG_F949G_LIGHT = 0x01,
FLAG_F949G_3D6G = 0x20,
};
const uint8_t h7_mys_byte[] = {
@@ -89,7 +97,7 @@ const uint8_t ls_mys_byte[] = {
const uint8_t yz_p4_seq[] = {0xa0, 0x20, 0x60};
#ifdef DRAGON_HUB_TELEMETRY
#ifdef MT99XX_HUB_TELEMETRY
const uint8_t DRAGON_seq[] = {0x20, 0x60, 0x20, 0x80};
#endif
@@ -97,6 +105,15 @@ static void __attribute__((unused)) MT99XX_send_packet()
{
static uint8_t seq_num=0;
//Set RF freq
if(sub_protocol == LS)
XN297_RFChannel(0x2D); // LS always transmits on the same channel
else
if(sub_protocol==FY805)
XN297_RFChannel(0x4B); // FY805 always transmits on the same channel
else // MT99 & H7 & YZ & A180 & DRAGON & F949G
XN297_Hopping(hopping_frequency_no);
if(IS_BIND_IN_PROGRESS)
{
//Bind packet
@@ -120,9 +137,10 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[2] = 0x12;
packet[3] = 0x17;
break;
case F949G:
case A180:
packet_period = MT99XX_PACKET_PERIOD_A180;
default: // MT99 & H7 & A180 & DRAGON
default: // MT99 & H7 & A180 & DRAGON & F949G
packet[1] = 0x14;
packet[2] = 0x03;
packet[3] = 0x25;
@@ -132,12 +150,15 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[5] = rx_tx_addr[1];
packet[6] = rx_tx_addr[2];
packet[7] = crc8; // checksum offset
packet[8] = 0xAA; // fixed
if(sub_protocol != F949G)
packet[8] = 0xAA; // fixed
else
packet[8] = 0x00;
}
else
{
if(sub_protocol != YZ)
{ // MT99XX & H7 & LS & FY805 & A180 & DRAGON
{ // MT99XX & H7 & LS & FY805 & A180 & DRAGON & F949G
packet[0] = convert_channel_16b_limit(THROTTLE,0xE1,0x00); // throttle
packet[1] = convert_channel_16b_limit(RUDDER ,0x00,0xE1); // rudder
packet[2] = convert_channel_16b_limit(AILERON ,0xE1,0x00); // aileron
@@ -190,12 +211,8 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[6] = FLAG_DRAGON_RATE
| GET_FLAG( CH6_SW, FLAG_DRAGON_RTH );
#ifdef DRAGON_HUB_TELEMETRY
#ifdef MT99XX_HUB_TELEMETRY
//Telemetry
// C=48 S=Y A= 6C 00 22 CC CC P(9)= 6C 00 22 27 00 00 00 00 60
// C=48 S=Y A= 6C 00 22 CC CC P(9)= 6C 00 22 28 00 00 00 00 61
// C=18 S=Y A= 6C 00 22 CC CC P(9)= 6C 00 22 24 00 00 00 00 5D
// 6C 00 22 = TX address, 27/28/24=vbatt, check = sum(P[0..7]) + AB, where AB comes from? Is it constant?
if(hopping_frequency_no == 0)
{
seq_num++;
@@ -205,7 +222,10 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet_count = 0;
}
if(packet_count > 10) // Telemetry packet request every 10 or 11 packets
{
packet[6] |= 0x04; // Request telemetry flag
phase = MT99XX_RX;
}
packet[7] = DRAGON_seq[seq_num]; // seq: 20 80 20 60 20 80 20 60... 80 changes to 80+batt from telem
if(seq_num==3)
packet[7] |= v_lipo1;
@@ -213,6 +233,12 @@ static void __attribute__((unused)) MT99XX_send_packet()
packet[7] = 0x20;
#endif
break;
case F949G:
packet[6] = 0x02
| GET_FLAG( CH5_SW, FLAG_F949G_3D6G )
| GET_FLAG( CH6_SW, FLAG_F949G_LIGHT );
packet[7] = 0x00;
break;
}
uint8_t result=crc8;
for(uint8_t i=0; i<8; i++)
@@ -246,46 +272,34 @@ static void __attribute__((unused)) MT99XX_send_packet()
}
}
if(sub_protocol == LS)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x2D); // LS always transmits on the same channel
else
if(sub_protocol==FY805)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x4B); // FY805 always transmits on the same channel
else // MT99 & H7 & YZ & A180 & DRAGON
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(packet, MT99XX_PACKET_SIZE);
if(sub_protocol == DRAGON)
{
if(hopping_frequency_no == 6)
packet_period = 3 * MT99XX_PACKET_PERIOD_DRAGON; // hole probably for the telemetry
else
packet_period = MT99XX_PACKET_PERIOD_DRAGON;
}
//Hopp
hopping_frequency_no++;
if(sub_protocol == YZ || sub_protocol == A180 || sub_protocol == DRAGON )
if(sub_protocol == YZ || sub_protocol == A180 || sub_protocol == DRAGON || sub_protocol == F949G)
hopping_frequency_no++; // skip every other channel
if(hopping_frequency_no > 15)
hopping_frequency_no = 0;
NRF24L01_SetPower();
// Send
XN297_SetPower();
XN297_SetFreqOffset();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, MT99XX_PACKET_SIZE);
}
static void __attribute__((unused)) MT99XX_RF_init()
{
NRF24L01_Initialize();
if(sub_protocol == YZ)
XN297_SetScrambledMode(XN297_UNSCRAMBLED);
XN297_Configure(XN297_CRCEN, XN297_UNSCRAMBLED, XN297_250K);
else if(sub_protocol == F949G)
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_250K);
else
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr((uint8_t *)"\xCC\xCC\xCC\xCC\xCC", 5);
if(sub_protocol == YZ)
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps (nRF24L01+ only)
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) );
XN297_HoppingCalib(16);
#ifdef MT99XX_HUB_TELEMETRY
XN297_SetRXAddr(rx_tx_addr, MT99XX_PACKET_SIZE);
#endif
}
static void __attribute__((unused)) MT99XX_initialize_txid()
@@ -325,7 +339,16 @@ static void __attribute__((unused)) MT99XX_initialize_txid()
//channel_offset = 0x06
break;
#endif
default: //MT99 & H7 & A180 & DRAGON
#ifdef FORCE_F949G_ID
case F949G:
rx_tx_addr[0] = 0x7E; // LilTeo14 ID
rx_tx_addr[1] = 0x2F;
rx_tx_addr[2] = 0x29;
//crc8 = 0xD6
//channel_offset = 0x03
break;
#endif
default: //MT99 & H7 & A180 & DRAGON & F949G
rx_tx_addr[2] = 0x00;
break;
}
@@ -346,31 +369,77 @@ static void __attribute__((unused)) MT99XX_initialize_txid()
uint16_t MT99XX_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
if(bind_counter)
switch(phase)
{
bind_counter--;
if (bind_counter == 0)
{
// set tx address for data packets
XN297_SetTXAddr(rx_tx_addr, 5);
// set rf channels
uint8_t channel_offset = ((crc8>>4) + (crc8 & 0x0f)) % 8;
for(uint8_t i=0;i<16;i++)
hopping_frequency[i] += channel_offset;
BIND_DONE;
}
case MT99XX_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
if(bind_counter)
{
bind_counter--;
if (bind_counter == 0)
{
// set tx address for data packets
XN297_SetTXAddr(rx_tx_addr, 5);
// set rf channels
uint8_t channel_offset = ((crc8>>4) + (crc8 & 0x0f)) % 8;
for(uint8_t i=0;i<16;i++)
hopping_frequency[i] += channel_offset;
XN297_HoppingCalib(16);
BIND_DONE;
}
}
MT99XX_send_packet();
break;
#ifdef MT99XX_HUB_TELEMETRY
case MT99XX_RX:
//Switch to RX
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
phase++;
return MT99XX_PACKET_PERIOD_DRAGON_TELEM - MT99XX_PACKET_PERIOD_DRAGON - 500;
case MT99XX_CHECK:
//Check telem
if(XN297_IsRX())
{
//debug("RX");
if(XN297_ReadPayload(packet_in, MT99XX_PACKET_SIZE))
{
// C=48 S=Y A= 6C 00 22 CC CC P(9)= 6C 00 22 27 00 00 00 00 60
// C=48 S=Y A= 6C 00 22 CC CC P(9)= 6C 00 22 28 00 00 00 00 61
// C=18 S=Y A= 6C 00 22 CC CC P(9)= 6C 00 22 24 00 00 00 00 5D
// 6C 00 22 = TX address, 27/28/24=vbatt, check = sum(P[0..7]) + AB
// D2 EE 00 25 00 00 00 00 90 -> check also + AB
//for(uint8_t i=0; i<MT99XX_PACKET_SIZE; i++)
// debug(" %02X",packet_in[i]);
uint8_t check=0xAB;
for(uint8_t i=0; i<8; i++)
check += packet_in[i];
if(packet_in[8] == check && packet_in[0] == rx_tx_addr[0] && packet_in[1] == rx_tx_addr[1] && packet_in[2] == rx_tx_addr[2])
{ // checksum and address are ok
// debug(" OK");
v_lipo1 = packet_in[3] & 0x7F; // Batt
v_lipo2 = packet_in[3] & 0x80; // Low batt flag
RX_RSSI=100;
telemetry_link = 1;
}
}
//debugln("");
}
//Switch to TX
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(TX_EN);
phase=MT99XX_DATA;
return 500;
#endif
}
MT99XX_send_packet();
return packet_period;
return packet_period;
}
void MT99XX_init(void)
{
if(sub_protocol != A180 && sub_protocol != DRAGON)
if(sub_protocol != A180 && sub_protocol != DRAGON && sub_protocol != F949G)
BIND_IN_PROGRESS; // autobind protocol
bind_counter = MT99XX_BIND_COUNT;
@@ -380,5 +449,6 @@ void MT99XX_init(void)
packet_period = MT99XX_PACKET_PERIOD_MT;
packet_count=0;
phase=MT99XX_DATA;
}
#endif

View File

@@ -0,0 +1,241 @@
/*
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(MOULDKG_NRF24L01_INO)
#include "iface_xn297.h"
//#define FORCE_MOULDKG_ORIGINAL_ID
#define MOULDKG_PACKET_PERIOD 5000
#define MOULDKG_BIND_PACKET_PERIOD 12000
#define MOULDKG_TX_BIND_CHANNEL 11
#define MOULDKG_RX_BIND_CHANNEL 76
#define MOULDKG_PAYLOAD_SIZE_DIGIT 5
#define MOULDKG_PAYLOAD_SIZE_ANALOG 10
#define MOULDKG_BIND_PAYLOAD_SIZE 7
#define MOULDKG_BIND_COUNT 300
#define MOULDKG_RF_NUM_CHANNELS 4
enum {
MOULDKG_BINDTX=0,
MOULDKG_BINDRX,
MOULDKG_PREP_DATA,
MOULDKG_PREP_DATA1,
MOULDKG_DATA,
};
uint8_t MOULDKG_RX_id[4*3];
static void __attribute__((unused)) MOULDKG_send_packet()
{
uint8_t len = MOULDKG_BIND_PAYLOAD_SIZE;
memcpy(&packet[1],rx_tx_addr,3);
if(IS_BIND_IN_PROGRESS)
{
packet[0] = 0xC0;
memset(&packet[4], 0x00, 3);
}
else
{
uint8_t n = num_ch<<2;
if(sub_protocol == MOULDKG_ANALOG)
{
packet[0] = 0x36;
uint8_t ch[]={ 1,0,2,3 };
for(uint8_t i=0;i<4;i++)
packet[i+4] = convert_channel_8b(ch[i]+n);
len = MOULDKG_PAYLOAD_SIZE_ANALOG;
}
else
{//DIGIT
len = MOULDKG_PAYLOAD_SIZE_DIGIT;
uint8_t val=0;
if(packet_count&1)
{
packet[0] = 0x31;
//Button B
if(Channel_data[CH2+n]>CHANNEL_MAX_COMMAND) val |= 0x40;
else if(Channel_data[CH2+n]<CHANNEL_MIN_COMMAND) val |= 0x80;
//Button C
if(Channel_data[CH3+n]>CHANNEL_MAX_COMMAND) val |= 0x10;
else if(Channel_data[CH3+n]<CHANNEL_MIN_COMMAND) val |= 0x20;
}
else
{
packet[0] = 0x30;
val = 0x60;
// | GET_FLAG(CH5_SW, 0x80) // Button E
// | GET_FLAG(CH6_SW, 0x10); // Button F
}
//Button A
if(Channel_data[CH1+n]>CHANNEL_MAX_COMMAND) val |= 0x01;
else if(Channel_data[CH1+n]<CHANNEL_MIN_COMMAND) val |= 0x02;
//Button D
if(Channel_data[CH4+n]>CHANNEL_MAX_COMMAND) val |= 0x04;
else if(Channel_data[CH4+n]<CHANNEL_MIN_COMMAND) val |= 0x08;
packet[4]= val;
}
}
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, len);
#if 0
for(uint8_t i=0; i < len; i++)
debug("%02X ", packet[i]);
debugln();
#endif
}
static void __attribute__((unused)) MOULDKG_initialize_txid()
{
//rx_tx_addr[0] = rx_tx_addr[3]; // Use RX_num;
#ifdef FORCE_MOULDKG_ORIGINAL_ID
rx_tx_addr[0]=0x57;
rx_tx_addr[1]=0x1B;
rx_tx_addr[2]=0xF8;
#endif
}
static void __attribute__((unused)) MOULDKG_RF_init()
{
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr((uint8_t*)"KDH", 3);
XN297_SetRXAddr((uint8_t*)"KDH", MOULDKG_BIND_PAYLOAD_SIZE);
}
uint16_t MOULDKG_callback()
{
uint8_t rf,n;
uint16_t addr;
switch(phase)
{
case MOULDKG_BINDTX:
if(XN297_IsRX())
{
//Example: TX: C=11 S=Y A= 4B 44 48 P(7)= C0 37 02 4F 00 00 00
// RX: C=76 S=Y A= 4B 44 48 P(7)= 5A 37 02 4F 03 0D 8E
// 03 0D 8E => RF channels 0F,1C,39,3C
XN297_ReadPayload(packet_in, MOULDKG_BIND_PAYLOAD_SIZE);
for(uint8_t i=0; i < MOULDKG_BIND_PAYLOAD_SIZE; i++)
debug("%02X ", packet_in[i]);
debugln();
//Not sure if I should test packet_in[0]
if(memcmp(&packet_in[1],&packet[1],3)==0)
{//TX ID match
if(option == 0)
{
memcpy(MOULDKG_RX_id,&packet_in[4],3);
phase = MOULDKG_PREP_DATA1;
}
else
{// Store RX ID
addr=MOULDKG_EEPROM_OFFSET+RX_num*3;
for(uint8_t i=0;i<3;i++)
eeprom_write_byte((EE_ADDR)(addr+i),packet_in[4+i]);
phase = MOULDKG_PREP_DATA;
}
break;
}
}
XN297_RFChannel(MOULDKG_TX_BIND_CHANNEL); // Set TX bind channel
XN297_SetTxRxMode(TXRX_OFF);
MOULDKG_send_packet();
phase++;
return 600;
case MOULDKG_BINDRX:
//Wait for the packet transmission to finish
while(XN297_IsPacketSent()==false);
//Switch to RX
XN297_SetTxRxMode(TXRX_OFF);
XN297_RFChannel(MOULDKG_RX_BIND_CHANNEL); // Set RX bind channel
XN297_SetTxRxMode(RX_EN);
phase = MOULDKG_BINDTX;
return MOULDKG_BIND_PACKET_PERIOD-600;
case MOULDKG_PREP_DATA:
addr=MOULDKG_EEPROM_OFFSET+RX_num*3;
debug("RXID: ");
for(uint8_t i=0;i<3*4;i++)
{ // load 4 consecutive RX IDs
MOULDKG_RX_id[i]=eeprom_read_byte((EE_ADDR)(addr+i));
debug(" %02X",MOULDKG_RX_id[i]);
}
debugln("");
case MOULDKG_PREP_DATA1:
//Switch to normal mode
BIND_DONE;
XN297_SetTxRxMode(TXRX_OFF);
phase = MOULDKG_DATA;
break;
case MOULDKG_DATA:
#ifdef MULTI_SYNC
if(num_ch==0)
telemetry_set_input_sync(MOULDKG_PACKET_PERIOD);
#endif
if(option == 0) option++;
if(num_ch<option)
{
//Set RX ID address
n = num_ch*3;
XN297_SetTXAddr(&MOULDKG_RX_id[n], 3);
//Set frequency based on current RX ID and packet number
rf = 0x0C;
if(packet_count & 0x04)
{
n++;
rf += 0x20;
}
if(packet_count & 0x02)
rf += 0x10 + (MOULDKG_RX_id[n] >> 4);
else
rf += MOULDKG_RX_id[n] & 0x0F;
XN297_RFChannel(rf);
#if 1
debugln("num_ch=%d,packet_count=%d,rf=%02X,ID=%02X %02X %02X",num_ch,packet_count,rf,MOULDKG_RX_id[num_ch*3],MOULDKG_RX_id[num_ch*3+1],MOULDKG_RX_id[num_ch*3+2]);
#endif
MOULDKG_send_packet();
if(num_ch==0)
packet_count++;
}
num_ch++;
num_ch &= 0x03;
break;
}
return MOULDKG_PACKET_PERIOD/4;
}
void MOULDKG_init()
{
if(option == 0)
BIND_IN_PROGRESS;
MOULDKG_initialize_txid();
MOULDKG_RF_init();
bind_counter = MOULDKG_BIND_COUNT;
if(IS_BIND_IN_PROGRESS)
phase = MOULDKG_BINDTX;
else
phase = MOULDKG_PREP_DATA;
packet_count = 0;
num_ch = 0;
}
#endif
// Analog
// Bind TX: C=11 S=Y A= 4B 44 48 P(7)= C0 46 01 00 00 00 00
// Bind RX: 5A 46 01 00 63 82 4E
// Norm: C=15 S=Y A= 63 82 4E P(10)= 36 46 01 00 80 80 80 80 00 00

View File

@@ -3,7 +3,7 @@
3,FrskyD,D8,Cloned
4,Hisky,Hisky,HK310
5,V2x2,V2x2,JXD506,MR101
6,DSM,DSM2_1F,DSM2_2F,DSMX_1F,DSMX_2F,AUTO
6,DSM,DSM2_1F,DSM2_2F,DSMX_1F,DSMX_2F,AUTO,DSMR_1F
7,Devo,8CH,10CH,12CH,6CH,7CH
8,YD717,YD717,SKYWLKR,SYMAX4,XINXUN,NIHUI
9,KN,WLTOYS,FEILUN
@@ -14,7 +14,7 @@
14,Bayang,Bayang,H8S3D,X16_AH,IRDRONE,DHD_D4,QX100
15,FrskyX,CH_16,CH_8,EU_16,EU_8,Cloned,Clon_8
16,ESky,Std,ET4
17,MT99xx,MT,H7,YZ,LS,FY805,A180,Dragon
17,MT99xx,MT,H7,YZ,LS,FY805,A180,Dragon,F949G
18,MJXq,WLH08,X600,X800,H26D,E010,H26WH,PHOENIX
19,Shenqi
20,FY326,FY326,FY319
@@ -25,7 +25,7 @@
25,FrskyV
26,HONTAI,HONTAI,JJRCX1,X5C1,FQ777_951
27,OpnLrs
28,AFHDS2A,PWM_IBUS,PPM_IBUS,PWM_SBUS,PPM_SBUS,PWM_IB16,PPM_IB16
28,AFHDS2A,PWM_IBUS,PPM_IBUS,PWM_SBUS,PPM_SBUS,PWM_IB16,PPM_IB16,PWM_SB16,PPM_SB16
29,Q2X2,Q222,Q242,Q282
30,WK2x01,WK2801,WK2401,W6_5_1,W6_6_1,W6_HEL,W6_HEL_I
31,Q303,Q303,CX35,CX10D,CX10WD
@@ -42,11 +42,11 @@
42,BUGSMINI,BUGSMINI,BUGS3H
43,Traxxas,RX6519
44,NCC1701
45,E01X,E012,E015,E016H
45,E01X,E012,E015
46,V911S,V911S,E119
47,GD00x,GD_V1,GD_V2
48,V761,3CH,4CH
49,KF606
49,KF606,KF606,MIG320
50,Redpine,Fast,Slow
51,Potensic,A20
52,ZSX,280
@@ -57,7 +57,7 @@
57,HoTT,Sync,No_Sync
58,FX816,P38
59,Bayang_RX,Multi,CPPM
60,Pelikan,Pro,Lite
60,Pelikan,Pro,Lite,SCX24
61,Tiger
62,XK,X450,X420
63,XN_DUMP,250K,1M,2M,AUTO
@@ -81,4 +81,10 @@
81,E010r5
82,LOLI
83,E129
84,JOYSWAY
84,JOYSWAY
85,E016H
87,IKEA
88,WILLIFM
89,Losi
90,MouldKg,Analog,Digit
91,Xerall

View File

@@ -0,0 +1,192 @@
/*
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(MULTI_CONFIG_INO)
#ifdef CYRF6936_INSTALLED
#include "iface_cyrf6936.h"
#endif
void CONFIG_write_GID(uint32_t id)
{
for(uint8_t i=0;i<4;i++)
eeprom_write_byte((EE_ADDR)EEPROM_ID_OFFSET+i,id >> (i*8));
//eeprom_write_byte((EE_ADDR)(EEPROM_ID_OFFSET+10),0xf0);
}
void CONFIG_write_CID(uint8_t *data)
{
for(uint8_t i=0;i<6;i++)
eeprom_write_byte((EE_ADDR)EEPROM_CID_OFFSET+i, data[i]);
//eeprom_write_byte((EE_ADDR)EEPROM_CID_INIT_OFFSET, 0xf0);
}
uint16_t CONFIG_callback()
{
static uint8_t line=0, page=0;
uint32_t id=0;
// [0] = page<<4|line number
// [1..6] = max 6 bytes
if(CONFIG_SerialRX)
{
debug("config");
for(uint8_t i=0; i<7; i++)
debug("%02X ",CONFIG_SerialRX_val[i]);
debugln("");
CONFIG_SerialRX = false;
switch(CONFIG_SerialRX_val[0]&0x0F)
{
//case 0:
// Page change
// break;
case 1:
for(uint8_t i=0; i<4; i++)
{
id <<= 8;
id |= CONFIG_SerialRX_val[i+1];
}
debugln("Update ID to %lx", id);
CONFIG_write_GID(id);
break;
case 2:
if(CONFIG_SerialRX_val[1]==0xAA)
{
#define STM32_UUID ((uint32_t *)0x1FFFF7E8)
id = STM32_UUID[0] ^ STM32_UUID[1] ^ STM32_UUID[2];
debugln("Reset GID to %lx", id);
CONFIG_write_GID(id);
}
break;
#ifdef CYRF6936_INSTALLED
case 4:
debug("Update CID to ");
for(uint8_t i=0; i<6; i++)
debug("%02X ",CONFIG_SerialRX_val[i+1]);
debugln("");
CONFIG_write_CID(&CONFIG_SerialRX_val[1]);
case 5:
if(CONFIG_SerialRX_val[1]==0xAA)
{
uint8_t data[6];
CYRF_WriteRegister(CYRF_25_MFG_ID, 0xFF); /* Fuses power on */
CYRF_ReadRegisterMulti(CYRF_25_MFG_ID, data, 6);
CYRF_WriteRegister(CYRF_25_MFG_ID, 0x00); /* Fuses power off */
debug("Reset CID to ");
for(uint8_t i=0; i<6; i++)
debug("%02X ",data[i]);
debugln("");
CONFIG_write_CID(data);
}
break;
#endif
case 7:
if(CONFIG_SerialRX_val[1]==0xAA)
{
debugln("Format EE");
#if defined(STM32_BOARD)
EEPROM.format();
#else
for (uint16_t i = 0; i < 512; i++)
eeprom_write_byte((EE_ADDR)i, 0xFF);
#endif
}
break;
}
}
if( telemetry_link )
return 10000;
// [0] = page<<4|line number
// line=0: VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_PATCH_LEVEL, Channel order:RUDDER<<6|THROTTLE<<4|ELEVATOR<<2|AILERON
// [1..21] = max 20 characters, any displayable chars followed by:
// 0x00 : end of line
// 0x80+len: selectable text to follow
// 0x90+len: selectable text to follow with "Are you sure?"
// 0xA0+len: not editable dec value
// 0xB0+len: editable dec value
// 0xC0+len: not editable hex value
// 0xD0+len: editable hex value
memset(&packet_in[1],0,20);
do
{
packet_in[0] = (page<<4) | line;
switch(line)
{
case 0:
packet_in[1]=VERSION_MAJOR;
packet_in[2]=VERSION_MINOR;
packet_in[3]=VERSION_REVISION;
packet_in[4]=VERSION_PATCH_LEVEL;
packet_in[5]=RUDDER<<6|THROTTLE<<4|ELEVATOR<<2|AILERON;
break;
case 1:
//Global ID
#ifndef FORCE_GLOBAL_ID
memcpy(&packet_in[1],"Global ID",9);
packet_in[10] = 0xD0 + 4;
#else
memcpy(&packet_in[1],"Fixed ID ",9);
packet_in[10] = 0xC0 + 4;
#endif
MProtocol_id_master = random_id(EEPROM_ID_OFFSET,false);
set_rx_tx_addr(MProtocol_id_master);
for(uint8_t i=0; i<4; i++)
packet_in[11+i]=rx_tx_addr[i];
break;
#if defined(STM32_BOARD) && not defined(FORCE_GLOBAL_ID)
case 2:
//Reset global ID
packet_in[1] = 0x90+9;
memcpy(&packet_in[2],"Reset GID",9);
break;
#endif
#ifdef CYRF6936_INSTALLED
case 4:
//Cyrf ID
#ifndef FORCE_CYRF_ID
memcpy(&packet_in[1],"Cyrf ID",7);
packet_in[8] = 0xD0 + 6;
CYRF_GetMfgData(&packet_in[9]);
#else
memcpy(&packet_in[1],"Fixed CID",9);
packet_in[10] = 0xC0 + 6;
CYRF_GetMfgData(&packet_in[11]);
#endif
break;
#ifndef FORCE_CYRF_ID
case 5:
//Reset Cyrf ID
packet_in[1] = 0x90+9;
memcpy(&packet_in[2],"Reset CID",9);
break;
#endif
#endif
case 7:
packet_in[1] = 0x90+13;
memcpy(&packet_in[2],"Format EEPROM",13);
break;
}
line++;
line %= 8;
}
while(packet_in[1]==0); // next line if empty
telemetry_link = 1;
return 10000;
}
void CONFIG_init()
{
}
#endif

View File

@@ -97,6 +97,12 @@ const char STR_E016HV2[] ="E016Hv2";
const char STR_E010R5[] ="E010r5";
const char STR_LOLI[] ="LOLI";
const char STR_E129[] ="E129";
const char STR_E016H[] ="E016H";
const char STR_IKEAANSLUTA[]="Ansluta";
const char STR_CONFIG[] ="Config";
const char STR_LOSI[] ="Losi";
const char STR_MOULDKG[] ="MouldKg";
const char STR_XERALL[] ="Xerall";
const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20";
const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501";
@@ -104,7 +110,7 @@ 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_HISKY[] = "\x05""Std\0 ""HK310";
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";
const char STR_SUBTYPE_DSM[] = "\x04""2 1F""2 2F""X 1F""X 2F""Auto""R 1F";
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_KN[] = "\x06""WLtoys""FeiLun";
@@ -113,7 +119,7 @@ const char STR_SUBTYPE_SLT[] = "\x06""V1_6ch""V2_8ch""Q100\0 ""Q200\0 ""M
const char STR_SUBTYPE_CX10[] = "\x07""Green\0 ""Blue\0 ""DM007\0 ""-\0 ""JC3015a""JC3015b""MK33041";
const char STR_SUBTYPE_CG023[] = "\x05""Std\0 ""YD829";
const char STR_SUBTYPE_BAYANG[] = "\x07""Std\0 ""H8S3D\0 ""X16 AH\0""IRDrone""DHD D4\0""QX100\0 ";
const char STR_SUBTYPE_MT99[] = "\x06""MT99\0 ""H7\0 ""YZ\0 ""LS\0 ""FY805\0""A180\0 ""Dragon";
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_MJXQ[] = "\x07""WLH08\0 ""X600\0 ""X800\0 ""H26D\0 ""E010\0 ""H26WH\0 ""Phoenix";
const char STR_SUBTYPE_FY326[] = "\x05""Std\0 ""FY319";
const char STR_SUBTYPE_HONTAI[] = "\x07""Std\0 ""JJRC X1""X5C1\0 ""FQ_951";
@@ -127,14 +133,14 @@ const char STR_SUBTYPE_CORONA[] = "\x05""V1\0 ""V2\0 ""FD V3";
const char STR_SUBTYPE_HITEC[] = "\x07""Optima\0""Opt Hub""Minima\0";
const char STR_SUBTYPE_BUGS_MINI[] = "\x06""Std\0 ""Bugs3H";
const char STR_SUBTYPE_TRAXXAS[] = "\x04""6519";
const char STR_SUBTYPE_E01X[] = "\x05""E012\0""E015\0""E016H";
const char STR_SUBTYPE_E01X[] = "\x05""E012\0""E015\0";
const char STR_SUBTYPE_GD00X[] = "\x05""GD_V1""GD_V2";
const char STR_SUBTYPE_REDPINE[] = "\x04""Fast""Slow";
const char STR_SUBTYPE_POTENSIC[] = "\x03""A20";
const char STR_SUBTYPE_ZSX[] = "\x07""280JJRC";
const char STR_SUBTYPE_HEIGHT[] = "\x03""5ch""8ch";
const char STR_SUBTYPE_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 ";
const char STR_SUBTYPE_XN297DUMP[] = "\x07""250Kbps""1Mbps\0 ""2Mbps\0 ""Auto\0 ""NRF\0 ""CC2500\0";
const char STR_SUBTYPE_ESKY150[] = "\x03""4ch""7ch";
const char STR_SUBTYPE_ESKY150V2[] = "\x05""150V2";
const char STR_SUBTYPE_V911S[] = "\x05""V911S""E119\0";
@@ -146,13 +152,15 @@ const char STR_SUBTYPE_FRSKYL[] = "\x08""LR12\0 ""LR12 6ch";
const char STR_SUBTYPE_WFLY[] = "\x05""WFR0x";
const char STR_SUBTYPE_WFLY2[] = "\x05""RF20x";
const char STR_SUBTYPE_HOTT[] = "\x07""Sync\0 ""No_Sync";
const char STR_SUBTYPE_PELIKAN[] = "\x04""Pro\0""Lite";
const char STR_SUBTYPE_PELIKAN[] = "\x05""Pro\0 ""Lite\0""SCX24";
const char STR_SUBTYPE_V761[] = "\x03""3ch""4ch";
const char STR_SUBTYPE_RLINK[] = "\x07""Surface""Air\0 ""DumboRC";
const char STR_SUBTYPE_REALACC[] = "\x03""R11";
const char STR_SUBTYPE_KYOSHO[] = "\x04""FHSS""Hype";
const char STR_SUBTYPE_FUTABA[] = "\x05""SFHSS";
const char STR_SUBTYPE_JJRC345[] = "\x08""JJRC345\0""SkyTmblr";
const char STR_SUBTYPE_MOULKG[] = "\x06""Analog""Digit\0";
const char STR_SUBTYPE_KF606[] = "\x06""KF606\0""MIG320";
#define NO_SUBTYPE nullptr
@@ -225,7 +233,7 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_DM002, STR_DM002, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, DM002_init, DM002_callback },
#endif
#if defined(DSM_CYRF6936_INO)
{PROTO_DSM, STR_DSM, STR_SUBTYPE_DSM, 5, OPTION_MAXTHR, 0, 1, SW_CYRF, DSM_init, DSM_callback },
{PROTO_DSM, STR_DSM, STR_SUBTYPE_DSM, 6, OPTION_MAXTHR, 0, 1, SW_CYRF, DSM_init, DSM_callback },
#endif
#if defined(DSM_RX_CYRF6936_INO)
{PROTO_DSM_RX, STR_DSM_RX, STR_CPPM, NBR_CPPM, OPTION_NONE, 0, 1, SW_CYRF, DSM_RX_init, DSM_RX_callback },
@@ -233,11 +241,14 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(E010R5_CYRF6936_INO)
{PROTO_E010R5, STR_E010R5, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_CYRF, E010R5_init, E010R5_callback },
#endif
#if defined(E016H_NRF24L01_INO)
{PROTO_E016H, STR_E016H, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, E016H_init, E016H_callback },
#endif
#if defined(E016HV2_CC2500_INO)
{PROTO_E016HV2, STR_E016HV2, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_CC2500, E016HV2_init, E016HV2_callback },
#endif
#if defined(E01X_NRF24L01_INO)
{PROTO_E01X, STR_E01X, STR_SUBTYPE_E01X, 3, OPTION_OPTION, 0, 0, SW_NRF, E01X_init, E01X_callback },
{PROTO_E01X, STR_E01X, STR_SUBTYPE_E01X, 2, OPTION_OPTION, 0, 0, SW_NRF, E01X_init, E01X_callback },
#endif
#if defined(E129_CYRF6936_INO)
{PROTO_E129, STR_E129, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_CYRF, E129_init, E129_callback },
@@ -324,6 +335,9 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(HUBSAN_A7105_INO)
{PROTO_HUBSAN, STR_HUBSAN, STR_SUBTYPE_HUBSAN, 3, OPTION_VIDFREQ, 0, 0, SW_A7105, HUBSAN_init, HUBSAN_callback },
#endif
#if defined(IKEAANSLUTA_CC2500_INO)
{PROTO_IKEAANSLUTA,STR_IKEAANSLUTA,NO_SUBTYPE, 0, OPTION_OPTION, 0, 0, SW_CC2500, IKEAANSLUTA_init,IKEAANSLUTA_callback },
#endif
#if defined(J6PRO_CYRF6936_INO)
{PROTO_J6PRO, STR_J6PRO, NO_SUBTYPE, 0, OPTION_NONE, 0, 1, SW_CYRF, J6PRO_init, J6PRO_callback },
#endif
@@ -334,7 +348,7 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_JOYSWAY, STR_JOYSWAY, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_A7105, JOYSWAY_init, JOYSWAY_callback },
#endif
#if defined(KF606_CCNRF_INO)
{PROTO_KF606, STR_KF606, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, KF606_init, KF606_callback },
{PROTO_KF606, STR_KF606, STR_SUBTYPE_KF606, 2, OPTION_RFTUNE, 0, 0, SW_NRF, KF606_init, KF606_callback },
#endif
#if defined(KN_NRF24L01_INO)
{PROTO_KN, STR_KN, STR_SUBTYPE_KN, 2, OPTION_NONE, 0, 0, SW_NRF, KN_init, KN_callback },
@@ -345,23 +359,29 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(LOLI_NRF24L01_INO)
{PROTO_LOLI, STR_LOLI, NO_SUBTYPE, 0, OPTION_NONE, 1, 0, SW_NRF, LOLI_init, LOLI_callback },
#endif
#if defined(MJXQ_NRF24L01_INO)
{PROTO_MJXQ, STR_MJXQ, STR_SUBTYPE_MJXQ, 7, OPTION_RFTUNE, 0, 0, SW_NRF, MJXQ_init, MJXQ_callback },
#if defined(LOSI_CYRF6936_INO)
{PROTO_LOSI, STR_LOSI, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_CYRF, LOSI_init, LOSI_callback },
#endif
#if defined(MJXQ_CCNRF_INO)
{PROTO_MJXQ, STR_MJXQ, STR_SUBTYPE_MJXQ, 7, OPTION_NONE, 0, 0, SW_NRF, MJXQ_init, MJXQ_callback },
#endif
#if defined(MLINK_CYRF6936_INO)
{PROTO_MLINK, STR_MLINK, NO_SUBTYPE, 0, OPTION_NONE, 1, 0, SW_CYRF, MLINK_init, MLINK_callback },
#endif
#if defined(MT99XX_NRF24L01_INO)
{PROTO_MT99XX, STR_MT99XX, STR_SUBTYPE_MT99, 7, OPTION_NONE, 0, 0, SW_NRF, MT99XX_init, MT99XX_callback },
#if defined(MOULDKG_NRF24L01_INO)
{PROTO_MOULDKG, STR_MOULDKG, STR_SUBTYPE_MOULKG, 2, OPTION_OPTION, 0, 0, SW_NRF, MOULDKG_init, MOULDKG_callback },
#endif
#if defined(MT99XX_CCNRF_INO)
{PROTO_MT99XX, STR_MT99XX, STR_SUBTYPE_MT99, 8, OPTION_NONE, 0, 0, SW_NRF, MT99XX_init, MT99XX_callback },
#endif
#if defined(NCC1701_NRF24L01_INO)
{PROTO_NCC1701, STR_NCC1701, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, NCC_init, NCC_callback },
#endif
#if defined(OMP_CC2500_INO)
{PROTO_OMP, STR_OMP, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, OMP_init, OMP_callback },
#if defined(OMP_CCNRF_INO)
{PROTO_OMP, STR_OMP, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, OMP_init, OMP_callback },
#endif
#if defined(PELIKAN_A7105_INO)
{PROTO_PELIKAN, STR_PELIKAN, STR_SUBTYPE_PELIKAN, 2, OPTION_NONE, 0, 1, SW_A7105, PELIKAN_init, PELIKAN_callback },
{PROTO_PELIKAN, STR_PELIKAN, STR_SUBTYPE_PELIKAN, 3, OPTION_NONE, 0, 1, SW_A7105, PELIKAN_init, PELIKAN_callback },
#endif
#if defined(POTENSIC_NRF24L01_INO)
{PROTO_POTENSIC, STR_POTENSIC, STR_SUBTYPE_POTENSIC, 1, OPTION_NONE, 0, 0, SW_NRF, POTENSIC_init, POTENSIC_callback },
@@ -372,7 +392,7 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(CX10_NRF24L01_INO)
{PROTO_Q2X2, STR_Q2X2, STR_SUBTYPE_Q2X2, 3, OPTION_NONE, 0, 0, SW_NRF, CX10_init, CX10_callback },
#endif
#if defined(Q303_NRF24L01_INO)
#if defined(Q303_CCNRF_INO)
{PROTO_Q303, STR_Q303, STR_SUBTYPE_Q303, 4, OPTION_NONE, 0, 0, SW_NRF, Q303_init, Q303_callback },
#endif
#if defined(Q90C_CCNRF_INO)
@@ -427,11 +447,14 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_WFLY2, STR_WFLY2, STR_SUBTYPE_WFLY2, 1, OPTION_OPTION, 1, 0, SW_A7105, WFLY2_init, WFLY2_callback },
// {PROTO_WFLY2, STR_WFLY2, STR_SUBTYPE_WFLY2, 1, OPTION_WBUS, 1, 0, SW_A7105, WFLY2_init, WFLY2_callback },// crash OpenTX...
#endif
#if defined(XK_NRF24L01_INO)
#if defined(XERALL_NRF24L01_INO)
{PROTO_XERALL, STR_XERALL, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, XERALL_init, XERALL_callback },
#endif
#if defined(XK_CCNRF_INO)
{PROTO_XK, STR_XK, STR_SUBTYPE_XK, 2, OPTION_RFTUNE, 0, 0, SW_NRF, XK_init, XK_callback },
#endif
#if defined(XN297DUMP_NRF24L01_INO)
{PROTO_XN297DUMP, STR_XN297DUMP, STR_SUBTYPE_XN297DUMP, 5, OPTION_RFCHAN, 0, 0, SW_NRF, XN297Dump_init, XN297Dump_callback },
{PROTO_XN297DUMP, STR_XN297DUMP, STR_SUBTYPE_XN297DUMP, 6, OPTION_RFCHAN, 0, 0, SW_NRF, XN297Dump_init, XN297Dump_callback },
#endif
#if defined(YD717_NRF24L01_INO)
{PROTO_YD717, STR_YD717, STR_SUBTYPE_YD717, 5, OPTION_NONE, 0, 0, SW_NRF, YD717_init, YD717_callback },
@@ -445,5 +468,71 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(NANORF_NRF24L01_INO)
{PROTO_NANORF, STR_NANORF, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, NANORF_init, NANORF_callback },
#endif
{0x00, nullptr, nullptr, 0, 0, 0, 0, 0, nullptr, nullptr }
{0xFF, nullptr, nullptr, 0, 0, 0, 0, 0, nullptr, nullptr }
};
#ifdef MULTI_TELEMETRY
uint16_t PROTOLIST_callback()
{
if(option != prev_option)
{//Only send once
/* Type 0x11 Protocol list export via telemetry. Used by the protocol PROTO_PROTOLIST=0, the list entry is given by the Option field.
length: variable
data[0] = protocol number, 0xFF is an invalid list entry (Option value too large), Option == 0xFF -> number of protocols in the list
data[1..n] = protocol name null terminated
data[n+1] = flags
flags>>4 Option text number to be displayed (check multi status for description)
flags&0x01 failsafe supported
flags&0x02 Channel Map Disabled supported
data[n+2] = number of sub protocols
data[n+3] = sub protocols text length, only sent if nbr_sub != 0
data[n+4..] = sub protocol names, only sent if nbr_sub != 0
*/
prev_option = option;
if(option >= (sizeof(multi_protocols)/sizeof(mm_protocol_definition)) - 1)
{//option is above the end of the list
//Header
multi_send_header(MULTI_TELEMETRY_PROTO, 1);
if(option == 0xFF)
Serial_write((sizeof(multi_protocols)/sizeof(mm_protocol_definition)) - 1); //Nbr proto
else
Serial_write(0xFF); //Error
}
else
{//valid option value
uint8_t proto_len = strlen(multi_protocols[option].ProtoString) + 1;
uint8_t nbr_sub = multi_protocols[option].nbrSubProto;
uint8_t sub_len = 0;
if(nbr_sub)
sub_len = multi_protocols[option].SubProtoString[0];
//Header
multi_send_header(MULTI_TELEMETRY_PROTO, 1 + proto_len + 1 + 1 + (nbr_sub?1:0) + (nbr_sub * sub_len));
//Protocol number
Serial_write(multi_protocols[option].protocol);
//Protocol name
for(uint8_t i=0;i<proto_len;i++)
Serial_write(multi_protocols[option].ProtoString[i]);
//Flags
uint8_t flags=0;
#ifdef FAILSAFE_ENABLE
if(multi_protocols[option].failSafe)
flags |= 0x01; //Failsafe supported
#endif
if(multi_protocols[option].chMap)
flags |= 0x02; //Disable_ch_mapping supported
Serial_write( flags | (multi_protocols[option].optionType<<4)); // flags && option type
//Number of sub protocols
Serial_write(nbr_sub);
if(nbr_sub !=0 )
{//Sub protocols length and texts
for(uint8_t i=0;i<=nbr_sub*sub_len;i++)
Serial_write(multi_protocols[option].SubProtoString[i]);
}
}
}
return 1000;
}
#endif

View File

@@ -18,8 +18,8 @@
//******************
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_REVISION 2
#define VERSION_PATCH_LEVEL 61
#define VERSION_REVISION 3
#define VERSION_PATCH_LEVEL 0
#define MODE_SERIAL 0
@@ -28,7 +28,7 @@
//******************
enum PROTOCOLS
{
PROTO_CONFIG = 0, // Module config
PROTO_PROTOLIST = 0, // NO RF
PROTO_FLYSKY = 1, // =>A7105
PROTO_HUBSAN = 2, // =>A7105
PROTO_FRSKYD = 3, // =>CC2500
@@ -112,6 +112,13 @@ enum PROTOCOLS
PROTO_LOLI = 82, // =>NRF24L01
PROTO_E129 = 83, // =>CYRF6936
PROTO_JOYSWAY = 84, // =>A7105
PROTO_E016H = 85, // =>NRF24L01
PROTO_CONFIG = 86, // Module config
PROTO_IKEAANSLUTA = 87, // =>CC2500
PROTO_WILLIFM = 88, // 27/35ab/40/41/72 MHz module external project
PROTO_LOSI = 89, // =>CYRF6936
PROTO_MOULDKG = 90, // =>NRF24L01
PROTO_XERALL = 91, // =>NRF24L01
PROTO_NANORF = 126, // =>NRF24L01
PROTO_TEST = 127, // =>CC2500
@@ -143,6 +150,8 @@ enum AFHDS2A
PPM_SBUS = 3,
PWM_IB16 = 4,
PPM_IB16 = 5,
PWM_SB16 = 6,
PPM_SB16 = 7,
};
enum Hisky
{
@@ -151,11 +160,12 @@ enum Hisky
};
enum DSM
{
DSM2_1F = 0,
DSM2_2F = 1,
DSMX_1F = 2,
DSMX_2F = 3,
DSM_AUTO = 4,
DSM2_1F = 0,
DSM2_2F = 1,
DSMX_1F = 2,
DSMX_2F = 3,
DSM_AUTO = 4,
DSMR = 5,
};
enum YD717
{
@@ -224,6 +234,7 @@ enum MT99XX
FY805 = 4,
A180 = 5,
DRAGON = 6,
F949G = 7,
};
enum MJXQ
{
@@ -355,6 +366,8 @@ enum XN297DUMP
XN297DUMP_1M = 1,
XN297DUMP_2M = 2,
XN297DUMP_AUTO = 3,
XN297DUMP_NRF = 4,
XN297DUMP_CC2500 = 5,
};
enum FRSKY_R9
{
@@ -397,6 +410,7 @@ enum PELIKAN
{
PELIKAN_PRO = 0,
PELIKAN_LITE= 1,
PELIKAN_SCX24=2,
};
enum V761
@@ -430,6 +444,18 @@ enum RLINK
RLINK_DUMBORC = 2,
};
enum MOULDKG
{
MOULDKG_ANALOG = 0,
MOULDKG_DIGIT = 1,
};
enum KF606
{
KF606_KF606 = 0,
KF606_MIG320 = 1,
};
#define NONE 0
#define P_HIGH 1
#define P_LOW 0
@@ -453,7 +479,7 @@ typedef uint16_t (*uint16_function_t) (void); //pointer to a function with no pa
typedef void (*void_function_t ) (void); //pointer to a function with no parameters which returns nothing
//Protocols definition
struct mm_protocol_definition {
struct __attribute__((__packed__)) mm_protocol_definition {
uint8_t protocol;
const char *ProtoString;
const char *SubProtoString;
@@ -494,6 +520,7 @@ enum MultiPacketTypes
MULTI_TELEMETRY_HOTT = 14,
MULTI_TELEMETRY_MLINK = 15,
MULTI_TELEMETRY_CONFIG = 16,
MULTI_TELEMETRY_PROTO = 17,
};
// Macros
@@ -587,6 +614,11 @@ enum MultiPacketTypes
#define DISABLE_TELEM_on protocol_flags3 |= _BV(3)
#define IS_DISABLE_TELEM_on ( ( protocol_flags3 & _BV(3) ) !=0 )
#define IS_DISABLE_TELEM_off ( ( protocol_flags3 & _BV(3) ) ==0 )
//Valid/invalid sub_proto
#define SUB_PROTO_VALID protocol_flags3 &= ~_BV(6)
#define SUB_PROTO_INVALID protocol_flags3 |= _BV(6)
#define IS_SUB_PROTO_INVALID ( ( protocol_flags3 & _BV(6) ) !=0 )
#define IS_SUB_PROTO_VALID ( ( protocol_flags3 & _BV(6) ) ==0 )
//LBT power
#define LBT_POWER_off protocol_flags3 &= ~_BV(7)
#define LBT_POWER_on protocol_flags3 |= _BV(7)
@@ -763,6 +795,8 @@ enum {
#define SPEED_125K 3
/** EEPROM Layout */
#define EEPROM_CID_INIT_OFFSET 0 // 1 byte flag that Cyrf ID is initialized
#define EEPROM_CID_OFFSET 1 // 6 bytes Cyrf ID
#define EEPROM_ID_OFFSET 10 // Module ID (4 bytes)
#define EEPROM_BANK_OFFSET 15 // Current bank number (1 byte)
#define EEPROM_ID_VALID_OFFSET 20 // 1 byte flag that ID is valid
@@ -779,7 +813,8 @@ enum {
#define FRSKYX_CLONE_EEPROM_OFFSET 822 // (1) format + (3) TX ID + (47) channels, 51 bytes, end is 873
#define FRSKYX2_CLONE_EEPROM_OFFSET 873 // (1) format + (3) TX ID, 4 bytes, end is 877
#define DSM_RX_EEPROM_OFFSET 877 // (4) TX ID + format, 5 bytes, end is 882
//#define CONFIG_EEPROM_OFFSET 882 // Current configuration of the multimodule
#define MOULDKG_EEPROM_OFFSET 882 // RX ID, 3 bytes per model, end is 882+64*3=1074
//#define CONFIG_EEPROM_OFFSET 1074 // Current configuration of the multimodule
/* STM32 Flash Size */
#ifndef DISABLE_FLASH_SIZE_CHECK
@@ -890,6 +925,9 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
E010R5 81
LOLI 82
E129 83
JOYSWAY 84
E016H 85
XERALL 91
BindBit=> 0x80 1=Bind/0=No
AutoBindBit=> 0x40 1=Yes /0=No
RangeCheck=> 0x20 1=Yes /0=No
@@ -1035,7 +1073,6 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
sub_protocol==E01X
E012 0
E015 1
E016H 2
sub_protocol==GD00X
GD_V1 0
GD_V2 1
@@ -1077,6 +1114,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
sub_protocol==PELIKAN
PELIKAN_PRO 0
PELIKAN_LITE 1
PELIKAN_SCX24 2
sub_protocol==V761
V761_3CH 0
V761_4CH 1
@@ -1251,4 +1289,21 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
data[1] = TX_LQI
data[2] = telem_type
data[3-9] = data
Type 0x10 Config telemetry
length: 22
data[0..21] = Config data
Type 0x11 Protocol list export via telemetry. Used by the protocol PROTO_PROTOLIST=0, the list entry is given by the Option field.
length: variable
data[0] = protocol number, 0xFF is an invalid list entry (Option value too large), Option == 0xFF -> number of protocols in the list
data[1..n] = protocol name null terminated
data[n+1] = flags
flags>>4 Option text number to be displayed (check multi status for description)
flags&0x01 failsafe supported
flags&0x02 Channel Map Disabled supported
data[n+2] = number of sub protocols
data[n+3] = sub protocols text length, only sent if nbr_sub != 0
data[n+4..] = sub protocol names, only sent if nbr_sub != 0
*/

View File

@@ -158,6 +158,7 @@ uint8_t CH_EATR[]={ELEVATOR, AILERON, THROTTLE, RUDDER, CH5, CH6, CH7, CH8, CH9,
// Mode_select variables
uint8_t mode_select;
uint8_t protocol_flags=0,protocol_flags2=0,protocol_flags3=0;
uint8_t option_override;
#ifdef ENABLE_PPM
// PPM variable
@@ -764,6 +765,17 @@ void End_Bind()
bind_counter=2;
}
void Update_Telem()
{
#if defined(TELEMETRY)
#ifndef MULTI_TELEMETRY
if((protocol == PROTO_BAYANG_RX) || (protocol == PROTO_AFHDS2A_RX) || (protocol == PROTO_FRSKY_RX) || (protocol == PROTO_SCANNER) || (protocol==PROTO_FRSKYD) || (protocol==PROTO_BAYANG) || (protocol==PROTO_NCC1701) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_FRSKYX) || (protocol==PROTO_FRSKYX2) || (protocol==PROTO_DSM) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_HOTT) || (protocol==PROTO_PROPEL) || (protocol==PROTO_OMP) || (protocol==PROTO_DEVO) || (protocol==PROTO_DSM_RX) || (protocol==PROTO_FRSKY_R9) || (protocol==PROTO_RLINK) || (protocol==PROTO_WFLY2) || (protocol==PROTO_LOLI) || (protocol==PROTO_MLINK) || (protocol==PROTO_MT99XX))
#endif
if(IS_DISABLE_TELEM_off)
TelemetryUpdate();
#endif
}
bool Update_All()
{
#ifdef ENABLE_SERIAL
@@ -854,13 +866,9 @@ bool Update_All()
}
else
#endif
#if defined(TELEMETRY)
#ifndef MULTI_TELEMETRY
if((protocol == PROTO_BAYANG_RX) || (protocol == PROTO_AFHDS2A_RX) || (protocol == PROTO_FRSKY_RX) || (protocol == PROTO_SCANNER) || (protocol==PROTO_FRSKYD) || (protocol==PROTO_BAYANG) || (protocol==PROTO_NCC1701) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_FRSKYX) || (protocol==PROTO_FRSKYX2) || (protocol==PROTO_DSM) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_HOTT) || (protocol==PROTO_PROPEL) || (protocol==PROTO_OMP) || (protocol==PROTO_DEVO) || (protocol==PROTO_DSM_RX) || (protocol==PROTO_FRSKY_R9) || (protocol==PROTO_RLINK) || (protocol==PROTO_WFLY2) || (protocol==PROTO_LOLI) || (protocol==PROTO_MLINK))
#endif
if(IS_DISABLE_TELEM_off)
TelemetryUpdate();
#endif
Update_Telem();
#ifdef ENABLE_BIND_CH
if(IS_AUTOBIND_FLAG_on && IS_BIND_CH_PREV_off && Channel_data[BIND_CH-1]>CHANNEL_MAX_COMMAND)
{ // Autobind is on and BIND_CH went up
@@ -1127,17 +1135,16 @@ static void protocol_init()
{
remote_callback = 0; // No protocol
LED_off; // Led off during protocol init
modules_reset(); // Reset all modules
crc16_polynomial = 0x1021; // Default CRC crc16_polynomial
crc8_polynomial = 0x31; // Default CRC crc8_polynomial
prev_option = option;
multi_protocols_index = 0xFF;
// reset telemetry
#ifdef TELEMETRY
#ifdef MULTI_SYNC
inputRefreshRate = 0; // Don't do it unless the protocol asks for it
#endif
multi_protocols_index = 0xFF;
tx_pause();
init_frskyd_link_telemetry();
pps_timer=millis();
@@ -1159,7 +1166,7 @@ static void protocol_init()
TX_RX_PAUSE_off;
TX_MAIN_PAUSE_off;
tx_resume();
#if defined(AFHDS2A_RX_A7105_INO) || defined(FRSKY_RX_CC2500_INO) || defined(BAYANG_RX_NRF24L01_INO)
#if defined(AFHDS2A_RX_A7105_INO) || defined(FRSKY_RX_CC2500_INO) || defined(BAYANG_RX_NRF24L01_INO) || defined(DSM_RX_CYRF6936_INO)
for(uint8_t ch=0; ch<16; ch++)
rx_rc_chan[ch] = 1024;
#endif
@@ -1179,50 +1186,72 @@ static void protocol_init()
FAILSAFE_VALUES_off;
#endif
DATA_BUFFER_LOW_off;
SUB_PROTO_INVALID;
option_override = 0xFF;
blink=millis();
debugln("Protocol selected: %d, sub proto %d, rxnum %d, option %d", protocol, sub_protocol, RX_num, option);
uint8_t index=0;
#if defined(FRSKYX_CC2500_INO) && defined(EU_MODULE)
if( ! ( (protocol == PROTO_FRSKYX || protocol == PROTO_FRSKYX2) && sub_protocol < 2 ) )
#endif
while(multi_protocols[index].protocol != 0)
if(protocol)
{
if(multi_protocols[index].protocol==protocol)
//Reset all modules
modules_reset();
uint8_t index=0;
#if defined(FRSKYX_CC2500_INO) && defined(EU_MODULE)
if( ! ( (protocol == PROTO_FRSKYX || protocol == PROTO_FRSKYX2) && sub_protocol < 2 ) )
#endif
while(multi_protocols[index].protocol != 0xFF)
{
//Save index
multi_protocols_index = index;
//Set the RF switch
rf_switch(multi_protocols[multi_protocols_index].rfSwitch);
//Init protocol
multi_protocols[multi_protocols_index].Init();
//Save call back function address
remote_callback = multi_protocols[multi_protocols_index].CallBack;
//Send a telemetry status right now
SEND_MULTI_STATUS_on;
#ifdef DEBUG_SERIAL
debug("Proto=%s",multi_protocols[multi_protocols_index].ProtoString);
uint8_t nbr=multi_protocols[multi_protocols_index].nbrSubProto;
debug(", nbr_sub=%d, Sub=",nbr);
if(nbr && (sub_protocol&0x07)<nbr)
{
uint8_t len=multi_protocols[multi_protocols_index].SubProtoString[0];
uint8_t offset=len*(sub_protocol&0x07)+1;
for(uint8_t j=0;j<len;j++)
debug("%c",multi_protocols[multi_protocols_index].SubProtoString[j+offset]);
if(multi_protocols[index].protocol==protocol)
{
//Save index
multi_protocols_index = index;
//Check sub protocol validity
if( ((sub_protocol&0x07) == 0) || (sub_protocol&0x07) < multi_protocols[index].nbrSubProto )
SUB_PROTO_VALID;
if(IS_SUB_PROTO_VALID)
{//Start the protocol
//Set the RF switch
rf_switch(multi_protocols[index].rfSwitch);
//Init protocol
multi_protocols[index].Init(); // Init could invalidate the sub proto in case it is not suuported
if(IS_SUB_PROTO_VALID)
remote_callback = multi_protocols[index].CallBack; //Save call back function address
}
debug(", Opt=%d",multi_protocols[multi_protocols_index].optionType);
debug(", FS=%d",multi_protocols[multi_protocols_index].failSafe);
debug(", CHMap=%d",multi_protocols[multi_protocols_index].chMap);
debugln(", rfSw=%d",multi_protocols[multi_protocols_index].rfSwitch);
#endif
break;
#ifdef DEBUG_SERIAL
debug("Proto=%s", multi_protocols[index].ProtoString);
debug(", nbr_sub=%d, Sub=", multi_protocols[index].nbrSubProto);
if(IS_SUB_PROTO_VALID)
{
uint8_t len=multi_protocols[index].SubProtoString[0];
uint8_t offset=len*(sub_protocol&0x07)+1;
for(uint8_t j=0;j<len;j++)
debug("%c",multi_protocols[index].SubProtoString[j+offset]);
}
debug(", Opt=%d",multi_protocols[index].optionType);
debug(", FS=%d",multi_protocols[index].failSafe);
debug(", CHMap=%d",multi_protocols[index].chMap);
debugln(", rfSw=%d",multi_protocols[index].rfSwitch);
#endif
break;
}
index++;
}
index++;
//Send a telemetry status right now
SEND_MULTI_STATUS_on;
Update_Telem();
}
#ifdef MULTI_TELEMETRY
else
{//protocol=PROTO_PROTOLIST=0
remote_callback = PROTOLIST_callback;
prev_option = option + 1;
}
#endif
}
#if defined(WAIT_FOR_BIND) && defined(ENABLE_BIND_CH)
if( IS_AUTOBIND_FLAG_on && IS_BIND_CH_PREV_off && (cur_protocol[1]&0x80)==0 && mode_select == MODE_SERIAL)
{ // Autobind is active but no bind requested by either BIND_CH or BIND. But do not wait if in PPM mode...
@@ -1233,16 +1262,19 @@ static void protocol_init()
WAIT_BIND_off;
CHANGE_PROTOCOL_FLAG_off;
//Wait 5ms after protocol init
cli(); // disable global int
OCR1A = TCNT1 + 5000*2; // set compare A for callback
#ifndef STM32_BOARD
TIFR1 = OCF1A_bm ; // clear compare A flag
#else
TIMER2_BASE->SR = 0x1E5F & ~TIMER_SR_CC1IF; // Clear Timer2/Comp1 interrupt flag
#endif
sei(); // enable global int
BIND_BUTTON_FLAG_off; // do not bind/reset id anymore even if protocol change
if(protocol)
{
//Wait 5ms after protocol init
cli(); // disable global int
OCR1A = TCNT1 + 5000*2; // set compare A for callback
#ifndef STM32_BOARD
TIFR1 = OCF1A_bm ; // clear compare A flag
#else
TIMER2_BASE->SR = 0x1E5F & ~TIMER_SR_CC1IF; // Clear Timer2/Comp1 interrupt flag
#endif
sei(); // enable global int
BIND_BUTTON_FLAG_off; // do not bind/reset id anymore even if protocol change
}
}
void update_serial_data()
@@ -1516,7 +1548,9 @@ void update_serial_data()
if ( used >= MAX_SPORT_BUFFER-(MAX_SPORT_BUFFER>>2) )
{
DATA_BUFFER_LOW_on;
SEND_MULTI_STATUS_on; //Send Multi Status ASAP to inform the TX
//Send Multi Status ASAP to inform the TX
SEND_MULTI_STATUS_on;
Update_Telem();
debugln("Low buf=%d,h=%d,t=%d",used,SportHead,SportTail);
}
}
@@ -1788,7 +1822,7 @@ void pollBoot()
#if defined(TELEMETRY)
void PPM_Telemetry_serial_init()
{
if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_BAYANG)|| (protocol==PROTO_NCC1701) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_PROPEL) || (protocol==PROTO_OMP) || (protocol==PROTO_RLINK) || (protocol==PROTO_WFLY2) || (protocol==PROTO_LOLI)
if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_BAYANG)|| (protocol==PROTO_NCC1701) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_PROPEL) || (protocol==PROTO_OMP) || (protocol==PROTO_RLINK) || (protocol==PROTO_WFLY2) || (protocol==PROTO_LOLI) || (protocol==PROTO_MT99XX)
#ifdef TELEMETRY_FRSKYX_TO_FRSKYD
|| (protocol==PROTO_FRSKYX) || (protocol==PROTO_FRSKYX2)
#endif
@@ -1827,7 +1861,7 @@ static uint32_t random_id(uint16_t address, uint8_t create_new)
}
if(id!=0x2AD141A7) //ID with seed=0
{
debugln("Read ID from EEPROM");
//debugln("Read ID from EEPROM");
return id;
}
}

View File

@@ -28,7 +28,6 @@ void NRF24L01_Initialize()
{
rf_setup = 0x09;
prev_power = 0x00; // Make sure prev_power is inline with current power
XN297_SetScrambledMode(XN297_SCRAMBLED);
//Load most likely default NRF config
NRF24L01_FlushTx();
@@ -196,11 +195,11 @@ void NRF24L01_SetPower()
void NRF24L01_SetTxRxMode(enum TXRX_State mode)
{
NRF24L01_WriteReg(NRF24L01_07_STATUS, (1 << NRF24L01_07_RX_DR) //reset the flag(s)
| (1 << NRF24L01_07_TX_DS)
| (1 << NRF24L01_07_MAX_RT));
if(mode == TX_EN) {
NRF_CE_off;
NRF24L01_WriteReg(NRF24L01_07_STATUS, (1 << NRF24L01_07_RX_DR) //reset the flag(s)
| (1 << NRF24L01_07_TX_DS)
| (1 << NRF24L01_07_MAX_RT));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_EN_CRC) // switch to TX mode
| (1 << NRF24L01_00_CRCO)
| (1 << NRF24L01_00_PWR_UP));
@@ -211,9 +210,6 @@ void NRF24L01_SetTxRxMode(enum TXRX_State mode)
if (mode == RX_EN)
{
NRF_CE_off;
NRF24L01_WriteReg(NRF24L01_07_STATUS, (1 << NRF24L01_07_RX_DR) //reset the flag(s)
| (1 << NRF24L01_07_TX_DS)
| (1 << NRF24L01_07_MAX_RT));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_EN_CRC) // switch to RX mode
| (1 << NRF24L01_00_CRCO)
| (1 << NRF24L01_00_PWR_UP)

View File

@@ -15,223 +15,16 @@
#if defined(CC2500_INSTALLED) || defined(NRF24L01_INSTALLED)
#include "iface_nrf250k.h"
#include "iface_xn297.h"
static void __attribute__((unused)) XN297L_Init()
{
//CC2500
#if defined(CC2500_INSTALLED)
debugln("Using CC2500");
xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
rf_switch(SW_CC2500);
CC2500_250K_Init();
#elif defined(NRF24L01_INSTALLED)
debugln("Using NRF");
rf_switch(SW_NRF);
NRF24L01_Initialize();
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
#endif
}
static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t* addr, uint8_t len)
{
#if defined(CC2500_INSTALLED)
if (len > 5) len = 5;
if (len < 3) len = 3;
xn297_addr_len = len;
memcpy(xn297_tx_addr, addr, len);
#elif defined(NRF24L01_INSTALLED)
XN297_SetTXAddr(addr,len);
#endif
}
static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t len)
{
#if defined(CC2500_INSTALLED)
uint8_t buf[32];
uint8_t last = 0;
uint8_t i;
// address
for (i = 0; i < xn297_addr_len; ++i)
{
buf[last] = xn297_tx_addr[xn297_addr_len - i - 1];
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[i];
last++;
}
// payload
for (i = 0; i < len; ++i) {
// bit-reverse bytes in packet
buf[last] = bit_reverse(msg[i]);
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[xn297_addr_len+i];
last++;
}
// crc
crc = 0xb5d2;
for (uint8_t i = 0; i < last; ++i)
crc16_update( buf[i], 8);
if(xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
else
crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]);
buf[last++] = crc >> 8;
buf[last++] = crc & 0xff;
// stop TX/RX
CC2500_Strobe(CC2500_SIDLE);
// flush tx FIFO
CC2500_Strobe(CC2500_SFTX);
// packet length
CC2500_WriteReg(CC2500_3F_TXFIFO, last + 3);
// xn297L preamble
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (uint8_t*)"\x71\x0f\x55", 3);
// xn297 packet
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last);
// transmit
CC2500_Strobe(CC2500_STX);
#elif defined(NRF24L01_INSTALLED)
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(msg, len);
#endif
}
static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
{
#if defined(CC2500_INSTALLED)
uint8_t buf[32];
uint8_t scramble_index=0;
uint8_t last = 0;
static uint8_t pid=0;
// address
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
buf[last] = xn297_tx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[scramble_index++];
last++;
}
// pcf
buf[last] = (len << 1) | (pid>>1);
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[scramble_index++];
last++;
buf[last] = (pid << 7) | (noack << 6);
// payload
buf[last]|= bit_reverse(msg[0]) >> 2; // first 6 bit of payload
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[scramble_index++];
for (uint8_t i = 0; i < len-1; ++i)
{
last++;
buf[last] = (bit_reverse(msg[i]) << 6) | (bit_reverse(msg[i+1]) >> 2);
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[scramble_index++];
}
last++;
buf[last] = bit_reverse(msg[len-1]) << 6; // last 2 bit of payload
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[scramble_index++] & 0xc0;
// crc
//if (xn297_crc)
{
crc = 0xb5d2;
for (uint8_t i = 0; i < last; ++i)
crc16_update( buf[i], 8);
crc16_update( buf[last] & 0xc0, 2);
if (xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
//else
// crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
buf[last++] |= (crc >> 8) >> 2;
buf[last++] = ((crc >> 8) << 6) | ((crc & 0xff) >> 2);
buf[last++] = (crc & 0xff) << 6;
}
pid++;
pid &= 3;
// stop TX/RX
CC2500_Strobe(CC2500_SIDLE);
// flush tx FIFO
CC2500_Strobe(CC2500_SFTX);
// packet length
CC2500_WriteReg(CC2500_3F_TXFIFO, last + 3);
// xn297L preamble
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (uint8_t*)"\x71\x0F\x55", 3);
// xn297 packet
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last);
// transmit
CC2500_Strobe(CC2500_STX);
#elif defined(NRF24L01_INSTALLED)
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WriteEnhancedPayload(msg, len, noack);
#endif
}
static void __attribute__((unused)) XN297L_HoppingCalib(uint8_t num_freq)
{ //calibrate hopping frequencies
#if defined(CC2500_INSTALLED)
CC2500_250K_HoppingCalib(num_freq);
#elif defined(NRF24L01_INSTALLED)
(void)num_freq;
#endif
}
static void __attribute__((unused)) XN297L_Hopping(uint8_t index)
{
#if defined(CC2500_INSTALLED)
CC2500_250K_Hopping(index);
#elif defined(NRF24L01_INSTALLED)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[index]);
#endif
}
static void __attribute__((unused)) XN297L_RFChannel(uint8_t number)
{ //change channel
#if defined(CC2500_INSTALLED)
CC2500_250K_RFChannel(number);
#elif defined(NRF24L01_INSTALLED)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, number);
#endif
}
static void __attribute__((unused)) XN297L_SetPower()
{
#if defined(CC2500_INSTALLED)
CC2500_SetPower();
#elif defined(NRF24L01_INSTALLED)
NRF24L01_SetPower();
#endif
}
static void __attribute__((unused)) XN297L_SetFreqOffset()
{ // Frequency offset
#if defined(CC2500_INSTALLED)
CC2500_SetFreqOffset();
#endif
}
uint8_t cc2500_nrf_tx_addr[5], cc2500_nrf_addr_len;
static void __attribute__((unused)) NRF250K_SetTXAddr(uint8_t* addr, uint8_t len)
{
if (len > 5) len = 5;
if (len < 3) len = 3;
#if defined(CC2500_INSTALLED)
CC2500_250K_NRF_SetTXAddr(addr, len);
cc2500_nrf_addr_len = len;
memcpy(cc2500_nrf_tx_addr, addr, len);
#elif defined(NRF24L01_INSTALLED)
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr, len);
@@ -241,20 +34,86 @@ static void __attribute__((unused)) NRF250K_SetTXAddr(uint8_t* addr, uint8_t len
static void __attribute__((unused)) NRF250K_WritePayload(uint8_t* msg, uint8_t len)
{
#if defined(CC2500_INSTALLED)
CC2500_250K_NRF_WritePayload(msg, len);
#if defined(ESKY150V2_CC2500_INO)
uint8_t buf[158];
#else
uint8_t buf[35];
#endif
uint8_t last = 0;
uint8_t i;
//nrf preamble
if(cc2500_nrf_tx_addr[cc2500_nrf_addr_len - 1] & 0x80)
buf[0]=0xAA;
else
buf[0]=0x55;
last++;
// address
for (i = 0; i < cc2500_nrf_addr_len; ++i)
buf[last++] = cc2500_nrf_tx_addr[cc2500_nrf_addr_len - i - 1];
// payload
for (i = 0; i < len; ++i)
buf[last++] = msg[i];
// crc
crc = 0xffff;
for (uint8_t i = 1; i < last; ++i)
crc16_update( buf[i], 8);
buf[last++] = crc >> 8;
buf[last++] = crc & 0xff;
buf[last++] = 0;
//for(uint8_t i=0;i<last;i++)
// debug("%02X ",buf[i]);
//debugln("");
// stop TX/RX
CC2500_Strobe(CC2500_SIDLE);
// flush tx FIFO
CC2500_Strobe(CC2500_SFTX);
// packet length
CC2500_WriteReg(CC2500_3F_TXFIFO, last);
// transmit nrf packet
uint8_t *buff=buf;
uint8_t status;
if(last>63)
{
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, 63);
CC2500_Strobe(CC2500_STX);
last-=63;
buff+=63;
while(last)
{//Loop until all the data is sent
do
{// Wait for the FIFO to become available
status=CC2500_ReadReg(CC2500_3A_TXBYTES | CC2500_READ_BURST);
}
while((status&0x7F)>31 && (status&0x80)==0);
if(last>31)
{//Send 31 bytes
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, 31);
last-=31;
buff+=31;
}
else
{//Send last bytes
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, last);
last=0;
}
}
}
else
{//Send packet
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, last);
CC2500_Strobe(CC2500_STX);
}
#elif defined(NRF24L01_INSTALLED)
NRF24L01_FlushTx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_MAX_RT));
NRF24L01_WritePayload(msg, len);
if(len<=32)
{
NRF24L01_FlushTx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_MAX_RT));
NRF24L01_WritePayload(msg, len);
}
#endif
}
static boolean __attribute__((unused)) NRF250K_IsPacketSent()
{
#if defined(CC2500_INSTALLED)
return true; // don't know on the CC2500 how to detect if the packet has been transmitted...
#elif defined(NRF24L01_INSTALLED)
return NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS);
#endif
}
#endif

View File

@@ -13,13 +13,9 @@ Multiprotocol is distributed in the hope that it will be useful,
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(OMP_CC2500_INO)
#if defined(OMP_CCNRF_INO)
#ifndef NRF24L01_INSTALLED
#undef OMP_HUB_TELEMETRY
#endif
#include "iface_nrf250k.h"
#include "iface_xn297.h"
//#define FORCE_OMP_ORIGINAL_ID
//#define OMP_TELEM_DEBUG
@@ -33,10 +29,6 @@ Multiprotocol is distributed in the hope that it will be useful,
static void __attribute__((unused)) OMP_send_packet()
{
#ifdef OMP_HUB_TELEMETRY
rf_switch(SW_CC2500);
#endif
if(IS_BIND_IN_PROGRESS)
{
memcpy(packet,"BND",3);
@@ -52,15 +44,12 @@ static void __attribute__((unused)) OMP_send_packet()
packet_sent++;
packet_sent %= OMP_RF_NUM_CHANNELS-1; // Change telem RX channels every time
if(packet_sent==0)
{
packet[0] |= 0x40; // |0x40 to request RX telemetry
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
}
#endif
//hopping frequency
packet[0 ] |= hopping_frequency_no;
XN297L_Hopping(hopping_frequency_no);
XN297_Hopping(hopping_frequency_no);
hopping_frequency_no++;
hopping_frequency_no &= OMP_RF_NUM_CHANNELS-1; // 8 RF channels
@@ -103,27 +92,22 @@ static void __attribute__((unused)) OMP_send_packet()
packet[15] = 0x04;
}
XN297L_SetPower(); // Set tx_power
XN297L_SetFreqOffset(); // Set frequency offset
XN297L_WriteEnhancedPayload(packet, OMP_PAYLOAD_SIZE, packet_sent!=0);
XN297_SetPower(); // Set tx_power
XN297_SetFreqOffset(); // Set frequency offset
XN297_SetTxRxMode(TX_EN);
XN297_WriteEnhancedPayload(packet, OMP_PAYLOAD_SIZE, packet_sent!=0);
}
static void __attribute__((unused)) OMP_RF_init()
{
//Config CC2500
XN297L_Init();
XN297L_SetTXAddr((uint8_t*)"FLPBD", 5);
XN297L_HoppingCalib(OMP_RF_NUM_CHANNELS); // Calibrate all channels
XN297L_RFChannel(OMP_RF_BIND_CHANNEL); // Set bind channel
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_250K);
XN297_SetTXAddr((uint8_t*)"FLPBD", 5);
XN297_HoppingCalib(OMP_RF_NUM_CHANNELS); // Calibrate all channels
XN297_RFChannel(OMP_RF_BIND_CHANNEL); // Set bind channel
#ifdef OMP_HUB_TELEMETRY
//Config NRF
NRF24L01_Initialize();
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
XN297_Configure(_BV(NRF24L01_00_EN_CRC));
XN297_SetRXAddr(rx_tx_addr, 5); // Set the RX address
NRF24L01_SetTxRxMode(TXRX_OFF); // Turn it off for now
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, OMP_PAYLOAD_SIZE + 4); // packet length +4 bytes of PCF+CRC
XN297_SetRXAddr(rx_tx_addr, OMP_PAYLOAD_SIZE);
#endif
}
@@ -167,6 +151,8 @@ enum {
uint16_t OMP_callback()
{
bool rx;
switch(phase)
{
case OMP_BIND:
@@ -176,12 +162,15 @@ uint16_t OMP_callback()
return OMP_PACKET_PERIOD;
case OMP_PREPDATA:
BIND_DONE;
XN297L_SetTXAddr(rx_tx_addr, 5);
XN297_SetTXAddr(rx_tx_addr, 5);
phase++; // OMP_DATA
case OMP_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(OMP_PACKET_PERIOD);
#endif
#ifdef OMP_HUB_TELEMETRY
rx = XN297_IsRX(); // Needed for the NRF24L01 since otherwise the bit gets cleared
#endif
OMP_send_packet();
#ifdef OMP_HUB_TELEMETRY
if(packet_sent == 0)
@@ -191,8 +180,11 @@ uint16_t OMP_callback()
}
else if(packet_sent == 1)
{
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
if( rx )
{ // a packet has been received
#ifdef OMP_TELEM_DEBUG
debug("RX :");
#endif
if(XN297_ReadEnhancedPayload(packet_in, OMP_PAYLOAD_SIZE) == OMP_PAYLOAD_SIZE)
{ // packet with good CRC and length
#ifdef OMP_TELEM_DEBUG
@@ -238,7 +230,7 @@ uint16_t OMP_callback()
debugln("");
#endif
}
NRF24L01_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(TXRX_OFF);
packet_count++;
if(packet_count>=100)
{//LQI calculation
@@ -254,21 +246,15 @@ uint16_t OMP_callback()
return OMP_PACKET_PERIOD;
#ifdef OMP_HUB_TELEMETRY
case OMP_RX:
NRF24L01_WriteReg(NRF24L01_07_STATUS, (1 << NRF24L01_07_RX_DR) //reset the flag(s)
| (1 << NRF24L01_07_TX_DS)
| (1 << NRF24L01_07_MAX_RT));
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_PWR_UP) | (1 << NRF24L01_00_PRIM_RX) ); // Start RX
{
uint16_t start=(uint16_t)micros();
while ((uint16_t)((uint16_t)micros()-(uint16_t)start) < 500)
{
if(CC2500_ReadReg(CC2500_35_MARCSTATE | CC2500_READ_BURST) != 0x13)
if(XN297_IsPacketSent())
break;
}
}
NRF_CE_on;
rf_switch(SW_NRF);
XN297_SetTxRxMode(RX_EN);
phase = OMP_DATA;
return OMP_PACKET_PERIOD-OMP_WRITE_TIME;
#endif

View File

@@ -13,7 +13,7 @@ Multiprotocol is distributed in the hope that it will be useful,
#if defined(POTENSIC_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
//#define FORCE_POTENSIC_ORIGINAL_ID
@@ -61,19 +61,20 @@ static void __attribute__((unused)) POTENSIC_send_packet()
}
POTENSIC_set_checksum();
packet[9] = hopping_frequency_no;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no&0x03]);
//RF channel
XN297_Hopping(hopping_frequency_no&0x03);
hopping_frequency_no++;
// Power on, TX mode, 2byte CRC
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, POTENSIC_PACKET_SIZE);
NRF24L01_SetPower();
}
static void __attribute__((unused)) POTENSIC_RF_init()
{
NRF24L01_Initialize();
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
if(IS_BIND_IN_PROGRESS)
XN297_SetTXAddr((uint8_t*)"\x01\x01\x01\x01\x06", 5); // Bind address

View File

@@ -20,91 +20,137 @@
//#define PELIKAN_FORCE_ID
//#define PELIKAN_LITE_FORCE_ID
#define PELIKAN_LITE_FORCE_HOP
#define PELIKAN_LITE_FORCE_HOP // hop sequence creation is unknown
//#define PELIKAN_SCX24_FORCE_ID
#define PELIKAN_SCX24_FORCE_HOP // hop sequence creation is unknown
#define PELIKAN_BIND_COUNT 400
#define PELIKAN_BIND_COUNT 400 // 3sec
#define PELIKAN_BIND_RF 0x3C
#define PELIKAN_NUM_RF_CHAN 0x1D
#define PELIKAN_PACKET_PERIOD 7980
#define PELIKAN_LITE_PACKET_PERIOD 18000
#define PELIKAN_SCX24_PACKET_PERIOD 15069
static void __attribute__((unused)) pelikan_build_packet()
{
static boolean upper=false;
packet[0] = 0x15;
uint8_t sum;
uint16_t channel;
if(sub_protocol == PELIKAN_SCX24)
packet[0] = 0x11;
else //PELIKAN_PRO & PELIKAN_LITE
packet[0] = 0x15;
if(IS_BIND_IN_PROGRESS)
{
packet[1] = 0x04; //version??
packet[2] = rx_tx_addr[0];
packet[3] = rx_tx_addr[1];
packet[4] = rx_tx_addr[2];
packet[5] = rx_tx_addr[3];
if(sub_protocol==PELIKAN_PRO)
packet[6] = 0x05; //sub version??
else //PELIKAN_LITE
packet[6] = 0x03; //sub version??
packet[7] = 0x00; //??
packet[8] = 0x55; //??
if(sub_protocol == PELIKAN_SCX24)
{
packet[1] = 0x65; //??
packet[6] = 0x55; //??
packet[7] = 0xAA; //??
}
else
{//PELIKAN_PRO & PELIKAN_LITE
packet[1] = 0x04; //version??
if(sub_protocol==PELIKAN_PRO)
packet[6] = 0x05; //sub version??
else //PELIKAN_LITE
packet[6] = 0x03; //sub version??
packet[7] = 0x00; //??
}
packet[8] = 0x55; //??
packet_length = 10;
}
else
{
//ID
packet[1] = rx_tx_addr[0];
packet[7] = rx_tx_addr[1];
packet[12] = rx_tx_addr[2];
packet[13] = rx_tx_addr[3];
//Channels
uint8_t offset=upper?4:0;
uint16_t channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871,false);
uint8_t top=(channel>>2) & 0xC0;
packet[2] = channel;
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871,false);
top|=(channel>>4) & 0x30;
packet[3] = channel;
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871,false);
top|=(channel>>6) & 0x0C;
packet[4] = channel;
channel=convert_channel_16b_nolimit(CH_AETR[offset], 153, 871,false);
top|=(channel>>8) & 0x03;
packet[5] = channel;
packet[6] = top;
//Check
crc8=0x15;
for(uint8_t i=1;i<8;i++)
crc8+=packet[i];
packet[8]=crc8;
//Low/Up channel flag
packet[9]=upper?0xAA:0x00;
upper=!upper;
//Hopping counters
if(sub_protocol==PELIKAN_LITE || ++packet_count>4)
if(sub_protocol == PELIKAN_SCX24)
{
packet_count=0;
if(++hopping_frequency_no>=PELIKAN_NUM_RF_CHAN)
hopping_frequency_no=0;
//ID
packet[4] = rx_tx_addr[1];
//Channels
channel = Channel_data[0]; //STEERING: 1B1..23B..2C5 ???
packet[2] = channel >> 9;
packet[3] = channel >> 1;
channel = Channel_data[1]; //THROTTLE: 0DB..1FF..30E
packet[5] = channel >> 9;
packet[6] = channel >> 1;
channel = Channel_data[2]; //CH3: 055..3AA
packet[7] = channel >> 9;
packet[8] = channel >> 1;
//Hopping counters
if(++packet_count>2)
{
packet_count=0;
if(++hopping_frequency_no>=PELIKAN_NUM_RF_CHAN)
hopping_frequency_no=0;
}
//Length
packet_length = 14;
}
packet[10]=hopping_frequency_no;
packet[11]=packet_count;
packet_length = 15;
else
{//PELIKAN_PRO & PELIKAN_LITE
//ID
packet[7] = rx_tx_addr[1];
//Channels
uint8_t offset=upper?4:0;
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871,false);
uint8_t top=(channel>>2) & 0xC0;
packet[2] = channel;
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871,false);
top|=(channel>>4) & 0x30;
packet[3] = channel;
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871,false);
top|=(channel>>6) & 0x0C;
packet[4] = channel;
channel=convert_channel_16b_nolimit(CH_AETR[offset], 153, 871,false);
top|=(channel>>8) & 0x03;
packet[5] = channel;
packet[6] = top;
//Check
sum=0x00;
for(uint8_t i=0;i<8;i++)
sum+=packet[i];
packet[8]=sum;
//Low/Up channel flag
packet[9]=upper?0xAA:0x00;
upper=!upper;
//Hopping counters
if(sub_protocol==PELIKAN_LITE || ++packet_count>4)
{
packet_count=0;
if(++hopping_frequency_no>=PELIKAN_NUM_RF_CHAN)
hopping_frequency_no=0;
}
//Length
packet_length = 15;
}
//Hopping
packet[packet_length-5] = hopping_frequency_no;
packet[packet_length-4] = packet_count;
//ID
packet[packet_length-3] = rx_tx_addr[2];
packet[packet_length-2] = rx_tx_addr[3];
}
//Check
crc8=0x15;
for(uint8_t i=1; i<packet_length-1 ;i++)
crc8+=packet[i];
packet[packet_length-1]=crc8;
sum=0x00;
for(uint8_t i=0; i<packet_length-1 ;i++)
sum+=packet[i];
packet[packet_length-1] = sum;
//Send
#ifdef DEBUG_SERIAL
if(packet[9]==0x00)
{
debug("C: %02X P(%d):",IS_BIND_IN_PROGRESS?PELIKAN_BIND_RF:hopping_frequency[hopping_frequency_no],packet_length);
for(uint8_t i=0;i<packet_length;i++)
debug(" %02X",packet[i]);
debugln("");
}
debug("C: %02X P(%d):",IS_BIND_IN_PROGRESS?PELIKAN_BIND_RF:hopping_frequency[hopping_frequency_no],packet_length);
for(uint8_t i=0;i<packet_length;i++)
debug(" %02X",packet[i]);
debugln("");
#endif
A7105_WriteData(packet_length, IS_BIND_IN_PROGRESS?PELIKAN_BIND_RF:hopping_frequency[hopping_frequency_no]);
A7105_SetPower();
@@ -125,17 +171,19 @@ uint16_t PELIKAN_callback()
BIND_DONE;
A7105_Strobe(A7105_STANDBY);
if(sub_protocol==PELIKAN_PRO)
A7105_WriteReg(A7105_03_FIFOI,0x28);
A7105_WriteReg(A7105_03_FIFOI,0x28); //????
else if(sub_protocol==PELIKAN_SCX24)
A7105_WriteReg(A7105_03_FIFOI,0x0D);
else//PELIKAN_LITE
A7105_WriteID(MProtocol_id);
}
}
#ifdef MULTI_SYNC
telemetry_set_input_sync(sub_protocol==PELIKAN_PRO?PELIKAN_PACKET_PERIOD:PELIKAN_LITE_PACKET_PERIOD);
telemetry_set_input_sync(packet_period);
#endif
pelikan_build_packet();
if(sub_protocol==PELIKAN_PRO || IS_BIND_IN_PROGRESS)
return PELIKAN_PACKET_PERIOD;
if(IS_BIND_IN_PROGRESS || sub_protocol != PELIKAN_LITE)
return packet_period;
//PELIKAN_LITE
phase++;
return 942;
@@ -241,6 +289,12 @@ const uint8_t PROGMEM pelikan_lite_hopp[][PELIKAN_NUM_RF_CHAN] = {
{ 0x46,0x2A,0x3E,0x5A,0x5C,0x24,0x4E,0x32,0x54,0x26,0x2C,0x34,0x56,0x1E,0x3A,0x3C,0x50,0x4A,0x2E,0x42,0x20,0x52,0x28,0x22,0x44,0x58,0x36,0x38,0x4C }
};
#endif
#ifdef PELIKAN_SCX24_FORCE_HOP
const uint8_t PROGMEM pelikan_scx24_hopp[][PELIKAN_NUM_RF_CHAN] = {
{ 0x1E,0x32,0x46,0x5A,0x44,0x58,0x2E,0x42,0x56,0x2C,0x40,0x54,0x2A,0x3E,0x52,0x28,0x3C,0x50,0x26,0x3A,0x4E,0x24,0x38,0x4C,0x22,0x36,0x4A,0x20,0x1A },
{ 0x2C,0x44,0x1E,0x52,0x56,0x22,0x3A,0x3E,0x34,0x4C,0x26,0x5A,0x50,0x2A,0x42,0x38,0x2E,0x46,0x20,0x54,0x4A,0x24,0x3C,0x32,0x28,0x40,0x58,0x1B,0x4E }
};
#endif
void PELIKAN_init()
{
@@ -248,12 +302,13 @@ void PELIKAN_init()
if(IS_BIND_IN_PROGRESS || sub_protocol==PELIKAN_LITE)
A7105_WriteReg(A7105_03_FIFOI,0x10);
pelikan_init_hop();
bind_counter = PELIKAN_BIND_COUNT;
//ID from dump
#if defined(PELIKAN_FORCE_ID)
if(sub_protocol==PELIKAN_PRO)
{
if(sub_protocol==PELIKAN_PRO)
{
pelikan_init_hop();
//ID from dump
#if defined(PELIKAN_FORCE_ID)
rx_tx_addr[0]=0x0D; // hopping freq
rx_tx_addr[1]=0xF4; // hopping freq
rx_tx_addr[2]=0x50; // ID
@@ -261,16 +316,14 @@ void PELIKAN_init()
// Fill frequency table
for(uint8_t i=0;i<PELIKAN_NUM_RF_CHAN;i++)
hopping_frequency[i]=pgm_read_byte_near(&pelikan_hopp[0][i]);
}
#endif
#if defined(PELIKAN_LITE_FORCE_ID) || defined(PELIKAN_LITE_FORCE_HOP)
#endif
packet_period = PELIKAN_PACKET_PERIOD;
}
else
{
bind_counter >>= 1;
if(sub_protocol==PELIKAN_LITE)
{
#if defined(PELIKAN_LITE_FORCE_ID)
// ID
rx_tx_addr[2]=0x60;
rx_tx_addr[3]=0x18;
#endif
#if defined(PELIKAN_LITE_FORCE_HOP)
// Hop frequency table
rx_tx_addr[0]=0x04; // hopping freq
@@ -278,15 +331,52 @@ void PELIKAN_init()
for(uint8_t i=0;i<PELIKAN_NUM_RF_CHAN;i++)
hopping_frequency[i]=pgm_read_byte_near(&pelikan_lite_hopp[0][i]);
#endif
#if defined(PELIKAN_LITE_FORCE_ID)
// ID
rx_tx_addr[2]=0x60;
rx_tx_addr[3]=0x18;
#endif
MProtocol_id = ((uint32_t)rx_tx_addr[0]<<24)|((uint32_t)rx_tx_addr[1]<<16)|((uint32_t)rx_tx_addr[2]<<8)|(rx_tx_addr[3]);
if(IS_BIND_DONE)
A7105_WriteID(MProtocol_id);
packet_period = PELIKAN_LITE_PACKET_PERIOD;
}
#endif
else// if(sub_protocol==PELIKAN_SCX24)
{
#if defined(PELIKAN_SCX24_FORCE_HOP)
// Hop frequency table
uint8_t num=rx_tx_addr[3] & 0x01;
if(num)
{//1
rx_tx_addr[0]=0x10; // hopping freq TX2
rx_tx_addr[1]=0x63; // hopping freq TX2
}
else
{//0
rx_tx_addr[0]=0x12; // hopping freq TX1
rx_tx_addr[1]=0x46; // hopping freq TX1
}
MProtocol_id=((uint32_t)rx_tx_addr[0]<<24)|((uint32_t)rx_tx_addr[1]<<16)|((uint32_t)rx_tx_addr[2]<<8)|(rx_tx_addr[3]);
if(sub_protocol==PELIKAN_LITE && IS_BIND_DONE)
A7105_WriteID(MProtocol_id);
for(uint8_t i=0;i<PELIKAN_NUM_RF_CHAN;i++)
hopping_frequency[i]=pgm_read_byte_near(&pelikan_scx24_hopp[num][i]);
#endif
#if defined(PELIKAN_SCX24_FORCE_ID)
// ID
rx_tx_addr[2]=0x80; // TX1
rx_tx_addr[3]=0x19; // TX1
rx_tx_addr[2]=0x80; // TX2
rx_tx_addr[3]=0x22; // TX2
#endif
A7105_WriteReg(A7105_0E_DATA_RATE,0x03);
if(IS_BIND_DONE)
A7105_WriteReg(A7105_03_FIFOI,0x0D);
packet_period = PELIKAN_SCX24_PACKET_PERIOD;
}
}
hopping_frequency_no=PELIKAN_NUM_RF_CHAN;
packet_count=5;
phase=0;
hopping_frequency_no = PELIKAN_NUM_RF_CHAN;
packet_count = 5;
phase = 0;
bind_counter = PELIKAN_BIND_COUNT;
}
#endif

View File

@@ -13,9 +13,9 @@
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(Q303_NRF24L01_INO)
#if defined(Q303_CCNRF_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
#define Q303_BIND_COUNT 1500
#define Q303_INITIAL_WAIT 500
@@ -185,6 +185,11 @@ static void __attribute__((unused)) Q303_send_packet()
}
else
{
//RF freq
XN297_Hopping(hopping_frequency_no++);
hopping_frequency_no %= rf_ch_num;
//Build packet
packet[0] = 0x55;
// sticks
switch(sub_protocol)
@@ -267,32 +272,27 @@ static void __attribute__((unused)) Q303_send_packet()
}
}
// Power on, TX mode, CRC enabled
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? Q303_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no++]);
hopping_frequency_no %= rf_ch_num;
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
// Send
XN297_SetPower();
XN297_SetFreqOffset();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, packet_length);
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) Q303_RF_init()
{
const uint8_t bind_address[] = {0xcc,0xcc,0xcc,0xcc,0xcc};
NRF24L01_Initialize();
if(sub_protocol==Q303)
{
XN297_SetScrambledMode(XN297_UNSCRAMBLED);
NRF24L01_SetBitrate(NRF24L01_BR_250K);
XN297_Configure(XN297_CRCEN, XN297_UNSCRAMBLED, XN297_250K);
XN297_HoppingCalib(rf_ch_num);
}
else
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr(bind_address, 5);
XN297_RFChannel(Q303_RF_BIND_CHANNEL);
}
static void __attribute__((unused)) Q303_initialize_txid()

View File

@@ -16,7 +16,7 @@ Multiprotocol is distributed in the hope that it will be useful,
#if defined(Q90C_CCNRF_INO)
#include "iface_nrf250k.h"
#include "iface_xn297.h"
//#define FORCE_Q90C_ORIGINAL_ID
@@ -51,7 +51,7 @@ static void __attribute__((unused)) Q90C_send_packet()
}
else
{
XN297L_Hopping(hopping_frequency_no++); // RF Freq
XN297_Hopping(hopping_frequency_no++); // RF Freq
hopping_frequency_no %= Q90C_RF_NUM_CHANNELS;
packet[0]= convert_channel_8b(THROTTLE); // 0..255
// A,E,R have weird scaling, 0x00-0xff range (unsigned) but center isn't 7f or 80
@@ -108,9 +108,11 @@ static void __attribute__((unused)) Q90C_send_packet()
packet[11] = sum ^ crc8;
}
XN297L_SetFreqOffset(); // Set frequency offset
XN297L_SetPower(); // Set tx_power
XN297L_WriteEnhancedPayload(packet, Q90C_PACKET_SIZE, 0);
// Send
XN297_SetFreqOffset(); // Set frequency offset
XN297_SetPower(); // Set tx_power
XN297_SetTxRxMode(TX_EN);
XN297_WriteEnhancedPayload(packet, Q90C_PACKET_SIZE, 0);
}
static void __attribute__((unused)) Q90C_initialize_txid()
@@ -133,13 +135,13 @@ static void __attribute__((unused)) Q90C_initialize_txid()
static void __attribute__((unused)) Q90C_RF_init()
{
XN297L_Init();
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_250K);
if(IS_BIND_IN_PROGRESS)
XN297L_SetTXAddr((uint8_t*)"\x4F\x43\x54\x81\x81", Q90C_ADDRESS_LENGTH);
XN297_SetTXAddr((uint8_t*)"\x4F\x43\x54\x81\x81", Q90C_ADDRESS_LENGTH);
else
XN297L_SetTXAddr(rx_tx_addr, Q90C_ADDRESS_LENGTH);
XN297L_HoppingCalib(Q90C_RF_NUM_CHANNELS); // Calibrate all channels
XN297L_RFChannel(Q90C_RF_BIND_CHANNEL); // Set bind channel
XN297_SetTXAddr(rx_tx_addr, Q90C_ADDRESS_LENGTH);
XN297_HoppingCalib(Q90C_RF_NUM_CHANNELS); // Calibrate all channels
XN297_RFChannel(Q90C_RF_BIND_CHANNEL); // Set bind channel
}
uint16_t Q90C_callback()
@@ -151,7 +153,7 @@ uint16_t Q90C_callback()
if(--bind_counter==0)
{
BIND_DONE;
XN297L_SetTXAddr(rx_tx_addr, Q90C_ADDRESS_LENGTH);
XN297_SetTXAddr(rx_tx_addr, Q90C_ADDRESS_LENGTH);
}
Q90C_send_packet();
return Q90C_PACKET_PERIOD;

View File

@@ -16,7 +16,7 @@ Multiprotocol is distributed in the hope that it will be useful,
#if defined(REALACC_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
#define FORCE_REALACC_ORIGINAL_ID
@@ -51,7 +51,7 @@ static void __attribute__((unused)) REALACC_send_packet()
| GET_FLAG(CH5_SW, 0x01) // Flip
| GET_FLAG(CH6_SW, 0x80); // Light
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency_no);
XN297_Hopping(hopping_frequency_no);
hopping_frequency_no++;
hopping_frequency_no %= REALACC_RF_NUM_CHANNELS;
XN297_WriteEnhancedPayload(packet, REALACC_PAYLOAD_SIZE,0);
@@ -88,10 +88,9 @@ static void __attribute__((unused)) REALACC_initialize_txid()
static void __attribute__((unused)) REALACC_RF_init()
{
NRF24L01_Initialize();
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr((uint8_t*)"MAIN", 4);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, REALACC_BIND_RF_CHANNEL); // Set bind channel
XN297_RFChannel(REALACC_BIND_RF_CHANNEL); // Set bind channel
}
uint16_t REALACC_callback()
@@ -99,10 +98,8 @@ uint16_t REALACC_callback()
#ifdef MULTI_SYNC
telemetry_set_input_sync(REALACC_PACKET_PERIOD);
#endif
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
NRF24L01_SetPower();
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
if(IS_BIND_IN_PROGRESS)
{
REALACC_send_bind_packet();

View File

@@ -158,6 +158,9 @@ static void __attribute__((unused)) RLINK_send_packet()
// header
if(packet_count>3)
packet[1] = 0x02; // 0x02 telemetry request flag
else
packet[1] = 0x00; // no telemetry
switch(sub_protocol)
{
case RLINK_SURFACE:
@@ -268,7 +271,7 @@ uint16_t RLINK_callback()
TX_RSSI -= 128;
else
TX_RSSI += 128;
RX_RSSI=packet_in[7]; //Should be packet_in[7]-256 but since it's an uint8_t...
RX_RSSI=packet_in[7]&0x7F; //Should be packet_in[7]-256 but since it's an uint8_t...
v_lipo1=packet_in[8]<<1; //RX Batt
v_lipo2=packet_in[9]; //Batt
telemetry_link=1; //Send telemetry out

View File

@@ -123,41 +123,32 @@ static void telemetry_set_input_sync(uint16_t refreshRate)
static void multi_send_status()
{
if(protocol == 0) return;
multi_send_header(MULTI_TELEMETRY_STATUS, 24);
// Build flags
uint8_t flags=0;
if (IS_INPUT_SIGNAL_on)
if(IS_INPUT_SIGNAL_on)
flags |= 0x01;
if (mode_select==MODE_SERIAL)
if(mode_select==MODE_SERIAL)
flags |= 0x02;
if (remote_callback != 0)
if(remote_callback != 0)
{
flags |= 0x04;
if(multi_protocols_index == 0xFF)
{
if(protocol!=PROTO_SCANNER)
flags &= ~0x04; //Invalid protocol
}
else if(sub_protocol&0x07)
{
uint8_t nbr=multi_protocols[multi_protocols_index].nbrSubProto;
//if(protocol==PROTO_DSM) nbr++; //Auto sub_protocol
if((sub_protocol&0x07)>=nbr)
flags &= ~0x04; //Invalid sub protocol
}
if (IS_WAIT_BIND_on)
if(multi_protocols_index != 0xFF && IS_SUB_PROTO_VALID)
flags |= 0x04; //Invalid protocol / sub protocol, can't make the distinction since there is no more flags...
if(IS_WAIT_BIND_on)
flags |= 0x10;
else
if (IS_BIND_IN_PROGRESS)
if(IS_BIND_IN_PROGRESS)
flags |= 0x08;
if(multi_protocols_index != 0xFF)
{
if(multi_protocols[multi_protocols_index].chMap)
flags |= 0x40; //Disable_ch_mapping supported
flags |= 0x40; //Disable_ch_mapping supported
#ifdef FAILSAFE_ENABLE
if(multi_protocols[multi_protocols_index].failSafe)
flags |= 0x20; //Failsafe supported
flags |= 0x20; //Failsafe supported
#endif
}
if(IS_DATA_BUFFER_LOW_on)
@@ -174,52 +165,55 @@ static void multi_send_status()
// Channel order
Serial_write(RUDDER<<6|THROTTLE<<4|ELEVATOR<<2|AILERON);
if(multi_protocols_index == 0xFF) // selection out of list... send first available protocol
if(multi_protocols_index == 0xFF) // selection out of list... send first available protocol
{
Serial_write(multi_protocols[0].protocol); // begining of list
Serial_write(multi_protocols[0].protocol); // begining of list
Serial_write(multi_protocols[0].protocol); // begining of list
Serial_write(multi_protocols[0].protocol); // begining of list
for(uint8_t i=0;i<16;i++)
Serial_write(0x00); // everything else is invalid
Serial_write(0x00); // everything else is invalid
}
else
{
// Protocol next/prev
if(multi_protocols[multi_protocols_index+1].protocol != 0)
if(multi_protocols[multi_protocols_index+1].protocol != 0xFF)
{
if(multi_protocols[multi_protocols_index+1].protocol == PROTO_SCANNER)
if(multi_protocols[multi_protocols_index+1].protocol == PROTO_SCANNER )//|| multi_protocols[multi_protocols_index+1].protocol == PROTO_CONFIG )
{// if next is scanner
if(multi_protocols[multi_protocols_index+2].protocol != 0)
if(multi_protocols[multi_protocols_index+2].protocol != 0xFF)
Serial_write(multi_protocols[multi_protocols_index+2].protocol); // skip to next protocol number
else
Serial_write(multi_protocols[multi_protocols_index].protocol); // or end of list
Serial_write(multi_protocols[multi_protocols_index].protocol); // or end of list
}
else
Serial_write(multi_protocols[multi_protocols_index+1].protocol); // next protocol number
Serial_write(multi_protocols[multi_protocols_index+1].protocol); // next protocol number
}
else
Serial_write(multi_protocols[multi_protocols_index].protocol); // end of list
if(multi_protocols_index>0)
Serial_write(multi_protocols[multi_protocols_index].protocol); // end of list
if(multi_protocols_index>0 && multi_protocols[multi_protocols_index-1].protocol != 0)
{
if(multi_protocols[multi_protocols_index-1].protocol==PROTO_SCANNER)
if(multi_protocols[multi_protocols_index-1].protocol == PROTO_SCANNER )//|| multi_protocols[multi_protocols_index-1].protocol == PROTO_CONFIG )
{// if prev is scanner
if(multi_protocols_index > 1)
Serial_write(multi_protocols[multi_protocols_index-2].protocol); // skip to prev protocol number
else
Serial_write(multi_protocols[multi_protocols_index].protocol); // begining of list
Serial_write(multi_protocols[multi_protocols_index].protocol); // begining of list
}
else
Serial_write(multi_protocols[multi_protocols_index-1].protocol); // prev protocol number
Serial_write(multi_protocols[multi_protocols_index-1].protocol); // prev protocol number
}
else
Serial_write(multi_protocols[multi_protocols_index].protocol); // begining of list
Serial_write(multi_protocols[multi_protocols_index].protocol); // begining of list
// Protocol
for(uint8_t i=0;i<7;i++)
Serial_write(multi_protocols[multi_protocols_index].ProtoString[i]); // protocol name
Serial_write(multi_protocols[multi_protocols_index].ProtoString[i]); // protocol name
// Sub-protocol
uint8_t nbr=multi_protocols[multi_protocols_index].nbrSubProto;
Serial_write(nbr | (multi_protocols[multi_protocols_index].optionType<<4)); // number of sub protocols && option type
if(option_override>0x0F)
Serial_write(nbr | (multi_protocols[multi_protocols_index].optionType<<4)); // number of sub protocols && option type
else
Serial_write(nbr | (option_override<<4)); // number of sub protocols && option_override type
uint8_t j=0;
if(nbr && (sub_protocol&0x07)<nbr)
if(IS_SUB_PROTO_VALID)
{
uint8_t len=multi_protocols[multi_protocols_index].SubProtoString[0];
uint8_t offset=len*(sub_protocol&0x07)+1;
@@ -234,8 +228,8 @@ static void multi_send_status()
#ifdef MULTI_CONFIG_INO
void CONFIG_frame()
{
multi_send_header(MULTI_TELEMETRY_CONFIG, packet_in[0]);
for (uint8_t i = 1; i <= packet_in[0]; i++) // config data
multi_send_header(MULTI_TELEMETRY_CONFIG, 21);
for (uint8_t i = 0; i < 21; i++) // Config data
Serial_write(packet_in[i]);
}
#endif
@@ -532,7 +526,7 @@ void frsky_link_frame()
telemetry_link |= 2 ; // Send hub if available
}
else
{//PROTO_HUBSAN, PROTO_AFHDS2A, PROTO_BAYANG, PROTO_NCC1701, PROTO_CABELL, PROTO_HITEC, PROTO_BUGS, PROTO_BUGSMINI, PROTO_FRSKYX, PROTO_FRSKYX2, PROTO_PROPEL, PROTO_DEVO, PROTO_RLINK, PROTO_OMP, PROTO_WFLY2, PROTO_LOLI, PROTO_MLINK
{//PROTO_HUBSAN, PROTO_AFHDS2A, PROTO_BAYANG, PROTO_NCC1701, PROTO_CABELL, PROTO_HITEC, PROTO_BUGS, PROTO_BUGSMINI, PROTO_FRSKYX, PROTO_FRSKYX2, PROTO_PROPEL, PROTO_DEVO, PROTO_RLINK, PROTO_OMP, PROTO_WFLY2, PROTO_LOLI, PROTO_MLINK, PROTO_MT99XX
frame[1] = v_lipo1;
frame[2] = v_lipo2;
frame[3] = RX_RSSI;

View File

@@ -16,7 +16,7 @@ Multiprotocol is distributed in the hope that it will be useful,
#if defined(TIGER_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
#define TIGER_FORCE_ID
@@ -66,7 +66,7 @@ static void __attribute__((unused)) TIGER_send_packet()
packet[TIGER_PAYLOAD_SIZE-1]=crc8;
//Hopping frequency
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no>>1]);
XN297_Hopping(hopping_frequency_no>>1);
hopping_frequency_no++;
if(IS_BIND_IN_PROGRESS)
{
@@ -79,22 +79,16 @@ static void __attribute__((unused)) TIGER_send_packet()
hopping_frequency_no=2*TIGER_BIND_RF_NUM_CHANNELS;
}
//Clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
//Send packet
//Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, TIGER_PAYLOAD_SIZE);
//Set tx_power
NRF24L01_SetPower();
}
static void __attribute__((unused)) TIGER_RF_init()
{
NRF24L01_Initialize();
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr((uint8_t *)"\x68\x94\xA6\xD5\xC3", 5);
// Power on, TX mode, 2byte CRC
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
}
static void __attribute__((unused)) TIGER_initialize_txid()

View File

@@ -15,7 +15,7 @@ Multiprotocol is distributed in the hope that it will be useful,
#if defined(V761_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
//#define V761_FORCE_ID
@@ -50,24 +50,32 @@ static void __attribute__((unused)) V761_set_checksum()
}
}
static void __attribute__((unused)) V761_send_packet()
{
static bool calib=false, prev_ch6=false;
if(phase != V761_DATA)
{
packet[0] = rx_tx_addr[0];
packet[1] = rx_tx_addr[1];
packet[2] = rx_tx_addr[2];
packet[3] = rx_tx_addr[3];
packet[3] = rx_tx_addr[3];
packet[4] = hopping_frequency[1];
packet[5] = hopping_frequency[2];
if(phase == V761_BIND2)
if(phase == V761_BIND2)
packet[6] = 0xf0; // ?
}
else
{
XN297_Hopping(hopping_frequency_no++);
if(hopping_frequency_no >= V761_RF_NUM_CHANNELS)
{
hopping_frequency_no = 0;
packet_count++;
if(packet_count >= 4)
packet_count = 0;
}
packet[0] = convert_channel_8b(THROTTLE); // Throttle
packet[2] = convert_channel_8b(ELEVATOR)>>1; // Elevator
@@ -82,8 +90,8 @@ static void __attribute__((unused)) V761_send_packet()
packet[3] = convert_channel_8b(RUDDER)>>1; // Rudder
}
packet[5] = (packet_count++ / 3)<<6;
packet[4] = (packet[5] == 0x40) ? 0x1a : 0x20; // ?
packet[5] = packet_count<<6; // 0X, 4X, 8X, CX
packet[4] = 0x20; // Trims 00..20..40, 0X->20 4X->TrAil 8X->TrEle CX->TrRud
if(CH5_SW) // Mode Expert Gyro off
flags = 0x0c;
@@ -105,28 +113,25 @@ static void __attribute__((unused)) V761_send_packet()
|GET_FLAG(CH8_SW, 0x08) // RTH activation
|GET_FLAG(CH9_SW, 0x10); // RTH on/off
if(sub_protocol==V761_3CH)
packet[6] |= 0x80; // unknown, set on original V761-1 dump but not on eachine dumps, keeping for compatibility
//packet counter
if(packet_count >= 12)
packet_count = 0;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]);
if(hopping_frequency_no >= V761_RF_NUM_CHANNELS)
hopping_frequency_no = 0;
packet[6] |= 0x80; // Unknown, set on original V761-1 dump but not on eachine dumps, keeping for compatibility
}
V761_set_checksum();
// Power on, TX mode, 2byte CRC
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
#if 0
debug("H:%02X P:",hopping_frequency_no);
for(uint8_t i=0;i<V761_PACKET_SIZE;i++)
debug(" %02X",packet[i]);
debugln("");
#endif
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, V761_PACKET_SIZE);
NRF24L01_SetPower();
}
static void __attribute__((unused)) V761_RF_init()
{
NRF24L01_Initialize();
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x02); // set address length (4 bytes)
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
}
static void __attribute__((unused)) V761_initialize_txid()
@@ -175,7 +180,7 @@ uint16_t V761_callback()
if(bind_counter)
bind_counter--;
packet_count ++;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, V761_BIND_FREQ);
XN297_RFChannel(V761_BIND_FREQ);
XN297_SetTXAddr((uint8_t*)"\x34\x43\x10\x10", 4);
V761_send_packet();
if(packet_count >= 20)
@@ -188,13 +193,14 @@ uint16_t V761_callback()
if(bind_counter)
bind_counter--;
packet_count ++;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[0]);
XN297_Hopping(0);
XN297_SetTXAddr(rx_tx_addr, 4);
V761_send_packet();
if(bind_counter == 0)
{
phase = V761_DATA;
packet_count = 0;
BIND_DONE;
phase = V761_DATA;
}
else if(packet_count >= 20)
{

View File

@@ -16,7 +16,7 @@
#if defined(V911S_CCNRF_INO)
#include "iface_nrf250k.h"
#include "iface_xn297.h"
//#define V911S_ORIGINAL_ID
@@ -30,7 +30,7 @@
// flags going to packet[1]
#define V911S_FLAG_EXPERT 0x04
#define E119_FLAG_EXPERT 0x08
#define E119_FLAG_EXPERT 0x08 //0x00 low, 0x08 high
#define E119_FLAG_CALIB 0x40
// flags going to packet[2]
#define V911S_FLAG_CALIB 0x01
@@ -58,7 +58,7 @@ static void __attribute__((unused)) V911S_send_packet()
}
if(rf_ch_num&2)
channel=7-channel;
XN297L_Hopping(channel);
XN297_Hopping(channel);
hopping_frequency_no++;
hopping_frequency_no&=7; // 8 RF channels
@@ -66,12 +66,12 @@ static void __attribute__((unused)) V911S_send_packet()
memset(packet+1, 0x00, V911S_PACKET_SIZE - 1);
if(sub_protocol==V911S_STD)
{
packet[ 1]=V911S_FLAG_EXPERT; // short press on left button
packet[ 1]=GET_FLAG(!CH6_SW,V911S_FLAG_EXPERT); // short press on left button
packet[ 2]=GET_FLAG(CH5_SW,V911S_FLAG_CALIB); // long press on right button
}
else
packet[ 1]=E119_FLAG_EXPERT // short press on left button
|GET_FLAG(CH5_SW,E119_FLAG_CALIB); // short press on right button
packet[ 1]=GET_FLAG(!CH6_SW,E119_FLAG_EXPERT) // short press on left button
|GET_FLAG( CH5_SW,E119_FLAG_CALIB); // short press on right button
//packet[3..6]=trims TAER signed
uint16_t ch=convert_channel_16b_limit(THROTTLE ,0,0x7FF);
@@ -102,23 +102,23 @@ static void __attribute__((unused)) V911S_send_packet()
}
if(sub_protocol==V911S_STD)
XN297L_WritePayload(packet, V911S_PACKET_SIZE);
XN297_WritePayload(packet, V911S_PACKET_SIZE);
else
XN297L_WriteEnhancedPayload(packet, V911S_PACKET_SIZE, IS_BIND_IN_PROGRESS?0:1);
XN297_WriteEnhancedPayload(packet, V911S_PACKET_SIZE, IS_BIND_IN_PROGRESS?0:1);
XN297L_SetPower(); // Set tx_power
XN297L_SetFreqOffset(); // Set frequency offset
XN297_SetPower(); // Set tx_power
XN297_SetFreqOffset(); // Set frequency offset
}
static void __attribute__((unused)) V911S_RF_init()
{
XN297L_Init();
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_250K);
if(sub_protocol==V911S_STD)
XN297L_SetTXAddr((uint8_t *)"KNBND",5); // V911S Bind address
XN297_SetTXAddr((uint8_t *)"KNBND",5); // V911S Bind address
else
XN297L_SetTXAddr((uint8_t *)"XPBND",5); // E119 Bind address
XN297L_HoppingCalib(V911S_NUM_RF_CHANNELS); // Calibrate all channels
XN297L_RFChannel(V911S_RF_BIND_CHANNEL); // Set bind channel
XN297_SetTXAddr((uint8_t *)"XPBND",5); // E119 Bind address
XN297_HoppingCalib(V911S_NUM_RF_CHANNELS); // Calibrate all channels
XN297_RFChannel(V911S_RF_BIND_CHANNEL); // Set bind channel
}
static void __attribute__((unused)) V911S_initialize_txid()
@@ -144,7 +144,7 @@ uint16_t V911S_callback()
if (bind_counter == 0)
{
BIND_DONE;
XN297L_SetTXAddr(rx_tx_addr, 5);
XN297_SetTXAddr(rx_tx_addr, 5);
packet_period=V911S_PACKET_PERIOD;
}
else if(bind_counter==100) // same as original TX...
@@ -193,7 +193,7 @@ void V911S_init(void)
}
else
{
XN297L_SetTXAddr(rx_tx_addr, 5);
XN297_SetTXAddr(rx_tx_addr, 5);
packet_period= V911S_PACKET_PERIOD;
}
hopping_frequency_no=0;

View File

@@ -236,8 +236,8 @@
#define CC2500_INSTALLED
#define NRF24L01_INSTALLED
#define SX1276_INSTALLED
#undef ENABLE_PPM
#undef SEND_CPPM
#undef ENABLE_PPM
#undef SEND_CPPM
#endif
//Make sure protocols are selected correctly
@@ -260,6 +260,7 @@
#undef E010R5_CYRF6936_INO
#undef E129_CYRF6936_INO
#undef J6PRO_CYRF6936_INO
#undef LOSI_CYRF6936_INO
#undef MLINK_CYRF6936_INO
#undef TRAXXAS_CYRF6936_INO
#undef WFLY_CYRF6936_INO
@@ -276,7 +277,7 @@
#undef FRSKY_RX_CC2500_INO
#undef HITEC_CC2500_INO
#undef HOTT_CC2500_INO
#undef OMP_CC2500_INO //CC2500 for control and NRF for telemetry
#undef IKEAANSLUTA_CC2500_INO
#undef REDPINE_CC2500_INO
#undef RLINK_CC2500_INO
#undef SCANNER_CC2500_INO
@@ -293,6 +294,7 @@
#undef CG023_NRF24L01_INO
#undef CX10_NRF24L01_INO
#undef DM002_NRF24L01_INO
#undef E016H_NRF24L01_INO
#undef E01X_NRF24L01_INO
#undef ESKY_NRF24L01_INO
#undef ESKY150_NRF24L01_INO
@@ -306,28 +308,36 @@
#undef JJRC345_NRF24L01_INO
#undef KN_NRF24L01_INO
#undef LOLI_NRF24L01_INO
#undef MJXQ_NRF24L01_INO
#undef MT99XX_NRF24L01_INO
#undef MOULDKG_NRF24L01_INO
#undef NCC1701_NRF24L01_INO
#undef POTENSIC_NRF24L01_INO
#undef PROPEL_NRF24L01_INO
#undef Q303_NRF24L01_INO
#undef REALACC_NRF24L01_INO
#undef SHENQI_NRF24L01_INO
#undef SYMAX_NRF24L01_INO
#undef TIGER_NRF24L01_INO
#undef V2X2_NRF24L01_INO
#undef V761_NRF24L01_INO
#undef XK_NRF24L01_INO
#undef XERALL_NRF24L01_INO
#undef YD717_NRF24L01_INO
#undef ZSX_NRF24L01_INO
#endif
#if not defined(CC2500_INSTALLED) && not defined(NRF24L01_INSTALLED)
#undef GD00X_CCNRF_INO
#undef KF606_CCNRF_INO
#undef MJXQ_CCNRF_INO
#undef MT99XX_CCNRF_INO
#undef OMP_CCNRF_INO
#undef Q303_CCNRF_INO
#undef Q90C_CCNRF_INO
#undef SLT_CCNRF_INO
#undef V911S_CCNRF_INO
#undef XK_CCNRF_INO
#endif
#if not defined(STM32_BOARD)
//RF2500 emulation does not work on atmega...
#undef E010R5_CYRF6936_INO
#undef E129_CYRF6936_INO
#endif
#if not defined(STM32_BOARD)
#undef SX1276_INSTALLED
@@ -376,8 +386,10 @@
#undef DSM_FWD_PGM
#undef WFLY2_HUB_TELEMETRY
#undef LOLI_HUB_TELEMETRY
#undef MT99XX_HUB_TELEMETRY
#undef MLINK_HUB_TELEMETRY
#undef MLINK_FW_TELEMETRY
#undef MULTI_CONFIG_INO
#else
#if not defined(SCANNER_CC2500_INO) || not defined(SCANNER_TELEMETRY)
#undef SCANNER_TELEMETRY
@@ -401,7 +413,7 @@
#if not defined(DEVO_CYRF6936_INO)
#undef DEVO_HUB_TELEMETRY
#endif
#if not defined(OMP_CC2500_INO)
#if not defined(OMP_CCNRF_INO)
#undef OMP_HUB_TELEMETRY
#endif
#if not defined(PROPEL_NRF24L01_INO)
@@ -454,11 +466,14 @@
#if not defined(LOLI_NRF24L01_INO)
#undef LOLI_HUB_TELEMETRY
#endif
#if not defined(MT99XX_CCNRF_INO)
#undef MT99XX_HUB_TELEMETRY
#endif
#if not defined(FRSKYD_CC2500_INO) && not defined(MLINK_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY)
//protocols using FRSKYD user frames
#undef HUB_TELEMETRY
#endif
#if not defined(HOTT_FW_TELEMETRY) && not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BUGS_HUB_TELEMETRY) && not defined(NCC1701_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(RLINK_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS) && not defined(HITEC_HUB_TELEMETRY) && not defined(HITEC_FW_TELEMETRY) && not defined(SCANNER_TELEMETRY) && not defined(FRSKY_RX_TELEMETRY) && not defined(AFHDS2A_RX_TELEMETRY) && not defined(BAYANG_RX_TELEMETRY) && not defined(DEVO_HUB_TELEMETRY) && not defined(PROPEL_HUB_TELEMETRY) && not defined(OMP_HUB_TELEMETRY) && not defined(WFLY2_HUB_TELEMETRY) && not defined(LOLI_HUB_TELEMETRY) && not defined(MLINK_HUB_TELEMETRY) && not defined(MLINK_FW_TELEMETRY)
#if not defined(HOTT_FW_TELEMETRY) && not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BUGS_HUB_TELEMETRY) && not defined(NCC1701_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(RLINK_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS) && not defined(HITEC_HUB_TELEMETRY) && not defined(HITEC_FW_TELEMETRY) && not defined(SCANNER_TELEMETRY) && not defined(FRSKY_RX_TELEMETRY) && not defined(AFHDS2A_RX_TELEMETRY) && not defined(BAYANG_RX_TELEMETRY) && not defined(DEVO_HUB_TELEMETRY) && not defined(PROPEL_HUB_TELEMETRY) && not defined(OMP_HUB_TELEMETRY) && not defined(WFLY2_HUB_TELEMETRY) && not defined(LOLI_HUB_TELEMETRY) && not defined(MLINK_HUB_TELEMETRY) && not defined(MLINK_FW_TELEMETRY) && not defined(MT99XX_HUB_TELEMETRY) && not defined(MULTI_CONFIG_INO)
#undef TELEMETRY
#undef INVERT_TELEMETRY
#undef MULTI_TELEMETRY

View File

@@ -0,0 +1,283 @@
/*
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 XERALL
#if defined(XERALL_NRF24L01_INO)
#include "iface_xn297.h"
//#define XERALL_ORIGINAL_ID
#define XERALL_PACKET_PERIOD 2500 //2046
#define XERALL_PACKET_SIZE 10
#define XERALL_NUM_RF_CHANNELS 4
#define XERALL_BIND_COUNT 15000 //about 30sec
// flags going to packet[6]
#define XERALL_FLAG_VIDEO 0x80
#define XERALL_FLAG_PHOTO 0x40
// flags going to packet[7]
#define XERALL_FLAG_RATE 0x80
#define XERALL_FLAG_FLIGHT_GROUND 0x20
#define XERALL_FLAG_HEADING_HOLD 0x04
#define XERALL_FLAG_ONE_BUTTON 0x02
enum {
XERALL_DATA,
XERALL_RX,
XERALL_CHECK,
};
static void __attribute__((unused)) XERALL_send_packet()
{
if(bind_phase)
bind_phase--;
else
{ // Hopping frequency
if(packet_sent==0)
{
XN297_Hopping(hopping_frequency_no);
hopping_frequency_no++;
hopping_frequency_no &= (XERALL_NUM_RF_CHANNELS-1);
}
packet_sent++;
if(IS_BIND_IN_PROGRESS)
{
if(packet_sent > 24)
packet_sent=0; // Hopp after 25 packets
}
else
{
if(packet_sent > 18)
packet_sent = 0; // Hopp after 19 packets
}
// Packet
if(IS_BIND_IN_PROGRESS && (bind_counter&0x10)) // Alternate bind and normal packets
{ // Bind packet: 01 56 06 23 00 13 20 40 02 00 and 01 F9 58 31 00 13 20 40 05 00
if(packet[0] != 0x01)
{
XN297_SetTXAddr((uint8_t *)"\x01\x01\x01\x01\x09", 5); // Bind address
XN297_SetRXAddr((uint8_t *)"\x01\x01\x01\x01\x09", XERALL_PACKET_SIZE);
}
packet[0] = 0x01;
for(uint8_t i=0;i<5;i++)
packet[i+1] = rx_tx_addr[i];
packet[9] = 0;
}
else
{
if(packet[0] != 0x08)
{
XN297_SetTXAddr(rx_tx_addr, 5);
XN297_SetRXAddr(rx_tx_addr, XERALL_PACKET_SIZE);
}
// Normal packet: 08 32 7C 1C 20 20 20 40 0A 00
packet[0] = 0x08;
//Throttle
packet[1] = convert_channel_16b_limit(THROTTLE ,0,0x32)<<1; //00..64 but only even values
//Rudder
packet[2] = (0xFF-convert_channel_8b(RUDDER))&0xF8; //F8..00 -> 5 bits
//Elevator
uint8_t ch = convert_channel_8b(ELEVATOR)>>3;
packet[2] |= ch>>2; //00..07 -> 3 bits high
packet[3] = ch<<6; //00,40,80,C0 -> 2 bits low
//Aileron
packet[3] |= ((0xFF-convert_channel_8b(AILERON))>>3)<<1; //5 bits
//Trim Rudder 0x00..0x20..0x3F
packet[4] = convert_channel_8b(CH11)>>2;
//Trim Elevator 0x00..0x20..0x3F
packet[5] = convert_channel_8b(CH12)>>2;
}
}
// Flags + Trim Aileron
//packet[6]
// 0x20 -> 0x60 short press photo/video => |0x40 -> momentary
// 0x20 -> 0xA0 long press photo/video => |0x80 -> toggle
// 0xA0 -> 0xE0 short press photo/video => |0x40 -> momentary
// 0x20 -> 0x00..0x20..0x3F Trim Aileron
packet[6] = (convert_channel_8b(CH13)>>2)
| GET_FLAG(CH9_SW,XERALL_FLAG_PHOTO)
| GET_FLAG(CH10_SW,XERALL_FLAG_VIDEO);
// Flags
// 0x40 -> 0x44 Heading hold mode => |0x04 -> toggle
// 0x40 -> 0xC0 High/low speed => |0x80 -> toggle
// 0x40 -> 0x42 One button takeoff/landing/emergency => |0x02 -> toggle
// 0x40 -> 0x60 Flight/Ground => |0x20 -> toggle
packet[7] = 0x40
| GET_FLAG(CH5_SW,XERALL_FLAG_FLIGHT_GROUND)
| GET_FLAG(CH6_SW,XERALL_FLAG_ONE_BUTTON)
| GET_FLAG(CH7_SW,XERALL_FLAG_RATE)
| GET_FLAG(CH8_SW,XERALL_FLAG_HEADING_HOLD);
// CRC
uint8_t sum = 0;
for(uint8_t i=1;i<8;i++)
sum += packet[i];
packet[8] = sum & 0x0F;
//0x00 -> 0x1A on first telemetry packet received
//packet[9] = 0x00;
// Send
XN297_SetPower();
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(TX_EN);
XN297_WriteEnhancedPayload(packet, XERALL_PACKET_SIZE, 0);
#if 0
debug("H:%d,P:",hopping_frequency_no);
for(uint8_t i=0; i<XERALL_PACKET_SIZE; i++)
debug("%02X ", packet[i]);
debugln();
#endif
}
static void __attribute__((unused)) XERALL_RF_init()
{
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
}
static void __attribute__((unused)) XERALL_initialize_txid()
{
rx_tx_addr[0] = rx_tx_addr[3];
#ifdef XERALL_ORIGINAL_ID
// Pascal
if(RX_num)
{
rx_tx_addr[0]=0x56;
rx_tx_addr[1]=0x06;
rx_tx_addr[2]=0x23;
rx_tx_addr[3]=0x00;
rx_tx_addr[4]=0x13;
}
else
{
// Alfons
rx_tx_addr[0]=0xF9;
rx_tx_addr[1]=0x58;
rx_tx_addr[2]=0x31;
rx_tx_addr[3]=0x00;
rx_tx_addr[4]=0x13;
}
#endif
rx_tx_addr[3] = 0x00;
rx_tx_addr[4] = 0x13;
hopping_frequency[0] = 56; // 0x38
hopping_frequency[1] = 46; // 0x2E
hopping_frequency[2] = 61; // 0x3D
hopping_frequency[3] = 51; // 0x33
}
#define XERALL_WRITE_WAIT 600
#define XERALL_CHECK_WAIT 300
uint16_t XERALL_callback()
{
static uint8_t wait = 0;
switch(phase)
{
case XERALL_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(XERALL_PACKET_PERIOD);
#endif
if (bind_counter == 0)
BIND_DONE;
else
bind_counter--;
XERALL_send_packet();
phase++;
return XERALL_WRITE_WAIT;
case XERALL_RX:
// switch to RX mode
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
phase++;
return XERALL_PACKET_PERIOD-XERALL_WRITE_WAIT-XERALL_CHECK_WAIT;
case XERALL_CHECK:
if( XN297_IsRX() )
{ // RX fifo data ready
uint8_t len = XN297_ReadEnhancedPayload(packet_in, XERALL_PACKET_SIZE);
if(len != 255) // CRC OK
{
#if 0
debug("RX(%d):",len);
for(uint8_t i=0; i<len; i++)
debug("%02X ", packet_in[i]);
debugln();
#endif
if(len == XERALL_PACKET_SIZE && packet_in[0] == 0x11)
{ // Request for ack packet
// Ack the telem packet
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(TX_EN);
XN297_WriteEnhancedPayload(packet, 0, 0);
packet[9] = packet_in[9];
if(packet[0] == 0x01) // Last packet sent was a bind packet
{// Build bind response
packet[0] = 0x02;
for(uint8_t i=1; i<5; i++)
packet[i] = packet_in[i]; // Tank ID???
bind_phase = 14;
XN297_SetTXAddr(rx_tx_addr, 5);
}
wait = 0;
phase = XERALL_DATA;
break;
}
else if(len == XERALL_PACKET_SIZE && packet_in[0] == 0x12)
{
BIND_DONE;
bind_phase = 0;
wait = 0;
}
else if(len == 0)
wait = 5; // The quad wants to talk let's pause sending data...
}
if(wait)
{ // switch to RX mode
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
}
}
if(wait)
{
wait--;
break;
}
phase = XERALL_DATA;
return XERALL_CHECK_WAIT;
}
return XERALL_PACKET_PERIOD;
}
void XERALL_init(void)
{
XERALL_initialize_txid();
XERALL_RF_init();
if(IS_BIND_IN_PROGRESS)
bind_counter = XERALL_BIND_COUNT;
hopping_frequency_no=0;
packet_sent = 0;
bind_phase = 0;
memset(packet, 0, XERALL_PACKET_SIZE);
phase = XERALL_DATA;
}
#endif

View File

@@ -14,9 +14,9 @@ Multiprotocol is distributed in the hope that it will be useful,
*/
// Compatible with X450 and X420/X520 plane.
#if defined(XK_NRF24L01_INO)
#if defined(XK_CCNRF_INO)
#include "iface_nrf250k.h"
#include "iface_xn297.h"
//#define FORCE_XK_ORIGINAL_ID
@@ -29,15 +29,10 @@ Multiprotocol is distributed in the hope that it will be useful,
static uint16_t __attribute__((unused)) XK_convert_channel(uint8_t num)
{
uint16_t val;
if(num==RUDDER)
{// introduce deadband on rudder to prevent twitching
//debug("RUD:%d",val);
val=convert_channel_8b_limit_deadband(RUDDER,0x00,0x80, 0xFF, 40)<<2;
//debugln(",%d",val);
}
else
val=convert_channel_10b(num, false);
// Introduce deadband on all channels to prevent twitching
//debug("val:%d",val);
uint16_t val=convert_channel_8b_limit_deadband(num,0x00,0x80, 0xFF, 40)<<2;
//debugln(",%d",val);
// 1FF..01=left, 00=center, 200..3FF=right
if(val==0x200)
@@ -56,6 +51,13 @@ static uint16_t __attribute__((unused)) XK_convert_channel(uint8_t num)
static void __attribute__((unused)) XK_send_packet()
{
// RF channel
XN297_Hopping((IS_BIND_IN_PROGRESS?0:XK_RF_BIND_NUM_CHANNELS)+(hopping_frequency_no>>1));
hopping_frequency_no++;
if(hopping_frequency_no >= (IS_BIND_IN_PROGRESS?XK_RF_BIND_NUM_CHANNELS*2:XK_RF_NUM_CHANNELS*2))
hopping_frequency_no=0;
// Build packet
memset(packet,0x00,7);
memset(&packet[10],0x00,5);
@@ -101,32 +103,16 @@ static void __attribute__((unused)) XK_send_packet()
crc+=packet[i];
packet[15]=crc;
rf_ch_num = (IS_BIND_IN_PROGRESS?0:XK_RF_BIND_NUM_CHANNELS)+(hopping_frequency_no>>1);
hopping_frequency_no++;
if(hopping_frequency_no >= (IS_BIND_IN_PROGRESS?XK_RF_BIND_NUM_CHANNELS*2:XK_RF_NUM_CHANNELS*2))
hopping_frequency_no=0;
// debug("C: %02X, P:",hopping_frequency[rf_ch_num]);
// for(uint8_t i=0; i<XK_PAYLOAD_SIZE; i++)
// debug(" %02X",packet[i]);
// debugln("");
if(sub_protocol==X420)
{
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[rf_ch_num]);
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(packet, XK_PAYLOAD_SIZE);
NRF24L01_SetPower();
}
else
{
XN297L_Hopping(rf_ch_num);
XN297L_WritePayload(packet, XK_PAYLOAD_SIZE);
XN297L_SetPower(); // Set tx_power
XN297L_SetFreqOffset(); // Set frequency offset
}
// Send
XN297_SetPower(); // Set tx_power
XN297_SetTxRxMode(TX_EN);
XN297_SetFreqOffset(); // Set frequency offset
XN297_WritePayload(packet, XK_PAYLOAD_SIZE);
}
const uint8_t PROGMEM XK_bind_hop[XK_RF_BIND_NUM_CHANNELS]= { 0x07, 0x24, 0x3E, 0x2B, 0x47, 0x0E, 0x39, 0x1C }; // Bind
@@ -201,17 +187,9 @@ static void __attribute__((unused)) XK_initialize_txid()
static void __attribute__((unused)) XK_RF_init()
{
if(sub_protocol==X420)
{
NRF24L01_Initialize();
XN297_SetTXAddr((uint8_t*)"\x68\x94\xA6\xD5\xC3", 5); // Bind address
}
else
{
XN297L_Init();
XN297L_SetTXAddr((uint8_t*)"\x68\x94\xA6\xD5\xC3", 5); // Bind address
XN297L_HoppingCalib(XK_RF_BIND_NUM_CHANNELS+XK_RF_NUM_CHANNELS); // Calibrate all channels
}
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, sub_protocol==X420 ? XN297_1M : XN297_250K);
XN297_SetTXAddr((uint8_t*)"\x68\x94\xA6\xD5\xC3", 5); // Bind address
XN297_HoppingCalib(XK_RF_BIND_NUM_CHANNELS+XK_RF_NUM_CHANNELS); // Calibrate all channels
}
uint16_t XK_callback()
@@ -223,10 +201,7 @@ uint16_t XK_callback()
if(--bind_counter==0)
{
BIND_DONE;
if(sub_protocol==X420)
XN297_SetTXAddr(rx_tx_addr, 5); // Normal packets address
else
XN297L_SetTXAddr(rx_tx_addr, 5); // Normal packets address
XN297_SetTXAddr(rx_tx_addr, 5); // Normal packets address
}
XK_send_packet();
return XK_PACKET_PERIOD;
@@ -234,7 +209,7 @@ uint16_t XK_callback()
void XK_init()
{
BIND_IN_PROGRESS; // Autobind protocol
BIND_IN_PROGRESS; // Autobind protocol
XK_initialize_txid();
XK_RF_init();
hopping_frequency_no = 0;

View File

@@ -19,7 +19,7 @@
#ifdef XN297DUMP_NRF24L01_INO
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
// Parameters which can be modified
#define XN297DUMP_PERIOD_SCAN 50000 // 25000
@@ -66,6 +66,12 @@ static void __attribute__((unused)) XN297Dump_RF_init()
}
}
extern const uint8_t xn297_scramble[];
extern const uint16_t PROGMEM xn297_crc_xorout_scrambled[];
extern const uint16_t PROGMEM xn297_crc_xorout[];
extern const uint16_t PROGMEM xn297_crc_xorout_scrambled_enhanced[];
extern const uint16_t xn297_crc_xorout_enhanced[];
static boolean __attribute__((unused)) XN297Dump_process_packet(void)
{
uint16_t crcxored;
@@ -113,29 +119,34 @@ static boolean __attribute__((unused)) XN297Dump_process_packet(void)
}
//Try enhanced payload
crc = 0xb5d2;
uint16_t crc_save = 0xb5d2;
packet_length=0;
for (uint8_t i = 0; i < XN297DUMP_MAX_PACKET_LEN-XN297DUMP_CRC_LENGTH; i++)
for (uint8_t i = 0; i < XN297DUMP_MAX_PACKET_LEN-XN297DUMP_CRC_LENGTH; i++)
{
packet_sc[i]=packet[i]^xn297_scramble[i];
crc = crc_save;
crc16_update( packet[i], 8);
crc_save = crc;
crc16_update( packet[i+1] & 0xC0, 2);
crcxored=(packet[i+1]<<10)|(packet[i+2]<<2)|(packet[i+3]>>6) ;
if((crc ^ pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[i - 3])) == crcxored)
{ // Found a valid CRC for the enhanced payload mode
packet_length=i;
scramble=true;
i++;
packet_sc[i]=packet[i]^xn297_scramble[i];
memcpy(packet_un,packet_sc,packet_length+2); // unscramble packet
break;
}
if((crc ^ pgm_read_word(&xn297_crc_xorout_enhanced[i - 3])) == crcxored)
{ // Found a valid CRC for the enhanced payload mode
packet_length=i;
scramble=false;
memcpy(packet_un,packet,packet_length+2); // packet is unscrambled
break;
if(i>=3)
{
if((crc ^ pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[i - 3])) == crcxored)
{ // Found a valid CRC for the enhanced payload mode
packet_length=i;
scramble=true;
i++;
packet_sc[i]=packet[i]^xn297_scramble[i];
memcpy(packet_un,packet_sc,packet_length+2); // unscramble packet
break;
}
if((crc ^ pgm_read_word(&xn297_crc_xorout_enhanced[i - 3])) == crcxored)
{ // Found a valid CRC for the enhanced payload mode
packet_length=i;
scramble=false;
memcpy(packet_un,packet,packet_length+2); // packet is unscrambled
break;
}
}
}
if(packet_length!=0)
@@ -318,15 +329,16 @@ static uint16_t XN297Dump_callback()
switch(bitrate)
{
case XN297DUMP_250K:
NRF24L01_SetBitrate(NRF24L01_BR_250K);
XN297_Configure(XN297_CRCEN, scramble?XN297_SCRAMBLED:XN297_UNSCRAMBLED, XN297_250K, true);
debug("250K");
break;
case XN297DUMP_2M:
XN297_Configure(XN297_CRCEN, scramble?XN297_SCRAMBLED:XN297_UNSCRAMBLED, XN297_1M);
NRF24L01_SetBitrate(NRF24L01_BR_2M);
debug("2M");
break;
default:
NRF24L01_SetBitrate(NRF24L01_BR_1M);
XN297_Configure(XN297_CRCEN, scramble?XN297_SCRAMBLED:XN297_UNSCRAMBLED, XN297_1M);
debug("1M");
break;
@@ -358,20 +370,12 @@ static uint16_t XN297Dump_callback()
rf_ch_num=0;
packet_count=0;
debug("Trying RF channel: 0");
NRF24L01_Initialize();
XN297_SetScrambledMode(scramble?XN297_SCRAMBLED:XN297_UNSCRAMBLED);
XN297_SetTXAddr(rx_tx_addr,address_length);
XN297_SetRXAddr(rx_tx_addr,address_length);
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, packet_length + 2 + (enhanced?2:0) ); // 2 extra bytes for xn297 crc
NRF24L01_WriteReg(NRF24L01_05_RF_CH,0);
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();
NRF24L01_SetTxRxMode(RX_EN);
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
XN297_SetRXAddr(rx_tx_addr,packet_length);
XN297_RFChannel(0);
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
}
}
}
@@ -404,7 +408,7 @@ static uint16_t XN297Dump_callback()
bind_counter=0;
debugln("Time between CH:%d and CH:%d",hopping_frequency[0],hopping_frequency[hopping_frequency_no]);
time_rf[hopping_frequency_no]=0xFFFFFFFF;
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency[0]);
XN297_RFChannel(hopping_frequency[0]);
uint16_t timeL=TCNT1;
if(TIMER2_BASE->SR & TIMER_SR_UIF)
{//timer just rolled over...
@@ -412,33 +416,27 @@ static uint16_t XN297Dump_callback()
timeL=0;
}
time=(timeH<<16)+timeL;
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(RX_EN);
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC) // switch to RX mode and disable CRC
| (1 << NRF24L01_00_CRCO)
| (1 << NRF24L01_00_PWR_UP)
| (1 << NRF24L01_00_PRIM_RX));
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
XN297Dump_overflow();
break;
}
debug(",%d",hopping_frequency_no);
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency_no);
XN297_RFChannel(hopping_frequency_no);
// switch to RX mode
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(RX_EN);
NRF24L01_FlushRx();
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
}
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
if( XN297_IsRX() )
{ // RX fifo data ready
if(NRF24L01_ReadReg(NRF24L01_09_CD))
// if(NRF24L01_ReadReg(NRF24L01_09_CD))
{
boolean res;
uint8_t res;
if(enhanced)
{
res=XN297_ReadEnhancedPayload(packet, packet_length);
res++;
}
else
res=XN297_ReadPayload(packet, packet_length);
if(res)
@@ -471,11 +469,8 @@ static uint16_t XN297Dump_callback()
}
}
// restart RX mode
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(RX_EN);
NRF24L01_FlushRx();
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
}
XN297Dump_overflow();
break;
@@ -518,7 +513,7 @@ static uint16_t XN297Dump_callback()
}
debugln("Time between CH:%d and CH:%d",hopping_frequency[0],hopping_frequency[hopping_frequency_no]);
time_rf[hopping_frequency_no]=-1;
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency[0]);
XN297_RFChannel(hopping_frequency[0]);
uint16_t timeL=TCNT1;
if(TIMER2_BASE->SR & TIMER_SR_UIF)
{//timer just rolled over...
@@ -527,19 +522,19 @@ static uint16_t XN297Dump_callback()
}
time=(timeH<<16)+timeL;
// switch to RX mode
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(RX_EN);
NRF24L01_FlushRx();
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
}
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
if( XN297_IsRX() )
{ // RX fifo data ready
if(NRF24L01_ReadReg(NRF24L01_09_CD))
//if(NRF24L01_ReadReg(NRF24L01_09_CD))
{
boolean res;
uint8_t res;
if(enhanced)
{
res=XN297_ReadEnhancedPayload(packet, packet_length);
res++;
}
else
res=XN297_ReadPayload(packet, packet_length);
if(res)
@@ -557,12 +552,12 @@ static uint16_t XN297Dump_callback()
if(time_rf[hopping_frequency_no] > (time>>1))
time_rf[hopping_frequency_no]=time>>1;
debugln("Time: %5luus", time>>1);
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency[0]);
XN297_RFChannel(hopping_frequency[0]);
}
else
{
time=(timeH<<16)+timeL;
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency[hopping_frequency_no]);
XN297_RFChannel(hopping_frequency[hopping_frequency_no]);
}
packet_count++;
if(packet_count>24)
@@ -573,22 +568,22 @@ static uint16_t XN297Dump_callback()
}
}
// restart RX mode
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(RX_EN);
NRF24L01_FlushRx();
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
}
XN297Dump_overflow();
break;
case 4:
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
if( XN297_IsRX() )
{ // RX fifo data ready
if(NRF24L01_ReadReg(NRF24L01_09_CD))
//if(NRF24L01_ReadReg(NRF24L01_09_CD))
{
boolean res;
uint8_t res;
if(enhanced)
{
res=XN297_ReadEnhancedPayload(packet, packet_length);
res++;
}
else
res=XN297_ReadPayload(packet, packet_length);
if(res)
@@ -604,24 +599,22 @@ static uint16_t XN297Dump_callback()
}
}
// restart RX mode
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(RX_EN);
NRF24L01_FlushRx();
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
XN297_SetTxRxMode(TXRX_OFF);
XN297_SetTxRxMode(RX_EN);
}
break;
}
}
else
else if(sub_protocol == XN297DUMP_NRF)
{
if(phase==0)
{
address_length=4;
memcpy(rx_tx_addr, (uint8_t *)"\x5A\x20\x12\xAC", address_length); //"\xA3\x05\x22\xC1"
bitrate=XN297DUMP_1M;
address_length=5;
memcpy(rx_tx_addr, (uint8_t *)"\x61\x94\x17\x27\xED", address_length); //"\xA3\x05\x22\xC1""\x5A\x20\x12\xAC"
bitrate=XN297DUMP_250K;
packet_length=32;
hopping_frequency_no=60; //bind ?, normal 60
hopping_frequency_no=54; //bind ?, normal 60
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TXRX_OFF);
@@ -658,12 +651,18 @@ static uint16_t XN297Dump_callback()
if(NRF24L01_ReadReg(NRF24L01_09_CD))
{
NRF24L01_ReadPayload(packet, packet_length);
bool ok=true;
//bool ok=true;
uint8_t buffer[40];
memcpy(buffer,packet,packet_length);
if(memcmp(&packet_in[0],&packet[0],packet_length))
//if(memcmp(&packet_in[0],&packet[0],packet_length))
{
//realign bits
debug("P:");
for(uint8_t i=0;i<packet_length;i++)
debug(" %02X",packet[i]);
debugln("");
memcpy(packet_in,packet,packet_length);
}
/*//realign bits
for(uint8_t i=0; i<packet_length; i++)
buffer[i]=buffer[i+2];
//for(uint8_t i=0; i<packet_length; i++)
@@ -693,7 +692,7 @@ static uint16_t XN297Dump_callback()
debugln("");
memcpy(packet_in,packet,packet_length);
}
}
}*/
/*crc=0;
for (uint8_t i = 1; i < 12; ++i)
crc16_update( packet[i], 8);
@@ -721,6 +720,119 @@ static uint16_t XN297Dump_callback()
}
}
}
else if(sub_protocol == XN297DUMP_CC2500)
{
#if defined (CC2500_INSTALLED)
if(phase==0)
{
address_length=5;
switch(RX_num)
{
case 0:
memcpy(rx_tx_addr, (uint8_t *)"\xAE\xD2\x71\x79\x46", address_length);
break;
case 1:
memcpy(rx_tx_addr, (uint8_t *)"\x5D\xA4\xE2\xF2\x8C", address_length);
break;
case 2:
memcpy(rx_tx_addr, (uint8_t *)"\xBB\x49\xC5\xE5\x18", address_length);
break;
case 3:
memcpy(rx_tx_addr, (uint8_t *)"\x76\x93\x8B\xCA\x30", address_length);
break;
case 4:
memcpy(rx_tx_addr, (uint8_t *)"\xED\x27\x17\x94\x61", address_length);
break;
case 5:
memcpy(rx_tx_addr, (uint8_t *)"\xDA\x4E\x2F\x28\xC2", address_length);
break;
case 6:
memcpy(rx_tx_addr, (uint8_t *)"\xAB\xB4\x9C\x5E\x51", address_length);
break;
case 7:
memcpy(rx_tx_addr, (uint8_t *)"\x57\x69\x38\xBC\xA3", address_length);
break;
}
packet_length=38;
hopping_frequency_no=54; //bind 30, normal 54
debugln("CC2500 dump, len=%d, rf=%d, address length=%d, bitrate=250K",packet_length,hopping_frequency_no,address_length);
//Config CC2500
CC2500_250K_Init();
CC2500_SetFreqOffset();
CC2500_WriteReg(CC2500_04_SYNC1, rx_tx_addr[0]); // Sync word, high byte
CC2500_WriteReg(CC2500_05_SYNC0, rx_tx_addr[1]); // Sync word, low byte
CC2500_WriteReg(CC2500_09_ADDR, rx_tx_addr[2]); // Set addr
CC2500_WriteReg(CC2500_12_MDMCFG2, 0x12); // Modem Configuration, GFSK, 16/16 Sync Word TX&RX
CC2500_WriteReg(CC2500_06_PKTLEN, packet_length); // Packet len
//2.4001GHz: offfset of 100KHz
CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // Frequency Control Word, High Byte
CC2500_WriteReg(CC2500_0E_FREQ1, 0x4F); // Frequency Control Word, Middle Byte
CC2500_WriteReg(CC2500_0F_FREQ0, 0xC1); // Frequency Control Word, Low Byte
CC2500_250K_RFChannel(hopping_frequency_no);
CC2500_SetTxRxMode(RX_EN);
CC2500_Strobe(CC2500_SFRX);
CC2500_Strobe(CC2500_SRX);
phase++;
}
else
{
CC2500_SetFreqOffset();
if((CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F) == packet_length + 2) // 2 = RSSI + LQI
{ // RX fifo data ready
//debugln("f_off=%02X", CC2500_ReadReg(0x32 | CC2500_READ_BURST));
CC2500_ReadData(packet, packet_length+2);
bool ok=true;
//filter address
if(rx_tx_addr[2]!=packet[0] || rx_tx_addr[3]!=packet[1] || rx_tx_addr[4]!=packet[2] )
ok=false;
//filter constants
if(RX_num == 0 && ok)
{
if (packet[3] != 0x10 || (packet[4] & 0xFC) != 0x54 || packet[5] != 0x64)
ok=false;
else if(packet[6] != 0x10 && packet[6] != 0x25)
ok=false;
else if(memcmp(&packet[9],"\xC6\xE7\x50\x02\xAA\x49",6)!=0)
ok=false;
}
else if(RX_num == 4 && ok)
{
if (packet[3] != 0x05 || (packet[4] & 0xCF) != 0x46)
ok=false;
else if(packet[5] != 0x41 && packet[5] != 0x42)
ok=false;
else if((packet[6]&0xF0) != 0x50 && (packet[6]&0xF0) != 0x00)
ok=false;
else if((packet[8]&0x0F) != 0x0C)
ok=false;
else if(memcmp(&packet[9],"\x6E\x75\x00\x2A\xA4\x94\xA4\x6F",8)!=0)
ok=false;
}
if(ok)
{
//uint8_t buffer[100];
//memcpy(buffer,packet,packet_length);
//if(memcmp(&packet_in[0],&packet[0],packet_length))
{
debug("P:");
for(uint8_t i=0;i<packet_length;i++)
debug(" %02X",packet[i]);
debugln("");
memcpy(packet_in,packet,packet_length);
}
}
CC2500_SetTxRxMode(TXRX_OFF);
CC2500_SetTxRxMode(RX_EN);
CC2500_Strobe(CC2500_SFRX);
CC2500_Strobe(CC2500_SRX);
}
}
#endif
}
bind_counter++;
if(IS_RX_FLAG_on) // Let the radio update the protocol
{

View File

@@ -2,69 +2,252 @@
#include "iface_xn297.h"
bool xn297_scramble_enabled, xn297_crc, xn297_bitrate, xn297_rf;
uint8_t xn297_addr_len, xn297_rx_packet_len;
uint8_t xn297_tx_addr[5], xn297_rx_addr[5];
// xn297 address / pcf / payload scramble table
const uint8_t xn297_scramble[] = {
0xE3, 0xB1, 0x4B, 0xEA, 0x85, 0xBC, 0xE5, 0x66,
0x0D, 0xAE, 0x8C, 0x88, 0x12, 0x69, 0xEE, 0x1F,
0xC7, 0x62, 0x97, 0xD5, 0x0B, 0x79, 0xCA, 0xCC,
0x1B, 0x5D, 0x19, 0x10, 0x24, 0xD3, 0xDC, 0x3F,
0x8E, 0xC5, 0x2F, 0xAA, 0x16, 0xF3, 0x95 };
// scrambled, standard mode crc xorout table
const uint16_t PROGMEM xn297_crc_xorout_scrambled[] = {
0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C,
0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B,
0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7,
0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,
0x2138, 0x129F, 0xB3A0, 0x2988, 0x23CA, 0xC0CB,
0x0C6C, 0xB329, 0xA0A1, 0x0A16, 0xA9D0 };
// unscrambled, standard mode crc xorout table
const uint16_t PROGMEM xn297_crc_xorout[] = {
0x0000, 0x3D5F, 0xA6F1, 0x3A23, 0xAA16, 0x1CAF,
0x62B2, 0xE0EB, 0x0821, 0xBE07, 0x5F1A, 0xAF15,
0x4F0A, 0xAD24, 0x5E48, 0xED34, 0x068C, 0xF2C9,
0x1852, 0xDF36, 0x129D, 0xB17C, 0xD5F5, 0x70D7,
0xB798, 0x5133, 0x67DB, 0xD94E, 0x0A5B, 0xE445,
0xE6A5, 0x26E7, 0xBDAB, 0xC379, 0x8E20 };
// scrambled enhanced mode crc xorout table
const uint16_t PROGMEM xn297_crc_xorout_scrambled_enhanced[] = {
0x0000, 0x7EBF, 0x3ECE, 0x07A4, 0xCA52, 0x343B,
0x53F8, 0x8CD0, 0x9EAC, 0xD0C0, 0x150D, 0x5186,
0xD251, 0xA46F, 0x8435, 0xFA2E, 0x7EBD, 0x3C7D,
0x94E0, 0x3D5F, 0xA685, 0x4E47, 0xF045, 0xB483,
0x7A1F, 0xDEA2, 0x9642, 0xBF4B, 0x032F, 0x01D2,
0xDC86, 0x92A5, 0x183A, 0xB760, 0xA953 };
// unscrambled enhanced mode crc xorout table
// unused so far
#ifdef XN297DUMP_NRF24L01_INO
const uint16_t xn297_crc_xorout_enhanced[] = {
0x0000, 0x8BE6, 0xD8EC, 0xB87A, 0x42DC, 0xAA89,
0x83AF, 0x10E4, 0xE83E, 0x5C29, 0xAC76, 0x1C69,
0xA4B2, 0x5961, 0xB4D3, 0x2A50, 0xCB27, 0x5128,
0x7CDB, 0x7A14, 0xD5D2, 0x57D7, 0xE31D, 0xCE42,
0x648D, 0xBF2D, 0x653B, 0x190C, 0x9117, 0x9A97,
0xABFC, 0xE68E, 0x0DE7, 0x28A2, 0x1965 };
#endif
#ifdef NRF24L01_INSTALLED
void XN297_SetTXAddr(const uint8_t* addr, uint8_t len)
static bool __attribute__((unused)) XN297_Configure(bool crc_en, bool scramble_en, bool bitrate, bool force_nrf)
{
if (len > 5) len = 5;
if (len < 3) len = 3;
uint8_t buf[] = { 0x55, 0x0F, 0x71, 0x0C, 0x00 }; // bytes for XN297 preamble 0xC710F55 (28 bit)
xn297_addr_len = len;
if (xn297_addr_len < 4)
for (uint8_t i = 0; i < 4; ++i)
buf[i] = buf[i+1];
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, buf, 5);
// Receive address is complicated. We need to use scrambled actual address as a receive address
// but the TX code now assumes fixed 4-byte transmit address for preamble. We need to adjust it
// first. Also, if the scrambled address begins with 1 nRF24 will look for preamble byte 0xAA
// instead of 0x55 to ensure enough 0-1 transitions to tune the receiver. Still need to experiment
// with receiving signals.
memcpy(xn297_tx_addr, addr, len);
xn297_crc = crc_en;
xn297_scramble_enabled = scramble_en;
xn297_bitrate = bitrate;
xn297_rf = XN297_NRF;
#if defined(NRF24L01_INSTALLED) and defined(CC2500_INSTALLED)
if(bitrate == XN297_1M || force_nrf)
xn297_rf = XN297_NRF; // Use NRF24L01
else
xn297_rf = XN297_CC2500; // Use CC2500
#elif defined(NRF24L01_INSTALLED) and not defined(CC2500_INSTALLED)
xn297_rf = XN297_NRF; // Use NRF24L01
#else //CC2500 only
xn297_rf = XN297_CC2500; // Use CC2500
if(bitrate == XN297_1M)
{
xn297_rf = XN297_NRF; // Use NRF24L01 which does not exist, nothing will happen...
SUB_PROTO_INVALID;
return false; // Can't do...
}
#endif
#if defined(NRF24L01_INSTALLED)
if(xn297_rf == XN297_NRF)
{
debugln("Using NRF");
rf_switch(SW_NRF);
NRF24L01_Initialize();
if(bitrate == XN297_250K)
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
}
#endif
#if defined(CC2500_INSTALLED)
if(xn297_rf == XN297_CC2500)
{
debugln("Using CC2500");
rf_switch(SW_CC2500);
CC2500_250K_Init();
option_override = 2; // OPTION_RFTUNE
}
#endif
return true;
}
void XN297_SetRXAddr(const uint8_t* addr, uint8_t len)
static void __attribute__((unused)) XN297_SetTXAddr(const uint8_t* addr, uint8_t len)
{
if (len > 5) len = 5;
if (len < 3) len = 3;
uint8_t buf[] = { 0, 0, 0, 0, 0 };
memcpy(buf, addr, len);
memcpy(xn297_rx_addr, addr, len);
xn297_addr_len = len;
memcpy(xn297_tx_addr, addr, len);
#ifdef NRF24L01_INSTALLED
if(xn297_rf == XN297_NRF)
{
uint8_t buf[] = { 0x55, 0x0F, 0x71, 0x0C, 0x00 }; // bytes for XN297 preamble 0xC710F55 (28 bit)
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, xn297_addr_len == 3 ? buf+1 : buf, 5);
}
#endif
};
static void __attribute__((unused)) XN297_SetRXAddr(const uint8_t* addr, uint8_t rx_packet_len)
{
//Scramble address
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
buf[i] = xn297_rx_addr[i];
xn297_rx_addr[i] = addr[i];
if(xn297_scramble_enabled)
buf[i] ^= xn297_scramble[xn297_addr_len-i-1];
xn297_rx_addr[i] ^= xn297_scramble[xn297_addr_len-i-1];
}
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, buf, 5);
if(xn297_crc)
rx_packet_len += 2; // Include CRC
rx_packet_len += 2; // Include pcf, will this be a problem timing wise even if not enhanced?
#ifdef NRF24L01_INSTALLED
if(xn297_rf == XN297_NRF)
{
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, xn297_rx_addr, xn297_addr_len);
if(rx_packet_len >= 32)
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 32);
else
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, rx_packet_len);
}
#endif
#ifdef CC2500_INSTALLED
if(xn297_rf == XN297_CC2500)
{// TX: Sync1, Sync0, Address
CC2500_WriteReg(CC2500_04_SYNC1, xn297_rx_addr[xn297_addr_len-1]); // Sync word, high byte
CC2500_WriteReg(CC2500_05_SYNC0, xn297_rx_addr[xn297_addr_len-2]); // Sync word, low byte
CC2500_WriteReg(CC2500_09_ADDR, xn297_rx_addr[xn297_addr_len-3]); // Address
rx_packet_len += 1 + xn297_addr_len - 3; // The Address field above will be in the payload then the end of the XN297 address
}
#endif
xn297_rx_packet_len = rx_packet_len;
}
void XN297_Configure(uint8_t flags)
static void __attribute__((unused)) XN297_SetTxRxMode(enum TXRX_State mode)
{
xn297_crc = !!(flags & _BV(NRF24L01_00_EN_CRC));
flags &= ~(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xFF);
static enum TXRX_State cur_mode=TXRX_OFF;
#ifdef NRF24L01_INSTALLED
if(xn297_rf == XN297_NRF)
{
NRF24L01_WriteReg(NRF24L01_07_STATUS, (1 << NRF24L01_07_RX_DR) //reset the flag(s)
| (1 << NRF24L01_07_TX_DS)
| (1 << NRF24L01_07_MAX_RT));
if(mode==TXRX_OFF)
{
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0); //PowerDown
NRF_CE_off;
return;
}
NRF_CE_off;
if(mode == TX_EN)
{
NRF24L01_FlushTx();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 1 << NRF24L01_00_PWR_UP);
}
else
{
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_PWR_UP)
| (1 << NRF24L01_00_PRIM_RX)); // RX
}
if(mode != cur_mode)
{
//delayMicroseconds(130);
cur_mode=mode;
}
NRF_CE_on;
}
#endif
#ifdef CC2500_INSTALLED
if(xn297_rf == XN297_CC2500)
{
if(mode != cur_mode)
{
CC2500_SetTxRxMode(mode);
if(mode == RX_EN)
{
CC2500_WriteReg(CC2500_12_MDMCFG2, 0x12); // Modem Configuration, GFSK, 16/16 Sync Word TX&RX
CC2500_WriteReg(CC2500_06_PKTLEN, xn297_rx_packet_len); // Packet len
CC2500_Strobe(CC2500_SFRX);
CC2500_Strobe(CC2500_SRX);
}
else
CC2500_WriteReg(CC2500_12_MDMCFG2, 0x10); // Modem Configuration, GFSK, no preambule and no sync word
cur_mode=mode;
}
}
#endif
}
void XN297_SetScrambledMode(const uint8_t mode)
static void __attribute__((unused)) XN297_SendPayload(uint8_t* msg, uint8_t len)
{
xn297_scramble_enabled = mode;
#ifdef NRF24L01_INSTALLED
if(xn297_rf == XN297_NRF)
{
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
NRF24L01_WritePayload(msg, len);
}
#endif
#ifdef CC2500_INSTALLED
if(xn297_rf == XN297_CC2500)
{
// stop TX/RX
CC2500_Strobe(CC2500_SIDLE);
// flush tx FIFO
CC2500_Strobe(CC2500_SFTX);
// packet length
CC2500_WriteReg(CC2500_06_PKTLEN, len + 4); // Packet len, fix packet len
// xn297L preamble
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (uint8_t*)"\x0C\x71\x0F\x55", 4);
// xn297 packet
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, msg, len);
// transmit
CC2500_Strobe(CC2500_STX);
}
#endif
}
void XN297_WritePayload(uint8_t* msg, uint8_t len)
static void __attribute__((unused)) XN297_WritePayload(uint8_t* msg, uint8_t len)
{
uint8_t buf[32];
uint8_t last = 0;
if (xn297_addr_len < 4)
{
// If address length (which is defined by receive address length)
// is less than 4 the TX address can't fit the preamble, so the last
// byte goes here
if (xn297_rf == XN297_NRF && xn297_addr_len < 4 && xn297_rf == XN297_NRF)
{ // If address length (which is defined by receiver address length) is less than 4 the TX address can't fit the preamble, so the last byte goes here
buf[last++] = 0x55;
}
// address
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
buf[last] = xn297_tx_addr[xn297_addr_len-i-1];
@@ -72,6 +255,8 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
buf[last] ^= xn297_scramble[i];
last++;
}
// payload
for (uint8_t i = 0; i < len; ++i)
{
// bit-reverse bytes in packet
@@ -80,9 +265,11 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
buf[last] ^= xn297_scramble[xn297_addr_len+i];
last++;
}
// crc
if (xn297_crc)
{
uint8_t offset = xn297_addr_len < 4 ? 1 : 0;
uint8_t offset = (xn297_addr_len < 4 && xn297_rf == XN297_NRF) ? 1 : 0;
crc = 0xb5d2;
for (uint8_t i = offset; i < last; ++i)
crc16_update( buf[i], 8);
@@ -93,88 +280,129 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
buf[last++] = crc >> 8;
buf[last++] = crc & 0xff;
}
NRF24L01_WritePayload(buf, last);
// send packet
XN297_SendPayload(buf, last);
}
void XN297_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
static void __attribute__((unused)) XN297_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
{
uint8_t packet[32];
uint8_t buf[32];
uint8_t scramble_index=0;
uint8_t last = 0;
static uint8_t pid=0;
// address
if (xn297_addr_len < 4)
{
// If address length (which is defined by receive address length)
// is less than 4 the TX address can't fit the preamble, so the last
// byte goes here
packet[last++] = 0x55;
if (xn297_rf == XN297_NRF && xn297_addr_len < 4)
{ // If address length (which is defined by receiver address length) is less than 4 the TX address can't fit the preamble, so the last byte goes here
buf[last++] = 0x55;
}
// address
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
packet[last] = xn297_tx_addr[xn297_addr_len-i-1];
buf[last] = xn297_tx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
buf[last] ^= xn297_scramble[scramble_index++];
last++;
}
// pcf
packet[last] = (len << 1) | (pid>>1);
buf[last] = (len << 1) | (pid>>1);
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
buf[last] ^= xn297_scramble[scramble_index++];
last++;
packet[last] = (pid << 7) | (noack << 6);
buf[last] = (pid << 7) | (noack << 6);
// payload
packet[last]|= bit_reverse(msg[0]) >> 2; // first 6 bit of payload
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
for (uint8_t i = 0; i < len-1; ++i)
if(len)
{
last++;
packet[last] = (bit_reverse(msg[i]) << 6) | (bit_reverse(msg[i+1]) >> 2);
buf[last]|= bit_reverse(msg[0]) >> 2; // first 6 bit of payload
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
}
buf[last] ^= xn297_scramble[scramble_index++];
last++;
packet[last] = bit_reverse(msg[len-1]) << 6; // last 2 bit of payload
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++] & 0xc0;
for (uint8_t i = 0; i < len-1; ++i)
{
last++;
buf[last] = (bit_reverse(msg[i]) << 6) | (bit_reverse(msg[i+1]) >> 2);
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[scramble_index++];
}
last++;
buf[last] = bit_reverse(msg[len-1]) << 6; // last 2 bit of payload
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[scramble_index++] & 0xc0;
}
// crc
if (xn297_crc)
{
uint8_t offset = xn297_addr_len < 4 ? 1 : 0;
uint8_t offset = (xn297_addr_len < 4 && xn297_rf == XN297_NRF) ? 1 : 0;
crc = 0xb5d2;
for (uint8_t i = offset; i < last; ++i)
crc16_update( packet[i], 8);
crc16_update( packet[last] & 0xc0, 2);
crc16_update( buf[i], 8);
crc16_update( buf[last] & 0xc0, 2);
if (xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
//else
// crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
packet[last++] |= (crc >> 8) >> 2;
packet[last++] = ((crc >> 8) << 6) | ((crc & 0xff) >> 2);
packet[last++] = (crc & 0xff) << 6;
buf[last++] |= (crc >> 8) >> 2;
buf[last++] = ((crc >> 8) << 6) | ((crc & 0xff) >> 2);
buf[last++] = (crc & 0xff) << 6;
}
NRF24L01_WritePayload(packet, last);
pid++;
if(pid>3)
pid=0;
// send packet
XN297_SendPayload(buf, last);
}
boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
{ //!!! Don't forget if using CRC to do a +2 on any of the used NRF24L01_11_RX_PW_Px !!!
uint8_t buf[32];
static bool __attribute__((unused)) XN297_IsRX()
{
#ifdef NRF24L01_INSTALLED
if(xn297_rf == XN297_NRF)
return (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR));
#endif
#ifdef CC2500_INSTALLED
if(xn297_rf == XN297_CC2500)
{
if((CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F) != xn297_rx_packet_len + 2) // 2 = RSSI + LQI
return false; // Buffer does not contain the expected number of bytes
// Check the address
uint8_t buf[3];
CC2500_ReadData(buf, xn297_addr_len-3 + 1);
for(uint8_t i=0; i < xn297_addr_len-3 + 1; i++)
if(buf[i] != xn297_rx_addr[xn297_addr_len-3 - i])
return false; // Bad address
return true; // Address is correct
}
#endif
return false;
}
static void __attribute__((unused)) XN297_ReceivePayload(uint8_t* msg, uint8_t len)
{
if (xn297_crc)
NRF24L01_ReadPayload(buf, len+2); // Read payload + CRC
else
NRF24L01_ReadPayload(buf, len);
len += 2; // Include CRC
#ifdef NRF24L01_INSTALLED
if(xn297_rf == XN297_NRF)
NRF24L01_ReadPayload(msg, len); // Read payload and CRC
#endif
#ifdef CC2500_INSTALLED
if(xn297_rf == XN297_CC2500)
CC2500_ReadData(msg, len);
#endif
}
static bool __attribute__((unused)) XN297_ReadPayload(uint8_t* msg, uint8_t len)
{ //!!! Don't forget if using CRC to do a +2 on the received packet length (NRF24L01_11_RX_PW_Px !!! or CC2500_06_PKTLEN)
uint8_t buf[32];
// Read payload
XN297_ReceivePayload(buf, len);
// Decode payload
for(uint8_t i=0; i<len; i++)
{
@@ -183,6 +411,7 @@ boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
b_in ^= xn297_scramble[i+xn297_addr_len];
msg[i] = bit_reverse(b_in);
}
if (!xn297_crc)
return true; // No CRC so OK by default...
@@ -190,12 +419,7 @@ boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
crc = 0xb5d2;
//process address
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
uint8_t b_in=xn297_rx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
b_in ^= xn297_scramble[i];
crc16_update( b_in, 8);
}
crc16_update( xn297_rx_addr[xn297_addr_len-i-1], 8);
//process payload
for (uint8_t i = 0; i < len; ++i)
crc16_update( buf[i], 8);
@@ -210,19 +434,22 @@ boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
return false; // CRC NOK
}
uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
static uint8_t __attribute__((unused)) XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
{ //!!! Don't forget do a +2 and if using CRC add +4 on any of the used NRF24L01_11_RX_PW_Px !!!
uint8_t buffer[32];
uint8_t pcf_size; // pcf payload size
if (xn297_crc)
NRF24L01_ReadPayload(buffer, len+4); // Read pcf + payload + CRC
else
NRF24L01_ReadPayload(buffer, len+2); // Read pcf + payload
uint8_t pcf_size; // pcf payload size
// Read payload
XN297_ReceivePayload(buffer, len+2); // Read pcf + payload + CRC
// Decode payload
pcf_size = buffer[0];
if(xn297_scramble_enabled)
pcf_size ^= xn297_scramble[xn297_addr_len];
pcf_size = pcf_size >> 1;
for(int i=0; i<len; i++)
if(pcf_size>32)
return 255; // Error
for(uint8_t i=0; i< pcf_size; i++)
{
msg[i] = bit_reverse((buffer[i+1] << 2) | (buffer[i+2] >> 6));
if(xn297_scramble_enabled)
@@ -231,35 +458,98 @@ uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
}
if (!xn297_crc)
return pcf_size; // No CRC so OK by default...
return pcf_size; // No CRC so OK by default...
// Calculate CRC
crc = 0xb5d2;
//process address
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
uint8_t b_in=xn297_rx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
b_in ^= xn297_scramble[i];
crc16_update( b_in, 8);
}
crc16_update( xn297_rx_addr[xn297_addr_len-i-1], 8);
//process payload
for (uint8_t i = 0; i < len+1; ++i)
for (uint8_t i = 0; i < pcf_size+1; ++i)
crc16_update( buffer[i], 8);
crc16_update( buffer[len+1] & 0xc0, 2);
crc16_update( buffer[pcf_size+1] & 0xc0, 2);
//xorout
if (xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+pcf_size]);
#ifdef XN297DUMP_NRF24L01_INO
else
crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + pcf_size]);
#endif
uint16_t crcxored=(buffer[len+1]<<10)|(buffer[len+2]<<2)|(buffer[len+3]>>6) ;
uint16_t crcxored=(buffer[pcf_size+1]<<10)|(buffer[pcf_size+2]<<2)|(buffer[pcf_size+3]>>6) ;
if( crc == crcxored)
return pcf_size; // CRC OK
return 0; // CRC NOK
return pcf_size; // CRC OK
return 255; // CRC NOK
}
static bool __attribute__((unused)) XN297_IsPacketSent()
{
#ifdef NRF24L01_INSTALLED
if(xn297_rf == XN297_NRF)
return (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS));
#endif
#ifdef CC2500_INSTALLED
if(xn297_rf == XN297_CC2500)
return (CC2500_ReadReg(CC2500_35_MARCSTATE | CC2500_READ_BURST) != 0x13);
#endif
return true; // packet sent to not block
}
static void __attribute__((unused)) XN297_HoppingCalib(uint8_t num_freq)
{ //calibrate hopping frequencies
#ifdef NRF24L01_INSTALLED
(void)num_freq;
#endif
#ifdef CC2500_INSTALLED
if(xn297_rf == XN297_CC2500)
CC2500_250K_HoppingCalib(num_freq);
#endif
}
static void __attribute__((unused)) XN297_Hopping(uint8_t index)
{
#ifdef NRF24L01_INSTALLED
if(xn297_rf == XN297_NRF)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[index]);
#endif
#ifdef CC2500_INSTALLED
if(xn297_rf == XN297_CC2500)
CC2500_250K_Hopping(index);
#endif
}
static void __attribute__((unused)) XN297_RFChannel(uint8_t number)
{ //change channel
#ifdef NRF24L01_INSTALLED
if(xn297_rf == XN297_NRF)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, number);
#endif
#ifdef CC2500_INSTALLED
if(xn297_rf == XN297_CC2500)
CC2500_250K_RFChannel(number);
#endif
}
static void __attribute__((unused)) XN297_SetPower()
{
#ifdef NRF24L01_INSTALLED
if(xn297_rf == XN297_NRF)
NRF24L01_SetPower();
#endif
#ifdef CC2500_INSTALLED
if(xn297_rf == XN297_CC2500)
CC2500_SetPower();
#endif
}
static void __attribute__((unused)) XN297_SetFreqOffset()
{ // Frequency offset
#ifdef CC2500_INSTALLED
if(xn297_rf == XN297_CC2500)
CC2500_SetFreqOffset();
#endif
}
// End of XN297 emulation
#endif

View File

@@ -16,7 +16,7 @@ Multiprotocol is distributed in the hope that it will be useful,
#if defined(ZSX_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
//#define FORCE_ZSX_ORIGINAL_ID
@@ -44,12 +44,10 @@ static void __attribute__((unused)) ZSX_send_packet()
| GET_FLAG(CH5_SW, 0x80); // Light
}
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
// Send
XN297_SetPower();
XN297_SetTxRxMode(TX_EN);
XN297_WritePayload(packet, ZSX_PAYLOAD_SIZE);
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) ZSX_initialize_txid()
@@ -65,10 +63,9 @@ static void __attribute__((unused)) ZSX_initialize_txid()
static void __attribute__((unused)) ZSX_RF_init()
{
NRF24L01_Initialize();
XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_1M);
XN297_SetTXAddr((uint8_t*)"\xc1\xc2\xc3", 3);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, ZSX_RF_BIND_CHANNEL); // Set bind channel
XN297_RFChannel(ZSX_RF_BIND_CHANNEL); // Set bind channel
}
uint16_t ZSX_callback()
@@ -81,7 +78,7 @@ uint16_t ZSX_callback()
{
BIND_DONE;
XN297_SetTXAddr(rx_tx_addr, 3);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x00);
XN297_RFChannel(0x00);
}
ZSX_send_packet();
return ZSX_PACKET_PERIOD;

View File

@@ -168,6 +168,9 @@
//All the protocols will not fit in the Atmega328p module so you need to pick and choose.
//Comment the protocols you are not using with "//" to save Flash space.
//Protocol for module configuration
#define MULTI_CONFIG_INO
//The protocols below need an A7105 to be installed
#define AFHDS2A_A7105_INO
#define AFHDS2A_RX_A7105_INO
@@ -187,6 +190,7 @@
#define E010R5_CYRF6936_INO
#define E129_CYRF6936_INO
#define J6PRO_CYRF6936_INO
#define LOSI_CYRF6936_INO
#define MLINK_CYRF6936_INO
#define TRAXXAS_CYRF6936_INO
#define WFLY_CYRF6936_INO
@@ -203,7 +207,7 @@
#define FRSKY_RX_CC2500_INO
#define HITEC_CC2500_INO
#define HOTT_CC2500_INO
#define OMP_CC2500_INO //CC2500 for control and NRF for telemetry
//#define IKEAANSLUTA_CC2500_INO // This is mostly a "for-fun" kind of a thing, not needed for most users
#define SCANNER_CC2500_INO
#define FUTABA_CC2500_INO
#define SKYARTEC_CC2500_INO
@@ -216,10 +220,11 @@
#define BAYANG_RX_NRF24L01_INO
#define BUGSMINI_NRF24L01_INO
#define CABELL_NRF24L01_INO
#define CFLIE_NRF24L01_INO
//#define CFLIE_NRF24L01_INO
#define CG023_NRF24L01_INO
#define CX10_NRF24L01_INO //Include Q2X2 protocol
#define DM002_NRF24L01_INO
#define E016H_NRF24L01_INO
#define E01X_NRF24L01_INO
#define ESKY_NRF24L01_INO
#define ESKY150_NRF24L01_INO
@@ -233,28 +238,31 @@
#define JJRC345_NRF24L01_INO
#define KN_NRF24L01_INO
#define LOLI_NRF24L01_INO
#define MJXQ_NRF24L01_INO
#define MT99XX_NRF24L01_INO
//#define MOULDKG_NRF24L01_INO
#define NCC1701_NRF24L01_INO
#define POTENSIC_NRF24L01_INO
#define PROPEL_NRF24L01_INO
#define Q303_NRF24L01_INO
#define REALACC_NRF24L01_INO
#define SHENQI_NRF24L01_INO
#define SYMAX_NRF24L01_INO
#define TIGER_NRF24L01_INO
#define V2X2_NRF24L01_INO
#define V761_NRF24L01_INO
#define XK_NRF24L01_INO
#define XERALL_NRF24L01_INO
#define YD717_NRF24L01_INO
#define ZSX_NRF24L01_INO
//The protocols below need either a CC2500 or NRF24L01 to be installed
#define GD00X_CCNRF_INO
#define KF606_CCNRF_INO
#define MJXQ_CCNRF_INO
#define MT99XX_CCNRF_INO
#define OMP_CCNRF_INO
#define Q303_CCNRF_INO
#define Q90C_CCNRF_INO
#define SLT_CCNRF_INO
#define V911S_CCNRF_INO
#define XK_CCNRF_INO
//The protocols below need a SX1276 to be installed
#define FRSKYR9_SX1276_INO
@@ -285,9 +293,9 @@
/**************************/
/*** FAILSAFE SETTINGS ***/
/**************************/
//The following protocols are supporting failsafe: FrSkyX, Devo, WK2x01, Futaba/SFHSS, HISKY/HK310 and AFHDS2A
//The following protocols are supporting failsafe: FrSkyX, FrSkyX2, FRSKYR9, Devo, WK2x01, Futaba/SFHSS, HISKY/HK310, HoTT, LOLI, MLINK, WFLY, WFLY2 and AFHDS2A
//In Serial mode failsafe is configured on the radio itself.
//In PPM mode and only after the module is up and fully operational, press the bind button for at least 5sec to send the current stick positions as failsafe to the RX.
//In PPM mode and only after the module is up and fully operational, press the bind button for at least 5sec to send all the current channels positions as failsafe to the RX.
//If you want to disable failsafe globally comment the line below using "//".
#define FAILSAFE_ENABLE
@@ -332,6 +340,7 @@
#define RLINK_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define WFLY2_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define LOLI_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define MT99XX_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
//#define MLINK_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define MLINK_FW_TELEMETRY // Forward received telemetry packet directly to TX to be decoded by erskyTX and OpenTX
//#define HITEC_HUB_TELEMETRY // Use FrSkyD Hub format to send basic telemetry to the radios which can decode it like er9x, erskyTX and OpenTX
@@ -540,6 +549,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PPM_SBUS
PWM_IB16
PPM_IB16
PWM_SB16
PPM_SB16
PROTO_AFHDS2A_RX
NONE
PROTO_ASSAN
@@ -588,16 +599,18 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
DSM2_2F
DSMX_1F
DSMX_2F
DSMR
PROTO_DSM_RX
NONE
PROTO_E010R5
NONE
PROTO_E016H
NONE
PROTO_E016HV2
NONE
PROTO_E01X
E012
E015
E016H
PROTO_E129
NONE
PROTO_ESKY
@@ -689,6 +702,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
H107
H301
H501
PROTO_IKEAANSLUTA
NONE
PROTO_J6PRO
NONE
PROTO_JJRC345
@@ -697,7 +712,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PROTO_JOYSWAY
NONE
PROTO_KF606
NONE
KF606_KF606
KF606_MIG320
PROTO_KN
WLTOYS
FEILUN
@@ -706,6 +722,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
KYOSHO_HYPE
PROTO_LOLI
NONE
PROTO_LOSI
NONE
PROTO_MJXQ
WLH08
X600
@@ -716,6 +734,9 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PHOENIX
PROTO_MLINK
NONE
PROTO_MOULDKG
MOULDKG_ANALOG
MOULDKG_DIGIT
PROTO_MT99XX
MT99
H7
@@ -724,6 +745,7 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
FY805
A180
DRAGON
F949G
PROTO_NCC1701
NONE
PROTO_OMP
@@ -731,6 +753,7 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PROTO_PELIKAN
PELIKAN_PRO
PELIKAN_LITE
PELIKAN_SCX24
PROTO_POTENSIC
NONE
PROTO_PROPEL
@@ -797,6 +820,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
W6_6_1
W6_HEL
W6_HEL_I
PROTO_XERALL
NONE
PROTO_XK
X450
X420

View File

@@ -35,7 +35,7 @@
#undef FQ777_NRF24L01_INO
#undef ASSAN_NRF24L01_INO
#undef HONTAI_NRF24L01_INO
#undef Q303_NRF24L01_INO
#undef Q303_CCNRF_INO
#undef GW008_NRF24L01_INO
#undef DM002_NRF24L01_INO
#undef CABELL_NRF24L01_INO

View File

@@ -1,34 +1,28 @@
#ifndef _IFACE_NRF250K_H_
#define _IFACE_NRF250K_H_
#if defined (CC2500_INSTALLED)
#ifdef CC2500_INSTALLED
#include "iface_cc2500.h"
#elif defined (NRF24L01_INSTALLED)
#endif
#ifdef NRF24L01_INSTALLED
#include "iface_nrf24l01.h"
#endif
#include "iface_xn297.h"
//XN297L
static void __attribute__((unused)) XN297L_Init();
static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t*, uint8_t);
static void __attribute__((unused)) XN297L_WritePayload(uint8_t*, uint8_t);
static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t*, uint8_t, uint8_t);
static void __attribute__((unused)) XN297L_HoppingCalib(__attribute__((unused)) uint8_t);
static void __attribute__((unused)) XN297L_Hopping(uint8_t);
static void __attribute__((unused)) XN297L_RFChannel(uint8_t);
static void __attribute__((unused)) XN297L_SetPower();
static void __attribute__((unused)) XN297L_SetFreqOffset();
#if defined (CC2500_INSTALLED) || defined (NRF24L01_INSTALLED)
//NRF250K
#define NRF250K_Init() XN297L_Init()
#define NRF250K_HoppingCalib(X) XN297L_HoppingCalib(X)
#define NRF250K_Hopping(X) XN297L_Hopping(X)
#define NRF250K_RFChannel(X) XN297L_RFChannel(X)
#define NRF250K_SetPower() XN297L_SetPower()
#define NRF250K_SetFreqOffset() XN297L_SetFreqOffset()
//////////////
// Functions
#define NRF250K_Init() XN297_Configure(XN297_CRCEN, XN297_SCRAMBLED, XN297_250K)
#define NRF250K_HoppingCalib(X) XN297_HoppingCalib(X)
#define NRF250K_Hopping(X) XN297_Hopping(X)
#define NRF250K_RFChannel(X) XN297_RFChannel(X)
#define NRF250K_SetPower() XN297_SetPower()
#define NRF250K_SetFreqOffset() XN297_SetFreqOffset()
#define NRF250K_IsPacketSent() XN297_IsPacketSent()
static void __attribute__((unused)) NRF250K_SetTXAddr(uint8_t*, uint8_t);
static void __attribute__((unused)) NRF250K_WritePayload(uint8_t*, uint8_t);
static boolean __attribute__((unused)) NRF250K_IsPacketSent();
#endif
#endif
#endif

View File

@@ -8,76 +8,39 @@
#include "iface_nrf24l01.h"
#endif
///////////////
// XN297 emulation layer
// XN297 emulation layer
enum {
XN297_UNSCRAMBLED = 0,
XN297_SCRAMBLED
};
#if defined (CC2500_INSTALLED) || defined (NRF24L01_INSTALLED)
uint8_t xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
uint8_t xn297_addr_len;
uint8_t xn297_tx_addr[5];
uint8_t xn297_rx_addr[5];
uint8_t xn297_crc = 0;
//////////////////
// Configuration
#define XN297_UNSCRAMBLED false
#define XN297_SCRAMBLED true
#define XN297_CRCDIS false
#define XN297_CRCEN true
#define XN297_1M false
#define XN297_250K true
#define XN297_NRF false
#define XN297_CC2500 true
// xn297 address / pcf / payload scramble table
const uint8_t xn297_scramble[] = {
0xE3, 0xB1, 0x4B, 0xEA, 0x85, 0xBC, 0xE5, 0x66,
0x0D, 0xAE, 0x8C, 0x88, 0x12, 0x69, 0xEE, 0x1F,
0xC7, 0x62, 0x97, 0xD5, 0x0B, 0x79, 0xCA, 0xCC,
0x1B, 0x5D, 0x19, 0x10, 0x24, 0xD3, 0xDC, 0x3F,
0x8E, 0xC5, 0x2F, 0xAA, 0x16, 0xF3, 0x95 };
//////////////
// Functions
static bool __attribute__((unused)) XN297_Configure(bool, bool, bool, bool force_nrf=false);
static void __attribute__((unused)) XN297_SetTXAddr(const uint8_t*, uint8_t);
static void __attribute__((unused)) XN297_SetRXAddr(const uint8_t*, uint8_t);
static void __attribute__((unused)) XN297_SetTxRxMode(enum TXRX_State);
static void __attribute__((unused)) XN297_SendPayload(uint8_t*, uint8_t);
static void __attribute__((unused)) XN297_WritePayload(uint8_t*, uint8_t);
static void __attribute__((unused)) XN297_WriteEnhancedPayload(uint8_t*, uint8_t, uint8_t);
static bool __attribute__((unused)) XN297_IsRX();
static void __attribute__((unused)) XN297_ReceivePayload(uint8_t*, uint8_t);
static bool __attribute__((unused)) XN297_ReadPayload(uint8_t*, uint8_t);
static uint8_t __attribute__((unused)) XN297_ReadEnhancedPayload(uint8_t*, uint8_t);
static void __attribute__((unused)) XN297_HoppingCalib(uint8_t);
static void __attribute__((unused)) XN297_Hopping(uint8_t);
static void __attribute__((unused)) XN297_RFChannel(uint8_t);
static void __attribute__((unused)) XN297_SetPower();
static void __attribute__((unused)) XN297_SetFreqOffset();
static bool __attribute__((unused)) XN297_IsPacketSent();
// scrambled, standard mode crc xorout table
const uint16_t PROGMEM xn297_crc_xorout_scrambled[] = {
0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C,
0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B,
0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7,
0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,
0x2138, 0x129F, 0xB3A0, 0x2988, 0x23CA, 0xC0CB,
0x0C6C, 0xB329, 0xA0A1, 0x0A16, 0xA9D0 };
// unscrambled, standard mode crc xorout table
const uint16_t PROGMEM xn297_crc_xorout[] = {
0x0000, 0x3D5F, 0xA6F1, 0x3A23, 0xAA16, 0x1CAF,
0x62B2, 0xE0EB, 0x0821, 0xBE07, 0x5F1A, 0xAF15,
0x4F0A, 0xAD24, 0x5E48, 0xED34, 0x068C, 0xF2C9,
0x1852, 0xDF36, 0x129D, 0xB17C, 0xD5F5, 0x70D7,
0xB798, 0x5133, 0x67DB, 0xD94E, 0x0A5B, 0xE445,
0xE6A5, 0x26E7, 0xBDAB, 0xC379, 0x8E20 };
// scrambled enhanced mode crc xorout table
const uint16_t PROGMEM xn297_crc_xorout_scrambled_enhanced[] = {
0x0000, 0x7EBF, 0x3ECE, 0x07A4, 0xCA52, 0x343B,
0x53F8, 0x8CD0, 0x9EAC, 0xD0C0, 0x150D, 0x5186,
0xD251, 0xA46F, 0x8435, 0xFA2E, 0x7EBD, 0x3C7D,
0x94E0, 0x3D5F, 0xA685, 0x4E47, 0xF045, 0xB483,
0x7A1F, 0xDEA2, 0x9642, 0xBF4B, 0x032F, 0x01D2,
0xDC86, 0x92A5, 0x183A, 0xB760, 0xA953 };
// unscrambled enhanced mode crc xorout table
// unused so far
#ifdef XN297DUMP_NRF24L01_INO
const uint16_t xn297_crc_xorout_enhanced[] = {
0x0000, 0x8BE6, 0xD8EC, 0xB87A, 0x42DC, 0xAA89,
0x83AF, 0x10E4, 0xE83E, 0x5C29, 0xAC76, 0x1C69,
0xA4B2, 0x5961, 0xB4D3, 0x2A50, 0xCB27, 0x5128,
0x7CDB, 0x7A14, 0xD5D2, 0x57D7, 0xE31D, 0xCE42,
0x648D, 0xBF2D, 0x653B, 0x190C, 0x9117, 0x9A97,
0xABFC, 0xE68E, 0x0DE7, 0x28A2, 0x1965 };
#endif
#ifdef NRF24L01_INSTALLED
void XN297_SetTXAddr(const uint8_t*, uint8_t);
void XN297_SetRXAddr(const uint8_t*, uint8_t);
void XN297_Configure(uint8_t);
void XN297_SetScrambledMode(const uint8_t);
void XN297_WritePayload(uint8_t*, uint8_t);
void XN297_WriteEnhancedPayload(uint8_t*, uint8_t, uint8_t);
boolean XN297_ReadPayload(uint8_t*, uint8_t);
uint8_t XN297_ReadEnhancedPayload(uint8_t*, uint8_t);
#endif
#endif

View File

@@ -74,17 +74,18 @@ CFlie|38|CFlie||||||||NRF24L01|
[CX10](Protocols_Details.md#CX10---12)|12|GREEN|BLUE|DM007|-|J3015_1|J3015_2|MK33041||NRF24L01|XN297
[Devo](Protocols_Details.md#DEVO---7)|7|Devo|8CH|10CH|12CH|6CH|7CH|||CYRF6936|
[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||||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|
[E010R5](Protocols_Details.md#E010R5---81)|81|||||||||CYRF6936/NRF24L01|RF2500
[E016H](Protocols_Details.md#E016H---85)|85|||||||||NRF24L01|XN297
[E016HV2](Protocols_Details.md#E016HV2---80)|80|||||||||CC2500/NRF24L01|unknown
[E01X](Protocols_Details.md#E01X---45)|45|E012|E015|E016H||||||NRF24L01|XN297/HS6200
[E01X](Protocols_Details.md#E01X---45)|45|E012|E015|||||||NRF24L01|HS6200
[E129](Protocols_Details.md#E129---83)|83|||||||||CYRF6936/NRF24L01|RF2500
[ESky](Protocols_Details.md#ESKY---16)|16|ESky|ET4|||||||NRF24L01|
[ESky150](Protocols_Details.md#ESKY150---35)|35|||||||||NRF24L01|
[ESky150V2](Protocols_Details.md#ESKY150V2---69)|69|||||||||CC2500|NRF51822
[Flysky](Protocols_Details.md#FLYSKY---1)|1|Flysky|V9x9|V6x6|V912|CX20||||A7105|
[Flysky AFHDS2A](Protocols_Details.md#FLYSKY-AFHDS2A---28)|28|PWM_IBUS|PPM_IBUS|PWM_SBUS|PPM_SBUS|PWM_IBUS16|PPM_IBUS16|||A7105|
[Flysky AFHDS2A](Protocols_Details.md#FLYSKY-AFHDS2A---28)|28|PWM_IBUS|PPM_IBUS|PWM_SBUS|PPM_SBUS|PWM_IBUS16|PPM_IBUS16|PWM_SBUS16|PPM_SBUS16|A7105|
[Flysky AFHDS2A RX](Protocols_Details.md#FLYSKY-AFHDS2A-RX---56)|56|Multi|CPPM|||||||A7105|
[FQ777](Protocols_Details.md#FQ777---23)|23|||||||||NRF24L01|SSV7241
[FrskyD](Protocols_Details.md#FRSKYD---3)|3|D8|Cloned|||||||CC2500|
@@ -109,17 +110,19 @@ CFlie|38|CFlie||||||||NRF24L01|
[J6Pro](Protocols_Details.md#J6Pro---22)|22|||||||||CYRF6936|
[JJRC345](Protocols_Details.md#JJRC345---71)|71|JJRC345|SkyTmblr|||||||NRF24L01|XN297
[JOYSWAY](Protocols_Details.md#JOYSWAY---84)|84|||||||||NRF24L01|XN297
[KF606](Protocols_Details.md#KF606---49)|49|||||||||NRF24L01|XN297
[KF606](Protocols_Details.md#KF606---49)|49|KF606|MIG320|||||||NRF24L01|XN297
[KN](Protocols_Details.md#KN---9)|9|WLTOYS|FEILUN|||||||NRF24L01|
[Kyosho](Protocols_Details.md#Kyosho---73)|73|FHSS|Hype|||||||A7105|
[LOLI](Protocols_Details.md#LOLI---82)|82|||||||||NRF24L01|
[Losi](Protocols_Details.md#Losi---89)|89|||||||||CYRF6936|
[MJXq](Protocols_Details.md#MJXQ---18)|18|WLH08|X600|X800|H26D|E010*|H26WH|PHOENIX*||NRF24L01|XN297
[MLINK](Protocols_Details.md#MLINK---78)|78|||||||||CYRF6936|
[MT99xx](Protocols_Details.md#MT99XX---17)|17|MT|H7|YZ|LS|FY805|A180|DRAGON||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
[NCC1701](Protocols_Details.md#NCC1701---44)|44|||||||||NRF24L01|
[OMP](Protocols_Details.md#OMP---77)|77|||||||||CC2500&NRF24L01|XN297L
[OpenLRS](Protocols_Details.md#OpenLRS---27)|27|||||||||None|
[Pelikan](Protocols_Details.md#Pelikan---60)|60|Pro|Lite|||||||A7105|
[Pelikan](Protocols_Details.md#Pelikan---60)|60|Pro|Lite|SCX24||||||A7105|
[Potensic](Protocols_Details.md#Potensic---51)|51|A20||||||||NRF24L01|XN297
[PROPEL](Protocols_Details.md#PROPEL---66)|66|74-Z||||||||NRF24L01|
[Q2X2](Protocols_Details.md#Q2X2---29)|29|Q222|Q242|Q282||||||NRF24L01|
@@ -141,6 +144,7 @@ CFlie|38|CFlie||||||||NRF24L01|
[WFLY](Protocols_Details.md#WFLY---40)|40|WFR0x||||||||CYRF6936|
[WFLY2](Protocols_Details.md#WFLY2---79)|79|RF20x||||||||A7105|
[WK2x01](Protocols_Details.md#WK2X01---30)|30|WK2801|WK2401|W6_5_1|W6_6_1|W6_HEL|W6_HEL_I|||CYRF6936|
[XERALL](Protocols_Details.md#XERALL---91)|91|Tank||||||||NRF24L01|XN297
[XK](Protocols_Details.md#XK---62)|62|X450|X420|||||||NRF24L01|XN297
[YD717](Protocols_Details.md#YD717---8)|8|YD717|SKYWLKR|SYMAX4|XINXUN|NIHUI||||NRF24L01|
[ZSX](Protocols_Details.md#ZSX---52)|52|280||||||||NRF24L01|XN297
@@ -225,17 +229,12 @@ RX output will match the Flysky standard AETR independently of the input configu
### Sub_protocol PPM_IBUS - *1*
### Sub_protocol PWM_SBUS - *2*
### Sub_protocol PPM_SBUS - *3*
As stated above.
### Sub_protocol PWM_IBUS16 - *4*
3 additional channels. Need recent or updated RXs.
CH15|CH16|CH17
---|---|---
CH15|CH16|LQI
LQI: Link Quality Indicator
### Sub_protocol PPM_IBUS16 - *5*
### Sub_protocol PWM_SBUS16 - *6*
### Sub_protocol PPM_SBUS16 - *7*
3 additional channels. Need recent or updated RXs.
@@ -263,7 +262,7 @@ Sending trainer channels to FrSky radios through telemetry does not work since t
On a STM32 module and with a simple hardware modification, you can go around this limitation using CPPM to send the trainer information to the radio.
For more information check the [CCPM Hardware Modification](/docs/CPPM_HW_Mod.md) page.
Once your **setup** is **completed**, you **must check the "Disable Telemetry" box** to stop the Multi module from sending any data to the radio and therfore freeing up the line for the internal module.
Once your **setup** is **complete** and before enabling the internal module, you **must check the "Disable Telemetry" box** to stop the Multi module from sending any data to the radio and therfore freeing up the line for the internal module.
## HEIGHT - *53*
@@ -355,6 +354,19 @@ Models: TX: CADET 4 LITE
**Only 1 frequency hopping table**
### Sub_protocol SCX24 - *2*
TX: Axial AX-4 2.4GHz transmitter and Panda Hobby 3CH Smart Radio 2.4GHz (MT-305A)
Models: Axial SCX24: Deadbolt, Jeep Wranger Rubicon, Chevrolet 1967 C10, B-17 Betty and Panda Hobby: Tetra K1, X1, X2
**Only 2 frequency hopping tables**
Extended limits supported
CH1|CH2|CH3
---|---|---
STEERING|THROTTLE|CH3
## WFLY2 - *79*
Receivers: RF201S,RF206S,RF207S,RF209S
@@ -502,6 +514,9 @@ Notes:
Option=number of channels from 3 to 12. Option|0x80 enables Max Throw. Option|0x40 enables a servo refresh rate of 11ms.
Here is a table detailling the different RX output ranges based on the radio settings:
![Image](/docs/images/DSM_RX_Output.JPG)
### Sub_protocol DSM2_1F - *0*
DSM2, Resolution 1024, servo refresh rate can only be 22ms
### Sub_protocol DSM2_2F - *1*
@@ -513,6 +528,17 @@ DSMX, Resolution 2048, servo refresh rate can be 22 or 11ms. 11ms won't be avail
### Sub_protocol AUTO - *4*
"AUTO" is recommended to automatically select the best settings for your DSM RX.
### Sub_protocol DSMR_1F - *5*
DSMR receivers
**Only 22 IDs available**, use RX num to cycle through them.
Telemetry enabled, extended limits available.
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
STR|THR|AUX1|AUX2|AUX3|AUX4|AUX5
## DSM_RX - *70*
The DSM receiver protocol enables master/slave trainning, separate access from 2 different radios to the same model,...
@@ -535,11 +561,13 @@ Sending trainer channels to FrSky radios through telemetry does not work since t
On a STM32 module and with a simple hardware modification, you can go around this limitation using CPPM to send the trainer information to the radio.
For more information check the [CCPM Hardware Modification](/docs/CPPM_HW_Mod.md) page.
Once your **setup** is **completed**, you **must check the "Disable Telemetry" box** to stop the Multi module from sending any data to the radio and therfore freeing up the line for the internal module.
Once your **setup** is **complete** and before enabling the internal module, you **must check the "Disable Telemetry" box** to stop the Multi module from sending any data to the radio and therfore freeing up the line for the internal module.
## E010R5 - *81*
Models: E010 R5 red boards, JJRC H36, H36F and H36S
Not supported by Atmega328p modules.
Autobind protocol.
**Only 5 IDs are available**. Use RX num to cycle through them. More IDs can be added if you send me your "unused" original TX.
@@ -551,6 +579,8 @@ A|E|T|R|FLIP|LED|CALIB|HEADLESS|RTH|GLIDE
## E129 - *83*
Models: Eachine E129/E130 and Twister Ninja 250
Not supported by Atmega328p modules.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|Take off/Land|Emergency|Trim A|Trim E|Trim R
@@ -567,6 +597,17 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|----|----|----
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
## Losi - *89*
TX: LSR-3000
**Only 1 ID available**. More IDs can be added if you dump your original TX.
Extended limits supported
CH1|CH2|CH3
---|---|---
ST|THR|CH3
## MLINK - *78*
Extended limits supported
@@ -798,7 +839,7 @@ Sending trainer channels to FrSky radios through telemetry does not work since t
On a STM32 module and with a simple hardware modification, you can go around this limitation using CPPM to send the trainer information to the radio.
For more information check the [CCPM Hardware Modification](/docs/CPPM_HW_Mod.md) page.
Once your **setup** is **completed**, you **must check the "Disable Telemetry" box** to stop the Multi module from sending any data to the radio and therfore freeing up the line for the internal module.
Once your **setup** is **complete** and before enabling the internal module, you **must check the "Disable Telemetry" box** to stop the Multi module from sending any data to the radio and therfore freeing up the line for the internal module.
### Sub_protocol CloneTX - *1*
This subprotocol makes a clone of a TX identifier transmitting FrSkyD/D8, FrSkyX/D16 v1.xxx FCC/LBT and FrSkyX/D16 v2.1.0 FCC/LBT.
@@ -881,28 +922,6 @@ Recommended for best telemetry performance.
Telemetry compatibility mode when Sync does not work due to an old firmware on the RX.
You should definitively upgrade your receivers/sensors to the latest firmware versions: https://www.rcgroups.com/forums/showpost.php?p=44668015&postcount=18022
## OMP - *77*
Model: OMPHOBBY M1 & M2 Helis, T720 RC Glider
Telemetry is supported only if a NRF24L01 RF component is installed:
- A1 = battery voltage including "recovered" battery voltage from corrupted telemetry packets
- A2 = battery voltage from only good telemetry packets
- How to calculate accurately the OpenTX Ratio and Offset:
Set the Ratio to 12.7 and Offset to 0, plug 2 batteries with extreme voltage values, write down the values Batt1=12.5V & Telem1=12.2V, Batt2=7V & Telem2=6.6V then calculate/set Ratio=12.7*[(12.5-7)/(12.2-6.6)]=12.47 => 12.5 and Offset=12.5-12.2*[(12.5-7)/(12.2-6.6)]=0.517 => 0.5
- RX_RSSI = TQly = percentage of received telemetry packets (good and corrupted) from the model which has nothing to do with how well the RX is receiving the TX
Option for this protocol corresponds to the CC2500 fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T_PITCH|R|T_HOLD|IDLE|MODE
IDLE= 3 pos switch: -100% Normal, 0% Idle1, +100% Idle2
From the TX manual: MODE= 3 pos switch -100% Attitude, 0% Attitude(?), +100% 3D
For M2: MODE= 3 pos switch -100% 6G, 0% 3D, +100% 3D
## Scanner - *54*
2.4GHz scanner accessible using the OpenTX 2.3 Spectrum Analyser tool.
@@ -965,7 +984,7 @@ A|E|T|R|CH5|CH6|CH7
If a CC2500 is installed it will be used for all the below protocols. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
If only a NRF24L01 is installed then these protocols might be problematic because they are using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
If only a NRF24L01 is installed then these protocols might be problematic because they are using the XN297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
## GD00X - *47*
Model: GD005 C-17 Transport, GD006 DA62 and ZC-Z50
@@ -985,12 +1004,196 @@ First generation of GD models, ZC-Z50
New generation of GD models
## KF606 - *49*
Model: KF606
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A||T||TRIM
### Sub_protocol KF606 - *0*
Model: KF606
### Sub_protocol MIG320 - *1*
Model: Zhiyang MIG-320
## MJXQ - *18*
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14
---|---|---|---|---|---|---|---|---|----|----|----|----|----
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|AUTOFLIP|PAN|TILT|RATE
RATE: -100%(default)=>higher rates by enabling dynamic trims (except for Headless), 100%=>disable dynamic trims
CC2500: only E010 and PHOENIX are supported.
### Sub_protocol WLH08 - *0*
### Sub_protocol X600 - *1*
Only 3 TX IDs available, change RX_Num value 0..2 to cycle through them
### Sub_protocol X800 - *2*
Only 3 TX IDs available, change RX_Num value 0..2 to cycle through them
### Sub_protocol H26D - *3*
Only 3 TX IDs available, change RX_Num value 0..2 to cycle through them
### Sub_protocol E010 - *4*
15 TX IDs available, change RX_Num value 0..14 to cycle through them
If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
### Sub_protocol H26WH - *5*
CH6|
---|
ARM|
Only 1 TX ID available
### Sub_protocol PHOENIX - *6*
CH6|
---|
ARM|
If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
## MT99XX - *17*
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS
CC2500: only YZ is supported.
### Sub_protocol MT99 - *0*
Models: MT99xx
### Sub_protocol H7 - *1*
Models: Eachine H7, Cheerson CX023
### Sub_protocol YZ - *2*
Model: Yi Zhan i6S
Only one model can be flown at the same time since the ID is hardcoded.
If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
### Sub_protocol LS - *3*
Models: LS114, 124, 215
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|INVERT|PICTURE|VIDEO|HEADLESS
### Sub_protocol FY805 - *4*
Model: FY805
**Only 1 ID available**
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP||||HEADLESS
### Sub_protocol A180 - *5*
Model: XK A180
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A|E|T|R|3D6G
### Sub_protocol DRAGON - *6*
Model: Eachine Mini Wing Dragon
Telemetry is supported: A1 = battery voltage with a Ratio of 25.5, A2=battery low flag (0=off,>0=on) and RSSI = dummy value of 100
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|MODE|RTH
MODE: -100%=Beginner, 0%=Intermediate, +100%=Advanced
### Sub_protocol F949G - *7*
Model: F949G
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|6G3D|Light
## OMP - *77*
Model: OMPHOBBY M1 & M2 Helis, T720 RC Glider
If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
Telemetry is supported:
- A1 = battery voltage including "recovered" battery voltage from corrupted telemetry packets
- A2 = battery voltage from only good telemetry packets
- How to calculate accurately the OpenTX Ratio and Offset:
Set the Ratio to 12.7 and Offset to 0, plug 2 batteries with extreme voltage values, write down the values Batt1=12.5V & Telem1=12.2V, Batt2=7V & Telem2=6.6V then calculate/set Ratio=12.7*[(12.5-7)/(12.2-6.6)]=12.47 => 12.5 and Offset=12.5-12.2*[(12.5-7)/(12.2-6.6)]=0.517 => 0.5
- RX_RSSI = TQly = percentage of received telemetry packets (good and corrupted) from the model which has nothing to do with how well the RX is receiving the TX
Option for this protocol corresponds to the CC2500 fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T_PITCH|R|T_HOLD|IDLE|MODE
IDLE= 3 pos switch: -100% Normal, 0% Idle1, +100% Idle2
From the TX manual: MODE= 3 pos switch -100% Attitude, 0% Attitude(?), +100% 3D
For M2: MODE= 3 pos switch -100% 6G, 0% 3D, +100% 3D
## Q303 - *31*
Autobind protocol
CH1|CH2|CH3|CH4
---|---|---|---
A|E|T|R
CC2500: only Q303 is supported.
### Sub_protocol Q303 - *0*
If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---
AHOLD|FLIP|PICTURE|VIDEO|HEADLESS|RTH|GIMBAL
GIMBAL needs 3 position -100%/0%/100%
### Sub_protocol CX35 - *1*
CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---
ARM|VTX|PICTURE|VIDEO||RTH|GIMBAL
ARM is 2 positions: land / take off
Each toggle of VTX will increment the channel.
Gimbal is full range.
### Sub_protocol CX10D - *2*
Models CX10D and CX33W
CH5|CH6
---|---
ARM|FLIP
ARM is 3 positions: -100%=land / 0%=manual / +100%=take off
### Sub_protocol CX10WD - *3*
CH5|CH6
---|---
ARM|FLIP
ARM is 3 positions: -100%=land / 0%=manual / +100%=take off
## Q90C - *72*
CH1|CH2|CH3|CH4|CH5|CH6
@@ -1074,15 +1277,37 @@ MODE: -100% level, +100% acro
## V911S - *46*
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A|E|T|R|CALIB
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|CALIB|RATE
Rate: -100% High, +100% Low
### Sub_protocol V911S - *0*
Models: WLtoys V911S, XK A110
### Sub_protocol E119 - *1*
Models: Eachine E119
Models: Eachine E119, JJRC W01-J3
## XK - *62*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|----
A|E|T|R|Flight_modes|Take_off|Emerg stop|3D/6G|Picture|Video
Flight_modes: -100%=M-Mode, 0%=6G-Mode, +100%=V-Mode. CH6-CH10 are mementary switches.
CC2500: only X450 is supported.
### Sub_protocol X450 - *0*
Models: XK X450 (TX=X8)
If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
### Sub_protocol X420 - *1*
Models: XK X420/X520 (TX=X4)
***
# NRF24L01 RF Module
@@ -1165,7 +1390,7 @@ Sending trainer channels to FrSky radios through telemetry does not work since t
On a STM32 module and with a simple hardware modification, you can go around this limitation using CPPM to send the trainer information to the radio.
For more information check the [CCPM Hardware Modification](/docs/CPPM_HW_Mod.md) page.
Once your **setup** is **completed**, you **must check the "Disable Telemetry" box** to stop the Multi module from sending any data to the radio and therfore freeing up the line for the internal module.
Once your **setup** is **complete** and before enabling the internal module, you **must check the "Disable Telemetry" box** to stop the Multi module from sending any data to the radio and therfore freeing up the line for the internal module.
## BUGSMINI - *42*
Models: MJX Bugs 3 Mini and 3H
@@ -1283,6 +1508,15 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---|---|---|----|----
A|E|T|R|FLIP|LED|CAMERA1|CAMERA2|HEADLESS|RTH|RATE_LOW
## E016H - *85*
Autobind protocol
Model: Eachine E016H
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|STOP|FLIP|-|HEADLESS|RTH
## E01X - *45*
Autobind protocol
@@ -1304,13 +1538,6 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|ARM|FLIP|LED|HEADLESS|RTH
### Sub_protocol E016H - *2*
Models: Eachine E016H
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|STOP|FLIP|-|HEADLESS|RTH
## ESKY - *16*
CH1|CH2|CH3|CH4|CH5|CH6
@@ -1430,8 +1657,9 @@ A|E|T|R|DR|THOLD|IDLEUP|GYRO|Ttrim|Atrim|Etrim
Dual Rate: +100%=full range, Throttle Hold: +100%=hold, Idle Up: +100%=3D, GYRO: -100%=6G, +100%=3G
### Sub_protocol WLTOYS - *0*
Models: V966/V977/F959S/...
### Sub_protocol FEILUN - *1*
Same channels assignement as above.
## HONTAI - *26*
Autobind protocol
@@ -1490,92 +1718,35 @@ CH14| CH6 | -100% | 0% | | - | -
CH15| CH7 | -100% | 0% | - | - | +100%
CH16| CH8 | -100% | 0% | - | - | -
## MJXQ - *18*
Autobind protocol
## MouldKg - *90*
Mould King 2.4GHz TX: Technic Brick models
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14
---|---|---|---|---|---|---|---|---|----|----|----|----|----
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|AUTOFLIP|PAN|TILT|RATE
Up to 4 bricks can be controlled at the same time.
RATE: -100%(default)=>higher rates by enabling dynamic trims (except for Headless), 100%=>disable dynamic trims
Option field | Value
-------------|------
0|The module will act like the original radio which will bind every time and attach to the first brick in bind mode
1|The module will control the brick number RX_num
2|The module will control the brick number RX_num and RX_num+1
3|The module will control the brick number RX_num, RX_num+1 and RX_num+2
4|The module will control the brick number RX_num, RX_num+1, RX_num+2 and RX_num+3
### Sub_protocol WLH08 - *0*
### Sub_protocol X600 - *1*
Only 3 TX IDs available, change RX_Num value 0..2 to cycle through them
### Sub_protocol X800 - *2*
Only 3 TX IDs available, change RX_Num value 0..2 to cycle through them
### Sub_protocol H26D - *3*
Only 3 TX IDs available, change RX_Num value 0..2 to cycle through them
### Sub_protocol E010 - *4*
15 TX IDs available, change RX_Num value 0..14 to cycle through them
To associate a brick to a RX number (RX_num above), set this RX number under the protocol, set option to 1, launch a bind and power on the brick you want to control. Repeat this for every brick using a different RX number each time and then indicate the number of bricks to be comtrolled using the Option field.
If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
Example: I want to control 2 bricks. I select RX number 1, set option to 1 and launch a bind on the first brick. I select RX number 2, set option to 1 and launch a bind on the second brick. Now to control both bricks I set RX number to 1 and option to 2. Therefore brick1 will react to channels CH1 to CH4 and brick2 to channel CH5 to CH8.
On another model I can control 4 other bricks, bind each brick to RX number 3 to 6 and then finaly set RX number to 3 and option to 4 to contol the 4 bricks with CH1 to CH16.
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
### Sub_protocol Analog - *0*
### Sub_protocol H26WH - *5*
CH6|
---|
ARM|
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---
Brick1_A|Brick1_B|Brick1_C|Brick1_D|Brick2_A|Brick2_B|Brick2_C|Brick2_D|Brick3_A|Brick3_B|Brick3_C|Brick3_D|Brick4_A|Brick4_B|Brick4_C|Brick4_D
Only 1 TX ID available
### Sub_protocol Digit - *1*
### Sub_protocol PHOENIX - *6*
CH6|
---|
ARM|
## MT99XX - *17*
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS
### Sub_protocol MT99 - *0*
Models: MT99xx
### Sub_protocol H7 - *1*
Models: Eachine H7, Cheerson CX023
### Sub_protocol YZ - *2*
Model: Yi Zhan i6S
Only one model can be flown at the same time since the ID is hardcoded.
If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
### Sub_protocol LS - *3*
Models: LS114, 124, 215
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|INVERT|PICTURE|VIDEO|HEADLESS
### Sub_protocol FY805 - *4*
Model: FY805
**Only 1 ID available**
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP||||HEADLESS
### Sub_protocol A180 - *5*
Model: XK A180
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A|E|T|R|3D6G
### Sub_protocol DRAGON - *6*
Model: Eachine Mini Wing Dragon
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|MODE|RTH
MODE: -100%=Beginner, 0%=Intermediate, +100%=Advanced
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---
Brick1_A|Brick1_B|Brick1_C|Brick1_D|Brick2_A|Brick2_B|Brick2_C|Brick2_D|Brick3_A|Brick3_B|Brick3_C|Brick3_D|Brick4_A|Brick4_B|Brick4_C|Brick4_D
## NCC1701 - *44*
Model: Air Hogs Star Trek USS Enterprise NCC-1701-A
@@ -1632,52 +1803,6 @@ A|E|T|R|FLIP|LED|PICTURE|VIDEO|HEADLESS|RTH|XCAL|YCAL
Model: JXD 509 is using Q282 with CH12=Start/Stop motors
## Q303 - *31*
Autobind protocol
CH1|CH2|CH3|CH4
---|---|---|---
A|E|T|R
### Sub_protocol Q303 - *0*
If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---
AHOLD|FLIP|PICTURE|VIDEO|HEADLESS|RTH|GIMBAL
GIMBAL needs 3 position -100%/0%/100%
### Sub_protocol CX35 - *1*
CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---
ARM|VTX|PICTURE|VIDEO||RTH|GIMBAL
ARM is 2 positions: land / take off
Each toggle of VTX will increment the channel.
Gimbal is full range.
### Sub_protocol CX10D - *2*
Models CX10D and CX33W
CH5|CH6
---|---
ARM|FLIP
ARM is 3 positions: -100%=land / 0%=manual / +100%=take off
### Sub_protocol CX10WD - *3*
CH5|CH6
---|---
ARM|FLIP
ARM is 3 positions: -100%=land / 0%=manual / +100%=take off
## Realacc - *76*
Model: Realacc R11
@@ -1771,8 +1896,11 @@ A|E|T|R|FLIP|LIGHT
## V761 - *48*
Gyro: -100%=Beginer mode (Gyro on, yaw and pitch rate limited), 0%=Mid Mode ( Gyro on no rate limits), +100%=Mode Expert Gyro off
Calib: momentary switch, calib will happen one the channel goes from -100% to +100%
Flip: momentary switch: hold flip(+100%), indicate flip direction with Ele or Ail, release flip(-100%)
RTN_ACT and RTN: -100% disable, +100% enable
### Sub_protocol 3CH - *0*
@@ -1789,24 +1917,28 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|GYRO|CALIB|FLIP|RTN_ACT|RTN
## XERALL - *91*
Model: Xerall TankCopter
## XK - *62*
To bind/link the model faster put the throttle low before powering up the model.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|----
A|E|T|R|Flight_modes|Take_off|Emerg stop|3D/6G|Picture|Video
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13
---|---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|Fly/Tank|Takeoff/Land/Emerg|Rate|HeadLess|Photo|Video|TrimR|TrimE|TrimA
Flight_modes: -100%=M-Mode, 0%=6G-Mode, +100%=V-Mode. CH6-CH10 are mementary switches.
Fly/Tank: -100%=Fly, +100%=Tank
### Sub_protocol X450 - *0*
Models: XK X450 (TX=X8)
Takeoff/Land/Emerg: momentary switch -100%->+100%, same switch for all 3 functions. For Takeoff throttle must be centered before actionning the momentary switch. For Emergency stop hold the momentary switch for a few sec.
If a CC2500 is installed it will be used for this sub protocol. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
Unlock the motors is achieved like on the original radio by putting sticks in the bottom corners (position depends on your mode 1,2,3,4) and throttle has to be raised to center before recentering the sticks for the motors to keep spinning. Takeoff happens as soon as the throttle goes above center.
If only a NRF24L01 is installed then this sub protocol might be problematic because it is using the xn297L emulation with a transmission speed of 250kbps which doesn't work very well with every NRF24L01, this is an hardware issue with the authenticity and accuracy of the components.
Rate: -100%=Low, +100%=High
### Sub_protocol X420 - *1*
Models: XK X420/X520 (TX=X4)
HeadLess: -100%=Off, +100%=On
Photo: momentary switch -100%->+100% (short press on the original remote)
Video: -100%=Off, +100%=On (long press on the original remote)
## YD717 - *8*
Autobind protocol

View File

@@ -98,6 +98,8 @@ buildReleaseFiles(){
build_release_stm32f1_serial_debug;
elif [[ "$BOARD" == "multi4in1:STM32F1:multi5in1t18int" ]]; then
build_release_stm32f1_t18int;
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c8:debug_option=none" ]]; then
build_release_stm32f1_64k;
else
printf "No release files for this board.";
fi

View File

@@ -3,27 +3,27 @@
source ./buildroot/bin/buildFunctions;
exitcode=0;
printf "\e[33;1mBuilding multi-avr-usbasp-aetr-A7105-inv-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-avr-usbasp-aetr-A7105-inv-v$MULTI_VERSION.bin\e[0m\n";
opt_disable CHECK_FOR_BOOTLOADER;
opt_disable $ALL_PROTOCOLS;
opt_enable $A7105_PROTOCOLS;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-usbasp-aetr-A7105-inv-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-avr-usbasp-aetr-A7105-inv-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-avr-usbasp-aetr-CC2500-inv-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-avr-usbasp-aetr-CC2500-inv-v$MULTI_VERSION.bin\e[0m\n";
opt_disable $ALL_PROTOCOLS;
opt_enable $CC2500_PROTOCOLS;
opt_disable HITEC_CC2500_INO REDPINE_CC2500_INO OMP_CC2500_INO SKYARTEC_CC2500_INO SCANNER_CC2500_INO;
opt_disable HITEC_CC2500_INO REDPINE_CC2500_INO OMP_CC2500_INO SKYARTEC_CC2500_INO SCANNER_CC2500_INO FRSKYL_CC2500_INO;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-usbasp-aetr-CC2500-inv-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-avr-usbasp-aetr-CC2500-inv-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-avr-usbasp-aetr-CYRF6936-inv-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-avr-usbasp-aetr-CYRF6936-inv-v$MULTI_VERSION.bin\e[0m\n";
opt_disable $ALL_PROTOCOLS;
opt_enable $CYRF6936_PROTOCOLS;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-usbasp-aetr-CYRF6936-inv-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-avr-usbasp-aetr-CYRF6936-inv-v$MULTI_VERSION.bin;
exit $exitcode;

View File

@@ -3,27 +3,27 @@
source ./buildroot/bin/buildFunctions;
exitcode=0;
printf "\e[33;1mBuilding multi-avr-txflash-aetr-A7105-inv-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-avr-txflash-aetr-A7105-inv-v$MULTI_VERSION.bin\e[0m\n";
opt_enable CHECK_FOR_BOOTLOADER;
opt_disable $ALL_PROTOCOLS;
opt_enable $A7105_PROTOCOLS;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-txflash-aetr-A7105-inv-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-avr-txflash-aetr-A7105-inv-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-avr-txflash-aetr-CC2500-inv-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-avr-txflash-aetr-CC2500-inv-v$MULTI_VERSION.bin\e[0m\n";
opt_disable $ALL_PROTOCOLS;
opt_enable $CC2500_PROTOCOLS;
opt_disable HITEC_CC2500_INO REDPINE_CC2500_INO OMP_CC2500_INO SKYARTEC_CC2500_INO SCANNER_CC2500_INO;
opt_disable HITEC_CC2500_INO REDPINE_CC2500_INO OMP_CC2500_INO SKYARTEC_CC2500_INO SCANNER_CC2500_INO FRSKYL_CC2500_INO;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-txflash-aetr-CC2500-inv-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-avr-txflash-aetr-CC2500-inv-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-avr-txflash-aetr-CYRF6936-inv-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-avr-txflash-aetr-CYRF6936-inv-v$MULTI_VERSION.bin\e[0m\n";
opt_disable $ALL_PROTOCOLS;
opt_enable $CYRF6936_PROTOCOLS;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-txflash-aetr-CYRF6936-inv-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-avr-txflash-aetr-CYRF6936-inv-v$MULTI_VERSION.bin;
exit $exitcode;

View File

@@ -3,18 +3,18 @@
source ./buildroot/bin/buildFunctions;
exitcode=0;
printf "\e[33;1mBuilding multi-orangerx-aetr-green-inv-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-orangerx-aetr-green-inv-v$MULTI_VERSION.bin\e[0m\n";
opt_enable $ALL_PROTOCOLS;
opt_disable ORANGE_TX_BLUE;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-orangerx-aetr-green-inv-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-orangerx-aetr-green-inv-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-orangerx-aetr-blue-inv-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-orangerx-aetr-blue-inv-v$MULTI_VERSION.bin\e[0m\n";
opt_enable ORANGE_TX_BLUE;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-orangerx-aetr-blue-inv-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-orangerx-aetr-blue-inv-v$MULTI_VERSION.bin;
printf "\e[33;1mPackaging ancilliary files for v$MULTI_VERSION\e[0m\n";
cp Multiprotocol/Multi.txt ./binaries/Multi.txt;

View File

@@ -0,0 +1,31 @@
#!/usr/bin/env bash
source ./buildroot/bin/buildFunctions;
exitcode=0;
# CC2500-only 64Kb builds
printf "\e[33;1mBuilding mm-stm-cc2500-64-aetr-v$MULTI_VERSION.bin\e[0m\n";
opt_enable $ALL_PROTOCOLS;
opt_disable IKEAANSLUTA_CC2500_INO;
opt_disable ENABLE_PPM;
opt_disable A7105_INSTALLED;
opt_disable CYRF6936_INSTALLED;
opt_disable NRF24L01_INSTALLED;
opt_disable INVERT_TELEMETRY;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-cc2500-64-aetr-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding mm-stm-cc2500-64-taer-v$MULTI_VERSION.bin\e[0m\n";
opt_replace AETR TAER;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-cc2500-64-taer-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding mm-stm-cc2500-64-reta-v$MULTI_VERSION.bin\e[0m\n";
opt_replace TAER RETA;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-cc2500-64-reta-v$MULTI_VERSION.bin;
exit $exitcode;

View File

@@ -3,11 +3,11 @@
source ./buildroot/bin/buildFunctions;
exitcode=0;
printf "\e[33;1mBuilding multi-stm-xn297dump-usbdebug-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-stm-xn297dump-usbdebug-v$MULTI_VERSION.bin\e[0m\n";
opt_disable $ALL_PROTOCOLS;
opt_add XN297DUMP_NRF24L01_INO;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-xn297dump-usbdebug-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-xn297dump-usbdebug-v$MULTI_VERSION.bin;
exit $exitcode;

View File

@@ -3,69 +3,75 @@
source ./buildroot/bin/buildFunctions;
exitcode=0;
# Builds for the DIY 5-in-1 module exceed the 120KB working capacity of the STM32F103CB
# To work around this we have to disable some protocols in the builds for this module
#DIY_5IN1_DISABLED="MOULDKG_NRF24L01_INO";
# Generic 4-in-1 builds
printf "\e[33;1mBuilding multi-stm-serial-aetr-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-stm-serial-aetr-v$MULTI_VERSION.bin\e[0m\n";
opt_disable ENABLE_PPM;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-serial-aetr-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-serial-aetr-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-serial-taer-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-stm-serial-taer-v$MULTI_VERSION.bin\e[0m\n";
opt_replace AETR TAER;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-serial-taer-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-serial-taer-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-serial-reta-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-stm-serial-reta-v$MULTI_VERSION.bin\e[0m\n";
opt_replace TAER RETA;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-serial-reta-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-serial-reta-v$MULTI_VERSION.bin;
# DIY 5-in-1 builds
printf "\e[33;1mBuilding multi-stm-5in1-aetr-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-stm-5in1-aetr-v$MULTI_VERSION.bin\e[0m\n";
opt_replace RETA AETR;
#opt_disable $DIY_5IN1_DISABLED;
opt_enable SX1276_INSTALLED;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-5in1-aetr-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-5in1-aetr-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-5in1-taer-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-stm-5in1-taer-v$MULTI_VERSION.bin\e[0m\n";
opt_replace AETR TAER;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-5in1-taer-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-5in1-taer-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-5in1-reta-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-stm-5in1-reta-v$MULTI_VERSION.bin\e[0m\n";
opt_replace TAER RETA;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-5in1-reta-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-5in1-reta-v$MULTI_VERSION.bin;
# T-Lite 5-in-1 builds
printf "\e[33;1mBuilding multi-tlite5in1-aetr-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-tlite5in1-aetr-v$MULTI_VERSION.bin\e[0m\n";
opt_replace RETA AETR;
opt_disable INVERT_TELEMETRY;
opt_disable SX1276_INSTALLED;
#opt_enable $DIY_5IN1_DISABLED;
opt_enable "MULTI_5IN1_INTERNAL JP_TLite"
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-tlite5in1-aetr-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-tlite5in1-aetr-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-tlite5in1-taer-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-tlite5in1-taer-v$MULTI_VERSION.bin\e[0m\n";
opt_replace AETR TAER;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-tlite5in1-taer-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-tlite5in1-taer-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-tlite5in1-reta-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-tlite5in1-reta-v$MULTI_VERSION.bin\e[0m\n";
opt_replace TAER RETA;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-tlite5in1-reta-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-tlite5in1-reta-v$MULTI_VERSION.bin;
# CC2500-only builds
printf "\e[33;1mBuilding multi-stm-cc2500-aetr-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-stm-cc2500-aetr-v$MULTI_VERSION.bin\e[0m\n";
opt_replace RETA AETR;
opt_disable "MULTI_5IN1_INTERNAL JP_TLite"
opt_disable A7105_INSTALLED;
@@ -74,22 +80,22 @@ opt_disable NRF24L01_INSTALLED;
opt_disable INVERT_TELEMETRY;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-cc2500-aetr-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-cc2500-aetr-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-cc2500-taer-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-stm-cc2500-taer-v$MULTI_VERSION.bin\e[0m\n";
opt_replace AETR TAER;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-cc2500-taer-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-cc2500-taer-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-cc2500-reta-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-stm-cc2500-reta-v$MULTI_VERSION.bin\e[0m\n";
opt_replace TAER RETA;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-cc2500-reta-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-cc2500-reta-v$MULTI_VERSION.bin;
# 4-in-1 PPM builds
printf "\e[33;1mBuilding multi-stm-ppm-aetr-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-stm-ppm-aetr-v$MULTI_VERSION.bin\e[0m\n";
opt_enable A7105_INSTALLED;
opt_enable CYRF6936_INSTALLED;
opt_enable NRF24L01_INSTALLED;
@@ -101,18 +107,18 @@ opt_disable MULTI_TELEMETRY;
opt_set NBR_BANKS 5;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-ppm-aetr-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-ppm-aetr-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-ppm-taer-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-stm-ppm-taer-v$MULTI_VERSION.bin\e[0m\n";
opt_replace AETR TAER;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-ppm-taer-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-ppm-taer-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-ppm-reta-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-stm-ppm-reta-v$MULTI_VERSION.bin\e[0m\n";
opt_replace TAER RETA;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-ppm-reta-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-ppm-reta-v$MULTI_VERSION.bin;
exit $exitcode;

View File

@@ -3,11 +3,11 @@
source ./buildroot/bin/buildFunctions;
exitcode=0;
printf "\e[33;1mBuilding multi-stm-xn297dump-ftdidebug-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-stm-xn297dump-ftdidebug-v$MULTI_VERSION.bin\e[0m\n";
opt_disable $ALL_PROTOCOLS;
opt_add XN297DUMP_NRF24L01_INO;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-xn297dump-ftdidebug-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-stm-xn297dump-ftdidebug-v$MULTI_VERSION.bin;
exit $exitcode;

View File

@@ -3,23 +3,23 @@
source ./buildroot/bin/buildFunctions;
exitcode=0;
printf "\e[33;1mBuilding multi-t18int-aetr-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-t18int-aetr-v$MULTI_VERSION.bin\e[0m\n";
opt_disable ENABLE_PPM;
opt_disable INVERT_TELEMETRY;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-t18int-aetr-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-t18int-aetr-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-t18int-taer-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-t18int-taer-v$MULTI_VERSION.bin\e[0m\n";
opt_replace AETR TAER;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-t18int-taer-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-t18int-taer-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-t18int-reta-v$MULTI_VERSION.bin\e[0m\n";
printf "\e[33;1mBuilding mm-t18int-reta-v$MULTI_VERSION.bin\e[0m\n";
opt_replace TAER RETA;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-t18int-reta-v$MULTI_VERSION.bin;
mv build/Multiprotocol.ino.bin ./binaries/mm-t18int-reta-v$MULTI_VERSION.bin;
exit $exitcode;

View File

@@ -36,3 +36,4 @@ For the hardware modification you need:
![Image](/docs/images/CPPM_JP4IN1_Mark.jpg)
![Image](/docs/images/CPPM_JP4IN1_Soldered.jpg)
![Image](/docs/images/CPPM_JP4IN1_Soldered2.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB