Compare commits

...

382 Commits

Author SHA1 Message Date
Pascal Langer
1c632d462f Update Protocols_Details.md 2020-05-23 22:53:53 +02:00
Pascal Langer
c46b49ccf1 HoTT: cleanup 2020-05-23 22:41:07 +02:00
Pascal Langer
e70708b133 FrSkyX: push more parts to common 2020-05-23 22:39:26 +02:00
Konstantin Tretyakov
62486c2220 JJRC345: Reduce stick sensitivity (#355)
A largely symbolic contribution to record participation in protocol development.
See: https://github.com/DeviationTX/deviation/pull/853
2020-05-23 00:09:46 +02:00
Pascal Langer
cffe66747a JJRC345: last commit 2020-05-22 21:03:01 +02:00
Pascal Langer
b31bbfa04f JJRC345: Change checksum calculation 2020-05-21 23:40:23 +02:00
Pascal Langer
48e4cad3ad JJRC345: add RTH on CH7 2020-05-21 17:49:04 +02:00
Pascal Langer
53f58ce2e1 JJRC345: update 2020-05-21 17:24:11 +02:00
Pascal Langer
eb8b5eac01 JJRC345: update channels range 2020-05-21 11:56:08 +02:00
Pascal Langer
02008a8b2e New protocol JJRC345: WIP
Work in progress
2020-05-21 11:47:51 +02:00
Pascal Langer
5b82599eb9 Update Protocols_Details.md 2020-05-20 12:23:37 +02:00
Pascal Langer
a5e4b2c6fa DSM RX: Fix compilation 2020-05-18 01:30:52 +02:00
Pascal Langer
987753ff73 DSM and DSM RX: fix bind 2020-05-18 01:13:08 +02:00
Pascal Langer
ee080839b1 Update DSM_Rx_cyrf6936.ino 2020-05-17 17:26:43 +02:00
Pascal Langer
4290c75478 HoTT: support for auto sensors discovery and sensors text config 2020-05-17 15:47:56 +02:00
Pascal Langer
cc6be6027d New DSM RX protocol 2020-05-17 15:45:23 +02:00
Pascal Langer
4cfde0a80a Update Protocols_Details.md 2020-05-10 13:41:14 +02:00
Pascal Langer
a77aee0e1a Update Protocols_Details.md 2020-05-09 16:11:36 +02:00
Pascal Langer
6f36473975 Devo basic telemetry 2020-05-09 16:11:10 +02:00
pascallanger
f5720d38bb Update Flash_from_Tx.md 2020-05-09 09:10:09 +02:00
pascallanger
23478d3d21 Update Protocols_Details.md 2020-05-08 22:50:52 +02:00
Pascal Langer
ba72b6dedd eSky150v2 last minute typo... 2020-05-08 20:01:33 +02:00
Pascal Langer
103f595891 New protocol eSky 150 v2
Protocol: 69
No sub protocol
No extended limit
RX outputs is be set automatically to the eSky default TAER
16 channels
2020-05-08 19:55:16 +02:00
Pascal Langer
957d623b4b FrSky D16 LBT v1.x & 2.1: adjust thresholds to match ETSI requirements 2020-05-02 18:20:47 +02:00
Pascal Langer
2be757e609 Skyartec: small changes 2020-04-22 15:02:06 +02:00
Pascal Langer
c4be660a05 Skyartec: activate cc2500 rf tune 2020-04-21 18:27:15 +02:00
Pascal Langer
c1c5f9fe3a Hide Proto Scanner 2020-04-21 12:15:53 +02:00
Pascal Langer
53c0637a85 Fix a bug introduced with Alpha protocols ordering 2020-04-21 11:43:48 +02:00
Pascal Langer
4ae30dc3b0 New protocol: Skyartec 2020-04-18 19:04:38 +02:00
Pascal Langer
fc5fbc9899 Multi_Names update for OpenTX 2020-04-16 17:03:17 +02:00
Pascal Langer
2397bf365b Update Multi_Names.ino 2020-04-16 13:52:10 +02:00
Pascal Langer
42cd17d5f2 Multi Names: if proto invalid give first available proto 2020-04-16 12:07:19 +02:00
Pascal Langer
a35e01bbeb Update Protocols_Details.md 2020-04-15 11:23:40 +02:00
Pascal Langer
b21e8030b3 Fix independant protocols build 2020-04-15 01:30:06 +02:00
Pascal Langer
0984a42fe5 Update Protocols_Details.md 2020-04-13 22:42:41 +02:00
Pascal Langer
ed50d60108 Update Protocols_Details.md 2020-04-13 22:41:37 +02:00
Pascal Langer
a7f72a73e5 Update Protocols_Details.md 2020-04-13 22:31:26 +02:00
Pascal Langer
1c02cb46f5 FrSky Clone mode
Check documentation for full details: https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/Protocols_Details.md#FRSKY_RX---55
2020-04-13 22:10:58 +02:00
Pascal Langer
da8fd21177 Update FrSkyL_cc2500.ino 2020-04-11 20:17:02 +02:00
Pascal Langer
7e5cd9819a New protocol FrSkyL: LR12
Model: L9R RX
2 sub protocols: LR12 and LR12_6CH
2020-04-11 20:09:32 +02:00
Pascal Langer
00aecb3ab1 Update Protocols_Details.md 2020-04-10 19:38:49 +02:00
Pascal Langer
cde77a88fd FrSkyRX: added sub_protocol, documentation and more 2020-04-10 19:32:50 +02:00
E1yot
08a555f187 Initial Version of CloneMode (#342)
* Initial Version

* Bugfix and change of the handling of the RX Num.

If RX Num is 63, write a finetune value of 127 to the EEPROM.
A real finetune value of 127 means, the frequency of module is out of range and
the module should be replaced. This way the clone mode should not get unwanted
active by a module with a frequency drift arround 63.
2020-04-10 19:01:01 +02:00
Pascal Langer
4039cbf8af Small corrections 2020-04-07 10:55:54 +02:00
Pascal Langer
3f652fa06c FrSkyX: improve SPort to RX code 2020-04-07 01:43:05 +02:00
Pascal Langer
272d2be3ae Update FrSky_Rx_cc2500.ino 2020-04-05 16:05:51 +02:00
Pascal Langer
7e461344a8 Update Protocols_Details.md 2020-04-05 10:46:26 +02:00
Pascal Langer
8af985a2cb FrSkyRX: check additional ID and use RX num 2020-04-05 10:44:09 +02:00
Pascal Langer
08eee34446 Protocol PROPEL: enhanced telemetry 2020-04-05 09:39:33 +02:00
Pascal Langer
0a5b97a177 New Protocol: PROPEL
Compatible model: PROPEL 74-Z Speeder Bike
Protcol: PROPEL (66)
Sub protocol: none
Autobind protocol
Extended limits not supported
Telemetry supported
14 channels in use due to many features
2020-04-03 19:36:05 +02:00
Bryce Johnson
cab782b38e redpine updates to make released betaflight and deviation builds (#341)
Co-authored-by: Bryce Johnson <bryce@redpinelabs.com>
2020-04-02 12:39:26 +02:00
pascallanger
d1518d763b Add files via upload 2020-03-30 21:22:12 +02:00
Pascal Langer
44a676b809 Update Multiprotocol.h 2020-03-30 18:22:13 +02:00
Pascal Langer
d66709ea87 Update Protocols_Details.md 2020-03-29 19:23:28 +02:00
Pascal Langer
358a77cf7c Update Protocols_Details.md 2020-03-29 19:15:32 +02:00
Pascal Langer
1a631908f4 Update FrSky_Rx_cc2500.ino 2020-03-29 19:09:56 +02:00
Pascal Langer
9f32a1f22b FrSkyRX protocol: chanskip test 2020-03-29 18:49:37 +02:00
Pascal Langer
dfd3386319 FrSkyX v2.1: initial support
Rewrite of the FrSkyX code to support both v1 and v2.1.0 with FCC and LBT.
FrSky v1 accessible as usual
FrSky v2.1.0 accessible through the protocol 64=FrSkyX2 with the same subprotocols as v1
The LBT feature is now fully implemented on the TX and turned on for both v1 LBT and v2.1.0 LBT.
For v2.1.0, to access the bind functions Telem=on/off, CH1-8/9-16 and bidirectional SPort (SxR setup for example), you need to update OpenTX to the latest 2.3.8 nightly (not available yet).
2020-03-29 18:44:03 +02:00
Pascal Langer
3df836e6b8 Hitec: fix a bind issue 2020-03-21 19:00:40 +01:00
Pascal Langer
2b8ed25843 FrSkyD: Change hopping frequencies
WARNING: all receivers must be rebound !!!
2020-03-21 15:17:46 +01:00
Pascal Langer
62250d2f25 ESky: addition of sub-protocol ET4 2020-03-21 15:16:01 +01:00
Pascal Langer
a4e9082f53 SLT CC2500 fix 2020-02-20 17:37:58 +01:00
Pascal Langer
7217e8c41d SLT: fix? 2020-02-18 15:50:54 +01:00
Pascal Langer
a7ac093753 SLT: CC2500 fix 2020-02-17 16:44:02 +01:00
Pascal Langer
5503502bad SLT: fix going from NRF to CC2500 2020-02-17 13:10:57 +01:00
Pascal Langer
5124c2a96d SLT: use the CC2500 emulation layer if requested/available 2020-02-17 11:45:28 +01:00
Pascal Langer
73d7728e08 Change CC2500 emulation layer to support NRF24L01 @250K 2020-02-17 11:44:53 +01:00
Pascal Langer
8b7bd00a48 Update Multi.txt 2020-02-16 20:48:49 +01:00
Pascal Langer
68a6af0eb5 Update E119 channels and flags
Default is high rate
CH5 is calib
2020-02-16 20:18:02 +01:00
Pascal Langer
693f9f58eb V911S: new sub protocol E119
Model: Eachine E119
Protocol: V911S -> 46
Sub protocol: E119 -> 1
CH5: left button ???
CH6: right button ???
2020-02-16 20:05:29 +01:00
Tomer Abramovich
4a01e2d472 missed the last 3 bytes here, loop should continue one more time (#322) 2020-01-24 21:09:37 +01:00
pascallanger
e4fd1f4399 FrSkyR9: 16 channels 2020-01-24 14:59:26 +01:00
pascallanger
0d5fcb0849 FrskyR9 protocol 2020-01-24 12:12:07 +01:00
pascallanger
2236c256ba Merge pull request #320 from UnTraDe/master
initial working version of R9M, 8 CH and BINDING support only
2020-01-24 10:12:19 +01:00
Tomer Abramovich
945ad2e7bd now using FrSkyX_scaleForPXX to scale channel values for FrSky R9 instead of using floating point math 2020-01-23 22:29:57 +02:00
Tomer Abramovich
6f9740f03f moved register definitions to a different file and created higher level functions for using them; added preliminary support for 868 MHz mode, not fully working yet 2020-01-23 22:25:00 +02:00
pascallanger
f9fa4dff73 Update _Config.h 2020-01-22 16:11:42 +01:00
Tomer Abramovich
77bf17967d initial working version of R9M, 8 CH and BINDING support only 2020-01-21 17:42:33 +02:00
pascallanger
7281c0b5bf Comment FRSKYX2 protocol for now 2020-01-21 10:51:07 +01:00
pascallanger
e6cab65560 Fix paranthesis... 2020-01-21 10:29:11 +01:00
pascallanger
cc115323e1 Prep for FrSky X v2 2020-01-20 23:52:17 +01:00
Ben Lye
58665ea7a7 Bubble up errors in release builds 2020-01-17 21:37:16 +00:00
Ben Lye
3920644caf Reduce protocols for debug test builds.
Make the debug builds small enough to pass the buildDefault test.
2020-01-17 21:37:16 +00:00
pascallanger
25aecbf15e XK full ID to address and hop freqs generation 2020-01-16 23:43:29 +01:00
pascallanger
e18d8868d2 Protocol Pelikan: hop freq change with RX_num 2020-01-15 16:28:03 +01:00
pascallanger
c6e5d00a2b Protocol Pelikan: fix rx_tx_addr[1]... 2020-01-14 23:00:50 +01:00
pascallanger
7a5b4dea1a XK X420/X520: 2 valid IDs
IDs are selected using RX num.
2020-01-14 22:51:47 +01:00
pascallanger
5df877f32c Protocol XK X420: Changed bitrate to 1Mbps 2020-01-14 22:05:30 +01:00
pascallanger
c5c7dda2e0 Update XK X420 channel order
Change channel order
Add CH140 for video
2020-01-14 21:25:43 +01:00
pascallanger
492b9e5ed4 New protocol XK
Still work in progress
Subprotocols: X450 and X420 -> not sure if they are subprotocols or just different IDs...
CH5: M-Mode=-100%, 6G-Mode=0%, V-Mode=+100%
CH6: Take off momentary switch
CH7: Emergency stop momentary switch
CH8: 3D/6G momentary switch
CH9: Photo momentary switch
2020-01-14 12:19:12 +01:00
pascallanger
9f721c528d Bayang: rewritten the protocol to be more friendly with main scheduler 2020-01-12 19:42:51 +01:00
pascallanger
7f3c80c2a9 Fix DSM invalid protocol when binding 2020-01-12 18:18:47 +01:00
pascallanger
8f789607e4 Pelikan: add some hopping frequencies 2020-01-12 17:38:30 +01:00
pascallanger
6a9b6ed4be XN297EMU: option=0->nrf24L01, option!=0 -> CC2500
XN297L@250kbps is emulated by default with the NRF24L01. If option (freq tune) is diffrent from 0, the CC2500 module (if installed) will be used instead with option being the freq usual tuning.
2020-01-12 14:06:27 +01:00
pascallanger
953a97dae4 Flyzone: add channel 5 2020-01-12 13:17:17 +01:00
pascallanger
86778c5997 XN297Dump: new auto mode
Automatically:
 - find XN297L packet -> bitrate, scrambling, enhanced...
 - use address to filter incoming packets
 - find all frequencies
 - determine channel order (basic)
 - help to find out the changes by only displaying packets when there is a change in the packet
2020-01-12 13:16:30 +01:00
pascallanger
8c32cdf5fd Pelikan: fix TX and multi ID
Still 1 hopping freq table
2020-01-12 13:00:30 +01:00
pascallanger
d092593e5c Fix FrSky RX bind which could fail if another TX was around 2020-01-12 12:57:16 +01:00
pascallanger
edbf4b6908 Merge pull request #311 from benlye/multi-status-fix
Fix module status on erSkyTX
2020-01-11 10:20:03 +01:00
Ben Lye
43f688d011 Fix module status on erSkyTX 2020-01-10 18:25:56 +00:00
pascallanger
054c3088c3 Merge pull request #305 from Shkolik/Direct_inputs
Direct inputs
2020-01-02 17:29:45 +01:00
Andrew Shkolik
0cedd5bb66 disable myConfig 2019-12-30 16:53:12 -06:00
Andrew Shkolik
1961579fe4 code cleanup 2019-12-30 15:44:16 -06:00
Andrew Shkolik
6906f1652e Inputs logic added 2019-12-24 23:41:04 -06:00
Andrew Shkolik
e2bbe8a422 definitions for direct inputs 2019-12-24 15:03:35 -06:00
pascallanger
8ea4e00d31 Pelikan protocol fix ? 2019-12-20 15:43:44 +01:00
pascallanger
917e27280f Pelikan and Tiger protocol fixes 2019-12-20 09:29:37 +01:00
pascallanger
ec92edfc85 New protocol Tiger
Model: Tiger drone 1400782
Protocol number: 61
No sub_protocol
CH5: Flip
CH6: Light
2019-12-19 23:40:33 +01:00
pascallanger
afd2be6c59 New Pelikan protocol
Protocol number: 60
No sub proto
8 channels AETR...
Extended limit supported
!!Only 1 ID for now!!
2019-12-19 22:39:01 +01:00
pascallanger
a23d50bf0d FrSkyX add bind options CH1-8/CH9-16 & Telem ON/OFF 2019-12-19 17:26:47 +01:00
pascallanger
cace1144db Add TX_LQI (TLQY) comment 2019-12-09 10:47:17 +01:00
pascallanger
0d646ed1a6 Update Protocols_Details.md 2019-12-05 17:14:26 +01:00
pascallanger
e9b09ffecd Update Protocols_Details.md 2019-12-04 10:58:40 +01:00
pascallanger
0008633d6e Bayang RX: Sync 2019-11-30 12:11:08 +01:00
pascallanger
396c005b0a BAYANG RX: enables 6 analog channels
Fix channels range -100%..+100%
2019-11-29 20:26:10 +01:00
pascallanger
d3c3fac4f7 Multi_names mandatory when using multi_telemetry
Validate that sub_proto is valid for the current protocol
Validate that disable channel mapping is valid for the current protocol
2019-11-29 18:50:57 +01:00
pascallanger
cf4acc1d4c Bayang RX: fix warnings 2019-11-29 18:46:24 +01:00
pascallanger
5bd95f8414 Merge pull request #300 from goebish/protocol_bayang_rx
Protocol Bayang rx
2019-11-29 16:37:13 +01:00
Goebish
a31d9a83a3 Use table for channel mapping 2019-11-29 14:26:59 +01:00
Goebish
9b24589897 Fix linefeeds 2019-11-29 14:24:23 +01:00
Goebish
8f3d634132 Fix documentation tag 2019-11-29 14:21:58 +01:00
Goebish
5ef1ccb99b Update protocol details 2019-11-29 13:36:36 +01:00
Goebish
e7d91bc76a Update protocol details 2019-11-29 12:10:56 +01:00
Goebish
e4309824c2 Add missing stuffs 2019-11-29 11:57:06 +01:00
Goebish
cc6a35ac8a Fix channel count 2019-11-29 02:53:19 +01:00
Goebish
1f13a6c281 Add Bayang RX protocol 2019-11-29 02:06:58 +01:00
Goebish
69519bdf14 Add skeleton for Bayang RX protocol 2019-11-28 20:02:59 +01:00
Ben Lye
2e5a8f384a Add '-inv-' to file names for the xn297dump builds 2019-11-28 18:59:40 +00:00
pascallanger
c803eeb26a Esky150: add sub protocols 4CH and 7CH 2019-11-28 17:01:33 +01:00
pascallanger
6a7497cdf8 Update FX816_nrf24l01.ino 2019-11-27 12:24:49 +01:00
pascallanger
3067ea3a5c New protocol: FX816
Model P38
Protocol number: 58
Sub protocol: None
Channels: A & T
2019-11-27 12:12:13 +01:00
pascallanger
9a5309d84b V911S: revert to nrf24l01 2019-11-27 12:10:49 +01:00
pascallanger
fff18f825a DSM: change timing to see if it improves long range telemetry RX range 2019-11-27 12:08:17 +01:00
Ben Lye
e70bdd4152 Update .travis.yml
Put the 'v' back in the version number in the file names
2019-11-26 09:28:45 +00:00
Ben Lye
cf77a1981f Travis CI test changes (#297) 2019-11-26 07:51:00 +00:00
pascallanger
10e33f5d5c Update _Config.h 2019-11-21 08:49:39 +01:00
pascallanger
db442d81dd Fix all compilation issues (?) 2019-11-11 19:15:39 +01:00
pascallanger
f800b4f90b Merge pull request #291 from pascallanger/SPort_Send
New features
2019-11-11 17:30:26 +01:00
pascallanger
712f297d86 Update _Config.h 2019-11-11 17:19:27 +01:00
pascallanger
0afed7d3a4 Fix HoTT menu for internal module 2019-11-11 15:36:39 +01:00
pascallanger
6a03972ff3 Update Protocols_Details.md 2019-11-10 19:34:31 +01:00
pascallanger
0e40f64c6b Enable HoTT RX config menu
Use OpenTX lua script
2019-11-10 18:55:03 +01:00
pascallanger
c83b769f28 Update Multiprotocol.ino 2019-11-10 09:25:42 +01:00
pascallanger
dad3282bbb XN297Dump RF channel display 2019-11-09 19:26:31 +01:00
pascallanger
1621263fb0 HoTT telem doc update 2019-11-09 12:10:56 +01:00
pascallanger
2686cd0c48 Scanner in blocking mode for best perf 2019-11-09 12:10:34 +01:00
pascallanger
b07b081a15 HoTT telemetry size change 2019-11-07 11:13:48 +01:00
pascallanger
c5d4e8c191 Failsafe improvement 2019-11-07 02:30:03 +01:00
pascallanger
928641f535 HoTT: add progmem to tables 2019-11-07 01:56:13 +01:00
pascallanger
c4c5ffec4f HoTT: Failsafe
Failsafe MUST be configured once with the desired channel values (hold or position) while the RX is up (wait 10+sec for the RX to learn the config) and then failsafe MUST be set to RX/Receiver otherwise the servos will jitter!!!
2019-11-07 01:03:57 +01:00
pascallanger
c048e97d3a DSM configurable max throw parameter through option 2019-11-05 19:12:06 +01:00
pascallanger
00f0719659 HoTT: more hop tables 2019-11-05 19:11:28 +01:00
pascallanger
0482627512 HoTT telem 2019-11-05 00:31:20 +01:00
pascallanger
5856442e0f First HoTT version 2019-11-04 19:16:19 +01:00
pascallanger
7b281e47d6 HoTT work in progress 2019-11-04 09:26:12 +01:00
pascallanger
6ef2934c18 Update Telemetry.ino 2019-11-03 15:48:14 +01:00
pascallanger
19b931223b Changed serial timer source 2019-11-03 15:46:05 +01:00
pascallanger
ca15d7108f Prep for HoTT protocol and fix STM32 seed 2019-11-02 20:51:41 +01:00
pascallanger
e6e4d33847 Few changes... 2019-11-02 18:13:47 +01:00
pascallanger
815cf4fd99 FrSky X telemetry quick fix 2019-11-01 18:42:45 +01:00
pascallanger
5cf2bf2cf5 Small tweaks 2019-11-01 15:11:31 +01:00
pascallanger
6632da0276 Fix link 2019-11-01 14:52:50 +01:00
pascallanger
9b499ab7d1 Fix (?) protocol issues 2019-10-31 23:33:10 +01:00
pascallanger
d29461607b Tweakes 2019-10-29 00:36:57 +01:00
pascallanger
243bdf2240 Merge branch 'master' into SPort_Send 2019-10-29 00:02:59 +01:00
pascallanger
cde185901a PPM protcols: remove warning when setting negative option values 2019-10-28 23:29:34 +01:00
pascallanger
a9f35f8095 Update _Config.h 2019-10-27 17:05:02 +01:00
pascallanger
63d7e32e06 INVERT_TELEMETRY_TX flag 2019-10-27 17:02:38 +01:00
pascallanger
400fdb3cc6 FrSkyX LBT RSSI timing improvement 2019-10-27 16:44:36 +01:00
pascallanger
9f1bdc901c FrSkyX LBT: implement LBT instead of transmitting all the time
Needs to be activated using FRSKYX_LBT for now.
2019-10-27 13:20:53 +01:00
pascallanger
61970b028e AFHDS2A: Fix LQI to channel 2019-10-26 15:40:46 +02:00
pascallanger
aee92737ca Fix Failsafe compilation 2019-10-25 22:27:46 +02:00
pascallanger
0fddd9c119 Fix AFHDS2A RX_LQI forward on CH
Hopefully...
2019-10-25 22:03:39 +02:00
pascallanger
b156f66146 Fix Failsafe compilation 2019-10-25 21:35:25 +02:00
pascallanger
63e6590b65 Merge branch 'master' into SPort_Send 2019-10-20 15:48:18 +02:00
pascallanger
103be7f6e0 Update Protocols_Details.md 2019-10-18 18:08:42 +02:00
pascallanger
2154b75499 Fix MULTI_NAMES len... 2019-10-17 22:35:43 +02:00
goebish
6a83cb5577 Frsky rx fixes (#289)
* Restore previous cc2500 register init

* Fix failsafe packets locks

* Fix D8 checksum check
2019-10-17 16:59:08 +02:00
pascallanger
70ce8e9a1f Fix SLT inversion 2019-10-17 16:56:15 +02:00
pascallanger
fdd0a00d5a Correct option value for FrSky protocols 2019-10-17 11:38:23 +02:00
pascallanger
a8cad1e70a Move optionDisp to Data[19] 2019-10-17 09:41:20 +02:00
pascallanger
40afd67fc6 Disable MULTI_SYNC when using RX or Scanner protocols 2019-10-16 20:18:24 +02:00
pascallanger
f3b9206d67 Merge branch 'master' into SPort_Send 2019-10-16 18:54:43 +02:00
pascallanger
b76dd4c8ac Update Compiling_STM32.md 2019-10-16 12:18:15 +02:00
pascallanger
3eb507ebe6 Update Compiling_STM32.md 2019-10-16 12:17:40 +02:00
pascallanger
fe0a1f0f94 Create T16-internal-connection.png 2019-10-16 11:30:45 +02:00
pascallanger
fab3339b8d Update Compiling_STM32.md 2019-10-16 10:49:42 +02:00
pascallanger
10604cf820 Create T16-internal-connector.png 2019-10-16 10:45:16 +02:00
pascallanger
e297310a25 Update Scanner_cc2500.ino 2019-10-15 20:00:45 +02:00
pascallanger
d71006f2ae Update Multi_Names.ino 2019-10-15 20:00:41 +02:00
pascallanger
7a8e099a79 Send MULTI NAMES all the time 2019-10-15 11:19:42 +02:00
pascallanger
822aa84fa2 Update Multi_Names.ino 2019-10-15 08:54:02 +02:00
pascallanger
948ce9e8b8 Send current protocol and sub protocol name 2019-10-15 02:04:19 +02:00
goebish
caf145c38a Auto-detect FrSky RX format (#286)
* Calibrate rf channels for D8 too

* Auto-detect D16FCC, D16LBT or D8 format during bind
2019-10-14 00:28:39 +02:00
pascallanger
f964cdec98 Update Multiprotocol.h 2019-10-13 22:23:32 +02:00
pascallanger
6848fab873 FiX AFHDS2A RX LNA switch 2019-10-13 16:46:24 +02:00
pascallanger
72d57cae71 Merge branch 'master' into SPort_Send 2019-10-13 16:37:18 +02:00
pascallanger
a23178e20e Fix ADHDS2A RX LNA switch 2019-10-13 16:35:09 +02:00
pascallanger
5ae4f0288b Global def for the common RX variables 2019-10-13 11:08:20 +02:00
goebish
e0e51eb187 Fix rc channels init (#284) 2019-10-12 20:31:09 +02:00
pascallanger
840944ea94 Merge branch 'SPort_Send' of https://github.com/pascallanger/DIY-Multiprotocol-TX-Module into SPort_Send 2019-10-12 19:50:46 +02:00
pascallanger
31ff27b1d3 PPM mode FrSkyX to FrSkyD
If TELEMETRY_FRSKYX_TO_FRSKYD is defined in PPM mode FrSkyX simple telemetry will be sent using FrSkyD format:
RX_RSSI, RX_Batt, TX_RSSI, TX_LQI
2019-10-12 19:50:41 +02:00
goebish
a234ccbd05 Protocol FrSkyD (D8) receiver (#283)
* Rename FrSkyX Rx to FrSky Rx

* Rename protocol

* Add D8 receiver sub protocol
2019-10-12 19:50:11 +02:00
pascallanger
6dfd54b8be Remove travis test for debug 2019-10-11 10:08:25 +02:00
Ben Lye
edb7729b35 Update README.md 2019-10-11 08:46:19 +01:00
pascallanger
d434e63c22 Multi_sync updates
Only for STM32
Enable bidirectionnal serial
2019-10-11 01:14:04 +02:00
pascallanger
cd7ede006c Sync radio -> module 2019-10-10 23:12:09 +02:00
pascallanger
d4d0dc3dbc Update Compiling_STM32.md 2019-10-10 16:18:15 +02:00
pascallanger
5c7f997e7a Send channel order in MULTI_TELEMETRY 2019-10-09 11:58:50 +02:00
Ben Lye
1623a007a4 Add Channel Order doc page (#281)
* Create Channel_Order.md

* Update Channel_Order.md

* Update README.md
2019-10-08 21:42:48 +02:00
pascallanger
0b19fa0bdf Disable channel mapping + telemetry inversion 2019-10-08 18:52:47 +02:00
pascallanger
897c8b6ec5 Remove "Disable channel mapping" 2019-10-08 00:07:23 +02:00
pascallanger
d427a7fec1 DSM TH_KILL channel 14 2019-10-07 23:31:03 +02:00
pascallanger
b0749a1bee DSM TH_KILL channel 14 2019-10-07 23:30:17 +02:00
pascallanger
2406080515 Update Protocols_Details.md 2019-10-07 23:27:04 +02:00
pascallanger
ff96146b04 Enhanced serial protocol
Protocol 0..255
RX_Num 0..63
Disable channel mapping -> not implemented yet
Disable telemetry
Data 0-9 bytes
2019-10-07 19:06:00 +02:00
pascallanger
e3a5b2825d Merge branch 'master' into SPort_Send 2019-10-07 08:44:51 +02:00
goebish
9fd72b5ad5 Fix scaling for +125% (#280) 2019-10-05 19:02:59 +02:00
goebish
c2bf63991f Fix channel and rssi scaling (#279) 2019-10-05 13:30:50 +02:00
pascallanger
a75ae7b65a Create irx4-lite-cabling.jpg 2019-10-04 19:46:13 +02:00
pascallanger
507e4cb07b Create irx4-lite-boot0.jpg 2019-10-04 19:40:56 +02:00
pascallanger
0f250bb04b Merge branch 'master' into SPort_Send 2019-10-04 19:04:24 +02:00
pascallanger
4a315057a2 Merge branch 'master' of https://github.com/pascallanger/DIY-Multiprotocol-TX-Module 2019-10-04 19:03:37 +02:00
pascallanger
c8f44a0c4b Fix Multi receiver channels 2019-10-04 19:03:19 +02:00
pascallanger
382d853fe2 Update Compiling_STM32.md 2019-10-04 18:52:48 +02:00
pascallanger
a5996c488e Pictures 2019-10-04 18:48:46 +02:00
pascallanger
760642ecb3 Create irx4-lite.jpg 2019-10-04 18:00:41 +02:00
pascallanger
c7a3548df0 Merge branch 'master' into SPort_Send 2019-10-04 10:32:37 +02:00
pascallanger
d8acc6a5e8 New boards with bin signatures 2019-10-04 10:14:52 +02:00
pascallanger
431808286b Data Buffer signaling 2019-10-03 16:38:50 +02:00
Ben Lye
747fa19259 Update package_multi_4in1_board_index.json 2019-10-02 22:11:18 +01:00
pascallanger
bf61295b76 Fix AFHDS2A_RX 2019-10-02 21:24:50 +02:00
pascallanger
49a1ecea00 Merge branch 'master' into SPort_Send 2019-10-02 21:07:08 +02:00
pascallanger
11f0e55bb1 SPort_Send sequencer 2019-10-02 20:09:18 +02:00
Ben Lye
331da37840 Update Binary_Signature.ino (#278)
Clean up the comments, add bitmasks.
2019-10-02 10:15:13 +02:00
goebish
032e0641a5 Fix AFHDS2A receiver packet filter (#276)
* Add skeleton for AFHDS2A receiver protocol

* Bind & data Ok

* Send channels to TX via telemetry

* Add RSSI

* Fix AVR compilation

* Fix channel number

* Fix packet type check
2019-10-02 09:04:13 +02:00
goebish
f3d2ab61e4 Protocol Flysky AFHDS2A receiver (#275)
* Add skeleton for AFHDS2A receiver protocol

* Bind & data Ok

* Send channels to TX via telemetry

* Add RSSI

* Fix AVR compilation

* Fix channel number
2019-10-01 20:44:26 +02:00
Ben Lye
e8b5f071fe Move signature conditionals to separate file, add channel order (#274) 2019-10-01 11:05:37 +02:00
Ben Lye
ada72d6113 Update Travis Configuration (#273)
Various improvements to the Travis CI script:
* Add channel order builds to releases - now building AETR, TAER, and RETA
* Add PPM builds for each channel order with no inversion and PPM banks set to 5
* Log config diff for each build (diff output folded to keep the log readable)
* Colorify the "Building" lines to make parsing the log easier
* Export .bin files instead of .hex files for the AVR modules
* Add Multi.txt to the release files
2019-10-01 07:43:08 +01:00
pascallanger
c2404d4f0d Code cleanup 2019-09-30 20:53:10 +02:00
pascallanger
821732bba9 Initial S.Port send
!!! No retransmit for now !!!
2019-09-30 17:35:12 +02:00
pascallanger
b6df650f50 Update BOM_DIY_ATmega.md 2019-09-29 15:13:47 +02:00
pascallanger
e783ce5788 Failsafe modification
The following protocols are supporting failsafe: FrSkyX, Devo, WK2x01, SFHSS, HISKY/HK310 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.
2019-09-27 16:20:43 +02:00
pascallanger
18af4a0724 AVR modules: Fix KF606, GD00X and Potensic 2019-09-26 15:51:28 +02:00
pascallanger
7e6ec1dc8d Update FrSkyX_Rx_cc2500.ino
Remove compilation warnings for AVR
2019-09-26 15:50:38 +02:00
pascallanger
4fbe0859e0 Update comments 2019-09-25 19:10:55 +02:00
pascallanger
b89c23fe7c PPM channel remapping 2019-09-23 18:13:25 +02:00
goebish
e038c49ae9 Protocol FrskyX D16 RX frequency auto-tune (#270)
* Add autotune during bind

* Fix data phase
2019-09-23 08:11:06 +02:00
Ben Lye
bed02c9384 Update .travis.yml (#269) 2019-09-22 14:17:23 -04:00
pascallanger
96bc4f7cdf Revert Fix FrskyX failsafe hold/no pulse inversion 2019-09-22 20:00:04 +02:00
pascallanger
6503469ddd Bump multi board version to the latest 2019-09-22 17:29:43 +02:00
pascallanger
61a1c3742c Fix FrskyX failsafe hold/no pulse inversion 2019-09-22 17:12:00 +02:00
pascallanger
1fb2a38bc1 Hitec additional telemetry 2019-09-22 17:11:23 +02:00
pascallanger
22a0d79315 FrskyX_RX documentation 2019-09-22 17:05:46 +02:00
MRC3742
0cc72772a3 Repair sub protocol column listing errors for two Protocol (#268) 2019-09-19 20:13:13 +02:00
Pascal Langer
11f4e636e3 AFHDS2A telemetry fix
Discard RX config packets
2019-09-19 10:51:24 +02:00
pascallanger
fef1a2e041 Update Advanced_Debug.md 2019-09-19 09:07:14 +02:00
pascallanger
41a9c8e013 Update Advanced_Debug.md 2019-09-19 08:59:40 +02:00
Pascal Langer
c1ad02b792 Create Debug1.png 2019-09-19 08:55:20 +02:00
Pascal Langer
ab2315c951 FrSkyX: few cosmetic and optimization changes 2019-09-18 11:05:46 +02:00
goebish
7948e33cbc Fix start channel (#267) 2019-09-18 08:48:04 +02:00
goebish
2be2dce584 Protocol FrSky D16 receiver (#266)
* Add skeleton for FrSkyX receiver protocol

* Binds & receives data packets

* Store bind information

* Fix compilation

* Bypass LNA since intended usage implies tx & rx are close together

* Bind channel has FS_AUTOCAL

* Add freq fine tune & low power mode (disable lna)

* Add TX ID check

* Retry longer until first packet is catched

* Fix chanskip for first packet

* Fix defines

* Fix bind

* Send channels to TX

* Fix RSSI reading

* Add missing static keyword

* Fix Validate.h

* Fix compilation
2019-09-17 23:35:19 +02:00
Ben Lye
69bdfe3dba Update package_multi_4in1_board_index.json 2019-09-17 20:36:24 +01:00
Pascal Langer
d73d163a58 Update Validate.h 2019-09-17 09:53:18 +02:00
Ben Lye
48a52ae5b2 Update Multiprotocol.ino (#265) 2019-09-17 09:37:18 +02:00
Pascal Langer
078dc2ab17 AFHDS2A telemetry AA and AC 2019-09-14 16:34:19 +02:00
Pascal Langer
6f4522caa6 Revert "AFHDS2A telemetry AA and AC"
This reverts commit 3c76ce9f39.
2019-09-14 16:31:27 +02:00
Pascal Langer
3c76ce9f39 AFHDS2A telemetry AA and AC 2019-09-14 16:27:07 +02:00
goebish
8601149051 Fix scanner telemetry (#262)
* Fix scanner telemetry

* Take several samples per channel, keep maximum value
2019-09-14 16:07:49 +02:00
pascallanger
d7ef15d435 Update Compiling_STM32.md 2019-09-12 16:08:20 +02:00
pascallanger
27e3645b56 Update Compiling_STM32.md 2019-09-12 15:55:08 +02:00
pascallanger
95eb4e1a22 Update Compiling_STM32.md 2019-09-12 15:54:18 +02:00
pascallanger
32ea07bf5a Update Compiling_STM32.md 2019-09-12 15:51:58 +02:00
pascallanger
06272575c5 Flash from TX 2019-09-12 15:50:12 +02:00
Pascal Langer
edd6432d4c Update Validate.h 2019-09-11 15:26:35 +02:00
Pascal Langer
303c4615e9 Fix scanner compilation issue 2019-09-11 12:23:36 +02:00
Pascal Langer
7d327c1622 Scanner 2.4GHz
Thanks to Goebish for this spectrum analyzer.
It will work soon with the OpenTX 2.3 Spectrum Analyser tool.
2019-09-10 23:37:54 +02:00
Ben Lye
6a74b83f98 Update .travis.yml 2019-09-08 14:40:59 +01:00
Ben Lye
c601c2dd98 Update .travis.yml 2019-09-08 14:25:52 +01:00
Ben Lye
c27b60749f Update Travis CI script (#257)
* Use latest STM32 board options
* Use latest Arduino IDE
* Fix build functions to return an error if the build fails
* Modify the files that get exported to releases
2019-09-08 13:33:26 +01:00
Ben Lye
b3cb286088 Update package_multi_4in1_board_index.json 2019-09-07 18:54:27 +01:00
Ben Lye
361903e8ec Doc updates for new board package (#256) 2019-09-07 18:23:08 +01:00
Ben Lye
d72c69242d Update package_multi_4in1_board_index.json
Add AVR board v1.0.8 and STM32 board v1.1.5.
2019-09-06 19:43:10 +01:00
Ben Lye
539819fa0c Accomodate new Debug Option setting in Arduino IDE (#255)
Thanks, that's perfect!
2019-09-06 14:05:57 +02:00
Ben Lye
d80c218744 Add timeout to serial debug (#253)
* Wait 30s for serial debug instead of waiting forever
* Delay of 50ms to allow FTDI debugger to connect at startup
2019-09-05 08:33:01 +02:00
pascallanger
0603d220a9 T16 Flash from TX 2019-09-04 17:39:47 +02:00
pascallanger
e13fe56f47 Include the Jumper T16 2019-09-04 17:38:00 +02:00
pascallanger
acd7694485 Update Protocols_Details.md 2019-09-02 19:23:15 +02:00
pascallanger
7f50edacc8 Update Protocols_Details.md 2019-09-02 19:07:48 +02:00
pascallanger
5a4906c5b5 Update Protocols_Details.md 2019-09-02 19:06:34 +02:00
Pascal Langer
4e906757b9 XN297Dump fix enhanced unscramble mode 2019-08-24 22:39:27 +02:00
Pascal Langer
1f0b21e351 Fix GW008 protocol 2019-08-24 22:14:18 +02:00
Pascal Langer
2f3ea323c7 CHECK_FOR_BOOTLOADER now enabled by default in _config.h 2019-08-24 21:50:36 +02:00
Pascal Langer
d4e77c6499 XN297Dump: added enhanced packet mode 2019-08-24 21:37:26 +02:00
pascallanger
ffc56b049d Update Advanced_Debug.md 2019-08-20 14:07:38 +02:00
pascallanger
ddac89d732 Update Advanced_Debug.md 2019-08-20 14:06:01 +02:00
Pascal Langer
fecf2805c7 WIP: Advanced topics 2019-08-20 14:01:56 +02:00
Pascal Langer
4dcc88ba32 Serial debug documentation 2019-08-18 18:44:36 +02:00
Pascal Langer
084308d8a4 Update Multi.txt 2019-08-18 17:08:27 +02:00
Pascal Langer
1ffb5c405b New protocol: Flyzone
Models compatible with TX FZ-410
Protocol 53
No sub protocol
2019-08-17 22:37:00 +02:00
Pascal Langer
ad29409407 New protocol ZSX
Model JJRC ZSX-280
Protocol number 52 ,no sub protocol
CH3: Throttle
CH4: Rudder
CH5: Light
2019-08-10 21:43:14 +02:00
Pascal Langer
6f33abb25e New protocol Traxxas
Protocol number: 43
Compatible with receivers 6519
Extended limits supported
CH1=AUX3
CH2=AUX4
CH3=THROTTLE
CH4=STEERING
2019-08-06 17:27:42 +02:00
Pascal Langer
2c9693389e Fix DSM telemetry and global cyrf6936 freq tunning
- Fixed DSM telemetry with some RXs (R720X)
 - Global frequency tunning for all protocols using the CYRF6936 by adjusting channel 15 when enabled
 - Changed default DSM_THROTTLE_KILL_CH to use channel 14
2019-08-01 14:23:08 +02:00
MRC3742
d3c82c4da4 Add option instructions to update STM module (#243) 2019-07-18 10:34:46 +02:00
Pascal Langer
541a96e7b4 Merge branch 'master' of https://github.com/pascallanger/DIY-Multiprotocol-TX-Module 2019-07-04 10:37:42 +02:00
Pascal Langer
5b234a9cbc Mandatory use of boards AVR 1.0.7 and STM32 1.1.4 solving path space issues 2019-07-04 10:37:25 +02:00
Ben Lye
24c3a62f3a Update package_multi_4in1_board_index.json 2019-07-04 09:31:51 +01:00
Pascal Langer
23756a387a XN297Dump: fix packet timer 2019-07-03 20:51:13 +02:00
Pascal Langer
efbd350dfd GD00X: fix typo... 2019-07-03 18:27:39 +02:00
Pascal Langer
072e95c84e Merge branch 'master' of https://github.com/pascallanger/DIY-Multiprotocol-TX-Module 2019-07-03 18:13:08 +02:00
Pascal Langer
4be26e7202 GD00X: add high/low rates 2019-07-03 18:07:18 +02:00
pascallanger
a616cbb95c Update Protocols_Details.md 2019-07-03 18:05:54 +02:00
Pascal Langer
8aea9aa3dd Added a common deadband conversion code
Modified protocols:
 - GD00X applied on aileron
 - KF606 applied on aileron
 - POTENSIC applied on throttle
2019-07-03 17:39:05 +02:00
pascallanger
e4992bc917 Update Protocols_Details.md 2019-07-03 16:48:06 +02:00
pascallanger
000b3e97c7 Update Protocols_Details.md 2019-07-03 09:55:16 +02:00
pascallanger
cb91e19413 Update Compiling_STM32.md 2019-07-03 00:18:45 +02:00
pascallanger
c72e690085 Update Compiling_STM32.md 2019-07-02 23:32:27 +02:00
pascallanger
f1a4e659e7 Update Compiling_STM32.md 2019-07-02 23:28:02 +02:00
pascallanger
0d56d17d52 Update Compiling_STM32.md 2019-07-02 23:25:37 +02:00
pascallanger
96c89c8c97 Update Compiling_STM32.md 2019-07-02 23:12:26 +02:00
pascallanger
7df5a1f211 Update Compiling_STM32.md 2019-07-02 23:11:03 +02:00
pascallanger
8ae8e028c7 Update Compiling_STM32.md 2019-07-02 22:34:23 +02:00
pascallanger
581ad5f8f4 Update Compiling_STM32.md 2019-07-02 22:33:05 +02:00
pascallanger
977bae3750 Add files via upload 2019-07-02 22:28:43 +02:00
pascallanger
8a0161607e Update Protocols_Details.md 2019-07-02 21:51:31 +02:00
Ben Lye
cd6a7bfc3a Update package_multi_4in1_board_index.json
Add new boards which resolves issue with spaces in the sketch path on Windows.
2019-06-27 15:50:44 +01:00
Pascal Langer
4671700b7d Devo protocol: number of channels 2019-06-23 17:13:30 +02:00
pascallanger
840ca74407 Redpine changes (#240)
* Change Looptimes
state => bind_counter

* minimize whitespace changes
2019-06-20 10:53:31 +02:00
Bryce Johnson
0d8a7e46de Redpine changes (#240)
* Change Looptimes
state => bind_counter
2019-06-20 10:53:17 +02:00
pascallanger
8b9940b0f0 Redpine typo 2019-06-19 16:07:08 +02:00
Pascal Langer
521b819b8a New protocol POTENSIC
Model: A20
Protocol number: 51
Sub protocol: none
Channels:
- CH5 TAKE_OFF/LANDING: momentary switch -100% -> +100%
- CH6 EMERGENCY: Stop +100%
- CH7 MODE: MODE: Beginner -100%, Medium 0%, Advanced +100%
- CH8 HEADLESS: Off -100%, On +100%
2019-06-19 11:25:21 +02:00
Bryce Johnson
208e9ef64b minimize whitespace changes 2019-06-17 19:08:07 -06:00
Bryce Johnson
a7ea8e012e Change Looptimes
state => bind_counter
2019-06-17 19:01:27 -06:00
Pascal Langer
d940a7e49a New Redpine protocol
Protocol Redpine: 50
Sub protocol: Fast=0, Slow=1
Option=freq tunning
2019-06-17 17:16:39 +02:00
Pascal Langer
9d50171034 BUGS fix a bug... 2019-06-10 09:19:56 +02:00
Pascal Langer
701a5b9e28 Merge branch 'master' of https://github.com/pascallanger/DIY-Multiprotocol-TX-Module 2019-06-09 19:00:27 +02:00
Pascal Langer
d11785ef2d V761... forgot to save the change before pushing... 2019-06-09 19:00:21 +02:00
pascallanger
f4a4d91ef8 V761 additional IDs 2019-06-09 15:06:29 +02:00
Pascal Langer
9514e47ed3 BUGS EEPROM clean: need to rebind BUGS and BUGSMINI 2019-06-09 14:51:21 +02:00
Pascal Langer
9461f2d632 V761 3rd ID 2019-06-09 14:50:17 +02:00
Pascal Langer
f6064d03e1 V761 aileron channel 2019-06-08 21:57:02 +02:00
MRC3742
0d917e0dc5 Update TOC for sub protocols using CC2500 to emulate XN297L @250kbps (#234) 2019-06-08 21:26:25 +02:00
pascallanger
9408af8d08 Update Protocols_Details.md 2019-06-08 21:25:02 +02:00
Pascal Langer
862ab48bbc Update V761_nrf24l01.ino 2019-06-06 10:26:54 +02:00
Pascal Langer
f498347c53 V761 second TX ID/freqs 2019-06-06 10:07:57 +02:00
Pascal Langer
3f77f59c8a XN297L emu scramble option 2019-06-06 01:15:28 +02:00
pascallanger
e96186015d XN297L CC2500 emulation 2019-06-05 23:31:17 +02:00
Pascal Langer
1fa6e4526b Include full xn297(L) xor tables 2019-06-05 23:23:27 +02:00
Pascal Langer
3853d585a0 XN297L/CC2500 emulation on V911s 2019-06-05 22:53:24 +02:00
Pascal Langer
e8c6225ef0 New XN297L 250Kbps emu layer based on CC2500
This layer can be enabled/disabled with the option XN297L_CC2500_EMU in _config.h
Protocols which are using it so far:
GD00X, KF606 and MJXQ/E010&PHOENIX
2019-06-05 21:54:47 +02:00
Pascal Langer
17c67cc780 Update V761_nrf24l01.ino 2019-06-04 22:42:37 +02:00
Pascal Langer
dcc4236833 Merge branch 'master' of https://github.com/pascallanger/DIY-Multiprotocol-TX-Module 2019-06-04 22:02:43 +02:00
Pascal Langer
6a7c735924 Fix V761 input 2019-06-04 22:02:20 +02:00
pascallanger
3c40cd853e Update Protocols_Details.md 2019-06-04 21:59:12 +02:00
pascallanger
5357660b68 KF606 and V761 protocols 2019-06-04 21:56:39 +02:00
Pascal Langer
a15a911f8e New protocol KF606
Model: KF606
Protocol: 49
No sub protocol
Channels: throttle, aileron and trim on ch5
2019-06-04 21:44:40 +02:00
Pascal Langer
ded0487ce6 XN297Dump improvements
Selection of address length
Timing accuracy
2019-06-04 21:41:50 +02:00
pascallanger
e7b079ece7 Update Protocols_Details.md 2019-06-01 16:05:23 +02:00
goebish
0cbe4de920 Fix E010/CC2500 Protocol on AVR (#229)
* Use cc2500 fast frequency hopping

* Calibrate cc2500 PLL if sub-protocol is E010/Phoenix only

* Fix e010 crc for AVR
2019-05-31 09:17:27 +02:00
Ben Lye
5c3bf30fe7 Fix CX20 image 2019-05-29 08:48:21 +01:00
Ben Lye
56b8694fd5 Add CX20 Image 2019-05-29 08:47:25 +01:00
Pascal Langer
c9fecafada WFly frequency tunning 2019-05-18 20:33:32 +02:00
Pascal Langer
f3ca7ad644 WFly freq tuning on channel 15
You need to enable the tuning in _config.h: #define USE_CYRF6936_CH15_TUNING
2019-05-18 17:36:39 +02:00
pascallanger
c3b48c78af Update Protocols_Details.md 2019-05-18 13:48:02 +02:00
Pascal Langer
18dcc29a0d XN297Dump: auto scramble detection 2019-05-17 20:34:02 +02:00
Pascal Langer
c3a5c263d3 XN297Dump fix CRC... 2019-05-17 19:56:52 +02:00
Pascal Langer
ccdf60d525 XN297DUMP: dynamic address search
The dump process is now looking for addresses with different length (3..5) additonnaly to the packet length.
Untested...
2019-05-17 17:00:08 +02:00
Pascal Langer
443e1cec75 New protocol V761
Protocol number: 48
Sub_protocol: none
Channel 5: +100% expert, 0% mid=gyro on no rate limits, -100% beginer=gyro on and axis rate limited.
ONLY 1 ID IS AVAILABLE SO BE CAREFUL WHILE FLYING.
2019-05-17 16:25:39 +02:00
goebish
aa540514b8 Use CC2500 if available instead of NRF24L01 for E010 and PHOENIX (#225)
* Use CC2500 if available instead of NRF24L01 for E010 and PHOENIX sub protocols

* Update documentation

* Why do I always swap below & above ?
2019-05-16 13:17:39 +02:00
pascallanger
fda7e2e5b6 Update Protocols_Details.md 2019-05-14 18:23:24 +02:00
pascallanger
fb4d5cf437 Update Protocols_Details.md 2019-05-14 18:22:07 +02:00
pascallanger
9fc2898a56 Bayang protocol DHD D4 sub_protocol 2019-05-10 21:52:54 +02:00
Pascal Langer
2e24323adf DHD D4 set to high rates 2019-05-10 21:39:15 +02:00
pascallanger
77abc1ed7c BUGS3H Altitude Hold 2019-05-10 21:09:31 +02:00
Pascal Langer
259d550d04 AFHDS2A: stop bind process as requested 2019-05-10 19:39:14 +02:00
Pascal Langer
1a8f9c5a12 AFHDS2A extended telemetry forward 2019-05-10 18:17:09 +02:00
Pascal Langer
1916eb3095 AFHDS2A: add debug on full telemetry frames 2019-05-10 11:04:21 +02:00
Pascal Langer
fc3eec7ae1 BUSMINI: 3H altitude hold mode on CH11 2019-05-09 23:56:06 +02:00
Ben Lye
8d10c9b004 Update .travis.yml
Fix file extension for compiled STM32 files
2019-05-09 21:36:49 +01:00
Pascal Langer
511f77f5e7 Bayang DHD D4 sub protocol 2019-05-09 18:23:19 +02:00
pascallanger
a58d7a4d79 Update Protocols_Details.md 2019-05-09 13:33:08 +02:00
Pascal Langer
6748f6ce78 Add XN297 Dump protocol
Protocol number: 63
Sub protocols: 0=250Kb, 1=1Mb, 2=2Mb
Option: -1=scan RF channels, 0-84=RF channel
DEBUG_SERIAL must be enabled
If a valid frame is received the frame will be sent on the serial port.
2019-05-08 22:01:24 +02:00
119 changed files with 12980 additions and 2897 deletions

View File

@@ -1,59 +1,287 @@
dist: trusty
dist: bionic
sudo: true
#
language: c
#
env:
global:
- IDE_VERSION=1.8.1
- IDE_VERSION=1.8.9
matrix:
- BOARD="multi4in1:STM32F1:multistm32f103c:upload_method=serialMethod"
- BOARD="multi4in1:STM32F1:multistm32f103c:upload_method=TxFlashMethod"
- BOARD="multi4in1:avr:multixmega32d4"
- BOARD="multi4in1:avr:multiatmega328p:bootloader=none"
- BOARD="multi4in1:avr:multiatmega328p:bootloader=optiboot"
#
- BOARD="multi4in1:avr:multixmega32d4"
- BOARD="multi4in1:STM32F1:multistm32f103c:debug_option=none"
- BOARD="multi4in1:STM32F1:multistm32f103c:debug_option=native"
- BOARD="multi4in1:STM32F1:multistm32f103c:debug_option=ftdi"
notifications:
email: false
#
before_install:
#
# Fetch the tag information for the current branch
- git fetch origin --tags
#
# Publish the buildroot script folder
- chmod +x ${TRAVIS_BUILD_DIR}/buildroot/bin/*
- export PATH=${TRAVIS_BUILD_DIR}/buildroot/bin/:${PATH}
#
# Arduino IDE adds a lot of noise caused by network traffic; firewall it
- sudo iptables -P INPUT DROP
- sudo iptables -P FORWARD DROP
- sudo iptables -P OUTPUT ACCEPT
- sudo iptables -A INPUT -i lo -j ACCEPT
- sudo iptables -A OUTPUT -o lo -j ACCEPT
- sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Helper functions for the builds
- buildMulti() { start_fold config_diff; travis_time_start; git diff Multiprotocol/_Config.h; end_fold config_diff; exitcode=0; BUILDCMD="arduino --verify --board $BOARD Multiprotocol/Multiprotocol.ino --pref build.path=./build/"; echo $BUILDCMD; $BUILDCMD; if [ $? -ne 0 ]; then exitcode=1; fi; echo; return $exitcode; }
- buildProtocol() { exitcode=0; opt_disable $ALL_PROTOCOLS; opt_enable $1; buildMulti; if [ $? -ne 0 ]; then exitcode=1; fi; return $exitcode; }
- buildEachProtocol() { exitcodesum=0; for PROTOCOL in $ALL_PROTOCOLS ; do printf "\e[33;1mBuilding $PROTOCOL\e[0m"; buildProtocol $PROTOCOL; if [ $? -ne 0 ]; then exitcodesum=$((exitcodesum + 1)); fi; done; return $exitcodesum; }
- buildRFModule() { exitcode=0; opt_disable $ALL_RFMODULES; opt_enable $1; buildMulti; if [ $? -ne 0 ]; then exitcode=1; fi; return $exitcode; }
- buildEachRFModule() { exitcodesum=0; for RFMODULE in $ALL_RFMODULES; do printf "\e[33;1mBuilding $RFMODULE\e[0m"; buildRFModule $RFMODULE; if [ $? -ne 0 ]; then exitcodesum=$((exitcodesum + 1)); fi; done; return $exitcodesum; }
- buildDefault() { exitcode=0; printf "\n\e[33;1mBuilding default configuration\e[0m\n"; buildMulti; if [ $? -ne 0 ]; then exitcode=1; fi; return $exitcode; }
- buildSerialOnly() { exitcode=0; printf "\n\e[33;1mBuilding serial mode only\e[0m\n"; opt_disable ENABLE_PPM; opt_enable ENABLE_SERIAL; buildMulti; if [ $? -ne 0 ]; then exitcode=1; fi; return $exitcode; }
- buildPPMOnly() { exitcode=0; printf "\n\e[33;1mBuilding PPM mode only\e[0m\n"; opt_enable ENABLE_PPM; opt_disable ENABLE_SERIAL; buildMulti; if [ $? -ne 0 ]; then exitcode=1; fi; return $exitcode; }
# Function to build the release files - dependent on board type
- if [[ "$BOARD" == "multi4in1:avr:multixmega32d4" ]]; then
buildReleaseFiles(){
exitcode=0;
printf "\n\e[33;1mBuilding multi-orangerx-aetr-green-inv-v$MULTI_VERSION.bin\e[0m";
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;
printf "\n\e[33;1mBuilding multi-orangerx-aetr-blue-inv-v$MULTI_VERSION.bin\e[0m";
opt_enable ORANGE_TX_BLUE;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-orangerx-aetr-blue-inv-v$MULTI_VERSION.bin;
cp Multiprotocol/Multi.txt ./binaries/Multi.txt;
return $exitcode; };
elif [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=none" ]]; then
buildReleaseFiles(){
printf "\n\e[33;1mBuilding multi-avr-usbasp-aetr-A7105-inv-v$MULTI_VERSION.bin\e[0m";
exitcode=0;
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;
printf "\n\e[33;1mBuilding multi-avr-usbasp-aetr-CC2500-inv-v$MULTI_VERSION.bin\e[0m";
opt_disable $ALL_PROTOCOLS;
opt_enable $CC2500_PROTOCOLS;
buildMulti;
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-usbasp-aetr-CC2500-inv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-avr-usbasp-aetr-CYRF6936-inv-v$MULTI_VERSION.bin\e[0m";
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;
return $exitcode; };
elif [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=optiboot" ]]; then
buildReleaseFiles(){
printf "\n\e[33;1mBuilding multi-avr-txflash-aetr-A7105-inv-v$MULTI_VERSION.bin\e[0m";
exitcode=0;
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;
printf "\n\e[33;1mBuilding multi-avr-txflash-aetr-CC2500-inv-v$MULTI_VERSION.bin\e[0m";
opt_disable $ALL_PROTOCOLS;
opt_enable $CC2500_PROTOCOLS;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-txflash-aetr-CC2500-inv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-avr-txflash-aetr-CYRF6936-inv-v$MULTI_VERSION.bin\e[0m";
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;
return $exitcode; };
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c:debug_option=none" ]]; then
buildReleaseFiles(){
printf "\n\e[33;1mBuilding multi-stm-erskytx-aetr-inv-v$MULTI_VERSION.bin\e[0m";
exitcode=0;
opt_enable CHECK_FOR_BOOTLOADER;
opt_enable $ALL_PROTOCOLS;
opt_enable MULTI_STATUS;
opt_disable MULTI_TELEMETRY;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-aetr-inv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-erskytx-taer-inv-v$MULTI_VERSION.bin\e[0m";
opt_replace AETR TAER;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-taer-inv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-erskytx-reta-inv-v$MULTI_VERSION.bin\e[0m";
opt_replace TAER RETA;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-reta-inv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-erskytx-aetr-noinv-v$MULTI_VERSION.bin\e[0m";
opt_replace RETA AETR;
opt_disable INVERT_TELEMETRY;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-aetr-noinv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-erskytx-taer-noinv-v$MULTI_VERSION.bin\e[0m";
opt_replace AETR TAER;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-taer-noinv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-erskytx-reta-noinv-v$MULTI_VERSION.bin\e[0m";
opt_replace TAER RETA;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-reta-noinv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-opentx-aetr-inv-v$MULTI_VERSION.bin\e[0m";
opt_replace RETA AETR;
opt_disable MULTI_STATUS;
opt_enable MULTI_TELEMETRY;
opt_enable INVERT_TELEMETRY;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-aetr-inv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-opentx-taer-inv-v$MULTI_VERSION.bin\e[0m";
opt_replace AETR TAER;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-taer-inv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-opentx-reta-inv-v$MULTI_VERSION.bin\e[0m";
opt_replace TAER RETA;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-reta-inv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-opentx-aetr-noinv-v$MULTI_VERSION.bin\e[0m";
opt_replace RETA AETR;
opt_disable INVERT_TELEMETRY;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-aetr-noinv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-opentx-taer-noinv-v$MULTI_VERSION.bin\e[0m";
opt_replace AETR TAER;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-taer-noinv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-opentx-reta-noinv-v$MULTI_VERSION.bin\e[0m";
opt_replace TAER RETA;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-reta-noinv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-ppm-aetr-noinv-v$MULTI_VERSION.bin\e[0m";
opt_replace RETA AETR;
opt_disable MULTI_STATUS;
opt_disable MULTI_TELEMETRY;
opt_set NBR_BANKS 5;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-ppm-aetr-noinv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-ppm-taer-noinv-v$MULTI_VERSION.bin\e[0m";
opt_replace AETR TAER;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-ppm-taer-noinv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-ppm-reta-noinv-v$MULTI_VERSION.bin\e[0m";
opt_replace TAER RETA;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-ppm-reta-noinv-v$MULTI_VERSION.bin;
return $exitcode; };
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c:debug_option=native" ]]; then
buildReleaseFiles(){
printf "\n\e[33;1mBuilding multi-stm-erskytx-xn297dump-inv-usbdebug-v$MULTI_VERSION.bin\e[0m";
exitcode=0;
opt_enable CHECK_FOR_BOOTLOADER;
opt_disable $ALL_PROTOCOLS;
opt_add XN297DUMP_NRF24L01_INO;
opt_enable MULTI_STATUS;
opt_disable MULTI_TELEMETRY;
opt_enable INVERT_TELEMETRY;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-xn297dump-inv-usbdebug-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-opentx-xn297dump-inv-usbdebug-v$MULTI_VERSION.bin\e[0m";
opt_disable $ALL_PROTOCOLS;
opt_disable MULTI_STATUS;
opt_enable MULTI_TELEMETRY;
opt_enable INVERT_TELEMETRY;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-xn297dump-inv-usbdebug-v$MULTI_VERSION.bin;
return $exitcode; };
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c:debug_option=ftdi" ]]; then
buildReleaseFiles(){
printf "\n\e[33;1mBuilding multi-stm-erskytx-xn297dump-inv-ftdidebug-v$MULTI_VERSION.bin\e[0m";
exitcode=0;
opt_enable CHECK_FOR_BOOTLOADER;
opt_disable $ALL_PROTOCOLS;
opt_add XN297DUMP_NRF24L01_INO;
opt_enable MULTI_STATUS;
opt_disable MULTI_TELEMETRY;
opt_enable INVERT_TELEMETRY;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-xn297dump-inv-ftdidebug-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-stm-opentx-xn297dump-inv-ftdidebug-v$MULTI_VERSION.bin\e[0m";
opt_disable $ALL_PROTOCOLS;
opt_disable MULTI_STATUS;
opt_enable MULTI_TELEMETRY;
opt_enable INVERT_TELEMETRY;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-xn297dump-inv-ftdidebug-v$MULTI_VERSION.bin;
return $exitcode; };
else
buildReleaseFiles() { echo "No release files for this board."; };
fi
install:
# Install Arduino IDE
- wget http://downloads.arduino.cc/arduino-$IDE_VERSION-linux64.tar.xz
- tar xf arduino-$IDE_VERSION-linux64.tar.xz
- mv arduino-$IDE_VERSION $HOME/arduino-ide
- export PATH=$PATH:$HOME/arduino-ide
# Set the Multi boards package URL
- arduino --pref "boardsmanager.additional.urls=https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/master/package_multi_4in1_board_index.json" --save-prefs
#
# Install the STM32 board if needed
- if [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
arduino --install-boards multi4in1:STM32F1;
fi
#
# Install the AVR board if needed
- if [[ "$BOARD" =~ "multi4in1:avr:" ]]; then
arduino --install-boards multi4in1:avr;
fi
#
- buildMulti() { BUILDCMD="arduino --verify --board $BOARD Multiprotocol/Multiprotocol.ino --pref build.path=./build/"; echo $BUILDCMD; $BUILDCMD; echo; }
- buildProtocol() { opt_disable $ALL_PROTOCOLS; opt_enable $1; buildMulti; }
- buildEachProtocol() { exitcode=0; for PROTOCOL in $ALL_PROTOCOLS ; do echo Building $PROTOCOL; buildProtocol $PROTOCOL; if [ $? -ne 0 ]; then exitcode=1; fi; done; return $exitcode; }
#
install: true
before_script:
#
# Change current working directory to the build dir
- cd ${TRAVIS_BUILD_DIR}
# Create somwhere to put the exported binaries
- mkdir ./binaries
# Log the initial Multi config
- cat Multiprotocol/_Config.h
# Back up the configuration
- cp Multiprotocol/_Config.h ./_Config.h.bak
# Get the firmware version number from the source
- MAJOR_VERSION=$(grep "VERSION_MAJOR" "Multiprotocol/Multiprotocol.h" | awk -v N=3 '{gsub(/\r/,""); print $N}')
- MINOR_VERSION=$(grep "VERSION_MINOR" "Multiprotocol/Multiprotocol.h" | awk -v N=3 '{gsub(/\r/,""); print $N}')
- REVISION_VERSION=$(grep "VERSION_REVISION" "Multiprotocol//Multiprotocol.h" | awk -v N=3 '{gsub(/\r/,""); print $N}')
- PATCH_VERSION=$(grep "VERSION_PATCH" "Multiprotocol//Multiprotocol.h" | awk -v N=3 '{gsub(/\r/,""); print $N}')
- MULTI_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$REVISION_VERSION.$PATCH_VERSION
# Derive the Multi protocols from the Multi source
- A7105_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_A7105_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
- CC2500_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_CC2500_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
@@ -65,107 +293,64 @@ before_script:
ALL_PROTOCOLS=$(echo $A7105_PROTOCOLS $CC2500_PROTOCOLS $CYRF6936_PROTOCOLS $NRF24L01_PROTOCOLS);
fi
- echo $ALL_PROTOCOLS
#
# Enable CHECK_FOR_BOOTLOADER when needed
- if [[ "$BOARD" =~ ":upload_method=TxFlashMethod" ]] || [[ "$BOARD" =~ ":bootloader=optiboot" ]]; then
opt_enable CHECK_FOR_BOOTLOADER;
# Declare all the installed modules
- ALL_RFMODULES=$(echo A7105_INSTALLED CYRF6936_INSTALLED CC2500_INSTALLED NRF24L01_INSTALLED);
# Disable CHECK_FOR_BOOTLOADER when not needed
- if [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=none" ]]; then
opt_disable CHECK_FOR_BOOTLOADER;
fi
#
# Trim the build down for the Atmega328p board
# Trim the enabled protocols down for the STM32 board with debugging
- if [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c:debug_option=ftdi" ]] || [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c:debug_option=native" ]]; then
opt_disable $ALL_PROTOCOLS;
opt_enable FRSKYX_CC2500_INO AFHDS2A_A7105_INO MJXQ_NRF24L01_INO DSM_CYRF6936_INO;
fi
# Trim the enabled protocols down for the Atmega328p board
- if [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:" ]]; then
opt_disable $ALL_PROTOCOLS;
opt_enable FRSKYX_CC2500_INO AFHDS2A_A7105_INO MJXQ_NRF24L01_INO DSM_CYRF6936_INO;
fi
#
# Useful Travis functions
- export -f travis_fold
- export -f travis_nanoseconds
- export -f travis_time_start
- export -f travis_time_finish
- start_fold() { echo -e "travis_fold:start:$1"; }
- end_fold() { echo -e "\ntravis_fold:end:$1\r"; }
script:
# Build with all protocols enabled for STM32; a subset of protocols for Atmega
- buildMulti
#
# Build with default configuration - all protocols are enabled for STM32; a subset of protocols for Atmega or STM32 debugging
- buildDefault
# Serial only
- opt_disable ENABLE_PPM
- opt_enable ENABLE_SERIAL
- buildMulti
#
- buildSerialOnly
# PPM only
- opt_enable ENABLE_PPM
- opt_disable ENABLE_SERIAL
- buildMulti
#
- buildPPMOnly
# Re-enable PPM and serial
- opt_enable ENABLE_SERIAL
- opt_enable ENABLE_PPM
#
# Build each protocol individually
- buildEachProtocol
before_deploy:
# Create somwhere to put the binaries
- mkdir ./binaries
# Build for each RF module individually
- buildEachRFModule
# Restore the default configuration
- cp ./_Config.h.bak Multiprotocol/_Config.h
# Build the release files for OrangeRX
- if [[ "$BOARD" =~ "multi4in1:avr:multixmega32d4" ]]; then
opt_enable $ALL_PROTOCOLS;
opt_disable ORANGE_TX_BLUE;
buildMulti;
mv build/Multiprotocol.ino.hex ./binaries/Multi-OrangeRX_Green_INV-$TRAVIS_TAG.hex;
opt_enable ORANGE_TX_BLUE;
buildMulti;
mv build/Multiprotocol.ino.hex ./binaries/Multi-OrangeRX_Blue_INV-$TRAVIS_TAG.hex;
fi
# Build the release files for AVR without bootloader
- if [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:bootloader=none" ]]; then
opt_disable CHECK_FOR_BOOTLOADER;
opt_disable $ALL_PROTOCOLS;
opt_enable $A7105_PROTOCOLS;
buildMulti;
mv build/Multiprotocol.ino.hex ./binaries/Multi-AVR_USBASP_A7105_INV-$TRAVIS_TAG.hex;
opt_disable $ALL_PROTOCOLS;
opt_enable $CC2500_PROTOCOLS;
buildMulti;
mv build/Multiprotocol.ino.hex ./binaries/Multi-AVR_USBASP_CC2500_INV-$TRAVIS_TAG.hex;
opt_disable $ALL_PROTOCOLS;
opt_enable $CYRF6936_PROTOCOLS;
buildMulti;
mv build/Multiprotocol.ino.hex ./binaries/Multi-AVR_USBASP_CYRF6936_INV-$TRAVIS_TAG.hex;
fi
# Build the release files for AVR with bootloader
- if [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:bootloader=optiboot" ]]; then
opt_enable CHECK_FOR_BOOTLOADER;
opt_disable $ALL_PROTOCOLS;
opt_enable $A7105_PROTOCOLS;
buildMulti;
mv build/Multiprotocol.ino.hex ./binaries/Multi-AVR_TXFLASH_A7105_INV-$TRAVIS_TAG.hex;
opt_disable $ALL_PROTOCOLS;
opt_enable $CC2500_PROTOCOLS;
buildMulti;
mv build/Multiprotocol.ino.hex ./binaries/Multi-AVR_TXFLASH_CC2500_INV-$TRAVIS_TAG.hex;
opt_disable $ALL_PROTOCOLS;
opt_enable $CYRF6936_PROTOCOLS;
buildMulti;
mv build/Multiprotocol.ino.hex ./binaries/Multi-AVR_TXFLASH_CYRF6936_INV-$TRAVIS_TAG.hex;
fi
# Build the release files for STM32 without bootloader
- if [[ "$BOARD" =~ "multi4in1:STM32F1:multistm32f103c:upload_method=serialMethod" ]]; then
opt_disable CHECK_FOR_BOOTLOADER;
opt_enable $ALL_PROTOCOLS;
buildMulti;
mv build/Multiprotocol.ino.bin ./binaries/Multi-STM_FTDI_INV-$TRAVIS_TAG.hex;
opt_disable MULTI_STATUS;
opt_enable MULTI_TELEMETRY;
buildMulti;
mv build/Multiprotocol.ino.bin ./binaries/Multi-STM_FTDI_INV_OPENTX-$TRAVIS_TAG.hex;
fi
# Build the release files for STM32 with bootloader
- if [[ "$BOARD" =~ "multi4in1:STM32F1:multistm32f103c:upload_method=TxFlashMethod" ]]; then
opt_enable CHECK_FOR_BOOTLOADER;
opt_enable $ALL_PROTOCOLS;
buildMulti;
mv build/Multiprotocol.ino.bin ./binaries/Multi-STM_TXFLASH_INV-$TRAVIS_TAG.hex;
opt_disable MULTI_STATUS;
opt_enable MULTI_TELEMETRY;
buildMulti;
mv build/Multiprotocol.ino.bin ./binaries/Multi-STM_TXFLASH_INV_OPENTX-$TRAVIS_TAG.hex;
fi
# Build each protocol individually
- buildEachProtocol
# Restore the default configuration
- cp ./_Config.h.bak Multiprotocol/_Config.h
# Builds the files for a release - always built, but only copied to Github if the test is tagged as a release
- buildReleaseFiles
deploy:
provider: releases
api_key:

View File

@@ -7,40 +7,7 @@
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"platforms": [{
"name": "Multi 4-in-1 AVR Boards",
"architecture": "avr",
"version": "1.0.0",
"category": "Contributed",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_board_v1.0.0.zip",
"archiveFileName": "package_multi_4in1_board_v1.0.0.zip",
"checksum": "SHA-256:3DE301E9FC3C8A81CB2CEDE3458A68C626A9A5C37A73FA9C85BE9D841935684D",
"size": "3205",
"boards": [{
"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"
}],
"toolsDependencies": []
},
{
"name": "Multi 4-in-1 AVR Boards",
"architecture": "avr",
"version": "1.0.1",
"category": "Contributed",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.0.1.tar.gz",
"archiveFileName": "package_multi_4in1_avr_board_v1.0.1.tar.gz",
"checksum": "SHA-256:9bb29828476c141f5ef877e66b80ca969021d648acaf1ac5248676beb9ee3003",
"size": "3201",
"boards": [{
"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"
}],
"toolsDependencies": []
},
"platforms": [
{
"name": "Multi 4-in-1 AVR Boards",
"architecture": "avr",
@@ -96,25 +63,112 @@
"toolsDependencies": []
},
{
"name": "Multi 4-in-1 STM32 Board",
"architecture": "STM32F1",
"version": "1.0.0",
"name": "Multi 4-in-1 AVR Boards",
"architecture": "avr",
"version": "1.0.5",
"category": "Contributed",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.0.0.zip",
"archiveFileName": "package_multi_4in1_stm32_board_v1.0.0.zip",
"checksum": "SHA-256:7B661C6455F5AD7329E61EC297D4ADED9EF19F618E04E09A35A3C840977A56F5",
"size": "10896168",
"boards": [{
"name": "Multi 4-in-1 (STM32F103C)"
}],
"toolsDependencies": [{
"packager": "arduino",
"name": "arm-none-eabi-gcc",
"version": "4.8.3-2014q1"
}]
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.0.5.tar.gz",
"archiveFileName": "package_multi_4in1_avr_board_v1.0.5.tar.gz",
"checksum": "SHA-256:0a4754d47cdbb49ca194b15835686331530ed9d36c0db093a29ae5f865e75421",
"size": "169830",
"boards": [
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
{"name": "Multi 4-in-1 (OrangeRX)"}
],
"toolsDependencies": []
},
{
"name": "Multi 4-in-1 AVR Boards",
"architecture": "avr",
"version": "1.0.6",
"category": "Contributed",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.0.6.tar.gz",
"archiveFileName": "package_multi_4in1_avr_board_v1.0.6.tar.gz",
"checksum": "SHA-256:4f4cf8820e30bf6c88f280514c67ee67b9dc6649f439597cfb8d0be3a5b13bf5",
"size": "169819",
"boards": [
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
{"name": "Multi 4-in-1 (OrangeRX)"}
],
"toolsDependencies": []
},
{
"name": "Multi 4-in-1 AVR Boards",
"architecture": "avr",
"version": "1.0.7",
"category": "Contributed",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.0.7.tar.gz",
"archiveFileName": "package_multi_4in1_avr_board_v1.0.7.tar.gz",
"checksum": "SHA-256:453c9999e433ed1bdda2ba2b12cb7cbba7b547591db969dc6b7efb941b61cf76",
"size": "169825",
"boards": [
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
{"name": "Multi 4-in-1 (OrangeRX)"}
],
"toolsDependencies": []
},
{
"name": "Multi 4-in-1 AVR Boards",
"architecture": "avr",
"version": "1.0.8",
"category": "Contributed",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.0.8.tar.gz",
"archiveFileName": "package_multi_4in1_avr_board_v1.0.8.tar.gz",
"checksum": "SHA-256:8e58b8733220d56155e10bf5bec0bfe6bf96f8460b3fd49a4b45c7f9fad776cb",
"size": "293388",
"boards": [
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
{"name": "Multi 4-in-1 (OrangeRX)"}
],
"toolsDependencies": []
},
{
"name": "Multi 4-in-1 AVR Boards",
"architecture": "avr",
"version": "1.0.9",
"category": "Contributed",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.0.9.tar.gz",
"archiveFileName": "package_multi_4in1_avr_board_v1.0.9.tar.gz",
"checksum": "SHA-256:269c4ddcb8018be2b31f5c9e9f0814d120af492e894b8d5098a814486d56faa5",
"size": "318437",
"boards": [
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
{"name": "Multi 4-in-1 (OrangeRX)"}
],
"toolsDependencies": []
},
{
"name": "Multi 4-in-1 AVR Boards",
"architecture": "avr",
"version": "1.1.0",
"category": "Contributed",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.1.0.tar.gz",
"archiveFileName": "package_multi_4in1_avr_board_v1.1.0.tar.gz",
"checksum": "SHA-256:7bacf2db754ceb890a203de5ce89d97aa787a9e6462debeb44cf04830859687a",
"size": "326431",
"boards": [
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
{"name": "Multi 4-in-1 (OrangeRX)"}
],
"toolsDependencies": []
},
{
"name": "Multi 4-in-1 STM32 Board",
@@ -127,7 +181,7 @@
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.0.1.tar.gz",
"archiveFileName": "package_multi_4in1_stm32_board_v1.0.1.tar.gz",
"checksum": "SHA-256:b522b5d3474308768c197a6897cad037fb54d6fac26c75678415a0908793bae3",
"size": "10332106",
"size": "10332875",
"boards": [{
"name": "Multi 4-in-1 (STM32F103C)"
}],
@@ -147,7 +201,7 @@
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.0.2.tar.gz",
"archiveFileName": "package_multi_4in1_stm32_board_v1.0.2.tar.gz",
"checksum": "SHA-256:26D21DBD2FE80680AC523B8BCA24B3ECF2C2016BAC626826D20B651E11278287",
"checksum": "SHA-256:26d21dbd2fe80680ac523b8bca24b3ecf2c2016bac626826d20b651e11278287",
"size": "10318646",
"boards": [{
"name": "Multi 4-in-1 (STM32F103C)"
@@ -347,7 +401,133 @@
"version": "4.8.3-2014q1"
}]
},
{
{
"name": "Multi 4-in-1 STM32 Board",
"architecture": "STM32F1",
"version": "1.1.2",
"category": "Contributed",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.2.tar.gz",
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.2.tar.gz",
"checksum": "SHA-256:debfdc14df3023045a2297bc99daf7104be75f21572fc5a4f57192ffae4028f0",
"size": "10322776",
"boards": [{
"name": "Multi 4-in-1 (STM32F103C)"
}],
"toolsDependencies": [{
"packager": "arduino",
"name": "arm-none-eabi-gcc",
"version": "4.8.3-2014q1"
}]
},
{
"name": "Multi 4-in-1 STM32 Board",
"architecture": "STM32F1",
"version": "1.1.3",
"category": "Contributed",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.3.tar.gz",
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.3.tar.gz",
"checksum": "SHA-256:6b9dceb033ccc31f37cebc4f025ddb862cd24a733e7c356ca2fa5719d595af89",
"size": "10322145",
"boards": [{
"name": "Multi 4-in-1 (STM32F103C)"
}],
"toolsDependencies": [{
"packager": "arduino",
"name": "arm-none-eabi-gcc",
"version": "4.8.3-2014q1"
}]
},
{
"name": "Multi 4-in-1 STM32 Board",
"architecture": "STM32F1",
"version": "1.1.4",
"category": "Contributed",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.4.tar.gz",
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.4.tar.gz",
"checksum": "SHA-256:16a83a3b4409cb55aead6593396979483996080634d214ae07c8a956db2480fb",
"size": "10322152",
"boards": [{
"name": "Multi 4-in-1 (STM32F103C)"
}],
"toolsDependencies": [{
"packager": "arduino",
"name": "arm-none-eabi-gcc",
"version": "4.8.3-2014q1"
}]
},
{
"name": "Multi 4-in-1 STM32 Board",
"architecture": "STM32F1",
"version": "1.1.5",
"category": "Contributed",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.5.tar.gz",
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.5.tar.gz",
"checksum": "SHA-256:2d45c95f59b4fb9fc7f7bf8caca2dd8c13b4258141c20db6169e0c7faf72e5e4",
"size": "7930904",
"boards": [{
"name": "Multi 4-in-1 (STM32F103C)"
}],
"toolsDependencies": [{
"packager": "arduino",
"name": "arm-none-eabi-gcc",
"version": "4.8.3-2014q1"
}]
},
{
"name": "Multi 4-in-1 STM32 Board",
"architecture": "STM32F1",
"version": "1.1.6",
"category": "Contributed",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.6.tar.gz",
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.6.tar.gz",
"checksum": "SHA-256:d2d1ef721bbcdc3c680c6f98b4b8ab394478ac0f82d67af2f6c389a4a30789f4",
"size": "7962942",
"boards": [{
"name": "Multi 4-in-1 (STM32F103C)"
}],
"toolsDependencies": [{
"packager": "arduino",
"name": "arm-none-eabi-gcc",
"version": "4.8.3-2014q1"
}]
},
{
"name": "Multi 4-in-1 STM32 Board",
"architecture": "STM32F1",
"version": "1.1.7",
"category": "Contributed",
"help": {
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
},
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.7.tar.gz",
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.7.tar.gz",
"checksum": "SHA-256:37cccde7eafad3d0587d28d13d5f8b2b3244bf7c83e6819b6cb08f4f468815e2",
"size": "7966348",
"boards": [{
"name": "Multi 4-in-1 (STM32F103C)"
}],
"toolsDependencies": [{
"packager": "arduino",
"name": "arm-none-eabi-gcc",
"version": "4.8.3-2014q1"
}]
},
{
"name": "Multi 4-in-1 OrangeRX Board - DEPRECATED, USE MULTI 4-IN-1 AVR BOARDS PACKAGE INSTEAD",
"architecture": "orangerx",
"version": "1.0.1",

View File

@@ -183,8 +183,8 @@ void A7105_AdjustLOBaseFreq(uint8_t cmd)
#endif
break;
case PROTO_BUGS:
#ifdef FORCE_HUBSAN_TUNING
offset=(int16_t)FORCE_HUBSAN_TUNING;
#ifdef FORCE_BUGS_TUNING
offset=(int16_t)FORCE_BUGS_TUNING;
#endif
break;
case PROTO_FLYSKY:
@@ -192,7 +192,18 @@ void A7105_AdjustLOBaseFreq(uint8_t cmd)
offset=(int16_t)FORCE_FLYSKY_TUNING;
#endif
break;
case PROTO_FLYZONE:
#ifdef FORCE_FLYZONE_TUNING
offset=(int16_t)FORCE_FLYZONE_TUNING;
#endif
break;
case PROTO_PELIKAN:
#ifdef FORCE_PELIKAN_TUNING
offset=(int16_t)FORCE_PELIKAN_TUNING;
#endif
break;
case PROTO_AFHDS2A:
case PROTO_AFHDS2A_RX:
#ifdef FORCE_AFHDS2A_TUNING
offset=(int16_t)FORCE_AFHDS2A_TUNING;
#endif
@@ -247,23 +258,7 @@ static void __attribute__((unused)) A7105_SetVCOBand(uint8_t vb1, uint8_t vb2)
A7105_WriteReg(A7105_25_VCO_SBCAL_I, vb2 | 0x08);
}
#ifdef HUBSAN_A7105_INO
const uint8_t PROGMEM HUBSAN_A7105_regs[] = {
0xFF, 0x63, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF ,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x04, 0xFF, // 00 - 0f
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2B, 0xFF, 0xFF, 0x62, 0x80, 0xFF, 0xFF, 0x0A, 0xFF, 0xFF, 0x07, // 10 - 1f
0x17, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 20 - 2f
0xFF, 0xFF // 30 - 31
};
#endif
#ifdef FLYSKY_A7105_INO
const uint8_t PROGMEM FLYSKY_A7105_regs[] = {
0xff, 0x42, 0x00, 0x14, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50, // 00 - 0f
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x0f, // 10 - 1f
0x13, 0xc3, 0x00, 0xff, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f
0x01, 0x0f // 30 - 31
};
#endif
#ifdef AFHDS2A_A7105_INO
#if defined(AFHDS2A_A7105_INO) || defined(AFHDS2A_RX_A7105_INO)
const uint8_t PROGMEM AFHDS2A_A7105_regs[] = {
0xFF, 0x42 | (1<<5), 0x00, 0x25, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3c, 0x05, 0x00, 0x50, // 00 - 0f
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x4f, 0x62, 0x80, 0xFF, 0xFF, 0x2a, 0x32, 0xc3, 0x1f, // 10 - 1f
@@ -279,6 +274,38 @@ const uint8_t PROGMEM BUGS_A7105_regs[] = {
0x01, 0x0f // 30 - 31
};
#endif
#ifdef FLYSKY_A7105_INO
const uint8_t PROGMEM FLYSKY_A7105_regs[] = {
0xff, 0x42, 0x00, 0x14, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50, // 00 - 0f
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x0f, // 10 - 1f
0x13, 0xc3, 0x00, 0xff, 0x00, 0x00, 0x3b, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f
0x01, 0x0f // 30 - 31
};
#endif
#ifdef FLYZONE_A7105_INO
const uint8_t PROGMEM FLYZONE_A7105_regs[] = {
0xff, 0x42, 0x00, 0x07, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x01, 0x50, // 00 - 0f
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x1f, // 10 - 1f
0x12, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3a, 0x00, 0x3f, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f
0x01, 0x0f // 30 - 31
};
#endif
#ifdef HUBSAN_A7105_INO
const uint8_t PROGMEM HUBSAN_A7105_regs[] = {
0xFF, 0x63, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF ,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x04, 0xFF, // 00 - 0f
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2B, 0xFF, 0xFF, 0x62, 0x80, 0xFF, 0xFF, 0x0A, 0xFF, 0xFF, 0x07, // 10 - 1f
0x17, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x47, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 20 - 2f
0xFF, 0xFF // 30 - 31
};
#endif
#ifdef PELIKAN_A7105_INO
const uint8_t PROGMEM PELIKAN_A7105_regs[] = {
0xff, 0x42, 0x00, 0x0F, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x01, 0x50, // 00 - 0f
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x07, // 10 - 1f
0x16, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3b, 0x00, 0x1f, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f
0x01, 0x0f // 30 - 31
};
#endif
#define ID_NORMAL 0x55201041
#define ID_PLUS 0xAA201041
@@ -287,6 +314,22 @@ void A7105_Init(void)
uint8_t *A7105_Regs=0;
uint8_t vco_calibration0, vco_calibration1;
#ifdef FLYZONE_A7105_INO
if(protocol==PROTO_FLYZONE)
{
A7105_Regs=(uint8_t*)FLYZONE_A7105_regs;
A7105_WriteID(0x25A53C45);
}
else
#endif
#ifdef PELIKAN_A7105_INO
if(protocol==PROTO_PELIKAN)
{
A7105_Regs=(uint8_t*)PELIKAN_A7105_regs;
A7105_WriteID(0x06230623);
}
else
#endif
#ifdef BUGS_A7105_INO
if(protocol==PROTO_BUGS)
A7105_Regs=(uint8_t*)BUGS_A7105_regs;
@@ -308,7 +351,7 @@ void A7105_Init(void)
else
#endif
{
#ifdef AFHDS2A_A7105_INO
#if defined(AFHDS2A_A7105_INO) || defined(AFHDS2A_RX_A7105_INO)
A7105_Regs=(uint8_t*)AFHDS2A_A7105_regs;
#endif
}
@@ -360,12 +403,30 @@ void A7105_Init(void)
A7105_SetVCOBand(vco_calibration0 & 0x07, vco_calibration1 & 0x07); // Set calibration band value to best match
else
if(protocol!=PROTO_HUBSAN)
A7105_WriteReg(A7105_25_VCO_SBCAL_I,protocol==PROTO_FLYSKY?0x08:0x0A); //Reset VCO Band calibration
{
switch(protocol)
{
case PROTO_FLYSKY:
vco_calibration1=0x08;
break;
case PROTO_FLYZONE:
vco_calibration1=0x02;
break;
case PROTO_PELIKAN:
vco_calibration1=0x0C;
break;
default:
vco_calibration1=0x0A;
break;
}
A7105_WriteReg(A7105_25_VCO_SBCAL_I,vco_calibration1); //Reset VCO Band calibration
}
A7105_SetTxRxMode(TX_EN);
A7105_SetPower();
A7105_AdjustLOBaseFreq(0);
#ifdef USE_A7105_CH15_TUNING
A7105_AdjustLOBaseFreq(0);
#endif
A7105_Strobe(A7105_STANDBY);
}

View File

@@ -0,0 +1,203 @@
/*
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(AFHDS2A_RX_A7105_INO)
#include "iface_a7105.h"
#define AFHDS2A_RX_TXPACKET_SIZE 38
#define AFHDS2A_RX_RXPACKET_SIZE 37
#define AFHDS2A_RX_NUMFREQ 16
enum {
AFHDS2A_RX_BIND1,
AFHDS2A_RX_BIND2,
AFHDS2A_RX_DATA
};
static void __attribute__((unused)) AFHDS2A_Rx_build_telemetry_packet()
{
uint32_t bits = 0;
uint8_t bitsavailable = 0;
uint8_t idx = 0;
packet_in[idx++] = RX_LQI; // 0 - 130
packet_in[idx++] = RX_RSSI;
packet_in[idx++] = 0; // start channel
packet_in[idx++] = 14; // number of channels in packet
// pack channels
for (uint8_t i = 0; i < 14; i++) {
uint32_t val = packet[9+i*2] | (packet[10+i*2] << 8);
if (val < 860)
val = 860;
// convert ppm (860-2140) to Multi (0-2047)
val = min(((val-860)<<3)/5, 2047);
bits |= val << bitsavailable;
bitsavailable += 11;
while (bitsavailable >= 8) {
packet_in[idx++] = bits & 0xff;
bits >>= 8;
bitsavailable -= 8;
}
}
}
static uint8_t __attribute__((unused)) AFHDS2A_Rx_data_ready()
{
// check if FECF+CRCF Ok
return !(A7105_ReadReg(A7105_00_MODE) & (1 << 5 | 1 << 6 | 1 << 0));
}
uint16_t initAFHDS2A_Rx()
{
uint8_t i;
A7105_Init();
hopping_frequency_no = 0;
packet_count = 0;
rx_data_started = false;
rx_disable_lna = IS_POWER_FLAG_on;
A7105_SetTxRxMode(rx_disable_lna ? TXRX_OFF : RX_EN);
A7105_Strobe(A7105_RX);
if (IS_BIND_IN_PROGRESS) {
phase = AFHDS2A_RX_BIND1;
}
else {
uint16_t temp = AFHDS2A_RX_EEPROM_OFFSET;
for (i = 0; i < 4; i++)
rx_id[i] = eeprom_read_byte((EE_ADDR)temp++);
for (i = 0; i < AFHDS2A_RX_NUMFREQ; i++)
hopping_frequency[i] = eeprom_read_byte((EE_ADDR)temp++);
phase = AFHDS2A_RX_DATA;
}
return 1000;
}
#define AFHDS2A_RX_WAIT_WRITE 0x80
uint16_t AFHDS2A_Rx_callback()
{
static uint32_t pps_timer = 0;
static uint16_t pps_counter = 0;
static int8_t read_retry;
int16_t temp;
uint8_t i;
#ifndef FORCE_AFHDS2A_TUNING
A7105_AdjustLOBaseFreq(1);
#endif
if (rx_disable_lna != IS_POWER_FLAG_on) {
rx_disable_lna = IS_POWER_FLAG_on;
A7105_SetTxRxMode(rx_disable_lna ? TXRX_OFF : RX_EN);
}
switch(phase) {
case AFHDS2A_RX_BIND1:
if (AFHDS2A_Rx_data_ready()) {
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
if ((packet[0] == 0xbb && packet[9] == 0x01) || (packet[0] == 0xbc && packet[9] <= 0x02)) {
memcpy(rx_id, &packet[1], 4); // TX id actually
memcpy(hopping_frequency, &packet[11], AFHDS2A_RX_NUMFREQ);
phase = AFHDS2A_RX_BIND2;
}
}
A7105_WriteReg(A7105_0F_PLL_I, (packet_count++ & 1) ? 0x0D : 0x8C); // bind channels
A7105_SetTxRxMode(RX_EN);
A7105_Strobe(A7105_RX);
return 10000;
case AFHDS2A_RX_BIND2:
// got 2nd bind packet from tx ?
if (AFHDS2A_Rx_data_ready()) {
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
if ((packet[0] == 0xBC && packet[9] == 0x02 && packet[10] == 0x00) &&
(memcmp(rx_id, &packet[1], 4) == 0) &&
(memcmp(rx_tx_addr, &packet[5], 4) == 0)) {
// save tx info to eeprom
temp = AFHDS2A_RX_EEPROM_OFFSET;
for (i = 0; i < 4; i++)
eeprom_write_byte((EE_ADDR)temp++, rx_id[i]);
for (i = 0; i < AFHDS2A_RX_NUMFREQ; i++)
eeprom_write_byte((EE_ADDR)temp++, hopping_frequency[i]);
BIND_DONE;
phase = AFHDS2A_RX_DATA;
return 3850;
}
}
// transmit response packet
packet[0] = 0xBC;
memcpy(&packet[1], rx_id, 4);
memcpy(&packet[5], rx_tx_addr, 4);
packet[9] = 0x01;
packet[10] = 0x00;
memset(&packet[11], 0xFF, 26);
A7105_WriteData(AFHDS2A_RX_RXPACKET_SIZE, packet_count++ & 1 ? 0x0D : 0x8C);
phase |= AFHDS2A_RX_WAIT_WRITE;
return 1700;
case AFHDS2A_RX_BIND2 | AFHDS2A_RX_WAIT_WRITE:
//Wait for TX completion
pps_timer = micros();
while (micros() - pps_timer < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
if (!(A7105_ReadReg(A7105_00_MODE) & 0x01))
break;
A7105_Strobe(A7105_RX);
phase &= ~AFHDS2A_RX_WAIT_WRITE;
return 10000;
case AFHDS2A_RX_DATA:
if (AFHDS2A_Rx_data_ready()) {
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
if (memcmp(&packet[1], rx_id, 4) == 0 && memcmp(&packet[5], rx_tx_addr, 4) == 0) {
if (packet[0] == 0x58 && packet[37] == 0x00 && telemetry_link == 0) { // standard packet, send channels to TX
int rssi = min(A7105_ReadReg(A7105_1D_RSSI_THOLD),160);
RX_RSSI = map16b(rssi, 160, 8, 0, 128);
AFHDS2A_Rx_build_telemetry_packet();
telemetry_link = 1;
}
rx_data_started = true;
read_retry = 10; // hop to next channel
pps_counter++;
}
}
// packets per second
if (millis() - pps_timer >= 1000) {
pps_timer = millis();
debugln("%d pps", pps_counter);
RX_LQI = pps_counter / 2;
pps_counter = 0;
}
// frequency hopping
if (read_retry++ >= 10) {
hopping_frequency_no++;
if(hopping_frequency_no >= AFHDS2A_RX_NUMFREQ)
hopping_frequency_no = 0;
A7105_WriteReg(A7105_0F_PLL_I, hopping_frequency[hopping_frequency_no]);
A7105_Strobe(A7105_RX);
if (rx_data_started)
read_retry = 0;
else
read_retry = -127; // retry longer until first packet is catched
}
return 385;
}
return 3850; // never reached
}
#endif

View File

@@ -78,56 +78,62 @@ enum{
static void AFHDS2A_update_telemetry()
{
if(packet[0]==0xAA && packet[9]==0xFD)
return; // ignore packets which contain the RX configuration: FD FF 32 00 01 00 FF FF FF 05 DC 05 DE FA FF FF FF FF FF FF FF FF FF FF FF FF FF FF
// Read TX RSSI
int16_t temp=256-(A7105_ReadReg(A7105_1D_RSSI_THOLD)*8)/5; // value from A7105 is between 8 for maximum signal strength to 160 or less
if(temp<0) temp=0;
else if(temp>255) temp=255;
TX_RSSI=temp;
// AA | TXID | rx_id | sensor id | sensor # | value 16 bit big endian | sensor id ......
// max 7 sensors per packet
// AC | TXID | rx_id | sensor id | sensor # | length | bytes | sensor id ......
#ifdef AFHDS2A_FW_TELEMETRY
if (option & 0x80)
{
// forward telemetry to TX, skip rx and tx id to save space
pkt[0]= TX_RSSI;
debug("T=");
for(int i=9;i < AFHDS2A_RXPACKET_SIZE; i++)
{// forward 0xAA and 0xAC telemetry to TX, skip rx and tx id to save space
packet_in[0]= TX_RSSI;
debug("T(%02X)=",packet[0]);
for(uint8_t i=9;i < AFHDS2A_RXPACKET_SIZE; i++)
{
pkt[i-8]=packet[i];
packet_in[i-8]=packet[i];
debug(" %02X",packet[i]);
}
debugln("");
packet_in[29]=packet[0]; // 0xAA Normal telemetry, 0xAC Extended telemetry
telemetry_link=2;
debugln("");
return;
}
#endif
#ifdef AFHDS2A_HUB_TELEMETRY
for(uint8_t sensor=0; sensor<7; sensor++)
{
// Send FrSkyD telemetry to TX
uint8_t index = 9+(4*sensor);
switch(packet[index])
if(packet[0]==0xAA)
{ // 0xAA Normal telemetry, 0xAC Extended telemetry not decoded here
for(uint8_t sensor=0; sensor<7; sensor++)
{
case AFHDS2A_SENSOR_RX_VOLTAGE:
//v_lipo1 = packet[index+3]<<8 | packet[index+2];
v_lipo1 = packet[index+2];
telemetry_link=1;
break;
case AFHDS2A_SENSOR_A3_VOLTAGE:
v_lipo2 = (packet[index+3]<<5) | (packet[index+2]>>3); // allows to read voltage up to 4S
telemetry_link=1;
break;
case AFHDS2A_SENSOR_RX_ERR_RATE:
RX_LQI=packet[index+2];
break;
case AFHDS2A_SENSOR_RX_RSSI:
RX_RSSI = -packet[index+2];
break;
case 0xff:
return;
/*default:
// unknown sensor ID
break;*/
// Send FrSkyD telemetry to TX
uint8_t index = 9+(4*sensor);
switch(packet[index])
{
case AFHDS2A_SENSOR_RX_VOLTAGE:
//v_lipo1 = packet[index+3]<<8 | packet[index+2];
v_lipo1 = packet[index+2];
telemetry_link=1;
break;
case AFHDS2A_SENSOR_A3_VOLTAGE:
v_lipo2 = (packet[index+3]<<5) | (packet[index+2]>>3); // allows to read voltage up to 4S
telemetry_link=1;
break;
case AFHDS2A_SENSOR_RX_ERR_RATE:
if(packet[index+2]<=100)
RX_LQI=packet[index+2];
break;
case AFHDS2A_SENSOR_RX_RSSI:
RX_RSSI = -packet[index+2];
break;
case 0xff: // end of data
return;
/*default:
// unknown sensor ID
break;*/
}
}
}
#endif
@@ -259,11 +265,15 @@ uint16_t ReadAFHDS2A()
A7105_ReadData(AFHDS2A_RXPACKET_SIZE);
if(packet[0] == 0xbc && packet[9] == 0x01)
{
uint8_t temp=AFHDS2A_EEPROM_OFFSET+RX_num*4;
uint8_t addr;
if(RX_num<16)
addr=AFHDS2A_EEPROM_OFFSET+RX_num*4;
else
addr=AFHDS2A_EEPROM_OFFSET2+(RX_num-16)*4;
for(uint8_t i=0; i<4; i++)
{
rx_id[i] = packet[5+i];
eeprom_write_byte((EE_ADDR)(temp+i),rx_id[i]);
eeprom_write_byte((EE_ADDR)(addr+i),rx_id[i]);
}
phase = AFHDS2A_BIND4;
packet_count++;
@@ -271,6 +281,11 @@ uint16_t ReadAFHDS2A()
}
}
packet_count++;
if(IS_BIND_DONE)
{ // exit bind if asked to do so from the GUI
phase = AFHDS2A_BIND4;
return 3850;
}
phase |= AFHDS2A_WAIT_WRITE;
return 1700;
case AFHDS2A_BIND1|AFHDS2A_WAIT_WRITE:
@@ -306,6 +321,9 @@ uint16_t ReadAFHDS2A()
packet_type = AFHDS2A_PACKET_STICKS;
phase = AFHDS2A_DATA;
case AFHDS2A_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(3850);
#endif
AFHDS2A_build_packet(packet_type);
if((A7105_ReadReg(A7105_00_MODE) & 0x01)) // Check if something has been received...
data_rx=0;
@@ -320,7 +338,10 @@ uint16_t ReadAFHDS2A()
{
#ifdef FAILSAFE_ENABLE
if(!(packet_counter % 1569) && IS_FAILSAFE_VALUES_on)
{
packet_type = AFHDS2A_PACKET_FAILSAFE;
FAILSAFE_VALUES_off;
}
else
#endif
packet_type = AFHDS2A_PACKET_STICKS; // todo : check for settings changes
@@ -328,25 +349,32 @@ uint16_t ReadAFHDS2A()
if(!(A7105_ReadReg(A7105_00_MODE) & (1<<5 | 1<<6)) && data_rx==1)
{ // RX+FECF+CRCF Ok
A7105_ReadData(AFHDS2A_RXPACKET_SIZE);
if(packet[0] == 0xaa)
{
if(packet[9] == 0xfc)
packet_type=AFHDS2A_PACKET_SETTINGS; // RX is asking for settings
else
if(packet[0] == 0xAA && packet[9] == 0xFC)
packet_type=AFHDS2A_PACKET_SETTINGS; // RX is asking for settings
else
if(packet[0] == 0xAA || packet[0] == 0xAC)
{
#ifdef AFHDS2A_LQI_CH
for(uint8_t sensor=0; sensor<7; sensor++)
{//read LQI value for RX output
uint8_t index = 9+(4*sensor);
if(packet[index]==AFHDS2A_SENSOR_RX_ERR_RATE)
RX_LQI=packet[index+2];
}
#endif
#if defined(AFHDS2A_FW_TELEMETRY) || defined(AFHDS2A_HUB_TELEMETRY)
AFHDS2A_update_telemetry();
#endif
if(!memcmp(&packet[1], rx_tx_addr, 4))
{ // TX address validated
#ifdef AFHDS2A_LQI_CH
if(packet[0]==0xAA && packet[9]!=0xFD)
{// Normal telemetry packet
for(uint8_t sensor=0; sensor<7; sensor++)
{//read LQI value for RX output
uint8_t index = 9+(4*sensor);
if(packet[index]==AFHDS2A_SENSOR_RX_ERR_RATE && packet[index+2]<=100)
{
RX_LQI=packet[index+2];
break;
}
}
}
#endif
#if defined(AFHDS2A_FW_TELEMETRY) || defined(AFHDS2A_HUB_TELEMETRY)
AFHDS2A_update_telemetry();
#endif
}
}
}
}
packet_counter++;
phase |= AFHDS2A_WAIT_WRITE;
@@ -379,14 +407,15 @@ uint16_t initAFHDS2A()
{
phase = AFHDS2A_DATA_INIT;
//Read RX ID from EEPROM based on RX_num, RX_num must be uniq for each RX
uint8_t temp=AFHDS2A_EEPROM_OFFSET+RX_num*4;
uint8_t addr;
if(RX_num<16)
addr=AFHDS2A_EEPROM_OFFSET+RX_num*4;
else
addr=AFHDS2A_EEPROM_OFFSET2+(RX_num-16)*4;
for(uint8_t i=0;i<4;i++)
rx_id[i]=eeprom_read_byte((EE_ADDR)(temp+i));
rx_id[i]=eeprom_read_byte((EE_ADDR)(addr+i));
}
hopping_frequency_no = 0;
#if defined(AFHDS2A_FW_TELEMETRY) || defined(AFHDS2A_HUB_TELEMETRY)
init_frskyd_link_telemetry();
#endif
return 50000;
}
#endif

View File

@@ -127,6 +127,9 @@ uint16_t ASSAN_callback()
phase=ASSAN_DATA2;
return 2000;
case ASSAN_DATA2:
#ifdef MULTI_SYNC
telemetry_set_input_sync(12000);
#endif
case ASSAN_DATA3:
ASSAN_send_packet();
phase++; // DATA 3 or 4

View File

@@ -42,6 +42,7 @@ enum {
#define BUGSMINI_CH_SW_PICTURE CH8_SW
#define BUGSMINI_CH_SW_VIDEO CH9_SW
#define BUGSMINI_CH_SW_LED CH10_SW
#define BUGSMINI_CH_SW_ALTHOLD CH11_SW
// flags packet[12]
#define BUGSMINI_FLAG_FLIP 0x08 // automatic flip
@@ -54,6 +55,7 @@ enum {
#define BUGSMINI_FLAG_ARM 0x40 // arm (toggle to turn on motors)
#define BUGSMINI_FLAG_DISARM 0x20 // disarm (toggle to turn off motors)
#define BUGSMINI_FLAG_ANGLE 0x02 // angle/acro mode (set is angle mode)
#define BUGSMINI_FLAG_ALTHOLD 0x04 // angle/altitude hold mode (set is altitude mode)
static void __attribute__((unused)) BUGSMINI_init()
{
@@ -133,7 +135,7 @@ static void __attribute__((unused)) BUGSMINI_send_packet(uint8_t bind)
packet[10]= (((rudder / 5) >> 1) + 7) // dynamic trim 0x07 - 0x39
| (rudder << 7);
packet[11]= 0x40 | (throttle << 7);
packet[12]= 0x80 | ((packet[12] ^ 0x40) & 0x40) // bugs 3 H doesn't have 0x80 ?
packet[12]= 0x80 | ((packet[12] ^ 0x40) & 0x40)
| BUGSMINI_FLAG_MODE
| GET_FLAG(BUGSMINI_CH_SW_PICTURE, BUGSMINI_FLAG_PICTURE)
| GET_FLAG(BUGSMINI_CH_SW_VIDEO, BUGSMINI_FLAG_VIDEO);
@@ -141,10 +143,11 @@ static void __attribute__((unused)) BUGSMINI_send_packet(uint8_t bind)
packet[12] |= GET_FLAG(BUGSMINI_CH_SW_FLIP, BUGSMINI_FLAG_FLIP);
packet[13] = arm_flags
| GET_FLAG(BUGSMINI_CH_SW_LED, BUGSMINI_FLAG_LED)
| GET_FLAG(BUGSMINI_CH_SW_ALTHOLD, BUGSMINI_FLAG_ALTHOLD)
| GET_FLAG(BUGSMINI_CH_SW_ANGLE, BUGSMINI_FLAG_ANGLE);
// BUGS3H althold -> BUGSMINI_FLAG_ALTHOLD|BUGSMINI_FLAG_ANGLE , angle -> 0
packet[14] = 0;
packet[15] = 0; // 0x53 on bugs 3 H ?
packet[15] = 0; // a lot of 0x53 and some 0x52 on bugs 3H
}
uint8_t checksum = 0x6d;
for(uint8_t i=1; i < BUGSMINI_TX_PAYLOAD_SIZE; i++)
@@ -178,7 +181,7 @@ static void __attribute__((unused)) BUGSMINI_make_address()
uint8_t start, length, index;
//read rxid
uint8_t base_adr=BUGSMINI_EEPROM_OFFSET+RX_num*2;
uint8_t base_adr=BUGSMINI_EEPROM_OFFSET+(RX_num&0x0F)*2;
uint8_t rxid_high = eeprom_read_byte((EE_ADDR)(base_adr+0));
uint8_t rxid_low = eeprom_read_byte((EE_ADDR)(base_adr+1));
@@ -269,7 +272,7 @@ uint16_t BUGSMINI_callback()
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // RX fifo data ready
XN297_ReadPayload(packet, BUGSMINI_RX_PAYLOAD_SIZE);
base_adr=BUGSMINI_EEPROM_OFFSET+RX_num*2;
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);
@@ -296,6 +299,9 @@ uint16_t BUGSMINI_callback()
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);
@@ -309,8 +315,8 @@ uint16_t BUGSMINI_callback()
case BUGSMINI_DATA2:
// switch to RX mode
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(RX_EN);
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));
phase = BUGSMINI_DATA1;
@@ -372,9 +378,6 @@ uint16_t initBUGSMINI()
armed = 0;
arm_flags = BUGSMINI_FLAG_DISARM; // initial value from captures
arm_channel_previous = BUGSMINI_CH_SW_ARM;
#ifdef BUGS_HUB_TELEMETRY
init_frskyd_link_telemetry();
#endif
return BUGSMINI_INITIAL_WAIT;
}

View File

@@ -0,0 +1,207 @@
/*
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(BAYANG_RX_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define BAYANG_RX_PACKET_SIZE 15
#define BAYANG_RX_RF_NUM_CHANNELS 4
#define BAYANG_RX_RF_BIND_CHANNEL 0
#define BAYANG_RX_ADDRESS_LENGTH 5
enum {
BAYANG_RX_BIND = 0,
BAYANG_RX_DATA
};
static void __attribute__((unused)) Bayang_Rx_init_nrf24l01()
{
const uint8_t bind_address[BAYANG_RX_ADDRESS_LENGTH] = { 0,0,0,0,0 };
NRF24L01_Initialize();
XN297_SetTXAddr(bind_address, BAYANG_RX_ADDRESS_LENGTH);
XN297_SetRXAddr(bind_address, BAYANG_RX_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, BAYANG_RX_PACKET_SIZE + 2); // 2 extra bytes for xn297 crc
NRF24L01_WriteReg(NRF24L01_05_RF_CH, BAYANG_RX_RF_BIND_CHANNEL);
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
NRF24L01_Activate(0x73);
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));
}
static uint8_t __attribute__((unused)) Bayang_Rx_check_validity() {
uint8_t sum = packet[0];
for (uint8_t i = 1; i < BAYANG_RX_PACKET_SIZE - 1; i++)
sum += packet[i];
return sum == packet[14];
}
static void __attribute__((unused)) Bayang_Rx_build_telemetry_packet()
{
uint32_t bits = 0;
uint8_t bitsavailable = 0;
uint8_t idx = 0;
packet_in[idx++] = RX_LQI;
packet_in[idx++] = RX_LQI>>1; // no RSSI: 125..0
packet_in[idx++] = 0; // start channel
packet_in[idx++] = 10; // number of channels in packet
// convert & pack channels
for (uint8_t i = 0; i < packet_in[3]; i++) {
uint32_t val = CHANNEL_MIN_100;
if (i < 4) {
// AETR
//val = (((packet[4 + i * 2] & ~0x7C) << 8) | packet[5 + i * 2]) << 1;
val=packet[4 + i * 2]&0x03;
val=(val<<8)+packet[5 + i * 2];
val=((val+128)<<3)/5;
} else if (i == 4 || i == 5) {
val=packet[i==4?1:13];
val=((val+32)<<5)/5; // extra analog channel
} else if (((i == 6) && (packet[2] & 0x08)) || // flip
((i == 7) && (packet[2] & 0x01)) || // rth
((i == 8) && (packet[2] & 0x20)) || // picture
((i == 9) && (packet[2] & 0x10))) { // video
// set channel to 100% if feature is enabled
val = CHANNEL_MAX_100;
}
bits |= val << bitsavailable;
bitsavailable += 11;
while (bitsavailable >= 8) {
packet_in[idx++] = bits & 0xff;
bits >>= 8;
bitsavailable -= 8;
}
}
}
uint16_t initBayang_Rx()
{
uint8_t i;
Bayang_Rx_init_nrf24l01();
hopping_frequency_no = 0;
rx_data_started = false;
rx_data_received = false;
if (IS_BIND_IN_PROGRESS) {
phase = BAYANG_RX_BIND;
}
else {
uint16_t temp = BAYANG_RX_EEPROM_OFFSET;
for (i = 0; i < 5; i++)
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_SetTXAddr(rx_tx_addr, BAYANG_RX_ADDRESS_LENGTH);
XN297_SetRXAddr(rx_tx_addr, BAYANG_RX_ADDRESS_LENGTH);
phase = BAYANG_RX_DATA;
}
return 1000;
}
uint16_t Bayang_Rx_callback()
{
uint8_t i;
static int8_t read_retry;
static uint16_t pps_counter;
static uint32_t pps_timer = 0;
switch (phase) {
case BAYANG_RX_BIND:
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 == 0) {
Bayang_Rx_build_telemetry_packet();
telemetry_link = 1;
}
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)
{
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
read_retry = -16; // retry longer until first packet is caught
}
return 250;
}
return 1000;
}
#endif

View File

@@ -20,7 +20,8 @@ Multiprotocol is distributed in the hope that it will be useful,
#include "iface_nrf24l01.h"
#define BAYANG_BIND_COUNT 1000
#define BAYANG_PACKET_PERIOD 1000
#define BAYANG_PACKET_PERIOD 2000
#define BAYANG_PACKET_TELEM_PERIOD 5000
#define BAYANG_INITIAL_WAIT 500
#define BAYANG_PACKET_SIZE 15
#define BAYANG_RF_NUM_CHANNELS 4
@@ -46,10 +47,10 @@ enum BAYANG_OPTION_FLAGS {
BAYANG_OPTION_FLAG_ANALOGAUX = 0x02,
};
static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
static void __attribute__((unused)) BAYANG_send_packet()
{
uint8_t i;
if (bind)
if (IS_BIND_IN_PROGRESS)
{
#ifdef BAYANG_HUB_TELEMETRY
if(option & BAYANG_OPTION_FLAG_TELEMETRY)
@@ -62,7 +63,7 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
else
#else
if(option & BAYANG_OPTION_FLAG_ANALOGAUX)
packet[0]= 0xA2; // analog aux is enabled
packet[0]= 0xA2; // analog aux is enabled
else
#endif
packet[0]= 0xA4;
@@ -80,6 +81,10 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
packet[10] = 0x30;
packet[11] = 0x01;
break;
case DHD_D4:
packet[10] = 0xC8;
packet[11] = 0x99;
break;
default:
packet[10] = rx_tx_addr[0]; // txid[0]
packet[11] = rx_tx_addr[1]; // txid[1]
@@ -106,7 +111,7 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
packet[1] = convert_channel_8b(CH14);
}
else
packet[1] = 0xFA; // normal mode is 0xf7, expert 0xfa
packet[1] = 0xFA; // normal mode is 0xF7, expert 0xFa , D4 normal is 0xF4
//Flags packet[2]
packet[2] = 0x00;
@@ -164,11 +169,14 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
packet[12] = 0xE0;
packet[13] = 0x2E;
break;
case DHD_D4:
packet[12] = 0x37; //0x17 during bind
packet[13] = 0xED;
break;
default:
packet[12] = rx_tx_addr[2]; // txid[2]
if (option & BAYANG_OPTION_FLAG_ANALOGAUX)
{
// Analog aux channel 2 (channel 15)
{ // Analog aux channel 2 (channel 15)
packet[13] = convert_channel_8b(CH15);
}
else
@@ -179,29 +187,15 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
for (uint8_t i=0; i < BAYANG_PACKET_SIZE-1; i++)
packet[14] += packet[i];
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? rf_ch_num:hopping_frequency[hopping_frequency_no++]);
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;
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(packet, BAYANG_PACKET_SIZE);
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
// 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));
#ifdef BAYANG_HUB_TELEMETRY
if (option & BAYANG_OPTION_FLAG_TELEMETRY)
{ // switch radio to rx as soon as packet is sent
while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x03);
}
#endif
XN297_WritePayload(packet, BAYANG_PACKET_SIZE);
NRF24L01_SetPower(); // Set tx_power
}
@@ -226,7 +220,8 @@ static void __attribute__((unused)) BAYANG_check_rx(void)
// compensated battery volts*100/2
v_lipo2 = (packet[5]<<7) + (packet[6]>>2);
// reception in packets / sec
RX_RSSI = packet[7];
RX_LQI = packet[7];
RX_RSSI = RX_LQI;
//Flags
//uint8_t flags = packet[3] >> 3;
// battery low: flags & 1
@@ -235,6 +230,7 @@ static void __attribute__((unused)) BAYANG_check_rx(void)
telemetry_link=1;
}
}
NRF24L01_SetTxRxMode(TXRX_OFF);
}
#endif
@@ -271,53 +267,73 @@ static void __attribute__((unused)) BAYANG_init()
}
}
enum {
BAYANG_BIND=0,
BAYANG_WRITE,
BAYANG_CHECK,
BAYANG_READ,
};
#define BAYANG_CHECK_DELAY 1000 // Time after write phase to check write complete
#define BAYANG_READ_DELAY 600 // Time before read phase
uint16_t BAYANG_callback()
{
if(IS_BIND_DONE)
#ifdef BAYANG_HUB_TELEMETRY
uint16_t start;
#endif
switch(phase)
{
if(packet_count==0)
BAYANG_send_packet(0);
packet_count++;
#ifdef BAYANG_HUB_TELEMETRY
if (option & BAYANG_OPTION_FLAG_TELEMETRY)
{ // telemetry is enabled
state++;
if (state > 1000)
{
//calculate telemetry reception packet rate - packets per 1000ms
TX_RSSI = telemetry_counter;
telemetry_counter = 0;
state = 0;
telemetry_lost=0;
}
if (packet_count > 1)
BAYANG_check_rx();
packet_count %= 5;
case BAYANG_BIND:
if (--bind_counter == 0)
{
XN297_SetTXAddr(rx_tx_addr, BAYANG_ADDRESS_LENGTH);
#ifdef BAYANG_HUB_TELEMETRY
XN297_SetRXAddr(rx_tx_addr, BAYANG_ADDRESS_LENGTH);
#endif
BIND_DONE;
phase++; //WRITE
}
else
#endif
packet_count%=2;
}
else
{
if (bind_counter == 0)
{
XN297_SetTXAddr(rx_tx_addr, BAYANG_ADDRESS_LENGTH);
#ifdef BAYANG_HUB_TELEMETRY
XN297_SetRXAddr(rx_tx_addr, BAYANG_ADDRESS_LENGTH);
BAYANG_send_packet();
break;
case BAYANG_WRITE:
#ifdef MULTI_SYNC
telemetry_set_input_sync((option & BAYANG_OPTION_FLAG_TELEMETRY)?BAYANG_PACKET_TELEM_PERIOD:BAYANG_PACKET_PERIOD);
#endif
BIND_DONE;
}
else
{
if(packet_count==0)
BAYANG_send_packet(1);
packet_count++;
packet_count%=4;
bind_counter--;
}
BAYANG_send_packet();
#ifdef BAYANG_HUB_TELEMETRY
if (option & BAYANG_OPTION_FLAG_TELEMETRY)
{ // telemetry is enabled
state++;
if (state > 200)
{
state = 0;
//telemetry reception packet rate - packets per second
TX_LQI = telemetry_counter>>1;
telemetry_counter = 0;
telemetry_lost=0;
}
phase++; //CHECK
return BAYANG_CHECK_DELAY;
}
#endif
break;
#ifdef BAYANG_HUB_TELEMETRY
case BAYANG_CHECK:
// 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)))
break;
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x03);
phase++; // READ
return BAYANG_PACKET_TELEM_PERIOD - BAYANG_CHECK_DELAY - BAYANG_READ_DELAY;
case BAYANG_READ:
BAYANG_check_rx();
phase=BAYANG_WRITE;
return BAYANG_READ_DELAY;
#endif
}
return BAYANG_PACKET_PERIOD;
}
@@ -325,7 +341,10 @@ uint16_t BAYANG_callback()
static void __attribute__((unused)) BAYANG_initialize_txid()
{
//Could be using txid[0..2] but using rx_tx_addr everywhere instead...
hopping_frequency[0]=0;
if(sub_protocol==DHD_D4)
hopping_frequency[0]=(rx_tx_addr[2]&0x07)|0x01;
else
hopping_frequency[0]=0;
hopping_frequency[1]=(rx_tx_addr[3]&0x1F)+0x10;
hopping_frequency[2]=hopping_frequency[1]+0x20;
hopping_frequency[3]=hopping_frequency[2]+0x20;
@@ -335,14 +354,11 @@ static void __attribute__((unused)) BAYANG_initialize_txid()
uint16_t initBAYANG(void)
{
BIND_IN_PROGRESS; // autobind protocol
phase=BAYANG_BIND;
bind_counter = BAYANG_BIND_COUNT;
BAYANG_initialize_txid();
BAYANG_init();
packet_count=0;
#ifdef BAYANG_HUB_TELEMETRY
init_frskyd_link_telemetry();
telemetry_lost=1; // do not send telemetry to TX right away until we have a TX_RSSI value to prevent warning message...
#endif
return BAYANG_INITIAL_WAIT+BAYANG_PACKET_PERIOD;
}

View File

@@ -0,0 +1,184 @@
/*
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/>.
*/
/************************/
/** Firmware Signature **/
/************************/
/*
The firmware signature is appended to the compiled binary image in order to provide information
about the options used to compile the firmware file. This information is then used by Multi-module
flashing tools to verify that the image is correct / valid.
In order for the build process to determine the options used to build the firmware this file conditionally
declares 'flag' variables for the options we are interested in.
When the pre-compiler parses the source code these variables are either present or not in the parsed cpp file,
typically '$build_dir$/preproc/ctags_target_for_gcc_minus_e.cpp'.
Once the .bin file is created an additional command-line build tool scans the parsed cpp file, detects the
flags, assembles the signature, and finally appends the signature to the end of the binary file.
The signature is 24 bytes long:
multi-x[8-byte hex code]-[8-byte version number]
For example:
multi-x1234abcd-01020199
The 8-byte hex code is a 32-bit bitmask value indicating the configuration options, currently:
Bit(s) Bitmask Option Comment
1-2 0x3 Module type Read as a two-bit value indicating a number from 0-3 which maps to a module type (AVR, STM32, OrangeRX)
3-7 0x7C Channel order Read as a five-bit value indicating a number from 0-23 which maps to as channel order (AETR, TAER, RETA, etc) (right-shift two bits to read)
8 0x80 Bootloader support Indicates whether or not the firmware was built with support for the bootloader
9 0x100 CHECK_FOR_BOOTLOADER Indicates if CHECK_FOR_BOOTLOADER is defined
10 0x200 INVERT_TELEMETRY Indicates if INVERT_TELEMETRY is defined
11 0x400 MULTI_STATUS Indicates if MULTI_STATUS is defined
12 0x800 MULTI_TELEMETRY Indicates if MULTI_TELEMETRY is defined
13 0x1000 DEBUG_SERIAL Indicates if DEBUG_SERIAL is defined
The 8-byte version number is the version number zero-padded to a fixed width of two-bytes per segment and no separator.
E.g. 1.2.3.45 becomes 01020345.
Multi Telemetery Type can be read from bits 11 and 12 using the bitmask 0xC00 and right-shifting ten bits:
Telemetry Type Decimal Value Binary Value
Undefined 0 00
erSkyTX 1 01
OpenTX 2 10
Module types are mapped to the following decimal / binary values:
Module Type Decimal Value Binary Valsue
AVR 0 00
STM32 1 01
OrangeRX 2 10
Channel orders are mapped to the following decimal / binary values:
Channel Order Decimal Value Binary Value
AETR 0 00000
AERT 1 00001
ARET 2 00010
ARTE 3 00011
ATRE 4 00100
ATER 5 00101
EATR 6 00110
EART 7 00111
ERAT 8 01000
ERTA 9 01001
ETRA 10 01010
ETAR 11 01011
TEAR 12 01100
TERA 13 01101
TREA 14 01110
TRAE 15 01111
TARE 16 10000
TAER 17 10001
RETA 18 10010
REAT 19 10011
RAET 20 10100
RATE 21 10101
RTAE 22 10110
RTEA 23 10111
*/
// Set the flags for detecting and writing the firmware signature
#if defined (CHECK_FOR_BOOTLOADER)
bool firmwareFlag_CHECK_FOR_BOOTLOADER = true;
#endif
#if defined (INVERT_TELEMETRY)
bool firmwareFlag_INVERT_TELEMETRY = true;
#endif
#if defined (MULTI_STATUS)
bool firmwareFlag_MULTI_STATUS = true;
#endif
#if defined (MULTI_TELEMETRY)
bool firmwareFlag_MULTI_TELEMETRY = true;
#endif
#if defined (DEBUG_SERIAL)
bool firmwareFlag_DEBUG_SERIAL = true;
#endif
// Channel order flags
#if defined (AETR)
bool firmwareFlag_ChannelOrder_AETR = true;
#endif
#if defined (AERT)
bool firmwareFlag_ChannelOrder_AERT = true;
#endif
#if defined (ARET)
bool firmwareFlag_ChannelOrder_ARET = true;
#endif
#if defined (ARTE)
bool firmwareFlag_ChannelOrder_ARTE = true;
#endif
#if defined (ATRE)
bool firmwareFlag_ChannelOrder_ATRE = true;
#endif
#if defined (ATER)
bool firmwareFlag_ChannelOrder_ATER = true;
#endif
#if defined (EATR)
bool firmwareFlag_ChannelOrder_EATR = true;
#endif
#if defined (EART)
bool firmwareFlag_ChannelOrder_EART = true;
#endif
#if defined (ERAT)
bool firmwareFlag_ChannelOrder_ERAT = true;
#endif
#if defined (ERTA)
bool firmwareFlag_ChannelOrder_ERTA = true;
#endif
#if defined (ETRA)
bool firmwareFlag_ChannelOrder_ETRA = true;
#endif
#if defined (ETAR)
bool firmwareFlag_ChannelOrder_ETAR = true;
#endif
#if defined (TEAR)
bool firmwareFlag_ChannelOrder_TEAR = true;
#endif
#if defined (TERA)
bool firmwareFlag_ChannelOrder_TERA = true;
#endif
#if defined (TREA)
bool firmwareFlag_ChannelOrder_TREA = true;
#endif
#if defined (TRAE)
bool firmwareFlag_ChannelOrder_TRAE = true;
#endif
#if defined (TARE)
bool firmwareFlag_ChannelOrder_TARE = true;
#endif
#if defined (TAER)
bool firmwareFlag_ChannelOrder_TAER = true;
#endif
#if defined (RETA)
bool firmwareFlag_ChannelOrder_RETA = true;
#endif
#if defined (REAT)
bool firmwareFlag_ChannelOrder_REAT = true;
#endif
#if defined (RAET)
bool firmwareFlag_ChannelOrder_RAET = true;
#endif
#if defined (RATE)
bool firmwareFlag_ChannelOrder_RATE = true;
#endif
#if defined (RTAE)
bool firmwareFlag_ChannelOrder_RTAE = true;
#endif
#if defined (RTEA)
bool firmwareFlag_ChannelOrder_RTEA = true;
#endif

View File

@@ -284,10 +284,11 @@ static void __attribute__((unused))BUGS_set_radio_data()
{
offset=BUGS_NUM_RFCHAN;
// Read radio_id from EEPROM
radio_id=0;
uint8_t base_adr=BUGS_EEPROM_OFFSET+RX_num*4;
for(uint8_t i=0; i<4; i++)
radio_id|=eeprom_read_byte((EE_ADDR)(base_adr+i))<<(i*8);
uint8_t base_adr=BUGS_EEPROM_OFFSET+(RX_num&0x0F)*2;
uint16_t rxid=0;
for(uint8_t i=0; i<2; i++)
rxid|=eeprom_read_byte((EE_ADDR)(base_adr+i))<<(i*8);
radio_id = BUGS_rxid_to_radioid(rxid);
}
A7105_WriteID(radio_id);
@@ -318,7 +319,6 @@ uint16_t ReadBUGS(void)
{
uint8_t mode, base_adr;
uint16_t rxid;
uint32_t radio_id;
uint16_t start;
// keep frequency tuning updated
@@ -374,10 +374,9 @@ uint16_t ReadBUGS(void)
BIND_DONE;
// set radio_id
rxid = (packet[1] << 8) + packet[2];
radio_id = BUGS_rxid_to_radioid(rxid);
base_adr=BUGS_EEPROM_OFFSET+RX_num*4;
for(uint8_t i=0; i<4; i++)
eeprom_write_byte((EE_ADDR)(base_adr+i),radio_id>>(i*8)); // Save radio_id in EEPROM
base_adr=BUGS_EEPROM_OFFSET+(RX_num&0x0F)*2;
for(uint8_t i=0; i<2; i++)
eeprom_write_byte((EE_ADDR)(base_adr+i),rxid>>(i*8)); // Save rxid in EEPROM
BUGS_set_radio_data();
phase = BUGS_DATA_1;
packet_count = 0;
@@ -386,6 +385,9 @@ uint16_t ReadBUGS(void)
break;
case BUGS_DATA_1:
#ifdef MULTI_SYNC
telemetry_set_input_sync(BUGS_PACKET_PERIOD);
#endif
A7105_SetPower();
BUGS_build_packet(0);
A7105_WriteReg(A7105_03_FIFOI, BUGS_FIFO_SIZE_TX);
@@ -437,11 +439,11 @@ uint16_t ReadBUGS(void)
uint16_t initBUGS(void)
{
uint32_t radio_id=0;
uint8_t base_adr=BUGS_EEPROM_OFFSET+RX_num*4;
for(uint8_t i=0; i<4; i++)
radio_id|=eeprom_read_byte((EE_ADDR)(base_adr+i))<<(i*8);
if(radio_id==0xffffffff)
uint16_t rxid=0;
uint8_t base_adr=BUGS_EEPROM_OFFSET+(RX_num&0x0F)*2;
for(uint8_t i=0; i<2; i++)
rxid|=eeprom_read_byte((EE_ADDR)(base_adr+i))<<(i*8);
if(rxid==0xffff)
BIND_IN_PROGRESS;
BUGS_set_radio_data();
@@ -457,9 +459,6 @@ uint16_t initBUGS(void)
armed = 0;
arm_flags = BUGS_FLAG_DISARM; // initial value from captures
arm_channel_previous = BUGS_CH_SW_ARM;
#ifdef BUGS_HUB_TELEMETRY
init_frskyd_link_telemetry();
#endif
return 10000;
}

View File

@@ -406,9 +406,12 @@ uint16_t CABELL_callback()
if (IS_BIND_DONE)
{
CABELL_send_packet(0); // packet_period is set/adjusted in CABELL_send_packet
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
return packet_period;
}
if (bind_counter == 0)
else if (bind_counter == 0)
{
BIND_DONE;
CABELL_init(); // non-bind address
@@ -429,10 +432,6 @@ uint16_t initCABELL(void)
else
bind_counter = CABELL_BIND_COUNT;
CABELL_init();
#if defined CABELL_HUB_TELEMETRY
init_frskyd_link_telemetry();
telemetry_lost=1; // do not send telemetry to TX right away until we have a TX_RSSI value to prevent warning message...
#endif
packet_period = CABELL_PACKET_PERIOD;

View File

@@ -150,6 +150,11 @@ void CC2500_SetPower()
#else
power=CC2500_HIGH_POWER;
#endif
if(IS_LBT_POWER_on)
{
power=CC2500_LBT_POWER;
LBT_POWER_off; // Only accept once
}
if(IS_RANGE_FLAG_on)
power=CC2500_RANGE_POWER;
if(prev_power != power)

View File

@@ -97,7 +97,7 @@ static inline uint8_t crtp_create_header(uint8_t port, uint8_t channel)
#define TX_ADDR_SIZE 5
// Timeout for callback in uSec, 10ms=10000us for Crazyflie
#define PACKET_PERIOD 10000
#define CFLIE_PACKET_PERIOD 10000
#define MAX_PACKET_SIZE 32 // CRTP is 32 bytes
@@ -109,8 +109,6 @@ static uint8_t tx_payload_len = 0; // Length of the packet stored in packet
static uint8_t rx_payload_len = 0; // Length of the packet stored in rx_packet
static uint8_t rx_packet[MAX_PACKET_SIZE]; // For reading in ACK payloads
static uint16_t cflie_counter;
static uint32_t packet_counter;
static uint8_t data_rate;
enum {
@@ -194,8 +192,6 @@ static void send_packet()
// Transmit the payload
NRF24L01_WritePayload(packet, tx_payload_len);
++packet_counter;
// // Check and adjust transmission power.
NRF24L01_SetPower();
}
@@ -256,7 +252,6 @@ static void send_search_packet()
NRF24L01_WritePayload(buf, sizeof(buf));
++packet_counter;
}
// Frac 16.16
@@ -782,12 +777,14 @@ static uint16_t cflie_callback()
break;
case PKT_TIMEOUT:
send_search_packet();
cflie_counter = CFLIE_BIND_COUNT;
}
break;
case CFLIE_DATA:
// if (Model.proto_opts[PROTOOPTS_TELEMETRY] == TELEM_ON_CRTPLOG) {
#ifdef MULTI_SYNC
telemetry_set_input_sync(CFLIE_PACKET_PERIOD);
#endif
// if (Model.proto_opts[PROTOOPTS_TELEMETRY] == TELEM_ON_CRTPLOG) {
// update_telemetry_crtplog();
// } else if (Model.proto_opts[PROTOOPTS_TELEMETRY] == TELEM_ON_ACKPKT) {
// update_telemetry_ackpkt();
@@ -798,7 +795,7 @@ static uint16_t cflie_callback()
send_cmd_packet();
break;
}
return PACKET_PERIOD; // Packet at standard protocol interval
return CFLIE_PACKET_PERIOD; // Packet at standard protocol interval
}
// Generate address to use from TX id and manufacturer id (STM32 unique id)

View File

@@ -138,7 +138,12 @@ static void __attribute__((unused)) CG023_init()
uint16_t CG023_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
CG023_send_packet(0);
}
else
{
if (bind_counter == 0)

View File

@@ -229,6 +229,9 @@ uint16_t CX10_callback()
}
break;
case CX10_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
CX10_Write_Packet(0);
break;
}

View File

@@ -152,6 +152,17 @@ void CYRF_SetPower(uint8_t val)
CYRF_WriteRegister(CYRF_03_TX_CFG,power);
prev_power=power;
}
#ifdef USE_CYRF6936_CH15_TUNING
static uint16_t Channel15=1024;
if(Channel15!=Channel_data[CH15])
{ // adjust frequency
Channel15=Channel_data[CH15]+0x155; // default value is 0x555 = 0x400 + 0x155
CYRF_WriteRegister(CYRF_1B_TX_OFFSET_LSB, Channel15&0xFF);
CYRF_WriteRegister(CYRF_1C_TX_OFFSET_MSB, Channel15>>8);
Channel15-=0x155;
}
#endif
}
/*
@@ -273,7 +284,7 @@ void CYRF_FindBestChannels(uint8_t *channels, uint8_t len, uint8_t minspace, uin
}
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
CYRF_SetTxRxMode(TX_EN);
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Clear abort RX
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX
}
#if defined(DEVO_CYRF6936_INO) || defined(J6PRO_CYRF6936_INO)
@@ -302,6 +313,7 @@ const uint8_t PROGMEM DEVO_j6pro_sopcodes[][8] = {
#endif
};
#endif
static void __attribute__((unused)) CYRF_PROGMEM_ConfigSOPCode(const uint8_t *data)
{
uint8_t code[8];

View File

@@ -1,339 +0,0 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef FAILSAFE_ENABLE
//Convert from percentage to failsafe value
#define FAILSAFE_THROTTLE_LOW_VAL (((FAILSAFE_THROTTLE_LOW+125)*1024)/125)
#if FAILSAFE_THROTTLE_LOW_VAL <= 0
#undef FAILSAFE_THROTTLE_LOW_VAL
#define FAILSAFE_THROTTLE_LOW_VAL 1
#elif (FAILSAFE_THROTTLE_LOW_VAL) >= 2046
#undef FAILSAFE_THROTTLE_LOW_VAL
#define FAILSAFE_THROTTLE_LOW_VAL 2046
#endif
void InitFailsafe()
{
for(uint8_t i=0;i<NUM_CHN;i++)
Failsafe_data[i]=1024;
Failsafe_data[THROTTLE]=(uint16_t)FAILSAFE_THROTTLE_LOW_VAL; //1=-125%, 204=-100%
FAILSAFE_VALUES_on;
#ifdef FAILSAFE_SERIAL_ONLY
if(mode_select == MODE_SERIAL)
FAILSAFE_VALUES_off;
#endif
}
#endif
#ifdef ENABLE_PPM
void InitPPM()
{
for(uint8_t i=0;i<NUM_CHN;i++)
PPM_data[i]=PPM_MAX_100+PPM_MIN_100;
PPM_data[THROTTLE]=PPM_MIN_100*2;
}
#endif
void InitChannel()
{
for(uint8_t i=0;i<NUM_CHN;i++)
Channel_data[i]=1024;
#ifdef FAILSAFE_THROTTLE_LOW_VAL
Channel_data[THROTTLE]=(uint16_t)FAILSAFE_THROTTLE_LOW_VAL; //0=-125%, 204=-100%
#else
Channel_data[THROTTLE]=204;
#endif
}
/************************/
/** Convert routines **/
/************************/
// Revert a channel and store it
void reverse_channel(uint8_t num)
{
uint16_t val=2048-Channel_data[num];
if(val>=2048) val=2047;
Channel_data[num]=val;
}
// Channel value is converted to ppm 860<->2140 -125%<->+125% and 988<->2012 -100%<->+100%
uint16_t convert_channel_ppm(uint8_t num)
{
uint16_t val=Channel_data[num];
return (((val<<2)+val)>>3)+860; //value range 860<->2140 -125%<->+125%
}
// Channel value 100% is converted to 10bit values 0<->1023
uint16_t convert_channel_10b(uint8_t num)
{
uint16_t val=Channel_data[num];
val=((val<<2)+val)>>3;
if(val<=128) return 0;
if(val>=1152) return 1023;
return val-128;
}
// Channel value 100% is converted to 8bit values 0<->255
uint8_t convert_channel_8b(uint8_t num)
{
uint16_t val=Channel_data[num];
val=((val<<2)+val)>>5;
if(val<=32) return 0;
if(val>=288) return 255;
return val-32;
}
// Channel value 100% is converted to value scaled
int16_t convert_channel_16b_limit(uint8_t num,int16_t min,int16_t max)
{
int32_t val=limit_channel_100(num); // 204<->1844
val=(val-CHANNEL_MIN_100)*(max-min)/(CHANNEL_MAX_100-CHANNEL_MIN_100)+min;
return (uint16_t)val;
}
// Channel value -125%<->125% is scaled to 16bit value with no limit
int16_t convert_channel_16b_nolimit(uint8_t num, int16_t min, int16_t max)
{
int32_t val=Channel_data[num]; // 0<->2047
val=(val-CHANNEL_MIN_100)*(max-min)/(CHANNEL_MAX_100-CHANNEL_MIN_100)+min;
return (uint16_t)val;
}
// Channel value is converted sign + magnitude 8bit values
uint8_t convert_channel_s8b(uint8_t num)
{
uint8_t ch;
ch = convert_channel_8b(num);
return (ch < 128 ? 127-ch : ch);
}
// Channel value is limited to 100%
uint16_t limit_channel_100(uint8_t num)
{
if(Channel_data[num]>=CHANNEL_MAX_100)
return CHANNEL_MAX_100;
if (Channel_data[num]<=CHANNEL_MIN_100)
return CHANNEL_MIN_100;
return Channel_data[num];
}
// Channel value is converted for HK310
void convert_channel_HK310(uint8_t num, uint8_t *low, uint8_t *high)
{
uint16_t temp=0xFFFF-(3440+((Channel_data[num]*5)>>1))/3;
*low=(uint8_t)(temp&0xFF);
*high=(uint8_t)(temp>>8);
}
#ifdef FAILSAFE_ENABLE
// Failsafe value is converted for HK310
void convert_failsafe_HK310(uint8_t num, uint8_t *low, uint8_t *high)
{
uint16_t temp=0xFFFF-(3440+((Failsafe_data[num]*5)>>1))/3;
*low=(uint8_t)(temp&0xFF);
*high=(uint8_t)(temp>>8);
}
#endif
// Channel value for FrSky (PPM is multiplied by 1.5)
uint16_t convert_channel_frsky(uint8_t num)
{
uint16_t val=Channel_data[num];
return ((val*15)>>4)+1290;
}
/******************************/
/** FrSky D and X routines **/
/******************************/
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO)
enum {
FRSKY_BIND = 0,
FRSKY_BIND_DONE = 1000,
FRSKY_DATA1,
FRSKY_DATA2,
FRSKY_DATA3,
FRSKY_DATA4,
FRSKY_DATA5
};
void Frsky_init_hop(void)
{
uint8_t val;
uint8_t channel = rx_tx_addr[0]&0x07;
uint8_t channel_spacing = rx_tx_addr[1];
//Filter bad tables
if(channel_spacing<0x02) channel_spacing+=0x02;
if(channel_spacing>0xE9) channel_spacing-=0xE7;
if(channel_spacing%0x2F==0) channel_spacing++;
hopping_frequency[0]=channel;
for(uint8_t i=1;i<50;i++)
{
channel=(channel+channel_spacing) % 0xEB;
val=channel;
if((val==0x00) || (val==0x5A) || (val==0xDC))
val++;
hopping_frequency[i]=i>46?0:val;
}
}
#endif
/******************************/
/** FrSky V, D and X routines **/
/******************************/
#if defined(FRSKYV_CC2500_INO) || defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO)
const PROGMEM uint8_t FRSKY_common_startreg_cc2500_conf[]= {
CC2500_02_IOCFG0 ,
CC2500_00_IOCFG2 ,
CC2500_17_MCSM1 ,
CC2500_18_MCSM0 ,
CC2500_06_PKTLEN ,
CC2500_07_PKTCTRL1 ,
CC2500_08_PKTCTRL0 ,
CC2500_3E_PATABLE ,
CC2500_0B_FSCTRL1 ,
CC2500_0C_FSCTRL0 , // replaced by option value
CC2500_0D_FREQ2 ,
CC2500_0E_FREQ1 ,
CC2500_0F_FREQ0 ,
CC2500_10_MDMCFG4 ,
CC2500_11_MDMCFG3 ,
CC2500_12_MDMCFG2 ,
CC2500_13_MDMCFG1 ,
CC2500_14_MDMCFG0 ,
CC2500_15_DEVIATN };
#if defined(FRSKYV_CC2500_INO)
const PROGMEM uint8_t FRSKYV_cc2500_conf[]= {
/*02_IOCFG0*/ 0x06 ,
/*00_IOCFG2*/ 0x06 ,
/*17_MCSM1*/ 0x0c ,
/*18_MCSM0*/ 0x18 ,
/*06_PKTLEN*/ 0xff ,
/*07_PKTCTRL1*/ 0x04 ,
/*08_PKTCTRL0*/ 0x05 ,
/*3E_PATABLE*/ 0xfe ,
/*0B_FSCTRL1*/ 0x08 ,
/*0C_FSCTRL0*/ 0x00 ,
/*0D_FREQ2*/ 0x5c ,
/*0E_FREQ1*/ 0x58 ,
/*0F_FREQ0*/ 0x9d ,
/*10_MDMCFG4*/ 0xAA ,
/*11_MDMCFG3*/ 0x10 ,
/*12_MDMCFG2*/ 0x93 ,
/*13_MDMCFG1*/ 0x23 ,
/*14_MDMCFG0*/ 0x7a ,
/*15_DEVIATN*/ 0x41 };
#endif
#if defined(FRSKYD_CC2500_INO)
const PROGMEM uint8_t FRSKYD_cc2500_conf[]= {
/*02_IOCFG0*/ 0x06 ,
/*00_IOCFG2*/ 0x06 ,
/*17_MCSM1*/ 0x0c ,
/*18_MCSM0*/ 0x18 ,
/*06_PKTLEN*/ 0x19 ,
/*07_PKTCTRL1*/ 0x04 ,
/*08_PKTCTRL0*/ 0x05 ,
/*3E_PATABLE*/ 0xff ,
/*0B_FSCTRL1*/ 0x08 ,
/*0C_FSCTRL0*/ 0x00 ,
/*0D_FREQ2*/ 0x5c ,
/*0E_FREQ1*/ 0x76 ,
/*0F_FREQ0*/ 0x27 ,
/*10_MDMCFG4*/ 0xAA ,
/*11_MDMCFG3*/ 0x39 ,
/*12_MDMCFG2*/ 0x11 ,
/*13_MDMCFG1*/ 0x23 ,
/*14_MDMCFG0*/ 0x7a ,
/*15_DEVIATN*/ 0x42 };
#endif
#if defined(FRSKYX_CC2500_INO)
const PROGMEM uint8_t FRSKYX_cc2500_conf[]= {
//FRSKYX
/*02_IOCFG0*/ 0x06 ,
/*00_IOCFG2*/ 0x06 ,
/*17_MCSM1*/ 0x0c ,
/*18_MCSM0*/ 0x18 ,
/*06_PKTLEN*/ 0x1E ,
/*07_PKTCTRL1*/ 0x04 ,
/*08_PKTCTRL0*/ 0x01 ,
/*3E_PATABLE*/ 0xff ,
/*0B_FSCTRL1*/ 0x0A ,
/*0C_FSCTRL0*/ 0x00 ,
/*0D_FREQ2*/ 0x5c ,
/*0E_FREQ1*/ 0x76 ,
/*0F_FREQ0*/ 0x27 ,
/*10_MDMCFG4*/ 0x7B ,
/*11_MDMCFG3*/ 0x61 ,
/*12_MDMCFG2*/ 0x13 ,
/*13_MDMCFG1*/ 0x23 ,
/*14_MDMCFG0*/ 0x7a ,
/*15_DEVIATN*/ 0x51 };
const PROGMEM uint8_t FRSKYXEU_cc2500_conf[]= {
/*02_IOCFG0*/ 0x06 ,
/*00_IOCFG2*/ 0x06 ,
/*17_MCSM1*/ 0x0E ,
/*18_MCSM0*/ 0x18 ,
/*06_PKTLEN*/ 0x23 ,
/*07_PKTCTRL1*/ 0x04 ,
/*08_PKTCTRL0*/ 0x01 ,
/*3E_PATABLE*/ 0xff ,
/*0B_FSCTRL1*/ 0x08 ,
/*0C_FSCTRL0*/ 0x00 ,
/*0D_FREQ2*/ 0x5c ,
/*0E_FREQ1*/ 0x80 ,
/*0F_FREQ0*/ 0x00 ,
/*10_MDMCFG4*/ 0x7B ,
/*11_MDMCFG3*/ 0xF8 ,
/*12_MDMCFG2*/ 0x03 ,
/*13_MDMCFG1*/ 0x23 ,
/*14_MDMCFG0*/ 0x7a ,
/*15_DEVIATN*/ 0x53 };
#endif
const PROGMEM uint8_t FRSKY_common_end_cc2500_conf[][2]= {
{ CC2500_19_FOCCFG, 0x16 },
{ CC2500_1A_BSCFG, 0x6c },
{ CC2500_1B_AGCCTRL2, 0x43 },
{ CC2500_1C_AGCCTRL1, 0x40 },
{ CC2500_1D_AGCCTRL0, 0x91 },
{ CC2500_21_FREND1, 0x56 },
{ CC2500_22_FREND0, 0x10 },
{ CC2500_23_FSCAL3, 0xa9 },
{ CC2500_24_FSCAL2, 0x0A },
{ CC2500_25_FSCAL1, 0x00 },
{ CC2500_26_FSCAL0, 0x11 },
{ CC2500_29_FSTEST, 0x59 },
{ CC2500_2C_TEST2, 0x88 },
{ CC2500_2D_TEST1, 0x31 },
{ CC2500_2E_TEST0, 0x0B },
{ CC2500_03_FIFOTHR, 0x07 },
{ CC2500_09_ADDR, 0x00 } };
void FRSKY_init_cc2500(const uint8_t *ptr)
{
for(uint8_t i=0;i<19;i++)
{
uint8_t reg=pgm_read_byte_near(&FRSKY_common_startreg_cc2500_conf[i]);
uint8_t val=pgm_read_byte_near(&ptr[i]);
if(reg==CC2500_0C_FSCTRL0)
val=option;
CC2500_WriteReg(reg,val);
}
prev_option = option ; // Save option to monitor FSCTRL0 change
for(uint8_t i=0;i<17;i++)
{
uint8_t reg=pgm_read_byte_near(&FRSKY_common_end_cc2500_conf[i][0]);
uint8_t val=pgm_read_byte_near(&FRSKY_common_end_cc2500_conf[i][1]);
CC2500_WriteReg(reg,val);
}
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
CC2500_Strobe(CC2500_SIDLE); // Go to idle...
}
#endif

164
Multiprotocol/Convert.ino Normal file
View File

@@ -0,0 +1,164 @@
/*
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/>.
*/
/************************/
/** Convert routines **/
/************************/
// Reverse a channel and store it
void reverse_channel(uint8_t num)
{
uint16_t val=2048-Channel_data[num];
if(val>=2048) val=2047;
Channel_data[num]=val;
}
// Channel value is converted to ppm 860<->2140 -125%<->+125% and 988<->2012 -100%<->+100%
uint16_t convert_channel_ppm(uint8_t num)
{
uint16_t val=Channel_data[num];
return (((val<<2)+val)>>3)+860; //value range 860<->2140 -125%<->+125%
}
// Channel value 100% is converted to 10bit values 0<->1023
uint16_t convert_channel_10b(uint8_t num)
{
uint16_t val=Channel_data[num];
val=((val<<2)+val)>>3;
if(val<=128) return 0;
if(val>=1152) return 1023;
return val-128;
}
// Channel value 100% is converted to 8bit values 0<->255
uint8_t convert_channel_8b(uint8_t num)
{
uint16_t val=Channel_data[num];
val=((val<<2)+val)>>5;
if(val<=32) return 0;
if(val>=288) return 255;
return val-32;
}
// Channel value 100% is converted to 8b with deadband
uint8_t convert_channel_8b_limit_deadband(uint8_t num,uint8_t min,uint8_t mid, uint8_t max, uint8_t deadband)
{
uint16_t val=limit_channel_100(num); // 204<->1844
uint16_t db_low=CHANNEL_MID-deadband, db_high=CHANNEL_MID+deadband; // 1024+-deadband
int32_t calc;
uint8_t out;
if(val>=db_low && val<=db_high)
return mid;
else if(val<db_low)
{
val-=CHANNEL_MIN_100;
calc=mid-min;
calc*=val;
calc/=(db_low-CHANNEL_MIN_100);
out=calc;
out+=min;
}
else
{
val-=db_high;
calc=max-mid;
calc*=val;
calc/=(CHANNEL_MAX_100-db_high+1);
out=calc;
out+=mid;
if(max>min) out++; else out--;
}
return out;
}
// Channel value 100% is converted to value scaled
int16_t convert_channel_16b_limit(uint8_t num,int16_t min,int16_t max)
{
int32_t val=limit_channel_100(num); // 204<->1844
val=(val-CHANNEL_MIN_100)*(max-min)/(CHANNEL_MAX_100-CHANNEL_MIN_100)+min;
return (uint16_t)val;
}
// Channel value -125%<->125% is scaled to 16bit value with no limit
int16_t convert_channel_16b_nolimit(uint8_t num, int16_t min, int16_t max)
{
int32_t val=Channel_data[num]; // 0<->2047
val=(val-CHANNEL_MIN_100)*(max-min)/(CHANNEL_MAX_100-CHANNEL_MIN_100)+min;
return (uint16_t)val;
}
// Channel value is converted sign + magnitude 8bit values
uint8_t convert_channel_s8b(uint8_t num)
{
uint8_t ch;
ch = convert_channel_8b(num);
return (ch < 128 ? 127-ch : ch);
}
// Channel value is limited to 100%
uint16_t limit_channel_100(uint8_t num)
{
if(Channel_data[num]>=CHANNEL_MAX_100)
return CHANNEL_MAX_100;
if (Channel_data[num]<=CHANNEL_MIN_100)
return CHANNEL_MIN_100;
return Channel_data[num];
}
// Channel value is converted for HK310
void convert_channel_HK310(uint8_t num, uint8_t *low, uint8_t *high)
{
uint16_t temp=0xFFFF-(3440+((Channel_data[num]*5)>>1))/3;
*low=(uint8_t)(temp&0xFF);
*high=(uint8_t)(temp>>8);
}
#ifdef FAILSAFE_ENABLE
// Failsafe value is converted for HK310
void convert_failsafe_HK310(uint8_t num, uint8_t *low, uint8_t *high)
{
uint16_t temp=0xFFFF-(3440+((Failsafe_data[num]*5)>>1))/3;
*low=(uint8_t)(temp&0xFF);
*high=(uint8_t)(temp>>8);
}
#endif
// Channel value for FrSky (PPM is multiplied by 1.5)
uint16_t convert_channel_frsky(uint8_t num)
{
uint16_t val=Channel_data[num];
return ((val*15)>>4)+1290;
}
// 0-2047, 0 = 817, 1024 = 1500, 2047 = 2182
//64=860,1024=1500,1984=2140//Taranis 125%
static uint16_t __attribute__((unused)) FrSkyX_scaleForPXX( uint8_t i, uint8_t num_chan=8)
{ //mapped 860,2140(125%) range to 64,1984(PXX values);
uint16_t chan_val=convert_channel_frsky(i)-1226;
if(i>=num_chan) chan_val|=2048; // upper channels offset
return chan_val;
}
#ifdef FAILSAFE_ENABLE
static uint16_t __attribute__((unused)) FrSkyX_scaleForPXX_FS( uint8_t i )
{ //mapped 1,2046(125%) range to 64,1984(PXX values);
uint16_t chan_val=((Failsafe_data[i]*15)>>4)+64;
if(Failsafe_data[i]==FAILSAFE_CHANNEL_NOPULSES)
chan_val=FAILSAFE_CHANNEL_NOPULSES;
else if(Failsafe_data[i]==FAILSAFE_CHANNEL_HOLD)
chan_val=FAILSAFE_CHANNEL_HOLD;
if(i>7) chan_val|=2048; // upper channels offset
return chan_val;
}
#endif

View File

@@ -258,6 +258,9 @@ static uint16_t __attribute__((unused)) CORONA_build_packet()
uint16_t ReadCORONA()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(22000);
#endif
// Tune frequency if it has been changed
if ( prev_option != option )
{

View File

@@ -113,7 +113,12 @@ static void __attribute__((unused)) DM002_init()
uint16_t DM002_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(DM002_PACKET_PERIOD);
#endif
DM002_send_packet(0);
}
else
{
if (bind_counter == 0)

182
Multiprotocol/DSM.ino Normal file
View File

@@ -0,0 +1,182 @@
#if defined(DSM_CYRF6936_INO) || defined(DSM_RX_CYRF6936_INO)
#include "iface_cyrf6936.h"
uint8_t sop_col;
const uint8_t PROGMEM DSM_pncodes[5][9][8] = {
/* Note these are in order transmitted (LSB 1st) */
{ /* Row 0 */
/* Col 0 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8},
/* Col 1 */ {0x88, 0x17, 0x13, 0x3B, 0x2D, 0xBF, 0x06, 0xD6},
/* Col 2 */ {0xF1, 0x94, 0x30, 0x21, 0xA1, 0x1C, 0x88, 0xA9},
/* Col 3 */ {0xD0, 0xD2, 0x8E, 0xBC, 0x82, 0x2F, 0xE3, 0xB4},
/* Col 4 */ {0x8C, 0xFA, 0x47, 0x9B, 0x83, 0xA5, 0x66, 0xD0},
/* Col 5 */ {0x07, 0xBD, 0x9F, 0x26, 0xC8, 0x31, 0x0F, 0xB8},
/* Col 6 */ {0xEF, 0x03, 0x95, 0x89, 0xB4, 0x71, 0x61, 0x9D},
/* Col 7 */ {0x40, 0xBA, 0x97, 0xD5, 0x86, 0x4F, 0xCC, 0xD1},
/* Col 8 */ {0xD7, 0xA1, 0x54, 0xB1, 0x5E, 0x89, 0xAE, 0x86}
},
{ /* Row 1 */
/* Col 0 */ {0x83, 0xF7, 0xA8, 0x2D, 0x7A, 0x44, 0x64, 0xD3},
/* Col 1 */ {0x3F, 0x2C, 0x4E, 0xAA, 0x71, 0x48, 0x7A, 0xC9},
/* Col 2 */ {0x17, 0xFF, 0x9E, 0x21, 0x36, 0x90, 0xC7, 0x82},
/* Col 3 */ {0xBC, 0x5D, 0x9A, 0x5B, 0xEE, 0x7F, 0x42, 0xEB},
/* Col 4 */ {0x24, 0xF5, 0xDD, 0xF8, 0x7A, 0x77, 0x74, 0xE7},
/* Col 5 */ {0x3D, 0x70, 0x7C, 0x94, 0xDC, 0x84, 0xAD, 0x95},
/* Col 6 */ {0x1E, 0x6A, 0xF0, 0x37, 0x52, 0x7B, 0x11, 0xD4},
/* Col 7 */ {0x62, 0xF5, 0x2B, 0xAA, 0xFC, 0x33, 0xBF, 0xAF},
/* Col 8 */ {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97}
},
{ /* Row 2 */
/* Col 0 */ {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97},
/* Col 1 */ {0x8E, 0x4A, 0xD0, 0xA9, 0xA7, 0xFF, 0x20, 0xCA},
/* Col 2 */ {0x4C, 0x97, 0x9D, 0xBF, 0xB8, 0x3D, 0xB5, 0xBE},
/* Col 3 */ {0x0C, 0x5D, 0x24, 0x30, 0x9F, 0xCA, 0x6D, 0xBD},
/* Col 4 */ {0x50, 0x14, 0x33, 0xDE, 0xF1, 0x78, 0x95, 0xAD},
/* Col 5 */ {0x0C, 0x3C, 0xFA, 0xF9, 0xF0, 0xF2, 0x10, 0xC9},
/* Col 6 */ {0xF4, 0xDA, 0x06, 0xDB, 0xBF, 0x4E, 0x6F, 0xB3},
/* Col 7 */ {0x9E, 0x08, 0xD1, 0xAE, 0x59, 0x5E, 0xE8, 0xF0},
/* Col 8 */ {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E}
},
{ /* Row 3 */
/* Col 0 */ {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E},
/* Col 1 */ {0x80, 0x69, 0x26, 0x80, 0x08, 0xF8, 0x49, 0xE7},
/* Col 2 */ {0x7D, 0x2D, 0x49, 0x54, 0xD0, 0x80, 0x40, 0xC1},
/* Col 3 */ {0xB6, 0xF2, 0xE6, 0x1B, 0x80, 0x5A, 0x36, 0xB4},
/* Col 4 */ {0x42, 0xAE, 0x9C, 0x1C, 0xDA, 0x67, 0x05, 0xF6},
/* Col 5 */ {0x9B, 0x75, 0xF7, 0xE0, 0x14, 0x8D, 0xB5, 0x80},
/* Col 6 */ {0xBF, 0x54, 0x98, 0xB9, 0xB7, 0x30, 0x5A, 0x88},
/* Col 7 */ {0x35, 0xD1, 0xFC, 0x97, 0x23, 0xD4, 0xC9, 0x88},
/* Col 8 */ {0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93}
// Wrong values used by Orange TX/RX
// /* Col 8 */ {0x88, 0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40}
},
{ /* Row 4 */
/* Col 0 */ {0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93},
/* Col 1 */ {0xDC, 0x68, 0x08, 0x99, 0x97, 0xAE, 0xAF, 0x8C},
/* Col 2 */ {0xC3, 0x0E, 0x01, 0x16, 0x0E, 0x32, 0x06, 0xBA},
/* Col 3 */ {0xE0, 0x83, 0x01, 0xFA, 0xAB, 0x3E, 0x8F, 0xAC},
/* Col 4 */ {0x5C, 0xD5, 0x9C, 0xB8, 0x46, 0x9C, 0x7D, 0x84},
/* Col 5 */ {0xF1, 0xC6, 0xFE, 0x5C, 0x9D, 0xA5, 0x4F, 0xB7},
/* Col 6 */ {0x58, 0xB5, 0xB3, 0xDD, 0x0E, 0x28, 0xF1, 0xB0},
/* Col 7 */ {0x5F, 0x30, 0x3B, 0x56, 0x96, 0x45, 0xF4, 0xA1},
/* Col 8 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8}
},
};
static void __attribute__((unused)) DSM_read_code(uint8_t *buf, uint8_t row, uint8_t col, uint8_t len)
{
for(uint8_t i=0;i<len;i++)
buf[i]=pgm_read_byte_near( &DSM_pncodes[row][col][i] );
}
const uint8_t PROGMEM DSM_init_vals[][2] = {
{CYRF_02_TX_CTRL, 0x00}, // All TX interrupt disabled
{CYRF_05_RX_CTRL, 0x00}, // All RX interrupt disabled
{CYRF_28_CLK_EN, 0x02}, // Force receive clock enable
{CYRF_32_AUTO_CAL_TIME, 0x3c}, // Default init value
{CYRF_35_AUTOCAL_OFFSET, 0x14}, // Default init value
{CYRF_26_XTAL_CFG, 0x08}, // Start delay
{CYRF_06_RX_CFG, 0x4A}, // LNA enabled, RX override enabled, Fast turn mode enabled, RX is 1MHz below TX
{CYRF_1B_TX_OFFSET_LSB, 0x55}, // Default init value
{CYRF_1C_TX_OFFSET_MSB, 0x05}, // Default init value
{CYRF_39_ANALOG_CTRL, 0x01}, // All slow for synth setting time
{CYRF_01_TX_LENGTH, 0x10}, // 16 bytes packet
{CYRF_14_EOP_CTRL, 0x02}, // Set EOP Symbol Count to 2
{CYRF_12_DATA64_THOLD, 0x0a}, // 64 Chip Data PN corelator threshold, default datasheet value is 0x0E
//Below is for bind only
{CYRF_03_TX_CFG, 0x38 | CYRF_BIND_POWER}, //64 chip codes, SDR mode
{CYRF_10_FRAMING_CFG, 0x4a}, // SOP disabled, no LEN field and SOP correlator of 0x0a but since SOP is disabled...
{CYRF_1F_TX_OVERRIDE, 0x04}, // Disable TX CRC, no ACK, use TX synthesizer
{CYRF_1E_RX_OVERRIDE, 0x14}, // Disable RX CRC, Force receive data rate, use RX synthesizer
};
const uint8_t PROGMEM DSM_data_vals[][2] = {
{CYRF_29_RX_ABORT, 0x20}, // Abort RX operation in case we are coming from bind
{CYRF_0F_XACT_CFG, 0x24}, // Force Idle
{CYRF_29_RX_ABORT, 0x00}, // Clear abort RX
{CYRF_03_TX_CFG, 0x28 | CYRF_HIGH_POWER}, // 64 chip codes, 8DR mode
{CYRF_10_FRAMING_CFG, 0xea}, // SOP enabled, SOP_CODE_ADR 64 chips, Packet len enabled, SOP correlator 0x0A
{CYRF_1F_TX_OVERRIDE, 0x00}, // CRC16 enabled, no ACK
{CYRF_1E_RX_OVERRIDE, 0x00}, // CRC16 enabled, no ACK
};
static void __attribute__((unused)) DSM_cyrf_config()
{
for(uint8_t i = 0; i < sizeof(DSM_init_vals) / 2; i++)
CYRF_WriteRegister(pgm_read_byte_near(&DSM_init_vals[i][0]), pgm_read_byte_near(&DSM_init_vals[i][1]));
CYRF_WritePreamble(0x333304);
}
static void __attribute__((unused)) DSM_cyrf_configdata()
{
for(uint8_t i = 0; i < sizeof(DSM_data_vals) / 2; i++)
CYRF_WriteRegister(pgm_read_byte_near(&DSM_data_vals[i][0]), pgm_read_byte_near(&DSM_data_vals[i][1]));
}
static uint8_t __attribute__((unused)) DSM_get_pn_row(uint8_t channel, bool dsmx)
{
return (dsmx ? (channel - 2) % 5 : channel % 5);
}
static void __attribute__((unused)) DSM_set_sop_data_crc(bool ch2, bool dsmx)
{
//The crc for channel '1' is NOT(mfgid[0] << 8 + mfgid[1])
//The crc for channel '2' is (mfgid[0] << 8 + mfgid[1])
if(ch2)
CYRF_ConfigCRCSeed(seed); //CH2
else
CYRF_ConfigCRCSeed(~seed); //CH1
uint8_t pn_row = DSM_get_pn_row(hopping_frequency[hopping_frequency_no], dsmx);
uint8_t code[16];
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
DSM_read_code(code+8,pn_row,7 - sop_col + 1,8); // 7-sop_col+1 between 1 and 7
CYRF_ConfigDataCode(code, 16);
CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]);
hopping_frequency_no++;
if(dsmx)
hopping_frequency_no %=23;
else
hopping_frequency_no %=2;
}
static void __attribute__((unused)) DSM_calc_dsmx_channel()
{
uint8_t idx = 0;
uint32_t id = ~(((uint32_t)cyrfmfg_id[0] << 24) | ((uint32_t)cyrfmfg_id[1] << 16) | ((uint32_t)cyrfmfg_id[2] << 8) | (cyrfmfg_id[3] << 0));
uint32_t id_tmp = id;
while(idx < 23)
{
uint8_t i;
uint8_t count_3_27 = 0, count_28_51 = 0, count_52_76 = 0;
id_tmp = id_tmp * 0x0019660D + 0x3C6EF35F; // Randomization
uint8_t next_ch = ((id_tmp >> 8) % 0x49) + 3; // Use least-significant byte and must be larger than 3
if ( (next_ch ^ cyrfmfg_id[3]) & 0x01 )
continue;
for (i = 0; i < idx; i++)
{
if(hopping_frequency[i] == next_ch)
break;
if(hopping_frequency[i] <= 27)
count_3_27++;
else
if (hopping_frequency[i] <= 51)
count_28_51++;
else
count_52_76++;
}
if (i != idx)
continue;
if ((next_ch < 28 && count_3_27 < 8)
||(next_ch >= 28 && next_ch < 52 && count_28_51 < 7)
||(next_ch >= 52 && count_52_76 < 8))
hopping_frequency[idx++] = next_ch;
}
}
#endif

View File

@@ -0,0 +1,493 @@
/*
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(DSM_RX_CYRF6936_INO)
#include "iface_cyrf6936.h"
//#define DSM_DEBUG_RF
uint8_t DSM_rx_type;
enum {
DSM_RX_BIND1 = 0,
DSM_RX_BIND2,
DSM_RX_DATA_PREP,
DSM2_RX_SCAN,
DSM_RX_DATA_CH1,
DSM_RX_DATA_CH2,
};
static void __attribute__((unused)) DSM_Rx_init()
{
DSM_cyrf_config();
rx_disable_lna = IS_POWER_FLAG_on;
if(IS_BIND_IN_PROGRESS)
{
//64 SDR Mode is configured so only the 8 first values are needed but need to write 16 values...
uint8_t code[16];
DSM_read_code(code,0,8,8);
CYRF_ConfigDataCode(code, 16);
CYRF_ConfigRFChannel(1);
CYRF_SetTxRxMode(RX_EN); // Force end state read
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83); // Prepare to receive
}
else
{
DSM_cyrf_configdata();
CYRF_WriteRegister(CYRF_06_RX_CFG, rx_disable_lna ? 0x0A:0x4A); // AGC disabled, LNA disabled/enabled, Attenuator disabled, RX override enabled, Fast turn mode enabled, RX is 1MHz below TX
}
}
uint16_t convert_channel_DSM_nolimit(int32_t val)
{
val=(val-0x150)*(CHANNEL_MAX_100-CHANNEL_MIN_100)/(0x6B0-0x150)+CHANNEL_MIN_100;
if(val<0)
val=0;
else
if(val>2047)
val=2047;
return (uint16_t)val;
}
static uint8_t __attribute__((unused)) DSM_Rx_check_packet()
{
uint8_t rx_status=CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((rx_status & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
rx_status |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((rx_status & 0x07) == 0x02)
{ // data received with no errors
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
#ifdef DSM_DEBUG_RF
debugln("l=%d",len);
#endif
if(len>=2 && len<=16)
{
// Read packet
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // Need to set RXOW before data read
CYRF_ReadDataPacketLen(packet, len);
// Check packet ID
if ((DSM_rx_type&0x80) == 0)
{//DSM2
packet[0] ^= 0xff;
packet[1] ^= 0xff;
}
if(packet[0] == cyrfmfg_id[2] && packet[1] == cyrfmfg_id[3])
return 0x02; // Packet ok
}
return 0x00; // Wrong size or ID -> nothing received
}
return rx_status; // Return error code
}
static void __attribute__((unused)) DSM_Rx_build_telemetry_packet()
{
uint8_t nbr_bits = 11;
if((DSM_rx_type&0xF0) == 0x00)
nbr_bits=10; // Only DSM_22 is using a resolution of 1024
// Use packet length to calculate the number of channels
len -= 2; // Remove header length
len >>= 1; // Channels are on 2 bytes
if(len==0) return; // No channels...
// Extract channels
uint8_t idx;
for (uint8_t i = 0; i < len; i++)
{
uint16_t value=(packet[i*2+2]<<8) | packet[i*2+3];
if(value!=0xFFFF)
{
idx=(value&0x7FFF)>>nbr_bits; // retrieve channel index 0..12
if(idx<13)
{
if(nbr_bits==10) value <<= 1; // switch to 11 bits
value &= 0x7FF;
rx_rc_chan[CH_TAER[idx]]=convert_channel_DSM_nolimit(value);
}
}
}
// Buid telemetry packet
idx=0;
packet_in[idx++] = RX_LQI;
packet_in[idx++] = RX_LQI;
packet_in[idx++] = 0; // start channel
packet_in[idx++] = 12; // number of channels in packet
// Pack channels
uint32_t bits = 0;
uint8_t bitsavailable = 0;
for (uint8_t i = 0; i < 12; i++)
{
bits |= ((uint32_t)rx_rc_chan[i]) << bitsavailable;
bitsavailable += 11;
while (bitsavailable >= 8)
{
packet_in[idx++] = bits & 0xff;
bits >>= 8;
bitsavailable -= 8;
}
}
if(bitsavailable)
packet_in[idx++] = bits & 0xff;
// Send telemetry
telemetry_link = 1;
}
static bool __attribute__((unused)) DSM_Rx_bind_check_validity()
{
uint16_t sum = 384 - 0x10;//
for(uint8_t i = 0; i < 8; i++)
sum += packet_in[i];
if( packet_in[8] != (sum>>8) || packet_in[9] != (sum&0xFF)) //Checksum
return false;
for(uint8_t i = 8; i < 14; i++)
sum += packet_in[i];
if( packet_in[14] != (sum>>8) || packet_in[15] != (sum&0xFF)) //Checksum
return false;
if(memcmp(packet_in,packet_in+4,4)) //Check ID
return false;
return true;
}
static void __attribute__((unused)) DSM_Rx_build_bind_packet()
{
uint16_t sum = 384 - 0x10;//
packet[0] = 0xff ^ cyrfmfg_id[0]; // ID
packet[1] = 0xff ^ cyrfmfg_id[1];
packet[2] = 0xff ^ cyrfmfg_id[2];
packet[3] = 0xff ^ cyrfmfg_id[3];
packet[4] = 0x01; // RX version
packet[5] = num_ch; // Number of channels
packet[6] = DSM_rx_type; // DSM type, let's just send back whatever the TX gave us...
packet[7] = 0x00; // Unknown
for(uint8_t i = 0; i < 8; i++)
sum += packet[i];
packet[8] = sum >> 8;
packet[9] = sum & 0xff;
}
static void __attribute__((unused)) DSM_abort_channel_rx(uint8_t ch)
{
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
CYRF_SetTxRxMode(IS_POWER_FLAG_on ? TXRX_OFF:RX_EN); // Force end state read
if (rx_disable_lna != IS_POWER_FLAG_on && IS_BIND_DONE)
{
rx_disable_lna = IS_POWER_FLAG_on;
CYRF_WriteRegister(CYRF_06_RX_CFG, rx_disable_lna ? 0x0A:0x4A); // AGC disabled, LNA disabled/enabled, Attenuator disabled, RX override enabled, Fast turn mode enabled, RX is 1MHz below TX
}
if(ch&0x02) DSM_set_sop_data_crc(true ,DSM_rx_type&0x80); // Set sop data,crc seed and rf channel using CH1, DSM2/X
if(ch&0x01) DSM_set_sop_data_crc(false,DSM_rx_type&0x80); // Set sop data,crc seed and rf channel using CH1, DSM2/X
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX operation
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83); // Prepare to receive
}
uint16_t DSM_Rx_callback()
{
uint8_t rx_status;
static uint8_t read_retry=0;
static uint16_t pps_counter;
static uint32_t pps_timer = 0;
switch (phase)
{
case DSM_RX_BIND1:
if(packet_count==0)
read_retry=0;
//Check received data
rx_status = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((rx_status & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
rx_status |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((rx_status & 0x07) == 0x02)
{ // data received with no errors
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // Need to set RXOW before data read
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
debugln("RX:%d, CH:%d",len,hopping_frequency_no);
if(len==16)
{
CYRF_ReadDataPacketLen(packet_in, 16);
if(DSM_Rx_bind_check_validity())
{
// store tx info into eeprom
uint16_t temp = DSM_RX_EEPROM_OFFSET;
debug("ID=");
for(uint8_t i=0;i<4;i++)
{
cyrfmfg_id[i]=packet_in[i]^0xFF;
eeprom_write_byte((EE_ADDR)temp++, cyrfmfg_id[i]);
debug(" %02X", cyrfmfg_id[i]);
}
// check num_ch
num_ch=packet_in[11];
if(num_ch>12) num_ch=12;
//check DSM_rx_type
/*packet[12] 1 byte -> max DSM type allowed:
0x01 => 22ms 1024 DSM2 1 packet => number of channels is <8 and no telemetry
0x02 => 22ms 1024 DSM2 2 packets => either a number of channel >7 or telemetry enable RX
0x12 => 11ms 2048 DSM2 2 packets => can be any number of channels with/without telemetry
0xA2 => 22ms 2048 DSMX 1 packet => number of channels is <8 and no telemetry
0xB2 => 11ms 2048 DSMX => can be any number of channels with/without telemetry
(0x01 or 0xA2) and num_ch < 7 => 22ms else 11ms
&0x80 => false=DSM2, true=DSMX
&0xF0 => false=1024, true=2048 */
DSM_rx_type=packet_in[12];
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);
debugln(", num_ch=%d, type=%02X",num_ch, DSM_rx_type);
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
CYRF_SetTxRxMode(TX_EN); // Force end state TX
CYRF_ConfigDataCode((const uint8_t *)"\x98\x88\x1B\xE4\x30\x79\x03\x84", 16);
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX
DSM_Rx_build_bind_packet();
bind_counter=500;
phase++; // DSM_RX_BIND2;
return 1000;
}
}
DSM_abort_channel_rx(0); // Abort RX operation and receive
if(read_retry==0)
read_retry=4;
}
else
if(rx_status & 0x02) // RX error
DSM_abort_channel_rx(0); // Abort RX operation and receive
packet_count++;
if(packet_count>12)
{
packet_count=1;
if(read_retry)
read_retry--;
if(read_retry==0)
{
packet_count=0;
hopping_frequency_no++; // Change channel
hopping_frequency_no %= 0x50;
hopping_frequency_no |= 0x01; // Odd channels only
CYRF_ConfigRFChannel(hopping_frequency_no);
DSM_abort_channel_rx(0); // Abort RX operation and receive
}
}
return 1000;
case DSM_RX_BIND2:
//Transmit settings back
CYRF_WriteDataPacketLen(packet,10); // Send packet
if(bind_counter--==0)
{
BIND_DONE;
phase++; // DSM_RX_DATA_PREP
}
break;
case DSM_RX_DATA_PREP:
hopping_frequency_no = 0;
read_retry=0;
rx_data_started = false;
pps_counter = 0;
RX_LQI = 100;
DSM_cyrf_configdata();
pps_timer=millis();
sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;
seed = (cyrfmfg_id[0] << 8) + cyrfmfg_id[1];
if(DSM_rx_type&0x80)
{ // DSMX
DSM_calc_dsmx_channel(); // Build hop table
DSM_abort_channel_rx(1); // Abort RX operation, set sop&data&seed&rf using CH1, DSM2/X and receive
phase=DSM_RX_DATA_CH1;
}
else
{ // DSM2
rf_ch_num=0;
hopping_frequency_no = 0;
hopping_frequency[0] = 3;
hopping_frequency[1] = 0;
DSM_abort_channel_rx(1); // Abort RX operation, set sop&data&seed&rf using CH1, DSM2/X and receive
phase=DSM2_RX_SCAN;
}
break;
case DSM2_RX_SCAN: // Scan for DSM2 frequencies
//Received something ?
rx_status = DSM_Rx_check_packet();
if(rx_status == 0x02)
{ // data received with no errors
debugln("CH%d:Found %d",rf_ch_num+1,hopping_frequency[rf_ch_num]);
read_retry=0;
if(rf_ch_num)
{ // Both CH1 and CH2 found
read_retry=0;
hopping_frequency_no=0;
DSM_abort_channel_rx(1); // Abort RX operation, set sop&data&seed&rf using CH1, DSM2/X and receive
pps_timer=millis();
phase++; // DSM_RX_DATA_CH1
}
else
{
rf_ch_num++; // CH1 found, scan for CH2
hopping_frequency_no = 1;
if(hopping_frequency[1] < 3) // If no CH2 keep then restart from current
hopping_frequency[1]=hopping_frequency[0]+1;
DSM_abort_channel_rx(2); // Abort RX operation, set sop&data&seed&rf using CH2, DSM2/X and receive
}
}
else
{
read_retry++;
if(read_retry>50) // After 50ms
{ // Try next channel
debugln("CH%d:Next channel",rf_ch_num+1);
read_retry=0;
hopping_frequency_no = rf_ch_num;
hopping_frequency[rf_ch_num]++;
if(hopping_frequency[rf_ch_num] > 73) hopping_frequency[rf_ch_num] = 3;
DSM_abort_channel_rx(rf_ch_num+1); // Abort RX operation, set sop&data&seed&rf using CH1/2, DSM2/X and receive
}
else if(rx_status & 0x02)
{ // data received with errors
if((rx_status & 0x01) && rf_ch_num==0)
hopping_frequency[1] = hopping_frequency[0];// Might be CH2 since it's a CRC error so keep it
debugln("CH%d:RX error",rf_ch_num+1);
DSM_abort_channel_rx(0); // Abort RX operation and receive
}
}
return 1000;
case DSM_RX_DATA_CH1:
//Packets per second
if (millis() - pps_timer >= 1000)
{//182pps @11ms, 91pps @22ms
pps_timer = millis();
if(DSM_rx_type!=0xA2 && DSM_rx_type!=0x01) // if 11ms
pps_counter >>=1; // then /2
debugln("%d pps", pps_counter);
RX_LQI = pps_counter; // max=91pps
pps_counter = 0;
}
//Received something ?
rx_status = DSM_Rx_check_packet();
if(rx_status == 0x02)
{ // data received with no errors
#ifdef DSM_DEBUG_RF
debugln("CH1:RX");
#endif
DSM_Rx_build_telemetry_packet();
rx_data_started = true;
pps_counter++;
DSM_abort_channel_rx(2); // Abort RX operation, set sop&data&seed&rf using CH2, DSM2/X and receive
phase++;
return 5000;
}
else
{
read_retry++;
if(rx_data_started && read_retry>6) // After 6*500=3ms
{ // skip to CH2
#ifdef DSM_DEBUG_RF
debugln("CH1:Skip to CH2");
#endif
DSM_abort_channel_rx(2); // Abort RX operation, set sop&data&seed&rf using CH2, DSM2/X and receive
phase++;
return 4000;
}
if(rx_data_started && RX_LQI==0)
{ // communication lost
#ifdef DSM_DEBUG_RF
debugln("CH1:Restart...");
#endif
phase=DSM_RX_DATA_PREP;
return 1000;
}
if(read_retry>250)
{ // move to next RF channel
#ifdef DSM_DEBUG_RF
debugln("CH1:Scan");
#endif
DSM_abort_channel_rx(3); // Abort RX operation, set sop&data&seed&rf using CH2 then CH1, DSM2/X and receive
read_retry=0;
}
else if(rx_status & 0x02)
{ // data received with errors
#ifdef DSM_DEBUG_RF
debugln("CH1:RX error %02X",rx_status);
#endif
DSM_abort_channel_rx(0); // Abort RX operation and receive
}
}
return 500;
case DSM_RX_DATA_CH2:
rx_status = DSM_Rx_check_packet();
if(rx_status == 0x02)
{ // data received with no errors
#ifdef DSM_DEBUG_RF
debugln("CH2:RX");
#endif
DSM_Rx_build_telemetry_packet();
pps_counter++;
}
#ifdef DSM_DEBUG_RF
else
debugln("CH2:No RX");
#endif
DSM_abort_channel_rx(1); // Abort RX operation, set sop&data&seed&rf using CH1, DSM2/X and receive
read_retry=0;
phase=DSM_RX_DATA_CH1;
if(DSM_rx_type==0xA2) //|| DSM_rx_type==0x01 -> not needed for DSM2 since we are ok to listen even if there will be nothing
return 15000; //22ms
else
return 4000; //11ms
}
return 10000;
}
uint16_t initDSM_Rx()
{
DSM_Rx_init();
hopping_frequency_no = 0;
if (IS_BIND_IN_PROGRESS)
{
packet_count=0;
phase = DSM_RX_BIND1;
}
else
{
uint16_t temp = DSM_RX_EEPROM_OFFSET;
debug("ID=");
for(uint8_t i=0;i<4;i++)
{
cyrfmfg_id[i]=eeprom_read_byte((EE_ADDR)temp++);
debug(" %02X", cyrfmfg_id[i]);
}
DSM_rx_type=eeprom_read_byte((EE_ADDR)temp);
debugln(", type=%02X", DSM_rx_type);
phase = DSM_RX_DATA_PREP;
}
return 15000;
}
#endif

View File

@@ -41,8 +41,6 @@ enum {
};
//
uint8_t sop_col;
uint8_t DSM_num_ch=0;
uint8_t ch_map[14];
const uint8_t PROGMEM DSM_ch_map_progmem[][14] = {
//22+11ms for 4..7 channels
@@ -62,116 +60,6 @@ const uint8_t PROGMEM DSM_ch_map_progmem[][14] = {
{1, 5, 2, 3, 4, 8, 9, 1, 5, 2, 3, 0, 7, 6 }, //10ch - DX18
};
const uint8_t PROGMEM DSM_pncodes[5][8][8] = {
/* Note these are in order transmitted (LSB 1st) */
{ /* Row 0 */
/* Col 0 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8},
/* Col 1 */ {0x88, 0x17, 0x13, 0x3B, 0x2D, 0xBF, 0x06, 0xD6},
/* Col 2 */ {0xF1, 0x94, 0x30, 0x21, 0xA1, 0x1C, 0x88, 0xA9},
/* Col 3 */ {0xD0, 0xD2, 0x8E, 0xBC, 0x82, 0x2F, 0xE3, 0xB4},
/* Col 4 */ {0x8C, 0xFA, 0x47, 0x9B, 0x83, 0xA5, 0x66, 0xD0},
/* Col 5 */ {0x07, 0xBD, 0x9F, 0x26, 0xC8, 0x31, 0x0F, 0xB8},
/* Col 6 */ {0xEF, 0x03, 0x95, 0x89, 0xB4, 0x71, 0x61, 0x9D},
/* Col 7 */ {0x40, 0xBA, 0x97, 0xD5, 0x86, 0x4F, 0xCC, 0xD1},
/* Col 8 {0xD7, 0xA1, 0x54, 0xB1, 0x5E, 0x89, 0xAE, 0x86}*/
},
{ /* Row 1 */
/* Col 0 */ {0x83, 0xF7, 0xA8, 0x2D, 0x7A, 0x44, 0x64, 0xD3},
/* Col 1 */ {0x3F, 0x2C, 0x4E, 0xAA, 0x71, 0x48, 0x7A, 0xC9},
/* Col 2 */ {0x17, 0xFF, 0x9E, 0x21, 0x36, 0x90, 0xC7, 0x82},
/* Col 3 */ {0xBC, 0x5D, 0x9A, 0x5B, 0xEE, 0x7F, 0x42, 0xEB},
/* Col 4 */ {0x24, 0xF5, 0xDD, 0xF8, 0x7A, 0x77, 0x74, 0xE7},
/* Col 5 */ {0x3D, 0x70, 0x7C, 0x94, 0xDC, 0x84, 0xAD, 0x95},
/* Col 6 */ {0x1E, 0x6A, 0xF0, 0x37, 0x52, 0x7B, 0x11, 0xD4},
/* Col 7 */ {0x62, 0xF5, 0x2B, 0xAA, 0xFC, 0x33, 0xBF, 0xAF},
/* Col 8 {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97} */
},
{ /* Row 2 */
/* Col 0 */ {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97},
/* Col 1 */ {0x8E, 0x4A, 0xD0, 0xA9, 0xA7, 0xFF, 0x20, 0xCA},
/* Col 2 */ {0x4C, 0x97, 0x9D, 0xBF, 0xB8, 0x3D, 0xB5, 0xBE},
/* Col 3 */ {0x0C, 0x5D, 0x24, 0x30, 0x9F, 0xCA, 0x6D, 0xBD},
/* Col 4 */ {0x50, 0x14, 0x33, 0xDE, 0xF1, 0x78, 0x95, 0xAD},
/* Col 5 */ {0x0C, 0x3C, 0xFA, 0xF9, 0xF0, 0xF2, 0x10, 0xC9},
/* Col 6 */ {0xF4, 0xDA, 0x06, 0xDB, 0xBF, 0x4E, 0x6F, 0xB3},
/* Col 7 */ {0x9E, 0x08, 0xD1, 0xAE, 0x59, 0x5E, 0xE8, 0xF0},
/* Col 8 {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E} */
},
{ /* Row 3 */
/* Col 0 */ {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E},
/* Col 1 */ {0x80, 0x69, 0x26, 0x80, 0x08, 0xF8, 0x49, 0xE7},
/* Col 2 */ {0x7D, 0x2D, 0x49, 0x54, 0xD0, 0x80, 0x40, 0xC1},
/* Col 3 */ {0xB6, 0xF2, 0xE6, 0x1B, 0x80, 0x5A, 0x36, 0xB4},
/* Col 4 */ {0x42, 0xAE, 0x9C, 0x1C, 0xDA, 0x67, 0x05, 0xF6},
/* Col 5 */ {0x9B, 0x75, 0xF7, 0xE0, 0x14, 0x8D, 0xB5, 0x80},
/* Col 6 */ {0xBF, 0x54, 0x98, 0xB9, 0xB7, 0x30, 0x5A, 0x88},
/* Col 7 */ {0x35, 0xD1, 0xFC, 0x97, 0x23, 0xD4, 0xC9, 0x88},
/* Col 8 {0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93} */
// Wrong values used by Orange TX/RX
// /* Col 8 */ {0x88, 0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40}
},
{ /* Row 4 */
/* Col 0 */ {0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93},
/* Col 1 */ {0xDC, 0x68, 0x08, 0x99, 0x97, 0xAE, 0xAF, 0x8C},
/* Col 2 */ {0xC3, 0x0E, 0x01, 0x16, 0x0E, 0x32, 0x06, 0xBA},
/* Col 3 */ {0xE0, 0x83, 0x01, 0xFA, 0xAB, 0x3E, 0x8F, 0xAC},
/* Col 4 */ {0x5C, 0xD5, 0x9C, 0xB8, 0x46, 0x9C, 0x7D, 0x84},
/* Col 5 */ {0xF1, 0xC6, 0xFE, 0x5C, 0x9D, 0xA5, 0x4F, 0xB7},
/* Col 6 */ {0x58, 0xB5, 0xB3, 0xDD, 0x0E, 0x28, 0xF1, 0xB0},
/* Col 7 */ {0x5F, 0x30, 0x3B, 0x56, 0x96, 0x45, 0xF4, 0xA1},
/* Col 8 {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8} */
},
};
static void __attribute__((unused)) DSM_read_code(uint8_t *buf, uint8_t row, uint8_t col, uint8_t len)
{
for(uint8_t i=0;i<len;i++)
buf[i]=pgm_read_byte_near( &DSM_pncodes[row][col][i] );
}
static uint8_t __attribute__((unused)) DSM_get_pn_row(uint8_t channel)
{
return ((sub_protocol == DSMX_11 || sub_protocol == DSMX_22 )? (channel - 2) % 5 : channel % 5);
}
const uint8_t PROGMEM DSM_init_vals[][2] = {
{CYRF_02_TX_CTRL, 0x00}, // All TX interrupt disabled
{CYRF_05_RX_CTRL, 0x00}, // All RX interrupt disabled
{CYRF_28_CLK_EN, 0x02}, // Force receive clock enable
{CYRF_32_AUTO_CAL_TIME, 0x3c}, // Default init value
{CYRF_35_AUTOCAL_OFFSET, 0x14}, // Default init value
{CYRF_06_RX_CFG, 0x4A}, // LNA enabled, RX override enabled, Fast turn mode enabled, RX is 1MHz below TX
{CYRF_1B_TX_OFFSET_LSB, 0x55}, // Default init value
{CYRF_1C_TX_OFFSET_MSB, 0x05}, // Default init value
{CYRF_39_ANALOG_CTRL, 0x01}, // All slow for synth setting time
{CYRF_01_TX_LENGTH, 0x10}, // 16 bytes packet
{CYRF_14_EOP_CTRL, 0x02}, // Set EOP Symbol Count to 2
{CYRF_12_DATA64_THOLD, 0x0a}, // 64 Chip Data PN corelator threshold, default datasheet value is 0x0E
//Below is for bind only
{CYRF_03_TX_CFG, 0x38 | CYRF_BIND_POWER}, //64 chip codes, SDR mode
{CYRF_10_FRAMING_CFG, 0x4a}, // SOP disabled, no LEN field and SOP correlator of 0x0a but since SOP is disabled...
{CYRF_1F_TX_OVERRIDE, 0x04}, // Disable TX CRC, no ACK, use TX synthesizer
{CYRF_1E_RX_OVERRIDE, 0x14}, // Disable RX CRC, Force receive data rate, use RX synthesizer
};
const uint8_t PROGMEM DSM_data_vals[][2] = {
{CYRF_29_RX_ABORT, 0x20}, // Abort RX operation in case we are coming from bind
{CYRF_0F_XACT_CFG, 0x24}, // Force Idle
{CYRF_29_RX_ABORT, 0x00}, // Clear abort RX
{CYRF_03_TX_CFG, 0x28 | CYRF_HIGH_POWER}, // 64 chip codes, 8DR mode
{CYRF_10_FRAMING_CFG, 0xea}, // SOP enabled, SOP_CODE_ADR 64 chips, Packet len enabled, SOP correlator 0x0A
{CYRF_1F_TX_OVERRIDE, 0x00}, // CRC16 enabled, no ACK
{CYRF_1E_RX_OVERRIDE, 0x00}, // CRC16 enabled, no ACK
};
static void __attribute__((unused)) DSM_cyrf_config()
{
for(uint8_t i = 0; i < sizeof(DSM_init_vals) / 2; i++)
CYRF_WriteRegister(pgm_read_byte_near(&DSM_init_vals[i][0]), pgm_read_byte_near(&DSM_init_vals[i][1]));
CYRF_WritePreamble(0x333304);
CYRF_ConfigRFChannel(0x61);
}
static void __attribute__((unused)) DSM_build_bind_packet()
{
uint8_t i;
@@ -189,17 +77,17 @@ static void __attribute__((unused)) DSM_build_bind_packet()
packet[8] = sum >> 8;
packet[9] = sum & 0xff;
packet[10] = 0x01; //???
packet[11] = DSM_num_ch;
packet[11] = num_ch;
if (sub_protocol==DSM2_22)
packet[12]=DSM_num_ch<8?0x01:0x02; // DSM2/1024 1 or 2 packets depending on the number of channels
packet[12]=num_ch<8?0x01:0x02; // DSM2/1024 1 or 2 packets depending on the number of channels
if(sub_protocol==DSM2_11)
packet[12]=0x12; // DSM2/2048 2 packets
if(sub_protocol==DSMX_22)
#if defined DSM_TELEMETRY
packet[12] = 0xb2; // DSMX/2048 2 packets
#else
packet[12] = DSM_num_ch<8? 0xa2 : 0xb2; // DSMX/2048 1 or 2 packets depending on the number of channels
packet[12] = num_ch<8? 0xa2 : 0xb2; // DSMX/2048 1 or 2 packets depending on the number of channels
#endif
if(sub_protocol==DSMX_11 || sub_protocol==DSM_AUTO) // Force DSMX/1024 in mode Auto
packet[12]=0xb2; // DSMX/1024 2 packets
@@ -215,29 +103,25 @@ static void __attribute__((unused)) DSM_initialize_bind_phase()
{
CYRF_ConfigRFChannel(DSM_BIND_CHANNEL); //This seems to be random?
//64 SDR Mode is configured so only the 8 first values are needed but need to write 16 values...
CYRF_ConfigDataCode((const uint8_t*)"\xD7\xA1\x54\xB1\x5E\x89\xAE\x86\xc6\x94\x22\xfe\x48\xe6\x57\x4e", 16);
uint8_t code[16];
DSM_read_code(code,0,8,8);
CYRF_ConfigDataCode(code, 16);
DSM_build_bind_packet();
}
static void __attribute__((unused)) DSM_cyrf_configdata()
{
for(uint8_t i = 0; i < sizeof(DSM_data_vals) / 2; i++)
CYRF_WriteRegister(pgm_read_byte_near(&DSM_data_vals[i][0]), pgm_read_byte_near(&DSM_data_vals[i][1]));
}
static void __attribute__((unused)) DSM_update_channels()
{
prev_option=option;
if(sub_protocol==DSM_AUTO)
DSM_num_ch=12; // Force 12 channels in mode Auto
num_ch=12; // Force 12 channels in mode Auto
else
DSM_num_ch=option;
if(DSM_num_ch<4 || DSM_num_ch>12)
DSM_num_ch=6; // Default to 6 channels if invalid choice...
num_ch=option & 0x7F; // Remove the Max Throw flag
if(num_ch<4 || num_ch>12)
num_ch=6; // Default to 6 channels if invalid choice...
// Create channel map based on number of channels and refresh rate
uint8_t idx=DSM_num_ch-4;
if(DSM_num_ch>7 && DSM_num_ch<11 && (sub_protocol==DSM2_11 || sub_protocol==DSMX_11))
uint8_t idx=num_ch-4;
if(num_ch>7 && num_ch<11 && (sub_protocol==DSM2_11 || sub_protocol==DSMX_11))
idx+=5; // In 11ms mode change index only for channels 8..10
for(uint8_t i=0;i<14;i++)
ch_map[i]=pgm_read_byte_near(&DSM_ch_map_progmem[idx][i]);
@@ -260,7 +144,7 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
packet[0] = (0xff ^ cyrfmfg_id[2]);
packet[1] = (0xff ^ cyrfmfg_id[3]);
if(sub_protocol==DSM2_22)
bits=10; // Only DSM_22 is using a resolution of 1024
bits=10; // Only DSM2_22 is using a resolution of 1024
}
#ifdef DSM_THROTTLE_KILL_CH
uint16_t kill_ch=Channel_data[DSM_THROTTLE_KILL_CH-1];
@@ -274,8 +158,8 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
/* Spektrum own remotes transmit normal values during bind and actually use this (e.g. Nano CP X) to
select the transmitter mode (e.g. computer vs non-computer radio), so always send normal output */
#ifdef DSM_THROTTLE_KILL_CH
if(CH_TAER[idx]==THROTTLE && kill_ch<=604)
{//Activate throttle kill only if DSM_THROTTLE_KILL_CH below -50%
if(idx==CH1 && kill_ch<=604)
{//Activate throttle kill only if channel is throttle and DSM_THROTTLE_KILL_CH below -50%
if(kill_ch<CHANNEL_MIN_100) // restrict val to 0...400
kill_ch=0;
else
@@ -285,9 +169,12 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
else
#endif
#ifdef DSM_MAX_THROW
value=Channel_data[CH_TAER[idx]]; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX
value=Channel_data[CH_TAER[idx]]; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX
#else
value=convert_channel_16b_nolimit(CH_TAER[idx],0x150,0x6B0); // -100%..+100% => 1100..1900us and -125%..+125% => 1000..2000us based on Redcon 6 channel DSM2 RX
if(option & 0x80)
value=Channel_data[CH_TAER[idx]]; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX
else
value=convert_channel_16b_nolimit(CH_TAER[idx],0x150,0x6B0); // -100%..+100% => 1100..1900us and -125%..+125% => 1000..2000us based on Redcon 6 channel DSM2 RX
#endif
if(bits==10) value>>=1;
value |= (upper && i==0 ? 0x8000 : 0) | (idx << bits);
@@ -297,66 +184,6 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
}
}
static void __attribute__((unused)) DSM_set_sop_data_crc()
{
//The crc for channel '1' is NOT(mfgid[0] << 8 + mfgid[1])
//The crc for channel '2' is (mfgid[0] << 8 + mfgid[1])
uint16_t crc = (cyrfmfg_id[0] << 8) + cyrfmfg_id[1];
if(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B)
CYRF_ConfigCRCSeed(crc); //CH2
else
CYRF_ConfigCRCSeed(~crc); //CH1
uint8_t pn_row = DSM_get_pn_row(hopping_frequency[hopping_frequency_no]);
uint8_t code[16];
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
DSM_read_code(code+8,pn_row,7 - sop_col + 1,8); // 7-sop_col+1 between 1 and 7
CYRF_ConfigDataCode(code, 16);
CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]);
hopping_frequency_no++;
if(sub_protocol == DSMX_11 || sub_protocol == DSMX_22)
hopping_frequency_no %=23;
else
hopping_frequency_no %=2;
}
static void __attribute__((unused)) DSM_calc_dsmx_channel()
{
uint8_t idx = 0;
uint32_t id = ~(((uint32_t)cyrfmfg_id[0] << 24) | ((uint32_t)cyrfmfg_id[1] << 16) | ((uint32_t)cyrfmfg_id[2] << 8) | (cyrfmfg_id[3] << 0));
uint32_t id_tmp = id;
while(idx < 23)
{
uint8_t i;
uint8_t count_3_27 = 0, count_28_51 = 0, count_52_76 = 0;
id_tmp = id_tmp * 0x0019660D + 0x3C6EF35F; // Randomization
uint8_t next_ch = ((id_tmp >> 8) % 0x49) + 3; // Use least-significant byte and must be larger than 3
if ( (next_ch ^ cyrfmfg_id[3]) & 0x01 )
continue;
for (i = 0; i < idx; i++)
{
if(hopping_frequency[i] == next_ch)
break;
if(hopping_frequency[i] <= 27)
count_3_27++;
else
if (hopping_frequency[i] <= 51)
count_28_51++;
else
count_52_76++;
}
if (i != idx)
continue;
if ((next_ch < 28 && count_3_27 < 8)
||(next_ch >= 28 && next_ch < 52 && count_28_51 < 7)
||(next_ch >= 52 && count_52_76 < 8))
hopping_frequency[idx++] = next_ch;
}
}
static uint8_t __attribute__((unused)) DSM_Check_RX_packet()
{
uint8_t result=1; // assume good packet
@@ -364,21 +191,25 @@ static uint8_t __attribute__((unused)) DSM_Check_RX_packet()
uint16_t sum = 384 - 0x10;
for(uint8_t i = 1; i < 9; i++)
{
sum += pkt[i];
sum += packet_in[i];
if(i<5)
if(pkt[i] != (0xff ^ cyrfmfg_id[i-1]))
if(packet_in[i] != (0xff ^ cyrfmfg_id[i-1]))
result=0; // bad packet
}
if( pkt[9] != (sum>>8) && pkt[10] != (uint8_t)sum )
if( packet_in[9] != (sum>>8) && packet_in[10] != (uint8_t)sum )
result=0;
return result;
}
uint16_t ReadDsm()
{
#define DSM_CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2
#define DSM_WRITE_DELAY 1950 // Time after write to verify write complete
#define DSM_READ_DELAY 600 // Time before write to check read phase, and switch channels. Was 400 but 600 seems what the 328p needs to read a packet
#define DSM_CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2
#ifdef STM32_BOARD
#define DSM_WRITE_DELAY 1600 // Time after write to verify write complete
#else
#define DSM_WRITE_DELAY 1950 // Time after write to verify write complete
#endif
#define DSM_READ_DELAY 600 // Time before write to check read phase, and switch channels. Was 400 but 600 seems what the 328p needs to read a packet
#if defined DSM_TELEMETRY
uint8_t rx_phase;
uint8_t len;
@@ -399,7 +230,7 @@ uint16_t ReadDsm()
#if defined DSM_TELEMETRY
case DSM_BIND_CHECK:
//64 SDR Mode is configured so only the 8 first values are needed but we need to write 16 values...
CYRF_ConfigDataCode((const uint8_t *)"\x98\x88\x1B\xE4\x30\x79\x03\x84\xC9\x2C\x06\x93\x86\xB9\x9E\xD7", 16);
CYRF_ConfigDataCode((const uint8_t *)"\x98\x88\x1B\xE4\x30\x79\x03\x84", 16);
CYRF_SetTxRxMode(RX_EN); //Receive mode
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //Prepare to receive
bind_counter=2*DSM_BIND_COUNT; //Timeout of 4.2s if no packet received
@@ -412,18 +243,22 @@ uint16_t ReadDsm()
rx_phase |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((rx_phase & 0x07) == 0x02)
{ // data received with no errors
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
if(len>MAX_PKT-2)
len=MAX_PKT-2;
CYRF_ReadDataPacketLen(pkt+1, len);
if(len==10 && DSM_Check_RX_packet())
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // Need to set RXOW before data read
if(CYRF_ReadRegister(CYRF_09_RX_COUNT)==10) // Len
{
pkt[0]=0x80;
telemetry_link=1; // send received data on serial
phase++;
return 2000;
CYRF_ReadDataPacketLen(packet_in+1, 10);
if(DSM_Check_RX_packet())
{
packet_in[0]=0x80;
telemetry_link=1; // Send received data on serial
phase++;
return 2000;
}
}
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
CYRF_SetTxRxMode(RX_EN); // Force end state read
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX operation
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83); // Prepare to receive
}
else
if((rx_phase & 0x02) != 0x02)
@@ -435,7 +270,7 @@ uint16_t ReadDsm()
}
if( --bind_counter == 0 )
{ // Exit if no answer has been received for some time
phase++; // DSM_CHANSEL
phase++; // DSM_CHANSEL
return 7000 ;
}
return 7000;
@@ -446,9 +281,12 @@ uint16_t ReadDsm()
CYRF_SetTxRxMode(TX_EN);
hopping_frequency_no = 0;
phase = DSM_CH1_WRITE_A; // in fact phase++
DSM_set_sop_data_crc();
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11||sub_protocol==DSMX_22);
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
#endif
case DSM_CH1_WRITE_B:
case DSM_CH2_WRITE_A:
case DSM_CH2_WRITE_B:
@@ -465,6 +303,7 @@ uint16_t ReadDsm()
while ((uint8_t)((uint8_t)micros()-(uint8_t)start) < 100) // Wait max 100µs, max I've seen is 50µs
if((CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80) == 0x00)
break;
if(phase==DSM_CH1_CHECK_A || phase==DSM_CH1_CHECK_B)
{
#if defined DSM_TELEMETRY
@@ -477,7 +316,7 @@ uint16_t ReadDsm()
CYRF_SetTxRxMode(TX_EN);
}
#endif
DSM_set_sop_data_crc();
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11 || sub_protocol==DSMX_22);
phase++; // change from CH1_CHECK to CH2_WRITE
return DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY;
}
@@ -498,14 +337,14 @@ uint16_t ReadDsm()
{ // good data (complete with no errors)
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
if(len>MAX_PKT-2)
len=MAX_PKT-2;
CYRF_ReadDataPacketLen(pkt+1, len);
pkt[0]=CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;// store RSSI of the received telemetry signal
if(len>TELEMETRY_BUFFER_SIZE-2)
len=TELEMETRY_BUFFER_SIZE-2;
CYRF_ReadDataPacketLen(packet_in+1, len);
packet_in[0]=CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;// store RSSI of the received telemetry signal
telemetry_link=1;
}
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
if (phase == DSM_CH2_READ_A && (sub_protocol==DSM2_22 || sub_protocol==DSMX_22) && DSM_num_ch < 8) // 22ms mode
if (phase == DSM_CH2_READ_A && (sub_protocol==DSM2_22 || sub_protocol==DSMX_22) && num_ch < 8) // 22ms mode
{
CYRF_SetTxRxMode(RX_EN); // Force end state read
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX operation
@@ -519,14 +358,14 @@ uint16_t ReadDsm()
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();
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11||sub_protocol==DSMX_22);
return DSM_READ_DELAY;
#else
// No telemetry
DSM_set_sop_data_crc();
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11||sub_protocol==DSMX_22);
if (phase == DSM_CH2_CHECK_A)
{
if(DSM_num_ch > 7 || sub_protocol==DSM2_11 || sub_protocol==DSMX_11)
if(num_ch > 7 || sub_protocol==DSM2_11 || sub_protocol==DSMX_11)
phase = DSM_CH1_WRITE_B; //11ms mode or upper to transmit change from CH2_CHECK_A to CH1_WRITE_A
else
{ //Normal mode 22ms
@@ -555,6 +394,8 @@ uint16_t initDsm()
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_11 || sub_protocol == DSMX_22)
DSM_calc_dsmx_channel();

View File

@@ -17,8 +17,6 @@
#include "iface_cyrf6936.h"
#define DEVO_NUM_CHANNELS 8
//For Debug
//#define NO_SCRAMBLE
@@ -93,7 +91,7 @@ static void __attribute__((unused)) DEVO_add_pkt_suffix()
static void __attribute__((unused)) DEVO_build_beacon_pkt(uint8_t upper)
{
packet[0] = (DEVO_NUM_CHANNELS << 4) | 0x07;
packet[0] = (num_ch << 4) | 0x07;
uint8_t max = 8, offset = 0, enable = 0;
if (upper)
{
@@ -105,7 +103,7 @@ static void __attribute__((unused)) DEVO_build_beacon_pkt(uint8_t upper)
{
#ifdef FAILSAFE_ENABLE
uint16_t failsafe=Failsafe_data[CH_EATR[i+offset]];
if(i + offset < DEVO_NUM_CHANNELS && failsafe!=FAILSAFE_CHANNEL_HOLD && IS_FAILSAFE_VALUES_on)
if(i + offset < num_ch && failsafe!=FAILSAFE_CHANNEL_HOLD && IS_FAILSAFE_VALUES_on)
{
enable |= 0x80 >> i;
packet[i+1] = ((failsafe*25)>>8)-100;
@@ -122,7 +120,7 @@ static void __attribute__((unused)) DEVO_build_beacon_pkt(uint8_t upper)
static void __attribute__((unused)) DEVO_build_bind_pkt()
{
packet[0] = (DEVO_NUM_CHANNELS << 4) | 0x0a;
packet[0] = (num_ch << 4) | 0x0a;
packet[1] = bind_counter & 0xff;
packet[2] = (bind_counter >> 8);
packet[3] = *hopping_frequency_ptr;
@@ -144,7 +142,7 @@ static void __attribute__((unused)) DEVO_build_data_pkt()
{
static uint8_t ch_idx=0;
packet[0] = (DEVO_NUM_CHANNELS << 4) | (0x0b + ch_idx);
packet[0] = (num_ch << 4) | (0x0b + ch_idx);
uint8_t sign = 0x0b;
for (uint8_t i = 0; i < 4; i++)
{
@@ -159,11 +157,36 @@ static void __attribute__((unused)) DEVO_build_data_pkt()
}
packet[9] = sign;
ch_idx++;
if (ch_idx * 4 >= DEVO_NUM_CHANNELS)
if (ch_idx * 4 >= num_ch)
ch_idx = 0;
DEVO_add_pkt_suffix();
}
static void __attribute__((unused)) DEVO_parse_telemetry_packet()
{
DEVO_scramble_pkt(); //This will unscramble the packet
debugln("RX");
if ((((uint32_t)packet[15] << 16) | ((uint32_t)packet[14] << 8) | packet[13]) != (MProtocol_id & 0x00ffffff))
return; // ID does not match
//RSSI
TX_RSSI = CYRF_ReadRegister(CYRF_13_RSSI) & 0x1F;
TX_RSSI = (TX_RSSI << 1) + TX_RSSI;
RX_RSSI = TX_RSSI;
telemetry_link = 1;
//TODO: FW telemetry https://github.com/DeviationTX/deviation/blob/5efb6a28bea697af9a61b5a0ed2528cc8d203f90/src/protocol/devo_cyrf6936.c#L232
debug("P[0]=%02X",packet[0]);
if (packet[0] == 0x30) // Volt packet
{
v_lipo1 = packet[1] << 1;
v_lipo2 = packet[3] << 1;
}
}
static void __attribute__((unused)) DEVO_cyrf_set_bound_sop_code()
{
/* crc == 0 isn't allowed, so use 1 if the math results in 0 */
@@ -258,7 +281,7 @@ static void __attribute__((unused)) DEVO_BuildPacket()
}
break;
case DEVO_BOUND_10:
DEVO_build_beacon_pkt(DEVO_NUM_CHANNELS > 8 ? failsafe_pkt : 0);
DEVO_build_beacon_pkt(num_ch > 8 ? failsafe_pkt : 0);
failsafe_pkt = failsafe_pkt ? 0 : 1;
DEVO_scramble_pkt();
phase = DEVO_BOUND_1;
@@ -272,8 +295,87 @@ static void __attribute__((unused)) DEVO_BuildPacket()
uint16_t devo_callback()
{
static uint8_t txState=0;
#if defined DEVO_HUB_TELEMETRY
int delay;
if (txState == 0)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(2400);
#endif
DEVO_BuildPacket();
CYRF_WriteDataPacket(packet);
txState = 1;
return 900;
}
if (txState == 1)
{
int i = 0;
uint8_t reg;
while (! ((reg = CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS)) & 0x02))
{
if (++i >= DEVO_NUM_WAIT_LOOPS)
break;
}
if (((reg & 0x22) == 0x20) || (CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80))
{
CYRF_Reset();
DEVO_cyrf_init();
DEVO_cyrf_set_bound_sop_code();
CYRF_ConfigRFChannel(*hopping_frequency_ptr);
//printf("Rst CYRF\n");
delay = 1500;
txState = 15;
}
else
{
if (phase == DEVO_BOUND)
{
/* exit binding state */
phase = DEVO_BOUND_3;
DEVO_cyrf_set_bound_sop_code();
}
if((packet_count != 0) && (bind_counter == 0))
{
CYRF_SetTxRxMode(RX_EN); //Receive mode
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //0x80??? //Prepare to receive
txState = 2;
return 1300;
}
}
if(packet_count == 0)
{
CYRF_SetPower(0x08); //Keep tx power updated
hopping_frequency_ptr = hopping_frequency_ptr == &hopping_frequency[2] ? hopping_frequency : hopping_frequency_ptr + 1;
CYRF_ConfigRFChannel(*hopping_frequency_ptr);
}
delay = 1500;
}
if(txState == 2)
{
uint8_t rx_state = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((rx_state & 0x03) == 0x02)
{ // RXC=1, RXE=0 then 2nd check is required (debouncing)
rx_state |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
}
if((rx_state & 0x07) == 0x02)
{ // good data (complete with no errors)
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read
CYRF_ReadDataPacketLen(packet, CYRF_ReadRegister(CYRF_09_RX_COUNT));
DEVO_parse_telemetry_packet();
}
CYRF_SetTxRxMode(TX_EN); //Write mode
delay = 200;
}
txState = 0;
return delay;
#else
if (txState == 0)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(2400);
#endif
txState = 1;
DEVO_BuildPacket();
CYRF_WriteDataPacket(packet);
@@ -297,10 +399,29 @@ uint16_t devo_callback()
CYRF_ConfigRFChannel(*hopping_frequency_ptr);
}
return 1200;
#endif
}
uint16_t DevoInit()
{
switch(sub_protocol)
{
case 1:
num_ch=10;
break;
case 2:
num_ch=12;
break;
case 3:
num_ch=6;
break;
case 4:
num_ch=7;
break;
default:
num_ch=8;
break;
}
DEVO_cyrf_init();
CYRF_GetMfgData(cyrfmfg_id);
CYRF_SetTxRxMode(TX_EN);

View File

@@ -287,7 +287,12 @@ uint16_t E01X_callback()
}
}
else
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
E01X_send_packet(0);
}
return packet_period;
}

View File

@@ -92,8 +92,8 @@ static void __attribute__((unused)) ESKY150_send_packet()
uint8_t flight_mode=0;
uint16_t aux_ch6=0;
uint8_t aux_ch7=0;
if(option==1)
{
if(sub_protocol)
{ // 7 channels
flight_mode=ESKY150_convert_2bit_channel(CH5);
aux_ch6=convert_channel_16b_limit(CH6,1000,2000);
aux_ch7=ESKY150_convert_2bit_channel(CH7);
@@ -151,7 +151,12 @@ uint8_t ESKY150_convert_2bit_channel(uint8_t num)
uint16_t ESKY150_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(ESKY150_SENDING_PACKET_PERIOD);
#endif
ESKY150_send_packet();
}
else
{
NRF24L01_WritePayload(packet, ESKY150_PAYLOADSIZE);

View File

@@ -0,0 +1,141 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(ESKY150V2_CC2500_INO)
#include "iface_nrf250k.h"
//#define ESKY150V2_FORCE_ID
#define ESKY150V2_PAYLOADSIZE 40
#define ESKY150V2_BINDPAYLOADSIZE 150
#define ESKY150V2_NFREQCHANNELS 70
#define ESKY150V2_TXID_SIZE 4
#define ESKY150V2_BIND_CHANNEL 0x00
#define ESKY150V2_PACKET_PERIOD 10000
#define ESKY150V2_BINDING_PACKET_PERIOD 57000
#ifdef ESKY150V2_FORCE_ID
const uint8_t PROGMEM ESKY150V2_hop[ESKY150V2_NFREQCHANNELS]= {
0x07, 0x47, 0x09, 0x27, 0x0B, 0x42, 0x0D, 0x35, 0x17, 0x40, 0x26, 0x3D, 0x16, 0x43, 0x06, 0x2A, 0x24, 0x44,
0x0E, 0x38, 0x20, 0x48, 0x22, 0x2D, 0x2B, 0x39, 0x0F, 0x36, 0x23, 0x46, 0x14, 0x3B, 0x1A, 0x41, 0x10, 0x2E,
0x1E, 0x28, 0x0C, 0x49, 0x1D, 0x3E, 0x29, 0x2C, 0x25, 0x30, 0x1C, 0x2F, 0x1B, 0x33, 0x13, 0x31, 0x0A, 0x37,
0x12, 0x3C, 0x18, 0x4B, 0x11, 0x45, 0x21, 0x4A, 0x1F, 0x3F, 0x15, 0x32, 0x08, 0x3A, 0x19, 0x34 };
/*const uint8_t PROGMEM ESKY150V2_hop2[40]= {
0x19, 0x23, 0x13, 0x1B, 0x09, 0x22, 0x14, 0x27, 0x06, 0x26, 0x16, 0x24, 0x0B, 0x2A, 0x0E, 0x1C, 0x11, 0x1E,
0x08, 0x29, 0x0D, 0x28, 0x18, 0x2D, 0x12, 0x20, 0x0C, 0x1A, 0x10, 0x1D, 0x07, 0x2C, 0x0A, 0x2B, 0x0F, 0x25,
0x15, 0x1F, 0x17, 0x21 };*/
#endif
static void __attribute__((unused)) ESKY150V2_set_freq(void)
{
calc_fh_channels(ESKY150V2_NFREQCHANNELS);
#ifdef ESKY150V2_FORCE_ID
for(uint8_t i=0; i<ESKY150V2_NFREQCHANNELS; i++)
hopping_frequency[i]=pgm_read_byte_near( &ESKY150V2_hop[i] );
#endif
//Bind channel
hopping_frequency[ESKY150V2_NFREQCHANNELS]=ESKY150V2_BIND_CHANNEL;
//Calib all channels
NRF250K_SetFreqOffset(); // Set frequency offset
NRF250K_HoppingCalib(ESKY150V2_NFREQCHANNELS+1);
}
static void __attribute__((unused)) ESKY150V2_send_packet()
{
NRF250K_SetFreqOffset(); // Set frequency offset
NRF250K_Hopping(hopping_frequency_no);
if (++hopping_frequency_no >= ESKY150V2_NFREQCHANNELS)
hopping_frequency_no = 0;
NRF250K_SetPower(); //Set power level
packet[0] = 0xFA; // Unknown
packet[1] = 0x41; // Unknown
packet[2] = 0x08; // Unknown
packet[3] = 0x00; // Unknown
for(uint8_t i=0;i<16;i++)
{
uint16_t channel=convert_channel_16b_limit(CH_TAER[i],200,1000);
packet[4+2*i] = channel;
packet[5+2*i] = channel>>8;
}
NRF250K_WritePayload(packet, ESKY150V2_PAYLOADSIZE);
}
uint16_t ESKY150V2_callback()
{
if(option==0) option=1; //Trick the RF component auto select system
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(ESKY150V2_PACKET_PERIOD);
#endif
ESKY150V2_send_packet();
}
else
{
BIND_DONE; //Need full power for bind to work...
NRF250K_SetPower(); //Set power level
BIND_IN_PROGRESS;
NRF250K_WritePayload(packet, ESKY150V2_BINDPAYLOADSIZE);
if (--bind_counter == 0)
{
BIND_DONE;
// Change TX address from bind to normal mode
NRF250K_SetTXAddr(rx_tx_addr, ESKY150V2_TXID_SIZE);
memset(packet,0x00,ESKY150V2_PAYLOADSIZE);
}
return 30000; //ESKY150V2_BINDING_PACKET_PERIOD;
}
return ESKY150V2_PACKET_PERIOD;
}
uint16_t initESKY150V2()
{
if(option==0) option=1; // Trick the RF component auto select system
NRF250K_Init();
ESKY150V2_set_freq();
hopping_frequency_no = 0;
#ifdef ESKY150V2_FORCE_ID // ID taken from TX dump
rx_tx_addr[0]=0x87;rx_tx_addr[1]=0x5B;rx_tx_addr[2]=0x2C;rx_tx_addr[3]=0x5D;
#endif
memset(packet,0x00,ESKY150V2_BINDPAYLOADSIZE);
if(IS_BIND_IN_PROGRESS)
{
NRF250K_SetTXAddr((uint8_t *)"\x73\x73\x74\x63", ESKY150V2_TXID_SIZE); //Bind address
NRF250K_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);
packet[8]=0x41; //Unknown
packet[9]=0x88; //Unknown
packet[10]=0x41; //Unknown
memset(&packet[11],0xAA,4); //Unknown
memcpy(&packet[15],hopping_frequency,ESKY150V2_NFREQCHANNELS); // hop table
//for(uint8_t i=0; i<40; i++) // Does not seem to be needed
// packet[i+85]=pgm_read_byte_near( &ESKY150V2_hop2[i] );
bind_counter=100;
}
else
NRF250K_SetTXAddr(rx_tx_addr, ESKY150V2_TXID_SIZE);
return 50000;
}
#endif

View File

@@ -18,8 +18,13 @@
#include "iface_nrf24l01.h"
//#define ESKY_ET4_FORCE_ID
#define ESKY_BIND_COUNT 1000
#define ESKY_PACKET_PERIOD 3333
#define ESKY_STD_PACKET_PERIOD 3333
#define ESKY_ET4_PACKET_PERIOD 1190
#define ESKY_ET4_TOTAL_PACKET_PERIOD 20300
#define ESKY_ET4_BIND_PACKET_PERIOD 5000
#define ESKY_PAYLOAD_SIZE 13
#define ESKY_PACKET_CHKTIME 100 // Time to wait for packet to be sent (no ACK, so very short)
@@ -63,28 +68,37 @@ static void __attribute__((unused)) ESKY_init()
static void __attribute__((unused)) ESKY_init2()
{
NRF24L01_FlushTx();
hopping_frequency_no = 0;
uint16_t channel_ord = rx_tx_addr[0] % 74;
hopping_frequency[12] = 10 + (uint8_t)channel_ord; //channel_code
uint8_t channel1, channel2;
channel1 = 10 + (uint8_t)((37 + channel_ord*5) % 74);
channel2 = 10 + (uint8_t)(( channel_ord*5) % 74) ;
if(sub_protocol==ESKY_STD)
{
uint16_t channel_ord = rx_tx_addr[0] % 74;
hopping_frequency[12] = 10 + (uint8_t)channel_ord; //channel_code
uint8_t channel1, channel2;
channel1 = 10 + (uint8_t)((37 + channel_ord*5) % 74);
channel2 = 10 + (uint8_t)(( channel_ord*5) % 74) ;
hopping_frequency[0] = channel1;
hopping_frequency[1] = channel1;
hopping_frequency[2] = channel1;
hopping_frequency[3] = channel2;
hopping_frequency[4] = channel2;
hopping_frequency[5] = channel2;
//end_bytes
hopping_frequency[6] = 6;
hopping_frequency[7] = channel1*2;
hopping_frequency[8] = channel2*2;
hopping_frequency[9] = 6;
hopping_frequency[10] = channel1*2;
hopping_frequency[11] = channel2*2;
hopping_frequency[0] = channel1;
hopping_frequency[1] = channel1;
hopping_frequency[2] = channel1;
hopping_frequency[3] = channel2;
hopping_frequency[4] = channel2;
hopping_frequency[5] = channel2;
//end_bytes
hopping_frequency[6] = 6;
hopping_frequency[7] = channel1*2;
hopping_frequency[8] = channel2*2;
hopping_frequency[9] = 6;
hopping_frequency[10] = channel1*2;
hopping_frequency[11] = channel2*2;
}
else
{ // ESKY_ET4
hopping_frequency[0] = 0x29; //41
hopping_frequency[1] = 0x12; //18
hopping_frequency[6] = 0x87; //135 payload end byte
hopping_frequency[12] = 0x84; //132 indicates which channels to use
}
// Turn radio power on
NRF24L01_SetTxRxMode(TX_EN);
}
@@ -111,20 +125,32 @@ static void __attribute__((unused)) ESKY_send_packet(uint8_t bind)
}
else
{
// Regular packet
// Each data packet is repeated 3 times on one channel, and 3 times on another channel
// For arithmetic simplicity, channels are repeated in rf_channels array
if (hopping_frequency_no == 0)
if (packet_count == 0)
for (uint8_t i = 0; i < 6; i++)
{
uint16_t val=convert_channel_ppm(CH_AETR[i]);
packet[i*2] = val>>8; //high byte of servo timing(1000-2000us)
packet[i*2+1] = val&0xFF; //low byte of servo timing(1000-2000us)
}
rf_ch = hopping_frequency[hopping_frequency_no];
packet[12] = hopping_frequency[hopping_frequency_no+6]; // end_bytes
hopping_frequency_no++;
if (hopping_frequency_no > 6) hopping_frequency_no = 0;
if(sub_protocol==ESKY_STD)
{
// Regular packet
// Each data packet is repeated 3 times on one channel, and 3 times on another channel
// For arithmetic simplicity, channels are repeated in rf_channels array
rf_ch = hopping_frequency[packet_count];
packet[12] = hopping_frequency[packet_count+6]; // end_bytes
packet_count++;
if (packet_count > 6) packet_count = 0;
}
else
{ // ESKY_ET4
// Regular packet
// Each data packet is repeated 14 times alternating between 2 channels
rf_ch = hopping_frequency[packet_count&1];
packet_count++;
if(packet_count>14) packet_count=0;
packet[12] = hopping_frequency[6]; // end_byte
}
}
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch);
NRF24L01_FlushTx();
@@ -135,7 +161,20 @@ static void __attribute__((unused)) ESKY_send_packet(uint8_t bind)
uint16_t ESKY_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
if(packet_count==0)
telemetry_set_input_sync(sub_protocol==ESKY_STD?ESKY_STD_PACKET_PERIOD*6:ESKY_ET4_TOTAL_PACKET_PERIOD);
#endif
ESKY_send_packet(0);
if(sub_protocol==ESKY_ET4)
{
if(packet_count==0)
return ESKY_ET4_TOTAL_PACKET_PERIOD-ESKY_ET4_PACKET_PERIOD*13;
else
return ESKY_ET4_PACKET_PERIOD;
}
}
else
{
ESKY_send_packet(1);
@@ -145,16 +184,25 @@ uint16_t ESKY_callback()
BIND_DONE;
}
}
return ESKY_PACKET_PERIOD;
return ESKY_STD_PACKET_PERIOD;
}
uint16_t initESKY(void)
{
bind_counter = ESKY_BIND_COUNT;
rx_tx_addr[2] = rx_tx_addr[3]; // Model match
#ifdef ESKY_ET4_FORCE_ID
if(sub_protocol==ESKY_ET4)
{
rx_tx_addr[0]=0x72;
rx_tx_addr[1]=0xBB;
rx_tx_addr[2]=0xCC;
}
#endif
rx_tx_addr[3] = 0xBB;
ESKY_init();
ESKY_init2();
packet_count=0;
return 50000;
}

View File

@@ -188,7 +188,12 @@ uint16_t FQ777_callback()
}
}
else
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(FQ777_PACKET_PERIOD);
#endif
FQ777_send_packet(0);
}
return FQ777_PACKET_PERIOD;
}

View File

@@ -0,0 +1,113 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
// Compatible with FEI XIONG P38 plane.
#if defined(FX816_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define FX816_INITIAL_WAIT 500
#define FX816_PACKET_PERIOD 10000
#define FX816_RF_BIND_CHANNEL 0x28 //40
#define FX816_RF_NUM_CHANNELS 4
#define FX816_PAYLOAD_SIZE 6
#define FX816_BIND_COUNT 300 //3sec
static void __attribute__((unused)) FX816_send_packet()
{
packet[0] = IS_BIND_IN_PROGRESS?0x55:0xAA;
packet[1] = rx_tx_addr[0];
packet[2] = rx_tx_addr[1];
uint8_t val=convert_channel_8b(AILERON);
#define FX816_SWITCH 20
if(val>127+FX816_SWITCH)
packet[3] = 1;
else if(val<127-FX816_SWITCH)
packet[3] = 2;
else
packet[3] = 0;
packet[4] = convert_channel_16b_limit(THROTTLE,0,100);
val=0;
for(uint8_t i=0;i<FX816_PAYLOAD_SIZE-1;i++)
val+=packet[i];
packet[5]=val;
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();
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_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc", 5);
NRF24L01_FlushTx();
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_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // No retransmits
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
NRF24L01_Activate(0x73);
}
static void __attribute__((unused)) FX816_initialize_txid()
{
//Only 8 IDs: the RX led does not indicate frame loss.
//I didn't open the plane to find out if I could connect there so this is the best I came up with with few trial and errors...
rx_tx_addr[0]=0x35+(rx_tx_addr[3]&0x07); //Original dump=0x35
rx_tx_addr[1]=0x09; //Original dump=0x09
memcpy(hopping_frequency,"\x09\x1B\x30\x42",FX816_RF_NUM_CHANNELS); //Original dump=9=0x09,27=0x1B,48=0x30,66=0x42
for(uint8_t i=0;i<FX816_RF_NUM_CHANNELS;i++)
hopping_frequency[i]+=rx_tx_addr[3]&0x07;
}
uint16_t FX816_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(FX816_PACKET_PERIOD);
#endif
if(IS_BIND_IN_PROGRESS)
if(--bind_counter==0)
BIND_DONE;
FX816_send_packet();
return FX816_PACKET_PERIOD;
}
uint16_t initFX816()
{
BIND_IN_PROGRESS; // autobind protocol
FX816_initialize_txid();
FX816_init();
hopping_frequency_no = 0;
bind_counter=FX816_BIND_COUNT;
return FX816_INITIAL_WAIT;
}
#endif

View File

@@ -188,6 +188,9 @@ uint16_t FY326_callback()
return FY326_PACKET_CHKTIME;
break;
case FY326_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(FY326_PACKET_PERIOD);
#endif
FY326_send_packet(0);
break;
}

View File

@@ -145,7 +145,7 @@ static void __attribute__((unused)) flysky_build_packet(uint8_t init)
for(i = 0; i < 8; i++)
{
uint16_t temp=convert_channel_ppm(CH_AETR[i]);
if(sub_protocol == CX20 && CH_AETR[i]==ELEVATOR)
if(sub_protocol == CX20 && i==CH2) //ELEVATOR
temp=3000-temp;
packet[5 + i*2]=temp&0xFF; //low byte of servo timing(1000-2000us)
packet[6 + i*2]=(temp>>8)&0xFF; //high byte of servo timing(1000-2000us)
@@ -168,16 +168,15 @@ uint16_t ReadFlySky()
}
else
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
flysky_build_packet(0);
A7105_WriteData(21, hopping_frequency[hopping_frequency_no & 0x0F]);
A7105_SetPower();
}
hopping_frequency_no++;
if(sub_protocol==CX20)
return 3984;
else
return 1510; //1460 on deviation but not working with the latest V911 bricks... Turnigy 9X v2 is 1533, Flysky TX for 9XR/9XR Pro is 1510, V911 TX is 1490.
return packet_period;
}
const uint8_t PROGMEM tx_channels[8][4] = {
@@ -235,6 +234,10 @@ uint16_t initFlySky()
}
hopping_frequency_no=0;
packet_count=0;
if(sub_protocol==CX20)
packet_period=3984;
else
packet_period=1510; //1460 on deviation but not working with the latest V911 bricks... Turnigy 9X v2 is 1533, Flysky TX for 9XR/9XR Pro is 1510, V911 TX is 1490.
if(IS_BIND_IN_PROGRESS)
bind_counter = FLYSKY_BIND_COUNT;
else

View File

@@ -0,0 +1,106 @@
/*
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 FZ-410 TX
#if defined(FLYZONE_A7105_INO)
#include "iface_a7105.h"
//#define FLYZONE_FORCEID
#define FLYZONE_BIND_COUNT 220 // 5 sec
#define FLYZONE_BIND_CH 0x18 // TX, RX for bind end is 0x17
static void __attribute__((unused)) flyzone_build_packet()
{
packet[0] = 0xA5;
packet[1] = rx_tx_addr[2];
packet[2] = rx_tx_addr[3];
packet[3] = convert_channel_8b(AILERON); //00..80..FF
packet[4] = convert_channel_8b(ELEVATOR); //00..80..FF
packet[5] = convert_channel_8b(THROTTLE); //00..FF
packet[6] = convert_channel_8b(RUDDER); //00..80..FF
packet[7] = convert_channel_8b(CH5); //00..80..FF
}
uint16_t ReadFlyzone()
{
#ifndef FORCE_FLYZONE_TUNING
A7105_AdjustLOBaseFreq(1);
#endif
if(IS_BIND_IN_PROGRESS)
{
packet[0] = 0x1B;
packet[1] = rx_tx_addr[2];
packet[2] = rx_tx_addr[3];
A7105_WriteData(3, FLYZONE_BIND_CH);
if (bind_counter--==0)
BIND_DONE;
return 22700;
}
else
{
if(phase>19)
{
phase=0;
#ifdef MULTI_SYNC
telemetry_set_input_sync(20*1500);
#endif
flyzone_build_packet();
A7105_WriteData(8, hopping_frequency[0]);
A7105_SetPower();
}
else
{
A7105_WriteReg(A7105_0F_PLL_I, hopping_frequency[(phase&0x02)>>1]);
A7105_Strobe(A7105_TX);
}
phase++;
}
return 1500;
}
uint16_t initFlyzone()
{
A7105_Init();
hopping_frequency[0]=((random(0xfefefefe) & 0x0F)+2)<<2;
hopping_frequency[1]=hopping_frequency[0]+0x50;
#ifdef FLYZONE_FORCEID
rx_tx_addr[2]=0x35;
rx_tx_addr[3]=0xD0;
hopping_frequency[0]=0x18;
hopping_frequency[1]=0x68;
#endif
phase=255;
bind_counter = FLYZONE_BIND_COUNT;
return 2400;
}
#endif
// Normal packet is 8 bytes: 0xA5 0xAF 0x59 0x84 0x7A 0x00 0x80 0xFF
// Protocol is using AETR channel order, 1 byte per channel 00..80..FF including trim. Channels are in packet [3,4,5,6].
// packet[0,1,2,7] values are constant in normal mode.
// packet[0]=0xA5 -> normal mode
// packet[1,2] ->ID
// packet[7]=0xFF -> ???
// Channel values are updated every 30ms which is quite slow, slower than PPM...
// Packets are sent every 1500µs on 2 different channels. 2 times on first channel, 2 times on second channel and restart. The channels are changing between the files 0x08, 0x58 and 0x18, 0x68.
//
// Bind is sending 3 bytes on channel 0x18: 0x1B 0x35 0xD0 every 22.7ms
// packet[0]=0x1B -> bind mode
// packet[1,2] ->ID
// It listens for the model on channel 0x17 and recieves 0x1B 0x35 0xD0 when the plane accepts bind.

View File

@@ -0,0 +1,435 @@
/*
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/>.
*/
/******************************/
/** FrSky D and X routines **/
/******************************/
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO) || defined(FRSKY_RX_CC2500_INO) || defined(FRSKYR9_SX1276_INO)
uint8_t FrSkyFormat=0;
#endif
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO) || defined(FRSKY_RX_CC2500_INO) || defined(FRSKYR9_SX1276_INO)
//**CRC**
const uint16_t PROGMEM FrSkyX_CRC_Short[]={
0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7 };
static uint16_t __attribute__((unused)) FrSkyX_CRCTable(uint8_t val)
{
uint16_t word ;
word = pgm_read_word(&FrSkyX_CRC_Short[val&0x0F]) ;
val /= 16 ;
return word ^ (0x1081 * val) ;
}
uint16_t FrSkyX_crc(uint8_t *data, uint8_t len, uint8_t init=0)
{
uint16_t crc = init;
for(uint8_t i=0; i < len; i++)
crc = (crc<<8) ^ FrSkyX_CRCTable((uint8_t)(crc>>8) ^ *data++);
return crc;
}
#endif
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYR9_SX1276_INO)
static void __attribute__((unused)) FrSkyX_channels(uint8_t offset)
{
static uint8_t chan_start=0;
//packet[7] = FLAGS 00 - standard packet
//10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
//20 - range check packet
#ifdef FAILSAFE_ENABLE
#define FRSKYX_FAILSAFE_TIMEOUT 1032
static uint16_t failsafe_count=0;
static uint8_t FS_flag=0,failsafe_chan=0;
if (FS_flag == 0 && failsafe_count > FRSKYX_FAILSAFE_TIMEOUT && chan_start == 0 && IS_FAILSAFE_VALUES_on)
{
FS_flag = 0x10;
failsafe_chan = 0;
} else if (FS_flag & 0x10 && failsafe_chan < (FrSkyFormat & 0x01 ? 8-1:16-1))
{
FS_flag = 0x10 | ((FS_flag + 2) & 0x0F); //10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
failsafe_chan ++;
} else if (FS_flag & 0x10)
{
FS_flag = 0;
failsafe_count = 0;
FAILSAFE_VALUES_off;
}
failsafe_count++;
packet[7] = FS_flag;
#else
packet[7] = 0;
#endif
//
uint8_t chan_index = chan_start;
uint16_t ch1,ch2;
for(uint8_t i = offset; i < 12+offset ; i+=3)
{//12 bytes of channel data
#ifdef FAILSAFE_ENABLE
if( (FS_flag & 0x10) && ((failsafe_chan & 0x07) == (chan_index & 0x07)) )
ch1 = FrSkyX_scaleForPXX_FS(failsafe_chan);
else
#endif
ch1 = FrSkyX_scaleForPXX(chan_index);
chan_index++;
//
#ifdef FAILSAFE_ENABLE
if( (FS_flag & 0x10) && ((failsafe_chan & 0x07) == (chan_index & 0x07)) )
ch2 = FrSkyX_scaleForPXX_FS(failsafe_chan);
else
#endif
ch2 = FrSkyX_scaleForPXX(chan_index);
chan_index++;
//3 bytes per channel
packet[i] = ch1;
packet[i+1]=(((ch1>>8) & 0x0F)|(ch2 << 4));
packet[i+2]=ch2>>4;
}
if(FrSkyFormat & 0x01) //In X8 mode send only 8ch every 9ms
chan_start = 0 ;
else
chan_start^=0x08;
}
#endif
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO) || defined(FRSKY_RX_CC2500_INO)
enum {
FRSKY_BIND = 0,
FRSKY_BIND_DONE = 1000,
FRSKY_DATA1,
FRSKY_DATA2,
FRSKY_DATA3,
FRSKY_DATA4,
FRSKY_DATA5,
};
void Frsky_init_hop(void)
{
uint8_t val;
uint8_t channel = rx_tx_addr[0]&0x07;
uint8_t channel_spacing = rx_tx_addr[1];
//Filter bad tables
if(channel_spacing<0x02) channel_spacing+=0x02;
if(channel_spacing>0xE9) channel_spacing-=0xE7;
if(channel_spacing%0x2F==0) channel_spacing++;
hopping_frequency[0]=channel;
for(uint8_t i=1;i<50;i++)
{
channel=(channel+channel_spacing) % 0xEB;
val=channel;
if((val==0x00) || (val==0x5A) || (val==0xDC))
val++;
hopping_frequency[i]=i>46?0:val;
}
}
void FrSkyX2_init_hop(void)
{
uint16_t id=(rx_tx_addr[2]<<8) + rx_tx_addr[3];
//Increment
uint8_t inc = (id % 46) + 1;
if( inc == 12 || inc ==35 ) inc++; //Exception list from dumps
//Start offset
uint8_t offset = id % 5;
debug("hop: ");
uint8_t channel;
for(uint8_t i=0; i<47; i++)
{
channel = 5 * (uint16_t(inc * i) % 47) + offset;
//Exception list from dumps
if(FrSkyFormat & 2 )// LBT or FCC
{//LBT
if( channel <=1 || channel == 43 || channel == 44 || channel == 87 || channel == 88 || channel == 129 || channel == 130 || channel == 173 || channel == 174)
channel += 2;
else if( channel == 216 || channel == 217 || channel == 218)
channel += 3;
}
else //FCC
if ( channel == 3 || channel == 4 || channel == 46 || channel == 47 || channel == 90 || channel == 91 || channel == 133 || channel == 134 || channel == 176 || channel == 177 || channel == 220 || channel == 221 )
channel += 2;
//Store
hopping_frequency[i] = channel;
debug(" %02X",channel);
}
debugln("");
hopping_frequency[47] = 0; //Bind freq
}
void Frsky_init_clone(void)
{
debugln("Clone mode");
uint16_t temp = FRSKYD_CLONE_EEPROM_OFFSET;
if(protocol==PROTO_FRSKYX)
temp=FRSKYX_CLONE_EEPROM_OFFSET;
else if(protocol==PROTO_FRSKYX2)
temp=FRSKYX2_CLONE_EEPROM_OFFSET;
FrSkyFormat=eeprom_read_byte((EE_ADDR)temp++);
if(protocol==PROTO_FRSKYX)
FrSkyFormat >>= 1;
else
FrSkyFormat >>= 2;
FrSkyFormat <<= 1; //FCC_16/LBT_16
rx_tx_addr[3] = eeprom_read_byte((EE_ADDR)temp++);
rx_tx_addr[2] = eeprom_read_byte((EE_ADDR)temp++);
rx_tx_addr[1] = eeprom_read_byte((EE_ADDR)temp++);
memset(hopping_frequency,0x00,50);
if(protocol!=PROTO_FRSKYX2)
{//D8 and D16v1
for (uint8_t ch = 0; ch < 47; ch++)
hopping_frequency[ch] = eeprom_read_byte((EE_ADDR)temp++);
}
else
FrSkyX2_init_hop();
}
#endif
/******************************/
/** FrSky V, D and X routines **/
/******************************/
#if defined(FRSKYV_CC2500_INO) || defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO)
const PROGMEM uint8_t FRSKY_common_startreg_cc2500_conf[]= {
CC2500_02_IOCFG0 ,
CC2500_00_IOCFG2 ,
CC2500_17_MCSM1 ,
CC2500_18_MCSM0 ,
CC2500_06_PKTLEN ,
CC2500_07_PKTCTRL1 ,
CC2500_08_PKTCTRL0 ,
CC2500_3E_PATABLE ,
CC2500_0B_FSCTRL1 ,
CC2500_0C_FSCTRL0 , // replaced by option value
CC2500_0D_FREQ2 ,
CC2500_0E_FREQ1 ,
CC2500_0F_FREQ0 ,
CC2500_10_MDMCFG4 ,
CC2500_11_MDMCFG3 ,
CC2500_12_MDMCFG2 ,
CC2500_13_MDMCFG1 ,
CC2500_14_MDMCFG0 ,
CC2500_15_DEVIATN };
#if defined(FRSKYV_CC2500_INO)
const PROGMEM uint8_t FRSKYV_cc2500_conf[]= {
/*02_IOCFG0*/ 0x06 ,
/*00_IOCFG2*/ 0x06 ,
/*17_MCSM1*/ 0x0c ,
/*18_MCSM0*/ 0x18 ,
/*06_PKTLEN*/ 0xff ,
/*07_PKTCTRL1*/ 0x04 ,
/*08_PKTCTRL0*/ 0x05 ,
/*3E_PATABLE*/ 0xfe ,
/*0B_FSCTRL1*/ 0x08 ,
/*0C_FSCTRL0*/ 0x00 ,
/*0D_FREQ2*/ 0x5c ,
/*0E_FREQ1*/ 0x58 ,
/*0F_FREQ0*/ 0x9d ,
/*10_MDMCFG4*/ 0xAA ,
/*11_MDMCFG3*/ 0x10 ,
/*12_MDMCFG2*/ 0x93 ,
/*13_MDMCFG1*/ 0x23 ,
/*14_MDMCFG0*/ 0x7a ,
/*15_DEVIATN*/ 0x41 };
#endif
#if defined(FRSKYD_CC2500_INO)
const PROGMEM uint8_t FRSKYD_cc2500_conf[]= {
/*02_IOCFG0*/ 0x06 ,
/*00_IOCFG2*/ 0x06 ,
/*17_MCSM1*/ 0x0c ,
/*18_MCSM0*/ 0x18 ,
/*06_PKTLEN*/ 0x19 ,
/*07_PKTCTRL1*/ 0x04 ,
/*08_PKTCTRL0*/ 0x05 ,
/*3E_PATABLE*/ 0xff ,
/*0B_FSCTRL1*/ 0x08 ,
/*0C_FSCTRL0*/ 0x00 ,
/*0D_FREQ2*/ 0x5c ,
/*0E_FREQ1*/ 0x76 ,
/*0F_FREQ0*/ 0x27 ,
/*10_MDMCFG4*/ 0xAA ,
/*11_MDMCFG3*/ 0x39 ,
/*12_MDMCFG2*/ 0x11 ,
/*13_MDMCFG1*/ 0x23 ,
/*14_MDMCFG0*/ 0x7a ,
/*15_DEVIATN*/ 0x42 };
#endif
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO)
const PROGMEM uint8_t FRSKYX_cc2500_conf[]= {
//FRSKYX
/*02_IOCFG0*/ 0x06 ,
/*00_IOCFG2*/ 0x06 ,
/*17_MCSM1*/ 0x0c , //X2->0x0E -> Go/Stay in RX mode
/*18_MCSM0*/ 0x18 ,
/*06_PKTLEN*/ 0x1E ,
/*07_PKTCTRL1*/ 0x04 ,
/*08_PKTCTRL0*/ 0x01 , //X2->0x05 -> CRC enabled
/*3E_PATABLE*/ 0xff ,
/*0B_FSCTRL1*/ 0x0A ,
/*0C_FSCTRL0*/ 0x00 ,
/*0D_FREQ2*/ 0x5c ,
/*0E_FREQ1*/ 0x76 ,
/*0F_FREQ0*/ 0x27 ,
/*10_MDMCFG4*/ 0x7B ,
/*11_MDMCFG3*/ 0x61 , //X2->0x84 -> bitrate 70K->77K
/*12_MDMCFG2*/ 0x13 ,
/*13_MDMCFG1*/ 0x23 ,
/*14_MDMCFG0*/ 0x7a ,
/*15_DEVIATN*/ 0x51 };
const PROGMEM uint8_t FRSKYXEU_cc2500_conf[]= {
/*02_IOCFG0*/ 0x06 ,
/*00_IOCFG2*/ 0x06 ,
/*17_MCSM1*/ 0x0E ,
/*18_MCSM0*/ 0x18 ,
/*06_PKTLEN*/ 0x23 ,
/*07_PKTCTRL1*/ 0x04 ,
/*08_PKTCTRL0*/ 0x01 , //X2->0x05 -> CRC enabled
/*3E_PATABLE*/ 0xff ,
/*0B_FSCTRL1*/ 0x08 ,
/*0C_FSCTRL0*/ 0x00 ,
/*0D_FREQ2*/ 0x5c ,
/*0E_FREQ1*/ 0x80 ,
/*0F_FREQ0*/ 0x00 ,
/*10_MDMCFG4*/ 0x7B ,
/*11_MDMCFG3*/ 0xF8 ,
/*12_MDMCFG2*/ 0x03 ,
/*13_MDMCFG1*/ 0x23 ,
/*14_MDMCFG0*/ 0x7a ,
/*15_DEVIATN*/ 0x53 };
const PROGMEM uint8_t FRSKYL_cc2500_conf[]= {
/*02_IOCFG0*/ 0x02 ,
/*00_IOCFG2*/ 0x02 ,
/*17_MCSM1*/ 0x0C ,
/*18_MCSM0*/ 0x18 ,
/*06_PKTLEN*/ 0xFF ,
/*07_PKTCTRL1*/ 0x00 ,
/*08_PKTCTRL0*/ 0x02 ,
/*3E_PATABLE*/ 0xFE ,
/*0B_FSCTRL1*/ 0x0A ,
/*0C_FSCTRL0*/ 0x00 ,
/*0D_FREQ2*/ 0x5c ,
/*0E_FREQ1*/ 0x76 ,
/*0F_FREQ0*/ 0x27 ,
/*10_MDMCFG4*/ 0x5C ,
/*11_MDMCFG3*/ 0x3B ,
/*12_MDMCFG2*/ 0x00 ,
/*13_MDMCFG1*/ 0x03 ,
/*14_MDMCFG0*/ 0x7A ,
/*15_DEVIATN*/ 0x47 };
#endif
const PROGMEM uint8_t FRSKY_common_end_cc2500_conf[][2]= {
{ CC2500_19_FOCCFG, 0x16 },
{ CC2500_1A_BSCFG, 0x6c },
{ CC2500_1B_AGCCTRL2, 0x43 },
{ CC2500_1C_AGCCTRL1, 0x40 },
{ CC2500_1D_AGCCTRL0, 0x91 },
{ CC2500_21_FREND1, 0x56 },
{ CC2500_22_FREND0, 0x10 },
{ CC2500_23_FSCAL3, 0xa9 },
{ CC2500_24_FSCAL2, 0x0A },
{ CC2500_25_FSCAL1, 0x00 },
{ CC2500_26_FSCAL0, 0x11 },
{ CC2500_29_FSTEST, 0x59 },
{ CC2500_2C_TEST2, 0x88 },
{ CC2500_2D_TEST1, 0x31 },
{ CC2500_2E_TEST0, 0x0B },
{ CC2500_03_FIFOTHR, 0x07 },
{ CC2500_09_ADDR, 0x00 } };
void FRSKY_init_cc2500(const uint8_t *ptr)
{
for(uint8_t i=0;i<19;i++)
{
uint8_t reg=pgm_read_byte_near(&FRSKY_common_startreg_cc2500_conf[i]);
uint8_t val=pgm_read_byte_near(&ptr[i]);
if(reg==CC2500_0C_FSCTRL0)
val=option;
CC2500_WriteReg(reg,val);
}
prev_option = option ; // Save option to monitor FSCTRL0 change
for(uint8_t i=0;i<17;i++)
{
uint8_t reg=pgm_read_byte_near(&FRSKY_common_end_cc2500_conf[i][0]);
uint8_t val=pgm_read_byte_near(&FRSKY_common_end_cc2500_conf[i][1]);
CC2500_WriteReg(reg,val);
}
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
CC2500_Strobe(CC2500_SIDLE); // Go to idle...
}
#endif
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO)
uint8_t FrSkyX_chanskip;
uint8_t FrSkyX_TX_Seq, FrSkyX_TX_IN_Seq;
uint8_t FrSkyX_RX_Seq ;
#ifdef SPORT_SEND
struct t_FrSkyX_TX_Frame
{
uint8_t count;
uint8_t payload[8];
} ;
// Store FrskyX telemetry
struct t_FrSkyX_TX_Frame FrSkyX_TX_Frames[4] ;
#endif
static void __attribute__((unused)) FrSkyX_set_start(uint8_t ch )
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_25_FSCAL1, calData[ch]);
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[ch]);
}
static void __attribute__((unused)) FrSkyX_init()
{
if(protocol==PROTO_FRSKYL)
FRSKY_init_cc2500(FRSKYL_cc2500_conf);
else
FRSKY_init_cc2500((FrSkyFormat&2)?FRSKYXEU_cc2500_conf:FRSKYX_cc2500_conf); // LBT or FCC
if(protocol==PROTO_FRSKYX2)
{
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Enable CRC
if(!(FrSkyFormat&2))
{ // FCC
CC2500_WriteReg(CC2500_17_MCSM1, 0x0E); // Go/Stay in RX mode
CC2500_WriteReg(CC2500_11_MDMCFG3, 0x84); // bitrate 70K->77K
}
}
//
for(uint8_t c=0;c < 48;c++)
{//calibrate hop channels
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR,hopping_frequency[c]);
CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);//
calData[c] = CC2500_ReadReg(CC2500_25_FSCAL1);
}
//#######END INIT########
}
static void __attribute__((unused)) FrSkyX_initialize_data(uint8_t adr)
{
CC2500_WriteReg(CC2500_18_MCSM0, 0x8);
CC2500_WriteReg(CC2500_09_ADDR, adr ? 0x03 : rx_tx_addr[3]);
CC2500_WriteReg(CC2500_07_PKTCTRL1,0x05); // check address
}
#endif

View File

@@ -21,6 +21,7 @@ static void __attribute__((unused)) frsky2way_init(uint8_t bind)
{
FRSKY_init_cc2500(FRSKYD_cc2500_conf);
CC2500_WriteReg(CC2500_1B_AGCCTRL2, bind ? 0x43 : 0x03);
CC2500_WriteReg(CC2500_09_ADDR, bind ? 0x03 : rx_tx_addr[3]);
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05);
CC2500_Strobe(CC2500_SIDLE); // Go to idle...
@@ -95,11 +96,21 @@ static void __attribute__((unused)) frsky2way_data_frame()
uint16_t initFrSky_2way()
{
Frsky_init_hop();
//FrskyD init hop
if (sub_protocol==DCLONE)
Frsky_init_clone();
else
for(uint8_t i=0;i<50;i++)
{
uint8_t freq = (i * 0x1e) % 0xeb;
if(i == 3 || i == 23 || i == 47)
freq++;
if(i > 47)
freq=0;
hopping_frequency[i]=freq;
}
packet_count=0;
#if defined TELEMETRY
init_frskyd_link_telemetry();
#endif
if(IS_BIND_IN_PROGRESS)
{
frsky2way_init(1);
@@ -156,15 +167,18 @@ uint16_t ReadFrSky_2way()
{
if (state == FRSKY_DATA1)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(9000);
#endif
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if (len && len<=(0x11+3))// 20bytes
{
CC2500_ReadData(pkt, len); //received telemetry packets
CC2500_ReadData(packet_in, len); //received telemetry packets
#if defined(TELEMETRY)
if(pkt[len-1] & 0x80)
if(packet_in[len-1] & 0x80)
{//with valid crc
packet_count=0;
frsky_check_telemetry(pkt,len); //check if valid telemetry packets and buffer them.
frsky_check_telemetry(packet_in,len); //check if valid telemetry packets and buffer them.
}
#endif
}
@@ -177,7 +191,7 @@ uint16_t ReadFrSky_2way()
packet_count=0;
#if defined TELEMETRY
telemetry_link=0;//no link frames
pkt[6]=0;//no user frames.
packet_in[6]=0;//no user frames.
#endif
}
}

View File

@@ -0,0 +1,262 @@
/*
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(FRSKYL_CC2500_INO)
#include "iface_cc2500.h"
//#define FRSKYL_FORCE_ID
#define FRSKYL_PACKET_LEN 256
#define FRSKYL_PERIOD 18000
uint8_t FrSkyL_buffer[FRSKYL_PACKET_LEN];
static void __attribute__((unused)) FrSkyL_build_bind_packet()
{
//Header
packet[0] = 0x4E; // Unknown but constant
//Bind packet
memset(&packet[1],0x00,3);
//ID
packet[4 ] = rx_tx_addr[3]; // ID
packet[5 ] = rx_tx_addr[2]; // ID
int idx = ((state -FRSKY_BIND) % 10) * 5;
packet[6 ] = idx;
packet[7 ] = hopping_frequency[idx++];
packet[8 ] = hopping_frequency[idx++];
packet[9 ] = hopping_frequency[idx++];
packet[10] = hopping_frequency[idx++];
packet[11] = hopping_frequency[idx++];
packet[12] = rx_tx_addr[1]; // ID or hw ver?
packet[13] = RX_num;
packet[14] = 0x00; // Unknown but constant
//CRC
uint16_t lcrc = FrSkyX_crc(&packet[1], 14);
packet[15] = lcrc >> 8;
packet[16] = lcrc;
//Debug
/* debug("Bind:");
for(uint8_t i=0;i<17;i++)
debug(" %02X",packet[i]);
debugln("");*/
}
static void __attribute__((unused)) FrSkyL_build_packet()
{
static uint8_t chan_offset=0;
uint16_t chan_0,chan_1;
//Header
packet[0 ] = 0x4E; // Unknown but constant
//ID
packet[1 ] = rx_tx_addr[3]; // ID
packet[2 ] = rx_tx_addr[2]; // ID
packet[3 ] = rx_tx_addr[1]; // ID or hw ver?
//skip_hop
packet[4 ] = (FrSkyX_chanskip<<6)|hopping_frequency_no;
packet[5 ] = FrSkyX_chanskip>>2;
//Channels
uint8_t startChan = chan_offset;
for(uint8_t i = 0; i <9 ; i+=3)
{//9 bytes of channel data
chan_0 = FrSkyX_scaleForPXX(startChan,6);
startChan++;
//
chan_1 = FrSkyX_scaleForPXX(startChan,6);
startChan++;
//
packet[6+i] = lowByte(chan_0); //3 bytes*4
packet[6+i+1]=(((chan_0>>8) & 0x0F)|(chan_1 << 4));
packet[6+i+2]=chan_1>>4;
}
if(sub_protocol & 0x01 ) //6ch mode only??
chan_offset = 0 ;
else
chan_offset^=0x06;
//CRC
uint16_t lcrc = FrSkyX_crc(&packet[1], 14, RX_num);
packet[15] = lcrc >> 8;
packet[16] = lcrc;
//Debug
/*debug("Norm:");
for(uint8_t i=0;i<17;i++)
debug(" %02X",packet[i]);
debugln("");*/
}
static void __attribute__((unused)) FrSkyL_encode_packet(bool type)
{
#define FRSKYL_BIT0 0xED
#define FRSKYL_BIT1 0x712
uint32_t bits = 0;
uint8_t bitsavailable = 0;
uint8_t idx = 0,len=6;
if(type)
{//just replace packet content
idx=66;
len=17;
}
//debugln("Encode:");
for (uint8_t i = 0; i < len; i++)
{
uint8_t tmp=packet[i];
//debug("%02X =",tmp);
for(uint8_t j=0;j<8;j++)
{
bits <<= 11;
if(tmp&0x01)
bits |= FRSKYL_BIT1;
else
bits |= FRSKYL_BIT0;
tmp >>=1;
bitsavailable += 11;
while (bitsavailable >= 8) {
uint32_t bits_tmp=bits>>(bitsavailable-8);
bitsavailable -= 8;
FrSkyL_buffer[idx] = bits_tmp;
//debug(" %02X",FrSkyL_buffer[idx]);
idx++;
}
}
//debugln("");
}
}
uint16_t ReadFrSkyL()
{
static uint8_t written=0, send=0;
switch(send)
{
case 1:
CC2500_Strobe(CC2500_SIDLE);
CC2500_Strobe(CC2500_SFTX);
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, FrSkyL_buffer, 64);
CC2500_Strobe(CC2500_STX);
CC2500_Strobe(CC2500_SIDLE); // This cancels the current transmission???
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, FrSkyL_buffer, 64);
CC2500_Strobe(CC2500_SFTX); // This just clears what we've written???
CC2500_Strobe(CC2500_STX);
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, FrSkyL_buffer, 64);
written=64;
send++;
return 2623;
case 2:
len=FRSKYL_PACKET_LEN-written;
if(len>31)
len=31;
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, FrSkyL_buffer+written, len);
written+=len;
if(len!=31) //everything has been sent
{
send=0;
return 2936;
}
return 1984;
}
switch(state)
{
default:
//Bind
#ifdef MULTI_SYNC
telemetry_set_input_sync(9000);
#endif
FrSkyX_set_start(47);
CC2500_SetPower();
CC2500_Strobe(CC2500_SFRX);
//
FrSkyL_build_bind_packet();
FrSkyL_encode_packet(true);
CC2500_Strobe(CC2500_SIDLE);
if(IS_BIND_DONE)
state = FRSKY_BIND_DONE;
else
{
state++;
send=1;
}
return 537;
case FRSKY_BIND_DONE:
FrSkyX_initialize_data(0);
hopping_frequency_no=0;
BIND_DONE;
state++; //FRSKY_DATA1
break;
case FRSKY_DATA1:
if ( prev_option != option )
{
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); //Frequency offset hack
prev_option = option ;
}
FrSkyX_set_start(hopping_frequency_no);
FrSkyL_build_packet();
FrSkyL_encode_packet(true);
CC2500_SetPower();
hopping_frequency_no = (hopping_frequency_no+FrSkyX_chanskip)%47;
send=1;
return 537;
}
return 1;
}
uint16_t initFrSkyL()
{
set_rx_tx_addr(MProtocol_id_master);
rx_tx_addr[1]=0x02; // ID related, hw version?
#ifdef FRSKYL_FORCE_ID
rx_tx_addr[3]=0x0E;
rx_tx_addr[2]=0x1C;
rx_tx_addr[1]=0x02;
#endif
FrSkyX2_init_hop();
while(!FrSkyX_chanskip)
FrSkyX_chanskip=random(0xfefefefe)%47;
FrSkyX_init();
//Prepare frame
memset(FrSkyL_buffer,0x00,FRSKYL_PACKET_LEN-3);
memset(&FrSkyL_buffer[FRSKYL_PACKET_LEN-3],0x55,3);
memset(packet,0xAA,6);
FrSkyL_encode_packet(false);
/*debugln("Frame:");
for(uint16_t i=0;i<FRSKYL_PACKET_LEN;i++)
{
debug(" %02X",FrSkyL_buffer[i]);
if(i%11==10)
debugln("");
}
debugln("");*/
if(IS_BIND_IN_PROGRESS)
{
state = FRSKY_BIND;
FrSkyX_initialize_data(1);
}
else
{
state = FRSKY_DATA1;
FrSkyX_initialize_data(0);
}
return 10000;
}
#endif

View File

@@ -0,0 +1,208 @@
#if defined(FRSKYR9_SX1276_INO)
#include "iface_sx1276.h"
#define FREQ_MAP_SIZE 29
// TODO the channel spacing is equal, consider calculating the new channel instead of using lookup tables (first_chan + index * step)
static uint32_t FrSkyR9_freq_map_915[FREQ_MAP_SIZE] =
{
914472960,
914972672,
915472384,
915972096,
916471808,
916971520,
917471232,
917970944,
918470656,
918970368,
919470080,
919969792,
920469504,
920969216,
921468928,
921968640,
922468352,
922968064,
923467776,
923967488,
924467200,
924966912,
925466624,
925966336,
926466048,
926965760,
927465472,
// last two determined by FrSkyR9_step
0,
0
};
static uint32_t FrSkyR9_freq_map_868[FREQ_MAP_SIZE] =
{
859504640,
860004352,
860504064,
861003776,
861503488,
862003200,
862502912,
863002624,
863502336,
864002048,
864501760,
865001472,
865501184,
866000896,
866500608,
867000320,
867500032,
867999744,
868499456,
868999168,
869498880,
869998592,
870498304,
870998016,
871497728,
871997440,
872497152,
// last two determined by FrSkyR9_step
0,
0
};
static uint8_t FrSkyR9_step = 1;
static uint32_t* FrSkyR9_freq_map = FrSkyR9_freq_map_915;
uint16_t initFrSkyR9()
{
set_rx_tx_addr(MProtocol_id_master);
if(sub_protocol & 0x01)
FrSkyR9_freq_map = FrSkyR9_freq_map_868;
else
FrSkyR9_freq_map = FrSkyR9_freq_map_915;
FrSkyR9_step = 1 + (random(0xfefefefe) % 24);
FrSkyR9_freq_map[27] = FrSkyR9_freq_map[FrSkyR9_step];
FrSkyR9_freq_map[28] = FrSkyR9_freq_map[FrSkyR9_step+1];
SX1276_SetMode(true, false, SX1276_OPMODE_SLEEP);
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
// uint8_t buffer[2];
// buffer[0] = 0x00;
// buffer[1] = 0x00;
// SX1276_WriteRegisterMulti(SX1276_40_DIOMAPPING1, buffer, 2);
SX1276_SetDetectOptimize(true, SX1276_DETECT_OPTIMIZE_SF6);
SX1276_ConfigModem1(SX1276_MODEM_CONFIG1_BW_500KHZ, SX1276_MODEM_CONFIG1_CODING_RATE_4_5, true);
SX1276_ConfigModem2(6, false, false);
SX1276_ConfigModem3(false, false);
SX1276_SetPreambleLength(9);
SX1276_SetDetectionThreshold(SX1276_MODEM_DETECTION_THRESHOLD_SF6);
SX1276_SetLna(1, true);
SX1276_SetHopPeriod(0); // 0 = disabled, we hope frequencies manually
SX1276_SetPaDac(true);
hopping_frequency_no = 0;
// TODO this can probably be shorter
return 20000; // start calling FrSkyR9_callback in 20 milliseconds
}
uint16_t FrSkyR9_callback()
{
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
//SX1276_WriteReg(SX1276_11_IRQFLAGSMASK, 0xbf); // use only RxDone interrupt
// uint8_t buffer[2];
// buffer[0] = 0x00;
// buffer[1] = 0x00;
// SX1276_WriteRegisterMulti(SX1276_40_DIOMAPPING1, buffer, 2); // RxDone interrupt mapped to DIO0 (the rest are not used because of the REG_IRQ_FLAGS_MASK)
// SX1276_WriteReg(REG_PAYLOAD_LENGTH, 13);
// SX1276_WriteReg(REG_FIFO_ADDR_PTR, 0x00);
// SX1276_WriteReg(SX1276_01_OPMODE, 0x85); // RXCONTINUOUS
// delay(10); // 10 ms
// SX1276_WriteReg(SX1276_01_OPMODE, 0x81); // STDBY
//SX1276_WriteReg(SX1276_09_PACONFIG, 0xF0);
// max power: 15dBm (10.8 + 0.6 * MaxPower [dBm])
// output_power: 2 dBm (17-(15-OutputPower) (if pa_boost_pin == true))
SX1276_SetPaConfig(true, 7, 0);
SX1276_SetFrequency(FrSkyR9_freq_map[hopping_frequency_no]); // set current center frequency
delayMicroseconds(500);
packet[0] = 0x3C; // ????
packet[1] = rx_tx_addr[3]; // unique radio id
packet[2] = rx_tx_addr[2]; // unique radio id
packet[3] = hopping_frequency_no; // current channel index
packet[4] = FrSkyR9_step; // step size and last 2 channels start index
packet[5] = RX_num; // receiver number from OpenTX
// binding mode: 0x00 regular / 0x41 bind?
if(IS_BIND_IN_PROGRESS)
packet[6] = 0x41;
else
packet[6] = 0x00;
// TODO
packet[7] = 0x00; // fail safe related (looks like the same sequence of numbers as FrskyX protocol)
// two channel are spread over 3 bytes.
// each channel is 11 bit + 1 bit (msb) that states whether
// it's part of the upper channels (9-16) or lower (1-8) (0 - lower 1 - upper)
#define CH_POS 8
static uint8_t chan_start=0;
uint8_t chan_index = chan_start;
for(int i = 0; i < 12; i += 3)
{
// map channel values (0-2047) to (64-1984)
uint16_t ch1 = FrSkyX_scaleForPXX(chan_index);
uint16_t ch2 = FrSkyX_scaleForPXX(chan_index + 1);
packet[CH_POS + i] = ch1;
packet[CH_POS + i + 1] = (ch1 >> 8) | (ch2 << 4);
packet[CH_POS + i + 2] = (ch2 >> 4);
chan_index += 2;
}
if((sub_protocol & 0x02) == 0)
chan_start ^= 0x08; // Alternate between lower and upper when 16 channels is used
packet[20] = 0x08; // ????
packet[21] = 0x00; // ????
packet[22] = 0x00; // ????
packet[23] = 0x00; // ????
uint16_t crc = FrSkyX_crc(packet, 24);
packet[24] = crc; // low byte
packet[25] = crc >> 8; // high byte
SX1276_WritePayloadToFifo(packet, 26);
hopping_frequency_no = (hopping_frequency_no + FrSkyR9_step) % FREQ_MAP_SIZE;
SX1276_SetMode(true, false, SX1276_OPMODE_TX);
// need to clear RegIrqFlags?
return 19400;
}
#endif

View File

@@ -117,6 +117,9 @@ uint16_t ReadFRSKYV()
{
if(IS_BIND_DONE)
{ // Normal operation
#ifdef MULTI_SYNC
telemetry_set_input_sync(9006);
#endif
uint8_t chan = FRSKYV_calc_channel();
CC2500_Strobe(CC2500_SIDLE);
if (option != prev_option)

View File

@@ -1,234 +1,197 @@
/* **************************
* By Midelic on RCGroups *
**************************
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 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(FRSKYX_CC2500_INO)
#include "iface_cc2500.h"
uint8_t FrX_chanskip;
uint8_t FrX_send_seq ;
uint8_t FrX_receive_seq ;
#define FRX_FAILSAFE_TIMEOUT 1032
static void __attribute__((unused)) frskyX_set_start(uint8_t ch )
static void __attribute__((unused)) FrSkyX_build_bind_packet()
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_25_FSCAL1, calData[ch]);
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[ch]);
}
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
static void __attribute__((unused)) frskyX_init()
{
FRSKY_init_cc2500((sub_protocol&2)?FRSKYXEU_cc2500_conf:FRSKYX_cc2500_conf); // LBT or FCC
//
for(uint8_t c=0;c < 48;c++)
{//calibrate hop channels
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR,hopping_frequency[c]);
CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);//
calData[c] = CC2500_ReadReg(CC2500_25_FSCAL1);
//ID
packet[3] = rx_tx_addr[3]; // ID
packet[4] = rx_tx_addr[2]; // ID
if(protocol==PROTO_FRSKYX)
{
int idx = ((state -FRSKY_BIND) % 10) * 5;
packet[5] = idx;
packet[6] = hopping_frequency[idx++];
packet[7] = hopping_frequency[idx++];
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[12] = RX_num;
//
memset(&packet[13], 0, packet_size - 14);
if(binding_idx&0x01)
memcpy(&packet[13],(void *)"\x55\xAA\x5A\xA5",4); // Telem off
if(binding_idx&0x02)
memcpy(&packet[17],(void *)"\x55\xAA\x5A\xA5",4); // CH9-16
}
//#######END INIT########
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?
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
//Xor
for(uint8_t i=3; i<packet_size-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;
/*//Debug
debug("Bind:");
for(uint8_t i=0;i<=packet_size;i++)
debug(" %02X",packet[i]);
debugln("");*/
}
static void __attribute__((unused)) frskyX_initialize_data(uint8_t adr)
{
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack
CC2500_WriteReg(CC2500_18_MCSM0, 0x8);
CC2500_WriteReg(CC2500_09_ADDR, adr ? 0x03 : rx_tx_addr[3]);
CC2500_WriteReg(CC2500_07_PKTCTRL1,0x05);
}
//**CRC**
const uint16_t PROGMEM frskyX_CRC_Short[]={
0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7 };
static uint16_t __attribute__((unused)) frskyX_CRCTable(uint8_t val)
{
uint16_t word ;
word = pgm_read_word(&frskyX_CRC_Short[val&0x0F]) ;
val /= 16 ;
return word ^ (0x1081 * val) ;
}
static uint16_t __attribute__((unused)) frskyX_crc_x(uint8_t *data, uint8_t len)
{
uint16_t crc = 0;
for(uint8_t i=0; i < len; i++)
crc = (crc<<8) ^ frskyX_CRCTable((uint8_t)(crc>>8) ^ *data++);
return crc;
}
static void __attribute__((unused)) frskyX_build_bind_packet()
{
packet[0] = (sub_protocol & 2 ) ? 0x20 : 0x1D ; // LBT or FCC
packet[1] = 0x03;
packet[2] = 0x01;
//
packet[3] = rx_tx_addr[3];
packet[4] = rx_tx_addr[2];
int idx = ((state -FRSKY_BIND) % 10) * 5;
packet[5] = idx;
packet[6] = hopping_frequency[idx++];
packet[7] = hopping_frequency[idx++];
packet[8] = hopping_frequency[idx++];
packet[9] = hopping_frequency[idx++];
packet[10] = hopping_frequency[idx++];
packet[11] = 0x02;
packet[12] = RX_num;
//
uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ;
memset(&packet[13], 0, limit - 13);
uint16_t lcrc = frskyX_crc_x(&packet[3], limit-3);
//
packet[limit++] = lcrc >> 8;
packet[limit] = lcrc;
//
}
// 0-2047, 0 = 817, 1024 = 1500, 2047 = 2182
//64=860,1024=1500,1984=2140//Taranis 125%
static uint16_t __attribute__((unused)) frskyX_scaleForPXX( uint8_t i )
{ //mapped 860,2140(125%) range to 64,1984(PXX values);
uint16_t chan_val=convert_channel_frsky(i)-1226;
if(i>7) chan_val|=2048; // upper channels offset
return chan_val;
}
#ifdef FAILSAFE_ENABLE
static uint16_t __attribute__((unused)) frskyX_scaleForPXX_FS( uint8_t i )
{ //mapped 1,2046(125%) range to 64,1984(PXX values);
uint16_t chan_val=((Failsafe_data[i]*15)>>4)+64;
if(Failsafe_data[i]==FAILSAFE_CHANNEL_NOPULSES)
chan_val=FAILSAFE_CHANNEL_NOPULSES;
else if(Failsafe_data[i]==FAILSAFE_CHANNEL_HOLD)
chan_val=FAILSAFE_CHANNEL_HOLD;
if(i>7) chan_val|=2048; // upper channels offset
return chan_val;
}
#endif
#define FRX_FAILSAFE_TIME 1032
static void __attribute__((unused)) frskyX_data_frame()
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
//
static uint8_t chan_offset=0;
uint16_t chan_0 ;
uint16_t chan_1 ;
//
// data frames sent every 9ms; failsafe every 9 seconds
#ifdef FAILSAFE_ENABLE
static uint16_t failsafe_count=0;
static uint8_t FS_flag=0,failsafe_chan=0;
if (FS_flag == 0 && failsafe_count > FRX_FAILSAFE_TIME && chan_offset == 0 && IS_FAILSAFE_VALUES_on)
{
FS_flag = 0x10;
failsafe_chan = 0;
} else if (FS_flag & 0x10 && failsafe_chan < (sub_protocol & 0x01 ? 8-1:16-1))
{
FS_flag = 0x10 | ((FS_flag + 2) & 0x0F); //10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
failsafe_chan ++;
} else if (FS_flag & 0x10)
{
FS_flag = 0;
failsafe_count = 0;
}
failsafe_count++;
#endif
packet[0] = (sub_protocol & 0x02 ) ? 0x20 : 0x1D ; // LBT or FCC
packet[1] = rx_tx_addr[3];
packet[2] = rx_tx_addr[2];
packet[3] = 0x02;
//
packet[4] = (FrX_chanskip<<6)|hopping_frequency_no;
packet[5] = FrX_chanskip>>2;
packet[6] = RX_num;
//packet[7] = FLAGS 00 - standard packet
//10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
//20 - range check packet
#ifdef FAILSAFE_ENABLE
packet[7] = FS_flag;
#else
packet[7] = 0;
#endif
packet[8] = 0;
//
uint8_t startChan = chan_offset; for(uint8_t i = 0; i <12 ; i+=3)
{//12 bytes of channel data
#ifdef FAILSAFE_ENABLE
if( (FS_flag & 0x10) && ((failsafe_chan & 0x07) == (startChan & 0x07)) )
chan_0 = frskyX_scaleForPXX_FS(failsafe_chan);
else
#endif
chan_0 = frskyX_scaleForPXX(startChan);
startChan++;
//
#ifdef FAILSAFE_ENABLE
if( (FS_flag & 0x10) && ((failsafe_chan & 0x07) == (startChan & 0x07)) )
chan_1 = frskyX_scaleForPXX_FS(failsafe_chan);
else
#endif
chan_1 = frskyX_scaleForPXX(startChan);
startChan++;
//
packet[9+i] = lowByte(chan_0); //3 bytes*4
packet[9+i+1]=(((chan_0>>8) & 0x0F)|(chan_1 << 4));
packet[9+i+2]=chan_1>>4;
}
packet[21] = (FrX_receive_seq << 4) | FrX_send_seq ;//8 at start
if(sub_protocol & 0x01 ) // in X8 mode send only 8ch every 9ms
chan_offset = 0 ;
else
chan_offset^=0x08;
uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ;
for (uint8_t i=22;i<limit;i++)
packet[i]=0;
#if defined SPORT_POLLING
uint8_t idxs=0;
if(ok_to_send)
for (uint8_t i=23;i<limit;i++)
{//
if(sport_index==sport_idx)
{//no new data
ok_to_send=false;
break;
}
packet[i]=SportData[sport_index];
sport_index= (sport_index+1)& (MAX_SPORT_BUFFER-1);
idxs++;
}
packet[22]= idxs;
#ifdef DEBUG_SERIAL
for(uint8_t i=0;i<idxs;i++)
{
Serial.print(packet[23+i],HEX);
Serial.print(" ");
}
Serial.println(" ");
#endif
#endif // SPORT_POLLING
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] = rx_tx_addr[3]; // ID
packet[2] = rx_tx_addr[2]; // ID
packet[3] = rx_tx_addr[1]; // Unknown but constant ID?
//
packet[4] = (FrSkyX_chanskip<<6)|hopping_frequency_no;
packet[5] = FrSkyX_chanskip>>2;
packet[6] = RX_num;
uint16_t lcrc = frskyX_crc_x(&packet[3], limit-3);
packet[limit++]=lcrc>>8;//high byte
packet[limit]=lcrc;//low byte
packet[8] = 0; //??
FrSkyX_channels(9); // Set packet[7] and packet[9..20] with channels data and failsafe
//sequence and send SPort
for (uint8_t i=22;i<packet_size-1;i++)
packet[i]=0;
packet[21] = FrSkyX_RX_Seq << 4; //TX=8 at startup
#ifdef SPORT_SEND
if (FrSkyX_TX_IN_Seq!=0xFF)
{//RX has replied at least once
if (FrSkyX_TX_IN_Seq & 0x08)
{//Request init
//debugln("Init");
FrSkyX_TX_Seq = 0 ;
for(uint8_t i=0;i<4;i++)
FrSkyX_TX_Frames[i].count=0; //Discard frames in current output buffer
}
else if (FrSkyX_TX_IN_Seq & 0x04)
{//Retransmit the requested packet
debugln("Retry:%d",FrSkyX_TX_IN_Seq&0x03);
packet[21] |= FrSkyX_TX_IN_Seq&0x03;
packet[22] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq&0x03].count;
for (uint8_t i=23;i<23+FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq&0x03].count;i++)
packet[i] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq&0x03].payload[i];
}
else if ( FrSkyX_TX_Seq != 0x08 )
{
if(FrSkyX_TX_Seq==FrSkyX_TX_IN_Seq)
{//Send packet from the incoming radio buffer
//debugln("Send:%d",FrSkyX_TX_Seq);
packet[21] |= FrSkyX_TX_Seq;
uint8_t nbr_bytes=0;
for (uint8_t i=23;i<packet_size-1;i++)
{
if(SportHead==SportTail)
break; //buffer empty
packet[i]=SportData[SportHead];
FrSkyX_TX_Frames[FrSkyX_TX_Seq].payload[i-23]=SportData[SportHead];
SportHead=(SportHead+1) & (MAX_SPORT_BUFFER-1);
nbr_bytes++;
}
packet[22]=nbr_bytes;
FrSkyX_TX_Frames[FrSkyX_TX_Seq].count=nbr_bytes;
if(nbr_bytes)
{//Check the buffer status
uint8_t used = SportTail;
if ( SportHead > SportTail )
used += MAX_SPORT_BUFFER - SportHead ;
else
used -= SportHead ;
if ( used < (MAX_SPORT_BUFFER>>1) )
{
DATA_BUFFER_LOW_off;
debugln("Ok buf:%d",used);
}
}
FrSkyX_TX_Seq = ( FrSkyX_TX_Seq + 1 ) & 0x03 ; //Next iteration send next packet
}
else
{//Not in sequence somehow, transmit what the receiver wants but why not asking for retransmit...
//debugln("RX_Seq:%d,TX:%d",FrSkyX_TX_IN_Seq,FrSkyX_TX_Seq);
packet[21] |= FrSkyX_TX_IN_Seq;
packet[22] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].count;
for (uint8_t i=23;i<23+FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].count;i++)
packet[i] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].payload[i-23];
}
}
else
packet[21] |= 0x08 ; //FrSkyX_TX_Seq=8 at startup
}
if(packet[22])
{//Debug
debug("SP: ");
for(uint8_t i=0;i<packet[22];i++)
debug("%02X ",packet[23+i]);
debugln("");
}
#else
packet[21] |= FrSkyX_TX_Seq ;//TX=8 at startup
if ( !(FrSkyX_TX_IN_Seq & 0xF8) )
FrSkyX_TX_Seq = ( FrSkyX_TX_Seq + 1 ) & 0x03 ; // Next iteration send next packet
#endif // SPORT_SEND
//CRC
uint16_t lcrc = FrSkyX_crc(&packet[3], packet_size-4);
packet[packet_size-1] = lcrc >> 8;
packet[packet_size] = lcrc;
/*//Debug
debug("Norm:");
for(uint8_t i=0;i<=packet_size;i++)
debug(" %02X",packet[i]);
debugln("");*/
}
uint16_t ReadFrSkyX()
@@ -236,11 +199,11 @@ uint16_t ReadFrSkyX()
switch(state)
{
default:
frskyX_set_start(47);
FrSkyX_set_start(47);
CC2500_SetPower();
CC2500_Strobe(CC2500_SFRX);
//
frskyX_build_bind_packet();
FrSkyX_build_bind_packet();
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteData(packet, packet[0]+1);
if(IS_BIND_DONE)
@@ -249,73 +212,112 @@ uint16_t ReadFrSkyX()
state++;
return 9000;
case FRSKY_BIND_DONE:
frskyX_initialize_data(0);
FrSkyX_initialize_data(0);
hopping_frequency_no=0;
BIND_DONE;
state++;
break;
state++; //FRSKY_DATA1
break;
case FRSKY_DATA1:
CC2500_Strobe(CC2500_SIDLE);
if ( prev_option != option )
{
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); //Frequency offset hack
prev_option = option ;
}
CC2500_SetTxRxMode(TX_EN);
frskyX_set_start(hopping_frequency_no);
CC2500_SetPower();
CC2500_Strobe(CC2500_SFRX);
hopping_frequency_no = (hopping_frequency_no+FrX_chanskip)%47;
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteData(packet, packet[0]+1);
//
// frskyX_data_frame();
state++;
return 5200;
FrSkyX_set_start(hopping_frequency_no);
FrSkyX_build_packet();
if(FrSkyFormat & 2)
{// LBT
CC2500_Strobe(CC2500_SRX); //Acquire RSSI
state++;
return 400; // LBT v2.1
}
case FRSKY_DATA2:
CC2500_SetTxRxMode(RX_EN);
if(FrSkyFormat & 2)
{
uint16_t rssi=0;
for(uint8_t i=0;i<4;i++)
rssi += CC2500_ReadReg(CC2500_34_RSSI | CC2500_READ_BURST); // 0.5 db/count, RSSI value read from the RSSI status register is a 2's complement number
rssi>>=2;
#if 0
uint8_t rssi_level=convert_channel_8b(CH16)>>1; //CH16 0..127
if ( rssi > rssi_level && rssi < 128) //test rssi level dynamically
#else
if ( rssi > 14 && rssi < 128) // if RSSI above -65dBm (12=-70) => ETSI requirement
#endif
{
LBT_POWER_on; // Reduce to low power before transmitting
debugln("Busy %d %d",hopping_frequency_no,rssi);
}
}
CC2500_Strobe(CC2500_SIDLE);
state++;
return 200;
case FRSKY_DATA3:
CC2500_Strobe(CC2500_SFTX);
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
hopping_frequency_no = (hopping_frequency_no+FrSkyX_chanskip)%47;
CC2500_WriteData(packet, packet[0]+1);
state=FRSKY_DATA3;
if(FrSkyFormat & 2)
return 4000; // LBT v2.1
else
return 5200; // FCC v2.1
case FRSKY_DATA3:
CC2500_Strobe(CC2500_SIDLE);
CC2500_SetTxRxMode(RX_EN);
CC2500_Strobe(CC2500_SRX);
state++;
return 3100;
case FRSKY_DATA4:
if(FrSkyFormat & 2)
return 4100; // LBT v2.1
else
return 3300; // FCC v2.1
case FRSKY_DATA4:
#ifdef MULTI_SYNC
telemetry_set_input_sync(9000);
#endif
#if defined TELEMETRY
telemetry_link=1; //Send telemetry out anyway
#endif
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if (len && (len<=(0x0E + 3))) //Telemetry frame is 17
if (len && (len<=(0x0E + 3))) //Telemetry frame is 17
{
//debug("Telem:");
packet_count=0;
CC2500_ReadData(pkt, len);
CC2500_ReadData(packet_in, len);
#if defined TELEMETRY
frsky_check_telemetry(pkt,len); //check if valid telemetry packets
//parse telemetry packets here
//The same telemetry function used by FrSky(D8).
if(protocol==PROTO_FRSKYX || (protocol==PROTO_FRSKYX2 && (packet_in[len-1] & 0x80)) )
{//with valid crc for FRSKYX2
//Debug
//for(uint8_t i=0;i<len;i++)
// debug(" %02X",packet_in[i]);
frsky_check_telemetry(packet_in,len); //Check and parse telemetry packets
}
#endif
}
//debugln("");
}
else
{
packet_count++;
//debugln("M %d",packet_count);
// restart sequence on missed packet - might need count or timeout instead of one missed
if(packet_count>100)
{//~1sec
// seq_last_sent = 0;
// seq_last_rcvd = 8;
FrX_send_seq = 0x08 ;
// FrX_receive_seq = 0 ;
FrSkyX_TX_Seq = 0x08 ; //Request init
FrSkyX_TX_IN_Seq = 0xFF ; //No sequence received yet
#ifdef SPORT_SEND
for(uint8_t i=0;i<4;i++)
FrSkyX_TX_Frames[i].count=0; //Discard frames in current output buffer
#endif
packet_count=0;
#if defined TELEMETRY
telemetry_lost=1;
telemetry_link=0; //Stop sending telemetry
#endif
}
CC2500_Strobe(CC2500_SFRX); //flush the RXFIFO
}
frskyX_data_frame();
if ( FrX_send_seq != 0x08 )
{
FrX_send_seq = ( FrX_send_seq + 1 ) & 0x03 ;
CC2500_Strobe(CC2500_SFRX); //Flush the RXFIFO
}
state = FRSKY_DATA1;
return 500;
return 500; // FCC & LBT v2.1
}
return 1;
}
@@ -323,36 +325,51 @@ uint16_t ReadFrSkyX()
uint16_t initFrSkyX()
{
set_rx_tx_addr(MProtocol_id_master);
Frsky_init_hop();
FrSkyFormat = sub_protocol;
if (sub_protocol==XCLONE)
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
rx_tx_addr[1]=0x02; // ID related, hw version?
FrSkyX2_init_hop();
}
packet_count=0;
while(!FrX_chanskip)
FrX_chanskip=random(0xfefefefe)%47;
while(!FrSkyX_chanskip)
FrSkyX_chanskip=random(0xfefefefe)%47;
FrSkyX_init();
//for test***************
//rx_tx_addr[3]=0xB3;
//rx_tx_addr[2]=0xFD;
//************************
frskyX_init();
#if defined SPORT_POLLING
#ifdef INVERT_SERIAL
start_timer4() ;
#endif
#endif
//
if(IS_BIND_IN_PROGRESS)
{
state = FRSKY_BIND;
frskyX_initialize_data(1);
FrSkyX_initialize_data(1);
}
else
{
state = FRSKY_DATA1;
frskyX_initialize_data(0);
FrSkyX_initialize_data(0);
}
// seq_last_sent = 0;
// seq_last_rcvd = 8;
FrX_send_seq = 0x08 ;
FrX_receive_seq = 0 ;
FrSkyX_TX_Seq = 0x08 ; // Request init
FrSkyX_TX_IN_Seq = 0xFF ; // No sequence received yet
#ifdef SPORT_SEND
for(uint8_t i=0;i<4;i++)
FrSkyX_TX_Frames[i].count=0; // discard frames in current output buffer
SportHead=SportTail=0; // empty data buffer
#endif
FrSkyX_RX_Seq = 0 ; // Seq 0 to start with
binding_idx=0; // CH1-8 and Telem on
return 10000;
}
#endif
#endif

View File

@@ -0,0 +1,593 @@
/*
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(FRSKY_RX_CC2500_INO)
#include "iface_cc2500.h"
#define FRSKY_RX_D16FCC_LENGTH 0x1D+1
#define FRSKY_RX_D16LBT_LENGTH 0x20+1
#define FRSKY_RX_D16v2_LENGTH 0x1D+1
#define FRSKY_RX_D8_LENGTH 0x11+1
#define FRSKY_RX_FORMATS 5
enum
{
FRSKY_RX_D8 =0,
FRSKY_RX_D16FCC =1,
FRSKY_RX_D16LBT =2,
FRSKY_RX_D16v2FCC =3,
FRSKY_RX_D16v2LBT =4,
};
enum {
FRSKY_RX_TUNE_START,
FRSKY_RX_TUNE_LOW,
FRSKY_RX_TUNE_HIGH,
FRSKY_RX_BIND,
FRSKY_RX_DATA,
};
const PROGMEM uint8_t frsky_rx_common_reg[][2] = {
{CC2500_02_IOCFG0, 0x01},
{CC2500_18_MCSM0, 0x18},
{CC2500_07_PKTCTRL1, 0x05},
{CC2500_3E_PATABLE, 0xFF},
{CC2500_0C_FSCTRL0, 0},
{CC2500_0D_FREQ2, 0x5C},
{CC2500_13_MDMCFG1, 0x23},
{CC2500_14_MDMCFG0, 0x7A},
{CC2500_19_FOCCFG, 0x16},
{CC2500_1A_BSCFG, 0x6C},
{CC2500_1B_AGCCTRL2, 0x03},
{CC2500_1C_AGCCTRL1, 0x40},
{CC2500_1D_AGCCTRL0, 0x91},
{CC2500_21_FREND1, 0x56},
{CC2500_22_FREND0, 0x10},
{CC2500_23_FSCAL3, 0xA9},
{CC2500_24_FSCAL2, 0x0A},
{CC2500_25_FSCAL1, 0x00},
{CC2500_26_FSCAL0, 0x11},
{CC2500_29_FSTEST, 0x59},
{CC2500_2C_TEST2, 0x88},
{CC2500_2D_TEST1, 0x31},
{CC2500_2E_TEST0, 0x0B},
{CC2500_03_FIFOTHR, 0x07},
{CC2500_09_ADDR, 0x03},
};
const PROGMEM uint8_t frsky_rx_d16fcc_reg[][2] = {
{CC2500_17_MCSM1, 0x0C},
{CC2500_0E_FREQ1, 0x76},
{CC2500_0F_FREQ0, 0x27},
{CC2500_06_PKTLEN, 0x1E},
{CC2500_08_PKTCTRL0, 0x01},
{CC2500_0B_FSCTRL1, 0x0A},
{CC2500_10_MDMCFG4, 0x7B},
{CC2500_11_MDMCFG3, 0x61},
{CC2500_12_MDMCFG2, 0x13},
{CC2500_15_DEVIATN, 0x51},
};
const PROGMEM uint8_t frsky_rx_d16lbt_reg[][2] = {
{CC2500_17_MCSM1, 0x0E},
{CC2500_0E_FREQ1, 0x80},
{CC2500_0F_FREQ0, 0x00},
{CC2500_06_PKTLEN, 0x23},
{CC2500_08_PKTCTRL0, 0x01},
{CC2500_0B_FSCTRL1, 0x08},
{CC2500_10_MDMCFG4, 0x7B},
{CC2500_11_MDMCFG3, 0xF8},
{CC2500_12_MDMCFG2, 0x03},
{CC2500_15_DEVIATN, 0x53},
};
const PROGMEM uint8_t frsky_rx_d8_reg[][2] = {
{CC2500_17_MCSM1, 0x0C},
{CC2500_0E_FREQ1, 0x76},
{CC2500_0F_FREQ0, 0x27},
{CC2500_06_PKTLEN, 0x19},
{CC2500_08_PKTCTRL0, 0x05},
{CC2500_0B_FSCTRL1, 0x08},
{CC2500_10_MDMCFG4, 0xAA},
{CC2500_11_MDMCFG3, 0x39},
{CC2500_12_MDMCFG2, 0x11},
{CC2500_15_DEVIATN, 0x42},
};
static uint8_t frsky_rx_chanskip;
static int8_t frsky_rx_finetune;
static uint8_t frsky_rx_format;
static void __attribute__((unused)) frsky_rx_strobe_rx()
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_Strobe(CC2500_SFRX);
CC2500_Strobe(CC2500_SRX);
}
static void __attribute__((unused)) frsky_rx_initialise_cc2500() {
const uint8_t frsky_rx_length[] = { FRSKY_RX_D8_LENGTH, FRSKY_RX_D16FCC_LENGTH, FRSKY_RX_D16LBT_LENGTH, FRSKY_RX_D16v2_LENGTH, FRSKY_RX_D16v2_LENGTH };
packet_length = frsky_rx_length[frsky_rx_format];
CC2500_Reset();
CC2500_Strobe(CC2500_SIDLE);
for (uint8_t i = 0; i < sizeof(frsky_rx_common_reg) / 2; i++)
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_common_reg[i][0]), pgm_read_byte_near(&frsky_rx_common_reg[i][1]));
switch (frsky_rx_format)
{
case FRSKY_RX_D16v2FCC:
case FRSKY_RX_D16FCC:
for (uint8_t i = 0; i < sizeof(frsky_rx_d16fcc_reg) / 2; i++)
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_d16fcc_reg[i][0]), pgm_read_byte_near(&frsky_rx_d16fcc_reg[i][1]));
if(frsky_rx_format==FRSKY_RX_D16v2FCC)
{
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Enable CRC
CC2500_WriteReg(CC2500_17_MCSM1, 0x0E); // Go/Stay in RX mode
CC2500_WriteReg(CC2500_11_MDMCFG3, 0x84); // bitrate 70K->77K
}
break;
case FRSKY_RX_D16v2LBT:
case FRSKY_RX_D16LBT:
for (uint8_t i = 0; i < sizeof(frsky_rx_d16lbt_reg) / 2; i++)
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_d16lbt_reg[i][0]), pgm_read_byte_near(&frsky_rx_d16lbt_reg[i][1]));
if(frsky_rx_format==FRSKY_RX_D16v2LBT)
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Enable CRC
break;
case FRSKY_RX_D8:
for (uint8_t i = 0; i < sizeof(frsky_rx_d8_reg) / 2; i++)
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_d8_reg[i][0]), pgm_read_byte_near(&frsky_rx_d8_reg[i][1]));
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
break;
}
CC2500_WriteReg(CC2500_0A_CHANNR, 0); // bind channel
rx_disable_lna = IS_POWER_FLAG_on;
CC2500_SetTxRxMode(rx_disable_lna ? TXRX_OFF : RX_EN); // lna disable / enable
frsky_rx_strobe_rx();
delayMicroseconds(1000); // wait for RX to activate
}
static void __attribute__((unused)) frsky_rx_set_channel(uint8_t channel)
{
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[channel]);
if(frsky_rx_format == FRSKY_RX_D8)
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
CC2500_WriteReg(CC2500_25_FSCAL1, calData[channel]);
frsky_rx_strobe_rx();
}
static void __attribute__((unused)) frsky_rx_calibrate()
{
frsky_rx_strobe_rx();
for (unsigned c = 0; c < 47; c++)
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[c]);
CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);
calData[c] = CC2500_ReadReg(CC2500_25_FSCAL1);
}
}
static uint8_t __attribute__((unused)) frskyx_rx_check_crc_id(bool bind,bool init)
{
/*debugln("RX");
for(uint8_t i=0; i<packet_length;i++)
debug(" %02X",packet[i]);
debugln("");*/
if(bind && packet[0]!=packet_length-1 && packet[1] !=0x03 && packet[2] != 0x01)
return false;
uint8_t offset=bind?3:1;
// Check D8 checksum
if (frsky_rx_format == FRSKY_RX_D8)
{
if((packet[packet_length+1] & 0x80) != 0x80) // Check CRC_OK flag in status byte 2
return false; // Bad CRC
if(init)
{//Save TXID
rx_tx_addr[3] = packet[3];
rx_tx_addr[2] = packet[4];
}
else
if(rx_tx_addr[3] != packet[offset] || rx_tx_addr[2] != packet[offset+1])
return false; // Bad address
return true; // Full match
}
// Check D16v2 checksum
if (frsky_rx_format == FRSKY_RX_D16v2LBT || frsky_rx_format == FRSKY_RX_D16v2FCC)
if((packet[packet_length+1] & 0x80) != 0x80) // Check CRC_OK flag in status byte 2
return false;
//debugln("HW Checksum ok");
// Check D16 checksum
uint16_t lcrc = FrSkyX_crc(&packet[3], packet_length - 5); // Compute crc
uint16_t rcrc = (packet[packet_length-2] << 8) | (packet[packet_length-1] & 0xff); // Received crc
if(lcrc != rcrc)
return false; // Bad CRC
//debugln("Checksum ok");
if (bind && (frsky_rx_format == FRSKY_RX_D16v2LBT || frsky_rx_format == FRSKY_RX_D16v2FCC))
for(uint8_t i=3; i<packet_length-2; i++) //unXOR bind packet
packet[i] ^= 0xA7;
uint8_t offset2=0;
if (bind && (frsky_rx_format == FRSKY_RX_D16LBT || frsky_rx_format == FRSKY_RX_D16FCC))
offset2=6;
if(init)
{//Save TXID
rx_tx_addr[3] = packet[3];
rx_tx_addr[2] = packet[4];
rx_tx_addr[1] = packet[5+offset2];
rx_tx_addr[0] = packet[6+offset2]; // RXnum
}
else
if(rx_tx_addr[3] != packet[offset] || rx_tx_addr[2] != packet[offset+1] || rx_tx_addr[1] != packet[offset+2+offset2])
return false; // Bad address
//debugln("Address ok");
if(!bind && rx_tx_addr[0] != packet[6])
return false; // Bad RX num
//debugln("Match");
return true; // Full match
}
static void __attribute__((unused)) frsky_rx_build_telemetry_packet()
{
uint16_t raw_channel[8];
uint32_t bits = 0;
uint8_t bitsavailable = 0;
uint8_t idx = 0;
uint8_t i;
if (frsky_rx_format == FRSKY_RX_D8)
{// decode D8 channels
raw_channel[0] = ((packet[10] & 0x0F) << 8 | packet[6]);
raw_channel[1] = ((packet[10] & 0xF0) << 4 | packet[7]);
raw_channel[2] = ((packet[11] & 0x0F) << 8 | packet[8]);
raw_channel[3] = ((packet[11] & 0xF0) << 4 | packet[9]);
raw_channel[4] = ((packet[16] & 0x0F) << 8 | packet[12]);
raw_channel[5] = ((packet[16] & 0xF0) << 4 | packet[13]);
raw_channel[6] = ((packet[17] & 0x0F) << 8 | packet[14]);
raw_channel[7] = ((packet[17] & 0xF0) << 4 | packet[15]);
for (i = 0; i < 8; i++) {
if (raw_channel[i] < 1290)
raw_channel[i] = 1290;
rx_rc_chan[i] = min(((raw_channel[i] - 1290) << 4) / 15, 2047);
}
}
else
{// decode D16 channels
raw_channel[0] = ((packet[10] << 8) & 0xF00) | packet[9];
raw_channel[1] = ((packet[11] << 4) & 0xFF0) | (packet[10] >> 4);
raw_channel[2] = ((packet[13] << 8) & 0xF00) | packet[12];
raw_channel[3] = ((packet[14] << 4) & 0xFF0) | (packet[13] >> 4);
raw_channel[4] = ((packet[16] << 8) & 0xF00) | packet[15];
raw_channel[5] = ((packet[17] << 4) & 0xFF0) | (packet[16] >> 4);
raw_channel[6] = ((packet[19] << 8) & 0xF00) | packet[18];
raw_channel[7] = ((packet[20] << 4) & 0xFF0) | (packet[19] >> 4);
for (i = 0; i < 8; i++) {
// ignore failsafe channels
if(packet[7] != 0x10+(i<<1)) {
uint8_t shifted = (raw_channel[i] & 0x800)>0;
uint16_t channel_value = raw_channel[i] & 0x7FF;
if (channel_value < 64)
rx_rc_chan[shifted ? i + 8 : i] = 0;
else
rx_rc_chan[shifted ? i + 8 : i] = min(((channel_value - 64) << 4) / 15, 2047);
}
}
}
// buid telemetry packet
packet_in[idx++] = RX_LQI;
packet_in[idx++] = RX_RSSI;
packet_in[idx++] = 0; // start channel
packet_in[idx++] = frsky_rx_format == FRSKY_RX_D8 ? 8 : 16; // number of channels in packet
// pack channels
for (i = 0; i < packet_in[3]; i++) {
bits |= ((uint32_t)rx_rc_chan[i]) << bitsavailable;
bitsavailable += 11;
while (bitsavailable >= 8) {
packet_in[idx++] = bits & 0xff;
bits >>= 8;
bitsavailable -= 8;
}
}
}
static void __attribute__((unused)) frsky_rx_data()
{
uint16_t temp = FRSKY_RX_EEPROM_OFFSET;
frsky_rx_format = eeprom_read_byte((EE_ADDR)temp++) % FRSKY_RX_FORMATS;
rx_tx_addr[3] = eeprom_read_byte((EE_ADDR)temp++);
rx_tx_addr[2] = eeprom_read_byte((EE_ADDR)temp++);
rx_tx_addr[1] = eeprom_read_byte((EE_ADDR)temp++);
rx_tx_addr[0] = RX_num;
frsky_rx_finetune = eeprom_read_byte((EE_ADDR)temp++);
debug("format=%d, ", frsky_rx_format);
debug("addr[3]=%02X, ", rx_tx_addr[3]);
debug("addr[2]=%02X, ", rx_tx_addr[2]);
debug("addr[1]=%02X, ", rx_tx_addr[1]);
debug("rx_num=%02X, ", rx_tx_addr[0]);
debugln("tune=%d", (int8_t)frsky_rx_finetune);
if(frsky_rx_format != FRSKY_RX_D16v2LBT && frsky_rx_format != FRSKY_RX_D16v2FCC)
{//D8 & D16v1
for (uint8_t ch = 0; ch < 47; ch++)
hopping_frequency[ch] = eeprom_read_byte((EE_ADDR)temp++);
}
else
{
FrSkyFormat=frsky_rx_format == FRSKY_RX_D16v2FCC?0:2;
FrSkyX2_init_hop();
}
debug("ch:");
for (uint8_t ch = 0; ch < 47; ch++)
debug(" %02X", hopping_frequency[ch]);
debugln("");
frsky_rx_initialise_cc2500();
frsky_rx_calibrate();
CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // FS_AUTOCAL = manual
CC2500_WriteReg(CC2500_09_ADDR, rx_tx_addr[3]); // set address
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05); // check address
if (option == 0)
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
else
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
frsky_rx_set_channel(hopping_frequency_no);
phase = FRSKY_RX_DATA;
}
uint16_t initFrSky_Rx()
{
state = 0;
frsky_rx_chanskip = 1;
hopping_frequency_no = 0;
rx_data_started = false;
frsky_rx_finetune = 0;
telemetry_link = 0;
packet_count = 0;
if (IS_BIND_IN_PROGRESS)
{
frsky_rx_format = FRSKY_RX_D8;
frsky_rx_initialise_cc2500();
phase = FRSKY_RX_TUNE_START;
debugln("FRSKY_RX_TUNE_START");
}
else
frsky_rx_data();
return 1000;
}
uint16_t FrSky_Rx_callback()
{
static uint32_t pps_timer=0;
static uint8_t pps_counter=0;
static int8_t read_retry = 0;
static int8_t tune_low, tune_high;
uint8_t len, ch;
if ((prev_option != option) && (phase >= FRSKY_RX_DATA))
{
if (option == 0)
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
else
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
prev_option = option;
}
if (rx_disable_lna != IS_POWER_FLAG_on)
{
rx_disable_lna = IS_POWER_FLAG_on;
CC2500_SetTxRxMode(rx_disable_lna ? TXRX_OFF : RX_EN);
}
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
switch(phase)
{
case FRSKY_RX_TUNE_START:
if (len == packet_length + 2) //+2=RSSI+LQI+CRC
{
CC2500_ReadData(packet, len);
if(frskyx_rx_check_crc_id(true,true))
{
frsky_rx_finetune = -127;
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
phase = FRSKY_RX_TUNE_LOW;
debugln("FRSKY_RX_TUNE_LOW");
frsky_rx_strobe_rx();
return 1000;
}
}
frsky_rx_format = (frsky_rx_format + 1) % FRSKY_RX_FORMATS; // switch to next format (D8, D16FCC, D16LBT, D16v2FCC, D16v2LBT)
frsky_rx_initialise_cc2500();
frsky_rx_finetune += 10;
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
frsky_rx_strobe_rx();
return 18000;
case FRSKY_RX_TUNE_LOW:
if (len == packet_length + 2) //+2=RSSI+LQI+CRC
{
CC2500_ReadData(packet, len);
if(frskyx_rx_check_crc_id(true,false)) {
tune_low = frsky_rx_finetune;
frsky_rx_finetune = 127;
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
phase = FRSKY_RX_TUNE_HIGH;
debugln("FRSKY_RX_TUNE_HIGH");
frsky_rx_strobe_rx();
return 1000;
}
}
frsky_rx_finetune += 1;
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
frsky_rx_strobe_rx();
return 18000;
case FRSKY_RX_TUNE_HIGH:
if (len == packet_length + 2) //+2=RSSI+LQI+CRC
{
CC2500_ReadData(packet, len);
if(frskyx_rx_check_crc_id(true,false)) {
tune_high = frsky_rx_finetune;
frsky_rx_finetune = (tune_low + tune_high) / 2;
CC2500_WriteReg(CC2500_0C_FSCTRL0, (int8_t)frsky_rx_finetune);
if(tune_low < tune_high)
{
phase = FRSKY_RX_BIND;
debugln("FRSKY_RX_TUNE_HIGH");
}
else
{
phase = FRSKY_RX_TUNE_START;
debugln("FRSKY_RX_TUNE_START");
}
frsky_rx_strobe_rx();
return 1000;
}
}
frsky_rx_finetune -= 1;
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
frsky_rx_strobe_rx();
return 18000;
case FRSKY_RX_BIND:
if (len == packet_length + 2) //+2=RSSI+LQI+CRC
{
CC2500_ReadData(packet, len);
if(frskyx_rx_check_crc_id(true,false)) {
if(frsky_rx_format != FRSKY_RX_D16v2LBT && frsky_rx_format != FRSKY_RX_D16v2FCC)
{// D8 & D16v1
if(packet[5] <= 0x2D)
{
for (ch = 0; ch < 5; ch++)
hopping_frequency[packet[5]+ch] = packet[6+ch];
state |= 1 << (packet[5] / 5);
}
}
else
state=0x3FF; //No hop table for D16v2
if (state == 0x3FF)
{
debugln("Bind complete");
BIND_DONE;
// store format, finetune setting, txid, channel list
uint16_t temp = FRSKY_RX_EEPROM_OFFSET;
if(sub_protocol==FRSKY_CLONE)
{
if(frsky_rx_format==FRSKY_RX_D8)
temp=FRSKYD_CLONE_EEPROM_OFFSET;
else if(frsky_rx_format == FRSKY_RX_D16FCC || frsky_rx_format == FRSKY_RX_D16LBT)
temp=FRSKYX_CLONE_EEPROM_OFFSET;
else
temp=FRSKYX2_CLONE_EEPROM_OFFSET;
}
eeprom_write_byte((EE_ADDR)temp++, frsky_rx_format);
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[3]);
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[2]);
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[1]);
if(sub_protocol==FRSKY_RX)
eeprom_write_byte((EE_ADDR)temp++, frsky_rx_finetune);
if(frsky_rx_format != FRSKY_RX_D16v2FCC && frsky_rx_format != FRSKY_RX_D16v2LBT)
for (ch = 0; ch < 47; ch++)
eeprom_write_byte((EE_ADDR)temp++, hopping_frequency[ch]);
frsky_rx_data();
debugln("FRSKY_RX_DATA");
}
}
frsky_rx_strobe_rx();
}
return 1000;
case FRSKY_RX_DATA:
if (len == packet_length + 2) //+2=RSSI+LQI+CRC
{
CC2500_ReadData(packet, len);
if(frskyx_rx_check_crc_id(false,false))
{
RX_RSSI = packet[len-2];
if(RX_RSSI >= 128)
RX_RSSI -= 128;
else
RX_RSSI += 128;
bool chanskip_valid=true;
// hop to next channel
if (frsky_rx_format != FRSKY_RX_D8)
{//D16v1 & D16v2
if(rx_data_started)
{
if(frsky_rx_chanskip != (((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2)))
{
chanskip_valid=false; // chanskip value has changed which surely indicates a bad frame
packet_count++;
if(packet_count>5) // the TX must have changed chanskip...
frsky_rx_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); // chanskip init
}
else
packet_count=0;
}
else
frsky_rx_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); // chanskip init
}
hopping_frequency_no = (hopping_frequency_no + frsky_rx_chanskip) % 47;
frsky_rx_set_channel(hopping_frequency_no);
if(chanskip_valid)
{
if (telemetry_link == 0)
{ // send channels to TX
frsky_rx_build_telemetry_packet();
telemetry_link = 1;
}
pps_counter++;
}
rx_data_started = true;
read_retry = 0;
}
}
// packets per second
if (millis() - pps_timer >= 1000) {
pps_timer = millis();
debugln("%d pps", pps_counter);
RX_LQI = pps_counter;
if(pps_counter==0) // no packets for 1 sec or more...
{// restart the search
rx_data_started=false;
packet_count=0;
}
pps_counter = 0;
}
// skip channel if no packet received in time
if (read_retry++ >= 9) {
hopping_frequency_no = (hopping_frequency_no + frsky_rx_chanskip) % 47;
frsky_rx_set_channel(hopping_frequency_no);
if(rx_data_started)
read_retry = 0;
else
read_retry = -50; // retry longer until first packet is catched
}
break;
}
return 1000;
}
#endif

View File

@@ -16,18 +16,20 @@ Multiprotocol is distributed in the hope that it will be useful,
#if defined(GD00X_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_nrf250k.h"
//#define FORCE_GD00X_ORIGINAL_ID
#define GD00X_INITIAL_WAIT 500
#define GD00X_PACKET_PERIOD 3500
#define GD00X_RF_BIND_CHANNEL 2
#define GD00X_RF_NUM_CHANNELS 4
#define GD00X_PAYLOAD_SIZE 15
#define GD00X_BIND_COUNT 857 //3sec
#define GD00X_V2_BIND_PACKET_PERIOD 5110
#define GD00X_V2_RF_BIND_CHANNEL 0x43
#define GD00X_V2_RF_NUM_CHANNELS 2
#define GD00X_V2_PAYLOAD_SIZE 6
// flags going to packet[11]
@@ -55,7 +57,7 @@ static void __attribute__((unused)) GD00X_send_packet()
channel=convert_channel_ppm(CH5); // TRIM
packet[9 ] = channel;
packet[10] = channel>>8;
packet[11] = GD00X_FLAG_DR // Force high rate
packet[11] = GET_FLAG(!CH7_SW, GD00X_FLAG_DR)
| GET_FLAG(CH6_SW, GD00X_FLAG_LIGHT);
packet[12] = 0x00;
packet[13] = 0x00;
@@ -70,23 +72,14 @@ static void __attribute__((unused)) GD00X_send_packet()
{
packet[0]=convert_channel_16b_limit(THROTTLE,0,100); // 0..100
// Deadband is needed on aileron
uint16_t aileron=limit_channel_100(AILERON); // 204<->1844
#define GD00X_V2_DB_MIN 1024-40
#define GD00X_V2_DB_MAX 1024+40
if(aileron>GD00X_V2_DB_MIN && aileron<GD00X_V2_DB_MAX)
packet[1]=0x20; // Send the channel centered
else // Ail: 0x3F..0x20..0x00
if(aileron>GD00X_V2_DB_MAX)
packet[1]=0x1F-((aileron-GD00X_V2_DB_MAX)*(0x20)/(CHANNEL_MAX_100+1-GD00X_V2_DB_MAX)); // 1F..00
else
packet[1]=0x3F-((aileron-CHANNEL_MIN_100)*(0x1F)/(GD00X_V2_DB_MIN-CHANNEL_MIN_100)); // 3F..21
// Deadband is needed on aileron, 40 gives +-6%
packet[1]=convert_channel_8b_limit_deadband(AILERON,0x3F,0x20,0x00,40); // Aileron: 3F..20..00
// Trims must be in a seperate channel for this model
packet[2]=0x3F-(convert_channel_8b(CH5)>>2); // Trim: 0x3F..0x20..0x00
uint8_t seq=((packet_count*3)/7)%5;
packet[4]=seq | GD00X_V2_FLAG_DR;
packet[4]=seq
| GET_FLAG(!CH7_SW, GD00X_V2_FLAG_DR);
if(CH6_SW!=prev_CH6)
{ // LED switch is temporary
@@ -118,42 +111,31 @@ static void __attribute__((unused)) GD00X_send_packet()
packet[5]='D';
}
// Power on, TX mode, CRC enabled
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
if(IS_BIND_DONE)
{
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
XN297L_Hopping(hopping_frequency_no);
if(sub_protocol==GD_V1)
{
hopping_frequency_no++;
hopping_frequency_no &= 3; // 4 RF channels
hopping_frequency_no &= GD00X_RF_NUM_CHANNELS-1; // 4 RF channels
}
}
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(packet, packet_length);
XN297L_WritePayload(packet, packet_length);
NRF24L01_SetPower(); // Set tx_power
XN297L_SetPower(); // Set tx_power
XN297L_SetFreqOffset(); // Set frequency offset
}
static void __attribute__((unused)) GD00X_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297L_Init();
if(sub_protocol==GD_V1)
XN297_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
XN297L_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
else
XN297_SetTXAddr((uint8_t*)"GDKNx", 5);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, sub_protocol==GD_V1?GD00X_RF_BIND_CHANNEL:GD00X_V2_RF_BIND_CHANNEL); // Bind channel
NRF24L01_FlushTx();
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_SetBitrate(NRF24L01_BR_250K); // 250Kbps
NRF24L01_SetPower();
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
}
static void __attribute__((unused)) GD00X_initialize_txid()
@@ -161,14 +143,14 @@ static void __attribute__((unused)) GD00X_initialize_txid()
if(sub_protocol==GD_V1)
{
uint8_t start=76+(rx_tx_addr[0]&0x03);
for(uint8_t i=0; i<4;i++)
for(uint8_t i=0; i<GD00X_RF_NUM_CHANNELS;i++)
hopping_frequency[i]=start-(i<<1);
#ifdef FORCE_GD00X_ORIGINAL_ID
rx_tx_addr[0]=0x1F; // or 0xA5 or 0x26
rx_tx_addr[1]=0x39; // or 0x37 or 0x35
rx_tx_addr[2]=0x12; // Constant on 3 TXs
rx_tx_addr[3]=0x13; // Constant on 3 TXs
for(uint8_t i=0; i<4;i++)
for(uint8_t i=0; i<GD00X_RF_NUM_CHANNELS;i++)
hopping_frequency[i]=79-(i<<1); // or 77 or 78
#endif
}
@@ -226,6 +208,9 @@ uint16_t GD00X_callback()
if(--bind_counter==0)
BIND_DONE;
GD00X_send_packet();
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
return packet_period;
}

View File

@@ -47,7 +47,7 @@ static void __attribute__((unused)) GW008_send_packet(uint8_t bind)
}
else
{
packet[1] = 0x01 | GET_FLAG(CH5, 0x40); // flip
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
packet[4] = convert_channel_16b_limit(RUDDER , 200, 0); // rudder
@@ -70,7 +70,7 @@ static void __attribute__((unused)) GW008_send_packet(uint8_t bind)
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WriteEnhancedPayload(packet, GW008_PAYLOAD_SIZE, 0, 0x3c7d);
XN297_WriteEnhancedPayload(packet, GW008_PAYLOAD_SIZE, 0);
NRF24L01_SetPower(); // Set tx_power
}
@@ -125,7 +125,7 @@ uint16_t GW008_callback()
NRF24L01_SetTxRxMode(TX_EN);
GW008_send_packet(1);
phase = GW008_BIND2;
return 300;
return 850; // minimum value 750 for STM32
}
break;
case GW008_BIND2:
@@ -139,6 +139,9 @@ uint16_t GW008_callback()
return 5000;
break;
case GW008_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(GW008_PACKET_PERIOD);
#endif
GW008_send_packet(0);
break;
}

View File

@@ -177,7 +177,12 @@ static void __attribute__((unused)) H8_3D_init()
uint16_t H8_3D_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
H8_3D_send_packet(0);
}
else
{
if (bind_counter == 0)

View File

@@ -0,0 +1,464 @@
/*
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(HOTT_CC2500_INO)
#include "iface_cc2500.h"
//#define HOTT_FORCE_ID // Force ID of original dump
#define HOTT_TX_PACKET_LEN 50
#define HOTT_RX_PACKET_LEN 22
#define HOTT_PACKET_PERIOD 10000
#define HOTT_NUM_RF_CHANNELS 75
#define HOTT_COARSE 0
enum {
HOTT_START = 0x00,
HOTT_CAL = 0x01,
HOTT_DATA1 = 0x02,
HOTT_RX1 = 0x03,
HOTT_RX2 = 0x04,
};
#ifdef HOTT_FW_TELEMETRY
#define HOTT_SENSOR_TYPE 6
#define HOTT_SENSOR_SEARCH_PERIOD 120
uint8_t HOTT_sensor_cur=0;
uint8_t HOTT_sensor_pages=0;
uint8_t HOTT_sensor_valid=false;
uint8_t HOTT_sensor_ok[HOTT_SENSOR_TYPE];
#endif
#define HOTT_FREQ0_VAL 0x6E
// Some important initialization parameters, all others are either default,
// or not important in the context of transmitter
// FIFOTHR 00
// SYNC1 D3
// SYNC0 91
// PKTLEN 32 - Packet length, 50 bytes
// PKTCTRL1 04 - APPEND_STATUS on=RSSI+LQI, all other are receive parameters - irrelevant
// PKTCTRL0 44 - whitening, use FIFO, use CRC, fixed packet length
// ADDR 00
// CHANNR 10
// FSCTRL1 09 - IF
// FSCTRL0 00 - zero freq offset
// FREQ2 5C - synthesizer frequencyfor 26MHz crystal
// FREQ1 6C
// FREQ0 B9
// MDMCFG4 2D -
// MDMCFG3 3B -
// MDMCFG2 73 - disable DC blocking, MSK, no Manchester code, 32 bits sync word
// MDMCFG1 A3 - FEC enable, 4 preamble bytes, CHANSPC_E - 03
// MDMCFG0 AA - CHANSPC_M - AA
// DEVIATN 47 -
// MCSM2 07 -
// MCSM1 00 - always use CCA, go to IDLE when done
// MCSM0 08 - disable autocalibration, PO_TIMEOUT - 64, no pin radio control, no forcing XTAL to stay in SLEEP
// FOCCFG 1D
const PROGMEM uint8_t HOTT_init_values[] = {
/* 00 */ 0x2F, 0x2E, 0x2F, 0x00, 0xD3, 0x91, 0x32, 0x04,
/* 08 */ 0x44, 0x00, 0x00, 0x09, 0x00, 0x5C, 0x6C, HOTT_FREQ0_VAL + HOTT_COARSE,
/* 10 */ 0x2D, 0x3B, 0x73, 0xA3, 0xAA, 0x47, 0x07, 0x00,
/* 18 */ 0x08, 0x1D, 0x1C, 0xC7, 0x09, 0xF0, 0x87, 0x6B,
/* 20 */ 0xF0, 0xB6, 0x10, 0xEA, 0x0A, 0x00, 0x11
};
static void __attribute__((unused)) HOTT_rf_init()
{
CC2500_Strobe(CC2500_SIDLE);
for (uint8_t i = 0; i < 39; ++i)
CC2500_WriteReg(i, pgm_read_byte_near(&HOTT_init_values[i]));
prev_option = option;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
}
static void __attribute__((unused)) HOTT_tune_chan()
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, (rf_ch_num+1)*3);
CC2500_Strobe(CC2500_SCAL);
}
static void __attribute__((unused)) HOTT_tune_chan_fast()
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, (rf_ch_num+1)*3);
CC2500_WriteReg(CC2500_25_FSCAL1, calData[rf_ch_num]);
}
static void __attribute__((unused)) HOTT_tune_freq()
{
if ( prev_option != option )
{
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
CC2500_WriteReg(CC2500_0F_FREQ0, HOTT_FREQ0_VAL + HOTT_COARSE);
prev_option = option ;
phase = HOTT_START; // Restart the tune process if option is changed to get good tuned values
}
}
const uint8_t PROGMEM HOTT_hop[][HOTT_NUM_RF_CHANNELS]=
{ { 48, 37, 16, 62, 9, 50, 42, 22, 68, 0, 55, 35, 21, 74, 1, 56, 31, 20, 70, 11, 45, 32, 24, 71, 8, 54, 38, 26, 61, 13, 53, 30, 15, 65, 7, 52, 34, 28, 60, 3, 47, 39, 18, 69, 2, 49, 44, 23, 72, 5, 51, 43, 19, 64, 12, 46, 33, 17, 67, 6, 58, 36, 29, 73, 14, 57, 41, 25, 63, 4, 59, 40, 27, 66, 10 },
{ 50, 23, 5, 34, 67, 53, 22, 12, 39, 62, 51, 21, 10, 33, 63, 59, 16, 1, 43, 66, 49, 19, 8, 30, 71, 47, 24, 2, 35, 68, 45, 25, 14, 41, 74, 55, 18, 4, 32, 61, 54, 17, 11, 31, 72, 52, 28, 6, 38, 65, 46, 15, 9, 40, 60, 48, 26, 3, 37, 70, 58, 29, 0, 36, 64, 56, 20, 7, 42, 69, 57, 27, 13, 44, 73 },
{ 73, 51, 39, 18, 9, 64, 56, 34, 16, 12, 66, 58, 36, 25, 11, 61, 47, 40, 15, 8, 71, 50, 43, 20, 6, 62, 54, 42, 19, 3, 63, 46, 44, 29, 14, 72, 49, 33, 22, 5, 69, 57, 30, 21, 10, 70, 45, 35, 26, 7, 65, 59, 31, 28, 1, 67, 48, 32, 24, 0, 60, 55, 41, 17, 2, 74, 52, 38, 27, 4, 68, 53, 37, 23, 13 },
{ 52, 60, 40, 21, 14, 50, 72, 41, 23, 13, 59, 61, 39, 16, 6, 58, 66, 33, 17, 5, 55, 64, 43, 20, 12, 54, 74, 35, 29, 3, 46, 63, 37, 22, 10, 48, 65, 31, 27, 9, 49, 73, 38, 24, 11, 56, 70, 32, 15, 1, 51, 71, 44, 18, 8, 45, 67, 36, 25, 7, 57, 62, 34, 28, 2, 53, 69, 42, 19, 4, 47, 68, 30, 26, 0 },
{ 50, 16, 34, 6, 71, 51, 24, 40, 7, 68, 57, 27, 33, 14, 70, 55, 26, 30, 5, 74, 47, 28, 44, 11, 67, 49, 15, 32, 9, 61, 52, 22, 37, 13, 66, 59, 18, 42, 3, 62, 46, 29, 31, 12, 60, 48, 19, 38, 1, 72, 58, 17, 36, 4, 64, 53, 21, 39, 0, 63, 56, 20, 41, 2, 65, 45, 25, 35, 10, 69, 54, 23, 43, 8, 73 },
{ 55, 38, 12, 62, 23, 52, 44, 3, 66, 18, 54, 36, 10, 74, 16, 56, 42, 9, 70, 17, 58, 33, 5, 69, 20, 50, 40, 1, 63, 24, 53, 37, 13, 65, 15, 48, 34, 4, 61, 22, 57, 31, 6, 64, 26, 46, 35, 11, 72, 21, 47, 30, 7, 68, 29, 45, 32, 8, 60, 19, 49, 43, 2, 67, 27, 51, 39, 0, 71, 28, 59, 41, 14, 73, 25 },
{ 70, 32, 18, 10, 58, 69, 38, 22, 2, 54, 67, 36, 19, 12, 57, 62, 34, 20, 14, 52, 63, 41, 15, 3, 51, 73, 42, 28, 6, 48, 60, 43, 29, 5, 45, 64, 31, 17, 4, 56, 65, 35, 26, 13, 53, 61, 37, 23, 1, 49, 68, 40, 16, 9, 47, 71, 39, 25, 7, 50, 66, 33, 24, 8, 59, 72, 44, 27, 11, 46, 74, 30, 21, 0, 55 },
{ 6, 45, 71, 27, 44, 10, 46, 74, 22, 32, 0, 55, 69, 21, 33, 4, 50, 66, 18, 38, 7, 57, 62, 19, 36, 1, 48, 70, 20, 40, 8, 47, 68, 15, 43, 2, 58, 61, 26, 42, 3, 56, 72, 23, 34, 14, 54, 67, 16, 37, 5, 59, 64, 24, 30, 12, 52, 65, 25, 39, 13, 49, 73, 17, 31, 9, 53, 60, 28, 35, 11, 51, 63, 29, 41 },
{ 31, 65, 50, 20, 13, 37, 66, 45, 23, 5, 32, 69, 54, 19, 7, 39, 74, 52, 27, 1, 42, 64, 53, 22, 4, 43, 70, 58, 16, 3, 40, 71, 57, 17, 0, 35, 63, 56, 18, 9, 44, 72, 51, 21, 6, 33, 67, 46, 25, 11, 30, 73, 55, 15, 8, 36, 62, 48, 24, 10, 41, 60, 49, 29, 14, 34, 61, 47, 26, 2, 38, 68, 59, 28, 12 },
{ 67, 22, 49, 36, 13, 64, 28, 57, 37, 6, 65, 29, 46, 39, 3, 70, 26, 45, 35, 1, 62, 24, 58, 34, 10, 68, 19, 53, 33, 4, 66, 21, 52, 31, 7, 74, 18, 47, 32, 5, 61, 16, 51, 38, 8, 72, 23, 55, 30, 12, 73, 17, 59, 44, 0, 60, 15, 50, 43, 14, 63, 27, 48, 42, 11, 71, 20, 54, 41, 9, 69, 25, 56, 40, 2 },
{ 19, 38, 14, 66, 57, 18, 44, 7, 74, 48, 23, 30, 6, 71, 58, 26, 32, 5, 61, 46, 20, 34, 0, 68, 45, 24, 36, 1, 70, 50, 27, 33, 10, 63, 52, 16, 42, 9, 65, 51, 15, 41, 11, 64, 53, 22, 37, 3, 60, 56, 28, 35, 4, 67, 49, 17, 39, 13, 69, 54, 25, 43, 2, 73, 55, 21, 31, 8, 62, 47, 29, 40, 12, 72, 59 },
{ 4, 52, 64, 28, 44, 14, 46, 74, 16, 32, 11, 50, 68, 27, 36, 0, 47, 70, 26, 34, 13, 57, 61, 18, 38, 6, 56, 62, 19, 40, 5, 58, 67, 17, 31, 12, 54, 63, 22, 33, 3, 53, 72, 21, 41, 10, 48, 66, 15, 35, 7, 45, 60, 20, 37, 9, 51, 69, 25, 42, 2, 59, 71, 24, 39, 1, 55, 65, 23, 30, 8, 49, 73, 29, 43 },
{ 44, 66, 19, 1, 56, 35, 62, 20, 4, 54, 39, 70, 24, 5, 55, 31, 74, 26, 12, 58, 32, 60, 17, 10, 45, 37, 63, 22, 3, 50, 33, 64, 16, 7, 51, 34, 61, 21, 8, 48, 38, 68, 29, 0, 46, 36, 72, 28, 14, 49, 42, 69, 25, 6, 57, 43, 65, 18, 2, 52, 30, 71, 23, 13, 47, 41, 67, 15, 9, 53, 40, 73, 27, 11, 59 },
{ 12, 16, 36, 46, 69, 6, 20, 44, 58, 62, 11, 19, 34, 48, 71, 1, 18, 42, 50, 74, 3, 25, 31, 47, 65, 0, 24, 33, 45, 72, 2, 23, 35, 56, 64, 10, 22, 38, 49, 63, 7, 26, 37, 51, 70, 14, 21, 30, 53, 67, 5, 15, 40, 52, 66, 9, 17, 39, 55, 60, 13, 27, 41, 54, 73, 4, 28, 32, 57, 61, 8, 29, 43, 59, 68 },
{ 63, 42, 18, 2, 57, 71, 34, 22, 10, 48, 67, 36, 25, 4, 46, 60, 31, 28, 6, 47, 74, 37, 15, 0, 55, 65, 32, 24, 12, 56, 66, 40, 27, 14, 52, 62, 38, 19, 3, 50, 73, 33, 29, 11, 53, 61, 35, 16, 7, 58, 72, 41, 26, 5, 59, 69, 30, 20, 9, 51, 68, 44, 23, 1, 49, 70, 39, 17, 8, 54, 64, 43, 21, 13, 45 },
{ 52, 1, 71, 17, 36, 47, 7, 64, 26, 32, 53, 5, 60, 20, 42, 57, 2, 66, 18, 34, 56, 4, 63, 24, 35, 46, 13, 72, 22, 30, 48, 0, 67, 21, 39, 50, 3, 74, 16, 31, 59, 14, 61, 23, 37, 45, 6, 65, 19, 44, 51, 11, 62, 27, 41, 55, 9, 68, 15, 38, 58, 8, 70, 29, 40, 54, 10, 69, 28, 33, 49, 12, 73, 25, 43 }
};
const uint16_t PROGMEM HOTT_hop_val[] = { 0xC06B, 0xC34A, 0xDB24, 0x8E09, 0x272E, 0x217F, 0x155B, 0xEDE8, 0x1D31, 0x0986, 0x56F7, 0x6454, 0xC42D, 0x01D2, 0xC253, 0x1180 };
static void __attribute__((unused)) HOTT_init()
{
packet[0] = pgm_read_word_near( &HOTT_hop_val[num_ch] );
packet[1] = pgm_read_word_near( &HOTT_hop_val[num_ch] )>>8;
for(uint8_t i=0; i<HOTT_NUM_RF_CHANNELS; i++)
hopping_frequency[i]=pgm_read_byte_near( &HOTT_hop[num_ch][i] );
#ifdef HOTT_FORCE_ID
memcpy(rx_tx_addr,"\x7C\x94\x00\x0D\x50",5);
#endif
memset(&packet[30],0xFF,9);
packet[39]=0x07; // unknown and constant
if(IS_BIND_IN_PROGRESS)
{
packet[28] = 0x80; // unknown 0x80 when bind starts then when RX replies start normal, 0x89/8A/8B/8C/8D/8E during normal packets
packet[29] = 0x02; // unknown 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets
memset(&packet[40],0xFA,5);
memcpy(&packet[45],rx_tx_addr,5);
}
else
{
packet[28] = 0x8C; // unknown 0x80 when bind starts then when RX replies start normal, 0x89/8A/8B/8C/8D/8E during normal packets, 0x0F->config menu
packet[29] = 0x02; // unknown 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets, 0x01->config menu, 0x0A->no more RX telemetry
memcpy(&packet[40],rx_tx_addr,5);
uint8_t addr=HOTT_EEPROM_OFFSET+RX_num*5;
for(uint8_t i=0;i<5;i++)
packet[45+i]=eeprom_read_byte((EE_ADDR)(addr+i));
}
}
static void __attribute__((unused)) HOTT_data_packet()
{
packet[2] = hopping_frequency_no;
packet[3] = 0x00; // used for failsafe but may also be used for additional channels
#ifdef FAILSAFE_ENABLE
static uint8_t failsafe_count=0;
if(IS_FAILSAFE_VALUES_on && IS_BIND_DONE)
{
failsafe_count++;
if(failsafe_count>=3)
{
FAILSAFE_VALUES_off;
failsafe_count=0;
}
}
else
failsafe_count=0;
#endif
// Channels value are PPM*2, -100%=1100µs, +100%=1900µs, order TAER
uint16_t val;
for(uint8_t i=4;i<28;i+=2)
{
val=Channel_data[(i-4)>>1];
val=(((val<<2)+val)>>2)+860*2; // value range 860<->2140 *2 <-> -125%<->+125%
#ifdef FAILSAFE_ENABLE
if(failsafe_count==1)
{ // first failsafe packet
packet[3]=0x40;
uint16_t fs=Failsafe_data[(i-4)>>1];
if( fs == FAILSAFE_CHANNEL_HOLD || fs == FAILSAFE_CHANNEL_NOPULSES)
val|=0x8000; // channel hold flag
else
{
val=(((fs<<2)+fs)>>2)+860*2; // value range 860<->2140 *2 <-> -125%<->+125%
val|=0x4000; // channel specific position flag
}
}
else if(failsafe_count==2)
{ // second failsafe packet=timing?
packet[3]=0x50;
if(i==4)
val=2;
else
val=0;
}
#endif
packet[i] = val;
packet[i+1] = val>>8;
}
#ifdef HOTT_FW_TELEMETRY
static uint8_t prev_SerialRX_val=0;
if(HoTT_SerialRX)
{//Text mode
uint8_t sensor=HoTT_SerialRX_val&0xF0;
if((sensor&0x80) && sensor!=0xF0 && (HoTT_SerialRX_val&0x0F) >= 0x07)
{//Valid Text query
if(sensor==0x80) HoTT_SerialRX_val&=0x0F; // RX only
if(prev_SerialRX_val!=HoTT_SerialRX_val)
{
prev_SerialRX_val=HoTT_SerialRX_val;
packet[28] = HoTT_SerialRX_val; // send the button being pressed only once
}
else
packet[28] = HoTT_SerialRX_val | 0x0F; // no button pressed
packet[29] = 0x01; // 0x01->Text config menu
}
}
else
{
packet[28] = 0x89+HOTT_sensor_cur; // 0x89/8A/8B/8C/8D/8E during normal packets
packet[29] = 0x02; // unknown 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets, 0x01->text config menu, 0x0A->no more RX telemetry
}
#else
packet[28] = 0x80; // no sensor
packet[29] = 0x02; // unknown 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets, 0x01->text config menu, 0x0A->no more RX telemetry
#endif
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
CC2500_WriteReg(CC2500_06_PKTLEN, 0x32);
CC2500_WriteData(packet, HOTT_TX_PACKET_LEN);
#if 0
debug("RF:%02X P:",rf_ch_num);
for(uint8_t i=0;i<HOTT_TX_PACKET_LEN;i++)
debug(" %02X",packet[i]);
debugln("");
#endif
hopping_frequency_no++;
hopping_frequency_no %= HOTT_NUM_RF_CHANNELS;
rf_ch_num=hopping_frequency[hopping_frequency_no];
}
uint16_t ReadHOTT()
{
#ifdef HOTT_FW_TELEMETRY
static uint8_t pps_counter=0;
#endif
switch(phase)
{
case HOTT_START:
rf_ch_num = 0;
HOTT_tune_chan();
phase = HOTT_CAL;
return 2000;
case HOTT_CAL:
calData[rf_ch_num]=CC2500_ReadReg(CC2500_25_FSCAL1);
if (++rf_ch_num < HOTT_NUM_RF_CHANNELS)
HOTT_tune_chan();
else
{
hopping_frequency_no = 0;
rf_ch_num=hopping_frequency[hopping_frequency_no];
counter = 0;
phase = HOTT_DATA1;
}
return 2000;
/* Work cycle: 10ms */
case HOTT_DATA1:
//TX
#ifdef MULTI_SYNC
telemetry_set_input_sync(HOTT_PACKET_PERIOD);
#endif
HOTT_tune_freq();
HOTT_tune_chan_fast();
HOTT_data_packet();
phase = HOTT_RX1;
return 4500;
case HOTT_RX1:
//RX
CC2500_SetTxRxMode(RX_EN);
CC2500_WriteReg(CC2500_06_PKTLEN, HOTT_RX_PACKET_LEN);
CC2500_Strobe(CC2500_SRX);
phase = HOTT_RX2;
return 4500;
case HOTT_RX2:
//Telemetry
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if (len==HOTT_RX_PACKET_LEN+2)
{
CC2500_ReadData(packet_in, len);
if((packet_in[HOTT_RX_PACKET_LEN+1]&0x80) && memcmp(rx_tx_addr,packet_in,5)==0)
{ // CRC OK and TX ID matches
if(IS_BIND_IN_PROGRESS)
{
debug("B:");
for(uint8_t i=0;i<HOTT_RX_PACKET_LEN;i++)
debug(" %02X", packet_in[i]);
debugln("");
uint8_t addr=HOTT_EEPROM_OFFSET+RX_num*5;
for(uint8_t i=0; i<5; i++)
eeprom_write_byte((EE_ADDR)(addr+i),packet_in[5+i]);
BIND_DONE;
HOTT_init();
}
#ifdef HOTT_FW_TELEMETRY
else
{ //Telemetry
// [0..4] = TXID
// [5..9] = RXID
// [10] = 0x40 bind, 0x00 normal, 0x80 config menu
// [11] = telmetry pages. For sensors 0x00 to 0x04, for config mennu 0x00 to 0x12.
// Normal telem page 0 = 0x55, 0x32, 0x38, 0x55, 0x64, 0x32, 0xD0, 0x07, 0x00, 0x55
// Page 0 [12] = [21] = [15]
// Page 0 [13] = RX_Voltage Cur*10 in V
// Page 0 [14] = Temperature-20 in °C
// Page 0 [15] = RX_RSSI CC2500 formated (a<128:a/2-71dBm, a>=128:(a-256)/2-71dBm)
// Page 0 [16] = RX_LQI in %
// Page 0 [17] = RX_Voltage Min*10 in V
// Page 0 [18,19] = [19]*256+[18]=max lost packet time in ms, max value seems 2s=0x7D0
// Page 0 [20] = 0x00 ??
//
// Config menu consists of the different telem pages put all together
// Page X [12] = seems like all the telem pages with the same value are going together to make the full config menu text. Seen so far 'a', 'b', 'c', 'd'
// Page X [13..21] = 9 ascii chars to be displayed, char is highlighted when ascii|0x80
// Screen display is 21 characters large which means that once the first 21 chars are filled go to the begining of the next line
// Menu commands are sent through TX packets:
// packet[28]= 0xXF=>no key press, 0xXD=>down, 0xXB=>up, 0xX9=>enter, 0xXE=>right, 0xX7=>left with X=0 or D
// packet[29]= 0xX1/0xX9 with X=0 or X counting 0,1,1,2,2,..,9,9
// Reduce telemetry to 14 bytes
packet_in[0]= packet_in[HOTT_RX_PACKET_LEN];
packet_in[1]= TX_LQI;
bool send_telem=true;
if(packet[29]==2) // Requesting binary sensor
{
if( packet_in[11]==1 ) // Page 1
{
if(packet_sent)
packet_sent--;
if( packet_in[12] == ((HOTT_sensor_cur+9)<<4) ) // The current sensor is responding: 0x90/A0/B0/C0/D0/E0
{
HOTT_sensor_pages = 0; // Sensor first page received
HOTT_sensor_valid = true; // Data from the expected sensor is being received
HOTT_sensor_ok[HOTT_sensor_cur]=true;
}
else
{
HOTT_sensor_valid = false;
HOTT_sensor_pages = 0x1E; // Switch to next sensor
}
}
if(HOTT_sensor_valid && packet_in[11] ) // Valid & page !=0
{
packet_in[10] = HOTT_sensor_cur+9; // Marking telem with sensor ID
HOTT_sensor_pages |= 1<<packet_in[11]; // Page received
}
if(packet_in[11] && !HOTT_sensor_valid)
send_telem=false;
}
else
{ //Text mode
HOTT_sensor_pages = 0;
HOTT_sensor_valid = false;
packet_in[10] = 0x80; // Marking telem Text mode
packet_in[12] = 0;
for(uint8_t i=0; i<HOTT_SENSOR_TYPE;i++)
packet_in[12] |= HOTT_sensor_ok[i]<<i; // Send detected sensors
}
debug("T%d=",send_telem);
for(uint8_t i=10;i < HOTT_RX_PACKET_LEN; i++)
{
packet_in[i-8]=packet_in[i];
debug(" %02X",packet_in[i]);
}
debugln("");
if(send_telem)
telemetry_link=2;
if((HOTT_sensor_pages&0x1E) == 0x1E) // All 4 pages received from the sensor
{
HOTT_sensor_valid=false;
HOTT_sensor_pages=0;
uint8_t loop=0;
do
{
HOTT_sensor_cur++; // Switch to next sensor
HOTT_sensor_cur %= HOTT_SENSOR_TYPE;
loop++;
}
while(HOTT_sensor_ok[HOTT_sensor_cur]==false && loop<HOTT_SENSOR_TYPE+1 && packet_sent==0);
debugln("Sensor:%02X",((HOTT_sensor_cur+9)<<4));
}
}
pps_counter++;
#endif
}
}
#ifdef HOTT_FW_TELEMETRY
packet_count++;
if(packet_count>=100)
{
TX_LQI=pps_counter;
if(pps_counter==0)
{ // lost connection with RX, power cycle? research sensors again.
HOTT_sensor_cur=0;
HOTT_sensor_valid=false;
for(uint8_t i=0; i<HOTT_SENSOR_TYPE;i++)
HOTT_sensor_ok[i]=false; // no sensors detected
packet_sent=HOTT_SENSOR_SEARCH_PERIOD;
}
pps_counter=packet_count=0;
}
#endif
CC2500_Strobe(CC2500_SFRX); //Flush the RXFIFO
phase=HOTT_DATA1;
return 1000;
}
return 0;
}
uint16_t initHOTT()
{
num_ch=random(0xfefefefe)%16;
HOTT_init();
HOTT_rf_init();
#ifdef HOTT_FW_TELEMETRY
HoTT_SerialRX_val=0;
HoTT_SerialRX=false;
HOTT_sensor_cur=0;
HOTT_sensor_pages=0;
HOTT_sensor_valid=false;
for(uint8_t i=0; i<HOTT_SENSOR_TYPE;i++)
HOTT_sensor_ok[i]=false; // no sensors detected
packet_count=0;
packet_sent=HOTT_SENSOR_SEARCH_PERIOD;
#endif
phase = HOTT_START;
return 10000;
}
#endif

View File

@@ -123,8 +123,8 @@ static void __attribute__((unused)) build_ch_data()
for (i = 0; i< 8; i++) {
j=CH_AETR[i];
temp=convert_channel_16b_limit(j,0,1000);
if (j == THROTTLE) // It is clear that hisky's throttle stick is made reversely, so I adjust it here on purpose
temp = 1000 -temp;
if (j == CH3) // It is clear that hisky's throttle stick is made reversely, so I adjust it here on purpose
temp = 1000 - temp;
if (j == CH7)
temp = temp < 400 ? 0 : 3; // Gyro mode, 0 - 6 axis, 3 - 3 axis
packet[i] = (uint8_t)(temp&0xFF);
@@ -151,6 +151,9 @@ uint16_t hisky_cb()
phase=6;
break;
case 7: // build packet
#ifdef MULTI_SYNC
telemetry_set_input_sync(5000);
#endif
#ifdef FAILSAFE_ENABLE
if(IS_FAILSAFE_VALUES_on && hopping_frequency_no==0)
{ // send failsafe every 100ms
@@ -159,6 +162,7 @@ uint16_t hisky_cb()
convert_failsafe_HK310(CH5, &packet[4],&packet[5]);
packet[7]=0xAA;
packet[8]=0x5A;
FAILSAFE_VALUES_off;
}
else
#endif
@@ -216,6 +220,9 @@ uint16_t hisky_cb()
break;
case 7:
//Build normal packet
#ifdef MULTI_SYNC
telemetry_set_input_sync(9000);
#endif
build_ch_data();
break;
case 8:

View File

@@ -146,6 +146,11 @@ static void __attribute__((unused)) HITEC_build_packet()
break;
case 0x7B:
packet[5]=hopping_frequency[13]>>1; // if not there the Optima link is jerky...
packet[14]=0x2A;
packet[15]=0x46; // unknown but if 0x45 then 17=0x46, if 0x46 then 17=0x46 or 0x47, if 0x47 then 0x45 or 0x46
packet[16]=0x2A;
packet[17]=0x47;
packet[18]=0x2A;
break;
}
if(sub_protocol==MINIMA)
@@ -259,6 +264,9 @@ uint16_t ReadHITEC()
case HITEC_PREP:
if ( prev_option == option )
{ // No user frequency change
#ifdef MULTI_SYNC
telemetry_set_input_sync(HITEC_PACKET_PERIOD);
#endif
HITEC_change_chan_fast();
hopping_frequency_no++;
if(hopping_frequency_no>=rf_ch_num)
@@ -285,32 +293,32 @@ uint16_t ReadHITEC()
return HITEC_RX1_TIMING;
case HITEC_RX2:
uint8_t len=CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if(len && len<MAX_PKT)
if(len && len<TELEMETRY_BUFFER_SIZE)
{ // Something has been received
CC2500_ReadData(pkt, len);
if( (pkt[len-1] & 0x80) && pkt[0]==len-3 && pkt[1]==rx_tx_addr[1] && pkt[2]==rx_tx_addr[2] && pkt[3]==rx_tx_addr[3])
CC2500_ReadData(packet_in, len);
if( (packet_in[len-1] & 0x80) && packet_in[0]==len-3 && packet_in[1]==rx_tx_addr[1] && packet_in[2]==rx_tx_addr[2] && packet_in[3]==rx_tx_addr[3])
{ //valid crc && length ok && tx_id ok
debug("RX:l=%d",len);
for(uint8_t i=0;i<len;i++)
debug(",%02X",pkt[i]);
debug(",%02X",packet_in[i]);
if(IS_BIND_IN_PROGRESS)
{
if(len==13) // Bind packets have a length of 13
{ // bind packet: 0A,00,E5,F2,7X,05,06,07,08,09,00
debug(",bind");
boolean check=true;
for(uint8_t i=5;i<=10;i++)
if(pkt[i]!=i%10) check=false;
if((pkt[4]&0xF0)==0x70 && check)
for(uint8_t i=5;i<10;i++)
if(packet_in[i]!=i) check=false;
if((packet_in[4]&0xF0)==0x70 && check)
{
bind_phase=pkt[4]+1;
bind_phase=packet_in[4]+1;
if(bind_phase==0x7B)
bind_counter=164; // in dumps the RX stops to reply at 0x7B so wait a little and exit
}
}
}
else
if( len==15 && pkt[4]==0 && pkt[12]==0 )
if( len==15 && packet_in[4]==0 && packet_in[12]==0 )
{ // Valid telemetry packets
// no station:
// 0C,1C,A1,2B,00,00,00,00,00,00,00,8D,00,64,8E -> 00 8D=>RX battery voltage 0x008D/28=5.03V
@@ -323,40 +331,42 @@ uint16_t ReadHITEC()
// 0C,1C,A1,2B,00,16,00,00,00,00,00,16,00,2C,8E
// 0C,1C,A1,2B,00,17,00,00,00,42,44,17,00,48,8D -> 42=>temperature3 0x42-0x28=26°C,44=>temperature4 0x44-0x28=28°C
// 0C,1C,A1,2B,00,18,00,00,00,00,00,18,00,50,92
debug(",telem,%02x",pkt[14]&0x7F);
debug(",telem,%02x",packet_in[14]&0x7F);
#if defined(HITEC_FW_TELEMETRY) || defined(HITEC_HUB_TELEMETRY)
TX_RSSI = packet_in[13];
if(TX_RSSI >=128)
TX_RSSI -= 128;
else
TX_RSSI += 128;
TX_LQI = packet_in[14]&0x7F;
#endif
#if defined(HITEC_FW_TELEMETRY)
if(sub_protocol==OPT_FW)
{
// 8 bytes telemetry packets => see at the end of this file how to fully decode it
pkt[0]=pkt[13]; // TX RSSI
pkt[1]=pkt[14]&0x7F; // TX LQI
uint8_t offset=pkt[5]==0?1:0;
packet_in[0]=TX_RSSI; // TX RSSI
packet_in[1]=TX_LQI; // TX LQI
uint8_t offset=packet_in[5]==0?1:0;
for(uint8_t i=5;i < 11; i++)
pkt[i-3]=pkt[i+offset]; // frame number followed by 5 bytes of data
packet_in[i-3]=packet_in[i+offset]; // frame number followed by 5 bytes of data
telemetry_link=2; // telemetry forward available
}
#endif
#if defined(HITEC_HUB_TELEMETRY)
if(sub_protocol==OPT_HUB)
{
switch(pkt[5]) // telemetry frame number
switch(packet_in[5]) // telemetry frame number
{
case 0x00:
v_lipo1 = (pkt[10])<<5 | (pkt[11])>>3; // calculation in float is volt=(pkt[10]<<8+pkt[11])/28
v_lipo1 = (packet_in[10])<<5 | (packet_in[11])>>3; // calculation in float is volt=(packet_in[10]<<8+packet_in[11])/28
break;
case 0x11:
v_lipo1 = (pkt[9])<<5 | (pkt[10])>>3; // calculation in float is volt=(pkt[9]<<8+pkt[10])/28
v_lipo1 = (packet_in[9])<<5 | (packet_in[10])>>3; // calculation in float is volt=(packet_in[9]<<8+packet_in[10])/28
break;
case 0x18:
v_lipo2 = (pkt[6])<<5 | (pkt[7])>>3; // calculation in float is volt=(pkt[6]<<8+pkt[7])/10
v_lipo2 = (packet_in[6])<<5 | (packet_in[7])>>3; // calculation in float is volt=(packet_in[6]<<8+packet_in[7])/10
break;
}
TX_RSSI = pkt[13];
if(TX_RSSI >=128)
TX_RSSI -= 128;
else
TX_RSSI += 128;
TX_LQI = pkt[14]&0x7F;
telemetry_link=1; // telemetry hub available
}
#endif
@@ -389,10 +399,6 @@ uint16_t initHITEC()
rx_tx_addr[3]=0x6A;
memcpy((void *)hopping_frequency,(void *)"\x00\x3A\x4A\x32\x0C\x58\x2A\x10\x26\x20\x08\x60\x68\x70\x78\x80\x88\x56\x5E\x66\x6E",HITEC_NUM_FREQUENCE);
#endif
#if defined(HITEC_HUB_TELEMETRY)
if(sub_protocol==OPT_HUB)
init_frskyd_link_telemetry();
#endif
phase = HITEC_START;
return 10000;
}
@@ -403,7 +409,7 @@ packet[1] = TX LQI value
packet[2] = frame number
packet[3-7] telemetry data
The frame number takes the following values: 0x00, 0x11, 0x12, ..., 0x18. The frames can be present or not, they also do not have to follow each others.
The frame number takes the following values: 0x00, 0x11, 0x12, ..., 0x1C. The frames can be present or not, they also do not have to follow each others.
Here is a description of the telemetry data for each frame number:
- frame 0x00
data byte 0 -> 0x00 unknown
@@ -414,9 +420,9 @@ data byte 4 -> RX Batt Volt_L => RX Batt=(Volt_H*256+Volt_L)/28
- frame 0x11
data byte 0 -> 0xAF start of frame
data byte 1 -> 0x00 unknown
data byte 2 -> 0x2D frame type but constant here
data byte 3 -> Volt1_H
data byte 4 -> Volt1_L RX Batt=(Volt1_H*256+Volt1_L)/28 V
data byte 2 -> 0x2D station type 0x2D=standard station nitro or electric, 0xAC=advanced station
data byte 3 -> RX Batt Volt_H
data byte 4 -> RX Batt Volt_L => RX Batt=(Volt_H*256+Volt_L)/28
- frame 0x12
data byte 0 -> Lat_sec_H GPS : latitude second
data byte 1 -> Lat_sec_L signed int : 1/100 of second
@@ -431,9 +437,9 @@ data byte 3 -> signed int : +=Est, - = west
data byte 4 -> Temp2 Temperature2=Temp2-40°C
- frame 0x14
data byte 0 -> Speed_H
data byte 1 -> Speed_L Speed=Speed_H*256+Speed_L km/h
data byte 1 -> Speed_L GPS Speed=Speed_H*256+Speed_L km/h
data byte 2 -> Alti_sea_H
data byte 3 -> Alti_sea_L Altitude sea=Alti_sea_H*256+Alti_sea_L m
data byte 3 -> Alti_sea_L GPS Altitude=Alti_sea_H*256+Alti_sea_L m
data byte 4 -> Temp1 Temperature1=Temp1-40°C
- frame 0x15
data byte 0 -> FUEL
@@ -448,15 +454,30 @@ data byte 2 -> Date_day
data byte 3 -> Time_hour GPS Time
data byte 4 -> Time_min
- frame 0x17
data byte 0 -> 0x00 COURSEH
data byte 1 -> 0x00 COURSEL GPS Course = COURSEH*256+COURSEL
data byte 2 -> 0x00 GPS count
data byte 0 -> COURSEH
data byte 1 -> COURSEL GPS heading = COURSEH*256+COURSEL in degrees
data byte 2 -> Count GPS satellites
data byte 3 -> Temp3 Temperature3=Temp2-40°C
data byte 4 -> Temp4 Temperature4=Temp3-40°C
- frame 0x18
data byte 1 -> Volt2_H
data byte 2 -> Volt2_L Volt2=(Volt2_H*256+Volt2_L)/10 V
data byte 3 -> AMP1_L
data byte 4 -> AMP1_H Amp=(AMP1_H*256+AMP1_L -180)/14 in signed A
data byte 0 -> Volt_L Volt=(Volt_H*256+Volt_L)/10 V
data byte 1 -> Volt_H
data byte 2 -> AMP_L
data byte 3 -> AMP_H Amp=(AMP1_*256+AMP_L -180)/14 in signed A
- frame 0x19 Servo sensor
data byte 0 -> AMP_Servo1 Amp=AMP_Servo1/10 in A
data byte 1 -> AMP_Servo2 Amp=AMP_Servo2/10 in A
data byte 2 -> AMP_Servo3 Amp=AMP_Servo3/10 in A
data byte 3 -> AMP_Servo4 Amp=AMP_Servo4/10 in A
- frame 0x1A
data byte 2 -> ASpeed_H Air speed=ASpeed_H*256+ASpeed_L km/h
data byte 3 -> ASpeed_L
- frame 0x1B Variometer sensor
data byte 0 -> Alti1H
data byte 1 -> Alti1L Altitude unfiltered
data byte 2 -> Alti2H
data byte 3 -> Alti2L Altitude filtered
- frame 0x1C Unknown
- frame 0x22 Unknown
*/
#endif

View File

@@ -242,9 +242,14 @@ uint16_t HONTAI_callback()
}
}
else
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
HONTAI_send_packet(0);
}
return sub_protocol == FQ777_951 ? FQ777_951_PACKET_PERIOD : HONTAI_PACKET_PERIOD;
return packet_period;
}
uint16_t initHONTAI()
@@ -253,6 +258,7 @@ uint16_t initHONTAI()
bind_counter = HONTAI_BIND_COUNT;
HONTAI_initialize_txid();
HONTAI_init();
packet_period = sub_protocol == FQ777_951 ? FQ777_951_PACKET_PERIOD : HONTAI_PACKET_PERIOD;
return HONTAI_INITIAL_WAIT;
}
#endif

View File

@@ -376,6 +376,9 @@ uint16_t ReadHubsan()
case DATA_4:
case DATA_5:
if( txState == 0) { // send packet
#ifdef MULTI_SYNC
telemetry_set_input_sync(10000);
#endif
#ifdef HUBSAN_HUB_TELEMETRY
rfMode = A7105_TX;
#endif
@@ -464,9 +467,6 @@ uint16_t initHubsan()
}
packet_count=0;
bind_phase=0;
#ifdef HUBSAN_HUB_TELEMETRY
init_frskyd_link_telemetry();
#endif
return 10000;
}

View File

@@ -201,7 +201,10 @@ uint16_t ReadJ6Pro()
cyrf_datainit();
phase = J6PRO_CHAN_1;
case J6PRO_CHAN_1:
//Keep transmit power updated
#ifdef MULTI_SYNC
telemetry_set_input_sync(24550);
#endif
//Keep transmit power updated
CYRF_SetPower(0x28);
j6pro_build_data_packet();
//return 3400;

View File

@@ -0,0 +1,184 @@
/*
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 JJRC345
#if defined(JJRC345_NRF24L01_INO)
#include "iface_nrf24l01.h"
//#define JJRC345_FORCE_ID
#define JJRC345_PACKET_PERIOD 7450 // Timeout for callback in uSec
#define JJRC345_INITIAL_WAIT 500
#define JJRC345_PACKET_SIZE 16
#define JJRC345_RF_BIND_CHANNEL 5
#define JJRC345_BIND_COUNT 500
#define JJRC345_NUM_CHANNELS 4
enum JJRC345_FLAGS {
// flags going to packet[8]
JJRC345_FLAG_HEADLESS = 0x40,
JJRC345_FLAG_RTH = 0x80,
};
static uint8_t __attribute__((unused)) JJRC345_convert_channel(uint8_t num)
{
uint8_t val=convert_channel_8b(num);
// 7E..60..41..01, 80 center, 81..C1..E0..FE
if(val<0x80)
{
val=0x80-val; // 80..01
if(val>0x7E)
val=0x7E; // 7E..01
}
else if(val>0xFE)
val=0xFE; // 81..FE
return val;
}
static void __attribute__((unused)) JJRC345_send_packet()
{
packet[0] = 0x00;
packet[2] = 0x00;
if (IS_BIND_IN_PROGRESS)
{ //00 05 00 0A 46 4A 41 47 00 00 40 46 A5 4A F1 18
packet[1] = JJRC345_RF_BIND_CHANNEL;
packet[4] = hopping_frequency[0];
packet[5] = hopping_frequency[1];
packet[6] = hopping_frequency[2];
packet[7] = hopping_frequency[3];
packet[12] = 0xa5;
}
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]);
hopping_frequency_no++;
hopping_frequency_no %= JJRC345_NUM_CHANNELS;
packet[1] = hopping_frequency[hopping_frequency_no]; // next packet will be sent on this channel
packet[4] = convert_channel_8b(THROTTLE); // throttle: 00..FF
packet[5] = JJRC345_convert_channel(RUDDER); // rudder: 70..60..41..01, 80 center, 81..C1..E0..F0
packet[6] = JJRC345_convert_channel(ELEVATOR); // elevator: 70..60..41..01, 80 center, 81..C1..E0..F0
packet[7] = JJRC345_convert_channel(AILERON); // aileron: 70..60..41..01, 80 center, 81..C1..E0..F0
if(CH5_SW) //Flip
{
if(packet[6]>0xF0)
packet[6]=0xFF;
else if(packet[6]<0x80 && packet[6]>0x70)
packet[6]=0x7F;
if(packet[7]>0xF0)
packet[7]=0xFF;
else if(packet[7]<0x80 && packet[7]>0x70)
packet[7]=0x7F;
}
packet[12] = 0x02; // Rate: 00-01-02
}
packet[3] = 0x00; // Checksum upper bits
packet[8] = 0x00 // Rudder trim, 00 when not used, 01..1F when trimmed left, 20..3F
| GET_FLAG(CH6_SW,JJRC345_FLAG_HEADLESS) // Headless mode: 00 normal, 40 headless
| GET_FLAG(CH7_SW,JJRC345_FLAG_RTH); // RTH: 80 active
packet[9] = 0; // Elevator trim, 00 when not used, 20..25 when trimmed up, 0..1F when trimmed down
packet[10] = 0x40; // Aileron trim, 40 when not used, 40..5F when trimmed left, 61..7F when trimmed right
packet[11] = hopping_frequency[0]; // First hopping frequency
// Checksum
uint16_t sum=2;
for (uint8_t i = 0; i < 13; i++)
sum += packet[i];
packet[13]=sum;
packet[3]=((sum>>8)<<2)+2;
// TX ID
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();
XN297_WritePayload(packet, JJRC345_PACKET_SIZE);
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) JJRC345_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, JJRC345_RF_BIND_CHANNEL); // Bind channel
NRF24L01_FlushTx();
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_SetBitrate(NRF24L01_BR_1M); // 1 Mbps
NRF24L01_SetPower();
}
uint16_t JJRC345_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(JJRC345_PACKET_PERIOD);
#endif
if(IS_BIND_IN_PROGRESS)
{
if (bind_counter)
bind_counter--;
else
BIND_DONE;
}
JJRC345_send_packet();
return JJRC345_PACKET_PERIOD;
}
static void __attribute__((unused)) JJRC345_initialize_txid()
{
calc_fh_channels(4);
#ifdef JJRC345_FORCE_ID
//TX 1
rx_tx_addr[2]=0x1B;
rx_tx_addr[3]=0x12;
hopping_frequency[0] = 0x3f;
hopping_frequency[1] = 0x49;
hopping_frequency[2] = 0x47;
hopping_frequency[3] = 0x47;
//TX 2
rx_tx_addr[2]=0xF1;
rx_tx_addr[3]=0x18;
hopping_frequency[0] = 0x46;
hopping_frequency[1] = 0x4A;
hopping_frequency[2] = 0x41;
hopping_frequency[3] = 0x47;
#endif
}
uint16_t initJJRC345(void)
{
BIND_IN_PROGRESS; // autobind protocol
bind_counter = JJRC345_BIND_COUNT;
JJRC345_initialize_txid();
JJRC345_init();
return JJRC345_INITIAL_WAIT;
}
#endif

View File

@@ -0,0 +1,112 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
// Compatible with KF606 plane.
#if defined(KF606_NRF24L01_INO)
#include "iface_nrf250k.h"
//#define FORCE_KF606_ORIGINAL_ID
#define KF606_INITIAL_WAIT 500
#define KF606_PACKET_PERIOD 3000
#define KF606_RF_BIND_CHANNEL 7
#define KF606_PAYLOAD_SIZE 4
#define KF606_BIND_COUNT 857 //3sec
#define KF606_RF_NUM_CHANNELS 2
static void __attribute__((unused)) KF606_send_packet()
{
if(IS_BIND_IN_PROGRESS)
{
packet[0] = 0xAA;
memcpy(&packet[1],rx_tx_addr,3);
}
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);
hopping_frequency_no ^= 1; // 2 RF channels
}
XN297L_WritePayload(packet, KF606_PAYLOAD_SIZE);
XN297L_SetPower(); // Set tx_power
XN297L_SetFreqOffset(); // Set frequency offset
}
static void __attribute__((unused)) KF606_initialize_txid()
{
rx_tx_addr[0]=rx_tx_addr[3]; // Use RX_num;
hopping_frequency[0]=(rx_tx_addr[0]&0x3F)+9;
hopping_frequency[1]=hopping_frequency[0]+3;
#ifdef FORCE_KF606_ORIGINAL_ID
//TX1
rx_tx_addr[0]=0x57;
rx_tx_addr[1]=0x02;
rx_tx_addr[2]=0x00;
hopping_frequency[0]=0x20;
hopping_frequency[0]=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;
#endif
}
static void __attribute__((unused)) KF606_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
}
uint16_t KF606_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(KF606_PACKET_PERIOD);
#endif
if(IS_BIND_IN_PROGRESS)
if(--bind_counter==0)
{
BIND_DONE;
XN297_SetTXAddr(rx_tx_addr, 3);
}
KF606_send_packet();
return KF606_PACKET_PERIOD;
}
uint16_t initKF606()
{
BIND_IN_PROGRESS; // autobind protocol
KF606_initialize_txid();
KF606_init();
hopping_frequency_no = 0;
bind_counter=KF606_BIND_COUNT;
return KF606_INITIAL_WAIT;
}
#endif

View File

@@ -279,12 +279,14 @@ uint16_t initKN()
packet_period = KN_WL_SENDING_PACKET_PERIOD;
bind_counter = KN_WL_BIND_COUNT;
packet_count = KN_WL_PACKET_SEND_COUNT;
seed = KN_WL_PACKET_SEND_COUNT * KN_WL_SENDING_PACKET_PERIOD;
}
else
{
packet_period = KN_FX_SENDING_PACKET_PERIOD;
bind_counter = KN_FX_BIND_COUNT;
packet_count = KN_FX_PACKET_SEND_COUNT;
seed = KN_FX_PACKET_SEND_COUNT * KN_FX_SENDING_PACKET_PERIOD;
}
kn_init();
phase = IS_BIND_IN_PROGRESS ? KN_PHASE_PRE_BIND : KN_PHASE_PRE_SEND;
@@ -318,6 +320,9 @@ uint16_t kn_callback()
case KN_PHASE_SENDING:
if(packet_sent >= packet_count)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(seed);
#endif
packet_sent = 0;
hopping_frequency_no++;
if(hopping_frequency_no >= KN_RF_CH_COUNT) hopping_frequency_no = 0;

View File

@@ -18,6 +18,7 @@
#if defined(MJXQ_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_nrf250k.h"
#define MJXQ_BIND_COUNT 150
#define MJXQ_PACKET_PERIOD 4000 // Timeout for callback in uSec
@@ -78,6 +79,7 @@ const uint8_t PROGMEM E010_map_rfchan[][2] = {
#define MJXQ_PAN_UP 0x04
#define MJXQ_TILT_DOWN 0x20
#define MJXQ_TILT_UP 0x10
static uint8_t __attribute__((unused)) MJXQ_pan_tilt_value()
{
// CH12_SW PAN // H26D
@@ -190,25 +192,35 @@ 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;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++ / 2]);
hopping_frequency_no %= 2 * MJXQ_RF_NUM_CHANNELS; // channels repeated
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
// Power on, TX mode, 2byte CRC and send packet
if (sub_protocol == H26D || sub_protocol == H26WH)
hopping_frequency_no++;
if (sub_protocol == E010 || sub_protocol == PHOENIX)
{
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WritePayload(packet, MJXQ_PACKET_SIZE);
XN297L_Hopping(hopping_frequency_no / 2);
XN297L_SetFreqOffset();
XN297L_SetPower();
XN297L_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_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();
}
NRF24L01_SetPower();
hopping_frequency_no %= 2 * MJXQ_RF_NUM_CHANNELS; // channels repeated
}
static void __attribute__((unused)) MJXQ_init()
@@ -225,30 +237,35 @@ static void __attribute__((unused)) MJXQ_init()
memcpy(hopping_frequency, "\x0a\x35\x42\x3d", MJXQ_RF_NUM_CHANNELS);
memcpy(addr, "\x6d\x6a\x73\x73\x73", MJXQ_ADDRESS_LENGTH);
}
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
if (sub_protocol == H26D || sub_protocol == H26WH)
if (sub_protocol == E010 || sub_protocol == PHOENIX)
{
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr, MJXQ_ADDRESS_LENGTH);
XN297L_Init();
XN297L_SetTXAddr(addr, sizeof(addr));
XN297L_HoppingCalib(MJXQ_RF_NUM_CHANNELS);
}
else
XN297_SetTXAddr(addr, MJXQ_ADDRESS_LENGTH);
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, MJXQ_PACKET_SIZE);
if (sub_protocol == E010 || sub_protocol == PHOENIX)
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250K
else
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
if (sub_protocol == H26D || sub_protocol == H26WH)
{
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr, MJXQ_ADDRESS_LENGTH);
}
else
XN297_SetTXAddr(addr, MJXQ_ADDRESS_LENGTH);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, MJXQ_PACKET_SIZE);
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
}
}
static void __attribute__((unused)) MJXQ_init2()
@@ -268,6 +285,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);
break;
case WLH08:
// do nothing
@@ -309,7 +327,12 @@ static void __attribute__((unused)) MJXQ_initialize_txid()
uint16_t MJXQ_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(MJXQ_PACKET_PERIOD);
#endif
MJXQ_send_packet(0);
}
else
{
if (bind_counter == 0)

View File

@@ -222,7 +222,12 @@ static void __attribute__((unused)) MT99XX_initialize_txid()
uint16_t MT99XX_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
MT99XX_send_packet();
}
else
{
if (bind_counter == 0)

View File

@@ -1,19 +1,19 @@
1,Flysky,Flysky,V9x9,V6x6,V912,CX20
2,Hubsan,H107,H301,H501
3,FrskyD
3,FrskyD,D8,Cloned
4,Hisky,Hisky,HK310
5,V2x2,V2x2,JXD506
6,DSM,DSM2-22,DSM2-11,DSMX-22,DSMX-11,AUTO
7,Devo
7,Devo,8CH,10CH,12CH,6CH,7CH
8,YD717,YD717,SKYWLKR,SYMAX4,XINXUN,NIHUI
9,KN,WLTOYS,FEILUN
10,SymaX,SYMAX,SYMAX5C
11,SLT,SLT_V1,SLT_V2,Q100,Q200,MR100
12,CX10,GREEN,BLUE,DM007,---,J3015_1,J3015_2,MK33041
13,CG023,CG023,YD829
14,Bayang,Bayang,H8S3D,X16_AH,IRDRONE
15,FrskyX,CH_16,CH_8,EU_16,EU_8
16,ESky
14,Bayang,Bayang,H8S3D,X16_AH,IRDRONE,DHD_D4
15,FrskyX,CH_16,CH_8,EU_16,EU_8,Cloned
16,ESky,Std,ET4
17,MT99xx,MT,H7,YZ,LS,FY805
18,MJXq,WLH08,X600,X800,H26D,E010,H26WH,PHOENIX
19,Shenqi
@@ -32,7 +32,7 @@
32,GW008
33,DM002
34,CABELL,CAB_V3,C_TELEM,-,-,-,-,F_SAFE,UNBIND
35,ESKY150
35,ESKY150,4CH,7CH
36,H8_3D,H8_3D,H20H,H20Mini,H30Mini
37,CORONA,COR_V1,COR_V2,FD_V3
38,CFlie
@@ -40,9 +40,31 @@
40,WFLY
41,BUGS
42,BUGSMINI,BUGSMINI,BUGS3H
43,Traxxas
43,Traxxas,RX6519
44,NCC1701
45,E01X,E012,E015,E016H
46,V911S
47,GD00X,V1,V2
63,Test
46,V911S,V911S,E119
47,GD00x,GD_V1,GD_V2
48,V761
49,KF606
50,Redpine,Fast,Slow
51,Potensic,A20
52,ZSX,280
53,Flyzone,FZ-410
54,Scanner
55,Frsky_RX,RX,CloneTX
56,AFHDS2A_RX
57,HoTT
58,FX816,P38
59,Bayang_RX
60,Pelikan
61,Tiger
62,XK,X450,X420
63,XN_DUMP,250K,1M,2M,AUTO
64,FrskyX2,CH_16,CH_8,EU_16,EU_8,Cloned
65,FrSkyR9,915MHz,868MHz,915_8ch,868_8ch
66,PROPEL,74-Z
67,LR12,LR12,LR12_6ch
68,Skyartec
69,ESKYv2,150V2
70,DSM_RX

View File

@@ -0,0 +1,367 @@
/*
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_NAMES)
const char STR_FLYSKY[] ="FlySky";
const char STR_HUBSAN[] ="Hubsan";
const char STR_FRSKYD[] ="FrSky D";
const char STR_HISKY[] ="Hisky";
const char STR_V2X2[] ="V2x2";
const char STR_DSM[] ="DSM";
const char STR_DSM_RX[] ="DSM_RX";
const char STR_DEVO[] ="Devo";
const char STR_YD717[] ="YD717";
const char STR_KN[] ="KN";
const char STR_SYMAX[] ="SymaX";
const char STR_SLT[] ="SLT";
const char STR_CX10[] ="CX10";
const char STR_CG023[] ="CG023";
const char STR_BAYANG[] ="Bayang";
const char STR_FRSKYL[] ="FrSky L";
const char STR_FRSKYX[] ="FrSky X";
const char STR_FRSKYX2[] ="FrSkyX2";
const char STR_ESKY[] ="ESky";
const char STR_MT99XX[] ="MT99XX";
const char STR_MJXQ[] ="MJXq";
const char STR_SHENQI[] ="Shenqi";
const char STR_FY326[] ="FY326";
const char STR_SFHSS[] ="SFHSS";
const char STR_J6PRO[] ="J6 Pro";
const char STR_JJRC345[] ="JJRC345";
const char STR_FQ777[] ="FQ777";
const char STR_ASSAN[] ="Assan";
const char STR_FRSKYV[] ="FrSky V";
const char STR_HONTAI[] ="Hontai";
const char STR_AFHDS2A[] ="FSky 2A";
const char STR_Q2X2[] ="Q2x2";
const char STR_WK2x01[] ="Walkera";
const char STR_Q303[] ="Q303";
const char STR_GW008[] ="GW008";
const char STR_DM002[] ="DM002";
const char STR_CABELL[] ="Cabell";
const char STR_ESKY150[] ="Esky150";
const char STR_ESKY150V2[] ="EskyV2";
const char STR_H8_3D[] ="H8 3D";
const char STR_CORONA[] ="Corona";
const char STR_CFLIE[] ="CFlie";
const char STR_HITEC[] ="Hitec";
const char STR_WFLY[] ="WFly";
const char STR_BUGS[] ="Bugs";
const char STR_BUGSMINI[] ="BugMini";
const char STR_TRAXXAS[] ="Traxxas";
const char STR_NCC1701[] ="NCC1701";
const char STR_E01X[] ="E01X";
const char STR_V911S[] ="V911S";
const char STR_GD00X[] ="GD00x";
const char STR_V761[] ="V761";
const char STR_KF606[] ="KF606";
const char STR_REDPINE[] ="Redpine";
const char STR_POTENSIC[] ="Potensi";
const char STR_ZSX[] ="ZSX";
const char STR_FLYZONE[] ="FlyZone";
const char STR_SCANNER[] ="Scanner";
const char STR_FRSKY_RX[] ="FrSkyRX";
const char STR_AFHDS2A_RX[] ="FS2A_RX";
const char STR_HOTT[] ="HoTT";
const char STR_FX816[] ="FX816";
const char STR_BAYANG_RX[] ="BayanRX";
const char STR_PELIKAN[] ="Pelikan";
const char STR_TIGER[] ="Tiger";
const char STR_XK[] ="XK";
const char STR_XN297DUMP[] ="XN297DP";
const char STR_FRSKYR9[] ="FrSkyR9";
const char STR_PROPEL[] ="PROPEL";
const char STR_SKYARTEC[] ="Skyartc";
const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20";
const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501";
const char STR_SUBTYPE_FRSKYD[] = "\x06""D8\0 ""Cloned";
const char STR_SUBTYPE_FRSKYX[] = "\x07""D16\0 ""D16 8ch""LBT(EU)""LBT 8ch""Cloned\0";
const char STR_SUBTYPE_HISKY[] = "\x05""Std\0 ""HK310";
const char STR_SUBTYPE_V2X2[] = "\x06""Std\0 ""JXD506";
const char STR_SUBTYPE_DSM[] = "\x06""2 22ms""2 11ms""X 22ms""X 11ms";
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";
const char STR_SUBTYPE_SYMAX[] = "\x03""Std""X5C";
const char STR_SUBTYPE_SLT[] = "\x06""V1_6ch""V2_8ch""Q100\0 ""Q200\0 ""MR100\0";
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";
const char STR_SUBTYPE_MT99[] = "\x06""MT99\0 ""H7\0 ""YZ\0 ""LS\0 ""FY805";
const char STR_SUBTYPE_MJXQ[] = "\x07""WLH08\0 ""X600\0 ""X800\0 ""H26D\0 ""E010\0 ""H26WH\0 ""Phoenix";
const char STR_SUBTYPE_FY326[] = "\x05""Std\0 ""FY319";
const char STR_SUBTYPE_HONTAI[] = "\x07""Std\0 ""JJRC X1""X5C1\0 ""FQ_951";
const char STR_SUBTYPE_AFHDS2A[] = "\x08""PWM,IBUS""PPM,IBUS""PWM,SBUS""PPM,SBUS";
const char STR_SUBTYPE_Q2X2[] = "\x04""Q222""Q242""Q282";
const char STR_SUBTYPE_WK2x01[] = "\x06""WK2801""WK2401""W6_5_1""W6_6_1""W6_HeL""W6_HeI";
const char STR_SUBTYPE_Q303[] = "\x06""Std\0 ""CX35\0 ""CX10D\0""CX10WD";
const char STR_SUBTYPE_CABELL[] = "\x07""V3\0 ""V3 Telm""-\0 ""-\0 ""-\0 ""-\0 ""F-Safe\0""Unbind\0";
const char STR_SUBTYPE_H83D[] = "\x07""Std\0 ""H20H\0 ""H20Mini""H30Mini";
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_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_FLYZONE[] = "\x05""FZ410";
const char STR_SUBTYPE_FX816[] = "\x03""P38";
const char STR_SUBTYPE_XN297DUMP[] = "\x07""250Kbps""1Mbps\0 ""2Mbps\0 ""Auto\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";
const char STR_SUBTYPE_XK[] = "\x04""X450""X420";
const char STR_SUBTYPE_FRSKYR9[] = "\x07""915MHz\0""868MHz\0""915 8ch""868 8ch";
const char STR_SUBTYPE_ESKY[] = "\x03""Std""ET4";
const char STR_SUBTYPE_PROPEL[] = "\x04""74-Z";
const char STR_SUBTYPE_FRSKY_RX[] = "\x07""RX\0 ""CloneTX";
const char STR_SUBTYPE_FRSKYL[] = "\x08""LR12\0 ""LR12 6ch";
const char STR_SUBTYPE_WFLY[] = "\x06""WFR0xS";
enum
{
OPTION_NONE,
OPTION_OPTION,
OPTION_RFTUNE,
OPTION_VIDFREQ,
OPTION_FIXEDID,
OPTION_TELEM,
OPTION_SRVFREQ,
OPTION_MAXTHR,
OPTION_RFCHAN
};
#define NO_SUBTYPE nullptr
const mm_protocol_definition multi_protocols[] = {
// Protocol number, Protocol String, Number of sub_protocols, Sub_protocol strings, Option type
#if defined(ASSAN_NRF24L01_INO)
{PROTO_ASSAN, STR_ASSAN, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(BAYANG_NRF24L01_INO)
{PROTO_BAYANG, STR_BAYANG, 5, STR_SUBTYPE_BAYANG, OPTION_TELEM },
#endif
#if defined(BAYANG_RX_NRF24L01_INO)
{PROTO_BAYANG_RX, STR_BAYANG_RX, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(BUGS_A7105_INO)
{PROTO_BUGS, STR_BUGS, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(BUGSMINI_NRF24L01_INO)
{PROTO_BUGSMINI, STR_BUGSMINI, 2, STR_SUBTYPE_BUGS_MINI, OPTION_NONE },
#endif
#if defined(CABELL_NRF24L01_INO)
{PROTO_CABELL, STR_CABELL, 8, STR_SUBTYPE_CABELL, OPTION_OPTION },
#endif
#if defined(CFLIE_NRF24L01_INO)
{PROTO_CFLIE, STR_CFLIE, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(E01X_NRF24L01_INO)
{PROTO_E01X, STR_E01X, 3, STR_SUBTYPE_E01X, OPTION_OPTION },
#endif
#if defined(CG023_NRF24L01_INO)
{PROTO_CG023, STR_CG023, 2, STR_SUBTYPE_CG023, OPTION_NONE },
#endif
#if defined(CORONA_CC2500_INO)
{PROTO_CORONA, STR_CORONA, 3, STR_SUBTYPE_CORONA, OPTION_RFTUNE },
#endif
#if defined(CX10_NRF24L01_INO)
{PROTO_CX10, STR_CX10, 7, STR_SUBTYPE_CX10, OPTION_NONE },
#endif
#if defined(DEVO_CYRF6936_INO)
{PROTO_DEVO, STR_DEVO, 5, STR_SUBTYPE_DEVO, OPTION_FIXEDID },
#endif
#if defined(DM002_NRF24L01_INO)
{PROTO_DM002, STR_DM002, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(DSM_CYRF6936_INO)
{PROTO_DSM, STR_DSM, 4, STR_SUBTYPE_DSM, OPTION_MAXTHR },
#endif
#if defined(DSM_RX_CYRF6936_INO)
{PROTO_DSM_RX, STR_DSM_RX, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(ESKY_NRF24L01_INO)
{PROTO_ESKY, STR_ESKY, 2, STR_SUBTYPE_ESKY, OPTION_NONE },
#endif
#if defined(ESKY150_NRF24L01_INO)
{PROTO_ESKY150, STR_ESKY150, 2, STR_SUBTYPE_ESKY150, OPTION_NONE },
#endif
#if defined(ESKY150V2_CC2500_INO)
{PROTO_ESKY150V2, STR_ESKY150V2, 1, STR_SUBTYPE_ESKY150V2, OPTION_RFTUNE },
#endif
#if defined(FLYSKY_A7105_INO)
{PROTO_FLYSKY, STR_FLYSKY, 5, STR_SUBTYPE_FLYSKY, OPTION_NONE },
#endif
#if defined(AFHDS2A_A7105_INO)
{PROTO_AFHDS2A, STR_AFHDS2A, 4, STR_SUBTYPE_AFHDS2A, OPTION_SRVFREQ },
#endif
#if defined(AFHDS2A_RX_A7105_INO)
{PROTO_AFHDS2A_RX, STR_AFHDS2A_RX,0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(FLYZONE_A7105_INO)
{PROTO_FLYZONE, STR_FLYZONE, 1, STR_SUBTYPE_FLYZONE, OPTION_NONE },
#endif
#if defined(FQ777_NRF24L01_INO)
{PROTO_FQ777, STR_FQ777, 0, NO_SUBTYPE, OPTION_NONE },
#endif
//OpenTX 2.3.x issue: DO NOT CHANGE ORDER below
#if defined(FRSKY_RX_CC2500_INO)
{PROTO_FRSKY_RX, STR_FRSKY_RX, 2, STR_SUBTYPE_FRSKY_RX, OPTION_RFTUNE },
#endif
#if defined(FRSKYD_CC2500_INO)
{PROTO_FRSKYD, STR_FRSKYD, 2, STR_SUBTYPE_FRSKYD, OPTION_RFTUNE },
#endif
#if defined(FRSKYV_CC2500_INO)
{PROTO_FRSKYV, STR_FRSKYV, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(FRSKYX_CC2500_INO)
{PROTO_FRSKYX, STR_FRSKYX, 5, STR_SUBTYPE_FRSKYX, OPTION_RFTUNE },
{PROTO_FRSKYX2, STR_FRSKYX2, 5, STR_SUBTYPE_FRSKYX, OPTION_RFTUNE },
#endif
//OpenTX 2.3.x issue: DO NOT CHANGE ORDER above
#if defined(FRSKYL_CC2500_INO)
{PROTO_FRSKYL, STR_FRSKYL, 2, STR_SUBTYPE_FRSKYL, OPTION_RFTUNE },
#endif
#if defined(FRSKYR9_SX1276_INO)
{PROTO_FRSKY_R9, STR_FRSKYR9, 4, STR_SUBTYPE_FRSKYR9, OPTION_NONE },
#endif
#if defined(FX816_NRF24L01_INO)
{PROTO_FX816, STR_FX816, 1, STR_SUBTYPE_FX816, OPTION_NONE },
#endif
#if defined(FY326_NRF24L01_INO)
{PROTO_FY326, STR_FY326, 2, STR_SUBTYPE_FY326, OPTION_NONE },
#endif
#if defined(GD00X_NRF24L01_INO)
{PROTO_GD00X, STR_GD00X, 2, STR_SUBTYPE_GD00X, OPTION_RFTUNE },
#endif
#if defined(GW008_NRF24L01_INO)
{PROTO_GW008, STR_GW008, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(H8_3D_NRF24L01_INO)
{PROTO_H8_3D, STR_H8_3D, 4, STR_SUBTYPE_H83D, OPTION_NONE },
#endif
#if defined(HISKY_NRF24L01_INO)
{PROTO_HISKY, STR_HISKY, 2, STR_SUBTYPE_HISKY, OPTION_NONE },
#endif
#if defined(HITEC_CC2500_INO)
{PROTO_HITEC, STR_HITEC, 3, STR_SUBTYPE_HITEC, OPTION_RFTUNE },
#endif
#if defined(HONTAI_NRF24L01_INO)
{PROTO_HONTAI, STR_HONTAI, 4, STR_SUBTYPE_HONTAI, OPTION_NONE },
#endif
#if defined(HOTT_CC2500_INO)
{PROTO_HOTT, STR_HOTT, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(HUBSAN_A7105_INO)
{PROTO_HUBSAN, STR_HUBSAN, 3, STR_SUBTYPE_HUBSAN, OPTION_VIDFREQ },
#endif
#if defined(J6PRO_CYRF6936_INO)
{PROTO_J6PRO, STR_J6PRO, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(JJRC345_NRF24L01_INO)
{PROTO_JJRC345, STR_JJRC345, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(KF606_NRF24L01_INO)
{PROTO_KF606, STR_KF606, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(KN_NRF24L01_INO)
{PROTO_KN, STR_KN, 2, STR_SUBTYPE_KN, OPTION_NONE },
#endif
#if defined(MJXQ_NRF24L01_INO)
{PROTO_MJXQ, STR_MJXQ, 7, STR_SUBTYPE_MJXQ, OPTION_RFTUNE },
#endif
#if defined(MT99XX_NRF24L01_INO)
{PROTO_MT99XX, STR_MT99XX, 5, STR_SUBTYPE_MT99, OPTION_NONE },
#endif
#if defined(NCC1701_NRF24L01_INO)
{PROTO_NCC1701, STR_NCC1701, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(PELIKAN_A7105_INO)
{PROTO_PELIKAN, STR_PELIKAN , 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(POTENSIC_NRF24L01_INO)
{PROTO_POTENSIC, STR_POTENSIC, 1, STR_SUBTYPE_POTENSIC, OPTION_NONE },
#endif
#if defined(PROPEL_NRF24L01_INO)
{PROTO_PROPEL, STR_PROPEL, 4, STR_SUBTYPE_PROPEL, OPTION_NONE },
#endif
#if defined(CX10_NRF24L01_INO)
{PROTO_Q2X2, STR_Q2X2, 3, STR_SUBTYPE_Q2X2, OPTION_NONE },
#endif
#if defined(Q303_NRF24L01_INO)
{PROTO_Q303, STR_Q303, 4, STR_SUBTYPE_Q303, OPTION_NONE },
#endif
#if defined(REDPINE_CC2500_INO)
{PROTO_REDPINE, STR_REDPINE, 2, STR_SUBTYPE_REDPINE, OPTION_RFTUNE },
#endif
#if defined(SCANNER_CC2500_INO)
// {PROTO_SCANNER, STR_SCANNER, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(SFHSS_CC2500_INO)
{PROTO_SFHSS, STR_SFHSS, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(SHENQI_NRF24L01_INO)
{PROTO_SHENQI, STR_SHENQI, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(SKYARTEC_CC2500_INO)
{PROTO_SKYARTEC, STR_SKYARTEC, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(SLT_NRF24L01_INO)
{PROTO_SLT, STR_SLT, 5, STR_SUBTYPE_SLT, OPTION_RFTUNE },
#endif
#if defined(SYMAX_NRF24L01_INO)
{PROTO_SYMAX, STR_SYMAX, 2, STR_SUBTYPE_SYMAX, OPTION_NONE },
#endif
#if defined(TIGER_NRF24L01_INO)
{PROTO_TIGER, STR_TIGER , 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(TRAXXAS_CYRF6936_INO)
{PROTO_TRAXXAS, STR_TRAXXAS, 1, STR_SUBTYPE_TRAXXAS, OPTION_NONE },
#endif
#if defined(V2X2_NRF24L01_INO)
{PROTO_V2X2, STR_V2X2, 2, STR_SUBTYPE_V2X2, OPTION_NONE },
#endif
#if defined(V761_NRF24L01_INO)
{PROTO_V761, STR_V761, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(V911S_NRF24L01_INO)
{PROTO_V911S, STR_V911S, 2, STR_SUBTYPE_V911S, OPTION_RFTUNE },
#endif
#if defined(WFLY_CYRF6936_INO)
{PROTO_WFLY, STR_WFLY, 1, STR_SUBTYPE_WFLY, OPTION_NONE },
#endif
#if defined(WK2x01_CYRF6936_INO)
{PROTO_WK2x01, STR_WK2x01, 6, STR_SUBTYPE_WK2x01, OPTION_NONE },
#endif
#if defined(XK_NRF24L01_INO)
{PROTO_XK, STR_XK , 2, STR_SUBTYPE_XK, OPTION_RFTUNE },
#endif
#if defined(XN297DUMP_NRF24L01_INO)
{PROTO_XN297DUMP, STR_XN297DUMP, 4, STR_SUBTYPE_XN297DUMP, OPTION_RFCHAN },
#endif
#if defined(YD717_NRF24L01_INO)
{PROTO_YD717, STR_YD717, 5, STR_SUBTYPE_YD717, OPTION_NONE },
#endif
#if defined(ZSX_NRF24L01_INO)
{PROTO_ZSX, STR_ZSX, 1, STR_SUBTYPE_ZSX, OPTION_NONE },
#endif
{0x00, nullptr, 0, nullptr, 0 }
};
#endif

View File

@@ -17,9 +17,9 @@
// Version
//******************
#define VERSION_MAJOR 1
#define VERSION_MINOR 2
#define VERSION_MINOR 3
#define VERSION_REVISION 1
#define VERSION_PATCH_LEVEL 39
#define VERSION_PATCH_LEVEL 1
//******************
// Protocols
@@ -74,7 +74,30 @@ enum PROTOCOLS
PROTO_E01X = 45, // =>NRF24L01
PROTO_V911S = 46, // =>NRF24L01
PROTO_GD00X = 47, // =>NRF24L01
PROTO_TEST = 63, // =>NRF24L01
PROTO_V761 = 48, // =>NRF24L01
PROTO_KF606 = 49, // =>NRF24L01
PROTO_REDPINE = 50, // =>CC2500
PROTO_POTENSIC = 51, // =>NRF24L01
PROTO_ZSX = 52, // =>NRF24L01
PROTO_FLYZONE = 53, // =>A7105
PROTO_SCANNER = 54, // =>CC2500
PROTO_FRSKY_RX = 55, // =>CC2500
PROTO_AFHDS2A_RX= 56, // =>A7105
PROTO_HOTT = 57, // =>CC2500
PROTO_FX816 = 58, // =>NRF24L01
PROTO_BAYANG_RX = 59, // =>NRF24L01
PROTO_PELIKAN = 60, // =>A7105
PROTO_TIGER = 61, // =>NRF24L01
PROTO_XK = 62, // =>NRF24L01
PROTO_XN297DUMP = 63, // =>NRF24L01
PROTO_FRSKYX2 = 64, // =>CC2500
PROTO_FRSKY_R9 = 65, // =>SX1276
PROTO_PROPEL = 66, // =>NRF24L01
PROTO_FRSKYL = 67, // =>CC2500
PROTO_SKYARTEC = 68, // =>CC2500
PROTO_ESKY150V2 = 69, // =>CC2500+NRF24L01
PROTO_DSM_RX = 70, // =>CYRF6936
PROTO_JJRC345 = 71, // =>NRF24L01
};
enum Flysky
@@ -85,6 +108,10 @@ enum Flysky
V912 = 3,
CX20 = 4,
};
enum Flyzone
{
FZ410 = 0,
};
enum Hubsan
{
H107 = 0,
@@ -166,6 +193,7 @@ enum BAYANG
H8S3D = 1,
X16_AH = 2,
IRDRONE = 3,
DHD_D4 = 4,
};
enum MT99XX
{
@@ -185,12 +213,18 @@ enum MJXQ
H26WH = 5,
PHOENIX = 6,
};
enum FRSKYD
{
FRSKYD = 0,
DCLONE = 1,
};
enum FRSKYX
{
CH_16 = 0,
CH_8 = 1,
EU_16 = 2,
EU_8 = 3,
XCLONE = 4,
};
enum HONTAI
{
@@ -267,6 +301,62 @@ enum BUGSMINI
BUGSMINI= 0,
BUGS3H = 1,
};
enum REDPINE
{
RED_FAST= 0,
RED_SLOW= 1,
};
enum TRAXXAS
{
RX6519 = 0,
};
enum ESKY150
{
ESKY150_4CH = 0,
ESKY150_7CH = 1,
};
enum V911S
{
V911S_STD = 0,
V911S_E119 = 1,
};
enum XK
{
X450 = 0,
X420 = 1,
};
enum XN297DUMP
{
XN297DUMP_250K = 0,
XN297DUMP_1M = 1,
XN297DUMP_2M = 2,
XN297DUMP_AUTO = 3,
};
enum FRSKY_R9
{
R9_915 = 0,
R9_868 = 1,
R9_915_8CH = 2,
R9_868_8CH = 3,
};
enum ESKY
{
ESKY_STD = 0,
ESKY_ET4 = 1,
};
enum FRSKY_RX
{
FRSKY_RX = 0,
FRSKY_CLONE = 1,
};
enum FRSKYL
{
LR12 = 0,
LR12_6CH = 1,
};
#define NONE 0
#define P_HIGH 1
#define P_LOW 0
@@ -275,16 +365,16 @@ enum BUGSMINI
struct PPM_Parameters
{
uint8_t protocol : 6;
uint8_t sub_proto : 3;
uint8_t rx_num : 4;
uint8_t power : 1;
uint8_t autobind : 1;
uint8_t option;
uint8_t protocol;
uint8_t sub_proto : 3;
uint8_t rx_num : 6;
uint8_t power : 1;
uint8_t autobind : 1;
int8_t option;
uint32_t chan_order;
};
// Telemetry
enum MultiPacketTypes
{
MULTI_TELEMETRY_STATUS = 1,
@@ -293,15 +383,25 @@ enum MultiPacketTypes
MULTI_TELEMETRY_DSM = 4,
MULTI_TELEMETRY_DSMBIND = 5,
MULTI_TELEMETRY_AFHDS2A = 6,
MULTI_TELEMETRY_CONFIG = 7,
MULTI_TELEMETRY_REUSE_1 = 7,
MULTI_TELEMETRY_SYNC = 8,
MULTI_TELEMETRY_SPORT_POLLING = 9,
MULTI_TELEMETRY_REUSE_2 = 9,
MULTI_TELEMETRY_HITEC = 10,
MULTI_TELEMETRY_SCANNER = 11,
MULTI_TELEMETRY_AFHDS2A_AC = 12,
MULTI_TELEMETRY_RX_CHANNELS = 13,
MULTI_TELEMETRY_HOTT = 14,
};
// Macros
#define NOP() __asm__ __volatile__("nop")
//***************
//*** Tests ***
//***************
#define IS_FAILSAFE_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_SFHSS || protocol==PROTO_WK2x01 || protocol== PROTO_HOTT || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKY_R9)
#define IS_CHMAP_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_SFHSS || protocol==PROTO_WK2x01 || protocol== PROTO_DSM || protocol==PROTO_SLT || protocol==PROTO_FLYSKY || protocol==PROTO_ESKY || protocol==PROTO_J6PRO || protocol==PROTO_PELIKAN || protocol==PROTO_SKYARTEC || protocol==PROTO_ESKY150V2 || protocol==PROTO_DSM_RX)
//***************
//*** Flags ***
//***************
@@ -357,6 +457,7 @@ enum MultiPacketTypes
#define TX_RX_PAUSE_on protocol_flags2 |= _BV(4)
#define IS_TX_RX_PAUSE_on ( ( protocol_flags2 & _BV(4) ) !=0 )
#define IS_TX_PAUSE_on ( ( protocol_flags2 & (_BV(4)|_BV(3)) ) !=0 )
#define IS_TX_PAUSE_off ( ( protocol_flags2 & (_BV(4)|_BV(3)) ) ==0 )
//Signal OK
#define INPUT_SIGNAL_off protocol_flags2 &= ~_BV(5)
#define INPUT_SIGNAL_on protocol_flags2 |= _BV(5)
@@ -372,6 +473,29 @@ enum MultiPacketTypes
#define WAIT_BIND_on protocol_flags2 |= _BV(7)
#define IS_WAIT_BIND_on ( ( protocol_flags2 & _BV(7) ) !=0 )
#define IS_WAIT_BIND_off ( ( protocol_flags2 & _BV(7) ) ==0 )
//Incoming telemetry data buffer
#define DATA_BUFFER_LOW_off protocol_flags3 &= ~_BV(0)
#define DATA_BUFFER_LOW_on protocol_flags3 |= _BV(0)
#define IS_DATA_BUFFER_LOW_on ( ( protocol_flags3 & _BV(0) ) !=0 )
#define IS_DATA_BUFFER_LOW_off ( ( protocol_flags3 & _BV(0) ) ==0 )
#define SEND_MULTI_STATUS_off protocol_flags3 &= ~_BV(1)
#define SEND_MULTI_STATUS_on protocol_flags3 |= _BV(1)
#define IS_SEND_MULTI_STATUS_on ( ( protocol_flags3 & _BV(1) ) !=0 )
#define IS_SEND_MULTI_STATUS_off ( ( protocol_flags3 & _BV(1) ) ==0 )
#define DISABLE_CH_MAP_off protocol_flags3 &= ~_BV(2)
#define DISABLE_CH_MAP_on protocol_flags3 |= _BV(2)
#define IS_DISABLE_CH_MAP_on ( ( protocol_flags3 & _BV(2) ) !=0 )
#define IS_DISABLE_CH_MAP_off ( ( protocol_flags3 & _BV(2) ) ==0 )
#define DISABLE_TELEM_off protocol_flags3 &= ~_BV(3)
#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 )
//LBT power
#define LBT_POWER_off protocol_flags3 &= ~_BV(7)
#define LBT_POWER_on protocol_flags3 |= _BV(7)
#define IS_LBT_POWER_on ( ( protocol_flags3 & _BV(7) ) !=0 )
#define IS_LBT_POWER_off ( ( protocol_flags3 & _BV(7) ) ==0 )
// Failsafe
#define FAILSAFE_CHANNEL_HOLD 2047
@@ -380,15 +504,16 @@ enum MultiPacketTypes
//********************
//** Debug messages **
//********************
#if defined(STM32_BOARD) && defined (DEBUG_SERIAL)
#if defined(STM32_BOARD) && (defined (DEBUG_SERIAL) || defined (ARDUINO_MULTI_DEBUG))
uint16_t debug_time=0;
#define debug(msg, ...) {char debug_buf[64]; sprintf(debug_buf, msg, ##__VA_ARGS__); Serial.write(debug_buf);}
#define debugln(msg, ...) {char debug_buf[64]; sprintf(debug_buf, msg "\r\n", ##__VA_ARGS__); Serial.write(debug_buf);}
#define debug_time(msg) { uint16_t debug_time_TCNT1=TCNT1; debug_time=debug_time_TCNT1-debug_time; debug(msg "%u", debug_time>>1); debug_time=debug_time_TCNT1; }
#define debugln_time(msg) { uint16_t debug_time_TCNT1=TCNT1; debug_time=debug_time_TCNT1-debug_time; debug(msg "%u\r\n", debug_time>>1); debug_time=debug_time_TCNT1; }
#else
#define debug(...) { }
#define debugln(...) { }
#define debug_time(...) { }
#define debugln_time(...) { }
#undef DEBUG_SERIAL
#endif
@@ -494,6 +619,7 @@ enum CC2500_POWER
CC2500_POWER_17 = 0xFF // +1dbm
};
#define CC2500_HIGH_POWER CC2500_POWER_17
#define CC2500_LBT_POWER CC2500_POWER_14
#define CC2500_LOW_POWER CC2500_POWER_13
#define CC2500_RANGE_POWER CC2500_POWER_1
#define CC2500_BIND_POWER CC2500_POWER_1
@@ -540,74 +666,107 @@ enum {
#define EEPROM_ID_VALID_OFFSET 20 // 1 byte flag that ID is valid
#define MODELMODE_EEPROM_OFFSET 30 // Autobind mode, 1 byte per model, end is 30+16=46
#define AFHDS2A_EEPROM_OFFSET 50 // RX ID, 4 bytes per model id, end is 50+64=114
#define BUGS_EEPROM_OFFSET 114 // TX ID, 4 bytes per model id, end is 114+64=178
#define BUGSMINI_EEPROM_OFFSET 178 // RX ID, 2 bytes per model id, end is 178+32=210
//#define CONFIG_EEPROM_OFFSET 210 // Current configuration of the multimodule
#define BUGS_EEPROM_OFFSET 114 // RX ID, 2 bytes per model id, end is 114+32=146
#define BUGSMINI_EEPROM_OFFSET 146 // RX ID, 2 bytes per model id, end is 146+32=178
#define FRSKY_RX_EEPROM_OFFSET 178 // (1) format + (3) TX ID + (1) freq_tune + (47) channels, 52 bytes, end is 178+52=230
#define AFHDS2A_RX_EEPROM_OFFSET 230 // (4) TX ID + (16) channels, 20 bytes, end is 230+20=250
#define AFHDS2A_EEPROM_OFFSET2 250 // RX ID, 4 bytes per model id, end is 250+192=442
#define HOTT_EEPROM_OFFSET 442 // RX ID, 5 bytes per model id, end is 320+442=762
#define BAYANG_RX_EEPROM_OFFSET 762 // (5) TX ID + (4) channels, 9 bytes, end is 771
#define FRSKYD_CLONE_EEPROM_OFFSET 771 // (1) format + (3) TX ID + (47) channels, 51 bytes, end is 822
#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
//****************************************
//*** MULTI protocol serial definition ***
//****************************************
/*
**************************
***************************
16 channels serial protocol
**************************
***************************
Serial: 100000 Baud 8e2 _ xxxx xxxx p --
Total of 26 bytes
Stream[0] = 0x55 sub_protocol values are 0..31 Stream contains channels
Stream[0] = 0x54 sub_protocol values are 32..63 Stream contains channels
Stream[0] = 0x57 sub_protocol values are 0..31 Stream contains failsafe
Stream[0] = 0x56 sub_protocol values are 32..63 Stream contains failsafe
header
Total of 26 bytes for protocol V1, variable length 27..36 for protocol V2
Stream[0] = header
0x55 sub_protocol values are 0..31 Stream contains channels
0x54 sub_protocol values are 32..63 Stream contains channels
0x57 sub_protocol values are 0..31 Stream contains failsafe
0x56 sub_protocol values are 32..63 Stream contains failsafe
Stream[1] = sub_protocol|BindBit|RangeCheckBit|AutoBindBit;
sub_protocol is 0..31 (bits 0..4), value should be added with 32 if Stream[0] = 0x54
=> Reserved 0
Flysky 1
Hubsan 2
FrskyD 3
Hisky 4
V2x2 5
DSM 6
Devo 7
YD717 8
KN 9
SymaX 10
SLT 11
CX10 12
CG023 13
Bayang 14
FrskyX 15
ESky 16
MT99XX 17
MJXQ 18
SHENQI 19
FY326 20
SFHSS 21
J6PRO 22
FQ777 23
ASSAN 24
FrskyV 25
HONTAI 26
OpenLRS 27
AFHDS2A 28
Q2X2 29
WK2x01 30
Q303 31
GW008 32
DM002 33
CABELL 34
ESKY150 35
H8_3D 36
CORONA 37
CFlie 38
Hitec 39
WFLY 40
BUGS 41
BUGSMINI 42
TRAXXAS 43
NCC1701 44
E01X 45
V911S 46
GD00X 47
sub_protocol is 0..31 (bits 0..4), value should be added with 32 if Stream[0] = 0x54 | 0x56
Reserved 0
Flysky 1
Hubsan 2
FrskyD 3
Hisky 4
V2x2 5
DSM 6
Devo 7
YD717 8
KN 9
SymaX 10
SLT 11
CX10 12
CG023 13
Bayang 14
FrskyX 15
ESky 16
MT99XX 17
MJXQ 18
SHENQI 19
FY326 20
SFHSS 21
J6PRO 22
FQ777 23
ASSAN 24
FrskyV 25
HONTAI 26
OpenLRS 27
AFHDS2A 28
Q2X2 29
WK2x01 30
Q303 31
GW008 32
DM002 33
CABELL 34
ESKY150 35
H8_3D 36
CORONA 37
CFlie 38
Hitec 39
WFLY 40
BUGS 41
BUGSMINI 42
TRAXXAS 43
NCC1701 44
E01X 45
V911S 46
GD00X 47
V761 48
KF606 49
REDPINE 50
POTENSIC 51
ZSX 52
FLYZONE 53
SCANNER 54
FRSKY_RX 55
AFHDS2A_RX 56
HOTT 57
FX816 58
BAYANG_RX 59
PELIKAN 60
TIGER 61
XK 62
XN297DUMP 63
FRSKYX2 64
FRSKY_R9 65
PROPEL 66
FRSKYL 67
SKYARTEC 68
ESKY150V2 69
DSM_RX 70
JJRC345 71
BindBit=> 0x80 1=Bind/0=No
AutoBindBit=> 0x40 1=Yes /0=No
RangeCheck=> 0x20 1=Yes /0=No
@@ -665,6 +824,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
H8S3D 1
X16_AH 2
IRDRONE 3
DHD_D4 4
sub_protocol==MT99XX
MT99 0
H7 1
@@ -679,11 +839,21 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
E010 4
H26WH 5
PHOENIX 6
sub_protocol==FRSKYD
FRSKYD 0
DCLONE 1
sub_protocol==FRSKYX
CH_16 0
CH_8 1
EU_16 2
EU_8 3
XCLONE 4
sub_protocol==FRSKYX2
CH_16 0
CH_8 1
EU_16 2
EU_8 3
XCLONE 4
sub_protocol==HONTAI
HONTAI 0
JJRCX1 1
@@ -743,6 +913,34 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
sub_protocol==GD00X
GD_V1 0
GD_V2 1
sub_protocol==REDPINE
RED_FAST 0
RED_SLOW 1
sub_protocol==TRAXXAS
RX6519 0
sub_protocol==ESKY150
ESKY150_4CH 0
ESKY150_7CH 1
sub_protocol==V911S
V911S_STD 0
V911S_E119 1
sub_protocol==XK
X450 0
X420 1
sub_protocol==FRSKY_R9
R9_915 0
R9_868 1
R9_915_8CH 2
R9_868_8CH 3
sub_protocol==ESKY
ESKY_STD 0
ESKY_ET4 1
sub_protocol==FRSKY_RX
FRSKY_RX 0
FRSKY_CLONE 1
sub_protocol==FRSKYL
LR12 0
LR12_6CH 1
Power value => 0x80 0=High/1=Low
Stream[3] = option_protocol;
@@ -756,7 +954,19 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
2047 +125%
Values are concatenated to fit in 22 bytes like in SBUS protocol.
Failsafe values have exactly the same range/values than normal channels except the extremes where
0=hold, 2047=no pulse. If failsafe is not set or RX then failsafe packets should not be sent.
0=no pulse, 2047=hold. If failsafe is not set or RX then failsafe packets should not be sent.
Stream[26] = sub_protocol bits 6 & 7|RxNum bits 4 & 5|Telemetry_Invert 3|Future_Use 2|Disable_Telemetry 1|Disable_CH_Mapping 0
sub_protocol is 0..255 (bits 0..5 + bits 6..7)
RxNum value is 0..63 (bits 0..3 + bits 4..5)
Telemetry_Invert => 0x08 0=normal, 1=invert
Future_Use => 0x04 0= , 1=
Disable_Telemetry => 0x02 0=enable, 1=disable
Disable_CH_Mapping => 0x01 0=enable, 1=disable
Stream[27.. 35] = between 0 and 9 bytes for additional protocol data
Protocol specific use:
FrSkyX and FrSkyX2: Stream[27] during bind Telem on=0x00,off=0x01 | CH1-8=0x00,CH9-16=0x02
FrSkyX and FrSkyX2: Stream[27..34] during normal operation unstuffed SPort data to be sent
HoTT: Stream[27] 1 byte for telemetry type
*/
/*
Multimodule Status
@@ -776,7 +986,9 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
0x04 = Protocol is valid
0x08 = Module is in binding mode
0x10 = Module waits a bind event to load the protocol
0x20 = Failsafe supported by currently running protocol
0x20 = Current protocol supports failsafe
0x40 = Current protocol supports disable channel mapping
0x80 = Data buffer is almost full
[3] major
[4] minor
[5] revision
@@ -810,24 +1022,42 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
[4] Flags
0x01 = Input signal detected
0x02 = Serial mode enabled
0x04 = protocol is valid
0x08 = module is in binding mode
0x10 = module waits a bind event to load the protocol
0x04 = Protocol is valid
0x08 = Module is in binding mode
0x10 = Module waits a bind event to load the protocol
0x20 = Current protocol supports failsafe
0x40 = Current protocol supports disable channel mapping
0x80 = Data buffer is almost full
[5] major
[6] minor
[7] revision
[8] patchlevel,
version of multi code, should be displayed as major.minor.revision.patchlevel
[8] patchlevel
version of multi code, should be displayed as major.minor.revision.patchlevel
[9] channel order: CH4|CH3|CH2|CH1 with CHx value A=0,E=1,T=2,R=3
[10] Next valid protocol number, can be used to skip invalid protocols
[11] Prev valid protocol number, can be used to skip invalid protocols
[12..18] Protocol name [7], not null terminated if prototcol len == 7
[19>>4] Option text to be displayed:
OPTION_NONE 0
OPTION_OPTION 1
OPTION_RFTUNE 2
OPTION_VIDFREQ 3
OPTION_FIXEDID 4
OPTION_TELEM 5
OPTION_SRVFREQ 6
OPTION_MAXTHR 7
OPTION_RFCHAN 8
[19&0x0F] Number of sub protocols
[20..27] Sub protocol name [8], not null terminated if sub prototcol len == 8
If the current protocol is invalid [12..27] are all 0x00.
more information can be added by specifing a longer length of the type, the TX will just ignore these bytes
Type 0x02 Frksy S.port telemetry
Type 0x03 Frsky Hub telemetry
*No* usual frsky byte stuffing and without start/stop byte (0x7e)
Type 0x04 Spektrum telemetry data
data[0] TX RSSI
data[1-15] telemetry data
@@ -838,11 +1068,24 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
technically DSM bind data is only 10 bytes but multi sends 16
like with telemtery, check length field)
Type 0x06 Flysky AFHDS2 telemetry data
Type 0x06 Flysky AFHDS2 telemetry data type 0xAA
length: 29
data[0] = RSSI value
data[1-28] telemetry data
Type 0x08 Input synchronisation
Informs the TX about desired rate and current delay
length: 4
data[0-1] Desired refresh rate in ??s
data[2-3] Time (??s) between last serial servo input received and servo input needed (lateness), TX should adjust its
sending time to minimise this value.
data[4] Interval of this message in ms
data[5] Input delay target in 10??s
Note that there are protocols (AFHDS2A) that have a refresh rate that is smaller than the maximum achievable
refresh rate via the serial protocol, in this case, the TX should double the rate and also subract this
refresh rate from the input lag if the input lag is more than the desired refresh rate.
The remote should try to get to zero of (inputdelay+target*10).
Type 0x0A Hitec telemetry data
length: 8
data[0] = TX RSSI value
@@ -851,4 +1094,30 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
data[3-7] telemetry data
Full description at the bottom of Hitec_cc2500.ino
Type 0x0B Spectrum Scanner telemetry data
length: 6
data[0] = start channel (2400 + x*0.333 Mhz)
data[1-5] power levels
Type 0x0C Flysky AFHDS2 telemetry data type 0xAC
length: 29
data[0] = RSSI value
data[1-28] telemetry data
Type 0x0D RX channels forwarding
length: variable
data[0] = received packets per second
data[1] = rssi
data[2] = start channel
data[3] = number of channels to follow
data[4-]= packed channels data, 11 bit per channel
Type 0x0E HoTT telemetry
length: 14
data[0] = TX_RSSI
data[1] = TX_LQI
data[2] = type
data[3] = page
data[4-13] = data
*/

File diff suppressed because it is too large Load Diff

View File

@@ -197,6 +197,9 @@ uint16_t NCC_callback()
phase = NCC_BIND_TX2;
return NCC_PACKET_INTERVAL - NCC_WRITE_WAIT;
case NCC_TX3:
#ifdef MULTI_SYNC
telemetry_set_input_sync(NCC_PACKET_INTERVAL);
#endif
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // RX fifo data ready
NRF24L01_ReadPayload(packet, NCC_RX_PACKET_LEN);
@@ -268,9 +271,6 @@ uint16_t initNCC(void)
hopping_frequency_no=4; // start with bind
NCC_init();
phase=NCC_BIND_TX1;
#ifdef NCC1701_HUB_TELEMETRY
init_frskyd_link_telemetry();
#endif
return 10000;
}

View File

@@ -172,6 +172,10 @@ void NRF24L01_SetPower()
if(prev_power != power)
{
rf_setup = (rf_setup & 0xF9) | (power << 1);
if(power==3)
rf_setup |=0x01; // Si24r01 full power, unused bit for NRF
else
rf_setup &=0xFE;
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
prev_power=power;
}
@@ -194,8 +198,6 @@ void NRF24L01_SetTxRxMode(enum TXRX_State mode)
if (mode == RX_EN)
{
NRF_CE_off;
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // reset the flag(s)
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0F); // switch to RX 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));
@@ -251,26 +253,52 @@ uint8_t xn297_tx_addr[5];
uint8_t xn297_rx_addr[5];
uint8_t xn297_crc = 0;
static 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};
// 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};
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};
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
static uint8_t bit_reverse(uint8_t b_in)
{
@@ -365,8 +393,7 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
for (uint8_t i = 0; i < len; ++i)
{
// bit-reverse bytes in packet
uint8_t b_out = bit_reverse(msg[i]);
buf[last] = b_out;
buf[last] = bit_reverse(msg[i]);
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[xn297_addr_len+i];
last++;
@@ -387,8 +414,7 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
NRF24L01_WritePayload(buf, last);
}
void XN297_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack, uint16_t crc_xorout)
void XN297_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
{
uint8_t packet[32];
uint8_t scramble_index=0;
@@ -444,7 +470,10 @@ void XN297_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack, uint16
for (uint8_t i = offset; i < last; ++i)
crc = crc16_update(crc, packet[i], 8);
crc = crc16_update(crc, packet[last] & 0xc0, 2);
crc ^= crc_xorout;
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);
@@ -480,7 +509,7 @@ boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
//process address
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
uint8_t b_in=xn297_tx_addr[xn297_addr_len-i-1];
uint8_t b_in=xn297_rx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
b_in ^= xn297_scramble[i];
crc = crc16_update(crc, b_in, 8);
@@ -500,10 +529,13 @@ boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
}
uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
{
{ //!!! Don't forget do a +2 and if using CRC add +2 on any of the used NRF24L01_11_RX_PW_Px !!!
uint8_t buffer[32];
uint8_t pcf_size; // pcf payload size
NRF24L01_ReadPayload(buffer, len+2); // pcf + payload
if (xn297_crc)
NRF24L01_ReadPayload(buffer, len+4); // Read pcf + payload + CRC
else
NRF24L01_ReadPayload(buffer, len+2); // Read pcf + payload
pcf_size = buffer[0];
if(xn297_scramble_enabled)
pcf_size ^= xn297_scramble[xn297_addr_len];
@@ -515,7 +547,35 @@ uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
msg[i] ^= bit_reverse((xn297_scramble[xn297_addr_len+i+1] << 2) |
(xn297_scramble[xn297_addr_len+i+2] >> 6));
}
return pcf_size;
if (!xn297_crc)
return pcf_size; // No CRC so OK by default...
// Calculate CRC
uint16_t 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];
crc = crc16_update(crc, b_in, 8);
}
//process payload
for (uint8_t i = 0; i < len+1; ++i)
crc = crc16_update(crc, buffer[i], 8);
crc = crc16_update(crc, buffer[len+1] & 0xc0, 2);
//xorout
if (xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
#ifdef XN297DUMP_NRF24L01_INO
else
crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
#endif
uint16_t crcxored=(buffer[len+1]<<10)|(buffer[len+2]<<2)|(buffer[len+3]>>6) ;
if( crc == crcxored)
return pcf_size; // CRC OK
return 0; // CRC NOK
}
// End of XN297 emulation

View File

@@ -0,0 +1,472 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef NRF24L01_INSTALLED
#include "iface_nrf250k.h"
static void __attribute__((unused)) XN297L_Init()
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
debugln("Using NRF");
PE1_on; //NRF24L01 antenna RF3 by default
PE2_off; //NRF24L01 antenna RF3 by default
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_FlushTx();
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_SetBitrate(NRF24L01_BR_250K); // 250Kbps
NRF24L01_SetPower();
return;
}
//CC2500
#ifdef CC2500_INSTALLED
debugln("Using CC2500");
PE1_off; // antenna RF2
PE2_on;
CC2500_Reset();
CC2500_Strobe(CC2500_SIDLE);
// Address Config = No address check
// Base Frequency = 2400
// CRC Autoflush = false
// CRC Enable = false
// Channel Spacing = 333.251953
// Data Format = Normal mode
// Data Rate = 249.939
// Deviation = 126.953125
// Device Address = 0
// Manchester Enable = false
// Modulated = true
// Modulation Format = GFSK
// Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word
// RX Filter BW = 203.125000
// Sync Word Qualifier Mode = No preamble/sync
// TX Power = 0
// Whitening = false
// Fast Frequency Hopping - no PLL auto calibration
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
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, 0xC3); // Frequency Control Word, Low Byte
CC2500_WriteReg(CC2500_10_MDMCFG4, 0x8D); // Modem Configuration
CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration
CC2500_WriteReg(CC2500_12_MDMCFG2, 0x10); // Modem Configuration
CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // Modem Configuration
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
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
#endif
}
static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t* addr, uint8_t len)
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
XN297_SetTXAddr(addr,len);
return;
}
//CC2500
#ifdef CC2500_INSTALLED
if (len > 5) len = 5;
if (len < 3) len = 3;
xn297_addr_len = len;
memcpy(xn297_tx_addr, addr, len);
#endif
}
static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t len)
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
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);
return;
}
//CC2500
#ifdef CC2500_INSTALLED
uint8_t buf[32];
uint8_t last = 0;
uint8_t i;
static const uint16_t initial = 0xb5d2;
// 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
uint16_t crc = initial;
for (uint8_t i = 0; i < last; ++i)
crc = crc16_update(crc, 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);
#endif
}
static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
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);
return;
}
//CC2500
#ifdef CC2500_INSTALLED
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
buf[last++] = 0x55;
}
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)
{
uint8_t offset = xn297_addr_len < 4 ? 1 : 0;
uint16_t crc = 0xb5d2;
for (uint8_t i = offset; i < last; ++i)
crc = crc16_update(crc, buf[i], 8);
crc = crc16_update(crc, 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);
#endif
}
static void __attribute__((unused)) XN297L_HoppingCalib(uint8_t num_freq)
{ //calibrate hopping frequencies
#ifdef CC2500_INSTALLED
if(option==0)
#endif
return; //NRF
#ifdef CC2500_INSTALLED
for (uint8_t i = 0; i < num_freq; i++)
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[i]*3);
CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);
calData[i]=CC2500_ReadReg(CC2500_25_FSCAL1);
}
#endif
}
static void __attribute__((unused)) XN297L_Hopping(uint8_t index)
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[index]);
return;
}
#ifdef CC2500_INSTALLED
// spacing is 333.25 kHz, must multiply xn297 channel by 3
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[index] * 3);
// set PLL calibration
CC2500_WriteReg(CC2500_25_FSCAL1, calData[index]);
#endif
}
static void __attribute__((unused)) XN297L_RFChannel(uint8_t number)
{ //change channel
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
NRF24L01_WriteReg(NRF24L01_05_RF_CH, number);
return;
}
#ifdef CC2500_INSTALLED
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, number*3);
CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);
#endif
}
static void __attribute__((unused)) XN297L_SetPower()
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
NRF24L01_SetPower();
return;
}
#ifdef CC2500_INSTALLED
CC2500_SetPower();
#endif
}
static void __attribute__((unused)) XN297L_SetFreqOffset()
{ // Frequency offset
#ifdef CC2500_INSTALLED
if(option==0 && prev_option==0)
#endif
return; //NRF
#ifdef CC2500_INSTALLED
if (prev_option != option)
{
if(prev_option==0 || option==0)
CHANGE_PROTOCOL_FLAG_on;
prev_option = option;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
}
#endif
}
static void __attribute__((unused)) NRF250K_SetTXAddr(uint8_t* addr, uint8_t len)
{
if (len > 5) len = 5;
if (len < 3) len = 3;
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr, len);
return;
}
//CC2500
#ifdef CC2500_INSTALLED
xn297_addr_len = len;
memcpy(xn297_tx_addr, addr, len);
#endif
}
static void __attribute__((unused)) NRF250K_WritePayload(uint8_t* msg, uint8_t len)
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
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);
return;
}
//CC2500
#ifdef CC2500_INSTALLED
#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(xn297_tx_addr[xn297_addr_len - 1] & 0x80)
buf[0]=0xAA;
else
buf[0]=0x55;
last++;
// address
for (i = 0; i < xn297_addr_len; ++i)
buf[last++] = xn297_tx_addr[xn297_addr_len - i - 1];
// payload
for (i = 0; i < len; ++i)
buf[last++] = msg[i];
// crc
uint16_t crc = 0xffff;
for (uint8_t i = 1; i < last; ++i)
crc = crc16_update(crc, 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
}
static boolean __attribute__((unused)) NRF250K_IsPacketSent()
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{ //NRF
return NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS);
}
return true; // don't know on the CC2500 how to detect if the packet has been transmitted...
}
#endif

View File

@@ -0,0 +1,128 @@
/*
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(POTENSIC_NRF24L01_INO)
#include "iface_nrf24l01.h"
//#define FORCE_POTENSIC_ORIGINAL_ID
#define POTENSIC_PACKET_PERIOD 4100 // Timeout for callback in uSec
#define POTENSIC_INITIAL_WAIT 500
#define POTENSIC_PACKET_SIZE 10
#define POTENSIC_BIND_COUNT 400
#define POTENSIC_RF_NUM_CHANNELS 4
static void __attribute__((unused)) POTENSIC_set_checksum()
{
uint8_t checksum = packet[1];
for(uint8_t i=2; i<POTENSIC_PACKET_SIZE-2; i++)
checksum += packet[i];
packet[8] |= checksum & 0x0f;
}
static void __attribute__((unused)) POTENSIC_send_packet()
{
packet[8]=0;
if(IS_BIND_IN_PROGRESS)
{
packet[0] = 0x61;
memcpy(&packet[1],rx_tx_addr,5);
packet[6] = 0x20;
packet[7] = 0xC0;
}
else
{
packet[0] = 0x64;
// Deadband is needed on throttle to emulate the spring to neutral otherwise the quad behaves weirdly, 160 gives +-20%
packet[1] = convert_channel_8b_limit_deadband(THROTTLE,0x00,0x19,0x32,160)<<1; // Throttle 00..19..32 *2
uint8_t elevator=convert_channel_8b(ELEVATOR)>>3;
packet[2] = ((255-convert_channel_8b(RUDDER))&0xF8)|(elevator>>2);
packet[3] = (elevator<<6)|(((255-convert_channel_8b(AILERON))>>2)&0xFE);
packet[4] = 0x20; // Trim
packet[5] = 0x20 // Trim
| GET_FLAG(CH7_SW, 0x80); // High: +100%
packet[6] = 0x20; // Trim
packet[7] = 0x40 // Low: -100%
| GET_FLAG((Channel_data[CH7] > CHANNEL_MIN_COMMAND && !CH7_SW), 0x80) // Medium: 0%
| GET_FLAG((CH5_SW||CH6_SW), 0x02) // Momentary Take off/Landing + Emergency
| GET_FLAG(CH8_SW, 0x04); // Headless: -100%=off,+100%=on
packet[8] = GET_FLAG(CH6_SW, 0x80); // Emergency
}
POTENSIC_set_checksum();
packet[9] = hopping_frequency_no;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[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();
XN297_WritePayload(packet, POTENSIC_PACKET_SIZE);
NRF24L01_SetPower();
}
static void __attribute__((unused)) POTENSIC_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
if(IS_BIND_IN_PROGRESS)
XN297_SetTXAddr((uint8_t*)"\x01\x01\x01\x01\x06", 5); // Bind address
else
XN297_SetTXAddr(rx_tx_addr,5); // Normal address
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_03_SETUP_AW, 0x03); // set address length (5 bytes)
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
NRF24L01_Activate(0x73);
}
static void __attribute__((unused)) POTENSIC_initialize_txid()
{
#ifdef FORCE_POTENSIC_ORIGINAL_ID
memcpy(rx_tx_addr,(uint8_t *)"\xF6\xE0\x20\x00\x0E",5);
#endif
memcpy(hopping_frequency,(uint8_t *)"\x32\x3E\x3A\x36",POTENSIC_RF_NUM_CHANNELS); //50, 62, 58, 54
}
uint16_t POTENSIC_callback()
{
if(IS_BIND_IN_PROGRESS)
if(--bind_counter==0)
{
BIND_DONE;
XN297_SetTXAddr(rx_tx_addr,5);
}
#ifdef MULTI_SYNC
telemetry_set_input_sync(POTENSIC_PACKET_PERIOD);
#endif
POTENSIC_send_packet();
return POTENSIC_PACKET_PERIOD;
}
uint16_t initPOTENSIC(void)
{
bind_counter = POTENSIC_BIND_COUNT;
POTENSIC_initialize_txid();
POTENSIC_init();
hopping_frequency_no = 0;
return POTENSIC_INITIAL_WAIT;
}
#endif

View File

@@ -0,0 +1,239 @@
/*
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 CADET PRO V4 TX
#if defined(PELIKAN_A7105_INO)
#include "iface_a7105.h"
//#define PELIKAN_FORCE_ID
#define PELIKAN_BIND_COUNT 400
#define PELIKAN_BIND_RF 0x3C
#define PELIKAN_NUM_RF_CHAN 0x1D
#define PELIKAN_PAQUET_PERIOD 7980
static void __attribute__((unused)) pelikan_build_packet()
{
static boolean upper=false;
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];
packet[6] = 0x05; //??
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);
uint8_t top=(channel>>2) & 0xC0;
packet[2] = channel;
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871);
top|=(channel>>4) & 0x30;
packet[3] = channel;
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871);
top|=(channel>>6) & 0x0C;
packet[4] = channel;
channel=convert_channel_16b_nolimit(CH_AETR[offset], 153, 871);
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(++packet_count>4)
{
packet_count=0;
if(++hopping_frequency_no>=PELIKAN_NUM_RF_CHAN)
hopping_frequency_no=0;
}
packet[10]=hopping_frequency_no;
packet[11]=packet_count;
packet_length = 15;
}
//Check
crc8=0x15;
for(uint8_t i=1; i<packet_length-1 ;i++)
crc8+=packet[i];
packet[packet_length-1]=crc8;
//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("");
}
#endif
A7105_WriteData(packet_length, IS_BIND_IN_PROGRESS?PELIKAN_BIND_RF:hopping_frequency[hopping_frequency_no]);
A7105_SetPower();
}
uint16_t ReadPelikan()
{
#ifndef FORCE_PELIKAN_TUNING
A7105_AdjustLOBaseFreq(1);
#endif
if(IS_BIND_IN_PROGRESS)
{
bind_counter--;
if (bind_counter==0)
{
BIND_DONE;
A7105_Strobe(A7105_STANDBY);
A7105_WriteReg(A7105_03_FIFOI,0x28);
}
}
#ifdef MULTI_SYNC
telemetry_set_input_sync(PELIKAN_PAQUET_PERIOD);
#endif
pelikan_build_packet();
return PELIKAN_PAQUET_PERIOD;
}
static uint8_t pelikan_firstCh(uint8_t u, uint8_t l)
{
int16_t i;
i = u * 10 + l - 23;
do
{
if (i > 24)
i -= 24;
if (i <= 0)
return 10;
else if ((i > 0) && (i < 13))
return 10 + 12 + (i * 4);
else if ((i > 12) && (i < 24))
return 10 - 2 + ((i - 12) * 4);
}
while (i > 24);
return 0;
}
static uint8_t pelikan_adjust_value(uint8_t value, uint8_t addition, uint8_t limit)
{
uint8_t i;
do
{
i = 0;
if (value > limit) {
value -= 62;
i++;
}
if (value == 24) {
value += addition;
i++;
}
if (value == 48) {
value += addition;
i++;
}
}
while (i > 0);
return value;
}
static uint8_t pelikan_add(uint8_t pfrq,uint8_t a, uint8_t limit)
{
uint8_t nfrq;
nfrq = pfrq + a;
nfrq = pelikan_adjust_value(nfrq, a, limit);
return nfrq;
}
static void __attribute__((unused)) pelikan_init_hop()
{
#define PELIKAN_HOP_LIMIT 70
rx_tx_addr[0] = 0;
rx_tx_addr[1]+= RX_num;
uint8_t high = (rx_tx_addr[1]>>4) % 3; // 0..2
uint8_t low = rx_tx_addr[1] & 0x0F;
if(high==2)
low %= 0x04; // 0..3
else if(high)
low %= 0x0E; // 0..D
else
low %= 0x0F; // 0..E
rx_tx_addr[1] = (high<<4) + low;
uint8_t addition = (20 * high)+ (2 * low) + 8;
uint8_t first_channel = pelikan_firstCh(high, low);
first_channel = pelikan_adjust_value(first_channel, addition, PELIKAN_HOP_LIMIT);
hopping_frequency[0] = first_channel;
debug("%02X", first_channel);
for (uint8_t i = 1; i < PELIKAN_NUM_RF_CHAN; i++)
{
hopping_frequency[i] = pelikan_add(hopping_frequency[i-1], addition, PELIKAN_HOP_LIMIT);
debug(" %02X", hopping_frequency[i]);
}
debugln("");
}
#ifdef PELIKAN_FORCE_ID
const uint8_t PROGMEM pelikan_hopp[][PELIKAN_NUM_RF_CHAN] = {
{ 0x5A,0x46,0x32,0x6E,0x6C,0x58,0x44,0x42,0x40,0x6A,0x56,0x54,0x52,0x3E,0x68,0x66,0x64,0x50,0x3C,0x3A,0x38,0x62,0x4E,0x4C,0x5E,0x4A,0x36,0x5C,0x34 }
};
#endif
uint16_t initPelikan()
{
A7105_Init();
if(IS_BIND_IN_PROGRESS)
A7105_WriteReg(A7105_03_FIFOI,0x10);
//ID from dump
#ifdef PELIKAN_FORCE_ID
rx_tx_addr[0]=0x0D; // hopping freq
rx_tx_addr[1]=0xF4; // hopping freq
rx_tx_addr[2]=0x50; // ID
rx_tx_addr[3]=0x18; // ID
// 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]);
#else
pelikan_init_hop();
#endif
hopping_frequency_no=PELIKAN_NUM_RF_CHAN;
packet_count=5;
return 2400;
}
#endif

View File

@@ -0,0 +1,329 @@
/*
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 PROPEL 74-Z Speeder Bike.
#if defined(PROPEL_NRF24L01_INO)
#include "iface_nrf24l01.h"
//#define PROPEL_FORCE_ID
#define PROPEL_INITIAL_WAIT 500
#define PROPEL_PACKET_PERIOD 10000
#define PROPEL_BIND_RF_CHANNEL 0x23
#define PROPEL_PAYLOAD_SIZE 16
#define PROPEL_SEARCH_PERIOD 50 //*10ms
#define PROPEL_BIND_PERIOD 1500
#define PROPEL_PACKET_SIZE 14
#define PROPEL_RF_NUM_CHANNELS 4
#define PROPEL_ADDRESS_LENGTH 5
#define PROPEL_DEFAULT_PERIOD 20
enum {
PROPEL_BIND1 = 0,
PROPEL_BIND2,
PROPEL_BIND3,
PROPEL_DATA1,
};
static uint16_t __attribute__((unused)) PROPEL_checksum()
{
typedef union {
struct {
uint8_t h:1;
uint8_t g:1;
uint8_t f:1;
uint8_t e:1;
uint8_t d:1;
uint8_t c:1;
uint8_t b:1;
uint8_t a:1;
} bits;
uint8_t byte:8;
} byte_bits_t;
uint8_t sum = packet[0];
for (uint8_t i = 1; i < PROPEL_PACKET_SIZE - 2; i++)
sum += packet[i];
byte_bits_t in = { .byte = sum };
byte_bits_t out = { .byte = sum };
out.byte ^= 0x0a;
out.bits.d = !(in.bits.d ^ in.bits.h);
out.bits.c = (!in.bits.c && !in.bits.d && in.bits.g)
|| (in.bits.c && !in.bits.d && !in.bits.g)
|| (!in.bits.c && in.bits.g && !in.bits.h)
|| (in.bits.c && !in.bits.g && !in.bits.h)
|| (in.bits.c && in.bits.d && in.bits.g && in.bits.h)
|| (!in.bits.c && in.bits.d && !in.bits.g && in.bits.h);
out.bits.b = (!in.bits.b && !in.bits.c && !in.bits.d)
|| (in.bits.b && in.bits.c && in.bits.g)
|| (!in.bits.b && !in.bits.c && !in.bits.g)
|| (!in.bits.b && !in.bits.d && !in.bits.g)
|| (!in.bits.b && !in.bits.c && !in.bits.h)
|| (!in.bits.b && !in.bits.g && !in.bits.h)
|| (in.bits.b && in.bits.c && in.bits.d && in.bits.h)
|| (in.bits.b && in.bits.d && in.bits.g && in.bits.h);
out.bits.a = (in.bits.a && !in.bits.b)
|| (in.bits.a && !in.bits.c && !in.bits.d)
|| (in.bits.a && !in.bits.c && !in.bits.g)
|| (in.bits.a && !in.bits.d && !in.bits.g)
|| (in.bits.a && !in.bits.c && !in.bits.h)
|| (in.bits.a && !in.bits.g && !in.bits.h)
|| (!in.bits.a && in.bits.b && in.bits.c && in.bits.g)
|| (!in.bits.a && in.bits.b && in.bits.c && in.bits.d && in.bits.h)
|| (!in.bits.a && in.bits.b && in.bits.d && in.bits.g && in.bits.h);
return (sum << 8) | (out.byte & 0xff);
}
static void __attribute__((unused)) PROPEL_bind_packet(bool valid_rx_id)
{
memset(packet, 0, PROPEL_PACKET_SIZE);
packet[0] = 0xD0;
memcpy(&packet[1], rx_tx_addr, 4); // only 4 bytes sent of 5-byte address
if (valid_rx_id) memcpy(&packet[5], rx_id, 4);
packet[9] = rf_ch_num; // hopping table to be used when switching to normal mode
packet[11] = 0x05; // unknown, 0x01 on TX2??
uint16_t check = PROPEL_checksum();
packet[12] = check >> 8;
packet[13] = check & 0xff;
NRF24L01_WriteReg(NRF24L01_07_STATUS, (_BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT)));
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WritePayload(packet, PROPEL_PACKET_SIZE);
}
static void __attribute__((unused)) PROPEL_data_packet()
{
memset(packet, 0, PROPEL_PACKET_SIZE);
packet[0] = 0xC0;
packet[1] = convert_channel_16b_limit(THROTTLE, 0x2f, 0xcf);
packet[2] = convert_channel_16b_limit(RUDDER , 0xcf, 0x2f);
packet[3] = convert_channel_16b_limit(ELEVATOR, 0x2f, 0xcf);
packet[4] = convert_channel_16b_limit(AILERON , 0xcf, 0x2f);
packet[5] = 0x40; //might be trims but unsused
packet[6] = 0x40; //might be trims but unsused
packet[7] = 0x40; //might be trims but unsused
packet[8] = 0x40; //might be trims but unsused
if (bind_phase)
{//need to send a couple of default packets after bind
bind_phase--;
packet[10] = 0x80; // LEDs
}
else
{
packet[9] = 0x02 // Always fast speed, slow=0x00, medium=0x01, fast=0x02, 0x03=flight training mode
| GET_FLAG( CH14_SW, 0x03) // Flight training mode
| GET_FLAG( CH10_SW, 0x04) // Calibrate
| GET_FLAG( CH12_SW, 0x08) // Take off
| GET_FLAG( CH8_SW, 0x10) // Fire
| GET_FLAG( CH11_SW, 0x20) // Altitude hold=0x20
| GET_FLAG( CH6_SW, 0x40) // Roll CW
| GET_FLAG( CH7_SW, 0x80); // Roll CCW
packet[10] = GET_FLAG( CH13_SW, 0x20) // Land
| GET_FLAG( CH9_SW, 0x40) // Weapon system activted=0x40
| GET_FLAG(!CH5_SW, 0x80); // LEDs
}
packet[11] = 5; // unknown, 0x01 on TX2??
uint16_t check = PROPEL_checksum();
packet[12] = check >> 8;
packet[13] = check & 0xff;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]);
hopping_frequency_no &= 0x03;
NRF24L01_SetPower();
NRF24L01_WriteReg(NRF24L01_07_STATUS, (_BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT)));
NRF24L01_FlushTx();
NRF24L01_WritePayload(packet, PROPEL_PACKET_SIZE);
}
static void __attribute__((unused)) PROPEL_init()
{
NRF24L01_Initialize();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x7f);
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x3f); // AA on all pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3f); // Enable all pipes
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte address
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x36); // retransmit 1ms, 6 times
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x07); // ?? match protocol capture
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x99\x77\x55\x33\x11", PROPEL_ADDRESS_LENGTH); //Bind address
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x99\x77\x55\x33\x11", PROPEL_ADDRESS_LENGTH); //Bind address
NRF24L01_WriteReg(NRF24L01_05_RF_CH, PROPEL_BIND_RF_CHANNEL);
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // Enable dynamic payload length
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Enable all features
// Beken 2425 register bank 1 initialized here in stock tx capture
// Hopefully won't matter for nRF compatibility
NRF24L01_FlushTx();
NRF24L01_SetTxRxMode(TX_EN);
}
const uint8_t PROGMEM PROPEL_hopping []= { 0x47,0x36,0x27,0x44,0x33,0x0D,0x3C,0x2E,0x1B,0x39,0x2A,0x18 };
static void __attribute__((unused)) PROPEL_initialize_txid()
{
//address last byte
rx_tx_addr[4]=0x11;
//random hopping channel table
rf_ch_num=random(0xfefefefe)&0x03;
for(uint8_t i=0; i<3; i++)
hopping_frequency[i]=pgm_read_byte_near( &PROPEL_hopping[i + 3*rf_ch_num] );
hopping_frequency[3]=0x23;
#ifdef PROPEL_FORCE_ID
if(RX_num&1)
memcpy(rx_tx_addr, (uint8_t *)"\x73\xd3\x31\x30\x11", PROPEL_ADDRESS_LENGTH); //TX1: 73 d3 31 30 11
else
memcpy(rx_tx_addr, (uint8_t *)"\x94\xc5\x31\x30\x11", PROPEL_ADDRESS_LENGTH); //TX2: 94 c5 31 30 11
rf_ch_num = 0x03; //TX1
memcpy(hopping_frequency,(uint8_t *)"\x39\x2A\x18\x23",PROPEL_RF_NUM_CHANNELS); //TX1: 57,42,24,35
rf_ch_num = 0x00; //TX2
memcpy(hopping_frequency,(uint8_t *)"\x47\x36\x27\x23",PROPEL_RF_NUM_CHANNELS); //TX2: 71,54,39,35
rf_ch_num = 0x01; // Manual search
memcpy(hopping_frequency,(uint8_t *)"\x44\x33\x0D\x23",PROPEL_RF_NUM_CHANNELS); //Manual: 68,51,13,35
rf_ch_num = 0x02; // Manual search
memcpy(hopping_frequency,(uint8_t *)"\x3C\x2E\x1B\x23",PROPEL_RF_NUM_CHANNELS); //Manual: 60,46,27,35
#endif
}
uint16_t PROPEL_callback()
{
uint8_t status;
switch (phase)
{
case PROPEL_BIND1:
PROPEL_bind_packet(false); //rx_id unknown
phase++; //BIND2
return PROPEL_BIND_PERIOD;
case PROPEL_BIND2:
status=NRF24L01_ReadReg(NRF24L01_07_STATUS);
if (status & _BV(NRF24L01_07_MAX_RT))
{// Max retry (6) reached
phase = PROPEL_BIND1;
return PROPEL_BIND_PERIOD;
}
if (!(_BV(NRF24L01_07_RX_DR) & status))
return PROPEL_BIND_PERIOD; // nothing received
// received frame, got rx_id, save it
NRF24L01_ReadPayload(packet_in, PROPEL_PACKET_SIZE);
memcpy(rx_id, &packet_in[1], 4);
PROPEL_bind_packet(true); //send bind packet with rx_id
phase++; //BIND3
break;
case PROPEL_BIND3:
if (_BV(NRF24L01_07_RX_DR) & NRF24L01_ReadReg(NRF24L01_07_STATUS))
{
NRF24L01_ReadPayload(packet_in, PROPEL_PACKET_SIZE);
if (packet_in[0] == 0xa3 && memcmp(&packet_in[1],rx_id,4)==0)
{//confirmation from the model
phase++; //PROPEL_DATA1
bind_phase=PROPEL_DEFAULT_PERIOD;
packet_count=0;
BIND_DONE;
break;
}
}
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, PROPEL_ADDRESS_LENGTH);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, PROPEL_ADDRESS_LENGTH);
PROPEL_bind_packet(true); //send bind packet with rx_id
break;
case PROPEL_DATA1:
if (_BV(NRF24L01_07_RX_DR) & NRF24L01_ReadReg(NRF24L01_07_STATUS))
{// data received from the model
NRF24L01_ReadPayload(packet_in, PROPEL_PACKET_SIZE);
if (packet_in[0] == 0xa3 && memcmp(&packet_in[1],rx_id,3)==0)
{
telemetry_counter++; //LQI
v_lipo1=packet[5]; //number of life left?
v_lipo2=packet[4]; //bit mask: 0x80=flying, 0x08=taking off, 0x04=landing, 0x00=landed/crashed
if(telemetry_lost==0)
telemetry_link=1;
}
}
PROPEL_data_packet();
packet_count++;
if(packet_count>=100)
{//LQI calculation
packet_count=0;
TX_LQI=telemetry_counter;
RX_RSSI=telemetry_counter;
telemetry_counter = 0;
telemetry_lost=0;
}
break;
}
return PROPEL_PACKET_PERIOD;
}
uint16_t initPROPEL()
{
BIND_IN_PROGRESS; // autobind protocol
PROPEL_initialize_txid();
PROPEL_init();
hopping_frequency_no = 0;
phase=PROPEL_BIND1;
return PROPEL_INITIAL_WAIT;
}
#endif
// equations for checksum check byte from truth table
// (1) z = a && !b
// || a && !c && !d
// || a && !c && !g
// || a && !d && !g
// || a && !c && !h
// || a && !g && !h
// || !a && b && c && g
// || !a && b && c && d && h
// || !a && b && d && g && h;
//
// (2) y = !b && !c && !d
// || b && c && g
// || !b && !c && !g
// || !b && !d && !g
// || !b && !c && !h
// || !b && !g && !h
// || b && c && d && h
// || b && d && g && h;
//
// (3) x = !c && !d && g
// || c && !d && !g
// || !c && g && !h
// || c && !g && !h
// || c && d && g && h
// || !c && d && !g && h;
//
// (4) w = d && h
// || !d && !h;
//
// (5) v = !e;
//
// (6) u = f;
//
// (7) t = !g;
//
// (8) s = h;

View File

@@ -292,7 +292,6 @@ static void __attribute__((unused)) Q303_init()
case CX35:
case CX10D:
case CX10WD:
XN297_SetScrambledMode(XN297_SCRAMBLED);
NRF24L01_SetBitrate(NRF24L01_BR_1M);
break;
case Q303:
@@ -355,7 +354,12 @@ static void __attribute__((unused)) Q303_initialize_txid()
uint16_t Q303_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
Q303_send_packet(0);
}
else
{
if (bind_counter == 0)

View File

@@ -0,0 +1,244 @@
/*
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(REDPINE_CC2500_INO)
#include "iface_cc2500.h"
#define REDPINE_LOOPTIME_FAST 20 //2.0ms
#define REDPINE_LOOPTIME_SLOW 20 //20ms
#define REDPINE_BIND 2000
#define REDPINE_PACKET_SIZE 11
#define REDPINE_FEC false // from cc2500 datasheet: The convolutional coder is a rate 1/2 code with a constraint length of m=4
#define REDPINE_NUM_HOPS 50
static void REDPINE_set_channel(uint8_t ch)
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_25_FSCAL1, calData[ch]);
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[ch]);
}
static void REDPINE_build_bind_packet()
{
memset(&packet[0], 0, REDPINE_PACKET_SIZE);
packet[0] = REDPINE_PACKET_SIZE - 1;
packet[1] = 0x03;
packet[2] = 0x01;
packet[3] = rx_tx_addr[2];
packet[4] = rx_tx_addr[3]; // Use RX_Num
uint16_t idx = ((REDPINE_BIND - bind_counter) % 10) * 5;
packet[5] = idx;
packet[6] = hopping_frequency[idx++];
packet[7] = hopping_frequency[idx++];
packet[8] = hopping_frequency[idx++];
packet[9] = hopping_frequency[idx++];
packet[10] = hopping_frequency[idx++];
// packet[11] = 0x02;
// packet[12] = RXNUM;
}
static uint16_t Redpine_Scale(uint8_t chan)
{
uint16_t chan_val=Channel_data[chan]; // -125%..+125% <=> 0..2047
if (chan_val > 2046) chan_val = 2046;
else if (chan_val < 10) chan_val = 10;
return chan_val;
}
static void REDPINE_data_frame() {
uint16_t chan[4];
memset(&packet[0], 0, REDPINE_PACKET_SIZE);
packet[0] = REDPINE_PACKET_SIZE - 1;
packet[1] = rx_tx_addr[2];
packet[2] = rx_tx_addr[3]; // Use RX_Num
chan[0] = Redpine_Scale(0);
chan[1] = Redpine_Scale(1);
chan[2] = Redpine_Scale(2);
chan[3] = Redpine_Scale(3);
packet[3] = chan[0];
packet[4] = (((chan[0] >> 8) & 0x07) | (chan[1] << 4)) | GET_FLAG(CH5_SW, 0x08);
packet[5] = ((chan[1] >> 4) & 0x7F) | GET_FLAG(CH6_SW, 0x80);
packet[6] = chan[2];
packet[7] = (((chan[2] >> 8) & 0x07) | (chan[3] << 4)) | GET_FLAG(CH7_SW, 0x08);
packet[8] = ((chan[3] >> 4) & 0x7F) | GET_FLAG(CH8_SW, 0x80);
packet[9] = GET_FLAG(CH9_SW, 0x01)
| GET_FLAG(CH10_SW, 0x02)
| GET_FLAG(CH11_SW, 0x04)
| GET_FLAG(CH12_SW, 0x08)
| GET_FLAG(CH13_SW, 0x10)
| GET_FLAG(CH14_SW, 0x20)
| GET_FLAG(CH15_SW, 0x40)
| GET_FLAG(CH16_SW, 0x80);
if (sub_protocol==0)
packet[10] = REDPINE_LOOPTIME_FAST;
else
packet[10] = REDPINE_LOOPTIME_SLOW;
}
static uint16_t ReadREDPINE()
{
if ( prev_option != option )
{ // Frequency adjust
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
prev_option = option ;
}
if(IS_BIND_IN_PROGRESS)
{
if (state == REDPINE_BIND) {
REDPINE_init(0);
}
REDPINE_set_channel(49);
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
CC2500_Strobe(CC2500_SFRX);
REDPINE_build_bind_packet();
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteData(packet, REDPINE_PACKET_SIZE);
if(--bind_counter==0)
{
BIND_DONE;
REDPINE_init(sub_protocol);
}
return 4000;
}
else
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
CC2500_SetTxRxMode(TX_EN);
REDPINE_set_channel(hopping_frequency_no);
CC2500_SetPower();
CC2500_Strobe(CC2500_SFRX);
REDPINE_data_frame();
CC2500_Strobe(CC2500_SIDLE);
hopping_frequency_no = (hopping_frequency_no + 1) % 49;
CC2500_WriteData(packet, REDPINE_PACKET_SIZE);
return packet_period;
}
return 1;
}
// register, fast 250k, slow
static const uint8_t REDPINE_init_data[][3] = {
{CC2500_00_IOCFG2, 0x06, 0x06},
{CC2500_02_IOCFG0, 0x06, 0x06},
{CC2500_03_FIFOTHR, 0x07, 0x07},
{CC2500_07_PKTCTRL1, 0x04, 0x04},
{CC2500_08_PKTCTRL0, 0x05, 0x05},
{CC2500_09_ADDR, 0x00, 0x00},
{CC2500_0B_FSCTRL1, 0x0A, 0x06},
{CC2500_0C_FSCTRL0, 0x00, 0x00},
{CC2500_0D_FREQ2, 0x5D, 0x5D},
{CC2500_0E_FREQ1, 0x93, 0x93},
{CC2500_0F_FREQ0, 0xB1, 0xB1},
{CC2500_10_MDMCFG4, 0x2D, 0x78},
{CC2500_11_MDMCFG3, 0x3B, 0x93},
{CC2500_12_MDMCFG2, 0x73, 0x03},
{CC2500_13_MDMCFG1, 0x23, 0x22},
{CC2500_14_MDMCFG0, 0x56, 0xF8}, // Chan space
{CC2500_15_DEVIATN, 0x00, 0x44},
{CC2500_17_MCSM1, 0x0c, 0x0c},
{CC2500_18_MCSM0, 0x18, 0x18},
{CC2500_19_FOCCFG, 0x1D, 0x16},
{CC2500_1A_BSCFG, 0x1C, 0x6c},
{CC2500_1B_AGCCTRL2, 0xC7, 0x43},
{CC2500_1C_AGCCTRL1, 0x00, 0x40},
{CC2500_1D_AGCCTRL0, 0xB0, 0x91},
{CC2500_21_FREND1, 0xB6, 0x56},
{CC2500_22_FREND0, 0x10, 0x10},
{CC2500_23_FSCAL3, 0xEA, 0xA9},
{CC2500_24_FSCAL2, 0x0A, 0x0A},
{CC2500_25_FSCAL1, 0x00, 0x00},
{CC2500_26_FSCAL0, 0x11, 0x11},
{CC2500_29_FSTEST, 0x59, 0x59},
{CC2500_2C_TEST2, 0x88, 0x88},
{CC2500_2D_TEST1, 0x31, 0x31},
{CC2500_2E_TEST0, 0x0B, 0x0B},
{CC2500_3E_PATABLE, 0xff, 0xff}
};
static void REDPINE_init(uint8_t format)
{
CC2500_Reset();
CC2500_WriteReg(CC2500_06_PKTLEN, REDPINE_PACKET_SIZE);
for (uint8_t i=0; i < ((sizeof(REDPINE_init_data)) / (sizeof(REDPINE_init_data[0]))); i++) {
CC2500_WriteReg(REDPINE_init_data[i][0], REDPINE_init_data[i][format+1]);
}
prev_option = option;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
CC2500_Strobe(CC2500_SIDLE);
// calibrate hop channels
for (uint8_t c = 0; c < REDPINE_NUM_HOPS; c++)
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[c]);
CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);
calData[c] = CC2500_ReadReg(CC2500_25_FSCAL1);
}
}
static uint16_t initREDPINE()
{
hopping_frequency_no = 0;
// Used from kn_nrf24l01.c : kn_calculate_freqency_hopping_channels
uint32_t idx = 0;
uint32_t rnd = MProtocol_id;
#define REDPINE_MAX_RF_CHANNEL 255
while (idx < REDPINE_NUM_HOPS-1)
{
uint32_t i;
rnd = rnd * 0x0019660D + 0x3C6EF35F; // Randomization
// Drop least-significant byte for better randomization. Start from 1
uint8_t next_ch = (rnd >> 8) % REDPINE_MAX_RF_CHANNEL + 1;
// Check that it's not duplicate nor adjacent nor channel 0 or 1
for (i = 0; i < idx; i++)
{
uint8_t ch = hopping_frequency[i];
if ((ch <= next_ch + 1) && (ch >= next_ch - 1) && (ch >= 1)) {
break;
}
}
if (i != idx)
continue;
hopping_frequency[idx++] = next_ch;
}
hopping_frequency[49] = 0; // Last channel is the bind channel at hop 0
if (sub_protocol==0)
packet_period = REDPINE_LOOPTIME_FAST*100;
else
packet_period = REDPINE_LOOPTIME_SLOW*1000;
bind_counter=REDPINE_BIND;
REDPINE_init(sub_protocol);
CC2500_SetTxRxMode(TX_EN); // enable PA
return 10000;
}
#endif

View File

@@ -173,8 +173,8 @@ static void __attribute__((unused)) SFHSS_build_data_packet()
else
{ //Use channel value
ch[i]=(ch[i]>>1)+2560;
if(CH_AETR[ch_offset+i]==THROTTLE && ch[i]<3072) // Throttle
ch[i]+=1024;
//if(IS_DISABLE_CH_MAP_off && ch_offset+i==CH3 && ch[i]<3072) // Throttle
// ch[i]+=1024;
}
}
}
@@ -235,6 +235,9 @@ uint16_t ReadSFHSS()
#define SFHSS_PACKET_PERIOD 6800
#define SFHSS_DATA2_TIMING 1625 // Adjust this value between 1600 and 1650 if your RX(s) are not operating properly
case SFHSS_DATA1:
#ifdef MULTI_SYNC
telemetry_set_input_sync(6800);
#endif
SFHSS_build_data_packet();
SFHSS_send_packet();
phase = SFHSS_DATA2;

View File

@@ -63,6 +63,10 @@ void SHENQI_send_packet()
}
else
{
#ifdef MULTI_SYNC
if(packet_count==1)
telemetry_set_input_sync(3000+2508+6*1750);
#endif
LT8900_SetAddress(rx_tx_addr,4);
packet[1]=255-convert_channel_8b(RUDDER);
packet[2]=255-convert_channel_16b_limit(THROTTLE,0x60,0xA0);
@@ -91,7 +95,9 @@ void SHENQI_send_packet()
uint16_t SHENQI_callback()
{
if(IS_BIND_DONE)
{
SHENQI_send_packet();
}
else
{
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))

View File

@@ -16,7 +16,7 @@
#if defined(SLT_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_nrf250k.h"
//#define SLT_Q200_FORCE_ID
@@ -25,6 +25,7 @@
#define SLT_PAYLOADSIZE_V2 11
#define SLT_NFREQCHANNELS 15
#define SLT_TXID_SIZE 4
#define SLT_BIND_CHANNEL 0x50
enum{
// flags going to packet[6] (Q200)
@@ -48,30 +49,13 @@ enum {
SLT_DATA2,
SLT_DATA3,
SLT_BIND1,
SLT_BIND2
SLT_BIND2,
};
static void __attribute__((unused)) SLT_init()
{
NRF24L01_Initialize();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO)); // 2-bytes CRC, radio off
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x02); // 4-byte RX/TX address
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // Disable auto retransmit
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 4); // bytes of data payload for pipe 1
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 256kbps
NRF24L01_SetPower();
if(sub_protocol==SLT_V1)
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\xC3\xC3\xAA\x55", SLT_TXID_SIZE);
else // V2
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
NRF24L01_FlushRx();
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, SLT_TXID_SIZE);
NRF24L01_FlushTx();
// Turn radio power on
NRF24L01_SetTxRxMode(TX_EN);
NRF250K_Init();
NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE);
}
static void __attribute__((unused)) SLT_set_freq(void)
@@ -109,21 +93,25 @@ static void __attribute__((unused)) SLT_set_freq(void)
}
}
}
//Bind channel
hopping_frequency[SLT_NFREQCHANNELS]=SLT_BIND_CHANNEL;
//Calib all channels
NRF250K_HoppingCalib(SLT_NFREQCHANNELS+1);
}
static void __attribute__((unused)) SLT_wait_radio()
{
if (packet_sent)
while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)));
while (!NRF250K_IsPacketSent());
packet_sent = 0;
}
static void __attribute__((unused)) SLT_send_packet(uint8_t len)
{
SLT_wait_radio();
NRF24L01_FlushTx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_MAX_RT));
NRF24L01_WritePayload(packet, len);
NRF250K_WritePayload(packet, len);
packet_sent = 1;
}
@@ -132,7 +120,8 @@ static void __attribute__((unused)) SLT_build_packet()
static uint8_t calib_counter=0;
// Set radio channel - once per packet batch
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
NRF250K_SetFreqOffset(); // Set frequency offset
NRF250K_Hopping(hopping_frequency_no);
if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
hopping_frequency_no = 0;
@@ -141,7 +130,7 @@ static void __attribute__((unused)) SLT_build_packet()
for (uint8_t i = 0; i < 4; ++i)
{
uint16_t v = convert_channel_10b(CH_AETR[i]);
if(sub_protocol>SLT_V2 && (CH_AETR[i]==THROTTLE || CH_AETR[i]==ELEVATOR) )
if(sub_protocol>SLT_V2 && (i==CH2 || i==CH3) )
v=1023-v; // reverse throttle and elevator channels for Q100/Q200/MR100 protocols
packet[i] = v;
e = (e >> 2) | (uint8_t) ((v >> 2) & 0xC0);
@@ -183,23 +172,16 @@ static void __attribute__((unused)) SLT_build_packet()
static void __attribute__((unused)) SLT_send_bind_packet()
{
SLT_wait_radio();
BIND_IN_PROGRESS; //Limit TX power to bind level
NRF24L01_SetPower();
NRF250K_Hopping(SLT_NFREQCHANNELS); //Bind channel
BIND_IN_PROGRESS; //Limit TX power to bind level
NRF250K_SetPower();
BIND_DONE;
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x50);
NRF250K_SetTXAddr((uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
memcpy((void*)packet,(void*)rx_tx_addr,SLT_TXID_SIZE);
if(phase==SLT_BIND2)
SLT_send_packet(SLT_TXID_SIZE);
else // SLT_BIND1
SLT_send_packet(SLT_PAYLOADSIZE_V2);
SLT_wait_radio(); //Wait until the packet's sent before changing TX address!
NRF24L01_SetPower(); //Change power back to normal level
if(phase==SLT_BIND2) // after V1 bind and V2 second bind packet
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, SLT_TXID_SIZE);
}
#define SLT_TIMING_BUILD 1000
@@ -213,7 +195,12 @@ uint16_t SLT_callback()
switch (phase)
{
case SLT_BUILD:
#ifdef MULTI_SYNC
telemetry_set_input_sync(sub_protocol==SLT_V1?20000:13730);
#endif
SLT_build_packet();
NRF250K_SetPower(); //Change power level
NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE);
phase++;
return SLT_TIMING_BUILD;
case SLT_DATA1:
@@ -250,7 +237,6 @@ uint16_t SLT_callback()
}
else
{// Continue to send normal packets
NRF24L01_SetPower(); // Set tx_power
phase = SLT_BUILD;
if(sub_protocol==SLT_V1)
return 20000-SLT_TIMING_BUILD;
@@ -286,8 +272,8 @@ uint16_t initSLT()
/* rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x0B;rx_tx_addr[3]=0x57;*/
#endif
}
SLT_set_freq();
SLT_init();
SLT_set_freq();
phase = SLT_BUILD;
return 50000;
}

View File

@@ -0,0 +1,177 @@
#ifdef SX1276_INSTALLED
#include "iface_sx1276.h"
void SX1276_WriteReg(uint8_t address, uint8_t data)
{
SPI_CSN_off;
SPI_Write(address | 0x80); // MSB 1 = write
NOP();
SPI_Write(data);
SPI_CSN_on;
}
uint8_t SX1276_ReadReg(uint8_t address)
{
SPI_CSN_off;
SPI_Write(address & 0x7F);
uint8_t result = SPI_Read();
SPI_CSN_on;
return result;
}
void SX1276_WriteRegisterMulti(uint8_t address, const uint8_t* data, uint8_t length)
{
SPI_CSN_off;
SPI_Write(address | 0x80); // MSB 1 = write
for(uint8_t i = 0; i < length; i++)
SPI_Write(data[i]);
SPI_CSN_on;
}
uint8_t SX1276_Reset()
{
//TODO
return 0;
}
void SX1276_SetFrequency(uint32_t frequency)
{
uint32_t f = frequency / 61;
uint8_t data[3];
data[0] = (f & (0xFF << 16)) >> 16;
data[1] = (f & (0xFF << 8)) >> 8;
data[2] = f & 0xFF;
SX1276_WriteRegisterMulti(SX1276_06_FRFMSB, data, 3);
}
void SX1276_SetMode(bool lora, bool low_freq_mode, uint8_t mode)
{
uint8_t data = 0x00;
if(lora)
{
data = data | (1 << 7);
data = data & ~(1 << 6);
}
else
{
data = data & ~(1 << 7);
data = data | (1 << 6);
}
if(low_freq_mode)
data = data | (1 << 3);
data = data | mode;
SX1276_WriteReg(SX1276_01_OPMODE, data);
}
void SX1276_SetDetectOptimize(bool auto_if, uint8_t detect_optimize)
{
uint8_t data = SX1276_ReadReg(SX1276_31_DETECTOPTIMIZE);
data = (data & 0b01111000) | detect_optimize;
data = data | (auto_if << 7);
SX1276_WriteReg(SX1276_31_DETECTOPTIMIZE, data);
}
void SX1276_ConfigModem1(uint8_t bandwidth, uint8_t coding_rate, bool implicit_header_mode)
{
uint8_t data = 0x00;
data = data | (bandwidth << 4);
data = data | (coding_rate << 1);
data = data | implicit_header_mode;
SX1276_WriteReg(SX1276_1D_MODEMCONFIG1, data);
}
void SX1276_ConfigModem2(uint8_t spreading_factor, bool tx_continuous_mode, bool rx_payload_crc_on)
{
uint8_t data = SX1276_ReadReg(SX1276_1E_MODEMCONFIG2);
data = data & 0b11; // preserve the last 2 bits
data = data | (spreading_factor << 4);
data = data | (tx_continuous_mode << 3);
data = data | (rx_payload_crc_on << 2);
SX1276_WriteReg(SX1276_1E_MODEMCONFIG2, data);
}
void SX1276_ConfigModem3(bool low_data_rate_optimize, bool agc_auto_on)
{
uint8_t data = SX1276_ReadReg(SX1276_26_MODEMCONFIG3);
data = data & 0b11; // preserve the last 2 bits
data = data | (low_data_rate_optimize << 3);
data = data | (agc_auto_on << 2);
SX1276_WriteReg(SX1276_26_MODEMCONFIG3, data);
}
void SX1276_SetPreambleLength(uint16_t length)
{
uint8_t data[2];
data[0] = (length >> 8) & 0xFF; // high byte
data[1] = length & 0xFF; // low byte
SX1276_WriteRegisterMulti(SX1276_20_PREAMBLEMSB, data, 2);
}
void SX1276_SetDetectionThreshold(uint8_t threshold)
{
SX1276_WriteReg(SX1276_37_DETECTIONTHRESHOLD, threshold);
}
void SX1276_SetLna(uint8_t gain, bool high_freq_lna_boost)
{
uint8_t data = SX1276_ReadReg(SX1276_0C_LNA);
data = data & 0b100; // preserve the third bit
data = data | (gain << 5);
if(high_freq_lna_boost)
data = data | 0b11;
SX1276_WriteReg(SX1276_0C_LNA, data);
}
void SX1276_SetHopPeriod(uint8_t freq_hop_period)
{
SX1276_WriteReg(SX1276_24_HOPPERIOD, freq_hop_period);
}
void SX1276_SetPaDac(bool on)
{
uint8_t data = SX1276_ReadReg(SX1276_4D_PADAC);
data = data & 0b11111000; // preserve the upper 5 bits
if(on)
data = data | 0x07;
else
data = data | 0x04;
SX1276_WriteReg(SX1276_4D_PADAC, data);
}
void SX1276_SetPaConfig(bool pa_boost_pin, uint8_t max_power, uint8_t output_power)
{
uint8_t data = 0x00;
data = data | (pa_boost_pin << 7);
data = data | (max_power << 4);
data = data | output_power;
SX1276_WriteReg(SX1276_09_PACONFIG, data);
}
void SX1276_WritePayloadToFifo(uint8_t* payload, uint8_t length)
{
SX1276_WriteReg(SX1276_22_PAYLOAD_LENGTH, length);
SX1276_WriteReg(SX1276_0E_FIFOTXBASEADDR, 0x00);
SX1276_WriteReg(SX1276_0D_FIFOADDRPTR, 0x00);
SX1276_WriteRegisterMulti(SX1276_00_FIFO, payload, length);
}
#endif

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(SCANNER_CC2500_INO)
#include "iface_cc2500.h"
#define SCAN_MAX_RADIOCHANNEL 249 // 2483 MHz
#define SCAN_CHANNEL_LOCK_TIME 90 // with precalibration, channel requires only 90 usec for synthesizer to settle
#define SCAN_AVERAGE_INTVL 20
#define SCAN_MAX_COUNT 10
#define SCAN_CHANS_PER_PACKET 5
enum ScanStates {
SCAN_CHANNEL_CHANGE = 0,
SCAN_GET_RSSI = 1,
};
static void __attribute__((unused)) Scanner_cc2500_init()
{
/* Initialize CC2500 chip */
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x12); // Packet Automation Control
CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0A); // Frequency Synthesizer Control
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, 0xC3); // Frequency Control Word, Low Byte
CC2500_WriteReg(CC2500_10_MDMCFG4, 0x8D); // Modem Configuration
CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration
CC2500_WriteReg(CC2500_12_MDMCFG2, 0x10); // Modem Configuration
CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // Modem Configuration
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_SetTxRxMode(RX_EN); // Receive mode
CC2500_Strobe(CC2500_SIDLE);
CC2500_Strobe(CC2500_SRX);
delayMicroseconds(1000); // wait for RX to activate
}
static void __attribute__((unused)) Scanner_calibrate()
{
for (uint8_t c = 0; c < SCAN_MAX_RADIOCHANNEL; c++)
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, c);
CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);
calData[c] = CC2500_ReadReg(CC2500_25_FSCAL1);
}
CC2500_Strobe(CC2500_SIDLE);
}
static void __attribute__((unused)) Scanner_scan_next()
{
CC2500_WriteReg(CC2500_0A_CHANNR, rf_ch_num);
CC2500_WriteReg(CC2500_25_FSCAL1, calData[rf_ch_num]);
CC2500_Strobe(CC2500_SFRX);
CC2500_Strobe(CC2500_SRX);
}
static int __attribute__((unused)) Scanner_scan_rssi()
{
uint8_t rssi;
rssi = CC2500_ReadReg(0x40 | CC2500_34_RSSI); // 0.5 db/count, RSSI value read from the RSSI status register is a 2's complement number
uint8_t rssi_rel;
if (rssi >= 128) {
rssi_rel = rssi - 128; // relative power levels 0-127 (equals -137 to -72 dBm)
}
else {
rssi_rel = rssi + 128; // relative power levels 128-255 (equals -73 to -10 dBm)
}
return rssi_rel;
}
uint16_t Scanner_callback()
{
uint8_t rssi,max_rssi;
//!!!Blocking mode protocol!!!
TX_MAIN_PAUSE_off;
tx_resume();
while(1)
{ //Start
packet_in[0] = rf_ch_num; // start channel for telemetry packet
for(uint8_t i=0;i<SCAN_CHANS_PER_PACKET;i++)
{
Scanner_scan_next(); // set channel
delayMicroseconds(SCAN_CHANNEL_LOCK_TIME); // wait for freq to adjust
max_rssi = 0;
for(uint8_t j=0;j<SCAN_MAX_COUNT;j++)
{
rssi = Scanner_scan_rssi();
if(rssi >= max_rssi) max_rssi = rssi;
delayMicroseconds(SCAN_AVERAGE_INTVL); // wait before next read
}
packet_in[i+1] = max_rssi;
//next channel
rf_ch_num++;
if (rf_ch_num >= (SCAN_MAX_RADIOCHANNEL + 1))
rf_ch_num = 0;
}
telemetry_link = 1;
do
{
if(Update_All())
return 1000; // protocol has changed, give back the control to main
}
while(telemetry_link == 1);
}
return 0;
}
uint16_t initScanner(void)
{
rf_ch_num = 0;
telemetry_link = 0;
Scanner_cc2500_init();
CC2500_Strobe(CC2500_SRX);
Scanner_calibrate();
CC2500_Strobe(CC2500_SIDLE);
CC2500_SetTxRxMode(RX_EN);
CC2500_Strobe(CC2500_SRX); // Receive mode
return 1250;
}
#endif

View File

@@ -0,0 +1,179 @@
/*
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(SKYARTEC_CC2500_INO)
#include "iface_cc2500.h"
//#define SKYARTEC_FORCE_ID
#define SKYARTEC_COARSE 0x00
#define SKYARTEC_TX_ADDR rx_tx_addr[1]
#define SKYARTEC_TX_CHANNEL rx_tx_addr[0]
enum {
SKYARTEC_PKT1 = 0,
SKYARTEC_SLEEP1,
SKYARTEC_PKT2,
SKYARTEC_SLEEP2,
SKYARTEC_PKT3,
SKYARTEC_SLEEP3,
SKYARTEC_PKT4,
SKYARTEC_SLEEP4,
SKYARTEC_PKT5,
SKYARTEC_SLEEP5,
SKYARTEC_PKT6,
SKYARTEC_LAST,
};
const PROGMEM uint8_t SKYARTEC_init_values[] = {
/* 04 */ 0x13, 0x18, 0xFF, 0x05,
/* 08 */ 0x05, 0x43, 0xCD, 0x09, 0x00, 0x5D, 0x93, 0xB1 + SKYARTEC_COARSE,
/* 10 */ 0x2D, 0x20, 0x73, 0x22, 0xF8, 0x50, 0x07, 0x30,
/* 18 */ 0x18, 0x1D, 0x1C, 0xC7, 0x00, 0xB2, 0x87, 0x6B,
/* 20 */ 0xF8, 0xB6, 0x10, 0xEA, 0x0A, 0x00, 0x11, 0x41,
/* 28 */ 0x00, 0x59, 0x7F, 0x3F, 0x88, 0x31, 0x0B
};
static void __attribute__((unused)) SKYARTEC_rf_init()
{
CC2500_Strobe(CC2500_SIDLE);
for (uint8_t i = 4; i <= 0x2E; ++i)
CC2500_WriteReg(i, pgm_read_byte_near(&SKYARTEC_init_values[i-4]));
prev_option = option;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
CC2500_Strobe(CC2500_SFTX);
CC2500_Strobe(CC2500_SFRX);
CC2500_Strobe(CC2500_SXOFF);
CC2500_Strobe(CC2500_SIDLE);
}
static void __attribute__((unused)) SKYARTEC_send_data_packet()
{
//13 c5 01 0259 0168 0000 0259 030c 021a 0489 f3 7e 0a
//header
packet[0] = 0x13; //Length
packet[1] = SKYARTEC_TX_ADDR; //Tx Addr?
packet[2] = 0x01; //???
//channels
for(uint8_t i = 0; i < 7; i++)
{
uint16_t value = convert_channel_16b_limit(CH_AETR[i],0x000,0x500);
packet[3+2*i] = value >> 8;
packet[4+2*i] = value & 0xff;
}
//checks
uint8_t xor1 = 0;
for(uint8_t i = 3; i <= 14; i++)
xor1 ^= packet[i];
packet[18] = xor1;
xor1 ^= packet[15];
xor1 ^= packet[16];
packet[17] = xor1;
packet[19] = packet[3] + packet[5] + packet[7] + packet[9] + packet[11] + packet[13];
CC2500_WriteReg(CC2500_04_SYNC1, rx_tx_addr[3]);
CC2500_WriteReg(CC2500_05_SYNC0, rx_tx_addr[2]);
CC2500_WriteReg(CC2500_09_ADDR, SKYARTEC_TX_ADDR);
CC2500_WriteReg(CC2500_0A_CHANNR, SKYARTEC_TX_CHANNEL);
CC2500_WriteData(packet, 20);
}
static void __attribute__((unused)) SKYARTEC_send_bind_packet()
{
//0b 7d 01 01 b2 c5 4a 2f 00 00 c5 d6
packet[0] = 0x0b; //Length
packet[1] = 0x7d;
packet[2] = 0x01;
packet[3] = 0x01;
packet[4] = rx_tx_addr[0];
packet[5] = rx_tx_addr[1];
packet[6] = rx_tx_addr[2];
packet[7] = rx_tx_addr[3];
packet[8] = 0x00;
packet[9] = 0x00;
packet[10] = SKYARTEC_TX_ADDR;
uint8_t xor1 = 0;
for(uint8_t i = 3; i < 11; i++)
xor1 ^= packet[i];
packet[11] = xor1;
CC2500_WriteReg(CC2500_04_SYNC1, 0x7d);
CC2500_WriteReg(CC2500_05_SYNC0, 0x7d);
CC2500_WriteReg(CC2500_09_ADDR, 0x7d);
CC2500_WriteReg(CC2500_0A_CHANNR, 0x7d);
CC2500_WriteData(packet, 12);
}
uint16_t ReadSKYARTEC()
{
if (phase & 0x01)
{
CC2500_Strobe(CC2500_SIDLE);
if (phase == SKYARTEC_LAST)
{
CC2500_SetPower();
// Tune frequency if it has been changed
if ( prev_option != option )
{
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
prev_option = option ;
}
phase = SKYARTEC_PKT1;
}
else
phase++;
return 3000;
}
if (phase == SKYARTEC_PKT1 && bind_counter)
{
SKYARTEC_send_bind_packet();
bind_counter--;
if(bind_counter == 0)
BIND_DONE;
}
else
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(6000);
#endif
SKYARTEC_send_data_packet();
}
phase++;
return 3000;
}
uint16_t initSKYARTEC()
{
SKYARTEC_rf_init();
#ifdef SKYARTEC_FORCE_ID
memset(rx_tx_addr,0x00,4);
#endif
if(rx_tx_addr[0]==0) rx_tx_addr[0]=0xB2;
if(rx_tx_addr[1]==0) rx_tx_addr[1]=0xC5;
if(rx_tx_addr[2]==0) rx_tx_addr[2]=0x4A;
if(rx_tx_addr[3]==0) rx_tx_addr[3]=0x2F;
bind_counter = 250;
phase = SKYARTEC_PKT1;
return 10000;
}
#endif

View File

@@ -359,6 +359,9 @@ uint16_t symax_callback()
}
break;
case SYMAX_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(SYMAX_PACKET_PERIOD);
#endif
SYMAX_send_packet(0);
break;
}

View File

@@ -0,0 +1,238 @@
/*
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/>.
Works with Traxxas 6519 receivers https://traxxas.com/sites/default/files/24CompGuide-2016.jpg .
*/
#if defined(TRAXXAS_CYRF6936_INO)
#include "iface_cyrf6936.h"
//#define TRAXXAS_FORCE_ID
#define TRAXXAS_CHANNEL 0x05
#define TRAXXAS_BIND_CHANNEL 0x2B
#define TRAXXAS_PACKET_SIZE 16
enum {
TRAXXAS_BIND_PREP_RX=0,
TRAXXAS_BIND_RX,
TRAXXAS_BIND_TX1,
TRAXXAS_PREP_DATA,
TRAXXAS_DATA,
};
const uint8_t PROGMEM TRAXXAS_sop_bind[] ={ 0x3C, 0x37, 0xCC, 0x91, 0xE2, 0xF8, 0xCC, 0x91 };
const uint8_t PROGMEM TRAXXAS_sop_data[] ={ 0xA1, 0x78, 0xDC, 0x3C, 0x9E, 0x82, 0xDC, 0x3C };
//const uint8_t PROGMEM TRAXXAS_sop_check[]={ 0x97, 0xE5, 0x14, 0x72, 0x7F, 0x1A, 0x14, 0x72 };
const uint8_t PROGMEM TRAXXAS_init_vals[][2] = {
//Init from dump
{CYRF_0B_PWR_CTRL, 0x00}, // PMU
{CYRF_32_AUTO_CAL_TIME, 0x3C}, // Default init value
{CYRF_35_AUTOCAL_OFFSET, 0x14}, // Default init value
{CYRF_1B_TX_OFFSET_LSB, 0x55}, // Default init value
{CYRF_1C_TX_OFFSET_MSB, 0x05}, // Default init value
{CYRF_28_CLK_EN, 0x02}, // Force Receive Clock Enable
{CYRF_06_RX_CFG, 0x88 | 0x02}, // AGC enabled, Fast Turn Mode enabled, adding overwrite enable to not lockup RX
{CYRF_1E_RX_OVERRIDE, 0x08}, // Reject packets with 0 seed
{CYRF_03_TX_CFG, 0x08 | CYRF_BIND_POWER}, // 8DR Mode, 32 chip codes
};
static void __attribute__((unused)) TRAXXAS_cyrf_bind_config()
{
CYRF_PROGMEM_ConfigSOPCode(TRAXXAS_sop_bind);
CYRF_WriteRegister(CYRF_15_CRC_SEED_LSB, 0x5A);
CYRF_WriteRegister(CYRF_16_CRC_SEED_MSB, 0x5A);
CYRF_ConfigRFChannel(TRAXXAS_BIND_CHANNEL);
}
static void __attribute__((unused)) TRAXXAS_cyrf_data_config()
{
CYRF_PROGMEM_ConfigSOPCode(TRAXXAS_sop_data);
#ifdef TRAXXAS_FORCE_ID // data taken from TX dump
CYRF_WriteRegister(CYRF_15_CRC_SEED_LSB, 0x1B);
CYRF_WriteRegister(CYRF_16_CRC_SEED_MSB, 0x3F);
#else
CYRF_WriteRegister(CYRF_15_CRC_SEED_LSB, cyrfmfg_id[0]+0xB6);
CYRF_WriteRegister(CYRF_16_CRC_SEED_MSB, cyrfmfg_id[1]+0x5D);
#endif
CYRF_ConfigRFChannel(TRAXXAS_CHANNEL);
CYRF_SetTxRxMode(TX_EN);
}
static void __attribute__((unused)) TRAXXAS_send_data_packet()
{
packet[0] = 0x01;
memset(&packet[1],0x00,TRAXXAS_PACKET_SIZE-1);
//Steering
uint16_t ch = convert_channel_16b_nolimit(RUDDER,500,1000);
packet[2]=ch>>8;
packet[3]=ch;
//Throttle
ch = convert_channel_16b_nolimit(THROTTLE,500,1000);
packet[4]=ch>>8;
packet[5]=ch;
//AUX3
ch = convert_channel_16b_nolimit(AILERON,500,1000);
packet[6]=ch>>8;
packet[7]=ch;
//AUX4???
ch = convert_channel_16b_nolimit(ELEVATOR,500,1000);
packet[12]=ch>>8;
packet[13]=ch;
CYRF_SetPower(0x08);
CYRF_WriteDataPacketLen(packet, TRAXXAS_PACKET_SIZE);
}
uint16_t ReadTRAXXAS()
{
uint8_t status;
switch(phase)
{
case TRAXXAS_BIND_PREP_RX:
TRAXXAS_cyrf_bind_config();
CYRF_SetTxRxMode(RX_EN); //Receive mode
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83); //Prepare to receive
packet_count=100; //Timeout for RX
phase=TRAXXAS_BIND_RX;
return 700;
case TRAXXAS_BIND_RX:
//Read data from RX
status = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((status & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
status |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
debugln("s=%02X",status);
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read
if((status & 0x07) == 0x02)
{ // Data received with no errors
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
debugln("L=%02X",len)
if(len==TRAXXAS_PACKET_SIZE)
{
CYRF_ReadDataPacketLen(packet, TRAXXAS_PACKET_SIZE);
debug("RX=");
for(uint8_t i=0;i<TRAXXAS_PACKET_SIZE;i++)
debug(" %02X",packet[i]);
debugln("");
for(uint8_t i=0;i<6;i++)
packet[i+1]=cyrfmfg_id[i];
packet[10]=0x01;
packet_count=12;
CYRF_SetTxRxMode(TX_EN);
phase=TRAXXAS_BIND_TX1;
return 200;
}
}
if( --packet_count == 0 )
{ // Retry RX
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Enable RX abort
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24); // Force end state
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Disable RX abort
if(--bind_counter != 0)
phase=TRAXXAS_BIND_PREP_RX; // Retry receiving bind packet
else
phase=TRAXXAS_PREP_DATA; // Abort binding
}
return 700;
case TRAXXAS_BIND_TX1:
CYRF_WriteDataPacketLen(packet, TRAXXAS_PACKET_SIZE);
debug("P=");
for(uint8_t i=0;i<TRAXXAS_PACKET_SIZE;i++)
debug(" %02X",packet[i]);
debugln("");
if(--packet_count==0) // Switch to normal mode
phase=TRAXXAS_PREP_DATA;
break;
case TRAXXAS_PREP_DATA:
BIND_DONE;
TRAXXAS_cyrf_data_config();
phase++;
case TRAXXAS_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(13940);
#endif
TRAXXAS_send_data_packet();
break;
}
return 13940;
}
uint16_t initTRAXXAS()
{
CYRF_Reset();
//Config CYRF registers
for(uint8_t i = 0; i < sizeof(TRAXXAS_init_vals) / 2; i++)
CYRF_WriteRegister(pgm_read_byte_near(&TRAXXAS_init_vals[i][0]), pgm_read_byte_near(&TRAXXAS_init_vals[i][1]));
//Read CYRF ID
CYRF_GetMfgData(cyrfmfg_id);
cyrfmfg_id[0]+=RX_num;
#ifdef TRAXXAS_FORCE_ID // data taken from TX dump
cyrfmfg_id[0]=0x65; // CYRF MFG ID
cyrfmfg_id[1]=0xE2;
cyrfmfg_id[2]=0x5E;
cyrfmfg_id[3]=0x55;
cyrfmfg_id[4]=0x4D;
cyrfmfg_id[5]=0xFE;
#endif
if(IS_BIND_IN_PROGRESS)
{
bind_counter=100;
phase = TRAXXAS_BIND_PREP_RX;
}
else
phase = TRAXXAS_PREP_DATA;
return 1000;
}
/*
Bind phase 1
CHANNEL: 0x2B
SOP_CODE: 0x3C 0x37 0xCC 0x91 0xE2 0xF8 0xCC 0x91
CRC_SEED_LSB: 0x5A
CRC_SEED_MSB: 0x5A
RX1: 0x02 0x4A 0xA3 0x2D 0x1A 0x49 0xFE 0x06 0x00 0x00 0x02 0x01 0x06 0x06 0x00 0x00
TX1: 0x02 0x65 0xE2 0x5E 0x55 0x4D 0xFE 0xEE 0x00 0x00 0x01 0x01 0x06 0x05 0x00 0x00
Note: RX cyrfmfg_id is 0x4A,0xA3,0x2D,0x1A,0x49,0xFE and TX cyrfmfg_id is 0x65,0xE2,0x5E,0x55,0x4D,0xFE
Bind phase 2 (looks like normal mode?)
CHANNEL: 0x05
SOP_CODE: 0xA1 0x78 0xDC 0x3C 0x9E 0x82 0xDC 0x3C
CRC_SEED_LSB: 0x1B
CRC_SEED_MSB: 0x3F
RX2: 0x03 0x4A 0xA3 0x2D 0x1A 0x49 0xFE 0x06 0x00 0x00 0x02 0x01 0x06 0x06 0x00 0x00
TX2: 0x01 0x65 0x01 0xF4 0x03 0xE7 0x02 0x08 0x00 0x00 0x01 0x01 0x02 0xEE 0x00 0x00
Note: TX2 is nearly a normal packet at the exception of the 2nd byte equal to cyrfmfg_id[0]
Bind phase 3 (check?)
CHANNEL: 0x22
SOP_CODE: 0x97 0xE5 0x14 0x72 0x7F 0x1A 0x14 0x72
CRC_SEED_LSB: 0xA5
CRC_SEED_MSB: 0xA5
RX3: 0x04 0x4A 0xA3 0x2D 0x1A 0x49 0xFE 0x06 0x00 0x00 0x02 0x01 0x06 0x06 0x00 0x00
Switch to normal mode
CHANNEL: 0x05
SOP_CODE: 0xA1 0x78 0xDC 0x3C 0x9E 0x82 0xDC 0x3C
CRC_SEED_LSB: 0x1B
CRC_SEED_MSB: 0x3F
TX3: 0x01 0x00 0x02 0xA8 0x03 0xE7 0x02 0x08 0x00 0x00 0x01 0x01 0x02 0xEE 0x00 0x00
*/
#endif

View File

@@ -40,11 +40,31 @@
#define CHANNEL_MAX_125 2047 // 125%
#define CHANNEL_MIN_125 0 // 125%
#define CHANNEL_MID 1024
#define CHANNEL_MIN_COMMAND 784 // 1350us
#define CHANNEL_SWITCH 1104 // 1550us
#define CHANNEL_MAX_COMMAND 1424 // 1750us
//Channel definitions
#define CH1 0
#define CH2 1
#define CH3 2
#define CH4 3
#define CH5 4
#define CH6 5
#define CH7 6
#define CH8 7
#define CH9 8
#define CH10 9
#define CH11 10
#define CH12 11
#define CH13 12
#define CH14 13
#define CH15 14
#define CH16 15
//Channel order
#ifdef AETR
#define AILERON 0
#define ELEVATOR 1
@@ -192,20 +212,3 @@
#define THROTTLE 1
#define RUDDER 0
#endif
#define CH1 0
#define CH2 1
#define CH3 2
#define CH4 3
#define CH5 4
#define CH6 5
#define CH7 6
#define CH8 7
#define CH9 8
#define CH10 9
#define CH11 10
#define CH12 11
#define CH13 12
#define CH14 13
#define CH15 14
#define CH16 15

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,182 @@
/*
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 Tiger Drone 1400782.
#if defined(TIGER_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define TIGER_FORCE_ID
#define TIGER_INITIAL_WAIT 500
#define TIGER_PACKET_PERIOD 3940
#define TIGER_RF_NUM_CHANNELS 4
#define TIGER_BIND_RF_NUM_CHANNELS 8
#define TIGER_PAYLOAD_SIZE 16
#define TIGER_BIND_COUNT 761 //3sec
static uint8_t __attribute__((unused)) TIGER_convert_channel(uint8_t num)
{
uint8_t val=convert_channel_8b(num);
// 7F..01=left, 00=center, 80..FF=right
if(val==0x80)
val=0; // 0
else
if(val>0x80)
val--; // 80..FE
else
{
val=0x80-val; // 80..01
if(val==0x80)
val--; // 7F..01
}
return val;
}
static void __attribute__((unused)) TIGER_send_packet()
{
if(IS_BIND_DONE)
{
//Channels
packet[0]=convert_channel_8b(THROTTLE); // 00..FF
packet[1]=TIGER_convert_channel(RUDDER); // 7F..01=left, 00=center, 80..FF=right
packet[2]=TIGER_convert_channel(ELEVATOR); // 7F..01=down, 00=center, 80..FF=up
packet[3]=TIGER_convert_channel(AILERON); // 7F..01=left, 00=center, 80..FF=right
//Flags
packet[14]= GET_FLAG(CH5_SW, 0x04) //FLIP
| GET_FLAG(CH6_SW, 0x10); //LIGHT
}
//Check
crc8=0;
for(uint8_t i=0;i<TIGER_PAYLOAD_SIZE-1;i++)
crc8+=packet[i];
packet[TIGER_PAYLOAD_SIZE-1]=crc8;
//Hopping frequency
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no>>1]);
hopping_frequency_no++;
if(IS_BIND_IN_PROGRESS)
{
if(hopping_frequency_no>=2*TIGER_BIND_RF_NUM_CHANNELS)
hopping_frequency_no=0;
}
else
{
if(hopping_frequency_no>=2*(TIGER_BIND_RF_NUM_CHANNELS+TIGER_RF_NUM_CHANNELS))
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
XN297_WritePayload(packet, TIGER_PAYLOAD_SIZE);
//Set tx_power
NRF24L01_SetPower();
}
static void __attribute__((unused)) TIGER_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t *)"\x68\x94\xA6\xD5\xC3", 5);
NRF24L01_FlushTx();
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_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // No retransmits
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
NRF24L01_Activate(0x73);
// 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()
{
#ifdef TIGER_FORCE_ID
rx_tx_addr[0]=0x64;
rx_tx_addr[1]=0x39;
rx_tx_addr[2]=0x12;
rx_tx_addr[3]=0x00;
rx_tx_addr[4]=0x00;
memcpy(hopping_frequency,"\x0E\x39\x1C\x07\x24\x3E\x2B\x47",TIGER_BIND_RF_NUM_CHANNELS);
memcpy(&hopping_frequency[TIGER_BIND_RF_NUM_CHANNELS],"\x36\x41\x37\x4E",TIGER_RF_NUM_CHANNELS);
#endif
//prepare bind packet
memset(&packet[0], 0x00, 4);
memset(&packet[4], 0x40, 10);
memcpy(&packet[7], rx_tx_addr, 5);
packet[14]=0xC0;
}
uint16_t TIGER_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(TIGER_PACKET_PERIOD);
#endif
if(IS_BIND_IN_PROGRESS)
if(--bind_counter==0)
{
BIND_DONE;
XN297_SetTXAddr((uint8_t *)"\x49\xA6\x83\xEB\x4B", 5);
}
TIGER_send_packet();
return TIGER_PACKET_PERIOD;
}
uint16_t initTIGER()
{
BIND_IN_PROGRESS; // autobind protocol
TIGER_initialize_txid();
TIGER_init();
hopping_frequency_no = 0;
bind_counter=TIGER_BIND_COUNT;
return TIGER_INITIAL_WAIT;
}
#endif
/*Bind
- RF setup: 1Mbps, scrambled, CRC
- TX addr: 0x68 0x94 0xA6 0xD5 0xC3
- 8 RF channels: 0x0E 0x39 0x1C 0x07 0x24 0x3E 0x2B 0x47
- 2 packets per RF channel, 3940µs between packets
- payload 16 bytes: 0x00 0x00 0x00 0x00 0x40 0x40 0x40 0x64 0x39 0x12 0x00 0x00 0x40 0x40 0xC0 0xAF
- payload[15]=sum of payload[0..14]
- the only difference with normal packets is the payload[14]=0xC0
- ??? payload[7..11] TX ID ???
Normal
- RF setup: 1Mbps
- TX addr: 0x49 0xA6 0x83 0xEB 0x4B
- 4 RF channels: 0x36 0x41 0x37 0x4E
- 2 packets per RF channel, 3940µs between packets
- payload 16 bytes: 0x00 0x00 0x00 0x00 0x40 0x40 0x40 0x64 0x39 0x12 0x00 0x00 0x40 0x40 0x00 0xEF
- payload[15]=sum of payload[0..14]
- throttle is on payload[0] 00..FF
- rudder is on payload[1] 00=center, 80..FF=right, 01..7F=left
- elevator is on payload[2] 00=center, 80..FF=up, 01..7F=down
- aileron is on payload[3] 00=center, 80..FF=right, 01..7F=left
- trims payload[4..6]
- ??? payload[7..11] TX ID ???
- ??? payload[12..13] ???
- flip is on payload[14] and flag 0x04
- light is on payload[14] and flag 0x10
*/

View File

@@ -264,6 +264,9 @@ uint16_t ReadV2x2()
case V202_DATA:
if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED)
return V2X2_PACKET_CHKTIME;
#ifdef MULTI_SYNC
telemetry_set_input_sync(V2X2_PACKET_PERIOD);
#endif
V2X2_send_packet(0);
break;
}

View File

@@ -0,0 +1,198 @@
/*
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/>.
Thanks to Goebish ,Ported from his deviation firmware
*/
#if defined(V761_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define V761_PACKET_PERIOD 7060 // Timeout for callback in uSec
#define V761_INITIAL_WAIT 500
#define V761_PACKET_SIZE 8
#define V761_BIND_COUNT 200
//Fx chan management
#define V761_BIND_FREQ 0x28
#define V761_RF_NUM_CHANNELS 3
enum
{
V761_BIND1 = 0,
V761_BIND2,
V761_DATA
};
static void __attribute__((unused)) V761_set_checksum()
{
uint8_t checksum = packet[0];
for(uint8_t i=1; i<V761_PACKET_SIZE-2; i++)
checksum += packet[i];
if(phase == V761_BIND1)
{
packet[6] = checksum ^ 0xff;
packet[7] = packet[6];
}
else
{
checksum += packet[6];
packet[7] = checksum ^ 0xff;
}
}
static void __attribute__((unused)) V761_send_packet()
{
if(phase != V761_DATA)
{
packet[0] = rx_tx_addr[0];
packet[1] = rx_tx_addr[1];
packet[2] = rx_tx_addr[2];
packet[3] = rx_tx_addr[3];
packet[4] = hopping_frequency[1];
packet[5] = hopping_frequency[2];
if(phase == V761_BIND2)
packet[6] = 0xf0; // ?
}
else
{
packet[0] = convert_channel_8b(THROTTLE); // throttle
packet[1] = convert_channel_8b(RUDDER)>>1; // rudder
packet[2] = convert_channel_8b(ELEVATOR)>>1; // elevator
packet[3] = convert_channel_8b(AILERON)>>1; // aileron
packet[5] = (packet_count++ / 3)<<6;
packet[4] = (packet[5] == 0x40) ? 0x1a : 0x20;
// Channel 5 - Gyro mode is packet 5
if(CH5_SW) // Mode Expert Gyro off
flags = 0x0c;
else
if(Channel_data[CH5] < CHANNEL_MIN_COMMAND)
flags = 0x08; // Beginer mode (Gyro on, yaw and pitch rate limited)
else
flags = 0x0a; // Mid Mode ( Gyro on no rate limits)
packet[5] |= flags;
packet[6] = 0x80; // unknown
//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;
}
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();
XN297_WritePayload(packet, V761_PACKET_SIZE);
NRF24L01_SetPower();
}
static void __attribute__((unused)) V761_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
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_03_SETUP_AW, 0x02); // set address length (4 bytes)
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
NRF24L01_Activate(0x73);
}
static void __attribute__((unused)) V761_initialize_txid()
{
// TODO: try arbitrary rx_tx_addr & frequencies (except hopping_frequency[0])
switch(RX_num%3)
{
case 1: //Dump from air on Protonus TX
memcpy(rx_tx_addr,(uint8_t *)"\xE8\xE4\x45\x09",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x21\x44",3);
break;
case 2: //Dump from air on mshagg2 TX
memcpy(rx_tx_addr,(uint8_t *)"\xAE\xD1\x45\x09",4);
memcpy(hopping_frequency,(uint8_t *)"\x13\x1D\x4A",3);
break;
default: //Dump from SPI
memcpy(rx_tx_addr,(uint8_t *)"\x6f\x2c\xb1\x93",4);
memcpy(hopping_frequency,(uint8_t *)"\x14\x1e\x4b",3);
break;
}
}
uint16_t V761_callback()
{
switch(phase)
{
case V761_BIND1:
if(bind_counter)
bind_counter--;
packet_count ++;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, V761_BIND_FREQ);
XN297_SetTXAddr((uint8_t*)"\x34\x43\x10\x10", 4);
V761_send_packet();
if(packet_count >= 20)
{
packet_count = 0;
phase = V761_BIND2;
}
return 15730;
case V761_BIND2:
if(bind_counter)
bind_counter--;
packet_count ++;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[0]);
XN297_SetTXAddr(rx_tx_addr, 4);
V761_send_packet();
if(bind_counter == 0)
{
phase = V761_DATA;
BIND_DONE;
}
else if(packet_count >= 20)
{
packet_count = 0;
phase = V761_BIND1;
}
return 15730;
case V761_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(V761_PACKET_PERIOD);
#endif
V761_send_packet();
break;
}
return V761_PACKET_PERIOD;
}
uint16_t initV761(void)
{
BIND_IN_PROGRESS;
bind_counter = V761_BIND_COUNT;
V761_initialize_txid();
phase = V761_BIND1;
V761_init();
hopping_frequency_no = 0;
packet_count = 0;
return V761_INITIAL_WAIT;
}
#endif

View File

@@ -16,7 +16,7 @@
#if defined(V911S_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_nrf250k.h"
//#define V911S_ORIGINAL_ID
@@ -30,6 +30,8 @@
// flags going to packet[1]
#define V911S_FLAG_EXPERT 0x04
#define E119_FLAG_EXPERT 0x08
#define E119_FLAG_CALIB 0x40
// flags going to packet[2]
#define V911S_FLAG_CALIB 0x01
@@ -56,10 +58,21 @@ static void __attribute__((unused)) V911S_send_packet(uint8_t bind)
}
if(rf_ch_num&2)
channel=7-channel;
XN297L_Hopping(channel);
hopping_frequency_no++;
hopping_frequency_no&=7; // 8 RF channels
packet[ 0]=(rf_ch_num<<3)|channel;
packet[ 1]=V911S_FLAG_EXPERT; // short press on left button
packet[ 2]=GET_FLAG(CH5_SW,V911S_FLAG_CALIB); // long press on right button
memset(packet+3, 0x00, V911S_PACKET_SIZE - 3);
memset(packet+1, 0x00, V911S_PACKET_SIZE - 1);
if(sub_protocol==V911S_STD)
{
packet[ 1]=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[3..6]=trims TAER signed
uint16_t ch=convert_channel_16b_limit(THROTTLE ,0,0x7FF);
packet[ 7] = ch;
@@ -68,42 +81,44 @@ static void __attribute__((unused)) V911S_send_packet(uint8_t bind)
packet[ 8]|= ch<<3;
packet[ 9] = ch>>5;
ch=convert_channel_16b_limit(ELEVATOR,0,0x7FF);
packet[10] = ch;
packet[11] = ch>>8;
ch=convert_channel_16b_limit(RUDDER ,0x7FF,0);
packet[11]|= ch<<3;
packet[12] = ch>>5;
if(sub_protocol==V911S_STD)
{
packet[10] = ch;
packet[11] = ch>>8;
ch=convert_channel_16b_limit(RUDDER ,0x7FF,0);
packet[11]|= ch<<3;
packet[12] = ch>>5;
}
else
{
ch=0x7FF-ch;
packet[ 9]|= ch<<6;
packet[10] = ch>>2;
packet[11] = ch>>10;
ch=convert_channel_16b_limit(RUDDER ,0x7FF,0);
packet[11]|= ch<<1;
packet[12] = ch>>7;
}
}
// Power on, TX mode, 2byte CRC
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
if (!bind)
{
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[channel]);
hopping_frequency_no++;
hopping_frequency_no&=7; // 8 RF channels
}
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(packet, V911S_PACKET_SIZE);
NRF24L01_SetPower(); // Set tx_power
if(sub_protocol==V911S_STD)
XN297L_WritePayload(packet, V911S_PACKET_SIZE);
else
XN297L_WriteEnhancedPayload(packet, V911S_PACKET_SIZE, bind?0:1);
XN297L_SetPower(); // Set tx_power
XN297L_SetFreqOffset(); // Set frequency offset
}
static void __attribute__((unused)) V911S_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t *)"\x4B\x4E\x42\x4E\x44", 5); // Bind address
NRF24L01_WriteReg(NRF24L01_05_RF_CH, V911S_RF_BIND_CHANNEL); // Bind channel
NRF24L01_FlushTx();
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_SetBitrate(NRF24L01_BR_250K); // 250Kbps
NRF24L01_SetPower();
XN297L_Init();
if(sub_protocol==V911S_STD)
XN297L_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
}
static void __attribute__((unused)) V911S_initialize_txid()
@@ -121,7 +136,12 @@ static void __attribute__((unused)) V911S_initialize_txid()
uint16_t V911S_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(V911S_PACKET_PERIOD);
#endif
V911S_send_packet(0);
}
else
{
if (bind_counter == 0)
@@ -145,15 +165,30 @@ uint16_t initV911S(void)
{
V911S_initialize_txid();
#ifdef V911S_ORIGINAL_ID
rx_tx_addr[0]=0xA5;
rx_tx_addr[1]=0xFF;
rx_tx_addr[2]=0x70;
rx_tx_addr[3]=0x8D;
rx_tx_addr[4]=0x76;
for(uint8_t i=0;i<V911S_NUM_RF_CHANNELS;i++)
hopping_frequency[i]=0x10+i*5;
hopping_frequency[0]++;
rf_ch_num=0;
if(sub_protocol==V911S_STD)
{//V911S
rx_tx_addr[0]=0xA5;
rx_tx_addr[1]=0xFF;
rx_tx_addr[2]=0x70;
rx_tx_addr[3]=0x8D;
rx_tx_addr[4]=0x76;
for(uint8_t i=0;i<V911S_NUM_RF_CHANNELS;i++)
hopping_frequency[i]=0x10+i*5;
hopping_frequency[0]++;
rf_ch_num=0;
}
else
{
//E119
rx_tx_addr[0]=0x30;
rx_tx_addr[1]=0xFF;
rx_tx_addr[2]=0xD1;
rx_tx_addr[3]=0x2C;
rx_tx_addr[4]=0x2A;
for(uint8_t i=0;i<V911S_NUM_RF_CHANNELS;i++)
hopping_frequency[i]=0x0E + i*5;
rf_ch_num=0;
}
#endif
V911S_init();

View File

@@ -18,10 +18,10 @@
#endif
#endif
// Check for minimum version of multi-module boards
#define MIN_AVR_BOARD 103
#define MIN_ORX_BOARD 103
#define MIN_STM32_BOARD 104
// Check for minimum board file definition version for DIY multi-module boards
#define MIN_AVR_BOARD 110
#define MIN_ORX_BOARD 110
#define MIN_STM32_BOARD 117
//AVR
#if (defined(ARDUINO_MULTI_NO_BOOT) && ARDUINO_MULTI_NO_BOOT < MIN_AVR_BOARD) || (defined(ARDUINO_MULTI_FLASH_FROM_TX) && ARDUINO_MULTI_FLASH_FROM_TX < MIN_AVR_BOARD)
#error You need to update your Multi 4-in-1 board definition. Open Boards Manager and update to the latest version of the Multi 4-in-1 AVR Boards.
@@ -35,6 +35,11 @@
#error You need to update your Multi 4-in-1 board definition. Open Boards Manager and update to the latest version of the Multi 4-in-1 STM32 Board.
#endif
// Enable serial debugging if a debugging option was chosen in the IDE
#ifdef ARDUINO_MULTI_DEBUG
#define DEBUG_SERIAL
#endif
// Error if CHECK_FOR_BOOTLOADER is not enabled but a FLASH_FROM_TX board is selected
#if (defined(ARDUINO_MULTI_FLASH_FROM_TX) || defined(ARDUINO_MULTI_STM32_FLASH_FROM_TX)) &! defined(CHECK_FOR_BOOTLOADER)
#if defined(STM32_BOARD)
@@ -44,9 +49,10 @@
#endif
#endif
// Error if CHECK_FOR_BOOTLOADER is enabled but the 'Flash from TX' bootloader
// Warning if CHECK_FOR_BOOTLOADER is enabled but no bootloader
#if defined(ARDUINO_MULTI_NO_BOOT) && defined(CHECK_FOR_BOOTLOADER)
#error "You have enabled CHECK_FOR_BOOTLOADER but not selected the 'Flash from TX' bootloader."
#undef CHECK_FOR_BOOTLOADER
#warning "Disabling CHECK_FOR_BOOTLOADER since no bootloader is selected."
#endif
//Check number of banks
@@ -62,11 +68,22 @@
#endif
// Check forced tuning values are valid
//CC2500
#ifdef FORCE_CORONA_TUNING
#if ( FORCE_CORONA_TUNING < -127 ) || ( FORCE_CORONA_TUNING > 127 )
#error "The CORONA forced frequency tuning value is outside of the range -127..127."
#endif
#endif
#ifdef FORCE_FRSKYD_TUNING
#if ( FORCE_FRSKYD_TUNING < -127 ) || ( FORCE_FRSKYD_TUNING > 127 )
#error "The FrSkyD forced frequency tuning value is outside of the range -127..127."
#endif
#endif
#ifdef FORCE_FRSKYL_TUNING
#if ( FORCE_FRSKYL_TUNING < -127 ) || ( FORCE_FRSKYL_TUNING > 127 )
#error "The FrSkyL forced frequency tuning value is outside of the range -127..127."
#endif
#endif
#ifdef FORCE_FRSKYV_TUNING
#if ( FORCE_FRSKYV_TUNING < -127 ) || ( FORCE_FRSKYV_TUNING > 127 )
#error "The FrSkyV forced frequency tuning value is outside of the range -127..127."
@@ -77,19 +94,40 @@
#error "The FrSkyX forced frequency tuning value is outside of the range -127..127."
#endif
#endif
#ifdef FORCE_HITEC_TUNING
#if ( FORCE_HITEC_TUNING < -127 ) || ( FORCE_HITEC_TUNING > 127 )
#error "The HITEC forced frequency tuning value is outside of the range -127..127."
#endif
#endif
#ifdef FORCE_HOTT_TUNING
#if ( FORCE_HOTT_TUNING < -127 ) || ( FORCE_HOTT_TUNING > 127 )
#error "The HOTT forced frequency tuning value is outside of the range -127..127."
#endif
#endif
#ifdef FORCE_REDPINE_TUNING
#if ( FORCE_REDPINE_TUNING < -127 ) || ( FORCE_REDPINE_TUNING > 127 )
#error "The REDPINE forced frequency tuning value is outside of the range -127..127."
#endif
#endif
#ifdef FORCE_SFHSS_TUNING
#if ( FORCE_SFHSS_TUNING < -127 ) || ( FORCE_SFHSS_TUNING > 127 )
#error "The SFHSS forced frequency tuning value is outside of the range -127..127."
#endif
#endif
#ifdef FORCE_CORONA_TUNING
#if ( FORCE_CORONA_TUNING < -127 ) || ( FORCE_CORONA_TUNING > 127 )
#error "The CORONA forced frequency tuning value is outside of the range -127..127."
#ifdef FORCE_SKYARTEC_TUNING
#if ( FORCE_SKYARTEC_TUNING < -127 ) || ( FORCE_SKYARTEC_TUNING > 127 )
#error "The SKYARTEC forced frequency tuning value is outside of the range -127..127."
#endif
#endif
#ifdef FORCE_HITEC_TUNING
#if ( FORCE_HITEC_TUNING < -127 ) || ( FORCE_HITEC_TUNING > 127 )
#error "The HITEC forced frequency tuning value is outside of the range -127..127."
//A7105
#ifdef FORCE_AFHDS2A_TUNING
#if ( FORCE_AFHDS2A_TUNING < -300 ) || ( FORCE_AFHDS2A_TUNING > 300 )
#error "The AFHDS2A forced frequency tuning value is outside of the range -300..300."
#endif
#endif
#ifdef FORCE_BUGS_TUNING
#if ( FORCE_BUGS_TUNING < -300 ) || ( FORCE_BUGS_TUNING > 300 )
#error "The BUGS forced frequency tuning value is outside of the range -300..300."
#endif
#endif
#ifdef FORCE_FLYSKY_TUNING
@@ -97,20 +135,35 @@
#error "The Flysky forced frequency tuning value is outside of the range -300..300."
#endif
#endif
#ifdef FORCE_FLYZONE_TUNING
#if ( FORCE_FLYZONE_TUNING < -300 ) || ( FORCE_FLYZONE_TUNING > 300 )
#error "The Flyzone forced frequency tuning value is outside of the range -300..300."
#endif
#endif
#ifdef FORCE_PELIKAN_TUNING
#if ( FORCE_PELIKAN_TUNING < -300 ) || ( FORCE_PELIKAN_TUNING > 300 )
#error "The Pelikan forced frequency tuning value is outside of the range -300..300."
#endif
#endif
#ifdef FORCE_HUBSAN_TUNING
#if ( FORCE_HUBSAN_TUNING < -300 ) || ( FORCE_HUBSAN_TUNING > 300 )
#error "The Hubsan forced frequency tuning value is outside of the range -300..300."
#endif
#endif
#ifdef FORCE_AFHDS2A_TUNING
#if ( FORCE_AFHDS2A_TUNING < -300 ) || ( FORCE_AFHDS2A_TUNING > 300 )
#error "The AFHDS2A forced frequency tuning value is outside of the range -300..300."
#endif
#endif
#ifndef USE_A7105_CH15_TUNING
#ifndef FORCE_BUGS_TUNING
#define FORCE_BUGS_TUNING 0
#endif
#ifndef FORCE_FLYSKY_TUNING
#define FORCE_FLYSKY_TUNING 0
#endif
#ifndef FORCE_FLYZONE_TUNING
#define FORCE_FLYZONE_TUNING 0
#endif
#ifndef FORCE_PELIKAN_TUNING
#define FORCE_PELIKAN_TUNING 0
#endif
#ifndef FORCE_HUBSAN_TUNING
#define FORCE_HUBSAN_TUNING 0
#endif
@@ -119,6 +172,10 @@
#endif
#endif
#if defined (USE_CYRF6936_CH15_TUNING) && (DSM_THROTTLE_KILL_CH == 15)
#error "Error Channel 15 conflict between the CYRF6936 freq tuning and the DSM throttle kill feature."
#endif
//Change/Force configuration if OrangeTX
#ifdef ORANGE_TX
#undef ENABLE_PPM // Disable PPM for OrangeTX module
@@ -128,6 +185,7 @@
#undef CC25_CSN_pin
#undef NRF24L01_INSTALLED // Disable NRF for OrangeTX module
#undef NRF_CSN_pin
#undef SX1276_INSTALLED // Disable NRF for OrangeTX module
#define TELEMETRY // Enable telemetry
#define INVERT_TELEMETRY // Enable invert telemetry
#define DSM_TELEMETRY // Enable DSM telemetry
@@ -135,57 +193,92 @@
//Make sure protocols are selected correctly
#ifndef A7105_INSTALLED
#undef FLYSKY_A7105_INO
#undef HUBSAN_A7105_INO
#undef AFHDS2A_A7105_INO
#undef AFHDS2A_RX_A7105_INO
#undef BUGS_A7105_INO
#undef FLYSKY_A7105_INO
#undef FLYZONE_A7105_INO
#undef HUBSAN_A7105_INO
#undef PELIKAN_A7105_INO
#endif
#ifndef CYRF6936_INSTALLED
#undef DEVO_CYRF6936_INO
#undef DSM_CYRF6936_INO
#undef DSM_RX_CYRF6936_INO
#undef HOTT_CC2500_INO
#undef J6PRO_CYRF6936_INO
#undef TRAXXAS_CYRF6936_INO
#undef WFLY_CYRF6936_INO
#undef WK2x01_CYRF6936_INO
#undef TRAXXAS_CYRF6936_INO
#endif
#ifndef CC2500_INSTALLED
#undef CORONA_CC2500_INO
#undef ESKY150V2_CC2500_INO
#undef FRSKYD_CC2500_INO
#undef FRSKYL_CC2500_INO
#undef FRSKYV_CC2500_INO
#undef FRSKYX_CC2500_INO
#undef SFHSS_CC2500_INO
#undef CORONA_CC2500_INO
#undef FRSKY_RX_CC2500_INO
#undef HITEC_CC2500_INO
#undef HOTT_CC2500_INO
#undef REDPINE_CC2500_INO
#undef SCANNER_CC2500_INO
#undef SFHSS_CC2500_INO
#undef SKYARTEC_CC2500_INO
#endif
#ifndef NRF24L01_INSTALLED
#undef ASSAN_NRF24L01_INO
#undef BAYANG_NRF24L01_INO
#undef BAYANG_RX_NRF24L01_INO
#undef BUGSMINI_NRF24L01_INO
#undef CABELL_NRF24L01_INO
#undef CFLIE_NRF24L01_INO
#undef CG023_NRF24L01_INO
#undef CX10_NRF24L01_INO
#undef DM002_NRF24L01_INO
#undef E01X_NRF24L01_INO
#undef ESKY_NRF24L01_INO
#undef ESKY150_NRF24L01_INO
#undef ESKY150V2_CC2500_INO // Use both CC2500 and NRF code
#undef FQ777_NRF24L01_INO
#undef FX816_NRF24L01_INO
#undef FY326_NRF24L01_INO
#undef GD00X_NRF24L01_INO
#undef GW008_NRF24L01_INO
#undef H8_3D_NRF24L01_INO
#undef HISKY_NRF24L01_INO
#undef HONTAI_NRF24L01_INO
#undef JJRC345_NRF24L01_INO
#undef KF606_NRF24L01_INO
#undef KN_NRF24L01_INO
#undef MJXQ_NRF24L01_INO
#undef MT99XX_NRF24L01_INO
#undef NCC1701_NRF24L01_INO
#undef POTENSIC_NRF24L01_INO
#undef PROPEL_NRF24L01_INO
#undef Q303_NRF24L01_INO
#undef SHENQI_NRF24L01_INO
#undef SLT_NRF24L01_INO
#undef SYMAX_NRF24L01_INO
#undef TIGER_NRF24L01_INO
#undef V2X2_NRF24L01_INO
#undef YD717_NRF24L01_INO
#undef MT99XX_NRF24L01_INO
#undef MJXQ_NRF24L01_INO
#undef SHENQI_NRF24L01_INO
#undef FY326_NRF24L01_INO
#undef FQ777_NRF24L01_INO
#undef ASSAN_NRF24L01_INO
#undef HONTAI_NRF24L01_INO
#undef Q303_NRF24L01_INO
#undef GW008_NRF24L01_INO
#undef GD00X_NRF24L01_INO
#undef DM002_NRF24L01_INO
#undef CABELL_NRF24L01_INO
#undef ESKY150_NRF24L01_INO
#undef H8_3D_NRF24L01_INO
#undef CFLIE_NRF24L01_INO
#undef BUGSMINI_NRF24L01_INO
#undef NCC1701_NRF24L01_INO
#undef E01X_NRF24L01_INO
#undef V761_NRF24L01_INO
#undef V911S_NRF24L01_INO
#undef XK_NRF24L01_INO
#undef YD717_NRF24L01_INO
#undef ZSX_NRF24L01_INO
#endif
#if not defined(STM32_BOARD)
#undef SX1276_INSTALLED
#endif
#ifndef SX1276_INSTALLED
#undef FRSKYR9_SX1276_INO
#endif
//OpenTX 2.3.x issue
#if defined (FRSKYD_CC2500_INO) || defined(FRSKYV_CC2500_INO) || defined(FRSKYX_CC2500_INO)
#define FRSKYX_CC2500_INO
#define FRSKY_RX_CC2500_INO
#endif
//Make sure telemetry is selected correctly
@@ -202,21 +295,51 @@
#undef NCC1701_HUB_TELEMETRY
#undef HUB_TELEMETRY
#undef SPORT_TELEMETRY
#undef SPORT_POLLING
#undef SPORT_SEND
#undef DSM_TELEMETRY
#undef MULTI_STATUS
#undef MULTI_TELEMETRY
#undef SCANNER_TELEMETRY
#undef SCANNER_CC2500_INO
#undef FRSKY_RX_TELEMETRY
#undef FRSKY_RX_CC2500_INO
#undef AFHDS2A_RX_TELEMETRY
#undef AFHDS2A_RX_A7105_INO
#undef HOTT_FW_TELEMETRY
#undef BAYANG_RX_TELEMETRY
#undef BAYANG_RX_NRF24L01_INO
#undef DEVO_HUB_TELEMETRY
#undef DSM_RX_CYRF6936_INO
#else
#if defined MULTI_TELEMETRY && not defined INVERT_TELEMETRY
#warning MULTI_TELEMETRY has been defined but not INVERT_TELEMETRY. They should be both enabled for OpenTX telemetry and status to work.
#if defined(MULTI_TELEMETRY) && defined(MULTI_STATUS)
#error You should choose either MULTI_TELEMETRY or MULTI_STATUS but not both.
#endif
#if not defined(SCANNER_CC2500_INO) || not defined(SCANNER_TELEMETRY)
#undef SCANNER_TELEMETRY
#undef SCANNER_CC2500_INO
#endif
#if not defined(FRSKY_RX_CC2500_INO) || not defined(FRSKY_RX_TELEMETRY)
#undef FRSKY_RX_TELEMETRY
#undef FRSKY_RX_CC2500_INO
#endif
#if not defined(AFHDS2A_RX_A7105_INO) || not defined(AFHDS2A_RX_TELEMETRY)
#undef AFHDS2A_RX_TELEMETRY
#undef AFHDS2A_RX_A7105_INO
#endif
#if not defined(BAYANG_RX_NRF24L01_INO) || not defined(BAYANG_RX_TELEMETRY)
#undef BAYANG_RX_TELEMETRY
#undef BAYANG_RX_NRF24L01_INO
#endif
#if not defined(BAYANG_NRF24L01_INO)
#undef BAYANG_HUB_TELEMETRY
#endif
#if not defined(DEVO_CYRF6936_INO)
#undef DEVO_HUB_TELEMETRY
#endif
#if not defined(NCC1701_NRF24L01_INO)
#undef NCC1701_HUB_TELEMETRY
#endif
#if not ( defined(BUGS_A7105_INO) || defined(BUGSMINI_NRF24L01_INO) )
#if not defined(BUGS_A7105_INO) && not defined(BUGSMINI_NRF24L01_INO)
#undef BUGS_HUB_TELEMETRY
#endif
#if not defined(CABELL_NRF24L01_INO)
@@ -238,24 +361,40 @@
#endif
#if not defined(FRSKYX_CC2500_INO)
#undef SPORT_TELEMETRY
#undef SPORT_POLLING
#undef SPORT_SEND
#endif
#if not defined (SPORT_TELEMETRY) || not defined (STM32_BOARD)
#undef SPORT_POLLING
#endif
#if defined SPORT_POLLING && not defined INVERT_TELEMETRY
#error SPORT_POLLING has been defined but not INVERT_TELEMETRY. They should be both enabled to work.
#if not defined (SPORT_TELEMETRY)
#undef SPORT_SEND
#endif
#if not defined(DSM_CYRF6936_INO)
#undef DSM_TELEMETRY
#endif
#if 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(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)
#if not defined(HOTT_CC2500_INO)
#undef HOTT_FW_TELEMETRY
#endif
#if not defined(HOTT_FW_TELEMETRY) && not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BUGS_HUB_TELEMETRY) && not defined(NCC1701_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(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)
#undef TELEMETRY
#undef INVERT_TELEMETRY
#undef SPORT_POLLING
#undef MULTI_TELEMETRY
#undef MULTI_STATUS
#endif
#endif
#ifdef SPORT_TELEMETRY
#define SPORT_SEND
#endif
#if not defined(STM32_BOARD)
#undef MULTI_SYNC
#endif
#if not defined(MULTI_TELEMETRY)
#undef MULTI_SYNC
#undef MULTI_NAMES
#else
#define MULTI_NAMES
#endif
//Make sure TX is defined correctly
#ifndef AILERON
#error You must select a correct channel order.
@@ -303,3 +442,22 @@
#if MAX_PPM_CHANNELS>16
#error MAX_PPM_CHANNELS must be below or equal to 16. The default for this value is 16.
#endif
#if defined (STM32_BOARD) && defined (DEBUG_SERIAL) && defined (NRF24L01_INSTALLED)
#define XN297DUMP_NRF24L01_INO
#endif
//Check if Direct inputs defined correctly
#if defined (ENABLE_DIRECT_INPUTS)
#if not defined (STM32_BOARD) || not defined (ENABLE_PPM) || defined (ENABLE_SERIAL)
#error You can enable dirct inputs only in PPM mode and only for STM32 board.
#endif
#if not defined (DI1_PIN) && not defined (DI2_PIN) && not defined (DI3_PIN) && not defined (DI4_PIN)
#error You must define at least 1 direct input pin or undefine ENABLE_DIRECT_INPUTS in config.
#endif
#if not defined (DI_CH1_read) && not defined (DI_CH2_read) && not defined (DI_CH3_read) && not defined (DI_CH4_read)
#error You must define at least 1 direct input chanell read macros or undefine ENABLE_DIRECT_INPUTS in config.
#endif
#endif

View File

@@ -194,25 +194,25 @@ uint16_t ReadWFLY()
debugln("L=%02X",len)
if(len==0x10)
{
CYRF_ReadDataPacketLen(pkt, len);
CYRF_ReadDataPacketLen(packet_in, len);
debug("RX=");
for(uint8_t i=0;i<0x0F;i++)
{
debug(" %02X",pkt[i]);
if(pkt[i]==packet[i])
debug(" %02X",packet_in[i]);
if(packet_in[i]==packet[i])
check++; // Verify quickly the content
sum+=pkt[i];
sum+=packet_in[i];
}
debugln(" %02X",pkt[15]);
if(sum==pkt[15] && check>=10)
debugln(" %02X",packet_in[15]);
if(sum==packet_in[15] && check>=10)
{ // Good packet received
if(pkt[2]==0x64)
if(packet_in[2]==0x64)
{ // Switch to normal mode
BIND_DONE;
phase=WFLY_PREP_DATA;
return 10000;
}
memcpy((void *)packet,(void *)pkt,0x10); // Send back to the RX what we've just received with no modifications
memcpy((void *)packet,(void *)packet_in,0x10); // Send back to the RX what we've just received with no modifications
}
phase=WFLY_BIND_TX;
return 200;
@@ -232,6 +232,9 @@ uint16_t ReadWFLY()
packet_count=0;
phase++;
case WFLY_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(5371);
#endif
start=micros();
while ((uint8_t)((uint8_t)micros()-(uint8_t)start) < 200)
if((CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80) == 0x00)
@@ -253,7 +256,7 @@ uint16_t initWFLY()
rx_tx_addr[2]=0xBF; // ID
rx_tx_addr[3]=0x13; // ID
ch=0x16; // value seen between 0x0A and 0x17
rc_ch_num=0x15 // RF channel to send the current hopping table
rf_ch_num=0x15 // RF channel to send the current hopping table
#endif
debug("ID:")

View File

@@ -435,6 +435,9 @@ uint16_t WK_cb()
{
if (packet_sent == 0)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(2800);
#endif
packet_sent = 1;
if(sub_protocol == WK2801)
WK_BuildPacket_2801();

View File

@@ -0,0 +1,217 @@
/*
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 X450 and X420/X520 plane.
#if defined(XK_NRF24L01_INO)
#include "iface_nrf250k.h"
//#define FORCE_XK_ORIGINAL_ID
#define XK_INITIAL_WAIT 500
#define XK_PACKET_PERIOD 4000
#define XK_RF_BIND_NUM_CHANNELS 8
#define XK_RF_NUM_CHANNELS 4
#define XK_PAYLOAD_SIZE 16
#define XK_BIND_COUNT 750 //3sec
static uint16_t __attribute__((unused)) XK_convert_channel(uint8_t num)
{
uint16_t val=convert_channel_10b(num);
// 1FF..01=left, 00=center, 200..3FF=right
if(val==0x200)
val=0; // 0
else
if(val>0x200)
val--; // 200..3FE
else
{
val=0x200-val; // 200..01
if(val==0x200)
val--; // 1FF..01
}
return val;
}
static void __attribute__((unused)) XK_send_packet()
{
memset(packet,0x00,7);
memset(&packet[10],0x00,5);
packet[12]=0x40;
packet[13]=0x40;
if(IS_BIND_IN_PROGRESS)
packet[14] = 0xC0;
else
{
uint16_t val=convert_channel_10b(THROTTLE);
packet[0] = val>>2; // 0..255
//packet[12] |= val & 2;
val=XK_convert_channel(RUDDER);
packet[1] = val>>2;
//packet[12] |= (val & 2)<<2;
val=XK_convert_channel(ELEVATOR);
packet[2] = val>>2;
//packet[13] |= val & 2;
val=XK_convert_channel(AILERON);
packet[3] = val>>2;
//packet[13] |= (val & 2)<<2;
memset(&packet[4],0x40,3); // Trims
if(Channel_data[CH5] > CHANNEL_MAX_COMMAND)
packet[10] = 0x10; // V-Mode
else
if(Channel_data[CH5] > CHANNEL_MIN_COMMAND)
packet[10] = 0x04; // 6G-Mode
//0x00 default M-Mode
packet[10] |= GET_FLAG(CH7_SW,0x80); // Emergency stop momentary switch
packet[11] = GET_FLAG(CH8_SW,0x03) // 3D/6G momentary switch
|GET_FLAG(CH6_SW,0x40); // Take off momentary switch
packet[14] = GET_FLAG(CH9_SW,0x01) // Photo momentary switch
|GET_FLAG(CH10_SW,0x2); // Video momentary switch
}
crc=packet[0];
for(uint8_t i=1; i<XK_PAYLOAD_SIZE-1;i++)
crc+=packet[i];
packet[15]=crc;
// debug("C: %02X, P:",hopping_frequency[(IS_BIND_IN_PROGRESS?0:XK_RF_BIND_NUM_CHANNELS)+(hopping_frequency_no>>1)]);
XN297L_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;
XN297L_WritePayload(packet, XK_PAYLOAD_SIZE);
// for(uint8_t i=0; i<XK_PAYLOAD_SIZE; i++)
// debug(" %02X",packet[i]);
// debugln("");
XN297L_SetPower(); // Set tx_power
XN297L_SetFreqOffset(); // Set frequency offset
}
const uint8_t PROGMEM XK_bind_hop[XK_RF_BIND_NUM_CHANNELS]= { 0x07, 0x24, 0x3E, 0x2B, 0x47, 0x0E, 0x39, 0x1C }; // Bind
const uint8_t PROGMEM XK_tx_addr[]= { 0xB3, 0x67, 0xE9, 0x98, 0x3A, 0xEC, 0xA6, 0x59, 0xB2, 0x94, 0x2B, 0xA5, 0x37, 0xC5, 0x4A, 0xD3,
0x49, 0xA6, 0x83, 0xEB, 0x4B, 0xC9, 0x59, 0xD2, 0x65, 0x34, 0x6A, 0xD3, 0x2C, 0x96, 0x2A, 0xA9,
0x32, 0xB2, 0xB4, 0x49, 0xD3, 0x37, 0xE9 };
const uint8_t PROGMEM XK_hop[]= { 0x47, 0x3A, 0x4C, 0x39, 0x4D, 0x34, 0x4A, 0x3F, 0x45, 0x3E, 0x4B, 0x3D, 0x3B, 0x48, 0x40, 0x49,
0x46, 0x3C, 0x43, 0x38, 0x35, 0x42, 0x33, 0x44, 0x4E, 0x37, 0x44, 0x35, 0x37, 0x4E, 0x36, 0x41 };
static void __attribute__((unused)) XK_initialize_txid()
{
//bind hop
for(uint8_t i=0; i<XK_RF_BIND_NUM_CHANNELS; i++)
hopping_frequency[i]=pgm_read_byte_near( &XK_bind_hop[i] );
//GID
packet[7]=rx_tx_addr[1];
packet[8]=rx_tx_addr[2];
packet[9]=rx_tx_addr[3];
uint8_t sum=packet[7]+packet[8]+packet[9];
// debugln("GID=%02X %02X %02X, sum=%d", packet[7],packet[8],packet[9],sum);
//Normal hop
uint8_t start=(sum&0x07)<<2;
// debug("start=%d, hop=",start);
for(uint8_t i=0; i<XK_RF_NUM_CHANNELS; i++)
{
hopping_frequency[ i + XK_RF_BIND_NUM_CHANNELS ]=pgm_read_byte_near( &XK_hop[ start + i ] );
// debug("%02X ", hopping_frequency[ i + XK_RF_BIND_NUM_CHANNELS ]);
}
// debugln("");
//Normal packet address
start=(sum&0x1F)+((sum>>5)&0x03);
// debug("start=%d, addr=",start);
for(uint8_t i=0; i<5; i++)
{
rx_tx_addr[i]=pgm_read_byte_near( &XK_tx_addr[ start + i ] );
// debug("%02X ", rx_tx_addr[ i ]);
}
// debugln("");
#ifdef FORCE_XK_ORIGINAL_ID
switch(RX_num%2)
{
default:
//TX1 X8 X450
//GID
packet[7]=0x04;
packet[8]=0x15;
packet[9]=0x22;
//Normal hop
memcpy(&hopping_frequency[XK_RF_BIND_NUM_CHANNELS],(uint8_t*)"\x3B\x48\x40\x49", XK_RF_NUM_CHANNELS); // freq and order verified
//Normal packet address
memcpy(rx_tx_addr,(uint8_t*)"\x2C\x96\x2A\xA9\x32",5);
break;
case 1:
//TX2 X4 X420
//GID
packet[7]=0x13;
packet[8]=0x24;
packet[9]=0x18;
//Normal hop
memcpy(&hopping_frequency[XK_RF_BIND_NUM_CHANNELS],(uint8_t*)"\x36\x41\x37\x4E", XK_RF_NUM_CHANNELS); // freq ok and order from xn297dump auto
//Normal packet address
memcpy(rx_tx_addr,(uint8_t*)"\xA6\x83\xEB\x4B\xC9",5);
break;
}
#endif
}
static void __attribute__((unused)) XK_init()
{
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
}
uint16_t XK_callback()
{
if(sub_protocol==X420)
option=0; // Forcing the use of NRF24L01@1Mbps
#ifdef MULTI_SYNC
telemetry_set_input_sync(XK_PACKET_PERIOD);
#endif
if(IS_BIND_IN_PROGRESS)
if(--bind_counter==0)
{
BIND_DONE;
XN297L_SetTXAddr(rx_tx_addr, 5); // Normal packets address
}
XK_send_packet();
return XK_PACKET_PERIOD;
}
uint16_t initXK()
{
if(sub_protocol==X420)
option=prev_option=0; // Forcing the use of NRF24L01@1Mbps
BIND_IN_PROGRESS; // Autobind protocol
XK_initialize_txid();
XK_init();
if(sub_protocol==X420)
NRF24L01_SetBitrate(NRF24L01_BR_1M); // X420/X520 runs @1Mbps
hopping_frequency_no = 0;
bind_counter=XK_BIND_COUNT;
return XK_INITIAL_WAIT;
}
#endif

View File

@@ -0,0 +1,658 @@
/*
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/>.
*/
// sub_protocol: 0=250Kbps, 1=1Mbps, 2=2Mbps. Other values default to 1Mbps.
// RX_num = address length 3 or 4 or 5. Other values default to 5.
// option = RF channel number 0..84 and -1 = scan all channels. Other values default to RF channel 0.
#ifdef XN297DUMP_NRF24L01_INO
#include "iface_nrf24l01.h"
// Parameters which can be modified
#define XN297DUMP_PERIOD_SCAN 50000 // 25000
#define XN297DUMP_MAX_RF_CHANNEL 84 // Default 84
// Do not touch from there
#define XN297DUMP_INITIAL_WAIT 500
#define XN297DUMP_MAX_PACKET_LEN 32
#define XN297DUMP_CRC_LENGTH 2
uint8_t address_length;
uint16_t timeH=0;
boolean scramble;
boolean enhanced;
boolean ack;
uint8_t pid;
uint8_t bitrate;
static void __attribute__((unused)) XN297Dump_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(RX_EN);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // 3 bytes RX/TX address
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\x55\x0F\x71", 3); // set up RX address to xn297 preamble
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, XN297DUMP_MAX_PACKET_LEN); // Enable rx pipe 0
debug("XN297 dump, address length=%d, bitrate=",address_length);
switch(bitrate)
{
case XN297DUMP_250K:
NRF24L01_SetBitrate(NRF24L01_BR_250K);
debugln("250K");
break;
case XN297DUMP_2M:
NRF24L01_SetBitrate(NRF24L01_BR_2M);
debugln("2M");
break;
default:
NRF24L01_SetBitrate(NRF24L01_BR_1M);
debugln("1M");
break;
}
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
NRF24L01_Activate(0x73);
NRF24L01_SetPower();
}
static boolean __attribute__((unused)) XN297Dump_process_packet(void)
{
uint16_t crcxored;
uint8_t packet_sc[XN297DUMP_MAX_PACKET_LEN], packet_un[XN297DUMP_MAX_PACKET_LEN];
enhanced=false;
// init crc
crc = 0xb5d2;
/*debug("P: 71 0F 55 ");
for(uint8_t i=0; i<XN297DUMP_MAX_PACKET_LEN; i++)
debug("%02X ",packet[i]);
debugln("");*/
//Try normal payload
// address
for (uint8_t i = 0; i < address_length; i++)
{
crc = crc16_update(crc, packet[i], 8);
packet_un[address_length-1-i]=packet[i];
packet_sc[address_length-1-i]=packet[i] ^ xn297_scramble[i];
}
// payload
for (uint8_t i = address_length; i < XN297DUMP_MAX_PACKET_LEN-XN297DUMP_CRC_LENGTH; i++)
{
crc = crc16_update(crc, packet[i], 8);
packet_sc[i] = bit_reverse(packet[i]^xn297_scramble[i]);
packet_un[i] = bit_reverse(packet[i]);
// check crc
crcxored = crc ^ pgm_read_word(&xn297_crc_xorout[i+1 - 3]);
if( (crcxored >> 8) == packet[i + 1] && (crcxored & 0xff) == packet[i + 2])
{
packet_length=i+1;
memcpy(packet,packet_un,packet_length);
scramble=false;
return true;
}
crcxored = crc ^ pgm_read_word(&xn297_crc_xorout_scrambled[i+1 - 3]);
if( (crcxored >> 8) == packet[i + 1] && (crcxored & 0xff) == packet[i + 2])
{
packet_length=i+1;
memcpy(packet,packet_sc,packet_length);
scramble=true;
return true;
}
}
//Try enhanced payload
crc = 0xb5d2;
packet_length=0;
uint16_t crc_enh;
for (uint8_t i = 0; i < XN297DUMP_MAX_PACKET_LEN-XN297DUMP_CRC_LENGTH; i++)
{
packet_sc[i]=packet[i]^xn297_scramble[i];
crc = crc16_update(crc, packet[i], 8);
crc_enh = crc16_update(crc, packet[i+1] & 0xC0, 2);
crcxored=(packet[i+1]<<10)|(packet[i+2]<<2)|(packet[i+3]>>6) ;
if((crc_enh ^ 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_enh ^ 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)
{ // Found a valid CRC for the enhanced payload mode
enhanced=true;
//check selected address length
if((packet_un[address_length]>>1)!=packet_length-address_length)
{
for(uint8_t i=3;i<=5;i++)
if((packet_un[i]>>1)==packet_length-i)
address_length=i;
debugln("Detected wrong address length, using %d intead", address_length );
}
pid=((packet_un[address_length]&0x01)<<1)|(packet_un[address_length+1]>>7);
ack=(packet_un[address_length+1]>>6)&0x01;
// address
for (uint8_t i = 0; i < address_length; i++)
packet[address_length-1-i]=packet_un[i];
// payload
for (uint8_t i = address_length; i < packet_length; i++)
packet[i] = bit_reverse((packet_un[i+1]<<2)|(packet_un[i+2]>>6));
return true;
}
return false;
}
static void __attribute__((unused)) XN297Dump_overflow()
{
if(TIMER2_BASE->SR & TIMER_SR_UIF)
{ // timer overflow
timeH++;
TIMER2_BASE->SR = 0x1E5F & ~TIMER_SR_UIF; // Clear Timer2 overflow flag
}
}
static uint16_t XN297Dump_callback()
{
static uint32_t time=0,*time_rf;
//!!!Blocking mode protocol!!!
TX_MAIN_PAUSE_off;
tx_resume();
while(1)
{
if(sub_protocol<XN297DUMP_AUTO)
{
if(option==0xFF && bind_counter>XN297DUMP_PERIOD_SCAN)
{ // Scan frequencies
hopping_frequency_no++;
bind_counter=0;
}
if(hopping_frequency_no!=rf_ch_num)
{ // Channel has changed
if(hopping_frequency_no>XN297DUMP_MAX_RF_CHANNEL)
hopping_frequency_no=0; // Invalid channel 0 by default
rf_ch_num=hopping_frequency_no;
debugln("Channel=%d,0x%02X",hopping_frequency_no,hopping_frequency_no);
NRF24L01_WriteReg(NRF24L01_05_RF_CH,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();
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));
phase=0; // init timer
}
XN297Dump_overflow();
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // RX fifo data ready
if(NRF24L01_ReadReg(NRF24L01_09_CD) || option != 0xFF)
{
NRF24L01_ReadPayload(packet,XN297DUMP_MAX_PACKET_LEN);
XN297Dump_overflow();
uint16_t timeL=TCNT1;
if(TIMER2_BASE->SR & TIMER_SR_UIF)
{//timer just rolled over...
XN297Dump_overflow();
timeL=0;
}
if((phase&0x01)==0)
{
phase=1;
time=0;
}
else
time=(timeH<<16)+timeL-time;
if(XN297Dump_process_packet())
{ // valid crc found
debug("RX: %5luus C=%d ", time>>1 , hopping_frequency_no);
time=(timeH<<16)+timeL;
if(enhanced)
{
debug("Enhanced ");
debug("pid=%d ",pid);
if(ack) debug("ack ");
}
debug("S=%c A=",scramble?'Y':'N');
for(uint8_t i=0; i<address_length; i++)
{
debug(" %02X",packet[i]);
}
debug(" P(%d)=",packet_length-address_length);
for(uint8_t i=address_length; i<packet_length; i++)
{
debug(" %02X",packet[i]);
}
debugln("");
}
else
{
debugln("RX: %5luus C=%d Bad CRC", time>>1 , hopping_frequency_no);
}
}
XN297Dump_overflow();
// 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();
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));
XN297Dump_overflow();
}
}
else
{
switch(phase)
{
case 0:
debugln("------------------------");
debugln("Detecting XN297 packets.");
XN297Dump_init();
debug("Trying RF channel: 0");
hopping_frequency_no=0;
bitrate=0;
phase++;
break;
case 1:
if(bind_counter>XN297DUMP_PERIOD_SCAN)
{ // Scan frequencies
hopping_frequency_no++;
bind_counter=0;
if(hopping_frequency_no>XN297DUMP_MAX_RF_CHANNEL)
{
hopping_frequency_no=0;
bitrate++;
bitrate%=3;
debugln("");
XN297Dump_init();
debug("Trying RF channel: 0");
}
if(hopping_frequency_no)
debug(",%d",hopping_frequency_no);
NRF24L01_WriteReg(NRF24L01_05_RF_CH,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();
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));
}
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // RX fifo data ready
if(NRF24L01_ReadReg(NRF24L01_09_CD))
{
NRF24L01_ReadPayload(packet,XN297DUMP_MAX_PACKET_LEN);
if(XN297Dump_process_packet())
{ // valid crc found
debug("\r\n\r\nPacket detected: bitrate=");
switch(bitrate)
{
case XN297DUMP_250K:
NRF24L01_SetBitrate(NRF24L01_BR_250K);
debug("250K");
break;
case XN297DUMP_2M:
NRF24L01_SetBitrate(NRF24L01_BR_2M);
debug("2M");
break;
default:
NRF24L01_SetBitrate(NRF24L01_BR_1M);
debug("1M");
break;
}
debug(" C=%d ", hopping_frequency_no);
if(enhanced)
{
debug("Enhanced ");
debug("pid=%d ",pid);
if(ack) debug("ack ");
}
debug("S=%c A=",scramble?'Y':'N');
for(uint8_t i=0; i<address_length; i++)
{
debug(" %02X",packet[i]);
rx_tx_addr[i]=packet[i];
}
debug(" P(%d)=",packet_length-address_length);
for(uint8_t i=address_length; i<packet_length; i++)
{
debug(" %02X",packet[i]);
}
packet_length=packet_length-address_length;
debugln("\r\n--------------------------------");
phase=2;
debugln("Identifying all RF channels in use.");
bind_counter=0;
hopping_frequency_no=0;
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));
}
}
}
break;
case 2:
if(bind_counter>XN297DUMP_PERIOD_SCAN)
{ // Scan frequencies
hopping_frequency_no++;
bind_counter=0;
if(hopping_frequency_no>XN297DUMP_MAX_RF_CHANNEL)
{
debug("\r\n\r\n%d RF channels identified:",rf_ch_num);
for(uint8_t i=0;i<rf_ch_num;i++)
debug(" %d",hopping_frequency[i]);
time_rf=(uint32_t*)malloc(rf_ch_num*sizeof(time));
if(time_rf==NULL)
{
debugln("\r\nCan't allocate memory for next phase!!!");
phase=0;
break;
}
debugln("\r\n--------------------------------");
debugln("Identifying RF channels order.");
hopping_frequency_no=1;
phase=3;
packet_count=0;
bind_counter=0;
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]);
uint16_t timeL=TCNT1;
if(TIMER2_BASE->SR & TIMER_SR_UIF)
{//timer just rolled over...
XN297Dump_overflow();
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));
XN297Dump_overflow();
break;
}
debug(",%d",hopping_frequency_no);
NRF24L01_WriteReg(NRF24L01_05_RF_CH,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));
}
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // RX fifo data ready
if(NRF24L01_ReadReg(NRF24L01_09_CD))
{
boolean res;
if(enhanced)
res=XN297_ReadEnhancedPayload(packet, packet_length);
else
res=XN297_ReadPayload(packet, packet_length);
if(res)
{ // valid crc found
XN297Dump_overflow();
uint16_t timeL=TCNT1;
if(TIMER2_BASE->SR & TIMER_SR_UIF)
{//timer just rolled over...
XN297Dump_overflow();
timeL=0;
}
if(packet_count==0)
{//save channel
hopping_frequency[rf_ch_num]=hopping_frequency_no;
rf_ch_num++;
time=0;
}
else
time=(timeH<<16)+timeL-time;
debug("\r\nRX on channel: %d, Time: %5luus P:",hopping_frequency_no, time>>1);
time=(timeH<<16)+timeL;
for(uint8_t i=0;i<packet_length;i++)
debug(" %02X",packet[i]);
packet_count++;
if(packet_count>5)
{
bind_counter=XN297DUMP_PERIOD_SCAN+1;
debug("\r\nTrying RF channel: ");
packet_count=0;
}
}
}
// 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));
}
XN297Dump_overflow();
break;
case 3:
if(bind_counter>XN297DUMP_PERIOD_SCAN)
{ // Scan frequencies
hopping_frequency_no++;
bind_counter=0;
if(hopping_frequency_no>=rf_ch_num)
{
uint8_t next=0;
debugln("\r\n\r\nChannel order:");
debugln("%d: 0us",hopping_frequency[0]);
uint8_t i=1;
do
{
time=time_rf[i];
if(time!=-1)
{
next=i;
for(uint8_t j=2;j<rf_ch_num;j++)
if(time>time_rf[j])
{
next=j;
time=time_rf[j];
}
time_rf[next]=-1;
debugln("%d: %5luus",hopping_frequency[next],time);
i=0;
}
i++;
}
while(i<rf_ch_num);
free(time_rf);
debugln("\r\n--------------------------------");
debugln("Identifying Sticks and features.");
phase=4;
hopping_frequency_no=0;
break;
}
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]);
uint16_t timeL=TCNT1;
if(TIMER2_BASE->SR & TIMER_SR_UIF)
{//timer just rolled over...
XN297Dump_overflow();
timeL=0;
}
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));
}
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // RX fifo data ready
if(NRF24L01_ReadReg(NRF24L01_09_CD))
{
boolean res;
if(enhanced)
res=XN297_ReadEnhancedPayload(packet, packet_length);
else
res=XN297_ReadPayload(packet, packet_length);
if(res)
{ // valid crc found
XN297Dump_overflow();
uint16_t timeL=TCNT1;
if(TIMER2_BASE->SR & TIMER_SR_UIF)
{//timer just rolled over...
XN297Dump_overflow();
timeL=0;
}
if(packet_count&1)
{
time=(timeH<<16)+timeL-time;
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]);
}
else
{
time=(timeH<<16)+timeL;
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency[hopping_frequency_no]);
}
packet_count++;
if(packet_count>6)
{
bind_counter=XN297DUMP_PERIOD_SCAN+1;
packet_count=0;
}
}
}
// 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));
}
XN297Dump_overflow();
break;
case 4:
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // RX fifo data ready
if(NRF24L01_ReadReg(NRF24L01_09_CD))
{
boolean res;
if(enhanced)
res=XN297_ReadEnhancedPayload(packet, packet_length);
else
res=XN297_ReadPayload(packet, packet_length);
if(res)
{ // valid crc found
if(memcmp(packet_in,packet,packet_length))
{
debug("P:");
for(uint8_t i=0;i<packet_length;i++)
debug(" %02X",packet[i]);
debugln("");
memcpy(packet_in,packet,packet_length);
}
}
}
// 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));
}
break;
}
}
bind_counter++;
if(IS_RX_FLAG_on) // Let the radio update the protocol
{
if(Update_All()) return 10000; // New protocol selected
if(prev_option!=option && sub_protocol<XN297DUMP_AUTO)
{ // option has changed
hopping_frequency_no=option;
prev_option=option;
}
}
XN297Dump_overflow();
}
return 100;
}
uint16_t initXN297Dump(void)
{
BIND_DONE;
if(sub_protocol<XN297DUMP_AUTO)
bitrate=sub_protocol;
else
bitrate=0;
address_length=RX_num;
if(address_length<3||address_length>5)
address_length=5; //default
XN297Dump_init();
bind_counter=0;
rf_ch_num=0xFF;
prev_option=option^0x55;
phase=0; // init
return XN297DUMP_INITIAL_WAIT;
}
#endif

View File

@@ -155,7 +155,12 @@ static void __attribute__((unused)) yd717_init()
uint16_t yd717_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(YD717_PACKET_PERIOD);
#endif
yd717_send_packet(0);
}
else
{
if (bind_counter == 0)

View File

@@ -0,0 +1,120 @@
/*
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 JJRC ZSX-280 plane.
#if defined(ZSX_NRF24L01_INO)
#include "iface_nrf250k.h"
//#define FORCE_ZSX_ORIGINAL_ID
#define ZSX_INITIAL_WAIT 500
#define ZSX_PACKET_PERIOD 10093
#define ZSX_RF_BIND_CHANNEL 7
#define ZSX_PAYLOAD_SIZE 6
#define ZSX_BIND_COUNT 50
#define ZSX_RF_NUM_CHANNELS 1
static void __attribute__((unused)) ZSX_send_packet()
{
memcpy(&packet[1],rx_tx_addr,3);
if(IS_BIND_IN_PROGRESS)
{
packet[0] = 0xAA;
packet[4] = 0x00;
packet[5] = 0x00;
}
else
{
packet[0]= 0x55;
packet[4]= 0xFF-convert_channel_8b(RUDDER); // FF..80..01
packet[5]= convert_channel_8b(THROTTLE)>>1 // 0..7F
| 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();
XN297_WritePayload(packet, ZSX_PAYLOAD_SIZE);
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) ZSX_initialize_txid()
{
rx_tx_addr[0]=rx_tx_addr[3]; // Use RX_num;
#ifdef FORCE_ZSX_ORIGINAL_ID
//TX1
rx_tx_addr[0]=0x03;
rx_tx_addr[1]=0x01;
rx_tx_addr[2]=0xC3;
#endif
}
static void __attribute__((unused)) ZSX_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_FlushTx();
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_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
XN297_SetTXAddr((uint8_t*)"\xc1\xc2\xc3", 3);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, ZSX_RF_BIND_CHANNEL); // Set bind channel
}
uint16_t ZSX_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(ZSX_PACKET_PERIOD);
#endif
if(IS_BIND_IN_PROGRESS)
if(--bind_counter==0)
{
BIND_DONE;
XN297_SetTXAddr(rx_tx_addr, 3);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x00);
}
ZSX_send_packet();
return ZSX_PACKET_PERIOD;
}
uint16_t initZSX()
{
BIND_IN_PROGRESS; // autobind protocol
ZSX_initialize_txid();
ZSX_init();
bind_counter=ZSX_BIND_COUNT;
return ZSX_INITIAL_WAIT;
}
#endif
// XN297 spped 1Mb, scrambled
// Bind
// channel 7
// address: C1 C2 C3
// P(6)= AA 03 01 C3 00 00
// 03 01 C3 <- normal address
// Normal
// channel 0 and seems to be fixed
// address: 03 01 C3
// P(6)= 55 03 01 C3 80 00
// 03 01 C3 <- normal address
// 80 <- rudder FF..80..01
// 00 <- throttle 00..7F, light flag 0x80

View File

@@ -29,10 +29,10 @@
/*************************/
/*** BOOTLOADER USE ***/
/*************************/
//Allow flashing multimodule directly with TX(erky9x or opentx modified firmwares)
//Instructions: https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/tree/master/BootLoaders#compiling--uploading-firmware-with-the-flash-from-tx-bootloader
//To enable this feature remove the "//" on the next line. Requires a compatible bootloader or upload method to be selected when you use the Multi 4-in-1 Boards Manager definitions.
//#define CHECK_FOR_BOOTLOADER
//Allow flashing multimodule directly with TX(erky9x or opentx maintenance mode)
//Instructions:https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/docs/Flash_from_Tx.md
//To disable this feature add "//" at the begining of the next line. Requires a compatible bootloader or upload method to be selected when you use the Multi 4-in-1 Boards Manager definitions.
#define CHECK_FOR_BOOTLOADER
/*******************/
@@ -54,7 +54,7 @@
/*** AUTO BIND ***/ // Also referred as "Bind on powerup"
/*****************/
//Bind from channel enables you to bind when a specified channel is going from low to high. This feature is only active
// if you specify AUTOBIND in PPM mode or set AutoBind to YES for serial mode. It also requires that the throttle channel is low.
// if you specify AUTOBIND in PPM mode or set AutoBind to YES for serial mode.
//Comment to globaly disable the bind feature from a channel.
#define ENABLE_BIND_CH
//Set the channel number used for bind. Default is 16.
@@ -77,6 +77,7 @@
#define CYRF6936_INSTALLED
#define CC2500_INSTALLED
#define NRF24L01_INSTALLED
//#define SX1276_INSTALLED // only supported on STM32 modules
/** OrangeRX TX **/
//If you compile for the OrangeRX TX module you need to select the correct board type.
@@ -84,17 +85,21 @@
//#define ORANGE_TX_BLUE
/** CC2500 Fine Frequency Tuning **/
//For optimal performance the CC2500 RF module used by the FrSkyD, FrSkyV, FrSkyX, SFHSS, CORONA and Hitec protocols needs to be tuned for each protocol.
//Initial tuning should be done via the radio menu with a genuine FrSky/Futaba/CORONA/Hitec receiver.
//For optimal performance the CC2500 RF module used by the CORONA, FrSkyD, FrSkyV, FrSkyX, Hitec, HoTT, SFHSS and Redpine protocols needs to be tuned for each protocol.
//Initial tuning should be done via the radio menu with a genuine CORONA/FrSky/Hitec/HoTT/Futaba/Redpine receiver.
//Once a good tuning value is found it can be set here and will override the radio's 'option' setting for all existing and new models which use that protocol.
//For more information: https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/tree/master/docs/Frequency_Tuning.md
//Uncomment the lines below (remove the "//") and set an appropriate value (replace the "0") to enable. Valid range is -127 to +127.
//#define FORCE_CORONA_TUNING 0
//#define FORCE_FRSKYD_TUNING 0
//#define FORCE_FRSKYL_TUNING 0
//#define FORCE_FRSKYV_TUNING 0
//#define FORCE_FRSKYX_TUNING 0
//#define FORCE_SFHSS_TUNING 0
//#define FORCE_CORONA_TUNING 0
//#define FORCE_SKYARTEC_TUNING 0
//#define FORCE_HITEC_TUNING 0
//#define FORCE_HOTT_TUNING 0
//#define FORCE_REDPINE_TUNING 0
/** A7105 Fine Frequency Tuning **/
//This is required in rare cases where some A7105 modules and/or RXs have an inaccurate crystal oscillator.
@@ -104,19 +109,28 @@
//Once a good tuning value is found it can be set here and will override the frequency tuning for a specific protocol.
//Uncomment the lines below (remove the "//") and set an appropriate value (replace the "0") to enable. Valid range is -300 to +300 and default is 0.
//#define FORCE_FLYSKY_TUNING 0
//#define FORCE_HUBSAN_TUNING 0
//#define FORCE_AFHDS2A_TUNING 0
//#define FORCE_BUGS_TUNING 0
//#define FORCE_BUGS_TUNING 0
//#define FORCE_FLYSKY_TUNING 0
//#define FORCE_FLYZONE_TUNING 0
//#define FORCE_PELIKAN_TUNING 0
//#define FORCE_HUBSAN_TUNING 0
/** CYRF6936 Fine Frequency Tuning **/
//This is required in rare cases where some CYRF6936 modules and/or RXs have an inaccurate crystal oscillator.
//If using Serial mode only (for now), you can use CH15 to find the right tuning value. -100%=-300, 0%=default 0, +100%=+300.
//Uncomment the line below (remove the "//") to enable this feature.
//#define USE_CYRF6936_CH15_TUNING
/** Low Power **/
//Low power is reducing the transmit power of the multi module. This setting is configurable per model in PPM (table below) or Serial mode (radio GUI).
//It can be activated when flying indoor or small models since the distance is short or if a model is causing issues when flying closed to the TX.
//By default low power is completly disabled on all rf chips to prevent mistakes, but you can enable it by uncommenting the lines below:
//#define A7105_ENABLE_LOW_POWER
//#define CYRF6936_ENABLE_LOW_POWER
//#define CC2500_ENABLE_LOW_POWER
//#define NRF24L01_ENABLE_LOW_POWER
//By default low power selection is enabled on all rf chips, but you can disable it by commenting (add //) the lines below if you don't want to risk
//flying a model with low power.
#define A7105_ENABLE_LOW_POWER
#define CYRF6936_ENABLE_LOW_POWER
#define CC2500_ENABLE_LOW_POWER
#define NRF24L01_ENABLE_LOW_POWER
/*****************/
@@ -127,6 +141,7 @@
//If you have 2 Multi modules which you want to share the same ID so you can use either to control the same RC model
// then you can force the ID to a certain known value using the lines below.
//Default is commented, you should uncoment only for test purpose or if you know exactly what you are doing!!!
//The 8 numbers below can be anything between 0...9 and A..F
//#define FORCE_GLOBAL_ID 0x12345678
//Protocols using the CYRF6936 (DSM, Devo, Walkera...) are using the CYRF ID instead which should prevent duplicated IDs.
@@ -145,29 +160,41 @@
//The protocols below need an A7105 to be installed
#define AFHDS2A_A7105_INO
#define FLYSKY_A7105_INO
#define HUBSAN_A7105_INO
#define AFHDS2A_RX_A7105_INO
#define BUGS_A7105_INO
#define FLYSKY_A7105_INO
#define FLYZONE_A7105_INO
#define HUBSAN_A7105_INO
#define PELIKAN_A7105_INO
//The protocols below need a CYRF6936 to be installed
#define DEVO_CYRF6936_INO
#define DSM_CYRF6936_INO
#define DSM_RX_CYRF6936_INO
#define J6PRO_CYRF6936_INO
#define TRAXXAS_CYRF6936_INO
#define WFLY_CYRF6936_INO
#define WK2x01_CYRF6936_INO
//#define TRAXXAS_CYRF6936_INO
//The protocols below need a CC2500 to be installed
#define CORONA_CC2500_INO
#define ESKY150V2_CC2500_INO //Need both CC2500 and NRF
#define FRSKYL_CC2500_INO
#define FRSKYD_CC2500_INO
#define FRSKYV_CC2500_INO
#define FRSKYX_CC2500_INO
#define FRSKY_RX_CC2500_INO
#define HITEC_CC2500_INO
#define HOTT_CC2500_INO
#define SCANNER_CC2500_INO
#define SFHSS_CC2500_INO
#define SKYARTEC_CC2500_INO
#define REDPINE_CC2500_INO
//The protocols below need a NRF24L01 to be installed
#define ASSAN_NRF24L01_INO
#define BAYANG_NRF24L01_INO
#define BAYANG_RX_NRF24L01_INO
#define BUGSMINI_NRF24L01_INO
#define CABELL_NRF24L01_INO
#define CFLIE_NRF24L01_INO
@@ -178,24 +205,35 @@
#define ESKY_NRF24L01_INO
#define ESKY150_NRF24L01_INO
#define FQ777_NRF24L01_INO
#define FX816_NRF24L01_INO
#define FY326_NRF24L01_INO
#define GD00X_NRF24L01_INO
#define GW008_NRF24L01_INO
#define HISKY_NRF24L01_INO
#define HONTAI_NRF24L01_INO
#define H8_3D_NRF24L01_INO
#define JJRC345_NRF24L01_INO
#define KF606_NRF24L01_INO
#define KN_NRF24L01_INO
#define MJXQ_NRF24L01_INO
#define MT99XX_NRF24L01_INO
#define NCC1701_NRF24L01_INO
#define NCC1701_NRF24L01_INO
#define POTENSIC_NRF24L01_INO
#define PROPEL_NRF24L01_INO
#define Q303_NRF24L01_INO
#define SHENQI_NRF24L01_INO
#define SLT_NRF24L01_INO
#define SYMAX_NRF24L01_INO
#define TIGER_NRF24L01_INO
#define V2X2_NRF24L01_INO
#define V761_NRF24L01_INO
#define V911S_NRF24L01_INO
#define XK_NRF24L01_INO
#define YD717_NRF24L01_INO
#define ZSX_NRF24L01_INO
//The protocols below need a SX1276 to be installed
#define FRSKYR9_SX1276_INO
/***************************/
/*** PROTOCOLS SETTINGS ***/
@@ -207,10 +245,10 @@
// For more throw, 1024..1976us @100% and 904..2096us @125%, remove the "//" on the line below. Be aware that too much throw can damage some UMX servos. To achieve standard throw in this mode use a channel weight of 84%.
//#define DSM_MAX_THROW
//Some models (X-Vert, Blade 230S...) require a special value to instant stop the motor(s).
// You can disable this feature by adding "//" on the line below. You have to specify which channel (15 by default) will be used to kill the throttle channel.
// If the channel 15 is above -50% the throttle is untouched but if it is between -50% and -100%, the throttle output will be forced between -100% and -150%.
// For example, a value of -80% applied on channel 15 will instantly kill the motors on the X-Vert.
#define DSM_THROTTLE_KILL_CH 15
// You can disable this feature by adding "//" on the line below. You have to specify which channel (14 by default) will be used to kill the throttle channel.
// If the channel 14 is above -50% the throttle is untouched but if it is between -50% and -100%, the throttle output will be forced between -100% and -150%.
// For example, a value of -80% applied on channel 14 will instantly kill the motors on the X-Vert.
#define DSM_THROTTLE_KILL_CH 14
//AFHDS2A specific settings
//-------------------------
@@ -221,25 +259,12 @@
/**************************/
/*** FAILSAFE SETTINGS ***/
/**************************/
//The module is using the same default failsafe values for all protocols which currently supports it:
// Devo, WK2x01, SFHSS, HISKY/HK310 and AFHDS2A
//All channels are centered except throttle which is forced low.
//If you want to diasble failsafe globally comment the line below using "//".
//The following protocols are supporting failsafe: FrSkyX, Devo, WK2x01, SFHSS, HISKY/HK310 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.
//If you want to disable failsafe globally comment the line below using "//".
#define FAILSAFE_ENABLE
//Failsafe throttle low value in percentage.
//Value between -125% and +125%. Default -100.
#define FAILSAFE_THROTTLE_LOW -100
//The radio using serial protocol can set failsafe data.
// Two options are available:
// a. replace the default failsafe data with serial failsafe data when they are received.
// b. wait for the radio to provide failsafe before sending it. Enable advanced settings like "FAILSAFE NOT SET" or "FAILSAFE RX".
// Option a. is the default since you have a protection even if no failsafe has been set on the radio.
// You can force option b. by uncommenting the line below (remove the "//").
//#define FAILSAFE_SERIAL_ONLY
/**************************/
/*** TELEMETRY SETTINGS ***/
/**************************/
@@ -250,40 +275,43 @@
//Comment to invert the polarity of the output telemetry serial signal.
//This function takes quite some flash space and processor power on an atmega.
//For OpenTX it must be uncommented.
//On a 9XR_PRO running ersky9x both commented and uncommented will work depending on the radio setting Invert COM1 under the Telemetry menu.
//On other addon/replacement boards like the 9xtreme board or the Ar9x board running ersky9x, you need to uncomment the line below.
//For a Taranis/T16 with an external module it must be uncommented. For a T16 internal module it must be commented.
//A 9XR_PRO running erskyTX will work with both commented and uncommented depending on the radio setting Invert COM1 under the Telemetry menu.
//On other addon/replacement boards like the 9xtreme board or the Ar9x board running erskyTX, you need to uncomment the line below.
//For er9x it depends if you have an inveter mod or not on the telemetry pin. If you don't have an inverter comment this line.
#define INVERT_TELEMETRY
//For STM32 and OrangeRX modules, comment to prevent the TX from forcing the serial telemetry polarity normal/invert.
#define INVERT_TELEMETRY_TX
//Comment if you don't want to send Multi status telemetry frames (Protocol available, Bind in progress, version...)
//Use with er9x/erksy9x, for OpenTX MULTI_TELEMETRY below is preferred instead
#define MULTI_STATUS
//Uncomment if you want to send Multi status telemetry frames (Protocol available, Bind in progress, version...)
//Use with er9x/erskyTX, for OpenTX you must select MULTI_TELEMETRY below
//#define MULTI_STATUS
//Uncomment to send Multi status and allow OpenTX to autodetect the telemetry format
//Supported by OpenTX version 2.2 RC9 and newer. NOT supported by er9x/ersky9x use MULTI_STATUS instead.
//#define MULTI_TELEMETRY
//Sends Multi status and allow OpenTX to autodetect the telemetry format. Comment to disable.
//Supported by OpenTX version 2.2 RC9 and newer. NOT supported by er9x/erskyTX use MULTI_STATUS instead.
#define MULTI_TELEMETRY
//Work in progress: Sync OpenTX frames with the current protocol timing. This feature is only available on the STM32 module. Uncomment to enable.
//#define MULTI_SYNC
//Comment a line to disable a specific protocol telemetry
#define DSM_TELEMETRY // Forward received telemetry packet directly to TX to be decoded by er9x, ersky9x and OpenTX
#define SPORT_TELEMETRY // Use FrSkyX SPORT format to send telemetry to TX
#define AFHDS2A_FW_TELEMETRY // Forward received telemetry packet directly to TX to be decoded by ersky9x and OpenTX
#define DSM_TELEMETRY // Forward received telemetry packet directly to TX to be decoded by er9x, erskyTX and OpenTX
#define SPORT_TELEMETRY // Use FrSkyX format to send/receive telemetry
#define AFHDS2A_FW_TELEMETRY // Forward received telemetry packet directly to TX to be decoded by erskyTX and OpenTX
#define AFHDS2A_HUB_TELEMETRY // Use FrSkyD Hub format to send basic telemetry to TX like er9x
#define HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define BAYANG_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define BUGS_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define DEVO_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define HUBSAN_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define NCC1701_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define CABELL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define HITEC_HUB_TELEMETRY // Use FrSkyD Hub format to send basic telemetry to the radios which can decode it like er9x, ersky9x and OpenTX
#define HITEC_FW_TELEMETRY // Under development: Forward received telemetry packets to be decoded by ersky9x and OpenTX
//SPORT_POLLING is an implementation of the same polling routine as XJT module for sport telemetry bidirectional communication.
//This is useful for passing sport control frames from TX to RX(ex: changing Betaflight PID or VTX channels on the fly using LUA scripts with OpentX).
//Using this feature requires to uncomment INVERT_TELEMETRY as this TX output on telemetry pin only inverted signal.
//!!!! This is a work in progress!!! Do not enable unless you want to test and report
//#define SPORT_POLLING
#define HITEC_HUB_TELEMETRY // Use FrSkyD Hub format to send basic telemetry to the radios which can decode it like er9x, erskyTX and OpenTX
#define HITEC_FW_TELEMETRY // Forward received telemetry packets to be decoded by erskyTX and OpenTX
#define SCANNER_TELEMETRY // Forward spectrum scanner data to TX
#define FRSKY_RX_TELEMETRY // Forward channels data to TX
#define AFHDS2A_RX_TELEMETRY // Forward channels data to TX
#define HOTT_FW_TELEMETRY // Forward received telemetry packets to be decoded by erskyTX and OpenTX
#define BAYANG_RX_TELEMETRY // Forward channels data to TX
/****************************/
/*** SERIAL MODE SETTINGS ***/
@@ -334,6 +362,10 @@
// The default value is 16 to receive all possible channels but you might want to filter some "bad" channels from the PPM frame like the ones above 6 on the Walkera PL0811.
#define MAX_PPM_CHANNELS 16
/** Telemetry **/
//Send simple FrSkyX telemetry using the FrSkyD telemetry format
#define TELEMETRY_FRSKYX_TO_FRSKYD
/** Rotary Switch Protocol Selector Settings **/
//The table below indicates which protocol to run when a specific position on the rotary switch has been selected.
//All fields and values are explained below. Everything is configurable from here like in the Serial mode.
@@ -343,99 +375,99 @@
// short press the bind button multiple times until you reach the desired one. The bank number currently selected is indicated by the number of LED flash.
// Full procedure is located here: https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/Protocols_Details.md#protocol-selection-in-ppm-mode
//The parameter below indicates the number of desired banks between 1 and 5. Default is 5.
#define NBR_BANKS 5
//The parameter below indicates the number of desired banks between 1 and 5. Default is 1.
#define NBR_BANKS 1
const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
#if NBR_BANKS > 0
//****************************** BANK 1 ******************************
// Switch Protocol Sub protocol RX_Num Power Auto Bind Option
/* 1 */ {PROTO_FLYSKY, Flysky , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 2 */ {PROTO_AFHDS2A, PWM_IBUS , 0 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 0
/* 3 */ {PROTO_AFHDS2A, PWM_IBUS , 1 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 1
/* 4 */ {PROTO_AFHDS2A, PWM_IBUS , 2 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 2
/* 5 */ {PROTO_AFHDS2A, PWM_IBUS , 3 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 3
/* 6 */ {PROTO_AFHDS2A, PWM_IBUS , 2 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 4
/* 7 */ {PROTO_AFHDS2A, PWM_IBUS , 3 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 5
/* 8 */ {PROTO_SFHSS, H107 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 9 */ {PROTO_FRSKYV, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
/* 10 */ {PROTO_FRSKYD, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
/* 11 */ {PROTO_FRSKYX, CH_16 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
/* 12 */ {PROTO_FRSKYX, EU_16 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
/* 13 */ {PROTO_DEVO , NONE , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 14 */ {PROTO_WK2x01, WK2801 , 0 , P_HIGH , NO_AUTOBIND , 0 },
// Switch Protocol Sub protocol RX_Num Power Auto Bind Option Chan Order
/* 1 */ {PROTO_FLYSKY, Flysky , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 2 */ {PROTO_AFHDS2A, PWM_IBUS , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 0
/* 3 */ {PROTO_AFHDS2A, PWM_IBUS , 1 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 1
/* 4 */ {PROTO_AFHDS2A, PWM_IBUS , 2 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 2
/* 5 */ {PROTO_AFHDS2A, PWM_IBUS , 3 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 3
/* 6 */ {PROTO_AFHDS2A, PWM_IBUS , 2 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 4
/* 7 */ {PROTO_AFHDS2A, PWM_IBUS , 3 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 5
/* 8 */ {PROTO_SFHSS, H107 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 9 */ {PROTO_FRSKYV, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 , 0x00000000 }, // option=fine freq tuning
/* 10 */ {PROTO_FRSKYD, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 , 0x00000000 }, // option=fine freq tuning
/* 11 */ {PROTO_FRSKYX, CH_16 , 0 , P_HIGH , NO_AUTOBIND , 40 , 0x00000000 }, // option=fine freq tuning
/* 12 */ {PROTO_FRSKYX, EU_16 , 0 , P_HIGH , NO_AUTOBIND , 40 , 0x00000000 }, // option=fine freq tuning
/* 13 */ {PROTO_DEVO , NONE , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 14 */ {PROTO_WK2x01, WK2801 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
#endif
#if NBR_BANKS > 1
//****************************** BANK 2 ******************************
// Switch Protocol Sub protocol RX_Num Power Auto Bind Option
/* 1 */ {PROTO_DSM , DSM2_11 , 0 , P_HIGH , NO_AUTOBIND , 6 }, // option=number of channels
/* 2 */ {PROTO_DSM , DSM2_22 , 0 , P_HIGH , NO_AUTOBIND , 6 }, // option=number of channels
/* 3 */ {PROTO_DSM , DSMX_11 , 0 , P_HIGH , NO_AUTOBIND , 6 }, // option=number of channels
/* 4 */ {PROTO_DSM , DSMX_22 , 0 , P_HIGH , NO_AUTOBIND , 6 }, // option=number of channels
/* 5 */ {PROTO_DSM , DSM2_11 , 0 , P_HIGH , NO_AUTOBIND , 8 }, // option=number of channels
/* 6 */ {PROTO_DSM , DSM2_22 , 0 , P_HIGH , NO_AUTOBIND , 8 }, // option=number of channels
/* 7 */ {PROTO_DSM , DSMX_11 , 0 , P_HIGH , NO_AUTOBIND , 8 }, // option=number of channels
/* 8 */ {PROTO_DSM , DSMX_22 , 0 , P_HIGH , NO_AUTOBIND , 8 }, // option=number of channels
/* 9 */ {PROTO_SLT , SLT_V1 , 0 , P_HIGH , NO_AUTOBIND , 6 },
/* 10 */ {PROTO_HUBSAN, H107 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 11 */ {PROTO_HUBSAN, H301 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 12 */ {PROTO_HUBSAN, H501 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 13 */ {PROTO_HISKY, Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 14 */ {PROTO_V2X2 , NONE , 0 , P_HIGH , NO_AUTOBIND , 0 },
// Switch Protocol Sub protocol RX_Num Power Auto Bind Option Chan Order
/* 1 */ {PROTO_DSM , DSM2_11 , 0 , P_HIGH , NO_AUTOBIND , 6 , 0x00000000 }, // option=number of channels
/* 2 */ {PROTO_DSM , DSM2_22 , 0 , P_HIGH , NO_AUTOBIND , 6 , 0x00000000 }, // option=number of channels
/* 3 */ {PROTO_DSM , DSMX_11 , 0 , P_HIGH , NO_AUTOBIND , 6 , 0x00000000 }, // option=number of channels
/* 4 */ {PROTO_DSM , DSMX_22 , 0 , P_HIGH , NO_AUTOBIND , 6 , 0x00000000 }, // option=number of channels
/* 5 */ {PROTO_DSM , DSM2_11 , 0 , P_HIGH , NO_AUTOBIND , 8 , 0x00000000 }, // option=number of channels
/* 6 */ {PROTO_DSM , DSM2_22 , 0 , P_HIGH , NO_AUTOBIND , 8 , 0x00000000 }, // option=number of channels
/* 7 */ {PROTO_DSM , DSMX_11 , 0 , P_HIGH , NO_AUTOBIND , 8 , 0x00000000 }, // option=number of channels
/* 8 */ {PROTO_DSM , DSMX_22 , 0 , P_HIGH , NO_AUTOBIND , 8 , 0x00000000 }, // option=number of channels
/* 9 */ {PROTO_SLT , SLT_V1 , 0 , P_HIGH , NO_AUTOBIND , 6 , 0x00000000 },
/* 10 */ {PROTO_HUBSAN, H107 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 11 */ {PROTO_HUBSAN, H301 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 12 */ {PROTO_HUBSAN, H501 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 13 */ {PROTO_HISKY, Hisky , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 14 */ {PROTO_V2X2 , NONE , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
#endif
#if NBR_BANKS > 2
//****************************** BANK 3 ******************************
// Switch Protocol Sub protocol RX_Num Power Auto Bind Option
/* 1 */ {PROTO_ESKY , NONE , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 2 */ {PROTO_ESKY150, NONE , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 3 */ {PROTO_ASSAN, NONE , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 4 */ {PROTO_CORONA, COR_V2 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 5 */ {PROTO_SYMAX, SYMAX , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 6 */ {PROTO_KN , WLTOYS , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 7 */ {PROTO_BAYANG, BAYANG , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 8 */ {PROTO_BAYANG, H8S3D , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 9 */ {PROTO_BAYANG, X16_AH , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 10 */ {PROTO_BAYANG, IRDRONE , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 11 */ {PROTO_H8_3D, H8_3D , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 12 */ {PROTO_H8_3D, H20H , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 13 */ {PROTO_H8_3D, H20MINI , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 14 */ {PROTO_H8_3D, H30MINI , 0 , P_HIGH , NO_AUTOBIND , 0 },
// Switch Protocol Sub protocol RX_Num Power Auto Bind Option Chan Order
/* 1 */ {PROTO_ESKY , NONE , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 2 */ {PROTO_ESKY150, NONE , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 3 */ {PROTO_ASSAN, NONE , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 4 */ {PROTO_CORONA, COR_V2 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 5 */ {PROTO_SYMAX, SYMAX , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 6 */ {PROTO_KN , WLTOYS , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 7 */ {PROTO_BAYANG, BAYANG , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 8 */ {PROTO_BAYANG, H8S3D , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 9 */ {PROTO_BAYANG, X16_AH , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 10 */ {PROTO_BAYANG, IRDRONE , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 11 */ {PROTO_H8_3D, H8_3D , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 12 */ {PROTO_H8_3D, H20H , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 13 */ {PROTO_H8_3D, H20MINI , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 14 */ {PROTO_H8_3D, H30MINI , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
#endif
#if NBR_BANKS > 3
//****************************** BANK 4 ******************************
// Switch Protocol Sub protocol RX_Num Power Auto Bind Option
/* 1 */ {PROTO_MJXQ , WLH08 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 2 */ {PROTO_MJXQ , X600 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 3 */ {PROTO_MJXQ , X800 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 4 */ {PROTO_MJXQ , H26D , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 5 */ {PROTO_MJXQ , E010 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 6 */ {PROTO_MJXQ , H26WH , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 7 */ {PROTO_HONTAI, HONTAI , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 8 */ {PROTO_HONTAI, JJRCX1 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 9 */ {PROTO_HONTAI, X5C1 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 10 */ {PROTO_HONTAI, FQ777_951 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 11 */ {PROTO_Q303 , Q303 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 12 */ {PROTO_Q303 , CX35 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 13 */ {PROTO_Q303 , CX10D , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 14 */ {PROTO_Q303 , CX10WD , 0 , P_HIGH , NO_AUTOBIND , 0 },
// Switch Protocol Sub protocol RX_Num Power Auto Bind Option Chan Order
/* 1 */ {PROTO_MJXQ , WLH08 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 2 */ {PROTO_MJXQ , X600 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 3 */ {PROTO_MJXQ , X800 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 4 */ {PROTO_MJXQ , H26D , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 5 */ {PROTO_MJXQ , E010 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 6 */ {PROTO_MJXQ , H26WH , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 7 */ {PROTO_HONTAI, HONTAI , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 8 */ {PROTO_HONTAI, JJRCX1 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 9 */ {PROTO_HONTAI, X5C1 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 10 */ {PROTO_HONTAI, FQ777_951 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 11 */ {PROTO_Q303 , Q303 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 12 */ {PROTO_Q303 , CX35 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 13 */ {PROTO_Q303 , CX10D , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 14 */ {PROTO_Q303 , CX10WD , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
#endif
#if NBR_BANKS > 4
//****************************** BANK 5 ******************************
// Switch Protocol Sub protocol RX_Num Power Auto Bind Option
/* 1 */ {PROTO_CX10 , CX10_GREEN , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 2 */ {PROTO_CX10 , CX10_BLUE , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 3 */ {PROTO_CX10 , DM007 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 4 */ {PROTO_CX10 , JC3015_1 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 5 */ {PROTO_CX10 , JC3015_2 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 6 */ {PROTO_CX10 , MK33041 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 7 */ {PROTO_Q2X2 , Q222 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 8 */ {PROTO_Q2X2 , Q242 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 9 */ {PROTO_Q2X2 , Q282 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 10 */ {PROTO_CG023, CG023 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 11 */ {PROTO_CG023, YD829 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 12 */ {PROTO_FQ777, NONE , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 13 */ {PROTO_YD717, YD717 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 14 */ {PROTO_MT99XX, MT99 , 0 , P_HIGH , NO_AUTOBIND , 0 },
// Switch Protocol Sub protocol RX_Num Power Auto Bind Option Chan Order
/* 1 */ {PROTO_CX10 , CX10_GREEN , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 2 */ {PROTO_CX10 , CX10_BLUE , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 3 */ {PROTO_CX10 , DM007 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 4 */ {PROTO_CX10 , JC3015_1 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 5 */ {PROTO_CX10 , JC3015_2 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 6 */ {PROTO_CX10 , MK33041 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 7 */ {PROTO_Q2X2 , Q222 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 8 */ {PROTO_Q2X2 , Q242 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 9 */ {PROTO_Q2X2 , Q282 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 10 */ {PROTO_CG023, CG023 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 11 */ {PROTO_CG023, YD829 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 12 */ {PROTO_FQ777, NONE , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 13 */ {PROTO_YD717, YD717 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 14 */ {PROTO_MT99XX, MT99 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
#endif
};
// RX_Num is used for TX & RX match. Using different RX_Num values for each receiver will prevent starting a model with the false config loaded...
@@ -452,12 +484,23 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
// Option: the value is between -128 and +127.
// The option value is only valid for some protocols, read this page for more information: https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/Protocols_Details.md
// Chan order: if the value is different from 0, this setting will remap the first 8 channels in any given order before giving them to the protocol.
// It does not disable the automatic channel remapping of the protocol itself but changes the input of it.
// Even if your TX is sending less than 8 channels you have to respect the format like if it was.
// Examples:
// - 0x12345678 will give to the protocol the channels in the order 1,2,3,4,5,6,7,8 which is equivalent to 0x00000000.
// - 0x42315678 will give to the protocol the channels in the order 4,2,3,1,5,6,7,8 swapping channel 1 and 4.
// - 0x40010000 will give to the protocol the channels in the order 4,2,3,1,5,6,7,8 swapping channel 1 and 4. Note: 0 means leave the channel where it is.
// - 0x0000ABCD will give to the protocol the channels in the order 1,2,3,4,10,11,12,13 which potentially enables acces to channels not available on your TX. Note A=10,B=11,C=12,D=13,E=14,F=15.
/* Available protocols and associated sub protocols to pick and choose from (Listed in alphabetical order)
PROTO_AFHDS2A
PWM_IBUS
PPM_IBUS
PWM_SBUS
PPM_SBUS
PROTO_AFHDS2A_RX
NONE
PROTO_ASSAN
NONE
PROTO_BAYANG
@@ -465,6 +508,9 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
H8S3D
X16_AH
IRDRONE
DHD_D4
PROTO_BAYANG_RX
NONE
PROTO_BUGS
NONE
PROTO_BUGSMINI
@@ -500,13 +546,19 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
DSM2_11
DSMX_22
DSMX_11
PROTO_DSM_RX
NONE
PROTO_E01X
E012
E015
E016H
PROTO_ESKY
NONE
ESKY_STD
ESKY_ET4
PROTO_ESKY150
ESKY150_4CH
ESKY150_7CH
PROTO_ESKY150V2
NONE
PROTO_FLYSKY
Flysky
@@ -514,10 +566,24 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
V6X6
V912
CX20
PROTO_FLYZONE
FZ410
PROTO_FQ777
NONE
PROTO_FRSKY_RX
FRSKY_RX
FRSKY_CLONE
PROTO_FRSKYD
NONE
FRSKYD
DCLONE
PROTO_FRSKYL
LR12
LR12_6CH
PROTO_FRSKYR9
R9_915
R9_868
R9_915_8CH
R9_868_8CH
PROTO_FRSKYV
NONE
PROTO_FRSKYX
@@ -525,6 +591,18 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
CH_8
EU_16
EU_8
XCLONE
PROTO_FRSKYX2
CH_16
CH_8
EU_16
EU_8
XCLONE
PROTO_FRSKY_RX
FRSKY_RX
FRSKY_CLONE
PROTO_FX816
NONE
PROTO_FY326
FY326
FY319
@@ -550,12 +628,18 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
JJRCX1
X5C1
FQ777_951
PROTO_HOTT
NONE
PROTO_HUBSAN
H107
H301
H501
PROTO_J6PRO
NONE
PROTO_JJRC345
NONE
PROTO_KF606
NONE
PROTO_KN
WLTOYS
FEILUN
@@ -575,6 +659,12 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
FY805
PROTO_NCC1701
NONE
PROTO_PELIKAN
NONE
PROTO_POTENSIC
NONE
PROTO_PROPEL
NONE
PROTO_Q2X2
Q222
Q242
@@ -584,10 +674,17 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
CX35
CX10D
CX10WD
PROTO_REDPINE
RED_FAST
RED_SLOW
PROTO_SCANNER
NONE
PROTO_SFHSS
NONE
PROTO_SHENQI
NONE
PROTO_SKYARTEC
NONE
PROTO_SLT
SLT_V1
SLT_V2
@@ -597,13 +694,18 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PROTO_SYMAX
SYMAX
SYMAX5C
PROTO_TRAXXAS
PROTO_TIGER
NONE
PROTO_TRAXXAS
RX6519
PROTO_V2X2
V2X2
JXD506
PROTO_V911S
PROTO_V761
NONE
PROTO_V911S
V911S_STD
V911S_E119
PROTO_WFLY
NONE
PROTO_WK2x01
@@ -613,10 +715,41 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
W6_6_1
W6_HEL
W6_HEL_I
PROTO_XK
X450
X420
PROTO_YD717
YD717
SKYWLKR
SYMAX4
XINXUN
NIHUI
PROTO_ZSX
NONE
*/
/**********************************/
/*** DIRECT INPUTS SETTINGS ***/
/**********************************/
//In this section you can configure the direct inputs.
//It enables switches wired directly to the board
//Direct inputs works only in ppm mode and only for stm_32 boards
//Uncomment following lines to enable derect inputs or define your own configuration in _MyConfig.h
/*
#define ENABLE_DIRECT_INPUTS
#define DI1_PIN PC13
#define IS_DI1_on (digitalRead(DI1_PIN)==LOW)
#define DI2_PIN PC14
#define IS_DI2_on (digitalRead(DI2_PIN)==LOW)
#define DI3_PIN PC15
#define IS_DI3_on (digitalRead(DI3_PIN)==LOW)
//Define up to 4 direct input channels
//CHANNEL1 - 2pos switch
#define DI_CH1_read IS_DI1_on ? PPM_MAX_100*2 : PPM_MIN_100*2
//CHANNEL2 - 3pos switch
#define DI_CH2_read IS_DI2_on ? PPM_MAX_100*2 : (IS_DI2_on ? PPM_MAX_100 + PPM_MIN_100 : PPM_MIN_100*2)
*/

View File

@@ -60,20 +60,20 @@
#define MY_PPM_PROT // Use the bellow protocol list
const PPM_Parameters My_PPM_prot[14*NBR_BANKS]={
//****************************** BANK 1 ******************************
// Switch Protocol Sub protocol RX_Num Power Auto Bind Option
/* 1 */ {PROTO_KN , WLTOYS , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 2 */ {PROTO_FLYSKY, Flysky , 0 , P_HIGH , AUTOBIND , 0 },
/* 3 */ {PROTO_AFHDS2A, PWM_IBUS , 1 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 1
/* 4 */ {PROTO_AFHDS2A, PWM_IBUS , 2 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 2
/* 5 */ {PROTO_AFHDS2A, PWM_IBUS , 3 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 3
/* 6 */ {PROTO_AFHDS2A, PWM_IBUS , 2 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 4
/* 7 */ {PROTO_AFHDS2A, PWM_IBUS , 3 , P_HIGH , NO_AUTOBIND , 0 }, // RX number 5
/* 8 */ {PROTO_SFHSS, H107 , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 9 */ {PROTO_FRSKYV, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
/* 10 */ {PROTO_FRSKYD, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
/* 11 */ {PROTO_FRSKYX, CH_16 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
/* 12 */ {PROTO_FRSKYX, EU_16 , 0 , P_HIGH , NO_AUTOBIND , 40 }, // option=fine freq tuning
/* 13 */ {PROTO_DEVO , NONE , 0 , P_HIGH , NO_AUTOBIND , 0 },
/* 14 */ {PROTO_WK2x01, WK2801 , 0 , P_HIGH , NO_AUTOBIND , 0 },
// Switch Protocol Sub protocol RX_Num Power Auto Bind Option Chan Order
/* 1 */ {PROTO_KN , WLTOYS , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 2 */ {PROTO_FLYSKY, Flysky , 0 , P_HIGH , AUTOBIND , 0 , 0x00000000 },
/* 3 */ {PROTO_AFHDS2A, PWM_IBUS , 1 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 1
/* 4 */ {PROTO_AFHDS2A, PWM_IBUS , 2 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 2
/* 5 */ {PROTO_AFHDS2A, PWM_IBUS , 3 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 3
/* 6 */ {PROTO_AFHDS2A, PWM_IBUS , 2 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 4
/* 7 */ {PROTO_AFHDS2A, PWM_IBUS , 3 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 5
/* 8 */ {PROTO_SFHSS, H107 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 9 */ {PROTO_FRSKYV, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 , 0x00000000 }, // option=fine freq tuning
/* 10 */ {PROTO_FRSKYD, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 , 0x00000000 }, // option=fine freq tuning
/* 11 */ {PROTO_FRSKYX, CH_16 , 0 , P_HIGH , NO_AUTOBIND , 40 , 0x00000000 }, // option=fine freq tuning
/* 12 */ {PROTO_FRSKYX, EU_16 , 0 , P_HIGH , NO_AUTOBIND , 40 , 0x00000000 }, // option=fine freq tuning
/* 13 */ {PROTO_DEVO , NONE , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
/* 14 */ {PROTO_WK2x01, WK2801 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
};
#endif

View File

@@ -0,0 +1,34 @@
#ifndef _IFACE_NRF250K_H_
#define _IFACE_NRF250K_H_
#if defined (CC2500_INSTALLED)
#include "iface_cc2500.h"
#endif
#if defined (NRF24L01_INSTALLED)
#include "iface_nrf24l01.h"
#endif
//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();
//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()
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

View File

@@ -0,0 +1,90 @@
/*
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/>.
*/
#ifndef _IFACE_SX1276_H_
#define _IFACE_SX1276_H_
enum
{
SX1276_00_FIFO = 0x00,
SX1276_01_OPMODE = 0x01,
SX1276_06_FRFMSB = 0x06,
SX1276_09_PACONFIG = 0x09,
SX1276_0B_OCP = 0x0B,
SX1276_0C_LNA = 0x0C,
SX1276_0D_FIFOADDRPTR = 0x0D,
SX1276_0E_FIFOTXBASEADDR = 0x0E,
SX1276_11_IRQFLAGSMASK = 0x11,
SX1276_1D_MODEMCONFIG1 = 0x1D,
SX1276_1E_MODEMCONFIG2 = 0x1E,
SX1276_20_PREAMBLEMSB = 0x20,
SX1276_22_PAYLOAD_LENGTH = 0x22,
SX1276_24_HOPPERIOD = 0x24,
SX1276_26_MODEMCONFIG3 = 0x26,
SX1276_31_DETECTOPTIMIZE = 0x31,
SX1276_37_DETECTIONTHRESHOLD = 0x37,
SX1276_40_DIOMAPPING1 = 0x40,
SX1276_42_VERSION = 0x42,
SX1276_4D_PADAC = 0x4D
};
enum
{
SX1276_OPMODE_SLEEP = 0,
SX1276_OPMODE_STDBY,
SX1276_OPMODE_FSTX,
SX1276_OPMODE_TX,
SX1276_OPMODE_FSRX,
SX1276_OPMODE_RXCONTINUOUS,
SX1276_OPMODE_RXSINGLE,
SX1276_OPMODE_CAD
};
enum
{
SX1276_DETECT_OPTIMIZE_SF7_TO_SF12 = 0x03,
SX1276_DETECT_OPTIMIZE_SF6 = 0x05
};
enum
{
SX1276_MODEM_CONFIG1_BW_7_8KHZ = 0,
SX1276_MODEM_CONFIG1_BW_10_4KHZ,
SX1276_MODEM_CONFIG1_BW_15_6KHZ,
SX1276_MODEM_CONFIG1_BW_20_8KHZ,
SX1276_MODEM_CONFIG1_BW_31_25KHZ,
SX1276_MODEM_CONFIG1_BW_41_7KHZ,
SX1276_MODEM_CONFIG1_BW_62_5KHZ,
SX1276_MODEM_CONFIG1_BW_125KHZ,
SX1276_MODEM_CONFIG1_BW_250KHZ,
SX1276_MODEM_CONFIG1_BW_500KHZ
};
enum
{
SX1276_MODEM_CONFIG1_CODING_RATE_4_5 = 1,
SX1276_MODEM_CONFIG1_CODING_RATE_4_6,
SX1276_MODEM_CONFIG1_CODING_RATE_4_7,
SX1276_MODEM_CONFIG1_CODING_RATE_4_8
};
enum
{
SX1276_MODEM_DETECTION_THRESHOLD_SF7_TO_SF12 = 0x0A,
SX1276_MODEM_DETECTION_THRESHOLD_SF6 = 0x0C,
};
#endif

View File

@@ -22,14 +22,13 @@ Here are detailed descriptions of every supported protocols (sorted by RF module
- Bind channel is going from -100% to +100%
* Additional notes:
- It's recommended to combine Throttle cut with another button to drive the bind channel. This will prevent to launch a bind while flying...
- Bind channel does not have to be assigned to a free channel. Since it only acts when Throttle is Low (and throttle cut active), it could be used on the same channel as Flip for example since you are not going to flip your model when Throttle is low... Same goes for RTH and such other features.
- **It's recommended to combine the bind switch with Throttle cut or throttle at -100% to drive the bind channel. This will prevent to launch a bind while flying** and enable you to use the bind switch for something else.
- Using channel 16 for the bind channel seems the most relevant as only one protocol so far is using 16 channels which is FrSkyX. But even on FrSkyX this feature won't have any impact since there is NO valid reason to have Autobind set to Y for such a protocol.
## Protocol selection in PPM mode
The protocol selection is based on 2 parameters:
* selection switch: this is the rotary switch on the module numbered from 0 to 15
- switch position 0 is to select the Serial mode for er9x/ersky9x/OpenTX radio
- switch position 0 is to select the Serial mode for er9x/erskyTX/OpenTX radio
- switch position 15 is to select the bank
- switch position 1..14 will select the protocol 1..14 in the bank *X*
* banks are used to increase the amount of accessible protocols by the switch. There are up to 5 banks giving acces to up to 70 protocol entries (5 * 14). To modify or verify which bank is currenlty active do the following:
@@ -56,7 +55,7 @@ Notes:
Serial mode is selected by placing the rotary switch to position 0 before power on of the radio.
You've upgraded the module but the radio does not display the name of the protocol you are loking for:
* ersky9x:
* erskyTX:
- Place the file [Multi.txt](https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module/master/Multiprotocol/Multi.txt) (which is part of the MPM source files) on the root of your SD card.
- If the entry still does not appear or is broken, [upgrade](https://openrcforums.com/forum/viewtopic.php?f=7&t=4676) to version R222d2 or newer.
* OpenTX:
@@ -65,58 +64,84 @@ You've upgraded the module but the radio does not display the name of the protoc
# Available Protocol Table of Contents (Listed Alphabetically)
Protocol Name|Protocol Number|Sub_Proto 0|Sub_Proto 1|Sub_Proto 2|Sub_Proto 3|Sub_Proto 4|Sub_Proto 5|Sub_Proto 6|Sub_Proto 7|RF Module
---|---|---|---|---|---|---|---|---|---|---
[Assan](Protocols_Details.md#ASSAN---24)|24|ASSAN||||||||NRF24L01
[Bayang](Protocols_Details.md#BAYANG---14)|14|Bayang|H8S3D|X16_AH|IRDRONE|||||NRF24L01
[Bugs](Protocols_Details.md#BUGS---41)|41|BUGS||||||||A7105
[BugsMini](Protocols_Details.md#BUGSMINI---42)|42|BUGSMINI|BUGSMINI|BUGS3H||||||NRF24L01
[Cabell](Protocols_Details.md#Cabell---34)|34|Cabell_V3|C_TELEM|-|-|-|-|F_SAFE|UNBIND|NRF24L01
CFlie|38|CFlie||||||||NRF24L01
[CG023](Protocols_Details.md#CG023---13)|13|CG023|YD829|||||||NRF24L01
[Corona](Protocols_Details.md#CORONA---37)|37|COR_V1|COR_V2|FD_V3||||||CC2500
[CX10](Protocols_Details.md#CX10---12)|12|GREEN|BLUE|DM007|-|J3015_1|J3015_2|MK33041||NRF24L01
[Devo](Protocols_Details.md#DEVO---7)|7|Devo||||||||CYRF6936
[DM002](Protocols_Details.md#DM002---33)|33|DM002||||||||NRF24L01
[DSM](Protocols_Details.md#DSM---6)|6|DSM2-22|DSM2-11|DSMX-22|DSMX-11|AUTO||||CYRF6936
[E01X](Protocols_Details.md#E01X---45)|45|E012|E015|E016H||||||NRF24L01
[ESky](Protocols_Details.md#ESKY---16)|16|ESky||||||||NRF24L01
[ESky150](Protocols_Details.md#ESKY150---35)|35|ESKY150||||||||NRF24L01
[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|||||A7105
[FQ777](Protocols_Details.md#FQ777---23)|23|FQ777||||||||NRF24L01
[FrskyD](Protocols_Details.md#FRSKYD---3)|3|FrskyD||||||||CC2500
[FrskyV](Protocols_Details.md#FRSKYV---25)|25|FrskyV||||||||CC2500
[FrskyX](Protocols_Details.md#FRSKYX---15)|15|CH_16|CH_8|EU_16|EU_8|||||CC2500
[FY326](Protocols_Details.md#FY326---20)|20|FY326|FY319|||||||NRF24L01
[GD00X](Protocols_Details.md#GD00X---47)|47|V1|V2|||||||NRF24L01
[GW008](Protocols_Details.md#GW008---32)|32|GW008||||||||NRF24L01
[H8_3D](Protocols_Details.md#H8_3D---36)|36|H8_3D|H20H|H20Mini|H30Mini|||||NRF24L01
[Hisky](Protocols_Details.md#HISKY---4)|4|Hisky|HK310|||||||NRF24L01
[Hitec](Protocols_Details.md#HITEC---39)|39|OPT_FW|OPT_HUB|MINIMA||||||CC2500
[Hontai](Protocols_Details.md#HONTAI---26)|26|HONTAI|JJRCX1|X5C1|FQ777_951|||||NRF24L01
[Hubsan](Protocols_Details.md#HUBSAN---2)|2|H107|H301|H501||||||A7105
[J6Pro](Protocols_Details.md#J6Pro---22)|22|J6PRO||||||||CYRF6936
[KN](Protocols_Details.md#KN---9)|9|WLTOYS|FEILUN|||||||NRF24L01
[MJXq](Protocols_Details.md#MJXQ---18)|18|WLH08|X600|X800|H26D|E010|H26WH|PHOENIX||NRF24L01
[MT99xx](Protocols_Details.md#MT99XX---17)|17|MT|H7|YZ|LS|FY805||||NRF24L01
[NCC1701](Protocols_Details.md#NCC1701---44)|44|NCC1701||||||||NRF24L01
[OpenLRS](Protocols_Details.md#OpenLRS---27)|27|||||||||None
[Q2X2](Protocols_Details.md#Q2X2---29)|29|Q222|Q242|Q282||||||NRF24L01
[Q303](Protocols_Details.md#Q303---31)|31|Q303|CX35|CX10D|CX10WD|||||NRF24L01
[SFHSS](Protocols_Details.md#SFHSS---21)|21|SFHSS||||||||CC2500
[Shenqi](Protocols_Details.md#Shenqi---19)|19|Shenqi||||||||NRF24L01
[SLT](Protocols_Details.md#SLT---11)|11|SLT_V1|SLT_V2|Q100|Q200|MR100||||NRF24L01
[SymaX](Protocols_Details.md#Symax---10)|10|SYMAX|SYMAX5C|||||||NRF24L01
Traxxas|43|Traxxas||||||||NRF24L01
[V2x2](Protocols_Details.md#V2X2---5)|5|V2x2|JXD506|||||||NRF24L01
[V911S](Protocols_Details.md#V911S---46)|46|V911S||||||||NRF24L01
[WFly](Protocols_Details.md#WFLY---40)|40|WFLY||||||||CYRF6936
[WK2x01](Protocols_Details.md#WK2X01---30)|30|WK2801|WK2401|W6_5_1|W6_6_1|W6_HEL|W6_HEL_I|||CYRF6936
[YD717](Protocols_Details.md#YD717---8)|8|YD717|SKYWLKR|SYMAX4|XINXUN|NIHUI||||NRF24L01
Protocol Name|Protocol Number|Sub_Proto 0|Sub_Proto 1|Sub_Proto 2|Sub_Proto 3|Sub_Proto 4|Sub_Proto 5|Sub_Proto 6|Sub_Proto 7|RF Module|Emulation
---|---|---|---|---|---|---|---|---|---|---|---
[Assan](Protocols_Details.md#ASSAN---24)|24|ASSAN||||||||NRF24L01|
[Bayang](Protocols_Details.md#BAYANG---14)|14|Bayang|H8S3D|X16_AH|IRDRONE|DHD_D4||||NRF24L01|XN297
[Bayang RX](Protocols_Details.md#BAYANG-RX---59)|59|||||||||NRF24L01|XN297
[Bugs](Protocols_Details.md#BUGS---41)|41|BUGS||||||||A7105|
[BugsMini](Protocols_Details.md#BUGSMINI---42)|42|BUGSMINI|BUGS3H|||||||NRF24L01|XN297
[Cabell](Protocols_Details.md#Cabell---34)|34|Cabell_V3|C_TELEM|-|-|-|-|F_SAFE|UNBIND|NRF24L01|
CFlie|38|CFlie||||||||NRF24L01|
[CG023](Protocols_Details.md#CG023---13)|13|CG023|YD829|||||||NRF24L01|XN297
[Corona](Protocols_Details.md#CORONA---37)|37|COR_V1|COR_V2|FD_V3||||||CC2500|
[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|DM002||||||||NRF24L01|XN297
[DSM](Protocols_Details.md#DSM---6)|6|DSM2-22|DSM2-11|DSMX-22|DSMX-11|AUTO||||CYRF6936|
[DSM_RX](Protocols_Details.md#DSM_RX---70)|70|||||||||CYRF6936|
[E01X](Protocols_Details.md#E01X---45)|45|E012|E015|E016H||||||NRF24L01|XN297/HS6200
[ESky](Protocols_Details.md#ESKY---16)|16|ESky|Std|ET4||||||NRF24L01|
[ESky150](Protocols_Details.md#ESKY150---35)|35|ESKY150||||||||NRF24L01|
[ESky150V2](Protocols_Details.md#ESKY150V2---69)|69|||||||||CC2500|NRF24L01
[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|||||A7105|
[Flysky AFHDS2A RX](Protocols_Details.md#FLYSKY-AFHDS2A-RX---56)|56|||||||||A7105|
[Flyzone](Protocols_Details.md#FLYZONE---53)|53|FZ410||||||||A7105|
[FQ777](Protocols_Details.md#FQ777---23)|23|||||||||NRF24L01|SSV7241
[FrskyD](Protocols_Details.md#FRSKYD---3)|3|D8|Cloned|||||||CC2500|
[FrskyL](Protocols_Details.md#FRSKYL---67)|67|LR12|LR12 6CH|||||||CC2500|
[FrskyR9](Protocols_Details.md#FRSKYR9---65)|65|FrskyR9|R9_915|R9_868||||||SX1276|
[FrskyV](Protocols_Details.md#FRSKYV---25)|25|FrskyV||||||||CC2500|
[FrskyX](Protocols_Details.md#FRSKYX---15)|15|CH_16|CH_8|EU_16|EU_8|Cloned||||CC2500|
[FrskyX2](Protocols_Details.md#FRSKYX2---64)|64|CH_16|CH_8|EU_16|EU_8|Cloned||||CC2500|
[Frsky_RX](Protocols_Details.md#FRSKY_RX---55)|55|RX|CloneTX|||||||CC2500|
[FX816](Protocols_Details.md#FX816---58)|28|FX816|P38|||||||NRF24L01|
[FY326](Protocols_Details.md#FY326---20)|20|FY326|FY319|||||||NRF24L01|
[GD00X](Protocols_Details.md#GD00X---47)|47|GD_V1*|GD_V2*|||||||NRF24L01|
[GW008](Protocols_Details.md#GW008---32)|32|GW008||||||||NRF24L01|XN297
[H8_3D](Protocols_Details.md#H8_3D---36)|36|H8_3D|H20H|H20Mini|H30Mini|||||NRF24L01|XN297
[Hisky](Protocols_Details.md#HISKY---4)|4|Hisky|HK310|||||||NRF24L01|
[Hitec](Protocols_Details.md#HITEC---39)|39|OPT_FW|OPT_HUB|MINIMA||||||CC2500|
[Hontai](Protocols_Details.md#HONTAI---26)|26|HONTAI|JJRCX1|X5C1|FQ777_951|||||NRF24L01|XN297
[HoTT](Protocols_Details.md#HoTT---57)|57|||||||||CC2500|
[Hubsan](Protocols_Details.md#HUBSAN---2)|2|H107|H301|H501||||||A7105|
[J6Pro](Protocols_Details.md#J6Pro---22)|22|||||||||CYRF6936|
[JJRC345](Protocols_Details.md#JJRC345---71)|71|||||||||NRF24L01|XN297
[KF606](Protocols_Details.md#KF606---49)|49|KF606*||||||||NRF24L01|XN297
[KN](Protocols_Details.md#KN---9)|9|WLTOYS|FEILUN|||||||NRF24L01|
[MJXq](Protocols_Details.md#MJXQ---18)|18|WLH08|X600|X800|H26D|E010*|H26WH|PHOENIX*||NRF24L01|XN297
[MT99xx](Protocols_Details.md#MT99XX---17)|17|MT|H7|YZ|LS|FY805||||NRF24L01|XN297
[NCC1701](Protocols_Details.md#NCC1701---44)|44|NCC1701||||||||NRF24L01|
[OpenLRS](Protocols_Details.md#OpenLRS---27)|27|||||||||None|
[Pelikan](Protocols_Details.md#Pelikan---60)|60|||||||||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|
[Q303](Protocols_Details.md#Q303---31)|31|Q303|CX35|CX10D|CX10WD|||||NRF24L01|XN297
[Redpine](Protocols_Details.md#Redpine---50)|50|FAST|SLOW|||||||NRF24L01|
[Scanner](Protocols_Details.md#Scanner---54)|54|||||||||CC2500|
[SFHSS](Protocols_Details.md#SFHSS---21)|21|||||||||CC2500|
[Shenqi](Protocols_Details.md#Shenqi---19)|19|||||||||NRF24L01|LT8900
[Skyartec](Protocols_Details.md#Skyartec---68)|68|||||||||CC2500|CC2500
[SLT](Protocols_Details.md#SLT---11)|11|SLT_V1|SLT_V2|Q100|Q200|MR100||||NRF24L01|
[SymaX](Protocols_Details.md#Symax---10)|10|SYMAX|SYMAX5C|||||||NRF24L01|
[Tiger](Protocols_Details.md#Tiger---61)|61|Tiger||||||||NRF24L01|XN297
[Traxxas](Protocols_Details.md#Traxxas---43)|43|RX6519||||||||CYRF6936|
[V2x2](Protocols_Details.md#V2X2---5)|5|V2x2|JXD506|||||||NRF24L01|
[V761](Protocols_Details.md#V761---48)|48|V761||||||||NRF24L01|XN297
[V911S](Protocols_Details.md#V911S---46)|46|V911S*|E119*|||||||NRF24L01|XN297
[WFly](Protocols_Details.md#WFLY---40)|40|WFLY||||||||CYRF6936|
[WK2x01](Protocols_Details.md#WK2X01---30)|30|WK2801|WK2401|W6_5_1|W6_6_1|W6_HEL|W6_HEL_I|||CYRF6936|
[XK](Protocols_Details.md#XK---62)|62|XK|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
* "*" Sub Protocols designated by * suffix are using a XN297L@250kbps which will be emulated by default with the NRF24L01. If option (freq tune) is diffrent from 0, the CC2500 module (if installed) will be used instead. Each specific sub protocol has a more detailed explanation.
# A7105 RF Module
If USE_A7105_CH15_TUNING is enabled, the value of channel 15 is used by all A7105 protocols for tuning the frequency. This is required in rare cases where some A7105 modules and/or RXs have an inaccurate crystal oscillator.
## FLYSKY - *1*
Extended limits supported
@@ -153,12 +178,14 @@ CH5|CH6|CH7
Extended limits and failsafe supported
Telemetry enabled protocol:
- by defaut using FrSky Hub protocol (for example er9x): RX&battery voltages and RX&TX RSSI
- if using ersky9x and OpenTX: full telemetry information available
- by defaut using FrSky Hub protocol (for example er9x): RX(A1), battery voltage FS-CVT01(A2) and RX&TX RSSI
- if using erskyTX and OpenTX: full telemetry information available
Option is used to change the servo refresh rate. A value of 0 gives 50Hz (min), 70 gives 400Hz (max). Specific refresh rate value can be calculated like this option=(refresh_rate-50)/5.
**RX_Num is used to give a number a given RX. You must use a different RX_Num per RX. A maximum of 16 AFHDS2A RXs are supported.**
**RX_Num is used to give a number a given RX. You must use a different RX_Num per RX. A maximum of 64 AFHDS2A RXs are supported.**
OpenTX suggested RSSI alarm threshold settings (Telemetry tab): Low=15, Critical=12.
If telemetry is incomplete (missing RX RSSI for example), it means that you have to upgrade your RX firmware to version 1.6 or later. You can do it from an original Flysky TX or using a STLink like explained in [this tutorial](https://www.rcgroups.com/forums/showthread.php?2677694-How-to-upgrade-Flysky-Turnigy-iA6B-RX-to-firmware-1-6-with-a-ST-Link).
@@ -175,6 +202,24 @@ Note that the RX ouput will be AETR whatever the input channel order is.
### Sub_protocol PWM_SBUS - *2*
### Sub_protocol PPM_SBUS - *3*
## FLYSKY AFHDS2A RX - *56*
The Flysky AFHDS2A receiver protocol enables master/slave trainning, separate access from 2 different radios to the same model,...
Available in OpenTX 2.3.3, Trainer Mode Master/Multi
Extended limits supported
Low power: enable/disable the LNA stage on the RF component to use depending on the distance with the TX.
## FLYZONE - *53*
Models using the Flyzone FZ-410 TX: Fokker D.VII Micro EP RTF
Models using the old ARES TX (prior to Hitec RED): Tiger Moth, eRC Micro Stik
CH1|CH2|CH3|CH4
---|---|---|---
A|E|T|R
## HUBSAN - *2*
Telemetry enabled for battery voltage and TX RSSI
@@ -221,6 +266,19 @@ A|E|T|R|ARM|ANGLE|FLIP|PICTURE|VIDEO|LED
ANGLE: angle is +100%, acro is -100%
## Pelikan - *60*
Models: TX: CADET PRO V4, RX: RX-602 V4
Extended limits supported
**Only 1 set of frequencies for now**
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8
Note that the RX ouput will be AETR.
***
# CC2500 RF Module
@@ -273,7 +331,7 @@ Models: FrSky receivers D4R and D8R. DIY RX-F801 and RX-F802 receivers. Also kno
Extended limits supported
Telemetry enabled for A0, A1, RSSI, TSSI and Hub
Telemetry enabled for A0, A1, RSSI, TX_RSSI, TX_LQI and Hub. Lowest the TX_LQI value is best the quality link is, it's a good indicator of how well the module is tuned.
Option for this protocol corresponds to fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
@@ -282,12 +340,42 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
### Sub_protocol D8 - *0*
Use the internal multi module Identifier.
### Sub_protocol Cloned - *1*
Use the identifier learnt from another FrSky radio when binding with the FrSkyRX/CloneTX mode.
RX number can't be used anymore and is ignored.
## FRSKYL - *67*
Models: FrSky receivers L9R. Also known as LR12.
Extended limits supported
Option for this protocol corresponds to fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
### Sub_protocol LR12 - *0*
Refresh rate: 36ms
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|----|----|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
### Sub_protocol LR12 6ch - *1*
Refresh rate: 18ms
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6
## FRSKYX - *15*
Models: FrSky receivers X4R, X6R and X8R. Also known as D16.
Models: FrSky v1.xxx receivers X4R, X6R and X8R. Protocol also known as D16 v1 FCC/LBT.
Extended limits and failsafe supported
Telemetry enabled for A1 (RxBatt), A2, RSSI, TSSI and Hub
Telemetry enabled for A1 (RxBatt), A2, RSSI, TX_RSSI, TX_LQI and Hub. Lowest the TX_LQI value is best the quality link is, it's a good indicator of how well the module is tuned.
Option for this protocol corresponds to fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
@@ -307,19 +395,65 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
### Sub_protocol EU_16 - *2*
EU-LBT protocol 16 channels @18ms. Note that the LBT part is not implemented, the TX transmits right away.
EU-LBT protocol 16 channels @18ms.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
---|---|---|---|---|---|---|---|---|----|----|----|----|----|----|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
### Sub_protocol EU_8 - *3*
EU-LBT protocol 8 channels @9ms. Note that the LBT part is not implemented, the TX transmits right away.
EU-LBT protocol 8 channels @9ms.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
### Sub_protocol Cloned - *4*
Use the identifier learnt from another FrSky radio when binding with the FrSkyRX/CloneTX mode.
## FRSKYX2 - *64*
Same as [FrskyX](Protocols_Details.md#FRSKYX---15) but for D16 v2.1.0 FCC/LBT.
## FRSKY_RX - *55*
### Sub_protocol RX - *0*
The FrSky receiver protocol enables master/slave trainning, separate access from 2 different radios to the same model,...
Auto detection of the protocol used by a TX transmitting FrSkyD/D8, FrSkyX/D16 v1.xxx FCC/LBT or FrSkyX/D16 v2.1.0 FCC/LBT at bind time.
Available in OpenTX 2.3.3, Trainer Mode Master/Multi
Extended limits supported
For **FrSkyX, RX num must match on the master and slave**. This enables a multi student configuration for example.
Option for this protocol corresponds to fine frequency tuning.
If the value is equal to 0, the RX will auto tune otherwise it will use the indicated value.
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.
Low power: enable/disable the LNA stage on the RF component to use depending on the distance with the TX.
### 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.
There are 3 slots available, 1 slot for D8 cloning, 1 slot for FrSkyX (D16v1) cloning and 1 slot for FrSkyX2 (D16v2.1.0) cloning.
The same TX or different TXs can be used for each slot but a maximum of 1 per slot.
If you launch the FrSky_RX/CloneTX protocol and do a bind with a TX transmitting with the D8 protocol, it will be saved in the slot D8. Same for D16v1 and D16v2.1 .
Then the system will alow you to enable cloning as you wish for each model using the FrSkyD/X/X2 "Cloned" subprotocol. This way you can have models working with the original MPM indentifier and models which are shared by both the cloned TX and MPM.
Clone mode operation:
- Select the FrSky_RX protocol, subprotocol CloneTX
- Select on the TX to be cloned the protocol you want to clone the identifier from: FrSkyD/D8 or FrSkyX/D16 v1.xxx FCC/LBT or FrSkyX/D16 v2.1.0 FCC/LBT
- Place both the TX and MPM in bind mode
- Wait for the bind to complete
- To use the cloned TX identifier, open a new model select the protocol you just cloned/binded and select the subprotocol "Cloned"
Notes:
- OpenTX 2.3.8 N184 (nightly) or later is needed to have access to the "D8Cloned" and "D16Cloned" subprotocols, D16v2.1 "Cloned" is available under FrSkyX2/Cloned.
- For FrSkyD, only the RX number used during bind is cloned -> you can't use RX num anymore
- For FrSkyX and FrSkyX2, RX number has to be adjusted on each model to match the original TX model
## HITEC - *39*
Models: OPTIMA, MINIMA and MICRO receivers.
@@ -335,19 +469,42 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
### Sub_protocol OPT_FW - *0*
OPTIMA RXs
Full telemetry available on ersky9x and OpenTX. This is still a WIP.
Full telemetry available on OpenTX 2.3.3+, still in progress for erskyTx. Lowest the TX_LQI value is best the quality link is, it's a good indicator of how well the module is tuned.
**The TX must be close to the RX for the bind negotiation to complete successfully**
### Sub_protocol OPT_HUB - *1*
OPTIMA RXs
Basic telemetry using FrSky Hub on er9x, ersky9x, OpenTX and any radio with FrSky telemetry support with RX voltage, VOLT2 voltage, TX RSSI and TX LQI.
Basic telemetry using FrSky Hub on er9x, erskyTX, OpenTX and any radio with FrSky telemetry support with RX voltage, VOLT2 voltage, TX_RSSI and TX_LQI. Lowest the TX_LQI value is best the quality link is, it's a good indicator of how well the module is tuned.
**The TX must be close to the RX for the bind negotiation to complete successfully**
### Sub_protocol MINIMA - *2*
MINIMA, MICRO and RED receivers
MINIMA, MICRO and RED receivers. Also used by ARES planes.
## HoTT - *57*
Models: Graupner HoTT receivers (tested on GR-12L and GR-16L).
Extended limits and failsafe supported
Full telemetry and full text config mode are available in OpenTX 2.3.8+.
**RX_Num is used to give a number a given RX. You must use a different RX_Num per RX. A maximum of 64 HoTT RXs are supported.**
**Failsafe MUST be configured once with the desired channel values (hold or position) while the RX is up (wait 10+sec for the RX to learn the config) and then failsafe MUST be set to RX/Receiver otherwise the servos will jitter!!!**
The RX features configuration are done using the OpenTX script "Graupner HoTT.lua" .
Option for this protocol corresponds to fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|----|----|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
## Scanner - *54*
2.4GHz scanner accessible using the OpenTX 2.3 Spectrum Analyser tool.
## SFHSS - *21*
Models: Futaba RXs and XK models.
@@ -361,17 +518,30 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8
## Skyartec - *68*
Option for this protocol corresponds to fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7
***
# CYRF6936 RF Module
If USE_CYRF6936_CH15_TUNING is enabled, the value of channel 15 is used by all CYRF6936 protocols for tuning the frequency. This is required in rare cases where some CYRF6936 modules and/or RXs have an inaccurate crystal oscillator.
## DEVO - *7*
Extended limits and failsafe supported
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
Note that the RX ouput will be EATR.
RX output will match the Devo standard EATR independently of the input configuration AETR, RETA... unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
Basic telemetry is available if RX supports it: TX_RSSI, A1 and A2
Bind procedure using serial:
- With the TX off, put the binding plug in and power on the RX (RX LED slow blink), then power it down and remove the binding plug. Receiver should now be in autobind mode.
@@ -394,6 +564,12 @@ Bind procedure using PPM:
- To verify that the TX is in fixed mode: power cycle the TX, the module LED should be solid ON (no blink).
- Note: Autobind/fixed ID mode is linked to the RX_Num number. Which means that you can have multiple dial numbers set to the same protocol DEVO with different RX_Num and have different bind modes at the same time. It enables PPM users to get model match under DEVO.
### Sub_protocol 8CH - *0*
### Sub_protocol 10CH - *1*
### Sub_protocol 12CH - *2*
### Sub_protocol 6CH - *3*
### Sub_protocol 7CH - *4*
## WK2X01 - *30*
Extended limits supported
Autobind protocol
@@ -469,16 +645,16 @@ Telemetry enabled for TSSI and plugins
option=number of channels from 4 to 12. An invalid option value will end up with 6 channels.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|----|----|CH15
---|---|---|---|---|---|---|---|---|----|----|----|----|----|----
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|----|----|TH_KILL
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|----|CH14
---|---|---|---|---|---|---|---|---|----|----|----|----|----
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|----|TH_KILL
Notes:
- model/type/number of channels indicated on the RX can be different from what the RX is in fact wanting to see. So don't hesitate to test different combinations until you have something working. Using Auto is the best way to find these settings.
- RX output will match the Spektrum standard TAER independently of the input configuration AETR, RETA...
- RX output will match the Spektrum standard TAER independently of the input configuration AETR, RETA... unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
- RX output will match the Spektrum standard throw (1500µs +/- 400µs -> 1100..1900µs) for a 100% input. This is true for both Serial and PPM input. For PPM, make sure the end points PPM_MIN_100 and PPM_MAX_100 in _config.h are matching your TX ouput. The maximum ouput is 1000..2000µs based on an input of 125%.
- If you want to override the above and get maximum throw (old way) uncomment in _config.h the line #define DSM_MAX_THROW . In this mode to achieve standard throw use a channel weight of 84%.
- TH_KILL is a feature which is enabled on channel 15 by default (can be disabled/changed) in the _config.h file. Some models (X-Vert, Blade 230S...) require a special position to instant stop the motor(s). If the channel 15 is above -50% the throttle is untouched but if it is between -50% and -100%, the throttle output will be forced between -100% and -150%. For example, a value of -80% applied on channel 15 will instantly kill the motors on the X-Vert.
- If you want to override the above and get maximum throw either uncomment in _config.h the line #define DSM_MAX_THROW or on OpenTX 2.3.3+ use the "Enable max throw" feature on the GUI (0=No,1=Yes). In this mode to achieve standard throw use a channel weight of 84%.
- TH_KILL is a feature which is enabled on channel 14 by default (can be disabled/changed) in the _config.h file. Some models (X-Vert, Blade 230S...) require a special position to instant stop the motor(s). If the channel 14 is above -50% the throttle is untouched but if it is between -50% and -100%, the throttle output will be forced between -100% and -150%. For example, a value of -80% applied on channel 14 will instantly kill the motors on the X-Vert.
### Sub_protocol DSM2_22 - *0*
DSM2, Resolution 1024, refresh rate 22ms
@@ -491,9 +667,22 @@ DSMX, Resolution 2048, refresh rate 11ms
### Sub_protocol AUTO - *4*
The "AUTO" feature enables the TX to automatically choose what are the best settings for your DSM RX and update your model protocol settings accordingly.
The current radio firmware which are able to use the "AUTO" feature are ersky9x (9XR Pro, 9Xtreme, Taranis, ...), er9x for M128(9XR)&M2561 and OpenTX (mostly Taranis).
The current radio firmware which are able to use the "AUTO" feature are erskyTX (9XR Pro, 9Xtreme, Taranis, ...), er9x for M128(9XR)&M2561 and OpenTX (mostly Taranis).
For these firmwares, you must have a telemetry enabled TX and you have to make sure you set the Telemetry "Usr proto" to "DSMx".
Also on er9x you will need to be sure to match the polarity of the telemetry serial (normal or inverted by bitbashing), while on ersky9x you can set "Invert COM1" accordinlgy.
Also on er9x you will need to be sure to match the polarity of the telemetry serial (normal or inverted by bitbashing), while on erskyTX you can set "Invert COM1" accordinlgy.
## DSM_RX - *70*
The DSM receiver protocol enables master/slave trainning, separate access from 2 different radios to the same model,...
Notes:
- Automatically detect DSM 2/X 11/22ms 1024/2048res
- Available in OpenTX 2.3.3+, Trainer Mode Master/Multi
- Channels 1..4 are remapped to the module default channel order unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
- Extended limits supported
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|----|----|----
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
## J6Pro - *22*
@@ -501,6 +690,15 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|----|----|----
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
## Traxxas - *43*
Receiver 6519
Extended limits supported
CH1|CH2|CH3|CH4
---|---|---|---
AUX3|AUX4|THROTTLE|STEERING
## WFLY - *40*
Receivers: WFR04S, WFR07S, WFR09S
@@ -565,6 +763,24 @@ CH12|CH13
----|----
TAKE_OFF|EMG_STOP
### Sub_protocol DHD_D4 - *4*
Model: DHD D4
CH12|CH13
----|----
TAKE_OFF|EMG_STOP
## BAYANG RX - *59*
The Bayang receiver protocol enables master/slave trainning, separate access from 2 different radios to the same model,...
See the [BAYANG protocol](Protocols_Details.md#BAYANG---14) on how to activate ANAUX1 and ANAUX2 (Option/Telemetry=2).
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|---
A|E|T|R|ANAUX1|ANAUX2|FLIP|RTH|PICTURE|VIDEO
Available in OpenTX 2.3.3, Trainer Mode Master/Multi
## BUGSMINI - *42*
Models: MJX Bugs 3 Mini and 3H
@@ -581,7 +797,9 @@ ANGLE: angle is +100%, acro is -100%
### Sub_protocol BUGSMINI - *0*
### Sub_protocol BUGS3H - *1*
CH11|
---|
ALTHOLD|
## Cabell - *34*
Homegrown protocol with variable number of channels (4-16) and telemetry (RSSI, V1, V2).
@@ -713,10 +931,22 @@ CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|GYRO|PITCH
### Sub_protocol Std - *0*
### Sub_protocol ET4 - *1*
Models compatible with the ET4 transmitter like ESky Big Lama
**Multiple IDs but only one frequency...**
## ESKY150 - *35*
ESky protocol for small models since 2014 (150, 300, 150X, ...)
Number of channels are set with option. option=0 4 channels and option=1 7 channels. An invalid option value will end up with 4 channels.
### Sub_protocol 4CH - *0*
CH1|CH2|CH3|CH4
---|---|---|---
A|E|T|R
### Sub_protocol 7CH - *1*
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
@@ -724,12 +954,40 @@ A|E|T|R|FMODE|AUX6|AUX7
FMODE and AUX7 have 4 positions: -100%..-50%=>0, -50%..5%=>1, 5%..50%=>2, 50%..100%=>3
## ESKY150V2 - *69*
ESky protocol for small models: 150 V2, F150 V2, Blade 70s
Notes:
- RX output will match the eSky standard TAER independently of the input configuration AETR, RETA... unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
- To run this protocol you need both CC2500 and NRF24L01 to be enabled for code reasons, only the CC2500 is really used.
CH1|CH2|CH3|CH4|CH5 |CH6 |CH7 |CH8 |CH9 |CH10|CH11|CH12|CH13|CH14|CH15|CH16
---|---|---|---|----|----|----|----|----|----|----|----|----|----|----|----
A|E|T|R|CH5 |CH6 |CH7 |CH8 |CH9 |CH10|CH11|CH12|CH13|CH14|CH15|CH16
RATE for the F150 V2 is assigned to channel 5: -100%=low, 100%=high
## FX816 - *58*
Model: FEI XIONG FX816 P38
Only 8 TX IDs available
CH1|CH2|CH3|CH4
---|---|---|---
A|-|T|-
## FY326 - *20*
### Sub_protocol FY326 - *0*
Model: FY326 Q7 Quadcopter
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|RTH|HEADLESS|EXPERT|CALIBRATE
### Sub_protocol FY319 - *1*
Model: X6 FY319 Quadcopter (Needs Testing)
## FQ777 - *23*
Model: FQ777-124 (with SV7241A)
@@ -738,19 +996,25 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
A|E|T|R|FLIP|RTH|HEADLESS|EXPERT
## GD00X - *47*
Model: GD005 C-17 Transport and GD006 DA62
Model: GD005 C-17 Transport, GD006 DA62 and ZC-Z50
If the model does not respond well to inputs or hard to bind, you can try to set Power to Low. But this protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components used and nothing we can do about it in the firmware.
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A||T||TRIM|LED
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
### Sub_protocol V1 - *0*
First model
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A||T||TRIM|LED|RATE
### Sub_protocol V2 - *1*
New model
TRIM: either use this channel for trim only or add a mixer with aileron to increase the roll rate.
RATE: -100% high rate, +100% low rate
### Sub_protocol GD_V1 - *0*
First generation of GD models, ZC-Z50
### Sub_protocol GD_V2 - *1*
New generation of GD models
## GW008 - *32*
Model: Global Drone GW008 from Banggood
@@ -834,6 +1098,24 @@ ARM|
### Sub_protocol FQ777_951 - *3*
## JJRC345 - *71*
Model: JJRC345
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T|R|FLIP|HEADLESS|RTH
## KF606 - *49*
Model: KF606
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A||T||TRIM
## MJXQ - *18*
Autobind protocol
@@ -853,7 +1135,9 @@ 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 the model does not respond well to inputs or hard to bind, you can try to set Power to Low. But this protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components used and nothing we can do about it in the firmware.
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
### Sub_protocol H26WH - *5*
CH6|
@@ -862,7 +1146,7 @@ ARM|
Only 1 TX ID available
### Sub_protocol H26WH - *6*
### Sub_protocol PHOENIX - *6*
CH6|
---|
ARM|
@@ -880,9 +1164,12 @@ Models: MT99xx
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 the model does not respond well to inputs or hard to bind, you can try to set Power to Low. But this protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components used and nothing we can do about it in the firmware.
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
### Sub_protocol LS - *3*
Models: LS114, 124, 215
@@ -913,6 +1200,32 @@ CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A|E|T|R|Warp
## Potensic - *51*
Model: Potensic A20
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|TAKE_OFF/LANDING|EMERGENCY|MODE|HEADLESS
TAKE_OFF/LANDING: momentary switch -100% -> +100%
EMERGENCY: Stop +100%
MODE: Beginner -100%, Medium 0%, Advanced +100%
HEADLESS: Off -100%, On +100%
## PROPEL - *66*
Model: PROPEL 74-Z Speeder Bike
Autobind protocol
Telemetry: RSSI is equal to TX_LQI which indicates how well the TX receives the RX (0-100%). A1 voltage should indicate the numbers of life remaining (not tested). A2 is giving the model status using a bit mask: 0x80=flying, 0x08=taking off, 0x04=landing, 0x00=landed/crashed
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14
---|---|---|---|---|---|---|---|---|----|----|----|----|----
A|E|T|R|LEDs|RollCW|RollCCW|Fire|Weapons|Calib|Alt_Hold|Take_off|Land|Training
## Q2X2 - *29*
### Sub_protocol Q222 - *0*
Models: Q222 v1 and V686 v2
@@ -937,7 +1250,10 @@ CH1|CH2|CH3|CH4
A|E|T|R
### Sub_protocol Q303 - *0*
If the model does not respond well to inputs or hard to bind, you can try to set Power to Low. But this protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components used and nothing we can do about it in the firmware.
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---
@@ -963,6 +1279,12 @@ ARM|FLIP
ARM is 3 positions: -100%=land / 0%=manual / +100%=take off
## Redpine - *50*
[Link to the forum](https://www.rcgroups.com/forums/showthread.php?3236043-Redpine-Lowest-latency-RC-protocol)
### Sub_protocol FAST - *0*
### Sub_protocol SLOW - *1*
## Shenqi - *19*
Autobind protocol
@@ -970,7 +1292,7 @@ Model: Shenqiwei 1/20 Mini Motorcycle
CH1|CH2|CH3|CH4
---|---|---|---
| |T|R
-|-|T|R
Throttle +100%=full forward,0%=stop,-100%=full backward.
@@ -1080,15 +1402,59 @@ CH10|CH11|CH12
---|---|---
Start/Stop|EMERGENCY|CAMERA_UP/DN
## V911S - *46*
Models: WLtoys V911S, XK A110
## Tiger - *61*
Autobind protocol
If the model does not respond well to inputs or hard to bind, you can try to set Power to Low. But this protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components used and nothing we can do about it in the firmware.
**Only 1 ID**
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|FLIP|LIGHT
## V761 - *48*
Model: Volantex V761 and may be other
Warning: Only 3 IDs, you can cycle through them using RX_Num.
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
-|E|T|R|GYRO
Gyro: -100%=Beginer mode (Gyro on, yaw and pitch rate limited), 0%=Mid Mode ( Gyro on no rate limits), +100%=Mode Expert Gyro off
## V911S - *46*
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A|E|T|R|CALIB
### Sub_protocol V911S - *0*
Models: WLtoys V911S, XK A110
### Sub_protocol E119 - *1*
Models: Eachine E119
## 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.
### Sub_protocol X450 - *0*
Models: XK X450 (TX=X8)
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
### Sub_protocol X420 - *1*
Models: XK X420/X520 (TX=X4)
## YD717 - *8*
Autobind protocol
@@ -1103,7 +1469,50 @@ A|E|T|R|FLIP|LIGHT|PICTURE|VIDEO|HEADLESS
### Sub_protocol NIHUI - *4*
Same channels assignement as above.
## ZSX - *52*
Model: JJRC ZSX-280
Autobind protocol
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
-|-|T|R|LIGHT
# SX1276 RF Module
## FRSKYR9 - *65*
Extended limits supported
### Sub_protocol R9_915 - *0*
915MHz, 16 channels
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
---|---|---|---|---|---|---|---|---|----|----|----|----|----|----|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
### Sub_protocol R9_868 - *1*
868MHz, 16 channels
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
---|---|---|---|---|---|---|---|---|----|----|----|----|----|----|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14|CH15|CH16
### Sub_protocol R9_915_8CH - *2*
915MHz, 8 channels
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
### Sub_protocol R9_868_8CH - *3*
868MHz, 8 channels
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
# OpenLRS module
## OpenLRS - *27*
This is a reservation for OpenLRSng which is using Multi's serial protocol for their modules: https://openlrsng.org/. On the Multi side there is no protocol affected on 27 so it's just ignored.

View File

@@ -19,9 +19,9 @@ If you like this project and want to support further development please consider
## Development status
Current Multiprotocol code check status: [![Travis Build Status for Multi](https://api.travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module.svg)](https://travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module)
Current Multiprotocol code check status: [![Travis Build Status for Multi](https://api.travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module.svg?branch=master)](https://travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module)
Current Multiprotocol boards check status: [![Travis Build Status for Multi Boards](https://api.travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module-Boards.svg)](https://travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module-Boards)
Current Multiprotocol boards check status: [![Travis Build Status for Multi Boards](https://api.travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module-Boards.svg?branch=master)](https://travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module-Boards)
## Quicklinks
@@ -40,6 +40,7 @@ Current Multiprotocol boards check status: [![Travis Build Status for Multi Boar
* [STM32 Multiprotocol Module](docs/Compiling_STM32.md)
* [OrangeRX Module](docs/Compiling_OrangeTx.md)
1. [Transmitter Setup](docs/Transmitters.md)
* [Channel Order](docs/Channel_Order.md)
1. [How to for popular models](docs/Models.md)
1. [Troubleshooting](docs/Troubleshooting.md)
2. [Advanced Topics (not for the fainthearted!)](docs/Advanced_Topics.md)

View File

@@ -0,0 +1,5 @@
#!/usr/bin/env bash
SED=$(which gsed || which sed)
eval "${SED} -i 's/#define \b${1}\b$/#define ${2}/g' Multiprotocol/_Config.h"

19
docs/Advanced_Debug.md Normal file
View File

@@ -0,0 +1,19 @@
# Enable the STM32 module serial debug feature
To enable serial debug on your module you must know how to buid the firmware from the source code available on this GitHub. To do so follow this page: [Compiling and programming the STM32 module](Compiling_STM32.md).
Procedure:
1. Upload the debug firmware to the module:
<img src="images/Debug1.png" />
iRangeX+, Banggood and old Jumper 4in1 modules|Recent Jumper 4in1 modules with built-in CP2102|FTDI
----------------------------------------------|-----------------------------------------------|----
Use the Debug Option: "Native USB Debugging"|Use the Debug Option: "Serial/FTDI Debugging"|Use the Debug Option: "Serial/FTDI Debugging"
Do not disconnect the USB cable. In case you have to do it, you have to connect the module, close and reopen the Serial Monitor to get the module working otherwise the status LED will do a [Fast double blink](Troubleshooting.md).|Do not disconnect the USB cable. In case you have to do it, you have to power the TX first, then connect the USB cable to the module and relaunch the Serial monitor.|No restrictions apart from relaunching the Serial monitor if you disconnect the FTDI from the PC.
2. Power on the TX
1. Open in the Arduino IDE the Serial Monitor: Tools->Serial Monitor or Ctrl+Shift+M<br> <img src="images/Serial_Monitor_1.png" />
1. Make sure the settings at the bottom of the Serial Monitor window are the same as the picture above especially the baud rate set to 115200 baud
1. The Serial Monitor window should show the module booting, selection of a different protocol and more depending on the protocol currently loaded<br> <img src="images/Serial_Monitor_2.png" />
1. At this stage you can test whatever is needed or have been instructed to do. You can easily select text in the window to copy and paste it on the forum or in a text file.
1. **Important: to use your module normally and before flying you must reupload the firmware as you usually do with the Debug Option set to "None"**

View File

@@ -1,11 +1,17 @@
# Advanced Topics {This page is currently a proof of concept}
# Advanced Topics
Warning: the topics on this page are not for the fainthearted. It is strongly recommended that you have some experience in getting up and runnning with your module before you dive in there. On the other hand what is described on this page are some very useful options that could greatly increase the value and the enjoyment of your Multiprotocol module.
# Enable STM32 module serial debug
This document describes how to enable serial debug for STM32 MULTI-modules. This can be useful in case of issues with a protocol or to reverse a protocol based on the XN297L RF component. See the [MULTI-Module Serial Debug](Advanced_Debug.md) page for more details.
# XN297L dump feature
This document describes how to dump packets sent from a TX using a XN297L RF compatible component over the air on a STM32 MULTI-modules. This can be useful to get details on a protocol or even fully reverse a protocol as used in many remote controls lately. See the [MULTI-Module XN297L Dump](Advanced_XN297Ldump.md) page for more details.
# EEPROM Backup and Restore
This document describes how to back up and restore the EEPROM for both Atmega328p and STM32 MULTI-modules. This can be useful if cloning a module, or to preserve settings. See the [MULTI-Module EEPROM](EEPROM.md) page for more details.
# Telemetry in PPM mode
It is possible to access the telemetry stream coming from the receiver through the MULTI-module. This document describes a simple bluetooth module to stream telemetry information to a mobile device like an Android smartphone or tablet. The method may be generalized to feed telemetry to the transmitter if the transmitter has the capabilities to process the information. This is very useful with modules used in the PPM mode with transmitters that do not support telemetry. See the [Advanced Bluetooth Telemetry](Advanced_Bluetooth_Telemetry.md) page for more details.
# Manually setting fuses on ATmega328
This document describes a relatively simple process to set the fuses on ATmega328. See the [Advanced Manually Setting ATmega328 Fuses](Advanced_Manually_Setting_ATmega328_Fuses.md) page for more details.
# EEPROM Backup and Restore
This document describes how to back up and restore the EEPROM for both Atmega328p and STM32 MULTI-modules. This can be useful if cloning a module, or to preserve settings. See the [MULTI-Module EEPROM](EEPROM.md) page for more details.

View File

@@ -0,0 +1,16 @@
# XN297L dump feature
To get the XN297L dump feature working on your module you must know:
1. How to buid the firmware from the source code available on this GitHub. To do so follow this page: [Compiling and programming the STM32 module](Compiling_STM32.md).
1. How to enable serial debug [MULTI-Module Serial Debug](Advanced_Debug.md).
Procedure to use the XN297L dump feature:
1. Start the Multi module in serial debug mode with the Arduion IDE Serial Monitor open<br> <img src="images/Serial_Monitor_2.png" />
1. Select the protocol 63 or "Custom 63" to enable the XN297L Dump protocol
1. This protocol parameters are:
* sub_protocol or type or the second number after "Custom 63" is used to set the transmission speed: 0=250Kbps, 1=1Mbps and 2=2Mbps. Any other value will default to 1Mbps.
* RX_num or Receiver number sets the address length 3, 4 or 5 bytes. Any other value will default to an address length of 5 bytes.
* option sets the RF channel number used to receive packets between 0..84 . A value of -1 will automatically scan all channels one by one. Any other value will default to the RF channel 0.
Examples:
TBC

View File

@@ -40,6 +40,54 @@ The board definitions are installed using the Arduino IDE Boards Manager.
* **Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)** for the Atmega module
* **Multi 4-in-1 (OrangeRX)** for the OrangeRX module
## Install device drivers
### Windows 7 or newer:
1. If you haven't already done so, clone or download and unpack the Multiprocol source
1. Open the folder where you unzipped or cloned the Multiprotocol project
1. Browse to **\BootLoaders\Boards\Windows**
1. Run **install-drivers.bat**
1. Follow the prompts to install the two drivers
### Windows XP or older
1. Download and install the legacy Windows XP drivers from [here](https://github.com/rogerclarkmelbourne/Arduino_STM32/tree/master/drivers/win/win_xp_legacy)
**NOTE:** If you have installed the drivers and your module is not detected as a Maple device it most likely does not have a USB bootloader installed. Ready-made modules from Banggood **do not** come with a USB bootloader installed. You will need to follow the procedure to upload using a USB-to-serial adapter one time before you can upload firmware using the USB port.
### Jumper JP4IN1 drivers
The driver for the Jumper JP4IN1 module, the Silicon Labs CP210x driver, can be downloaded from here: https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers
### Other USB-to-serial device drivers
Other drivers may be needed if you are using an external USB-to-serial adapter. Consult the documentation for your adapter.
Windows 10 includes drivers for many common serial devices, including many USB-to-serial adapters, so check Device Manager to see if your device is recognised.
### Mac OS X
Uploading via USB requires the [libusb library](https://libusb.info/) to be installed. The easiest way to install the library is using the [Homebrew package manager for macOS](https://brew.sh/) by executing the two lines given below in a Terminal.
Install Homebrew:
`/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"`
Once Homebrew is installed, use it to install libusb:
`brew install libusb`
### Linux
Permissions must be configured to allow access to serial devices.
1. If you haven't already done so, clone or download and unpack the Multiprocol source
1. Open a Terminal and change to the directory where you have cloned or unzipped the Multiprotocol source
1. Run the following commands:
```
sudo cp -v BootLoaders/Boards/Linux/45-maple.rules /etc/udev/rules.d/45-maple.rules
sudo chown root:root /etc/udev/rules.d/45-maple.rules
sudo chmod 644 /etc/udev/rules.d/45-maple.rules
sudo udevadm control --reload-rules
sudo usermod -a -G plugdev $USER
sudo usermod -a -G dialout $USER
```
## Compiling and Uploading
Refer to the hardware-specific pages for information on compiling the firmware and uploading it to the multiprotocol module:

View File

@@ -22,14 +22,14 @@ Qty|Part|Description|Value|Package|Digikey Part Number
1|U4 U6|Pin header|1x10||[S1011EC-40-ND](https://www.digikey.com/product-detail/en/sullins-connector-solutions/PRPC040SAAN-RC/S1011EC-40-ND/2775214)
1|P1|ISP|2x3||[3M9459-ND](http://www.digikey.com/product-search/en?keywords=3M%20961206-6404-AR)
1|P2|Receptacle|5-pin||[WM14512-ND](http://www.digikey.com/product-search/en?keywords=Molex%2C%20LLC%200022142054)
2|R4 R6|Resistor|1K|0603|[P1.0KGCT-ND](http://www.digikey.com/product-search/en?keywords=P1.0KGCT-ND)
1|R2|Resistor|2.2K|0603|[P2.2KGCT-ND](http://www.digikey.com/product-search/en?keywords=P2.2KGCT-ND)
2|R1 R3|Resistor|10k|0603|[P10KGCT-ND](http://www.digikey.com/product-search/en?keywords=P10KGCT-ND)
1|R5|Resistor|20K|0603|[P20KGCT-ND](http://www.digikey.com/product-search/en?keywords=P20KGCT-ND)
1|R1|Resistor|10k|0603|[P10KGCT-ND](http://www.digikey.com/product-search/en?keywords=P10KGCT-ND)
2|R2 R5 R7|Resistor|2.2K|0603|[P2.2KGCT-ND](http://www.digikey.com/product-search/en?keywords=P2.2KGCT-ND)
2|R3 R4 R6|Resistor|1K|0603|[P1.0KGCT-ND](http://www.digikey.com/product-search/en?keywords=P1.0KGCT-ND)
1|R8|Resistor|470|0603|[P470GCT-ND](https://www.digikey.com/products/en?keywords=P470GCT-ND)
1|SW1|Hex Switch||4-DIP|[FR01KR16P-W-S-ND](https://www.digikey.com/product-detail/en/nkk-switches/FR01KR16P-W-S/FR01KR16P-W-S-ND/2104098)
1|Sw2|Momentary Switch||6mm|[ 450-1643-ND](https://www.digikey.com/product-detail/en/te-connectivity-alcoswitch-switches/2-1825910-7/450-1642-ND/1632528)
1|SW3|Momentary Switch||6mm|[CKN9104CT-ND](http://www.digikey.com/product-search/en?keywords=CKN9104CT-ND)
1|U1|Voltage reg 5V|AMS1117-50|SOT223|[LM1117MP-5.0/NOPBCT-ND](https://www.digikey.com/product-detail/en/texas-instruments/LM1117MP-5.0-NOPB/LM1117MP-5.0-NOPBCT-ND/363589)
1|U2|Voltage reg 3.3V|AMS1117-33|SOT223|[LM1117MPX-3.3/NOPBCT-ND](https://www.digikey.com/product-detail/en/texas-instruments/LM1117MPX-3.3-NOPB/LM1117MPX-3.3-NOPBCT-ND/1010516)
1|X1|8 MHz Crystal|8MHz||[535-10267-1-ND](http://www.digikey.com/product-search/en?keywords=535-10267-1-ND)
1|X1|16 MHz Crystal|16MHz||[535-10267-1-ND](http://www.digikey.com/product-search/en?keywords=535-10267-1-ND)
1||2.4GHz Antenna|||[553-1309-ND](http://www.digikey.com/product-search/en?keywords=553-1309-ND)

Some files were not shown because too many files have changed in this diff Show More