Compare commits

...

271 Commits

Author SHA1 Message Date
Pascal Langer
9c6c55fa00 E010r5: added 2 TX IDs 2021-01-21 15:31:37 +01:00
Pascal Langer
5b9ca3ba06 Move the CYRF emulation functions around for future 2021-01-21 12:24:46 +01:00
Pascal Langer
23141b6087 E016Hv2 and ESKY150V2 don't need the NRF code anymore 2021-01-21 11:46:54 +01:00
Pascal Langer
6d4b4bd2c0 Update MultiChannelsUpdater.lua 2021-01-21 09:32:45 +01:00
Pascal Langer
5cec22a757 AFHDS2A RX: trial to fix bind with original TX 2021-01-19 22:50:55 +01:00
pascallanger
153ba2e090 Update Transmitters.md 2021-01-19 12:26:15 +01:00
Pascal Langer
21e8bed52b E016HV2: fixed a left over from protocol reverse engineering 2021-01-19 12:15:23 +01:00
Pascal Langer
ecfc5b0313 End bind as requested by the radio on more protocols 2021-01-19 12:13:24 +01:00
Pascal Langer
2bcebbda45 LOLI: adjust timing 2021-01-18 15:51:35 +01:00
Pascal Langer
52e8d87ab1 LOLI RX configuration script 2021-01-18 11:46:19 +01:00
pascallanger
b613345da4 Update Protocols_Details.md 2021-01-17 17:16:11 +01:00
pascallanger
f2665ca786 Update Protocols_Details.md 2021-01-17 16:53:42 +01:00
Pascal Langer
e3189d3aed E010r5: add GLIDE channel 2021-01-17 15:59:05 +01:00
pascallanger
c829e1c86f Protocol E129: Add E130 model, Protocol E010r5: Add GLIDE channel 2021-01-17 15:57:52 +01:00
pascallanger
8499a508f5 Protocol E129: Add E130 model, Protocol E010r5: Add GLIDE channel 2021-01-17 15:57:42 +01:00
Pascal Langer
50dec0e55d AFHDS2A RX: fixed 2021-01-16 18:33:10 +01:00
Pascal Langer
6f419adb7f Fix CRC in various places 2021-01-16 16:50:45 +01:00
pascallanger
502e8beafb Update Protocols_Details.md 2021-01-16 15:48:40 +01:00
Pascal Langer
5aae065dc0 New protocol: E129 2021-01-16 15:45:19 +01:00
pascallanger
152dbed3fa Add Kyosho FHS details 2021-01-14 08:51:22 +01:00
Pascal Langer
b516bb8d20 Fix AFHDS2A RX 2021-01-12 14:02:13 +01:00
Pascal Langer
30e3e84066 LOLI: RX config 2021-01-11 16:27:59 +01:00
Pascal Langer
8338104266 Update XN297Dump_nrf24l01.ino 2021-01-11 12:37:58 +01:00
Pascal Langer
00c6aa52b9 Fix NCC1701... 2021-01-11 12:33:29 +01:00
Pascal Langer
e5689d2f1b Fix FQ777 2021-01-11 12:30:12 +01:00
Pascal Langer
b51dedcea1 M-Link: still work in progress 2021-01-11 12:13:03 +01:00
Pascal Langer
49f004e53f E010r5: added flip, led and calib channels 2021-01-11 12:12:26 +01:00
Pascal Langer
062fc05eac Fix FrSky RX protocol not ending bind when requested 2021-01-11 09:42:16 +01:00
Pascal Langer
6d080d5d5f New LOLI protocol 2021-01-09 18:39:31 +01:00
Pascal Langer
0955340a93 New protocol: E010r5 2021-01-08 21:16:07 +01:00
Ben Lye
9b2318cc7e Fix EEPROM address variable types (#494) 2020-12-27 09:57:41 +01:00
Pascal Langer
2098cdc5e0 Merge branch 'master' of https://github.com/pascallanger/DIY-Multiprotocol-TX-Module 2020-12-23 10:54:43 +01:00
Pascal Langer
d19b5187c5 AFHDS2A RX: stop bind when requested 2020-12-23 10:54:39 +01:00
pascallanger
2a78b1d6b7 Update README.md 2020-12-22 12:01:05 +01:00
pascallanger
84ae6366eb Update README.md 2020-12-21 16:12:04 +01:00
pascallanger
e5b235ac83 Update README.md 2020-12-21 16:08:03 +01:00
Ben Lye
0195384592 Merge pull request #486 from benlye/actions-3
Various fixes for CI workflow
2020-12-21 14:56:29 +00:00
Ben Lye
0937f832fc Rename the build artifact archive 2020-12-21 14:50:31 +00:00
Ben Lye
c77b4af2a0 Various fixes for CI workflow 2020-12-21 14:33:55 +00:00
pascallanger
b943bae8dd Update README.md 2020-12-21 11:39:35 +01:00
pascallanger
4955978eb6 Update README.md 2020-12-21 11:36:39 +01:00
Ben Lye
df409fddf5 Merge pull request #485 from benlye/store-artifacts
Upload build artifacts to workflow job
2020-12-20 20:15:21 +00:00
Ben Lye
0330c596e4 Upload build artifacts to workflow job 2020-12-20 19:56:28 +00:00
Ben Lye
8c6c58f12f Update main.yml
Only run CI workflow on push or PR if firmware source code has changed.
2020-12-20 19:08:36 +00:00
Ben Lye
4bc08d22b8 Merge pull request #484 from benlye/github-actions
Configure GitHub Actions
2020-12-20 17:44:28 +00:00
Ben Lye
96fb3b20b7 Configure GitHub Actions for testing and releases 2020-12-20 17:11:18 +00:00
Ben Lye
47f713c6c8 Disable Travis 2020-12-20 11:38:34 +00:00
Pascal Langer
443c7a6b99 WFLY2: WBUS <-> PPM 2020-12-20 12:05:43 +01:00
Pascal Langer
e79ca9b7d7 E016H: Calibration on channel 8 2020-12-19 12:16:51 +01:00
Pascal Langer
b94f774f80 WFLY2: Failsafe doc update 2020-12-18 17:34:09 +01:00
Pascal Langer
5614e8bef6 E016H: Multi IDs 2020-12-18 15:30:50 +01:00
Pascal Langer
4ce3a5d298 Renamed protocol E016H to E016HV2 2020-12-18 00:09:13 +01:00
Pascal Langer
f6de3de78c Update Protocols_Details.md 2020-12-17 21:28:42 +01:00
Pascal Langer
8099018132 RLINK: subprotocol DumboRC 2020-12-17 21:24:56 +01:00
Pascal Langer
360dde2e1b E016H: compilation fix 2020-12-17 21:09:13 +01:00
Pascal Langer
cc7b7638d3 Update Protocols_Details.md 2020-12-17 18:23:38 +01:00
Pascal Langer
321e4aee34 E016H v2: new protocol WIP only 1 ID 2020-12-17 18:05:04 +01:00
Pascal Langer
f18847df57 Update Convert.ino 2020-12-17 09:02:11 +01:00
Pascal Langer
a2559a65d3 WFLY2: add switch from PPM <-> WBUS 2020-12-16 18:40:46 +01:00
Pascal Langer
5ac41fdd15 WFLY2: add failsafe (hold/no pulse not available yet) 2020-12-16 16:14:45 +01:00
Pascal Langer
6d38dd2d7a WFLY2: auto stop bind when the RX replies 2020-12-15 23:58:56 +01:00
Ben Lye
667058269c Add latest boards 2020-12-15 09:50:28 +00:00
Ben Lye
ad6f934892 Pin arduino-cli version to 0.13.0 2020-12-15 09:32:34 +00:00
Pascal Langer
714220c349 Update Protocols_Details.md 2020-12-15 10:20:05 +01:00
Pascal Langer
4887fca873 WFLY2: fix bind after code cleanup... 2020-12-15 09:51:11 +01:00
Pascal Langer
cfe80edcb6 WFLY2: update channels throw, bind frequencies 2020-12-14 18:56:12 +01:00
Pascal Langer
484588ff6b WFLY2: documentation 2020-12-14 11:07:21 +01:00
Pascal Langer
1bb059c2a2 WFLY: renamed WFLYRF to WFLY2 2020-12-13 23:15:43 +01:00
Pascal Langer
ef5d9cb6b3 HoTT: update doc for 16 channels 2020-12-13 23:00:47 +01:00
Pascal Langer
37a06c050d HoTT: added support for 16 channels (previously 12) 2020-12-13 22:56:47 +01:00
Pascal Langer
5f0ed395ba WFLYRF: use Radio ID 2020-12-11 13:55:50 +01:00
Pascal Langer
ae27c8b671 WFLYRF: Fixed partial ID for telemetry 2020-12-11 11:23:06 +01:00
Pascal Langer
088bfb9c2f WFLYRF: added ext voltage to A2 2020-12-11 10:57:14 +01:00
Pascal Langer
b01462e36b WFLYRF: fixed normal mode, added telemetry, bind is not working yet 2020-12-11 10:40:00 +01:00
Pascal Langer
abd36dc6a4 WFLY: Track changes in A7105 config (radio has A7106) 2020-12-10 18:57:06 +01:00
Pascal Langer
ebb8a33c1a Fix potential bug with wait loops 2020-12-10 16:52:34 +01:00
Pascal Langer
2b0f663482 WFLY RF: WIP protocol 2020-12-10 16:51:55 +01:00
pascallanger
956e632392 Update Protocols_Details.md 2020-12-10 13:48:04 +01:00
pascallanger
90b6bb8f7d Update Protocols_Details.md 2020-12-08 18:52:13 +01:00
pascallanger
6153e84abf Update README.md 2020-12-08 16:51:52 +01:00
pascallanger
16357f29e9 Add files via upload 2020-12-08 16:48:04 +01:00
Pascal Langer
0b8a5a7539 MLINK protocol: WIP, works only for a few sec... 2020-12-05 19:13:11 +01:00
Pascal Langer
6874e3a6a7 Template for WFLY RF 2020-12-05 19:12:11 +01:00
Pascal Langer
96263ed8a6 Prep for M-LINK 2020-12-04 09:00:17 +01:00
Ben Lye
7bb1cb9ae3 Add STM32 EEPROM initialization at startup (#475) 2020-11-30 18:11:35 +01:00
Pascal Langer
20e32c4cb0 Fix XK450 twitching? 2020-11-30 13:36:29 +01:00
Ben Lye
b4421306c0 Fix compiler errors when telemetry is disabled (#474) 2020-11-30 08:38:21 +01:00
Pascal Langer
e53f723fdb Update DSM FwdPrg.lua 2020-11-25 10:37:47 +01:00
Ben Lye
832a331437 Update Frequency_Tuning.md 2020-11-22 10:09:07 +00:00
Ben Lye
12e66bd84f Add tests for STM32F103C8 board 2020-11-09 11:09:12 +00:00
Pascal Langer
d290cc519f Bayang telemetry OpenTX Ratio and Offset 2020-11-06 10:04:01 +01:00
Ben Lye
f4b19fe33e Add module sub-type to signature
Differentiates between the STM32F1 boards.
2020-11-03 08:08:10 +00:00
pascallanger
767d2c079a Update Protocols_Details.md 2020-10-31 16:24:02 +01:00
pascallanger
7750310be5 Update Protocols_Details.md 2020-10-31 16:06:18 +01:00
Pascal Langer
6de4e1e1dd Protocols order 2020-10-31 15:59:04 +01:00
Ben Lye
627d47f139 C8 MCU flash size check (#461) 2020-10-30 12:21:39 +01:00
pascallanger
36675cf729 Change Travis links 2020-10-30 12:18:15 +01:00
Pascal Langer
33d8234eb3 Update JJRC345_nrf24l01.ino 2020-10-30 12:01:40 +01:00
Pascal Langer
347eb11328 SFHSS name change to Futaba 2020-10-30 12:01:29 +01:00
Ben Lye
5ed61f30e1 STM32 release file name standardization (#451)
Tweak the names of the STM32 serial and CC2500-only release files.
2020-10-11 14:09:42 +01:00
Ben Lye
a633f46f4f Travis release build changes (#450)
* Move the release build steps into separate shell scripts
* Remove builds that we don't need any more
  * Latest builds of er9x and erSkyTx both support MULTI_TELEMETRY so separate OpenTX / erSkyTx builds are no longer needed
  * Radio can switch telemetry inversion on or off automatically so STM32 inv / noinv builds are no longer needed
2020-10-11 12:52:05 +01:00
Pascal Langer
baf9a0f978 Update DSM FwdPrg.lua 2020-10-03 11:06:22 +02:00
Pascal Langer
c98b8fc8bf Flysky: Fix AFHDS and AFHDS2A 2020-10-03 10:52:11 +02:00
Pascal Langer
2fae0a35b8 Merge branch 'master' of https://github.com/pascallanger/DIY-Multiprotocol-TX-Module 2020-10-01 00:18:28 +02:00
Pascal Langer
b04f38ed3d Indicate ratio values to be used for A1 and A2 voltage sensors
OMP, RadioLink, Hubsan, Bayang, ...
2020-10-01 00:18:13 +02:00
pascallanger
60d5dd4101 Update Protocols_Details.md 2020-10-01 00:06:40 +02:00
Pascal Langer
75b7dd1dd7 Kyosho/Hype: channel order & doc 2020-10-01 00:05:20 +02:00
Pascal Langer
aa2717d6ab Kyosho/Hype: bind fix 2020-09-30 20:30:07 +02:00
Pascal Langer
4058f04b39 Kyosho/Hype: another attempt to fix bind... 2020-09-30 11:06:30 +02:00
Pascal Langer
25ebd55c85 Update Protocols_Details.md 2020-09-29 19:14:41 +02:00
Pascal Langer
d00b58c8ed Kyosho/Hype: fix bind 2020-09-29 17:06:01 +02:00
Pascal Langer
e7eb07a5a4 Kyosho: new sub_protocol Hype
Initial release
2020-09-29 11:24:55 +02:00
Ben Lye
a4cac50261 Add builds for modules with only CC2500 2020-09-24 14:09:08 +01:00
Pascal Langer
4f8da64822 OMP: doc update 2020-09-23 23:52:22 +02:00
Pascal Langer
4f89721cd0 RadioLink: any id
Need to rebind RXs...
2020-09-23 23:42:03 +02:00
Pascal Langer
43c2843490 Update AFHDS2A_a7105.ino 2020-09-23 23:08:26 +02:00
Pascal Langer
c152265284 OMP: doc 2020-09-23 23:05:05 +02:00
Pascal Langer
b591b92b4e Update OMP documentation 2020-09-23 09:41:26 +02:00
Pascal Langer
090388aa1b OMP: improve telemetry 2020-09-22 15:15:14 +02:00
Pascal Langer
c6ab696949 AFHDS2A: fix X6B telemetry issue? 2020-09-21 10:57:19 +02:00
Pascal Langer
df45a3ff83 OMP: prevent telemetry voltage from rolling over 2020-09-21 10:50:01 +02:00
pascallanger
fedd04b724 Update Troubleshooting.md 2020-09-19 21:23:51 +02:00
pascallanger
d8630da09d Update Troubleshooting.md 2020-09-19 20:35:44 +02:00
pascallanger
6192f7287e Update README.md 2020-09-18 17:15:18 +02:00
Pascal Langer
5b8a08ab22 OMP: added telemetry 2020-09-18 16:13:45 +02:00
Ben Lye
313b03fb84 Disable PPM/serial in builds as needed 2020-09-17 10:13:00 +01:00
Pascal Langer
5639def6fb Update DSM FwdPrg.lua 2020-09-15 12:05:26 +02:00
Pascal Langer
15a254879c DSM_RX: bind with other radio modules off 2020-09-15 12:03:16 +02:00
pascallanger
5baa9bd256 Update README.md 2020-09-13 11:34:23 +02:00
Pascal Langer
d5346c0eaf Add DISABLE_FLASH_SIZE_CHECK 2020-09-09 16:47:32 +02:00
Pascal Langer
a2213fd6dc DSM Forward Programming: work in progress 2020-09-09 10:45:14 +02:00
Pascal Langer
9b07f12f90 AFHDS2A: add sub proto 2020-09-08 08:49:38 +02:00
Pascal Langer
c9b49483e0 NanoRF 2020-09-07 22:58:37 +02:00
Pascal Langer
e2972a5823 AFHDS2A: enable 16 channels on SBUS 2020-09-07 20:31:47 +02:00
Pascal Langer
d5b3ed832d Update Multiprotocol.ino 2020-09-04 10:59:31 +02:00
Pascal Langer
9fcc030c15 STM32: test flash size 2020-09-04 10:39:30 +02:00
pascallanger
fc81b7ee5a Update Protocols_Details.md 2020-09-03 17:28:54 +02:00
Pascal Langer
f168abc2bb Fixed frame size 2020-08-31 22:21:21 +02:00
pascallanger
fe6778635e Add Realacc R11 protocol 2020-08-30 14:57:56 +02:00
Pascal Langer
65a6c19d02 OMP doc 2020-08-30 14:35:44 +02:00
pascallanger
a32b5561a1 Update Protocols_Details.md 2020-08-30 14:30:28 +02:00
pascallanger
4b4393952e Update README.md 2020-08-24 14:41:10 +02:00
Pascal Langer
ea205b1e69 Bayanf: fix telemetry batt 2020-08-20 19:00:06 +02:00
pascallanger
748140cdee Update Protocols_Details.md 2020-08-18 12:02:08 +02:00
Pascal Langer
e8037c857f OMP fixes 2020-08-17 08:26:42 +02:00
Pascal Langer
15e37cefee OMP: fix? 2020-08-16 18:48:40 +02:00
Pascal Langer
b1e4daf1c2 OMP: new protocol intial release
Untested!!!
2020-08-15 16:17:18 +02:00
Pascal Langer
4e0fccfc63 Update Protocols_Details.md 2020-08-14 19:40:25 +02:00
Pascal Langer
48b90029c4 V761: Work with any ID. Tested on Eachine RX. 2020-08-14 19:39:24 +02:00
Pascal Langer
8b189af2f9 R9: small change 2020-08-13 21:21:34 +02:00
Pascal Langer
030cdd35a2 Update REALACC_nrf24l01.ino 2020-08-11 00:02:19 +02:00
Pascal Langer
3789998ba9 Update ZSX_nrf24l01.ino 2020-08-10 23:54:51 +02:00
Pascal Langer
ea24ab6032 New protocol Realacc 2020-08-10 23:54:33 +02:00
Pascal Langer
1408431649 XN297Dump: increase the number of RF channels to look for 2020-08-10 22:52:50 +02:00
Pascal Langer
6810372064 RadioLink: enable Range test mode 2020-08-10 20:30:19 +02:00
Pascal Langer
708e2ac5f6 V761 bug fix: the model was not reconnecting unless you did a bind first 2020-08-07 15:18:15 +02:00
Pascal Langer
2178f6761d RadioLink: update A2=Batt telemetry value 2020-08-07 15:11:59 +02:00
Pascal Langer
aa5fd82004 Update FrSky_Rx_cc2500.ino 2020-08-05 09:50:40 +02:00
Pascal Langer
660282db2e RX protocols: abort RX bind as requested 2020-08-04 10:42:35 +02:00
Ben Lye
fdd357619b Fix folder structure inside LUA script zip file 2020-08-03 22:39:10 +01:00
Pascal Langer
5f12f99761 Update Validate.h 2020-08-01 19:35:39 +02:00
Pascal Langer
3d98abb6d4 Rename the Flyzone protocol by Height which is the original manufacturer 2020-08-01 19:19:11 +02:00
Pascal Langer
e35879a5d0 RadioLink: fix 2020-08-01 10:19:30 +02:00
Pascal Langer
37138f03ae Few fixes 2020-07-31 15:58:07 +02:00
Pascal Langer
51d39bbd8c RadioLink: add RXs to the supported list 2020-07-31 10:56:34 +02:00
Pascal Langer
0932a1c93f Update Protocols_Details.md 2020-07-31 10:52:37 +02:00
Pascal Langer
19164521e4 Flyzone protocol: 8 channels support 2020-07-31 10:42:10 +02:00
Pascal Langer
df28cfe3cc Radiolink: final version with 64 IDs 2020-07-31 10:41:07 +02:00
Pascal Langer
354878d542 RadioLink: preparation for final 2020-07-28 15:53:58 +02:00
Pascal Langer
695264d59a RadioLink: update 2020-07-28 00:55:47 +02:00
pascallanger
de190f3349 Update Protocols_Details.md 2020-07-25 14:43:52 +02:00
Pascal Langer
b049385094 Update Protocols_Details.md 2020-07-23 21:40:26 +02:00
Pascal Langer
75dc616130 Update RadioLink_cc2500.ino 2020-07-23 15:08:23 +02:00
Pascal Langer
b542f5e7cd RLINK: remove fixed ID 2020-07-23 10:10:08 +02:00
Pascal Langer
f3bee3cded RLINK: Fix voltage values 2020-07-23 10:03:04 +02:00
Pascal Langer
a9b7ab9a06 Update Protocols_Details.md 2020-07-22 20:13:54 +02:00
Pascal Langer
ed019e954e RadioLink: few fixes 2020-07-22 20:05:56 +02:00
Pascal Langer
65186b4356 Add Kyosho to the Lua channel namer exception list 2020-07-22 18:18:35 +02:00
Pascal Langer
e1d4f9a270 RadioLink Surface protocol: initial commit 2020-07-22 15:37:47 +02:00
Pascal Langer
69c95ca153 Fix compilation issues when Telem is disabled 2020-07-22 15:27:06 +02:00
Pascal Langer
e6976fb08d Merge branch 'master' of https://github.com/pascallanger/DIY-Multiprotocol-TX-Module 2020-07-21 01:40:19 +02:00
Pascal Langer
f502ba3659 FrSkyX Cloned: 8 channels option 2020-07-21 01:40:14 +02:00
pascallanger
e6ccc7e7cc Update Protocols_Details.md 2020-07-17 14:21:57 +02:00
Pascal Langer
da9d8851c2 Fix FrSkyX and FrSkyR9 bind options 2020-07-16 10:28:07 +02:00
pascallanger
ad48291d2a Update Protocols_Details.md 2020-07-16 00:02:29 +02:00
Pascal Langer
d6da230369 Flysky AFHDS2A: 16 channels + LQI
Use the 2 new sub protocols to extend the protocol to 16 channels on IBUS
2020-07-15 23:58:41 +02:00
pascallanger
f8ac406a94 Update Frequency_Tuning.md 2020-07-15 20:31:55 +02:00
Pascal Langer
e691ecd167 Update doc 2020-07-15 19:09:56 +02:00
Pascal Langer
930c26a111 Kyosho: new protocol 2020-07-10 15:25:32 +02:00
Pascal Langer
64419a6cf4 V2x2: fix? 2020-07-09 22:49:48 +02:00
Pascal Langer
5c59cddc7a FrSkyR9: FCC initial support 2020-07-06 09:52:43 +02:00
Ben Lye
4c7a51be46 Create folders in LUA script zip file 2020-07-05 16:54:55 +01:00
Ben Lye
7dad0fb89f Update install_drivers.bat
Change to libusbk driver for DFU device
2020-07-05 16:32:56 +01:00
Pascal Langer
adebb3fc5c FrSkyX: clean up 2020-07-05 17:19:29 +02:00
Pascal Langer
5ab00b9d18 FrSkyX: TXQly is the percentage of telemetry received packets (100...0%) 2020-07-05 00:28:43 +02:00
Pascal Langer
fbd5d7cf48 FrSky R9: telemetry TX to RX attempt 2020-07-04 22:43:19 +02:00
Pascal Langer
84132678cc FrSkyR9: TQLY = percentage of telemetry frames per second 2020-07-04 18:40:29 +02:00
Pascal Langer
78421748ba FrSky R9: fix sensors telem? 2020-07-04 17:50:05 +02:00
Pascal Langer
7112f58dae FrSkyX: fix telem 2020-07-04 15:15:55 +02:00
Pascal Langer
e56f737b34 FrSkyX: fix telemetry not stopping when RX is off 2020-07-04 13:33:56 +02:00
Pascal Langer
49d993f613 FrSkyR9: fix independant compilation issue 2020-07-04 11:48:26 +02:00
Pascal Langer
63dd8a9215 Update iface_sx1276.h 2020-07-03 19:51:22 +02:00
Pascal Langer
d5f819dd59 FrSkyR9: initial telemetry support 2020-07-03 19:51:11 +02:00
pascallanger
a68787f16e Update Protocols_Details.md 2020-07-03 18:03:36 +02:00
Pascal Langer
858ef5801c FrSkyX: fix AVR telemetry and may be improve telemetry overall 2020-07-03 17:42:12 +02:00
Pascal Langer
9e0bd29cee FrSkyD: clone mode - additional ID byte 2020-07-03 16:15:47 +02:00
Pascal Langer
15395de579 FrSky R9: adding CH1-8/CH9-16 and Telem ON/OFF (not that telem is supported yet) 2020-07-01 15:39:40 +02:00
Pascal Langer
db4aad04a7 FrSkyR9: fix 868 2020-07-01 14:39:11 +02:00
Pascal Langer
466e4cf227 Update DSM protocol details 2020-06-29 23:31:17 +02:00
Ben Lye
05a3780c38 Add latest STM32 board 2020-06-29 19:55:29 +01:00
pascallanger
85ea91cdbb Update README.md 2020-06-28 19:54:14 +02:00
pascallanger
985d7a6fd9 Update README.md 2020-06-28 19:37:58 +02:00
pascallanger
2a19b8dd45 Update README.md 2020-06-28 19:35:12 +02:00
Pascal Langer
b2b3078861 Update README.md 2020-06-28 19:17:02 +02:00
Pascal Langer
2ac92f5725 Create README.md 2020-06-28 19:15:39 +02:00
Pascal Langer
e2f5afd71e V761 doc updates 2020-06-28 19:07:34 +02:00
Ben Lye
e094ee036d Zip the LUA scripts for release 2020-06-28 16:06:06 +01:00
Ben Lye
2ad7f3e9f2 Fix LUA script copy 2020-06-28 15:13:33 +01:00
Pascal Langer
8e1f2258f8 OpenTX Lua scripts related to Multi 2020-06-27 17:59:06 +02:00
Pascal Langer
5c01bbf284 V761: additional channles 2020-06-27 17:58:29 +02:00
Pascal Langer
647425fc1a Revert "V761 additonal channels"
This reverts commit 7286049d07.
2020-06-27 17:56:19 +02:00
Pascal Langer
7286049d07 V761 additonal channels 2020-06-27 17:55:36 +02:00
Pascal Langer
ce67a065cd V761 - Eachine sub protocol 2020-06-26 17:54:56 +02:00
Ben Lye
8948cb6287 Switch to Arduino CLI instead of IDE for Travis CI builds 2020-06-26 09:56:07 +01:00
pascallanger
4daa5fa2bb Update Advanced_XN297Ldump.md 2020-06-22 10:10:57 +02:00
Pascal Langer
c49a7dae0a Few changes 2020-06-20 22:04:26 +02:00
Pascal Langer
890a042a43 V2X2 new sub proto MR101 and protocol rewrite
MR101 sub proto for Dromida XL
2020-06-20 21:40:03 +02:00
Pascal Langer
c95e576ef3 DSM RX: end bind and increased retry 2020-06-18 10:53:03 +02:00
Pascal Langer
2aa96dd129 SX1276: indent with tabs 2020-06-15 23:34:56 +02:00
AlessandroAU
908634474b Adds SX1276_DetectChip() function (#373)
* Adds SX1276_DetectChip() function

works by testing for 0x12 match in version reg 0x42

* fix build err
2020-06-15 23:03:03 +02:00
AlessandroAU
79b525ee71 Implement datasheet errata recommendation (#372) 2020-06-15 23:02:30 +02:00
Pascal Langer
872b8259ab Q90C VTX channel 2020-06-15 19:39:43 +02:00
Pascal Langer
a14c82708f Update Q90C_nrf24l01.ino 2020-06-15 15:30:31 +02:00
Pascal Langer
7e53778680 Update Q90C_nrf24l01.ino 2020-06-15 15:23:02 +02:00
Pascal Langer
210fbe3b9e Update Q90C_nrf24l01.ino 2020-06-15 14:45:49 +02:00
Pascal Langer
0a5fd72bdc DSM: 3 ch timing on CH13 2020-06-15 14:45:42 +02:00
Pascal Langer
6e1701ecc5 Q90C: Flight Modes 2020-06-14 23:22:27 +02:00
Pascal Langer
a5f627a2d6 Q90C test 2020-06-14 22:28:36 +02:00
Pascal Langer
b4a1f175c6 Update Q90C_nrf24l01.ino 2020-06-14 22:22:13 +02:00
Pascal Langer
e0690fa661 Update Q90C_nrf24l01.ino 2020-06-14 19:10:59 +02:00
Pascal Langer
bd962eff35 DSM: SAFE setting how to 2020-06-14 18:34:38 +02:00
Pascal Langer
b515355249 DSM RX: remove reverse on aileron and rudder 2020-06-13 21:54:18 +02:00
Pascal Langer
d1feef97be DSM: adjust end points, solve SAFE? 2020-06-13 16:20:51 +02:00
Pascal Langer
f52f96d44e DSM: selectable refresh rate 22/11ms when supported 2020-06-12 00:25:09 +02:00
Pascal Langer
944ec62f49 Update DSM_cyrf6936.ino 2020-06-10 09:03:41 +02:00
Pascal Langer
30905014d2 DSM: fix 11ms issue on some RXs? 2020-06-09 23:49:51 +02:00
Pascal Langer
32dbdfc6e3 Fix compilation when telemetry is disabled 2020-06-09 20:08:00 +02:00
Pascal Langer
b2e312b41e FrSkyX: force tuning fix for FrSkyX2 2020-06-07 18:06:19 +02:00
Ben Lye
52f4096197 Force 'noinv' for the T18 5in1 release files
And put it in the file name, just for consistency
2020-06-06 19:16:19 +01:00
Ben Lye
c547ea0c0f Disable some protocols for Atmega CC2500 builds
Trying to get the build to fit again.
2020-06-06 18:47:32 +01:00
Ben Lye
c73ee61128 Add T18 5in1 tests and release builds 2020-06-06 18:47:32 +01:00
Pascal Langer
90b287f1f4 Multi 5-in-1 initial support 2020-06-06 01:57:52 +02:00
Pascal Langer
0316c9eea9 HoTT: telem code cleanup 2020-06-05 22:44:32 +02:00
Pascal Langer
374b46966c FrSkyX: small change 2020-06-05 22:22:13 +02:00
Pascal Langer
3705415927 HoTT: fix telemetry 2020-06-05 22:20:19 +02:00
Pascal Langer
bff68f482e Update Protocols_Details.md 2020-06-03 14:08:09 +02:00
Pascal Langer
32ed758072 Update DSM_Rx_cyrf6936.ino 2020-06-03 12:55:45 +02:00
Pascal Langer
5ce99ee419 Test protocol 2020-06-03 11:43:27 +02:00
Pascal Langer
ceea384a36 Pelikan Lite: force_id update 2020-06-03 10:29:34 +02:00
Pascal Langer
fd3b026e12 Update Pelikan_a7105.ino 2020-06-02 19:10:11 +02:00
Pascal Langer
7e451c13a8 Pelikan: add sub protocol for Lite version 2020-06-02 19:04:05 +02:00
Pascal Langer
3dcf74c2e4 Bayang: renamed CX100 to QX100 2020-06-02 17:17:49 +02:00
Pascal Langer
50f1eca4be Bayang: new subprotocol CX100 2020-06-02 14:59:32 +02:00
Pascal Langer
0d97af5ae2 XN297dump: Auto mode small fix 2020-06-02 14:34:50 +02:00
Pascal Langer
aeb8d67219 HoTT: add subprotocols 2020-06-01 22:55:32 +02:00
Pascal Langer
1f65025036 HoTT: add LBT and telemetry improvment 2020-05-31 23:54:13 +02:00
Pascal Langer
8df3687684 Q90C: channels reverse 2020-05-26 22:26:30 +02:00
MRC3742
adf59a9d0d Misc updates for errors, omissions amd corrections (#359) 2020-05-26 19:52:09 +02:00
Pascal Langer
b9f00bdbc5 Q90C: checksum fix 2020-05-26 12:41:33 +02:00
Pascal Langer
a10e169573 New protocol Q90C 2020-05-24 17:39:14 +02:00
Pascal Langer
317b9a8156 Fix compilation when ESKY150V2 was built without HoTT 2020-05-23 23:34:05 +02:00
97 changed files with 8690 additions and 1879 deletions

189
.github/workflows/main.yml vendored Normal file
View File

@@ -0,0 +1,189 @@
# Workflow for testing MULTI-Module firmware builds
name: CI
on:
# Trigger the workflow on pushes, except those that are tagged (avoids double-testing releases)
push:
branches:
- '**'
tags-ignore:
- '**'
paths:
- '.github/workflows/**'
- 'buildroot/bin/**'
- 'Multiprotocol/**'
# Trigger the workflow on pull requests to the master branch
pull_request:
branches:
- master
paths:
- '.github/workflows/**'
- 'buildroot/bin/**'
- 'Multiprotocol/**'
# Triggers the workflow on release creation
release:
types:
- created
# Allows the workflow to be triggered manually from the Actions tab
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
# Configure the board matrix
strategy:
fail-fast: false
matrix:
board: [
"multi4in1:avr:multiatmega328p:bootloader=none",
"multi4in1:avr:multiatmega328p:bootloader=optiboot",
"multi4in1:avr:multixmega32d4",
"multi4in1:STM32F1:multi5in1t18int",
"multi4in1:STM32F1:multistm32f103cb:debug_option=none",
"multi4in1:STM32F1:multistm32f103cb:debug_option=native",
"multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi",
"multi4in1:STM32F1:multistm32f103c8:debug_option=none"
]
# Set the environment variables
env:
BOARD: ${{ matrix.board }}
steps:
- uses: actions/checkout@v2
- name: Install Arduino CLI
uses: arduino/setup-arduino-cli@v1.1.1
- name: Prepare build environment
run: |
echo "Github Ref: $GITHUB_REF"
echo "Event name: ${{ github.event_name }}"
echo "Event action: ${{ github.event.action }}"
echo "Tag name: ${{ github.event.release.tag_name }}"
arduino-cli config init --additional-urls https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/master/package_multi_4in1_board_index.json
arduino-cli core update-index
if [[ "$BOARD" =~ "multi4in1:avr:" ]]; then
arduino-cli core install arduino:avr;
arduino-cli core install multi4in1:avr
fi
if [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
arduino-cli core install multi4in1:STM32F1
fi
chmod +x ${GITHUB_WORKSPACE}/buildroot/bin/*
echo "${GITHUB_WORKSPACE}/buildroot/bin" >> $GITHUB_PATH
mkdir ./build
mkdir ./binaries
- name: Configure MULTI-Module firmware options
run: |
# Load the build functions
source ./buildroot/bin/buildFunctions;
# Get the version
getMultiVersion
echo "MULTI_VERSION=$(echo $MULTI_VERSION)" >> $GITHUB_ENV
# Get all the protocols for this board
getAllProtocols
echo "A7105_PROTOCOLS=$(echo $A7105_PROTOCOLS)" >> $GITHUB_ENV
echo "CC2500_PROTOCOLS=$(echo $CC2500_PROTOCOLS)" >> $GITHUB_ENV
echo "CYRF6936_PROTOCOLS=$(echo $CYRF6936_PROTOCOLS)" >> $GITHUB_ENV
echo "NRF24L01_PROTOCOLS=$(echo $NRF24L01_PROTOCOLS)" >> $GITHUB_ENV
echo "SX1276_PROTOCOLS=$(echo $SX1276_PROTOCOLS)" >> $GITHUB_ENV
echo "ALL_PROTOCOLS=$(echo $ALL_PROTOCOLS)" >> $GITHUB_ENV
# Get all the RF modules for this board
getAllRFModules
echo "ALL_RFMODULES=$(echo $ALL_RFMODULES)" >> $GITHUB_ENV
# 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
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
# Trim the enabled protocols down for the STM32F103CB board with debugging or the STM32F103C8 board in general
if [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi" ]] || [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=native" ]] || [[ "$BOARD" =~ "multi4in1:STM32F1:multistm32f103c8" ]]; then
opt_disable $ALL_PROTOCOLS;
opt_enable FRSKYX_CC2500_INO AFHDS2A_A7105_INO MJXQ_NRF24L01_INO DSM_CYRF6936_INO;
fi
- name: Save default firmware configuration
run: |
cat Multiprotocol/_Config.h
cp Multiprotocol/_Config.h ./_Config.h.bak
- name: Build default configuration
run: |
source ./buildroot/bin/buildFunctions;
buildMulti
- name: Build serial only
run: |
source ./buildroot/bin/buildFunctions;
cp ./_Config.h.bak Multiprotocol/_Config.h
opt_disable ENABLE_PPM;
buildMulti;
- name: Build PPM only
run: |
source ./buildroot/bin/buildFunctions;
cp ./_Config.h.bak Multiprotocol/_Config.h
opt_disable ENABLE_SERIAL;
buildMulti;
- name: Build each RF module individually
run: |
source ./buildroot/bin/buildFunctions;
cp ./_Config.h.bak Multiprotocol/_Config.h;
buildEachRFModule;
- name: Build each protocol individually
run: |
source ./buildroot/bin/buildFunctions;
cp ./_Config.h.bak Multiprotocol/_Config.h;
buildEachProtocol;
- name: Build release files
run: |
source ./buildroot/bin/buildFunctions;
cp ./_Config.h.bak Multiprotocol/_Config.h;
buildReleaseFiles;
ls -al ./binaries;
NUM_FILES=$(ls -l ./binaries | grep ^- | wc -l);
if [ $NUM_FILES -gt 0 ]; then
echo "HAVE_FILES=true" >> $GITHUB_ENV
else
echo "HAVE_FILES=false" >> $GITHUB_ENV
fi
- name: Deploy files to release
if: github.event_name == 'release' && github.event.action == 'created' && env.HAVE_FILES == 'true'
uses: AButler/upload-release-assets@v2.0
with:
files: './binaries/*'
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: 'Upload Artifacts'
if: env.HAVE_FILES == 'true'
uses: actions/upload-artifact@v2
with:
name: multi-test-build
path: ./binaries/

View File

@@ -1,362 +0,0 @@
dist: bionic
sudo: true
language: c
env:
global:
- IDE_VERSION=1.8.9
matrix:
- 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
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)
- CYRF6936_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_CYRF6936_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
- NRF24L01_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_NRF24L01_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
- if [[ "$BOARD" =~ "multi4in1:avr:multixmega32d4" ]]; then
ALL_PROTOCOLS=$(echo $CYRF6936_PROTOCOLS);
else
ALL_PROTOCOLS=$(echo $A7105_PROTOCOLS $CC2500_PROTOCOLS $CYRF6936_PROTOCOLS $NRF24L01_PROTOCOLS);
fi
- echo $ALL_PROTOCOLS
# 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 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 default configuration - all protocols are enabled for STM32; a subset of protocols for Atmega or STM32 debugging
- buildDefault
# Serial only
- buildSerialOnly
# PPM only
- buildPPMOnly
# Re-enable PPM and serial
- opt_enable ENABLE_SERIAL
- opt_enable ENABLE_PPM
# Build for each RF module individually
- buildEachRFModule
# Restore the default configuration
- cp ./_Config.h.bak Multiprotocol/_Config.h
# 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:
secure: KGXaoqvd8rbZ3AZtL9Rrn1JYiocGsPaihRUyR8gM8vTfvH9WYAE1+h6SzROQOuJSwr89MvTo3SBOTlM/0PDBnEGLec9Irt7cwO0xf9xM2vPuUG8DYcUzmJJzME9dkn/7qHof1JGgRpp1duUAN1triE9NxhKxL1hbs+tUUbDPAejxwoFNfnta/T4PfD6xmkZNJbneIfYFuFgyLpwwFhuUy9JP7s1AFOiT+fCHxPaZrPn5GsXqAi95Cb7Q3w1iVSt3BmrGxL2j3CeNpWzFY1RrMdc8ay+ppOhSPEIl2vyM7VeLRRBL3EVeFWkiS4ywevqw70wOivTczluv3OeuIJAe5o2UU+w5+59c7+i44Nih23PDAZBhAG5JkLUYUN0XUJpXJ5ZlZsb8IS8sI1txlZa5tNVoXO9+soGEY4rKSpZaPptuENm792CzzAjcaUI9pOFJ/0CBoSCbu5MpM/plkJCMd8fY27EE8cNYvolMuRATNlXs7h9mURGR69pmcR1jFShH+A7Kyp1S1sH19sGCEU16rt2aAtf2FadFg/gKACC2y9rB3wBb4Qnapu2AwNRlTYNuU1+G+kb2FXRwMl04q+38S+cIBHH9NHfdftp9MRPf8Ekatojs92be/Ux21S+hcA7sx/DV22Dl45V6l4mXzR7U4x1nQcdn1SGuy5I4lL6IYCk=
skip_cleanup: true
file_glob: true
file: binaries/*
on:
tags: true

View File

@@ -1,11 +1,11 @@
@echo off
echo Installing Maple DFU driver...
"%~dp0wdi-simple" --vid 0x1EAF --pid 0x0003 --type 1 --name "Maple DFU" --dest "%~dp0maple-dfu"
echo Installing MULTI-Module DFU Bootloader Driver...
"%~dp0wdi-simple" --vid 0x1EAF --pid 0x0003 --type 2 --name "MULTI-Module DFU Bootloader" --dest "%~dp0MULTI-DFU-Bootloader" -b
echo.
echo Installing Maple Serial driver...
"%~dp0wdi-simple" --vid 0x1EAF --pid 0x0004 --type 3 --name "Maple Serial" --dest "%~dp0maple-serial"
echo Installing MULTI-Module USB Serial Driver...
"%~dp0wdi-simple" --vid 0x1EAF --pid 0x0004 --type 3 --name "MULTI-Module USB Serial" --dest "%~dp0MULTI-USB-Serial" -b
echo.
pause

View File

@@ -170,6 +170,24 @@
],
"toolsDependencies": []
},
{
"name": "MULTI-Module AVR Boards",
"architecture": "avr",
"version": "1.1.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.1.1.tar.gz",
"archiveFileName": "package_multi_4in1_avr_board_v1.1.1.tar.gz",
"checksum": "SHA-256:02158258b4dbaca61bedbb6933336200d13b02ad0db981e2dda253682c482e99",
"size": "324512",
"boards": [
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
{"name": "Multi 4-in-1 (OrangeRX)"}
],
"toolsDependencies": []
},
{
"name": "Multi 4-in-1 STM32 Board",
"architecture": "STM32F1",
@@ -527,6 +545,95 @@
"version": "4.8.3-2014q1"
}]
},
{
"name": "Multi X-in-1 STM32 Boards",
"architecture": "STM32F1",
"version": "1.1.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_stm32_board_v1.1.8.tar.gz",
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.8.tar.gz",
"checksum": "SHA-256:e9ed8055ebf72abf37e60e1b8d1c6ee5472132ea7c0a3c4a63fbb8442613e4c2",
"size": "7481800",
"boards": [
{"name": "Multi 4-in-1 (STM32F103C)"},
{"name": "Multi 5-in-1 (Jumper T18 Internal)"}
],
"toolsDependencies": [{
"packager": "arduino",
"name": "arm-none-eabi-gcc",
"version": "4.8.3-2014q1"
}]
},
{
"name": "Multi X-in-1 STM32 Boards",
"architecture": "STM32F1",
"version": "1.2.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_stm32_board_v1.2.0.tar.gz",
"archiveFileName": "package_multi_4in1_stm32_board_v1.2.0.tar.gz",
"checksum": "SHA-256:754f08ca2a553701cc9112b645c079b6041107f1bf863648305e560c136a6ac5",
"size": "7496214",
"boards": [
{"name": "Multi 4-in-1 (STM32F103C)"},
{"name": "Multi 5-in-1 (Jumper T18 Internal)"}
],
"toolsDependencies": [{
"packager": "arduino",
"name": "arm-none-eabi-gcc",
"version": "4.8.3-2014q1"
}]
},
{
"name": "Multi X-in-1 STM32 Boards",
"architecture": "STM32F1",
"version": "1.2.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_stm32_board_v1.2.1.tar.gz",
"archiveFileName": "package_multi_4in1_stm32_board_v1.2.1.tar.gz",
"checksum": "SHA-256:c66d34afadc5b21e9e28c4d477fa03a6d55db0b74b59ff2dcb07b4d6ef06da1a",
"size": "7496448",
"boards": [
{"name": "Multi 4-in-1 (STM32F103C)"},
{"name": "Multi 5-in-1 (Jumper T18 Internal)"}
],
"toolsDependencies": [{
"packager": "arduino",
"name": "arm-none-eabi-gcc",
"version": "4.8.3-2014q1"
}]
},
{
"name": "MULTI-Module STM32 Boards",
"architecture": "STM32F1",
"version": "1.2.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.2.2.tar.gz",
"archiveFileName": "package_multi_4in1_stm32_board_v1.2.2.tar.gz",
"checksum": "SHA-256:0fe4a8899438bbc31dc37714acca13968e43d75a47e59143343d83b634d2e47d",
"size": "7485662",
"boards": [
{"name": "Multi X-in-1 STM32F103CB (128KB)"},
{"name": "Multi X-in-1 STM32F103C8 (64KB)"},
{"name": "Multi 5-in-1 (Jumper T18 Internal)"}
],
"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",

601
Lua_scripts/DSM FwdPrg.lua Normal file
View File

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

View File

@@ -0,0 +1,171 @@
---- #########################################################################
---- # #
---- # Copyright (C) OpenTX #
-----# #
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
---- # #
---- # This program is free software; you can redistribute it and/or modify #
---- # it under the terms of the GNU General Public License version 2 as #
---- # published by the Free Software Foundation. #
---- # #
---- # This program is distributed in the hope that it will be useful #
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
---- # GNU General Public License for more details. #
---- # #
---- #########################################################################
--###############################################################################
-- Multi buffer for HoTT description
-- To start operation:
-- Write "HoTT" at address 0..3
-- Write 0xFF at address 4 will request the buffer to be cleared
-- Write 0x0F at address 5
-- Read buffer from address 6 access the RX text for 168 bytes, 21 caracters
-- by 8 lines
-- Write at address 5 sends an order to the RX: 0xXF=start, 0xX7=prev page,
-- 0xXE=next page, 0xX9=enter, 0xXD=next or 0xXB=prev with X being the sensor
-- to request data from 8=RX only, 9=Vario, A=GPS, B=Cust, C=ESC, D=GAM, E=EAM
-- Write at address 4 the value 0xFF will request the buffer to be cleared
-- !! Before exiting the script must write 0 at address 0 for normal operation !!
--###############################################################################
HoTT_Sensor = 0
Timer_128 = 100
local function HoTT_Release()
multiBuffer( 0, 0 )
end
local function HoTT_Send(button)
multiBuffer( 5, 0x80+(HoTT_Sensor*16) + button)
end
local function HoTT_Sensor_Inc()
local detected_sensors=multiBuffer( 4 )
local a
if detected_sensors ~= 0xFF then
repeat
HoTT_Sensor=(HoTT_Sensor+1)%7 -- Switch to next sensor
if HoTT_Sensor ~= 0 then
a = math.floor(detected_sensors/ (2^(HoTT_Sensor-1))) -- shift right
end
until HoTT_Sensor==0 or a % 2 == 1
HoTT_Send( 0x0F )
end
end
local function HoTT_Draw_LCD()
local i
local value
local line
local result
local offset=0
local sensor_name = { "", "+Vario", "+GPS", "+Cust", "+ESC", "+GAM", "+EAM" }
lcd.clear()
if LCD_W == 480 then
--Draw title
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
lcd.drawText(1, 5, "Graupner HoTT: config RX" .. sensor_name[HoTT_Sensor+1] .. " - Menu cycle Sensors", MENU_TITLE_COLOR)
--Draw RX Menu
if multiBuffer( 4 ) == 0xFF then
lcd.drawText(10,50,"No HoTT telemetry...", BLINK)
else
for line = 0, 7, 1 do
for i = 0, 21-1, 1 do
value=multiBuffer( line*21+6+i )
if value > 0x80 then
value = value - 0x80
lcd.drawText(10+i*16,32+20*line,string.char(value).." ",INVERS)
else
lcd.drawText(10+i*16,32+20*line,string.char(value))
end
end
end
end
else
--Draw RX Menu on LCD_W=128
if multiBuffer( 4 ) == 0xFF then
lcd.drawText(2,17,"No HoTT telemetry...",SMLSIZE)
else
if Timer_128 ~= 0 then
--Intro page
Timer_128 = Timer_128 - 1
lcd.drawScreenTitle("Graupner Hott",0,0)
lcd.drawText(2,17,"Configuration of RX" .. sensor_name[HoTT_Sensor+1] ,SMLSIZE)
lcd.drawText(2,37,"Press menu to cycle Sensors" ,SMLSIZE)
else
--Menu page
for line = 0, 7, 1 do
for i = 0, 21-1, 1 do
value=multiBuffer( line*21+6+i )
if value > 0x80 then
value = value - 0x80
lcd.drawText(2+i*6,1+8*line,string.char(value).." ",SMLSIZE+INVERS)
else
lcd.drawText(2+i*6,1+8*line,string.char(value),SMLSIZE)
end
end
end
end
end
end
end
-- Init
local function HoTT_Init()
--Set protocol to talk to
multiBuffer( 0, string.byte('H') )
--test if value has been written
if multiBuffer( 0 ) ~= string.byte('H') then
error("Not enough memory!")
return 2
end
multiBuffer( 1, string.byte('o') )
multiBuffer( 2, string.byte('T') )
multiBuffer( 3, string.byte('T') )
--Request init of the RX buffer
multiBuffer( 4, 0xFF )
--Request RX to send the config menu
HoTT_Send( 0x0F )
HoTT_Sensor = 0;
HoTT_Detected_Sensors=0;
Timer_128 = 100
end
-- Main
local function HoTT_Run(event)
if event == nil then
error("Cannot be run as a model script!")
return 2
elseif event == EVT_VIRTUAL_EXIT then
HoTT_Release()
return 2
else
if event == EVT_VIRTUAL_PREV_PAGE then
killEvents(event)
HoTT_Send( 0x07 )
elseif event == EVT_VIRTUAL_ENTER then
HoTT_Send( 0x09 )
elseif event == EVT_VIRTUAL_PREV then
HoTT_Send( 0x0B )
elseif event == EVT_VIRTUAL_NEXT then
HoTT_Send( 0x0D )
elseif event == EVT_VIRTUAL_NEXT_PAGE then
HoTT_Send( 0x0E )
elseif event == EVT_VIRTUAL_MENU then
Timer_128 = 100
HoTT_Sensor_Inc()
else
HoTT_Send( 0x0F )
end
HoTT_Draw_LCD()
return 0
end
end
return { init=HoTT_Init, run=HoTT_Run }

184
Lua_scripts/MultiChan.txt Normal file
View File

@@ -0,0 +1,184 @@
24,0,Assan,Std,0,CH5,CH6,CH7,CH8
14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2
14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates
14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf
14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
14,5,Bayang,QX100,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video
41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED
42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED
42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol
34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess
13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess
37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8
37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8
37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8
12,0,CX10,Green,1,Flip,Rate
12,1,CX10,Blue,1,Flip,Rate,Pict,Video
12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess
12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video
12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip
12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH
7,0,Devo,8CH,0,CH5,CH6,CH7,CH8
7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10
7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
7,3,Devo,6CH,0,CH5,CH6
7,4,Devo,7CH,0,CH5,CH6,CH7
33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow
6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
6,4,DSM,AUTO,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
70,0,DSM_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH
45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH
45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH
16,0,ESKY,Std,0,Gyro,Pitch
16,1,ESKY,ET4,0,Gyro,Pitch
35,0,ESKY150,4CH,0
35,1,ESKY150,7CH,0,FMode,Aux6,Aux7
69,0,ESKY150V2,Std,0,CH5_RA,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
1,0,Flysky,Flysky,0,CH5,CH6,CH7,CH8
1,1,Flysky,V9x9,1,Flip,Light,Pict,Video
1,2,Flysky,V6x6,1,Flip,Light,Pict,Video,HLess,RTH,XCAL,YCAL
1,3,Flysky,V912,1,BtmBtn,TopBtn
1,4,Flysky,CX20,0,CH5,CH6,CH7
28,0,Flysky_AFHDS2A,PWM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
28,1,Flysky_AFHDS2A,PPM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
28,2,Flysky_AFHDS2A,PWM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
28,4,Flysky_AFHDS2A,PWM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
28,5,Flysky_AFHDS2A,PPM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
53,0,Height,5ch,0,Gear
53,1,Height,8ch,0,Gear,Gyro,Flap,Light
25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8
3,0,FrSkyD,D8,0,CH5,CH6,CH7,CH8
3,0,FrSkyD,D8Cloned,0,CH5,CH6,CH7,CH8
67,0,FrSkyL,LR12,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
67,1,FrSkyL,LR12_6CH,0,CH5,CH6
15,0,FrSkyX,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
15,1,FrSkyX,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
15,2,FrSkyX,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
15,3,FrSkyX,D16_8CH_LBT,0,CH5,CH6,CH7,CH8
15,4,FrSkyX,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
15,5,FrSkyX,D16Cloned_8CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
64,0,FrSkyX2,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
64,1,FrSkyX2,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
64,2,FrSkyX2,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
64,3,FrSkyX2,D16_8CH_LBT,1,CH5,CH6,CH7,CH8
64,4,FrSkyX2,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
64,5,FrSkyX2,D16Cloned_8CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
65,0,FrSkyR9,R9_915,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
65,1,FrSkyR9,R9_868,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
65,2,FrSkyR9,R9_915_8CH,0,CH5,CH6,CH7,CH8
65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8
55,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
55,1,FrSkyRX,CloneTX,0
58,0,FX816,P38,1
20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
23,0,FY326,FY326,1,Flip,RTH,HLess,Expert
47,0,GD00x,V1,1,Trim,LED,Rate
47,1,GD00x,V2,1,Trim,LED,Rate
32,0,GW008,FY326,1,Flip
36,0,H8_3D,Std,1,Flip,Light,Pict,Video,RTH,FlMode,Cal1
36,1,H8_3D,H20H,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
36,2,H8_3D,H20,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
36,3,H8_3D,H30,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
4,0,Hisky,Std,0,Gear,Pitch,Gyro,CH8
4,1,Hisky,HK310,0,Aux
39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9
39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9
39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9
26,0,Hontai,Std,1,Flip,LED,Pict,Video,HLess,RTH,Calib
26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess
2,1,Hubsan,H301,0,RTH,Light,Stab,Video
2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes
22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
71,0,JJRC345,JJRC345,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
71,1,JJRC345,SkyTmblr,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
49,0,KF606,Std,1,Trim
9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
73,0,Kyosho,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
18,0,MJXQ,WHL08,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
18,1,MJXQ,X600,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
18,2,MJXQ,X800,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
18,3,MJXQ,H26D,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
18,4,MJXQ,E010,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
18,5,MJXQ,H26WH,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
18,6,MJXQ,Phoenix,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
17,0,MT99XX,Std,1,Flip,LED,Pict,Video,HLess
17,1,MT99XX,H7,1,Flip,LED,Pict,Video,HLess
17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess
17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess
17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess
44,0,NCC1701,Std,1,Warp
77,0,OMP,M2,0,THold,IdleUp,6G_3D
60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
60,1,Pelikan,LITE_V4,0,CH5,CH6,CH7,CH8
51,0,Potensic,A20,1,TakLan,Emerg,Mode,HLess
66,0,Propel,74-Z,1,LEDs,RollCW,RolCCW,Fire,Weapon,Calib,AltHol,TakeOf,Land,Train
29,0,Q2x2,Q222,1,Flip,LED,Mod2,Mod1,HLess,RTH,XCal,YCal
29,1,Q2x2,Q242,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
29,2,Q2x2,Q282,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
31,0,Q303,Q303,1,AltHol,Flip,Pict,Video,HLess,RTH,Gimbal
31,1,Q303,C35,1,Arm,VTX,Pict,Video,n-a,RTH,Gimbal
31,2,Q303,CX10D,1,Arm,Flip
31,3,Q303,CX10WD,1,Arm,Flip
72,0,Q90C,Std,0,FMode,VTX+
74,0,RadioLink,Surface,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
74,1,RadioLink,Air,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
74,2,RadioLink,DumboRC,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
76,0,Realacc,R11,1,Flip,Light,Calib,HLess,RTH,UNK
50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
21,0,Futaba,SFHSS,0,CH5,CH6,CH7,CH8
19,0,Shenqi,Cycle,1
68,0,Skyartec,Std,0,CH5,CH6,CH7
11,0,SLT,V1,0,Gear,Pitch
11,1,SLT,V2,0,CH5,CH6,CH7,CH8
11,2,SLT,Q100,0,Rates,n-a,CH7,CH8,Mode,Flip,n-a,n-a,Calib
11,3,SLT,Q200,0,Rates,n-a,CH7,CH8,Mode,VidOn,VidOff,Calib
11,4,SLT,MR100,0,Rates,n-a,CH7,CH8,Mode,Flip,Video,Pict
10,0,Symax,Std,1,Flip,Rates,Pict,Video,HLess
10,1,Symax,X5C,1,Flip,Rates,Pict,Video,HLess
61,0,Tiger,Std,1,Flip,Light
43,0,Traxxas,6519,0
5,0,V2x2,Std,1,Flip,Light,Pict,Video,HLess,CalX,CalY
5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD
48,0,V761,3CH,0,Gyro,Calib,Flip,RtnAct,Rtn
48,1,V761,4CH,0,Gyro,Calib,Flip,RtnAct,Rtn
46,0,V911s,V911s,1,Calib
46,1,V911s,E119,1,Calib
22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8
30,1,WK2x01,WK2401,0
30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro
30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro
30,4,WK2x01,W6HEL,0,Gear,Col,Gyro
30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro
62,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess
8,1,YD717,SkyWlkr,1,Flip,Light,Pict,Video,HLess
8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess
8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess
8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess
52,0,ZSX,280,1,Light
78,0,M-Link,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
79,0,WFLY2,RF20x,0,CH5,CH6,CH7,CH8,CH9,CH10
80,0,E016Hv2,E016Hv2,1,TakLan,EmStop,Flip,Calib,HLess,RTH
81,0,E010r5,E010r5,1,Flip,LED,CALIB,HLess,RTH,GLIDE
82,0,LOLI,LOLI,0,CH5,CH6,CH7,CH8,1SwSePpPw,2SwSePw,3SwSe,4SwSe,5SwSeSb,6SwSe,7SwSePw,8SwSe
83,0,E129,E129,1,TakLan,EmStop,TrimA,TrimE,TrimR

View File

@@ -0,0 +1,311 @@
local toolName = "TNS|Multi chan namer|TNE"
---- #########################################################################
---- # #
---- # Copyright (C) OpenTX #
-----# #
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
---- # #
---- # This program is free software; you can redistribute it and/or modify #
---- # it under the terms of the GNU General Public License version 2 as #
---- # published by the Free Software Foundation. #
---- # #
---- # This program is distributed in the hope that it will be useful #
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
---- # GNU General Public License for more details. #
---- # #
---- #########################################################################
local protocol_name = ""
local sub_protocol_name = ""
local bind_ch = 0
local module_conf = {}
local module_pos = "Internal"
local file_ok = 0
local done = 0
local protocol = 0
local sub_protocol = 0
local f_seek = 0
local channel_names={}
local num_search = "Searching"
local function drawScreenTitle(title)
if LCD_W == 480 then
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
else
lcd.drawScreenTitle(title, 0, 0)
end
end
function bitand(a, b)
local result = 0
local bitval = 1
while a > 0 and b > 0 do
if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits
result = result + bitval -- set the current bit
end
bitval = bitval * 2 -- shift left
a = math.floor(a/2) -- shift right
b = math.floor(b/2)
end
return result
end
local function Multi_Draw_LCD(event)
local line = 0
lcd.clear()
drawScreenTitle("Multi channels namer")
--Display settings
local lcd_opt = 0
if LCD_W == 480 then
x_pos = 10
y_pos = 32
y_inc = 20
else
x_pos = 0
y_pos = 9
y_inc = 8
lcd_opt = SMLSIZE
end
--Multi Module detection
if module_conf["Type"] ~= 6 then
if LCD_W == 480 then
lcd.drawText(10,50,"No Multi module configured...", BLINK)
else
--Draw on LCD_W=128
lcd.drawText(2,17,"No Multi module configured...",SMLSIZE)
end
return
else
lcd.drawText(x_pos, y_pos+y_inc*line,module_pos .. " Multi detected.", lcd_opt)
line = line + 1
end
--Channel order
if (ch_order == -1) then
lcd.drawText(x_pos, y_pos+y_inc*line,"Channels order can't be read from Multi...", lcd_opt)
line = line + 1
end
--Can't open file MultiChan.txt
if file_ok == 0 then
lcd.drawText(x_pos, y_pos+y_inc*line,"Can't read MultiChan.txt file...", lcd_opt)
return
end
if ( protocol_name == "" or sub_protocol_name == "" ) and f_seek ~=-1 then
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
if f == nil then return end
lcd.drawText(x_pos, y_pos+y_inc*line,num_search, lcd_opt)
num_search = num_search .. "."
if #num_search > 15 then
num_search = string.sub(num_search,1,9)
end
local proto = 0
local sub_proto = 0
local proto_name = ""
local sub_proto_name = ""
local channels = ""
local nbr_try = 0
local nbr_car = 0
repeat
io.seek(f, f_seek)
local data = io.read(f, 100) -- read 100 characters
if #data ==0 then
f_seek = -1 -- end of file
break
end
proto, sub_proto, proto_name, sub_proto_name, bind_ch, channels = string.match(data,'(%d+),(%d),([%w-_ ]+),([%w-_ ]+),(%d)(.+)')
if proto ~= nil and sub_proto ~= nil and protocol_name ~= nil and sub_protocol_name ~= nil and bind_ch ~= nil then
if tonumber(proto) == protocol and tonumber(sub_proto) == sub_protocol then
protocol_name = proto_name
sub_protocol_name = sub_proto_name
bind_ch = tonumber(bind_ch)
if channels ~= nil then
--extract channel names
nbr_car = string.find(channels, "\r")
if nbr_car == nil then nbr_car = string.find(channels, "\n") end
if nbr_car ~= nil then
channels = string.sub(channels,1,nbr_car-1)
end
local i = 5
for k in string.gmatch(channels, ",([%w-_ ]+)") do
channel_names[i] = k
i = i + 1
end
end
f_seek = -1 -- protocol found
break
end
end
if f_seek ~= -1 then
nbr_car = string.find(data, "\n")
if nbr_car == nil then nbr_car = string.find(data, "\r") end
if nbr_car == nil then
f_seek = -1 -- end of file
break
end
f_seek = f_seek + nbr_car -- seek to next line
nbr_try = nbr_try + 1
end
until nbr_try > 20 or f_seek == -1
io.close(f)
end
if f_seek ~= -1 then
return -- continue searching...
end
--Protocol & Sub_protocol
if protocol_name == "" or sub_protocol_name == "" then
lcd.drawText(x_pos, y_pos+y_inc*line,"Unknown protocol "..tostring(protocol).."/"..tostring(sub_protocol).." ...", lcd_opt)
return
elseif LCD_W > 128 then
lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name .. " / SubProtocol: " .. sub_protocol_name, lcd_opt)
line = line + 1
else
lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name, lcd_opt)
line = line + 1
lcd.drawText(x_pos, y_pos+y_inc*line,"SubProtocol: " .. sub_protocol_name, lcd_opt)
line = line + 1
end
text1=""
text2=""
for i,v in ipairs(channel_names) do
if i<=8 then
if i==1 then
text1 = v
else
text1=text1 .. "," .. v
end
else
if i==9 then
text2 = v
else
text2=text2 .. "," .. v
end
end
end
if LCD_W > 128 then
lcd.drawText(x_pos, y_pos+y_inc*line,"Channels: " .. text1, lcd_opt)
line = line + 1
if text2 ~= "" then
lcd.drawText(x_pos*9, y_pos+y_inc*line,text2, lcd_opt)
line = line + 1
end
end
if event ~= EVT_VIRTUAL_ENTER and done == 0 then
lcd.drawText(x_pos, y_pos+y_inc*line,"<ENT> Save", lcd_opt + INVERS + BLINK)
return
end
lcd.drawText(x_pos, y_pos+y_inc*line,"Setting channel names.", lcd_opt)
line = line + 1
local output, nbr
if done == 0 then
for i,v in ipairs(channel_names) do
output = model.getOutput(i-1)
output["name"] = v
model.setOutput(i-1,output)
nbr = i
end
for i = nbr, 15 do
output = model.getOutput(i)
output["name"] = "n-a"
model.setOutput(i,output)
end
if bind_ch == 1 then
output = model.getOutput(15)
output["name"] = "BindCH"
model.setOutput(15,output)
end
done = 1
end
lcd.drawText(x_pos, y_pos+y_inc*line,"Done!", lcd_opt)
line = line + 1
end
-- Init
local function Multi_Init()
module_conf = model.getModule(0)
if module_conf["Type"] ~= 6 then
module_pos = "External"
module_conf = model.getModule(1)
if module_conf["Type"] ~= 6 then
return
end
end
protocol = module_conf["protocol"]
sub_protocol = module_conf["subProtocol"]
--Exceptions on first 4 channels...
local stick_names = { "Rud", "Ele", "Thr", "Ail" }
if ( protocol == 4 and sub_protocol == 1 ) or protocol == 19 or protocol == 52 then -- Hisky/HK310, Shenqi, ZSX
stick_names[2] = "n-a"
stick_names[4] = "n-a"
elseif protocol == 43 then -- Traxxas
stick_names[2] = "Aux4"
stick_names[4] = "Aux3"
elseif ( protocol == 48 and sub_protocol == 0 ) then -- V761 3CH
stick_names[4] = "n-a"
elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816
stick_names[1] = "n-a"
stick_names[2] = "n-a"
end
--Determine fist 4 channels order
local ch_order=module_conf["channelsOrder"]
if (ch_order == -1) then
channel_names[1] = stick_names[defaultChannel(0)+1]
channel_names[2] = stick_names[defaultChannel(1)+1]
channel_names[3] = stick_names[defaultChannel(2)+1]
channel_names[4] = stick_names[defaultChannel(3)+1]
else
channel_names[bitand(ch_order,3)+1] = stick_names[4]
ch_order = math.floor(ch_order/4)
channel_names[bitand(ch_order,3)+1] = stick_names[2]
ch_order = math.floor(ch_order/4)
channel_names[bitand(ch_order,3)+1] = stick_names[3]
ch_order = math.floor(ch_order/4)
channel_names[bitand(ch_order,3)+1] = stick_names[1]
end
--Exceptions on first 4 channels...
if ( protocol == 73 or (protocol == 74 and sub_protocol == 0) ) then -- Kyosho or RadioLink Surface
channel_names[1] = "ST"
channel_names[2] = "THR"
channel_names[3] = "CH3"
channel_names[4] = "CH4"
end
--Check MultiChan.txt
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
if f == nil then return end
file_ok = 1
io.close(f)
end
-- Main
local function Multi_Run(event)
if event == nil then
error("Cannot be run as a model script!")
return 2
else
Multi_Draw_LCD(event)
if event == EVT_VIRTUAL_EXIT then
return 2
end
end
return 0
end
return { init=Multi_Init, run=Multi_Run }

221
Lua_scripts/MultiLOLI.lua Normal file
View File

@@ -0,0 +1,221 @@
local toolName = "TNS|Multi LOLI RX config|TNE"
---- #########################################################################
---- # #
---- # Copyright (C) OpenTX #
-----# #
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
---- # #
---- # This program is free software; you can redistribute it and/or modify #
---- # it under the terms of the GNU General Public License version 2 as #
---- # published by the Free Software Foundation. #
---- # #
---- # This program is distributed in the hope that it will be useful #
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
---- # GNU General Public License for more details. #
---- # #
---- #########################################################################
local loli_nok = false
local channels={ { 768, "PWM", 100, 102, "PPM", 50, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH1
{ 768, "PWM", 100, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH2
{ -768, "Servo", 0, -2048, "Switch", -100 }, -- CH3
{ -768, "Servo", 0, -2048, "Switch", -100 }, -- CH4
{ 102, "SBUS", 50, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH5
{ -768, "Servo", 0, -2048, "Switch", -100 }, -- CH6
{ 768, "PWM", 100, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH7
{ -768, "Servo", 0, -2048, "Switch", -100 } } -- CH8
local sel = 1
local edit = false
local blink = 0
local BLINK_SPEED = 15
local function drawScreenTitle(title)
if LCD_W == 480 then
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
else
lcd.drawScreenTitle(title, 0, 0)
end
end
local function LOLI_Draw_LCD(event)
local line = 0
lcd.clear()
--Display settings
local lcd_opt = 0
if LCD_W == 480 then
drawScreenTitle("Multi - LOLI RX configuration tool")
x_pos = 152
x_inc = 90
y_pos = 40
y_inc = 20
else
x_pos = 5
x_inc = 30
y_pos = 1
y_inc = 8
lcd_opt = SMLSIZE
end
--Multi Module detection
if loli_nok then
if LCD_W == 480 then
lcd.drawText(10,50,"The LOLI protocol is not selected...", lcd_opt)
else
--Draw on LCD_W=128
lcd.drawText(2,17,"LOLI protocol not selected...",SMLSIZE)
end
return
end
--Display current config
if LCD_W == 480 then
line = line + 1
lcd.drawText(x_pos, y_pos+y_inc*line -2, "Channel", lcd_opt)
lcd.drawText(x_pos+x_inc, y_pos+y_inc*line -2, "Function", lcd_opt)
lcd.drawRectangle(x_pos-4, y_pos+y_inc*line -4 , 2*x_inc +2, 188)
lcd.drawLine(x_pos-4, y_pos+y_inc*line +18, x_pos-4 +2*x_inc +1, y_pos+y_inc*line +18, SOLID, 0)
lcd.drawLine(x_pos+x_inc -5, y_pos+y_inc*line -4, x_pos+x_inc -5, y_pos+y_inc*line -5 +188, SOLID, 0)
line = line + 1
end
local out
for i = 1, 8 do
out = getValue("ch"..(i+8))
lcd.drawText(x_pos, y_pos+y_inc*line, "CH"..i, lcd_opt)
for j = 1, #channels[i], 3 do
if out > channels[i][j] then
if sel == i then
invert = INVERS
if edit == true then
blink = blink + 1
if blink > BLINK_SPEED then
invert = 0
if blink > BLINK_SPEED * 2 then
blink = 0
end
end
end
else
invert = 0
end
lcd.drawText(x_pos+x_inc, y_pos+y_inc*line, channels[i][j+1], lcd_opt + invert)
break
end
end
line = line + 1
end
end
local function LOLI_Change_Value(dir)
local pos = 0
local out
--look for the current position
out = getValue("ch"..(sel+8))
for j = 1, #channels[sel], 3 do
if out > channels[sel][j] then
pos = j
break
end
end
--decrement or increment
if dir < 0 and pos > 1 then
pos = pos - 3
elseif dir > 0 and pos + 3 < #channels[sel] then
pos = pos + 3
else
return
end
--delete all mixers for the selected channel
local num_mix = model.getMixesCount(sel-1 +8)
for i = 1, num_mix do
model.deleteMix(sel-1 +8, 0);
end
--create new mixer
local source_max = getFieldInfo("cyc1")
local val = { name = channels[sel][pos+1],
source = source_max.id - 1, -- MAX=100 on TX16S
weight = channels[sel][pos+2],
offset = 0,
switch = 0,
multiplex = 0,
curveType = 0,
curveValue = 0,
flightModes = 0,
carryTrim = false,
mixWarn = 0,
delayUp = 0,
delayDown = 0,
speedUp = 0,
speedDown = 0 }
model.insertMix(sel-1 +8, 0, val)
end
local function LOLI_Menu(event)
if event == EVT_VIRTUAL_NEXT then
if edit == false then
-- not changing a value
if sel < 8 then
sel = sel + 1
end
else
-- need to inc the value
LOLI_Change_Value(1)
end
elseif event == EVT_VIRTUAL_PREV then
if edit == false then
-- not changing a value
if sel > 1 then
sel = sel - 1
end
else
-- need to dec the value
LOLI_Change_Value(-1)
end
elseif event == EVT_VIRTUAL_ENTER then
if edit == false then
edit = true
blink = BLINK_SPEED
else
edit = false
end
end
end
-- Init
local function LOLI_Init()
local module_conf = model.getModule(0)
if module_conf["Type"] ~= 6 or module_conf["protocol"] ~= 82 then
module_conf = model.getModule(1)
if module_conf["Type"] ~= 6 or module_conf["protocol"] ~= 82 then
loli_nok = true
end
end
end
-- Main
local function LOLI_Run(event)
if event == nil then
error("Cannot be run as a model script!")
return 2
elseif event == EVT_VIRTUAL_EXIT then
return 2
else
LOLI_Menu(event)
LOLI_Draw_LCD(event)
return 0
end
end
return { init=LOLI_Init, run=LOLI_Run }

56
Lua_scripts/README.md Normal file
View File

@@ -0,0 +1,56 @@
# Multiprotocol TX Module OpenTX LUA scripts
<img align="right" width=300 src="../docs/images/multi.png" />
If you like this project and want to support further development please consider making a [donation](../docs/Donations.md).
<table cellspacing=0>
<tr>
<td align=center width=200><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=VF2K9T23DRY56&lc=US&item_name=DIY%20Multiprotocol&currency_code=EUR&amount=5&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted"><img src="../docs/images/donate_button.png" border="0" name="submit" title="PayPal - Donate €5" alt="Donate €5"/></a><br><b>€5</b></td>
<td align=center width=200><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=VF2K9T23DRY56&lc=US&item_name=DIY%20Multiprotocol&currency_code=EUR&amount=10&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted"><img src="../docs/images/donate_button.png" border="0" name="submit" title="PayPal - Donate €10" alt="Donate €10"/></a><br><b>€10</b></td>
<td align=center width=200><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=VF2K9T23DRY56&lc=US&item_name=DIY%20Multiprotocol&currency_code=EUR&amount=15&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted"><img src="../docs/images/donate_button.png" border="0" name="submit" title="PayPal - Donate €15" alt="Donate €10"/></a><br><b>€15</b></td>
<td align=center width=200><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=VF2K9T23DRY56&lc=US&item_name=DIY%20Multiprotocol&currency_code=EUR&amount=25&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted"><img src="../docs/images/donate_button.png" border="0" name="submit" title="PayPal - Donate €25" alt="Donate €25"/></a><br><b>€25</b></td>
<td align=center width=200><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=VF2K9T23DRY56&lc=US&item_name=DIY%20Multiprotocol&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted"><img src="../docs/images/donate_button.png" border="0" name="submit" title="PayPal - Donate" alt="Donate"/></a><br><b>Other</b></td>
</tr>
</table>
## MultiChannelsUpdater
Automatically name the channels based on the loaded Multi protocol and sub protocol including the module channel order convention.
Need OpenTX 2.3.9 or above. Located on the radio SD card under \SCRIPTS\TOOLS. This script needs MultiChan.txt to be present in the same folder.
[![MultiChannelsUpdater](https://img.youtube.com/vi/L58ayXuewyA/0.jpg)](https://www.youtube.com/watch?v=L58ayXuewyA)
## MultiLOLI
Script to set the channels function (switch, servo, pwm, ppm, sbus) on a [LOLI RX](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/Protocols_Details.md#loli---82)
[![MultiLOLIconfig](https://img.youtube.com/vi/e698pQxfv-A/0.jpg)](https://www.youtube.com/watch?v=e698pQxfv-A)
## Graupner HoTT
Enable text configuration of the HoTT RX and sensors: Vario, GPS, ESC, GAM and EAM.
Need OpenTX 2.3.9 or above. Located on the radio SD card under \SCRIPTS\TOOLS.
Notes:
- Menu/MDL/Model is used to cycle through the detected sensors.
- It's normal to lose the telemetry feed while using the text mode configuration. Telemetry will resume properly if the script is exited by doing a short press on the exit button.
[![Text mode video](https://img.youtube.com/vi/81wd8NlF3Qw/0.jpg)](https://www.youtube.com/watch?v=81wd8NlF3Qw)
## DSM Forward Programming
This is a work in progress. It's only available for color screens (Horus, TX16S, T16, T18...).
If some text appears as Unknown_xxx, please report xxx and what the exact text display should be.
Need OpenTX 2.3.10 nightly or above. Located on the radio SD card under \SCRIPTS\TOOLS.
[![DSM Forward Programming](https://img.youtube.com/vi/sjIaDw5j9nE/0.jpg)](https://www.youtube.com/watch?v=sjIaDw5j9nE)
## DSM PID Flight log gain parameters for Blade micros
Lua telemetry script from [feathering on RCGroups](https://www.rcgroups.com/forums/showpost.php?p=46033341&postcount=20728) to facilitate setting the Gain Parameters on the Blade 150S FBL. It doesn't use Forward Programming but instead it just reads telemetry data from the Multi-module and displays it on a telemetry display.
It is very similar to the Telemetry Based Text Generator functionality on Spektrum transmitters where one doesn't need to rely on the angle of the swashplate to determine selection/value.

127
Lua_scripts/pidDsm.lua Normal file
View File

@@ -0,0 +1,127 @@
--
-- This telemetry script displays the Flight Log Gain
-- Parameters streamed from the Blade 150S Spektrum AR6335A
-- Flybarless Controller.
-- The script facilitates the setting of the FBL's
-- Gain Parameters including PID for both
-- cyclic and tail. It is similar to the Telemetry Based
-- Text Generator available on Spektrum transmitters.
-- Supporting similar Blade micros such as the Fusion 180
-- would possibly require minor modifications to this script.
-- This script reads telemetry data from the Spektrum
-- receiver and thus functionality relies on data being
-- captured by the OpenTX transmitter. A DSM
-- telemetry-ready module is required. Please see the
-- MULTI-Module project at https://www.multi-module.org/.
-- The only supported display is the Taranis'. It may work
-- with higher res screens.
--
-- Sensor names
local PSensor = "FdeA"
local ISensor = "FdeB"
local DSensor = "FdeL"
local RSensor = "FdeR"
local ActiveParamSensor = "Hold"
local tags = {"P", "I", "D"}
local function getPage(iParam)
-- get page from 0-based index
-- {0,1,2,3}: cyclic (1), {4,5,6,7}: tail (2)
local res = (math.floor(iParam/4)==0) and 1 or 2
return res
end
function round(v)
-- round float
local factor = 100
return math.floor(v * factor + 0.5) / factor
end
local function readValue(sensor)
-- read from sensor, round and return
local v = getValue(sensor)
v = round(v)
return v
end
local function readActiveParamValue(sensor)
-- read and return a validated active parameter value
local v = getValue(sensor)
if (v<1 or v>8) then
return nil
end
return v
end
local function readParameters()
-- read and return parameters
local p = readValue(PSensor)
local i = readValue(ISensor)
local d = readValue(DSensor)
local r = readValue(RSensor)
local a = readActiveParamValue(ActiveParamSensor)
return {p,i,d,r,a}
end
local function drawParameters()
-- draw labels and params on screen
local params = readParameters()
local activeParam = params[5]
-- if active gain does not validate then assume
-- Gain Adjustment Mode is disabled
if not activeParam then
lcd.clear()
lcd.drawText(20,30,"Please enter Gain Adjustment Mode")
return
end
local activePage = getPage(activeParam-1)
for iParam=0,7 do
-- highlight selected parameter
local attr = (activeParam==iParam+1) and 2 or 0
-- circular index (per page)
local perPageIndx = iParam % 4 + 1
-- check if displaying cyclic params.
local isCyclicPage = (getPage(iParam)==1)
-- set y draw coord
local y = perPageIndx*10+2
-- labels
local x = isCyclicPage and 6 or 120
-- labels are P,I,D for both pages except for last param
local val = iParam==3 and "Response" or
(iParam==7 and "Filtering" or tags[perPageIndx])
lcd.drawText (x, y, val, attr)
-- gains
-- set all params for non-active page to '--' rather than 'last value'
val = (getPage(iParam)==activePage) and params[perPageIndx] or '--'
x = isCyclicPage and 70 or 180
lcd.drawText (x, y, val, attr)
end
end
local function run_func(event)
-- TODO: calling clear() on every function call redrawing all labels is not ideal
lcd.clear()
lcd.drawText (8, 2, "Cyclic (0...200)")
lcd.drawText (114, 2, "Tail (0...200)")
drawParameters()
end
local function init_func() end
local function bg_func() end
return { run=run_func, background=bg_func, init=init_func }

View File

@@ -27,13 +27,16 @@ void A7105_WriteData(uint8_t len, uint8_t channel)
for (i = 0; i < len; i++)
SPI_Write(packet[i]);
A7105_CSN_on;
if(protocol!=PROTO_FLYSKY)
if(protocol!=PROTO_WFLY2)
{
A7105_Strobe(A7105_STANDBY); //Force standby mode, ie cancel any TX or RX...
A7105_SetTxRxMode(TX_EN); //Switch to PA
if(!(protocol==PROTO_FLYSKY || protocol==PROTO_KYOSHO))
{
A7105_Strobe(A7105_STANDBY); //Force standby mode, ie cancel any TX or RX...
A7105_SetTxRxMode(TX_EN); //Switch to PA
}
A7105_WriteReg(A7105_0F_PLL_I, channel);
A7105_Strobe(A7105_TX);
}
A7105_WriteReg(A7105_0F_PLL_I, channel);
A7105_Strobe(A7105_TX);
}
void A7105_ReadData(uint8_t len)
@@ -107,7 +110,7 @@ void A7105_WriteID(uint32_t ida)
{
A7105_CSN_off;
SPI_Write(A7105_06_ID_DATA); //ex id=0x5475c52a ;txid3txid2txid1txid0
SPI_Write((ida>>24)&0xff); //53
SPI_Write((ida>>24)&0xff); //54
SPI_Write((ida>>16)&0xff); //75
SPI_Write((ida>>8)&0xff); //c5
SPI_Write((ida>>0)&0xff); //2a
@@ -192,9 +195,9 @@ 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;
case PROTO_HEIGHT:
#ifdef FORCE_HEIGHT_TUNING
offset=(int16_t)FORCE_HEIGHT_TUNING;
#endif
break;
case PROTO_PELIKAN:
@@ -202,6 +205,16 @@ void A7105_AdjustLOBaseFreq(uint8_t cmd)
offset=(int16_t)FORCE_PELIKAN_TUNING;
#endif
break;
case PROTO_KYOSHO:
#ifdef FORCE_KYOSHO_TUNING
offset=(int16_t)FORCE_KYOSHO_TUNING;
#endif
break;
case PROTO_WFLY2:
#ifdef FORCE_WFLY2_TUNING
offset=(int16_t)FORCE_WFLY2_TUNING;
#endif
break;
case PROTO_AFHDS2A:
case PROTO_AFHDS2A_RX:
#ifdef FORCE_AFHDS2A_TUNING
@@ -211,7 +224,7 @@ void A7105_AdjustLOBaseFreq(uint8_t cmd)
}
}
if(offset==1024) // Use channel 15 as an input
offset=convert_channel_16b_nolimit(CH15,-300,300);
offset=convert_channel_16b_nolimit(CH15,-300,300,false);
if(old_offset==offset) // offset is the same as before...
return;
@@ -282,8 +295,8 @@ const uint8_t PROGMEM FLYSKY_A7105_regs[] = {
0x01, 0x0f // 30 - 31
};
#endif
#ifdef FLYZONE_A7105_INO
const uint8_t PROGMEM FLYZONE_A7105_regs[] = {
#ifdef HEIGHT_A7105_INO
const uint8_t PROGMEM HEIGHT_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
@@ -306,6 +319,28 @@ const uint8_t PROGMEM PELIKAN_A7105_regs[] = {
0x01, 0x0f // 30 - 31
};
#endif
#ifdef KYOSHO_A7105_INO
const uint8_t PROGMEM KYOSHO_A7105_regs[] = {
0xff, 0x42, 0xff, 0x25, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50, // 00 - 0f
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x40, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0x03, 0x1f, // 10 - 1f
0x1e, 0x00, 0x00, 0xff, 0x00, 0x00, 0x23, 0x70, 0x1F, 0x47, 0x80, 0x57, 0x01, 0x45, 0x19, 0x00, // 20 - 2f
0x01, 0x0f // 30 - 31
};
const uint8_t PROGMEM KYOSHO_HYPE_A7105_regs[] = {
0xff, 0x42, 0x00, 0x10, 0xC0, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0x05, 0x01, 0x04, // 00 - 0f
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x96, 0xc2, 0x1f, // 10 - 1f
0x12, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3a, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f
0x01, 0x0f // 30 - 31
};
#endif
#ifdef WFLY2_A7105_INO //A7106 values
const uint8_t PROGMEM WFLY2_A7105_regs[] = {
0xff, 0x62, 0xff, 0x1F, 0x40, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x05, 0x00, 0x64, // 00 - 0f Changes: 0B:19->33, 0C:01,33
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x40, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0x03, 0x0f, // 10 - 1f 1C:4A->0A
0x12, 0x00, 0x00, 0xff, 0x00, 0x00, 0x23, 0x70, 0x15, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f 2B:77->03, 2E:19->18
0x01, 0x0f // 30 - 31
};
#endif
#define ID_NORMAL 0x55201041
#define ID_PLUS 0xAA201041
@@ -314,10 +349,17 @@ void A7105_Init(void)
uint8_t *A7105_Regs=0;
uint8_t vco_calibration0, vco_calibration1;
#ifdef FLYZONE_A7105_INO
if(protocol==PROTO_FLYZONE)
#ifdef WFLY2_A7105_INO
if(protocol==PROTO_WFLY2)
{
A7105_Regs=(uint8_t*)FLYZONE_A7105_regs;
A7105_Regs=(uint8_t*)WFLY2_A7105_regs;
}
else
#endif
#ifdef HEIGHT_A7105_INO
if(protocol==PROTO_HEIGHT)
{
A7105_Regs=(uint8_t*)HEIGHT_A7105_regs;
A7105_WriteID(0x25A53C45);
}
else
@@ -348,13 +390,20 @@ void A7105_Init(void)
#ifdef FLYSKY_A7105_INO
if(protocol==PROTO_FLYSKY)
A7105_Regs=(uint8_t*)FLYSKY_A7105_regs;
else
#endif
#if defined(AFHDS2A_A7105_INO) || defined(AFHDS2A_RX_A7105_INO)
if(protocol==PROTO_AFHDS2A || protocol==PROTO_AFHDS2A_RX)
A7105_Regs=(uint8_t*)AFHDS2A_A7105_regs;
#endif
#ifdef KYOSHO_A7105_INO
if(protocol==PROTO_KYOSHO)
{
#if defined(AFHDS2A_A7105_INO) || defined(AFHDS2A_RX_A7105_INO)
A7105_Regs=(uint8_t*)AFHDS2A_A7105_regs;
#endif
if(sub_protocol==KYOSHO_FHSS)
A7105_Regs=(uint8_t*)KYOSHO_A7105_regs;
else
A7105_Regs=(uint8_t*)KYOSHO_HYPE_A7105_regs;
}
#endif
}
for (uint8_t i = 0; i < 0x32; i++)
@@ -368,59 +417,78 @@ void A7105_Init(void)
if(i==0x20) val=0x1E;
}
#endif
if( val != 0xFF)
#ifdef HEIGHT_A7105_INO
if(protocol==PROTO_HEIGHT && sub_protocol==HEIGHT_8CH)
if(i==0x03) val=0x0A;
#endif
if( val != 0xff)
A7105_WriteReg(i, val);
}
A7105_Strobe(A7105_STANDBY);
//IF Filter Bank Calibration
A7105_WriteReg(A7105_02_CALC,1);
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
// A7105_ReadReg(A7105_22_IF_CALIB_I);
// A7105_ReadReg(A7105_24_VCO_CURCAL);
if(protocol!=PROTO_HUBSAN)
{
//VCO Current Calibration
A7105_WriteReg(A7105_24_VCO_CURCAL,0x13); //Recommended calibration from A7105 Datasheet
//VCO Bank Calibration
A7105_WriteReg(A7105_26_VCO_SBCAL_II,0x3b); //Recommended calibration from A7105 Datasheet
if(protocol==PROTO_KYOSHO && sub_protocol==KYOSHO_FHSS)
{//strange calibration...
//IF Filter Bank Calibration
A7105_WriteReg(A7105_02_CALC,0x0F);
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
// A7105_ReadReg(A7105_22_IF_CALIB_I);
// A7105_ReadReg(A7105_24_VCO_CURCAL);
// A7105_ReadReg(25_VCO_SBCAL_I);
// A7105_ReadReg(1A_RX_GAIN_II);
// A7105_ReadReg(1B_RX_GAIN_III);
}
//VCO Bank Calibrate channel 0
A7105_WriteReg(A7105_0F_CHANNEL, 0);
A7105_WriteReg(A7105_02_CALC,2);
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
vco_calibration0 = A7105_ReadReg(A7105_25_VCO_SBCAL_I);
//VCO Bank Calibrate channel A0
A7105_WriteReg(A7105_0F_CHANNEL, 0xa0);
A7105_WriteReg(A7105_02_CALC, 2);
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
vco_calibration1 = A7105_ReadReg(A7105_25_VCO_SBCAL_I);
if(protocol==PROTO_BUGS)
A7105_SetVCOBand(vco_calibration0 & 0x07, vco_calibration1 & 0x07); // Set calibration band value to best match
else
{
//IF Filter Bank Calibration
A7105_WriteReg(A7105_02_CALC,1);
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
// A7105_ReadReg(A7105_22_IF_CALIB_I);
// A7105_ReadReg(A7105_24_VCO_CURCAL);
if(protocol!=PROTO_HUBSAN)
{
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
//VCO Current Calibration
A7105_WriteReg(A7105_24_VCO_CURCAL,0x13); //Recommended calibration from A7105 Datasheet
//VCO Bank Calibration
A7105_WriteReg(A7105_26_VCO_SBCAL_II,0x3b); //Recommended calibration from A7105 Datasheet
}
//VCO Bank Calibrate channel 0
A7105_WriteReg(A7105_0F_CHANNEL, 0);
A7105_WriteReg(A7105_02_CALC,2);
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
vco_calibration0 = A7105_ReadReg(A7105_25_VCO_SBCAL_I);
//VCO Bank Calibrate channel A0
A7105_WriteReg(A7105_0F_CHANNEL, 0xa0);
A7105_WriteReg(A7105_02_CALC, 2);
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
vco_calibration1 = A7105_ReadReg(A7105_25_VCO_SBCAL_I);
if(protocol==PROTO_BUGS || protocol==PROTO_WFLY2)
A7105_SetVCOBand(vco_calibration0 & 0x07, vco_calibration1 & 0x07); // Set calibration band value to best match
else
if(protocol!=PROTO_HUBSAN)
{
switch(protocol)
{
case PROTO_FLYSKY:
vco_calibration1=0x08;
break;
case PROTO_HEIGHT:
vco_calibration1=0x02;
break;
case PROTO_PELIKAN:
case PROTO_KYOSHO: //sub_protocol Hype
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();

View File

@@ -24,6 +24,7 @@
enum {
AFHDS2A_RX_BIND1,
AFHDS2A_RX_BIND2,
AFHDS2A_RX_BIND3,
AFHDS2A_RX_DATA
};
@@ -39,7 +40,7 @@ static void __attribute__((unused)) AFHDS2A_Rx_build_telemetry_packet()
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);
uint32_t val = packet[9+i*2] | (((packet[10+i*2])&0x0F) << 8);
if (val < 860)
val = 860;
// convert ppm (860-2140) to Multi (0-2047)
@@ -90,8 +91,6 @@ uint16_t initAFHDS2A_Rx()
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;
@@ -106,20 +105,23 @@ uint16_t AFHDS2A_Rx_callback()
switch(phase) {
case AFHDS2A_RX_BIND1:
if(IS_BIND_DONE) return initAFHDS2A_Rx(); // Abort bind
debugln("bind p=%d", phase+1);
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;
debugln("phase 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:
if(IS_BIND_DONE) return initAFHDS2A_Rx(); // Abort bind
// got 2nd bind packet from tx ?
if (AFHDS2A_Rx_data_ready()) {
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
@@ -132,30 +134,41 @@ uint16_t AFHDS2A_Rx_callback()
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;
phase = AFHDS2A_RX_BIND3;
debugln("phase bind3");
packet_count = 0;
}
}
case AFHDS2A_RX_BIND3:
debugln("bind p=%d", phase+1);
// transmit response packet
packet[0] = 0xBC;
memcpy(&packet[1], rx_id, 4);
memcpy(&packet[5], rx_tx_addr, 4);
packet[9] = 0x01;
//packet[9] = 0x01;
packet[10] = 0x00;
memset(&packet[11], 0xFF, 26);
A7105_SetTxRxMode(TX_EN);
rx_disable_lna = !IS_POWER_FLAG_on;
A7105_WriteData(AFHDS2A_RX_RXPACKET_SIZE, packet_count++ & 1 ? 0x0D : 0x8C);
if(phase == AFHDS2A_RX_BIND3 && packet_count > 20)
{
debugln("done");
BIND_DONE;
return initAFHDS2A_Rx(); // Restart protocol
}
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
while ((uint32_t)(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);
case AFHDS2A_RX_BIND3 | AFHDS2A_RX_WAIT_WRITE:
phase &= ~AFHDS2A_RX_WAIT_WRITE;
return 10000;

View File

@@ -20,6 +20,10 @@
#define AFHDS2A_RXPACKET_SIZE 37
#define AFHDS2A_NUMFREQ 16
#if not defined TELEMETRY
uint8_t RX_LQI=0;
#endif
enum{
AFHDS2A_PACKET_STICKS,
AFHDS2A_PACKET_SETTINGS,
@@ -65,7 +69,6 @@ static void AFHDS2A_calc_channels()
}
}
#if defined(AFHDS2A_FW_TELEMETRY) || defined(AFHDS2A_HUB_TELEMETRY)
// telemetry sensors ID
enum{
AFHDS2A_SENSOR_RX_VOLTAGE = 0x00,
@@ -76,10 +79,9 @@ enum{
AFHDS2A_SENSOR_A3_VOLTAGE = 0x03,
};
#if defined(AFHDS2A_FW_TELEMETRY) || defined(AFHDS2A_HUB_TELEMETRY)
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;
@@ -183,37 +185,64 @@ static void AFHDS2A_build_packet(uint8_t type)
{
case AFHDS2A_PACKET_STICKS:
packet[0] = 0x58;
for(uint8_t ch=0; ch<14; ch++)
//16 channels + RX_LQI on channel 17
for(uint8_t ch=0; ch<num_ch; ch++)
{
uint16_t channelMicros = convert_channel_ppm(CH_AETR[ch]);
packet[9 + ch*2] = channelMicros&0xFF;
packet[10 + ch*2] = (channelMicros>>8)&0xFF;
if(ch == 16 // CH17=RX_LQI
#ifdef AFHDS2A_LQI_CH
|| ch == (AFHDS2A_LQI_CH-1) // override channel with LQI
#endif
)
val = 2000 - 10*RX_LQI;
else
val = convert_channel_ppm(CH_AETR[ch]);
if(ch<14)
{
packet[9 + ch*2] = val;
packet[10 + ch*2] = (val>>8)&0x0F;
}
else
{
packet[10 + (ch-14)*6] |= (val)<<4;
packet[12 + (ch-14)*6] |= (val)&0xF0;
packet[14 + (ch-14)*6] |= (val>>4)&0xF0;
}
}
#ifdef AFHDS2A_LQI_CH
// override channel with LQI
val = 2000 - 10*RX_LQI;
packet[9+((AFHDS2A_LQI_CH-1)*2)] = val & 0xff;
packet[10+((AFHDS2A_LQI_CH-1)*2)] = (val >> 8) & 0xff;
#endif
break;
case AFHDS2A_PACKET_FAILSAFE:
packet[0] = 0x56;
for(uint8_t ch=0; ch<14; ch++)
for(uint8_t ch=0; ch<num_ch; ch++)
{
#ifdef FAILSAFE_ENABLE
uint16_t failsafeMicros = Failsafe_data[CH_AETR[ch]];
if( failsafeMicros!=FAILSAFE_CHANNEL_HOLD && failsafeMicros!=FAILSAFE_CHANNEL_NOPULSES)
if(ch<16)
val = Failsafe_data[CH_AETR[ch]];
else
val = FAILSAFE_CHANNEL_NOPULSES;
if(val!=FAILSAFE_CHANNEL_HOLD && val!=FAILSAFE_CHANNEL_NOPULSES)
{ // Failsafe values
failsafeMicros = (((failsafeMicros<<2)+failsafeMicros)>>3)+860;
packet[9 + ch*2] = failsafeMicros & 0xff;
packet[10+ ch*2] = ( failsafeMicros >> 8) & 0xff;
val = (((val<<2)+val)>>3)+860;
if(ch<14)
{
packet[9 + ch*2] = val;
packet[10 + ch*2] = (val>>8)&0x0F;
}
else
{
packet[10 + (ch-14)*6] &= 0x0F;
packet[10 + (ch-14)*6] |= (val)<<4;
packet[12 + (ch-14)*6] &= 0x0F;
packet[12 + (ch-14)*6] |= (val)&0xF0;
packet[14 + (ch-14)*6] &= 0x0F;
packet[14 + (ch-14)*6] |= (val>>4)&0xF0;
}
}
else
#endif
{ // no values
packet[9 + ch*2] = 0xff;
packet[10+ ch*2] = 0xff;
}
if(ch<14)
{ // no values
packet[9 + ch*2] = 0xff;
packet[10+ ch*2] = 0xff;
}
}
break;
case AFHDS2A_PACKET_SETTINGS:
@@ -224,17 +253,14 @@ static void AFHDS2A_build_packet(uint8_t type)
if(val<50 || val>400) val=50; // default is 50Hz
packet[11]= val;
packet[12]= val >> 8;
if(sub_protocol == PPM_IBUS || sub_protocol == PPM_SBUS)
packet[13] = 0x01; // PPM output enabled
else
packet[13] = 0x00;
packet[13] = sub_protocol & 0x01; // 1 -> PPM output enabled
packet[14]= 0x00;
for(uint8_t i=15; i<37; i++)
packet[i] = 0xff;
packet[18] = 0x05; // ?
packet[19] = 0xdc; // ?
packet[20] = 0x05; // ?
if(sub_protocol == PWM_SBUS || sub_protocol == PPM_SBUS)
if(sub_protocol&2)
packet[21] = 0xdd; // SBUS output enabled
else
packet[21] = 0xde; // IBUS
@@ -244,11 +270,18 @@ static void AFHDS2A_build_packet(uint8_t type)
}
#define AFHDS2A_WAIT_WRITE 0x80
#ifdef STM32_BOARD
#define AFHDS2A_WRITE_TIME 1550
#else
#define AFHDS2A_WRITE_TIME 1700
#endif
uint16_t ReadAFHDS2A()
{
static uint8_t packet_type;
static uint16_t packet_counter;
uint8_t data_rx;
uint8_t data_rx=0;
uint16_t start;
#ifndef FORCE_AFHDS2A_TUNING
A7105_AdjustLOBaseFreq(1);
@@ -265,7 +298,7 @@ uint16_t ReadAFHDS2A()
A7105_ReadData(AFHDS2A_RXPACKET_SIZE);
if(packet[0] == 0xbc && packet[9] == 0x01)
{
uint8_t addr;
uint16_t addr;
if(RX_num<16)
addr=AFHDS2A_EEPROM_OFFSET+RX_num*4;
else
@@ -293,7 +326,7 @@ uint16_t ReadAFHDS2A()
case AFHDS2A_BIND3|AFHDS2A_WAIT_WRITE:
//Wait for TX completion
start=micros();
while ((uint16_t)micros()-start < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
while ((uint16_t)((uint16_t)micros()-start) < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
break;
A7105_SetPower();
@@ -325,10 +358,8 @@ uint16_t ReadAFHDS2A()
telemetry_set_input_sync(3850);
#endif
AFHDS2A_build_packet(packet_type);
if((A7105_ReadReg(A7105_00_MODE) & 0x01)) // Check if something has been received...
data_rx=0;
else
data_rx=1; // Yes
if((A7105_ReadReg(A7105_00_MODE) & 0x01)==0) // Check if something has been received...
data_rx=1; // Yes
A7105_WriteData(AFHDS2A_TXPACKET_SIZE, hopping_frequency[hopping_frequency_no++]);
if(hopping_frequency_no >= AFHDS2A_NUMFREQ)
hopping_frequency_no = 0;
@@ -344,32 +375,27 @@ uint16_t ReadAFHDS2A()
}
else
#endif
packet_type = AFHDS2A_PACKET_STICKS; // todo : check for settings changes
packet_type = AFHDS2A_PACKET_STICKS; // todo : check for settings changes
}
if(!(A7105_ReadReg(A7105_00_MODE) & (1<<5 | 1<<6)) && data_rx==1)
{ // RX+FECF+CRCF Ok
A7105_ReadData(AFHDS2A_RXPACKET_SIZE);
if(packet[0] == 0xAA && packet[9] == 0xFC)
packet_type=AFHDS2A_PACKET_SETTINGS; // RX is asking for settings
packet_type=AFHDS2A_PACKET_SETTINGS; // RX is asking for settings
else
if(packet[0] == 0xAA || packet[0] == 0xAC)
{
if((packet[0] == 0xAA && packet[9]!=0xFD) || packet[0] == 0xAC)
{// Normal telemetry packet, ignore packets which contain the RX configuration: AA FD FF 32 00 01 00 FF FF FF 05 DC 05 DE FA FF FF FF FF FF FF FF FF FF FF FF FF FF FF
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;
}
}
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
@@ -378,18 +404,18 @@ uint16_t ReadAFHDS2A()
}
packet_counter++;
phase |= AFHDS2A_WAIT_WRITE;
return 1700;
return AFHDS2A_WRITE_TIME;
case AFHDS2A_DATA|AFHDS2A_WAIT_WRITE:
//Wait for TX completion
start=micros();
while ((uint16_t)micros()-start < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
while ((uint16_t)((uint16_t)micros()-start) < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
break;
A7105_SetPower();
A7105_SetTxRxMode(RX_EN);
A7105_Strobe(A7105_RX);
phase &= ~AFHDS2A_WAIT_WRITE;
return 2150;
return 3850-AFHDS2A_WRITE_TIME;
}
return 3850; // never reached, please the compiler
}
@@ -407,7 +433,7 @@ 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 addr;
uint16_t addr;
if(RX_num<16)
addr=AFHDS2A_EEPROM_OFFSET+RX_num*4;
else
@@ -416,6 +442,10 @@ uint16_t initAFHDS2A()
rx_id[i]=eeprom_read_byte((EE_ADDR)(addr+i));
}
hopping_frequency_no = 0;
if(sub_protocol&0x04)
num_ch=17;
else
num_ch=14;
return 50000;
}
#endif

View File

@@ -115,7 +115,7 @@ void delayMilliseconds(unsigned long ms)
uint16_t lms = ms ;
while (lms > 0) {
if (((uint16_t)micros() - start) >= 1000) {
if ((uint16_t)((uint16_t)micros() - start) >= 1000) {
lms--;
start += 1000;
}

View File

@@ -126,11 +126,10 @@ 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(IS_BIND_DONE) return initBayang_Rx(); // Abort 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()) {

View File

@@ -67,12 +67,16 @@ static void __attribute__((unused)) BAYANG_send_packet()
else
#endif
packet[0]= 0xA4;
if(sub_protocol==QX100)
packet[0] = 0x53;
for(i=0;i<5;i++)
packet[i+1]=rx_tx_addr[i];
for(i=0;i<4;i++)
packet[i+6]=hopping_frequency[i];
switch (sub_protocol)
{
case QX100:
case X16_AH:
packet[10] = 0x00;
packet[11] = 0x00;
@@ -139,19 +143,19 @@ static void __attribute__((unused)) BAYANG_send_packet()
if(CH13_SW)
packet[3] |= BAYANG_FLAG_EMG_STOP;
//Aileron
val = convert_channel_10b(AILERON);
val = convert_channel_10b(AILERON, false);
packet[4] = (val>>8) + (dyntrim ? ((val>>2) & 0xFC) : 0x7C);
packet[5] = val & 0xFF;
//Elevator
val = convert_channel_10b(ELEVATOR);
val = convert_channel_10b(ELEVATOR, false);
packet[6] = (val>>8) + (dyntrim ? ((val>>2) & 0xFC) : 0x7C);
packet[7] = val & 0xFF;
//Throttle
val = convert_channel_10b(THROTTLE);
val = convert_channel_10b(THROTTLE, false);
packet[8] = (val>>8) + 0x7C;
packet[9] = val & 0xFF;
//Rudder
val = convert_channel_10b(RUDDER);
val = convert_channel_10b(RUDDER, false);
packet[10] = (val>>8) + (dyntrim ? ((val>>2) & 0xFC) : 0x7C);
packet[11] = val & 0xFF;
}
@@ -161,6 +165,7 @@ static void __attribute__((unused)) BAYANG_send_packet()
packet[12] = rx_tx_addr[2]; // txid[2]
packet[13] = 0x34;
break;
case QX100:
case X16_AH:
packet[12] = 0;
packet[13] = 0;
@@ -216,9 +221,9 @@ static void __attribute__((unused)) BAYANG_check_rx(void)
if (packet[0] == 0x85 && packet[14] == check)
{
// uncompensated battery volts*100/2
v_lipo1 = (packet[3]<<7) + (packet[4]>>2);
v_lipo1 = (packet[3]<<7) + (packet[4]>>1);
// compensated battery volts*100/2
v_lipo2 = (packet[5]<<7) + (packet[6]>>2);
v_lipo2 = (packet[5]<<7) + (packet[6]>>1);
// reception in packets / sec
RX_LQI = packet[7];
RX_RSSI = RX_LQI;

View File

@@ -48,6 +48,7 @@ Bit(s) Bitmask Option Comment
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
14-16 0xE000 Module sub-type Reads as a three-bit value indicating a number from 0-7 which maps to a module sub-type (right-shift 13 bits to read)
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.
@@ -60,9 +61,15 @@ 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
AVR (Atmega328p) 0 00
STM32 (F103) 1 01
OrangeRX (Xmega) 2 10
Module sub-type is currently used for STM32F103 only and is mapped as follows:
Module Type Sub Type Decimal Value Binary Value
STM32 (F103) STM32F103CB 0 000
STM32 (F103) STM32F103C8 1 001
STM32 (F103) T18 5in1 2 010
Channel orders are mapped to the following decimal / binary values:
Channel Order Decimal Value Binary Value
@@ -109,6 +116,17 @@ RTEA 23 10111
bool firmwareFlag_DEBUG_SERIAL = true;
#endif
// STM32 Module sub-type flags
#if defined (MCU_STM32F103CB)
bool firmwareFlag_MCU_STM32F103CB = true;
#endif
#if defined (MCU_STM32F103C8)
bool firmwareFlag_MCU_STM32F103C8 = true;
#endif
#if defined (MULTI_5IN1_INTERNAL)
bool firmwareFlag_MULTI_5IN1_INTERNAL = true;
#endif
// Channel order flags
#if defined (AETR)
bool firmwareFlag_ChannelOrder_AETR = true;

View File

@@ -340,7 +340,7 @@ uint16_t ReadBUGS(void)
case BUGS_BIND_2:
//Wait for TX completion
start=micros();
while ((uint16_t)micros()-start < 500) // Wait max 500µs, using serial+telemetry exit in about 60µs
while ((uint16_t)((uint16_t)micros()-start) < 500) // Wait max 500µs, using serial+telemetry exit in about 60µs
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
break;
A7105_SetTxRxMode(RX_EN);
@@ -399,7 +399,7 @@ uint16_t ReadBUGS(void)
case BUGS_DATA_2:
//Wait for TX completion
start=micros();
while ((uint16_t)micros()-start < 500) // Wait max 500µs, using serial+telemetry exit in about 60µs
while ((uint16_t)((uint16_t)micros()-start) < 500) // Wait max 500µs, using serial+telemetry exit in about 60µs
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
break;
A7105_SetTxRxMode(RX_EN);

View File

@@ -163,4 +163,174 @@ void CC2500_SetPower()
prev_power=power;
}
}
void __attribute__((unused)) CC2500_SetFreqOffset()
{
if(prev_option != option)
{
prev_option = option;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
}
}
void __attribute__((unused)) CC2500_250K_Init()
{
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();
}
void __attribute__((unused)) CC2500_250K_HoppingCalib(uint8_t num_freq)
{
for (uint8_t i = 0; i < num_freq; i++)
{
CC2500_Strobe(CC2500_SIDLE);
// spacing is 333.25 kHz, must multiply channel by 3
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[i]*3);
// calibrate
CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);
calData[i]=CC2500_ReadReg(CC2500_25_FSCAL1);
}
}
void __attribute__((unused)) CC2500_250K_Hopping(uint8_t index)
{
// spacing is 333.25 kHz, must multiply channel by 3
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[index] * 3);
// set PLL calibration
CC2500_WriteReg(CC2500_25_FSCAL1, calData[index]);
}
void __attribute__((unused)) CC2500_250K_RFChannel(uint8_t number)
{
CC2500_Strobe(CC2500_SIDLE);
// spacing is 333.25 kHz, must multiply channel by 3
CC2500_WriteReg(CC2500_0A_CHANNR, number*3);
// calibrate
CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);
}
//NRF emulation layer with CRC16 enabled
uint8_t cc2500_nrf_tx_addr[5], cc2500_nrf_addr_len;
void __attribute__((unused)) CC2500_250K_NRF_SetTXAddr(uint8_t* addr, uint8_t len)
{
cc2500_nrf_addr_len = len;
memcpy(cc2500_nrf_tx_addr, addr, len);
}
void __attribute__((unused)) CC2500_250K_NRF_WritePayload(uint8_t* msg, uint8_t len)
{
#if defined(ESKY150V2_CC2500_INO)
uint8_t buf[158];
#else
uint8_t buf[35];
#endif
uint8_t last = 0;
uint8_t i;
//nrf preamble
if(cc2500_nrf_tx_addr[cc2500_nrf_addr_len - 1] & 0x80)
buf[0]=0xAA;
else
buf[0]=0x55;
last++;
// address
for (i = 0; i < cc2500_nrf_addr_len; ++i)
buf[last++] = cc2500_nrf_tx_addr[cc2500_nrf_addr_len - i - 1];
// payload
for (i = 0; i < len; ++i)
buf[last++] = msg[i];
// crc
crc = 0xffff;
for (uint8_t i = 1; i < last; ++i)
crc16_update( buf[i], 8);
buf[last++] = crc >> 8;
buf[last++] = crc & 0xff;
buf[last++] = 0;
//for(uint8_t i=0;i<last;i++)
// debug("%02X ",buf[i]);
//debugln("");
// stop TX/RX
CC2500_Strobe(CC2500_SIDLE);
// flush tx FIFO
CC2500_Strobe(CC2500_SFTX);
// packet length
CC2500_WriteReg(CC2500_3F_TXFIFO, last);
// transmit nrf packet
uint8_t *buff=buf;
uint8_t status;
if(last>63)
{
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, 63);
CC2500_Strobe(CC2500_STX);
last-=63;
buff+=63;
while(last)
{//Loop until all the data is sent
do
{// Wait for the FIFO to become available
status=CC2500_ReadReg(CC2500_3A_TXBYTES | CC2500_READ_BURST);
}
while((status&0x7F)>31 && (status&0x80)==0);
if(last>31)
{//Send 31 bytes
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, 31);
last-=31;
buff+=31;
}
else
{//Send last bytes
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, last);
last=0;
}
}
}
else
{//Send packet
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, last);
CC2500_Strobe(CC2500_STX);
}
}
#endif

View File

@@ -19,17 +19,17 @@
#include "iface_nrf24l01.h"
#define CX10_BIND_COUNT 4360 // 6 seconds
#define CX10_BIND_COUNT 4360 // 6 seconds
#define CX10_PACKET_SIZE 15
#define CX10A_PACKET_SIZE 19 // CX10 blue board packets have 19-byte payload
#define CX10A_PACKET_SIZE 19 // CX10 blue board packets have 19-byte payload
#define Q2X2_PACKET_SIZE 21
#define CX10_PACKET_PERIOD 1316 // Timeout for callback in uSec
#define CX10_PACKET_PERIOD 1316 // Timeout for callback in uSec
#define CX10A_PACKET_PERIOD 6000
#define CX10_INITIAL_WAIT 500
// flags
#define CX10_FLAG_FLIP 0x10 // goes to rudder channel
#define CX10_FLAG_FLIP 0x10 // goes to rudder channel
#define CX10_FLAG_MODE_MASK 0x03
#define CX10_FLAG_HEADLESS 0x04
// flags2
@@ -181,7 +181,7 @@ static void __attribute__((unused)) CX10_init()
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_11_RX_PW_P0, packet_length); // rx pipe 0 (used only for blue board)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, CX10_RF_BIND_CHANNEL);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, CX10_RF_BIND_CHANNEL);
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
}
@@ -220,7 +220,8 @@ uint16_t CX10_callback()
NRF24L01_FlushTx();
NRF24L01_SetTxRxMode(TX_EN);
CX10_Write_Packet(1);
delayMicroseconds(400);
// wait for packet to be sent
while( (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)) == 0); //delayMicroseconds(400);
// switch to RX mode
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();

View File

@@ -98,14 +98,14 @@ void CYRF_SetTxRxMode(uint8_t mode)
{
if(mode==TXRX_OFF)
{
if(protocol!=PROTO_WFLY)
if( protocol!=PROTO_WFLY && protocol!=PROTO_MLINK )
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24); // 4=IDLE, 8=TX, C=RX
CYRF_WriteRegister(CYRF_0E_GPIO_CTRL,0x00); // XOUT=0 PACTL=0
}
else
{
//Set the post tx/rx state
if(protocol!=PROTO_WFLY)
if( protocol!=PROTO_WFLY && protocol!=PROTO_MLINK )
CYRF_WriteRegister(CYRF_0F_XACT_CFG, mode == TX_EN ? 0x28 : 0x2C); // 4=IDLE, 8=TX, C=RX
if(mode == TX_EN)
#ifdef ORANGE_TX_BLUE
@@ -168,10 +168,10 @@ void CYRF_SetPower(uint8_t val)
/*
*
*/
void CYRF_ConfigCRCSeed(uint16_t crc)
void CYRF_ConfigCRCSeed(uint16_t crc_seed)
{
CYRF_WriteRegister(CYRF_15_CRC_SEED_LSB,crc & 0xff);
CYRF_WriteRegister(CYRF_16_CRC_SEED_MSB,crc >> 8);
CYRF_WriteRegister(CYRF_15_CRC_SEED_LSB,crc_seed & 0xff);
CYRF_WriteRegister(CYRF_16_CRC_SEED_MSB,crc_seed >> 8);
}
/*
* these are the recommended sop codes from Cyrpress
@@ -321,4 +321,69 @@ static void __attribute__((unused)) CYRF_PROGMEM_ConfigSOPCode(const uint8_t *da
code[i]=pgm_read_byte_near(&data[i]);
CYRF_ConfigSOPCode(code);
}
//CYRF GFSK 1Mb functions
const uint8_t PROGMEM CYRF_GFSK1M_init_vals[][2] = {
{CYRF_02_TX_CTRL, 0x00}, // transmit err & complete interrupts disabled
{CYRF_05_RX_CTRL, 0x00}, // receive err & complete interrupts disabled
{CYRF_28_CLK_EN, 0x02}, // Force Receive Clock Enable, MUST be set
{CYRF_32_AUTO_CAL_TIME, 0x3c}, // must be set to 3C
{CYRF_35_AUTOCAL_OFFSET, 0x14}, // must be set to 14
{CYRF_06_RX_CFG, 0x48}, // LNA manual control, Rx Fast Turn Mode Enable
{CYRF_1B_TX_OFFSET_LSB, 0x00}, // Tx frequency offset LSB
{CYRF_1C_TX_OFFSET_MSB, 0x00}, // Tx frequency offset MSB
{CYRF_0F_XACT_CFG, 0x24}, // Force End State, transaction end state = idle
{CYRF_03_TX_CFG, 0x00}, // GFSK mode
{CYRF_12_DATA64_THOLD, 0x0a}, // 64 Chip Data PN Code Correlator Threshold = 10
{CYRF_0F_XACT_CFG, 0x04}, // Transaction End State = idle
{CYRF_39_ANALOG_CTRL, 0x01}, // synth setting time for all channels is the same as for slow channels
{CYRF_0F_XACT_CFG, 0x24}, //Force IDLE
{CYRF_29_RX_ABORT, 0x00}, //Clear RX abort
{CYRF_12_DATA64_THOLD, 0x0a}, //set pn correlation threshold
{CYRF_10_FRAMING_CFG, 0x4a}, //set sop len and threshold
{CYRF_29_RX_ABORT, 0x0f}, //Clear RX abort?
{CYRF_03_TX_CFG, 0x00}, // GFSK mode
{CYRF_10_FRAMING_CFG, 0x4a}, // 0b11000000 //set sop len and threshold
{CYRF_1F_TX_OVERRIDE, 0x04}, //disable tx CRC
{CYRF_1E_RX_OVERRIDE, 0x14}, //disable rx crc
{CYRF_14_EOP_CTRL, 0x00}, //set EOP sync == 0
};
static void __attribute__((unused)) CYRF_GFSK1M_Init(uint8_t payload_length, uint8_t preamble_len)
{
for(uint8_t i = 0; i < sizeof(CYRF_GFSK1M_init_vals) / 2; i++)
CYRF_WriteRegister(pgm_read_byte_near(&CYRF_GFSK1M_init_vals[i][0]), pgm_read_byte_near(&CYRF_GFSK1M_init_vals[i][1]));
CYRF_WriteRegister(CYRF_01_TX_LENGTH, payload_length);
CYRF_WritePreamble(0xAAAA00 | preamble_len);
CYRF_SetPower(0x00);
CYRF_SetTxRxMode(TX_EN);
}
static void __attribute__((unused)) CYRF_GFSK1M_SendPayload(uint8_t *buffer, uint8_t len)
{
uint8_t send=len>16 ? 16 : len;
CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x40);
CYRF_WriteRegisterMulti(CYRF_20_TX_BUFFER, buffer, send); // Fill the buffer with 16 bytes max
CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x80); // Start send
buffer += send;
len -= send;
while(len>8)
{
while((CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS)&0x10) == 0); // Wait that half of the buffer is empty
CYRF_WriteRegisterMulti(CYRF_20_TX_BUFFER, buffer, 8); // Add 8 bytes to the buffer
buffer+=8;
len-=8;
}
if(len)
{
while((CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS)&0x10) == 0); // Wait that half of the buffer is empty
CYRF_WriteRegisterMulti(CYRF_20_TX_BUFFER, buffer, len); // Add the remaining bytes to the buffer
}
}
#define CYRF_GFSK1M_SetPower() CYRF_SetPower(0x00)
#endif

View File

@@ -32,9 +32,15 @@ uint16_t convert_channel_ppm(uint8_t num)
}
// Channel value 100% is converted to 10bit values 0<->1023
uint16_t convert_channel_10b(uint8_t num)
uint16_t convert_channel_10b(uint8_t num, bool failsafe)
{
uint16_t val=Channel_data[num];
uint16_t val;
#ifdef FAILSAFE_ENABLE
if(failsafe)
val=Failsafe_data[num]; // 0<->2047
else
#endif
val=Channel_data[num];
val=((val<<2)+val)>>3;
if(val<=128) return 0;
if(val>=1152) return 1023;
@@ -91,9 +97,15 @@ int16_t convert_channel_16b_limit(uint8_t num,int16_t min,int16_t max)
}
// 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)
int16_t convert_channel_16b_nolimit(uint8_t num, int16_t min, int16_t max, bool failsafe)
{
int32_t val=Channel_data[num]; // 0<->2047
int32_t val;
#ifdef FAILSAFE_ENABLE
if(failsafe)
val=Failsafe_data[num]; // 0<->2047
else
#endif
val=Channel_data[num]; // 0<->2047
val=(val-CHANNEL_MIN_100)*(max-min)/(CHANNEL_MAX_100-CHANNEL_MIN_100)+min;
return (uint16_t)val;
}
@@ -151,14 +163,14 @@ static uint16_t __attribute__((unused)) FrSkyX_scaleForPXX( uint8_t i, uint8_t
}
#ifdef FAILSAFE_ENABLE
static uint16_t __attribute__((unused)) FrSkyX_scaleForPXX_FS( uint8_t i )
static uint16_t __attribute__((unused)) FrSkyX_scaleForPXX_FS( uint8_t i, uint8_t num_chan=8)
{ //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
if(i>=num_chan) chan_val|=2048; // upper channels offset
return chan_val;
}
#endif

View File

@@ -18,6 +18,7 @@ Multiprotocol is distributed in the hope that it will be useful,
#include "iface_cyrf6936.h"
//#define DSM_DEBUG_RF
//#define DSM_DEBUG_CH
uint8_t DSM_rx_type;
@@ -85,6 +86,11 @@ static uint8_t __attribute__((unused)) DSM_Rx_check_packet()
packet[0] ^= 0xff;
packet[1] ^= 0xff;
}
#ifdef DSM_DEBUG_CH
for(uint8_t i=0;i<len;i++)
debug("%02X ",packet[i]);
debugln("");
#endif
if(packet[0] == cyrfmfg_id[2] && packet[1] == cyrfmfg_id[3])
return 0x02; // Packet ok
}
@@ -111,7 +117,10 @@ static void __attribute__((unused)) DSM_Rx_build_telemetry_packet()
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
idx=(value&0x7FFF)>>nbr_bits; // retrieve channel index
#ifdef DSM_DEBUG_CH
debugln("i=%d,v=%d,u=%X",idx,value&0x7FF,value&0x8000);
#endif
if(idx<13)
{
if(nbr_bits==10) value <<= 1; // switch to 11 bits
@@ -200,21 +209,24 @@ 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(IS_BIND_DONE) // Abort bind
{
phase = DSM_RX_DATA_PREP;
break;
}
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)
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
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)
@@ -236,11 +248,11 @@ uint16_t DSM_Rx_callback()
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 => 22ms 1024 DSM2 1 packet => number of channels is <8
0x02 => 22ms 1024 DSM2 2 packets => either a number of channel >7
0x12 => 11ms 2048 DSM2 2 packets => can be any number of channels
0xA2 => 22ms 2048 DSMX 1 packet => number of channels is <8
0xB2 => 11ms 2048 DSMX => can be any number of channels
(0x01 or 0xA2) and num_ch < 7 => 22ms else 11ms
&0x80 => false=DSM2, true=DSMX
&0xF0 => false=1024, true=2048 */
@@ -275,7 +287,7 @@ uint16_t DSM_Rx_callback()
}
DSM_abort_channel_rx(0); // Abort RX operation and receive
if(read_retry==0)
read_retry=4;
read_retry=8;
}
else
if(rx_status & 0x02) // RX error

View File

@@ -17,6 +17,10 @@
#include "iface_cyrf6936.h"
//#define DSM_DEBUG_FWD_PGM
//#define DSM_GR300
#define DSM_BIND_CHANNEL 0x0d //13 This can be any odd channel
//During binding we will send BIND_COUNT/2 packets
@@ -43,7 +47,8 @@ enum {
//
uint8_t ch_map[14];
const uint8_t PROGMEM DSM_ch_map_progmem[][14] = {
//22+11ms for 4..7 channels
//22+11ms for 3..7 channels
{1, 0, 2, 0xff, 0xff, 0xff, 0xff, 1, 0, 2, 0xff, 0xff, 0xff, 0xff}, //3ch - Guess
{1, 0, 2, 3, 0xff, 0xff, 0xff, 1, 0, 2, 3, 0xff, 0xff, 0xff}, //4ch - Guess
{1, 0, 2, 3, 4, 0xff, 0xff, 1, 0, 2, 3, 4, 0xff, 0xff}, //5ch - Guess
{1, 5, 2, 3, 0, 4, 0xff, 1, 5, 2, 3, 0, 4, 0xff}, //6ch - HP6DSM
@@ -53,11 +58,12 @@ const uint8_t PROGMEM DSM_ch_map_progmem[][14] = {
{1, 5, 2, 3, 6, 0xff, 0xff, 4, 0, 7, 8, 0xff, 0xff, 0xff}, //9ch - Guess
{1, 5, 2, 3, 6, 0xff, 0xff, 4, 0, 7, 8, 9, 0xff, 0xff}, //10ch - Guess
{1, 5, 2, 3, 6, 10, 0xff, 4, 0, 7, 8, 9, 0xff, 0xff}, //11ch - Guess
{1, 5, 2, 4, 6, 10, 0xff, 0, 7, 3, 8, 9 , 11 , 0xff}, //12ch - DX18
//11ms for 8..12 channels
{1, 5, 2, 4, 6, 10, 0xff, 0, 7, 3, 8, 9 , 11 , 0xff}, //12ch - DX18/DX8G2
//11ms for 8..11 channels
{1, 5, 2, 3, 6, 7, 0xff, 1, 5, 2, 4, 0, 0xff, 0xff}, //8ch - DX7
{1, 5, 2, 3, 6, 7, 0xff, 1, 5, 2, 4, 0, 8, 0xff}, //9ch - Guess
{1, 5, 2, 3, 4, 8, 9, 1, 5, 2, 3, 0, 7, 6 }, //10ch - DX18
{1, 5, 2, 3, 4, 8, 9, 1, 5, 2, 3, 0, 7, 6 }, //10ch - DX18
{1, 5, 2, 3, 4, 8, 9, 1, 10, 2, 3, 0, 7, 6 }, //11ch - Guess
};
static void __attribute__((unused)) DSM_build_bind_packet()
@@ -76,23 +82,26 @@ static void __attribute__((unused)) DSM_build_bind_packet()
sum += packet[i];
packet[8] = sum >> 8;
packet[9] = sum & 0xff;
packet[10] = 0x01; //???
packet[11] = num_ch;
packet[10] = 0x01; // ???
if(sub_protocol==DSM_AUTO)
packet[11] = 12;
else
packet[11] = num_ch;
if (sub_protocol==DSM2_22)
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]=num_ch<8?0x01:0x02; // DSM2/1024 1 or 2 packets depending on the number of channels
else if(sub_protocol==DSM2_11)
packet[12]=0x12; // DSM2/2048 2 packets
if(sub_protocol==DSMX_22)
else if(sub_protocol==DSMX_22)
#if defined DSM_TELEMETRY
packet[12] = 0xb2; // DSMX/2048 2 packets
#else
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
else // DSMX_11 && DSM_AUTO
packet[12]=0xb2; // DSMX/2048 2 packets
packet[13] = 0x00; //???
packet[13] = 0x00; //???
for(i = 8; i < 14; i++)
sum += packet[i];
packet[14] = sum >> 8;
@@ -112,17 +121,15 @@ static void __attribute__((unused)) DSM_initialize_bind_phase()
static void __attribute__((unused)) DSM_update_channels()
{
prev_option=option;
if(sub_protocol==DSM_AUTO)
num_ch=12; // Force 12 channels in mode Auto
else
num_ch=option & 0x7F; // Remove the Max Throw flag
if(num_ch<4 || num_ch>12)
num_ch=option & 0x0F; // Remove flags 0x80=max_throw, 0x40=11ms
if(num_ch<3 || 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=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
uint8_t idx=num_ch-3;
if((option & 0x40) && num_ch>7 && num_ch<12)
idx+=5; // In 11ms mode change index only for channels 8..11
for(uint8_t i=0;i<14;i++)
ch_map[i]=pgm_read_byte_near(&DSM_ch_map_progmem[idx][i]);
}
@@ -135,24 +142,27 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
DSM_update_channels();
if (sub_protocol==DSMX_11 || sub_protocol==DSMX_22 )
{
{//DSMX
packet[0] = cyrfmfg_id[2];
packet[1] = cyrfmfg_id[3];
}
else
{
{//DSM2
packet[0] = (0xff ^ cyrfmfg_id[2]);
packet[1] = (0xff ^ cyrfmfg_id[3]);
if(sub_protocol==DSM2_22)
bits=10; // Only DSM2_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];
#endif
for (uint8_t i = 0; i < 7; i++)
{
uint8_t idx = ch_map[(upper?7:0) + i];//1,5,2,3,0,4
uint16_t value = 0xffff;;
uint8_t idx = ch_map[(upper?7:0) + i]; // 1,5,2,3,0,4
uint16_t value = 0xffff;
if((option&0x40) == 0 && num_ch < 8 && upper)
idx=0xff; // in 22ms do not transmit upper channels if <8, is it the right method???
if (idx != 0xff)
{
/* Spektrum own remotes transmit normal values during bind and actually use this (e.g. Nano CP X) to
@@ -160,7 +170,7 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
#ifdef DSM_THROTTLE_KILL_CH
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
if(kill_ch<CHANNEL_MIN_100) // restrict val to 0...400
kill_ch=0;
else
kill_ch-=CHANNEL_MIN_100;
@@ -174,7 +184,7 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
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
value=convert_channel_16b_nolimit(CH_TAER[idx],0x156,0x6AA,false); // -100%..+100% => 1100..1900us and -125%..+125% => 1000..2000us based on a DX8 G2 dump
#endif
if(bits==10) value>>=1;
value |= (upper && i==0 ? 0x8000 : 0) | (idx << bits);
@@ -182,11 +192,28 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
packet[i*2+2] = (value >> 8) & 0xff;
packet[i*2+3] = (value >> 0) & 0xff;
}
#ifdef DSM_FWD_PGM
if(upper==0 && DSM_SerialRX && (DSM_SerialRX_val[0]&0xF8)==0x70 )
{ // Send forward programming data if available
for(uint8_t i=0; i<(DSM_SerialRX_val[0]&0x07);i++)
{
packet[i*2+4]=0x70+i;
packet[i*2+5]=DSM_SerialRX_val[i+1];
}
DSM_SerialRX=false;
#ifdef DSM_DEBUG_FWD_PGM
debug("FWD=");
for(uint8_t i=4; i<16;i++)
debug(" %02X",packet[i]);
debugln("");
#endif
}
#endif
}
static uint8_t __attribute__((unused)) DSM_Check_RX_packet()
{
uint8_t result=1; // assume good packet
uint8_t result=1; // assume good packet
uint16_t sum = 384 - 0x10;
for(uint8_t i = 1; i < 9; i++)
@@ -194,7 +221,7 @@ static uint8_t __attribute__((unused)) DSM_Check_RX_packet()
sum += packet_in[i];
if(i<5)
if(packet_in[i] != (0xff ^ cyrfmfg_id[i-1]))
result=0; // bad packet
result=0; // bad packet
}
if( packet_in[9] != (sum>>8) && packet_in[10] != (uint8_t)sum )
result=0;
@@ -215,15 +242,20 @@ uint16_t ReadDsm()
uint8_t len;
#endif
uint8_t start;
#ifdef DSM_GR300
uint16_t timing=5000+(convert_channel_8b(CH13)*100);
debugln("T=%u",timing);
#endif
switch(phase)
{
case DSM_BIND_WRITE:
if(bind_counter--==0)
#if defined DSM_TELEMETRY
phase=DSM_BIND_CHECK; //Check RX answer
phase=DSM_BIND_CHECK; //Check RX answer
#else
phase=DSM_CHANSEL; //Switch to normal mode
phase=DSM_CHANSEL; //Switch to normal mode
#endif
CYRF_WriteDataPacket(packet);
return 10000;
@@ -231,25 +263,32 @@ uint16_t ReadDsm()
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", 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
phase++; // change from BIND_CHECK to BIND_READ
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
phase++; // change from BIND_CHECK to BIND_READ
return 2000;
case DSM_BIND_READ:
//Read data from RX
rx_phase = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((rx_phase & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
if((rx_phase & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
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
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80);// Need to set RXOW before data read
if(CYRF_ReadRegister(CYRF_09_RX_COUNT)==10) // Len
{
CYRF_ReadDataPacketLen(packet_in+1, 10);
if(DSM_Check_RX_packet())
{
debug("Bind");
for(uint8_t i=0;i<10;i++)
debug(" %02X",packet_in[i+1]);
debugln("");
packet_in[0]=0x80;
packet_in[6]&=0x0F; // It looks like there is a flag 0x40 being added by some receivers
if(packet_in[6]>12) packet_in[6]=12;
else if(packet_in[6]<3) packet_in[6]=6;
telemetry_link=1; // Send received data on serial
phase++;
return 2000;
@@ -288,11 +327,16 @@ uint16_t ReadDsm()
telemetry_set_input_sync(11000); // Always request 11ms spacing even if we don't use half of it in 22ms mode
#endif
case DSM_CH1_WRITE_B:
DSM_build_data_packet(phase == DSM_CH1_WRITE_B); // build lower or upper channels
case DSM_CH2_WRITE_A:
case DSM_CH2_WRITE_B:
DSM_build_data_packet(phase == DSM_CH1_WRITE_B||phase == DSM_CH2_WRITE_B); // build lower or upper channels
CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS); // clear IRQ flags
CYRF_WriteDataPacket(packet);
#if 0
for(uint8_t i=0;i<16;i++)
debug(" %02X", packet[i]);
debugln("");
#endif
phase++; // change from WRITE to CHECK mode
return DSM_WRITE_DELAY;
case DSM_CH1_CHECK_A:
@@ -326,6 +370,10 @@ uint16_t ReadDsm()
phase++; // change from CH2_CHECK to CH2_READ
CYRF_SetTxRxMode(RX_EN); //Receive mode
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //0x80??? //Prepare to receive
#ifdef DSM_GR300
if(num_ch==3)
return timing - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY;
#endif
return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY;
case DSM_CH2_READ_A:
case DSM_CH2_READ_B:
@@ -340,6 +388,15 @@ uint16_t ReadDsm()
if(len>TELEMETRY_BUFFER_SIZE-2)
len=TELEMETRY_BUFFER_SIZE-2;
CYRF_ReadDataPacketLen(packet_in+1, len);
#ifdef DSM_DEBUG_FWD_PGM
//debug(" %02X", packet_in[1]);
if(packet_in[1]==9)
{
for(uint8_t i=0;i<len;i++)
debug(" %02X", packet_in[i+1]);
debugln("");
}
#endif
packet_in[0]=CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;// store RSSI of the received telemetry signal
telemetry_link=1;
}
@@ -350,6 +407,10 @@ uint16_t ReadDsm()
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX operation
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //0x80??? //Prepare to receive
phase = DSM_CH2_READ_B;
#ifdef DSM_GR300
if(num_ch==3)
return timing;
#endif
return 11000;
}
if (phase == DSM_CH2_READ_A)
@@ -370,11 +431,19 @@ uint16_t ReadDsm()
else
{ //Normal mode 22ms
phase = DSM_CH1_WRITE_A; // change from CH2_CHECK_A to CH1_WRITE_A (ie no upper)
#ifdef DSM_GR300
if(num_ch==3)
return timing - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
#endif
return 22000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
}
}
else
phase = DSM_CH1_WRITE_A; // change from CH2_CHECK_B to CH1_WRITE_A (upper already transmitted so transmit lower)
#ifdef DSM_GR300
if(num_ch==3)
return timing - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
#endif
return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY;
#endif
}

View File

@@ -146,7 +146,7 @@ static void __attribute__((unused)) DEVO_build_data_pkt()
uint8_t sign = 0x0b;
for (uint8_t i = 0; i < 4; i++)
{
int16_t value=convert_channel_16b_nolimit(CH_EATR[ch_idx * 4 + i],-1600,1600);//range -1600..+1600
int16_t value=convert_channel_16b_nolimit(CH_EATR[ch_idx * 4 + i],-1600,1600,false);//range -1600..+1600
if(value < 0)
{
value = -value;
@@ -162,6 +162,7 @@ static void __attribute__((unused)) DEVO_build_data_pkt()
DEVO_add_pkt_suffix();
}
#if defined DEVO_HUB_TELEMETRY
static void __attribute__((unused)) DEVO_parse_telemetry_packet()
{
DEVO_scramble_pkt(); //This will unscramble the packet
@@ -186,6 +187,7 @@ static void __attribute__((unused)) DEVO_parse_telemetry_packet()
v_lipo2 = packet[3] << 1;
}
}
#endif
static void __attribute__((unused)) DEVO_cyrf_set_bound_sop_code()
{
@@ -296,7 +298,7 @@ uint16_t devo_callback()
{
static uint8_t txState=0;
#if defined DEVO_HUB_TELEMETRY
#if defined DEVO_HUB_TELEMETRY
int delay;
if (txState == 0)

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(E010R5_CYRF6936_INO)
#include "iface_rf2500.h"
#define E010R5_FORCE_ID
#define E010R5_BIND_CH 0x2D //45
#define E010R5_PAYLOAD_SIZE 14
static void __attribute__((unused)) E010R5_build_data_packet()
{
packet[ 0] = 0x0D; // Packet length
packet[ 1] = convert_channel_8b(THROTTLE);
packet[ 2] = convert_channel_s8b(RUDDER);
packet[ 3] = convert_channel_s8b(ELEVATOR);
packet[ 4] = convert_channel_s8b(AILERON);
packet[ 5] = 0x20; // Trim Rudder
packet[ 6] = 0x20; // Trim Elevator
packet[ 7] = 0x20; // Trim Aileron
packet[ 8] = 0x01 // Flags: high=0x01, low=0x00
| GET_FLAG(CH5_SW, 0x04) // flip=0x04
| GET_FLAG(CH6_SW, 0x08) // led=0x08
| GET_FLAG(CH8_SW, 0x10) // headless=0x10
| GET_FLAG(CH9_SW, 0x20); // one key return=0x20
packet[ 9] = IS_BIND_IN_PROGRESS ? 0x80 : 0x00 // Flags: bind=0x80
| GET_FLAG(CH7_SW, 0x20) // calib=0x20
| GET_FLAG(CH10_SW, 0x01); // strange effect=0x01=long press on right button
packet[10] = rx_tx_addr[0];
packet[11] = rx_tx_addr[1];
packet[12] = rx_tx_addr[2];
packet[13] = 0x9D; // Check
for(uint8_t i=0;i<13;i++)
packet[13] += packet[i];
RF2500_BuildPayload(packet);
}
uint16_t ReadE010R5()
{
//Bind
if(bind_counter)
{
bind_counter--;
if(bind_counter==0)
BIND_DONE;
}
//Send packet
RF2500_SendPayload();
//Timing and hopping
packet_count++;
switch(packet_count)
{
case 1:
case 2:
case 4:
case 5:
return 1183;
default:
hopping_frequency_no++;
hopping_frequency_no &= 3;
if(IS_BIND_IN_PROGRESS)
rf_ch_num = 0x30 + (hopping_frequency_no<<3);
else
rf_ch_num = hopping_frequency[hopping_frequency_no];
RF2500_RFChannel(rf_ch_num);
RF2500_SetPower();
packet_count = 0;
case 3:
E010R5_build_data_packet();
return 3400;
}
return 0;
}
uint16_t initE010R5()
{
BIND_IN_PROGRESS; // Autobind protocol
bind_counter = 2600;
//RF2500 emu init
RF2500_Init(E010R5_PAYLOAD_SIZE, false); // 14 bytes, not scrambled
RF2500_SetTXAddr((uint8_t*)"\x0E\x54\x96\xEE"); // Same address for bind and normal packets
#ifdef E010R5_FORCE_ID
switch(rx_tx_addr[3]%3)
{
case 0:
//TX1
hopping_frequency[0]=0x35; //53
hopping_frequency[1]=0x30; //48
rx_tx_addr[1]=0x45;
rx_tx_addr[2]=0x46;
break;
case 1:
//TX2
hopping_frequency[0]=0x35; //53
hopping_frequency[1]=0x3C; //60
rx_tx_addr[1]=0x1B;
rx_tx_addr[2]=0x9E;
break;
default:
//TX3
hopping_frequency[0]=0x30; //48
hopping_frequency[1]=0x38; //56
rx_tx_addr[1]=0x17;
rx_tx_addr[2]=0x0D;
break;
}
#endif
rx_tx_addr[0]=0x00;
// This is the same as the E010 v1...
hopping_frequency[2]=hopping_frequency[0]+0x10;
hopping_frequency[3]=hopping_frequency[1]+0x10;
E010R5_build_data_packet();
RF2500_RFChannel(hopping_frequency[0]);
hopping_frequency_no=0;
packet_count=0;
return 3400;
}
#endif

View File

@@ -0,0 +1,158 @@
/*
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(E016HV2_CC2500_INO)
#include "iface_cc2500.h"
//#define FORCE_E016HV2_ORIGINAL_ID
#define E016HV2_INITIAL_WAIT 500
#define E016HV2_PACKET_PERIOD 10000
#define E016HV2_RF_BIND_CHANNEL 5
#define E016HV2_PAYLOAD_SIZE 11
#define E016HV2_BIND_COUNT 300 //3sec
static void __attribute__((unused)) E016HV2_send_packet()
{
//payload length (after this byte)
packet[0 ] = 0x0A;
//bind indicator
if(IS_BIND_IN_PROGRESS)
{
packet[1 ] = 0x02;
if(bind_counter)
bind_counter--;
else
{
BIND_DONE;
CC2500_250K_RFChannel(rf_ch_num); // Set main channel
}
}
else
packet[1 ] = 0x20;
//ID
packet[2 ] = rx_tx_addr[2];
packet[3 ] = rx_tx_addr[3];
//channels TREA
uint8_t channel;
if(IS_BIND_IN_PROGRESS)
channel=0x64; // Throttle must be centered during bind
else
channel=convert_channel_8b_limit_deadband(THROTTLE,0x00,0x64,0xC8, 20);
packet[4 ] = channel;
channel=convert_channel_16b_limit(RUDDER,0x00,0xC8);
packet[5 ] = channel;
channel=convert_channel_16b_limit(ELEVATOR,0x00,0xC8);
packet[6 ] = channel;
channel=convert_channel_16b_limit(AILERON,0x00,0xC8);
packet[7 ] = channel;
//flags
if(CH8_SW && !phase) //toggle calib flag
flags ^= 0x40;
phase=CH8_SW;
packet[8 ] = GET_FLAG(CH7_SW, 0x01) // 0x01=Flip
| GET_FLAG(CH9_SW, 0x02) // 0x02=Headless
| GET_FLAG(CH10_SW, 0x04) // 0x04=One Key Return
| flags; // 0x40=Calib
packet[9 ] = 0x02; // Speed control 0x00:low, 0x01:medium, 0x02:high
packet[10] = GET_FLAG(CH5_SW, 0x01) // 0x01=TakeOff/Land (momentary switch)
| GET_FLAG(CH6_SW, 0x04); // 0x04=Emergeny Stop (momentary switch)
CC2500_SetPower(); // Set tx_power
CC2500_SetFreqOffset(); // Set frequency offset
//Build real packet and send it
static uint8_t pid=0;
crc=0;
// stop TX/RX
CC2500_Strobe(CC2500_SIDLE);
// flush tx FIFO
CC2500_Strobe(CC2500_SFTX);
// packet length
CC2500_WriteReg(CC2500_3F_TXFIFO, 6 + 4 + 1 + 11 + 2); // preamble + address + packet_control + payload + crc
// preamble+address
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (uint8_t*)"\xAA\xAA\xAA\xAA\xAA\xAA\xE7\xE7\xE7\xE7", 10);
// packet control
CC2500_WriteReg(CC2500_3F_TXFIFO, 0x50+(pid<<2));
pid++;
// payload
//debug("P:")
for (uint8_t i = 0; i < E016HV2_PAYLOAD_SIZE; ++i)
{
uint8_t byte = (bit_reverse(packet[i])<<1) | (packet[i+1]&0x01);
//debug(" %02X",byte)
CC2500_WriteReg(CC2500_3F_TXFIFO,byte);
crc16_update(byte, 8);
}
// crc
CC2500_WriteReg(CC2500_3F_TXFIFO,crc >> 8);
CC2500_WriteReg(CC2500_3F_TXFIFO,crc);
//debugln(" %04X",crc)
// transmit
CC2500_Strobe(CC2500_STX);
}
uint16_t E016HV2_callback()
{
E016HV2_send_packet();
return E016HV2_PACKET_PERIOD;
}
uint16_t initE016HV2()
{
//Config CC2500
CC2500_250K_Init();
CC2500_250K_RFChannel(E016HV2_RF_BIND_CHANNEL); // Set bind channel
#ifdef FORCE_E016HV2_ORIGINAL_ID
rx_tx_addr[2]=0x27;
rx_tx_addr[3]=0x1B;
//rf_ch_num = 44;
#endif
//General ID
//3F1B -> 68,2C1B -> 49,2B1B -> 48,2A1B -> 47,291B -> 46,281B -> 45,271B -> 44,261B -> 43,251B -> 42
//241B -> no bind,231B -> no bind,221B -> 71,211B -> 70,201B -> 69,1F1B -> 68,1E1B -> 67,1D1B -> 66,1C1B -> 65,1B1B -> 64,1A1B -> 63,191B -> 62,181B -> 61,171B -> 60,161B -> 59
//0C1B -> 49,051B -> 42,041B -> no bind,031B -> no bind,021B -> 71,011B -> 70,001B -> no bind
if(rx_tx_addr[2]<3) rx_tx_addr[2]+=3; // rx_tx_addr[2]=0 is invalid
if(rx_tx_addr[3]==0) rx_tx_addr[3]+=64; // rx_tx_addr[3]=0 is invalid
rf_ch_num = (rx_tx_addr[2] + rx_tx_addr[3]) % 32 + 42;
if(rf_ch_num>71) // channels 72 and 73 are invalid
{
rx_tx_addr[2]-=2;
rf_ch_num-=2;
}
phase=CH8_SW;
flags=0;
bind_counter = E016HV2_BIND_COUNT;
BIND_IN_PROGRESS; // Autobind protocol
return E016HV2_INITIAL_WAIT;
}
#endif

View File

@@ -0,0 +1,152 @@
/*
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(E129_CYRF6936_INO)
#include "iface_rf2500.h"
//#define E129_FORCE_ID
#define E129_BIND_CH 0x2D //45
#define E129_PAYLOAD_SIZE 16
static void __attribute__((unused)) E129_build_data_packet()
{
//Build the packet
memset(packet,0,E129_PAYLOAD_SIZE);
packet[ 0] = 0x0F; // Packet length
if(IS_BIND_IN_PROGRESS)
{
packet[ 1] = 0xA4;
packet[ 2] = bit_reverse(rx_tx_addr[2]);
packet[ 3] = bit_reverse(rx_tx_addr[3]);
packet[ 4] = bit_reverse(rx_tx_addr[0]);
packet[ 5] = bit_reverse(rx_tx_addr[1]);
for(uint8_t i=0; i<4; i++)
packet[6+i]=hopping_frequency[i]-2;
}
else
{
packet[ 1] = 0xA6;
packet[ 2] = 0xF7; // High rate 0xF7, low rate 0xF4
//packet[ 3] = 0x00; // Mode: short press=0x20->0x00->0x20->..., long press=0x10->0x30->0x10->...
packet[ 4] = GET_FLAG(CH5_SW, 0x20) // Take off/Land 0x20
| GET_FLAG(CH6_SW, 0x04); // Emergency stop 0x04
uint16_t val = convert_channel_10b(AILERON,false);
uint8_t trim = convert_channel_8b(CH7) & 0xFC;
packet[ 5] = trim | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8
packet[ 6] = val; // channel (0x000...0x200...0x3FF)
val = convert_channel_10b(ELEVATOR,false);
trim = convert_channel_8b(CH8) & 0xFC;
packet[ 7] = trim | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8
packet[ 8] = val; // channel (0x000...0x200...0x3FF)
if(packet_count>200)
val = convert_channel_10b(THROTTLE,false);
else
{//Allow bind to complete with throttle not centered
packet_count++;
val=0x200;
}
packet[ 9] = (0x1F<<2) | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8
packet[10] = val; // channel (0x000...0x200...0x3FF)
val = convert_channel_10b(RUDDER,false);
trim = convert_channel_8b(CH9) & 0xFC;
packet[11] = trim | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8
packet[12] = val; // channel (0x000...0x200...0x3FF)
}
packet[14] = 0x00; // Check
for(uint8_t i=0;i<14;i++)
packet[14] += packet[i];
RF2500_BuildPayload(packet);
}
uint16_t ReadE129()
{
//Set RF channel
if(phase==0)
RF2500_RFChannel(IS_BIND_IN_PROGRESS ? E129_BIND_CH : hopping_frequency[hopping_frequency_no]);
//Send packet
RF2500_SendPayload();
//Send twice on same channel
if(phase==0)
{
phase++;
return 1260;
}
//Bind
if(bind_counter)
{
bind_counter--;
if(bind_counter==0)
{
BIND_DONE;
RF2500_SetTXAddr(rx_tx_addr); // 4 bytes of address
}
}
//Build packet
E129_build_data_packet();
//Set power
RF2500_SetPower();
//Hopp
hopping_frequency_no++;
hopping_frequency_no &= 3;
phase=0;
return 5200-1260;
}
uint16_t initE129()
{
BIND_IN_PROGRESS; // Autobind protocol
bind_counter = 384; // ~2sec
//RF2500 emu init
RF2500_Init(E129_PAYLOAD_SIZE, true); // 16 bytes, Scrambled
//Freq hopping
calc_fh_channels(4);
for(uint8_t i=0; i<4; i++)
if(hopping_frequency[i]==E129_BIND_CH)
hopping_frequency[i]++;
#ifdef E129_FORCE_ID
rx_tx_addr[0]=0xC1;
rx_tx_addr[1]=0x22;
rx_tx_addr[2]=0x05;
rx_tx_addr[3]=0xA3;
hopping_frequency[0]=0x3C; //60
hopping_frequency[1]=0x49; //73
hopping_frequency[2]=0x4B; //75
hopping_frequency[3]=0x41; //65
#endif
RF2500_SetTXAddr((uint8_t*)"\xE2\x32\xE0\xC8"); // 4 bytes of bind address
E129_build_data_packet();
hopping_frequency_no=0;
packet_count=0;
phase=0;
return 1260;
}
#endif

View File

@@ -15,7 +15,7 @@
#if defined(ESKY150V2_CC2500_INO)
#include "iface_nrf250k.h"
#include "iface_cc2500.h"
//#define ESKY150V2_FORCE_ID
@@ -52,17 +52,17 @@ static void __attribute__((unused)) ESKY150V2_set_freq(void)
hopping_frequency[ESKY150V2_NFREQCHANNELS]=ESKY150V2_BIND_CHANNEL;
//Calib all channels
NRF250K_SetFreqOffset(); // Set frequency offset
NRF250K_HoppingCalib(ESKY150V2_NFREQCHANNELS+1);
CC2500_SetFreqOffset(); // Set frequency offset
CC2500_250K_HoppingCalib(ESKY150V2_NFREQCHANNELS+1);
}
static void __attribute__((unused)) ESKY150V2_send_packet()
{
NRF250K_SetFreqOffset(); // Set frequency offset
NRF250K_Hopping(hopping_frequency_no);
CC2500_SetFreqOffset(); // Set frequency offset
CC2500_250K_Hopping(hopping_frequency_no);
if (++hopping_frequency_no >= ESKY150V2_NFREQCHANNELS)
hopping_frequency_no = 0;
NRF250K_SetPower(); //Set power level
CC2500_SetPower(); //Set power level
packet[0] = 0xFA; // Unknown
packet[1] = 0x41; // Unknown
@@ -74,7 +74,7 @@ static void __attribute__((unused)) ESKY150V2_send_packet()
packet[4+2*i] = channel;
packet[5+2*i] = channel>>8;
}
NRF250K_WritePayload(packet, ESKY150V2_PAYLOADSIZE);
CC2500_250K_NRF_WritePayload(packet, ESKY150V2_PAYLOADSIZE);
}
uint16_t ESKY150V2_callback()
@@ -90,14 +90,14 @@ uint16_t ESKY150V2_callback()
else
{
BIND_DONE; //Need full power for bind to work...
NRF250K_SetPower(); //Set power level
CC2500_SetPower(); //Set power level
BIND_IN_PROGRESS;
NRF250K_WritePayload(packet, ESKY150V2_BINDPAYLOADSIZE);
CC2500_250K_NRF_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);
CC2500_250K_NRF_SetTXAddr(rx_tx_addr, ESKY150V2_TXID_SIZE);
memset(packet,0x00,ESKY150V2_PAYLOADSIZE);
}
return 30000; //ESKY150V2_BINDING_PACKET_PERIOD;
@@ -108,7 +108,7 @@ uint16_t ESKY150V2_callback()
uint16_t initESKY150V2()
{
if(option==0) option=1; // Trick the RF component auto select system
NRF250K_Init();
CC2500_250K_Init();
ESKY150V2_set_freq();
hopping_frequency_no = 0;
@@ -120,8 +120,8 @@ uint16_t initESKY150V2()
if(IS_BIND_IN_PROGRESS)
{
NRF250K_SetTXAddr((uint8_t *)"\x73\x73\x74\x63", ESKY150V2_TXID_SIZE); //Bind address
NRF250K_Hopping(ESKY150V2_NFREQCHANNELS); //Bind channel
CC2500_250K_NRF_SetTXAddr((uint8_t *)"\x73\x73\x74\x63", ESKY150V2_TXID_SIZE); //Bind address
CC2500_250K_Hopping(ESKY150V2_NFREQCHANNELS); //Bind channel
memcpy(packet,"\x73\x73\x74\x63", ESKY150V2_TXID_SIZE);
memcpy(&packet[ESKY150V2_TXID_SIZE],rx_tx_addr, ESKY150V2_TXID_SIZE);
packet[8]=0x41; //Unknown
@@ -134,7 +134,7 @@ uint16_t initESKY150V2()
bind_counter=100;
}
else
NRF250K_SetTXAddr(rx_tx_addr, ESKY150V2_TXID_SIZE);
CC2500_250K_NRF_SetTXAddr(rx_tx_addr, ESKY150V2_TXID_SIZE);
return 50000;
}

View File

@@ -52,24 +52,18 @@ static void __attribute__((unused)) ssv_pack_dpl(uint8_t addr[], uint8_t pid, ui
header[0] = (addr[4] >> 7);
// calculate the crc
union
{
uint8_t bytes[2];
uint16_t val;
} crc;
crc.val=0x3c18;
crc=0x3c18;
for (i = 0; i < 7; ++i)
crc.val=crc16_update(crc.val,header[i],8);
crc16_update(header[i],8);
for (i = 0; i < *len; ++i)
crc.val=crc16_update(crc.val,payload[i],8);
crc16_update(payload[i],8);
// encode payload and crc
// xor with this:
for (i = 0; i < *len; ++i)
payload[i] ^= ssv_xor[i];
crc.bytes[1] ^= ssv_xor[i++];
crc.bytes[0] ^= ssv_xor[i++];
crc ^= ssv_xor[i++]<<8;
crc ^= ssv_xor[i++];
// pack the pcf, payload, and crc into packed_payload
packed_payload[0] = pcf >> 1;
@@ -78,11 +72,11 @@ static void __attribute__((unused)) ssv_pack_dpl(uint8_t addr[], uint8_t pid, ui
for (i = 0; i < *len - 1; ++i)
packed_payload[i+2] = (payload[i] << 7) | (payload[i+1] >> 1);
packed_payload[i+2] = (payload[i] << 7) | (crc.val >> 9);
packed_payload[i+2] = (payload[i] << 7) | (crc >> 9);
++i;
packed_payload[i+2] = (crc.val >> 1 & 0x80 ) | (crc.val >> 1 & 0x7F);
packed_payload[i+2] = (crc >> 1 & 0x80 ) | (crc >> 1 & 0x7F);
++i;
packed_payload[i+2] = (crc.val << 7);
packed_payload[i+2] = (crc << 7);
*len += 4;
}

View File

@@ -17,8 +17,9 @@
/** 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)
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO) || defined(FRSKY_RX_CC2500_INO) || defined(FRSKYR9_SX1276_INO)
uint8_t FrSkyFormat=0;
uint8_t FrSkyX_chanskip;
#endif
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO) || defined(FRSKY_RX_CC2500_INO) || defined(FRSKYR9_SX1276_INO)
@@ -33,7 +34,7 @@ static uint16_t __attribute__((unused)) FrSkyX_CRCTable(uint8_t val)
val /= 16 ;
return word ^ (0x1081 * val) ;
}
uint16_t FrSkyX_crc(uint8_t *data, uint8_t len, uint8_t init=0)
uint16_t FrSkyX_crc(uint8_t *data, uint8_t len, uint16_t init=0)
{
uint16_t crc = init;
for(uint8_t i=0; i < len; i++)
@@ -69,14 +70,18 @@ static void __attribute__((unused)) FrSkyX_channels(uint8_t offset)
FAILSAFE_VALUES_off;
}
failsafe_count++;
packet[7] = FS_flag;
if(protocol==PROTO_FRSKY_R9)
failsafe_count++; // R9 is 20ms, X is 9ms
packet[offset] = FS_flag;
#else
packet[7] = 0;
packet[offset] = 0;
#endif
//
packet[offset+1] = 0; //??
//
uint8_t chan_index = chan_start;
uint16_t ch1,ch2;
for(uint8_t i = offset; i < 12+offset ; i+=3)
for(uint8_t i = offset+2; i < 12+offset+2 ; i+=3)
{//12 bytes of channel data
#ifdef FAILSAFE_ENABLE
if( (FS_flag & 0x10) && ((failsafe_chan & 0x07) == (chan_index & 0x07)) )
@@ -180,11 +185,18 @@ void Frsky_init_clone(void)
else if(protocol==PROTO_FRSKYX2)
temp=FRSKYX2_CLONE_EEPROM_OFFSET;
FrSkyFormat=eeprom_read_byte((EE_ADDR)temp++);
/* FRSKY_RX_D8 =0,
FRSKY_RX_D16FCC =1,
FRSKY_RX_D16LBT =2,
FRSKY_RX_D16v2FCC =3,
FRSKY_RX_D16v2LBT =4,*/
if(protocol==PROTO_FRSKYX)
FrSkyFormat >>= 1;
else
FrSkyFormat >>= 2;
FrSkyFormat <<= 1; //FCC_16/LBT_16
if(sub_protocol==XCLONE_8)
FrSkyFormat++; //FCC_8/LBT_8
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++);
@@ -275,7 +287,7 @@ void Frsky_init_clone(void)
//FRSKYX
/*02_IOCFG0*/ 0x06 ,
/*00_IOCFG2*/ 0x06 ,
/*17_MCSM1*/ 0x0c , //X2->0x0E -> Go/Stay in RX mode
/*17_MCSM1*/ 0x0c , //X2->0x0E -> RX stays in RX and TX stays in TX???
/*18_MCSM0*/ 0x18 ,
/*06_PKTLEN*/ 0x1E ,
/*07_PKTCTRL1*/ 0x04 ,
@@ -376,21 +388,120 @@ void Frsky_init_clone(void)
}
#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 ;
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYR9_SX1276_INO)
uint8_t FrSkyX_TX_Seq, FrSkyX_TX_IN_Seq;
uint8_t FrSkyX_RX_Seq ;
#ifdef SPORT_SEND
struct t_FrSkyX_TX_Frame
#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_seq_sport(uint8_t start, uint8_t end)
{
uint8_t count;
uint8_t payload[8];
} ;
// Store FrskyX telemetry
struct t_FrSkyX_TX_Frame FrSkyX_TX_Frames[4] ;
for (uint8_t i=start+1;i<=end;i++)
packet[i]=0;
packet[start] = 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[start] |= FrSkyX_TX_IN_Seq&0x03;
packet[start+1] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq&0x03].count;
for (uint8_t i=start+2;i<start+2+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[start] |= FrSkyX_TX_Seq;
uint8_t nbr_bytes=0;
for (uint8_t i=start+2;i<=end;i++)
{
if(SportHead==SportTail)
break; //buffer empty
packet[i]=SportData[SportHead];
FrSkyX_TX_Frames[FrSkyX_TX_Seq].payload[i-start+2]=SportData[SportHead];
SportHead=(SportHead+1) & (MAX_SPORT_BUFFER-1);
nbr_bytes++;
}
packet[start+1]=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[start] |= FrSkyX_TX_IN_Seq;
packet[start+1] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].count;
for (uint8_t i=start+2;i<start+2+FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].count;i++)
packet[i] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].payload[i-start+2];
}
}
else
packet[start] |= 0x08 ; //FrSkyX_TX_Seq=8 at startup
}
if(packet[start+1])
{//Debug
debug("SP: ");
for(uint8_t i=0;i<packet[start+1];i++)
debug("%02X ",packet[start+2+i]);
debugln("");
}
#else
packet[start] |= 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
}
static void __attribute__((unused)) FrSkyX_telem_init(void)
{
FrSkyX_TX_Seq = 0x08 ; // Request init
#ifdef SPORT_SEND
FrSkyX_TX_IN_Seq = 0xFF ; // No sequence received yet
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
#ifdef TELEMETRY
telemetry_lost=1;
telemetry_link=0; //Stop sending telemetry
#endif
}
#endif
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO)
static void __attribute__((unused)) FrSkyX_set_start(uint8_t ch )
{
CC2500_Strobe(CC2500_SIDLE);
@@ -409,7 +520,7 @@ static void __attribute__((unused)) FrSkyX_init()
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_17_MCSM1, 0x0E); //0x0E -> RX stays in RX and TX stays in TX???
CC2500_WriteReg(CC2500_11_MDMCFG3, 0x84); // bitrate 70K->77K
}
}

View File

@@ -54,7 +54,7 @@ static void __attribute__((unused)) frsky2way_build_bind_packet()
packet[14] = 0x00;
packet[15] = 0x00;
packet[16] = 0x00;
packet[17] = 0x01;
packet[17] = rx_tx_addr[1];
}
static void __attribute__((unused)) frsky2way_data_frame()
@@ -71,7 +71,7 @@ static void __attribute__((unused)) frsky2way_data_frame()
packet[4] = 0x00;
#endif
packet[5] = 0x01;
packet[5] = rx_tx_addr[1];
//
packet[10] = 0;
packet[11] = 0;
@@ -100,6 +100,7 @@ uint16_t initFrSky_2way()
if (sub_protocol==DCLONE)
Frsky_init_clone();
else
{
for(uint8_t i=0;i<50;i++)
{
uint8_t freq = (i * 0x1e) % 0xeb;
@@ -109,6 +110,8 @@ uint16_t initFrSky_2way()
freq=0;
hopping_frequency[i]=freq;
}
rx_tx_addr[1]=1; // keep compatibility with already bound RXs
}
packet_count=0;
if(IS_BIND_IN_PROGRESS)
@@ -178,7 +181,7 @@ uint16_t ReadFrSky_2way()
if(packet_in[len-1] & 0x80)
{//with valid crc
packet_count=0;
frsky_check_telemetry(packet_in,len); //check if valid telemetry packets and buffer them.
frsky_process_telemetry(packet_in,len); //check if valid telemetry packets and buffer them.
}
#endif
}

View File

@@ -1,96 +1,194 @@
#if defined(FRSKYR9_SX1276_INO)
#include "iface_sx1276.h"
#define FREQ_MAP_SIZE 29
#define DISP_FREQ_TABLE
// TODO the channel spacing is equal, consider calculating the new channel instead of using lookup tables (first_chan + index * step)
#define FLEX_FREQ 29
#define FCC_FREQ 43
#define EU_FREQ 19
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
enum {
FRSKYR9_FREQ=0,
FRSKYR9_DATA,
FRSKYR9_RX1,
FRSKYR9_RX2,
};
static uint32_t FrSkyR9_freq_map_868[FREQ_MAP_SIZE] =
void FrSkyR9_set_frequency()
{
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,
uint8_t data[3];
uint16_t num=0;
hopping_frequency_no += FrSkyX_chanskip;
switch(sub_protocol & 0xFD)
{
case R9_868:
if(IS_BIND_DONE) // if bind is in progress use R9_915 instead
{
hopping_frequency_no %= FLEX_FREQ;
num=hopping_frequency_no;
if(hopping_frequency_no>=FLEX_FREQ-2)
num+=FrSkyX_chanskip-FLEX_FREQ+2; // the last 2 values are FrSkyX_chanskip and FrSkyX_chanskip+1
num <<= 5;
num += 0xD700;
break;
}//else use R9_915
case R9_915:
hopping_frequency_no %= FLEX_FREQ;
num=hopping_frequency_no;
if(hopping_frequency_no>=FLEX_FREQ-2)
num+=FrSkyX_chanskip-FLEX_FREQ+2; // the last 2 values are FrSkyX_chanskip and FrSkyX_chanskip+1
num <<= 5;
num += 0xE4C0;
break;
case R9_FCC:
hopping_frequency_no %= FCC_FREQ;
num=hopping_frequency_no;
num <<= 5;
num += 0xE200;
break;
case R9_EU:
hopping_frequency_no %= EU_FREQ;
num=hopping_frequency_no;
num <<= 4;
num += 0xD7D0;
break;
}
data[0] = num>>8;
data[1] = num&0xFF;
data[2] = 0x00;
// last two determined by FrSkyR9_step
0,
0
};
#ifdef DISP_FREQ_TABLE
if(phase==0xFF)
debugln("F%d=%02X%02X%02X=%lu", hopping_frequency_no, data[0], data[1], data[2], (uint32_t)((data[0]<<16)+(data[1]<<8)+data[2])*61);
#endif
SX1276_WriteRegisterMulti(SX1276_06_FRFMSB, data, 3);
}
static uint8_t FrSkyR9_step = 1;
static uint32_t* FrSkyR9_freq_map = FrSkyR9_freq_map_915;
static void __attribute__((unused)) FrSkyR9_build_packet()
{
//ID
packet[0] = rx_tx_addr[1];
packet[1] = rx_tx_addr[2];
packet[2] = rx_tx_addr[3];
//Hopping
packet[3] = hopping_frequency_no; // current channel index
packet[4] = FrSkyX_chanskip; // step size and last 2 channels start index
//RX number
packet[5] = RX_num; // receiver number from OpenTX
//Channels
FrSkyX_channels(6); // Set packet[6]=failsafe, packet[7]=0?? and packet[8..19]=channels data
//Bind
if(IS_BIND_IN_PROGRESS)
{// 915 0x01=CH1-8_TELEM_ON 0x41=CH1-8_TELEM_OFF 0xC1=CH9-16_TELEM_OFF 0x81=CH9-16_TELEM_ON
packet[6] = 0x01; // bind indicator
if(sub_protocol & 1)
packet[6] |= 0x20; // 868
if(binding_idx&0x01)
packet[6] |= 0x40; // telem OFF
if(binding_idx&0x02)
packet[6] |= 0x80; // ch9-16
}
//Sequence and send SPort
FrSkyX_seq_sport(20,23); //20=RX|TXseq, 21=bytes count, 22&23=data
//CRC
uint16_t crc = FrSkyX_crc(packet, 24);
packet[24] = crc; // low byte
packet[25] = crc >> 8; // high byte
}
static uint8_t __attribute__((unused)) FrSkyR9_CRC8(uint8_t *p, uint8_t l)
{
uint8_t crc = 0xFF;
for (uint8_t i = 0; i < l; i++)
{
crc = crc ^ p[i];
for ( uint8_t j = 0; j < 8; j++ )
if ( crc & 0x80 )
{
crc <<= 1;
crc ^= 0x07;
}
else
crc <<= 1;
}
return crc;
}
static void __attribute__((unused)) FrSkyR9_build_EU_packet()
{
//ID
packet[0] = rx_tx_addr[1];
packet[1] = rx_tx_addr[2];
packet[2] = rx_tx_addr[3];
//Hopping
packet[3] = FrSkyX_chanskip; // step size and last 2 channels start index
//RX number
packet[4] = RX_num; // receiver number from OpenTX
//Channels
//TODO FrSkyX_channels(5,4); // Set packet[5]=failsafe and packet[6..11]=4 channels data
//Bind
if(IS_BIND_IN_PROGRESS)
{
packet[5] = 0x01; // bind indicator
if((sub_protocol & 2) == 0)
packet[5] |= 0x10; // 16CH
// if(sub_protocol & 1)
// packet[5] |= 0x20; // 868
if(binding_idx&0x01)
packet[5] |= 0x40; // telem OFF
if(binding_idx&0x02)
packet[5] |= 0x80; // ch9-16
}
//Sequence and send SPort
packet[12] = (FrSkyX_RX_Seq << 4)|0x08; //TX=8 at startup
//CRC
packet[13] = FrSkyR9_CRC8(packet, 13);
}
uint16_t initFrSkyR9()
{
//Check frequencies
#ifdef DISP_FREQ_TABLE
phase=0xFF;
FrSkyX_chanskip=1;
hopping_frequency_no=0xFF;
for(uint8_t i=0;i<FCC_FREQ;i++)
FrSkyR9_set_frequency();
#endif
//Reset ID
set_rx_tx_addr(MProtocol_id_master);
if(sub_protocol & 0x01)
FrSkyR9_freq_map = FrSkyR9_freq_map_868;
//FrSkyX_chanskip
FrSkyX_chanskip = 1 + (random(0xfefefefe) % 24);
debugln("chanskip=%d", FrSkyX_chanskip);
//Set FrSkyFormat
if((sub_protocol & 0x02) == 0)
FrSkyFormat=0; // 16 channels
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];
FrSkyFormat=1; // 8 channels
debugln("%dCH", FrSkyFormat&1 ? 8:16);
//EU packet length
if( (sub_protocol & 0xFD) == R9_EU )
packet_length=14;
else
packet_length=26;
//SX1276 Init
SX1276_SetMode(true, false, SX1276_OPMODE_SLEEP);
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
@@ -106,103 +204,104 @@ uint16_t initFrSkyR9()
SX1276_SetPreambleLength(9);
SX1276_SetDetectionThreshold(SX1276_MODEM_DETECTION_THRESHOLD_SF6);
SX1276_SetLna(1, true);
SX1276_SetHopPeriod(0); // 0 = disabled, we hope frequencies manually
SX1276_SetHopPeriod(0); // 0 = disabled, we hop frequencies manually
SX1276_SetPaDac(true);
hopping_frequency_no = 0;
// TODO this can probably be shorter
return 20000; // start calling FrSkyR9_callback in 20 milliseconds
SX1276_SetTxRxMode(TX_EN); // Set RF switch to TX
//Enable all IRQ flags
SX1276_WriteReg(SX1276_11_IRQFLAGSMASK,0x00);
FrSkyX_telem_init();
hopping_frequency_no=0;
phase=FRSKYR9_FREQ;
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)
switch (phase)
{
// 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;
case FRSKYR9_FREQ:
//Force standby
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
//Set frequency
FrSkyR9_set_frequency(); // Set current center frequency
//Set power
// 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); // Lowest power for the T18
//Build packet
if( packet_length == 26 )
FrSkyR9_build_packet();
else
FrSkyR9_build_EU_packet();
phase++;
return 460; // Frequency settle time
case FRSKYR9_DATA:
//Set RF switch to TX
SX1276_SetTxRxMode(TX_EN);
//Send packet
SX1276_WritePayloadToFifo(packet, packet_length);
SX1276_SetMode(true, false, SX1276_OPMODE_TX);
#if not defined TELEMETRY
phase=FRSKYR9_FREQ;
return 20000-460;
#else
phase++;
return 11140; // Packet send time
case FRSKYR9_RX1:
//Force standby
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
//RX packet size is 13
SX1276_WriteReg(SX1276_22_PAYLOAD_LENGTH, 13);
//Reset pointer
SX1276_WriteReg(SX1276_0D_FIFOADDRPTR, 0x00);
//Set RF switch to RX
SX1276_SetTxRxMode(RX_EN);
//Clear all IRQ flags
SX1276_WriteReg(SX1276_12_REGIRQFLAGS,0xFF);
//Switch to RX
SX1276_WriteReg(SX1276_01_OPMODE, 0x85);
phase++;
return 7400;
case FRSKYR9_RX2:
if( (SX1276_ReadReg(SX1276_12_REGIRQFLAGS)&0xF0) == (_BV(SX1276_REGIRQFLAGS_RXDONE) | _BV(SX1276_REGIRQFLAGS_VALIDHEADER)) )
{
if(SX1276_ReadReg(SX1276_13_REGRXNBBYTES)==13)
{
SX1276_ReadRegisterMulti(SX1276_00_FIFO,packet_in,13);
if( packet_in[9]==rx_tx_addr[1] && packet_in[10]==rx_tx_addr[2] && FrSkyX_crc(packet_in, 11, rx_tx_addr[1]+(rx_tx_addr[2]<<8))==(packet_in[11]+(packet_in[12]<<8)) )
{
if(packet_in[0]&0x80)
RX_RSSI=packet_in[0]<<1;
else
v_lipo1=(packet_in[0]<<1)+1;
//TX_LQI=~(SX1276_ReadReg(SX1276_19_PACKETSNR)>>2)+1;
TX_RSSI=SX1276_ReadReg(SX1276_1A_PACKETRSSI)-157;
for(uint8_t i=0;i<9;i++)
packet[4+i]=packet_in[i]; // Adjust buffer to match FrSkyX
frsky_process_telemetry(packet,len); // Process telemetry packet
pps_counter++;
if(TX_LQI==0)
TX_LQI++; // Recover telemetry right away
}
}
}
if (millis() - pps_timer >= 1000)
{//1 packet every 20ms
pps_timer = millis();
debugln("%d pps", pps_counter);
TX_LQI = pps_counter<<1; // Max=100%
pps_counter = 0;
}
if(TX_LQI==0)
FrSkyX_telem_init(); // Reset telemetry
else
telemetry_link=1; // Send telemetry out anyway
phase=FRSKYR9_FREQ;
break;
#endif
}
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;
return 1000;
}
#endif

View File

@@ -98,89 +98,11 @@ static void __attribute__((unused)) FrSkyX_build_packet()
packet[5] = FrSkyX_chanskip>>2;
packet[6] = RX_num;
packet[8] = 0; //??
FrSkyX_channels(9); // Set packet[7] and packet[9..20] with channels data and failsafe
//Channels
FrSkyX_channels(7); // Set packet[7]=failsafe, packet[8]=0?? and packet[9..20]=channels data
//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
//Sequence and send SPort
FrSkyX_seq_sport(21,packet_size-2); //21=RX|TXseq, 22=bytes count, 23..packet_size-2=data
//CRC
uint16_t lcrc = FrSkyX_crc(&packet[3], packet_size-4);
@@ -215,23 +137,23 @@ uint16_t ReadFrSkyX()
FrSkyX_initialize_data(0);
hopping_frequency_no=0;
BIND_DONE;
state++; //FRSKY_DATA1
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 ;
}
FrSkyX_set_start(hopping_frequency_no);
FrSkyX_build_packet();
if(FrSkyFormat & 2)
{// LBT
CC2500_Strobe(CC2500_SRX); //Acquire RSSI
CC2500_Strobe(CC2500_SRX); //Acquire RSSI
state++;
return 400; // LBT v2.1
return 400; // LBT
}
case FRSKY_DATA2:
if(FrSkyFormat & 2)
@@ -241,84 +163,85 @@ uint16_t ReadFrSkyX()
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
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
if ( rssi > 14 && rssi < 128) //if RSSI above -65dBm (12=-70) => ETSI requirement
#endif
{
LBT_POWER_on; // Reduce to low power before transmitting
LBT_POWER_on; //Reduce to low power before transmitting
debugln("Busy %d %d",hopping_frequency_no,rssi);
}
}
CC2500_Strobe(CC2500_SIDLE);
CC2500_Strobe(CC2500_SFTX);
CC2500_Strobe(CC2500_SFTX); //Flush the TXFIFO
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
return 4000; // LBT
else
return 5200; // FCC v2.1
return 5200; // FCC
case FRSKY_DATA3:
CC2500_Strobe(CC2500_SIDLE);
CC2500_Strobe(CC2500_SFRX); //Flush the RXFIFO
CC2500_SetTxRxMode(RX_EN);
CC2500_Strobe(CC2500_SRX);
state++;
if(FrSkyFormat & 2)
return 4100; // LBT v2.1
return 4200; // LBT
else
return 3300; // FCC v2.1
case FRSKY_DATA4:
return 3400; // FCC
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
{
//debug("Telem:");
packet_count=0;
CC2500_ReadData(packet_in, len);
#if defined TELEMETRY
if(protocol==PROTO_FRSKYX || (protocol==PROTO_FRSKYX2 && (packet_in[len-1] & 0x80)) )
{//with valid crc for FRSKYX2
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if (len && len <= 17) //Telemetry frame is 17 bytes
{
//debug("Telem:");
CC2500_ReadData(packet_in, len); //Read what has been received so far
if(len<17)
{//not all bytes were received
uint8_t last_len=CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if(last_len==17) //All bytes received
{
CC2500_ReadData(packet_in+len, last_len-len); //Finish to read
len=17;
}
}
if(len==17 && (protocol==PROTO_FRSKYX || (protocol==PROTO_FRSKYX2 && (packet_in[len-1] & 0x80))) )
{//Telemetry received 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
if(frsky_process_telemetry(packet_in,len)) //Check and process telemetry packet
{//good packet received
pps_counter++;
if(TX_LQI==0)
TX_LQI++; //Recover telemetry right away
}
}
#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
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
//debugln("");
}
CC2500_Strobe(CC2500_SFRX); //Flush the RXFIFO
}
if (millis() - pps_timer >= 900)
{//1 packet every 9ms
pps_timer = millis();
debugln("%d pps", pps_counter);
TX_LQI = pps_counter; //Max=100%
pps_counter = 0;
}
if(TX_LQI==0)
FrSkyX_telem_init(); //Reset telemetry
else
telemetry_link=1; //Send telemetry out anyway
#endif
state = FRSKY_DATA1;
return 500; // FCC & LBT v2.1
}
return 400; // FCC & LBT
}
return 1;
}
@@ -327,7 +250,7 @@ uint16_t initFrSkyX()
set_rx_tx_addr(MProtocol_id_master);
FrSkyFormat = sub_protocol;
if (sub_protocol==XCLONE)
if (sub_protocol==XCLONE_16||sub_protocol==XCLONE_8)
Frsky_init_clone();
else if(protocol==PROTO_FRSKYX)
{
@@ -361,15 +284,7 @@ uint16_t initFrSkyX()
state = FRSKY_DATA1;
FrSkyX_initialize_data(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
FrSkyX_telem_init();
return 10000;
}
}
#endif

View File

@@ -201,9 +201,10 @@ static uint8_t __attribute__((unused)) frskyx_rx_check_crc_id(bool bind,bool ini
{//Save TXID
rx_tx_addr[3] = packet[3];
rx_tx_addr[2] = packet[4];
rx_tx_addr[1] = packet[17];
}
else
if(rx_tx_addr[3] != packet[offset] || rx_tx_addr[2] != packet[offset+1])
if(rx_tx_addr[3] != packet[offset] || rx_tx_addr[2] != packet[offset+1] || rx_tx_addr[1] != packet[bind?17:5])
return false; // Bad address
return true; // Full match
}
@@ -357,7 +358,6 @@ static void __attribute__((unused)) frsky_rx_data()
uint16_t initFrSky_Rx()
{
state = 0;
frsky_rx_chanskip = 1;
hopping_frequency_no = 0;
rx_data_started = false;
@@ -378,12 +378,12 @@ uint16_t initFrSky_Rx()
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(IS_BIND_DONE && phase != FRSKY_RX_DATA) return initFrSky_Rx(); // Abort bind
if ((prev_option != option) && (phase >= FRSKY_RX_DATA))
{
if (option == 0)
@@ -413,6 +413,7 @@ uint16_t FrSky_Rx_callback()
phase = FRSKY_RX_TUNE_LOW;
debugln("FRSKY_RX_TUNE_LOW");
frsky_rx_strobe_rx();
state = 0;
return 1000;
}
}
@@ -484,7 +485,7 @@ uint16_t FrSky_Rx_callback()
}
}
else
state=0x3FF; //No hop table for D16v2
state = 0x3FF; //No hop table for D16v2
if (state == 0x3FF)
{
debugln("Bind complete");

View File

@@ -14,7 +14,7 @@
*/
// Last sync with main deviation/sfhss_cc2500.c dated 2016-03-23
#if defined(SFHSS_CC2500_INO)
#if defined(FUTABA_CC2500_INO)
#include "iface_cc2500.h"
@@ -182,7 +182,7 @@ static void __attribute__((unused)) SFHSS_build_data_packet()
#endif
{ //Normal data
for(uint8_t i=0;i<4;i++)
ch[i] = convert_channel_16b_nolimit(CH_AETR[ch_offset+i],2020,1020);
ch[i] = convert_channel_16b_nolimit(CH_AETR[ch_offset+i],2020,1020,false);
}

View File

@@ -29,17 +29,19 @@ enum {
HOTT_START = 0x00,
HOTT_CAL = 0x01,
HOTT_DATA1 = 0x02,
HOTT_RX1 = 0x03,
HOTT_RX2 = 0x04,
HOTT_DATA2 = 0x03,
HOTT_RX1 = 0x04,
HOTT_RX2 = 0x05,
};
#ifdef HOTT_FW_TELEMETRY
#define HOTT_SENSOR_TYPE 6
#define HOTT_SENSOR_SEARCH_PERIOD 120
#define HOTT_SENSOR_SEARCH_PERIOD 2000
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];
uint8_t HOTT_sensor_seq=0;
#endif
#define HOTT_FREQ0_VAL 0x6E
@@ -112,7 +114,7 @@ static void __attribute__((unused)) HOTT_tune_freq()
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
phase = HOTT_START; // Restart the tune process if option is changed to get good tuned values
}
}
@@ -143,36 +145,38 @@ static void __attribute__((unused)) HOTT_init()
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);
memcpy(rx_tx_addr,"\x7C\x94\x00\x0D\x50",5); //TX1
memcpy(rx_tx_addr,"\xEA\x4D\x00\x01\x50",5); //TX2
#endif
memset(&packet[30],0xFF,9);
packet[39]=0x07; // unknown and constant
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;
uint16_t addr=HOTT_EEPROM_OFFSET+RX_num*5;
debug("RXID: ");
for(uint8_t i=0;i<5;i++)
{
packet[45+i]=eeprom_read_byte((EE_ADDR)(addr+i));
debug(" %02X",packet[45+i]);
}
debugln("");
}
}
static void __attribute__((unused)) HOTT_data_packet()
static void __attribute__((unused)) HOTT_prep_data_packet()
{
static uint8_t upper=0;
packet[2] = hopping_frequency_no;
packet[3] = 0x00; // used for failsafe but may also be used for additional channels
packet[3] = upper; // used for failsafe and upper channels (only supporting 16 channels)
#ifdef FAILSAFE_ENABLE
static uint8_t failsafe_count=0;
if(IS_FAILSAFE_VALUES_on && IS_BIND_DONE)
@@ -192,13 +196,16 @@ static void __attribute__((unused)) HOTT_data_packet()
uint16_t val;
for(uint8_t i=4;i<28;i+=2)
{
val=Channel_data[(i-4)>>1];
uint8_t ch=(i-4)>>1;
if(upper && ch >= 8)
ch+=4; // when upper swap CH9..CH12 by CH13..16
val=Channel_data[ch];
val=(((val<<2)+val)>>2)+860*2; // value range 860<->2140 *2 <-> -125%<->+125%
#ifdef FAILSAFE_ENABLE
if(failsafe_count==1)
{ // first failsafe packet
packet[3]=0x40;
uint16_t fs=Failsafe_data[(i-4)>>1];
packet[3] |= 0x40;
uint16_t fs=Failsafe_data[ch];
if( fs == FAILSAFE_CHANNEL_HOLD || fs == FAILSAFE_CHANNEL_NOPULSES)
val|=0x8000; // channel hold flag
else
@@ -209,7 +216,7 @@ static void __attribute__((unused)) HOTT_data_packet()
}
else if(failsafe_count==2)
{ // second failsafe packet=timing?
packet[3]=0x50;
packet[3] |= 0x50;
if(i==4)
val=2;
else
@@ -219,39 +226,47 @@ static void __attribute__((unused)) HOTT_data_packet()
packet[i] = val;
packet[i+1] = val>>8;
}
upper ^= 0x01; // toggle between CH9..CH12 and CH13..16
#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
if(IS_BIND_DONE)
{
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
if(sub_protocol == HOTT_SYNC)
packet[29] = ((HOTT_sensor_seq+1)<<3) | 2; // Telemetry packet sequence
else
packet[28] = HoTT_SerialRX_val | 0x0F; // no button pressed
packet[29] = 0x01; // 0x01->Text config menu
packet[29] = 0x02;
//debugln("28=%02X,29=%02X",packet[28],packet[29]);
}
}
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
{
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
}
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
CC2500_WriteReg(CC2500_06_PKTLEN, 0x32);
CC2500_WriteData(packet, HOTT_TX_PACKET_LEN);
CC2500_WriteReg(CC2500_06_PKTLEN, HOTT_TX_PACKET_LEN);
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, 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++)
@@ -265,10 +280,6 @@ static void __attribute__((unused)) HOTT_data_packet()
uint16_t ReadHOTT()
{
#ifdef HOTT_FW_TELEMETRY
static uint8_t pps_counter=0;
#endif
switch(phase)
{
case HOTT_START:
@@ -285,28 +296,72 @@ uint16_t ReadHOTT()
hopping_frequency_no = 0;
rf_ch_num=hopping_frequency[hopping_frequency_no];
counter = 0;
CC2500_SetTxRxMode(RX_EN);
phase = HOTT_DATA1;
}
return 2000;
/* Work cycle: 10ms */
case HOTT_DATA1:
//TX
//Set RF freq, setup LBT and prep packet
#ifdef MULTI_SYNC
telemetry_set_input_sync(HOTT_PACKET_PERIOD);
#endif
//Clear all
CC2500_Strobe(CC2500_SIDLE);
CC2500_Strobe(CC2500_SNOP);
CC2500_Strobe(CC2500_SFTX);
CC2500_Strobe(CC2500_SFRX);
CC2500_WriteReg(CC2500_04_SYNC1, 0xD3);
CC2500_WriteReg(CC2500_05_SYNC0, 0x91);
//Set RF freq
HOTT_tune_freq();
HOTT_tune_chan_fast();
HOTT_data_packet();
phase = HOTT_RX1;
return 4500;
//Setup LBT
CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xFF);
CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x0C);
CC2500_Strobe(CC2500_SRX);
//Prep packet
HOTT_prep_data_packet();
//Listen
CC2500_WriteReg(CC2500_17_MCSM1, 0x10); //??
CC2500_WriteReg(CC2500_18_MCSM0, 0x18); //??
CC2500_Strobe(CC2500_SRX); //??
phase++; //HOTT_DATA2
return 1095;
case HOTT_DATA2:
//LBT
if((CC2500_ReadReg(CC2500_38_PKTSTATUS | CC2500_READ_BURST)&0x10)==0)
{ //Channel is busy
LBT_POWER_on; // Reduce to low power before transmitting
debugln("Busy %d",rf_ch_num);
}
CC2500_WriteReg(CC2500_17_MCSM1, 0x00); //??
CC2500_WriteReg(CC2500_18_MCSM0, 0x08); //??
CC2500_SetPower();
//Send packet
CC2500_SetTxRxMode(TX_EN);
CC2500_Strobe(CC2500_STX);
phase++; //HOTT_RX1
return 3880;
case HOTT_RX1:
//Clear all
CC2500_Strobe(CC2500_SIDLE);
CC2500_Strobe(CC2500_SFTX);
CC2500_Strobe(CC2500_SFRX);
//RX
if(packet[29] & 0xF8)
{// binary telemetry
CC2500_WriteReg(CC2500_04_SYNC1, 0x2C);
CC2500_WriteReg(CC2500_05_SYNC0, 0x6E);
}
CC2500_SetTxRxMode(RX_EN);
CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xC7);
CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x09);
CC2500_WriteReg(CC2500_06_PKTLEN, HOTT_RX_PACKET_LEN);
CC2500_Strobe(CC2500_SRX);
phase = HOTT_RX2;
return 4500;
phase++; //HOTT_RX2
return 4025;
case HOTT_RX2:
//Telemetry
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
@@ -317,11 +372,15 @@ uint16_t ReadHOTT()
{ // CRC OK and TX ID matches
if(IS_BIND_IN_PROGRESS)
{
//GR-16: D4 20 F2 E6 F6 31 BD 01 00 90 00 FF 03 00 9E 1B 00 00 00 00 00 00
//GR-12L: D4 20 F2 E6 F6 6E EE 01 00 B1 00 FF 03 00 0E 08 10 00 02 00 00 00
//Vector: D4 20 F2 E6 F6 00 00 3A 01 A1 00 00 1A 24 35 1A 00 24 00 00 00 1A
// -----TXID----- -----RXID----- ---------------Unknown-------------
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;
uint16_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;
@@ -341,7 +400,7 @@ uint16_t ReadHOTT()
// 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 [18,19] = [19]<<8+[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
@@ -355,33 +414,7 @@ uint16_t ReadHOTT()
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
if(packet[29]==1)
{ //Text mode
HOTT_sensor_pages = 0;
HOTT_sensor_valid = false;
@@ -390,6 +423,41 @@ uint16_t ReadHOTT()
for(uint8_t i=0; i<HOTT_SENSOR_TYPE;i++)
packet_in[12] |= HOTT_sensor_ok[i]<<i; // Send detected sensors
}
else
{ //Binary sensor
HOTT_sensor_seq++; // Increment RX sequence counter
HOTT_sensor_seq %= 5; // 5 pages in binary mode per sensor
if(state==0 && HOTT_sensor_ok[0]==false && HOTT_sensor_ok[1]==false && HOTT_sensor_ok[2]==false && HOTT_sensor_ok[3]==false && HOTT_sensor_ok[4]==false && HOTT_sensor_ok[5]==false)
HOTT_sensor_seq=0; // No sensors always ask page 0
if(state)
state--;
if( packet_in[11]==1 ) // Page 1
{
if( packet_in[12] == (HOTT_sensor_cur+9)<<4 )
{ //Requested sensor is sending: 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[(packet_in[12]>>4)-9]=true;
}
else
{
HOTT_sensor_valid = false;
HOTT_sensor_pages = 0x1E; // Switch to next sensor
}
}
if(packet_in[11])
{ //Page != 0
if(HOTT_sensor_valid) // Valid
{
packet_in[10] = HOTT_sensor_cur+9; // Mark telem with sensor ID
HOTT_sensor_pages |= 1<<packet_in[11]; // Page received
}
else
send_telem=false; // Do not send
}
else
packet_in[10]=0; // Mark telem with sensor 0=RX
}
debug("T%d=",send_telem);
for(uint8_t i=10;i < HOTT_RX_PACKET_LEN; i++)
{
@@ -400,9 +468,7 @@ uint16_t ReadHOTT()
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;
{ //Next sensor
uint8_t loop=0;
do
{
@@ -410,8 +476,11 @@ uint16_t ReadHOTT()
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));
while(HOTT_sensor_ok[HOTT_sensor_cur]==false && loop<HOTT_SENSOR_TYPE+1 && state==0);
HOTT_sensor_valid=false;
HOTT_sensor_pages=0;
HOTT_sensor_seq=0;
debugln("Sensor:%02X",HOTT_sensor_cur+9);
}
}
pps_counter++;
@@ -425,16 +494,16 @@ uint16_t ReadHOTT()
TX_LQI=pps_counter;
if(pps_counter==0)
{ // lost connection with RX, power cycle? research sensors again.
HOTT_sensor_cur=0;
HOTT_sensor_cur=3;
HOTT_sensor_seq=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;
state=HOTT_SENSOR_SEARCH_PERIOD;
}
pps_counter=packet_count=0;
}
#endif
CC2500_Strobe(CC2500_SFRX); //Flush the RXFIFO
phase=HOTT_DATA1;
return 1000;
}
@@ -449,13 +518,14 @@ uint16_t initHOTT()
#ifdef HOTT_FW_TELEMETRY
HoTT_SerialRX_val=0;
HoTT_SerialRX=false;
HOTT_sensor_cur=0;
HOTT_sensor_cur=3;
HOTT_sensor_pages=0;
HOTT_sensor_valid=false;
HOTT_sensor_seq=0;
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;
state=HOTT_SENSOR_SEARCH_PERIOD;
#endif
phase = HOTT_START;
return 10000;

View File

@@ -14,16 +14,16 @@
*/
// Compatible with FZ-410 TX
#if defined(FLYZONE_A7105_INO)
#if defined(HEIGHT_A7105_INO)
#include "iface_a7105.h"
//#define FLYZONE_FORCEID
//#define HEIGHT_FORCEID
#define FLYZONE_BIND_COUNT 220 // 5 sec
#define FLYZONE_BIND_CH 0x18 // TX, RX for bind end is 0x17
#define HEIGHT_BIND_COUNT 220 // 5 sec
#define HEIGHT_BIND_CH 0x18 // TX, RX for bind end is 0x17
static void __attribute__((unused)) flyzone_build_packet()
static void __attribute__((unused)) HEIGHT_build_packet()
{
packet[0] = 0xA5;
packet[1] = rx_tx_addr[2];
@@ -33,11 +33,17 @@ static void __attribute__((unused)) flyzone_build_packet()
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
if(sub_protocol == HEIGHT_8CH)
{
packet[8] = convert_channel_8b(CH6); //00..80..FF
packet[9] = convert_channel_8b(CH7); //00..80..FF
packet[10] = convert_channel_8b(CH8); //00..80..FF
}
}
uint16_t ReadFlyzone()
uint16_t ReadHeight()
{
#ifndef FORCE_FLYZONE_TUNING
#ifndef FORCE_HEIGHT_TUNING
A7105_AdjustLOBaseFreq(1);
#endif
if(IS_BIND_IN_PROGRESS)
@@ -45,7 +51,7 @@ uint16_t ReadFlyzone()
packet[0] = 0x1B;
packet[1] = rx_tx_addr[2];
packet[2] = rx_tx_addr[3];
A7105_WriteData(3, FLYZONE_BIND_CH);
A7105_WriteData(3, HEIGHT_BIND_CH);
if (bind_counter--==0)
BIND_DONE;
return 22700;
@@ -58,8 +64,8 @@ uint16_t ReadFlyzone()
#ifdef MULTI_SYNC
telemetry_set_input_sync(20*1500);
#endif
flyzone_build_packet();
A7105_WriteData(8, hopping_frequency[0]);
HEIGHT_build_packet();
A7105_WriteData(sub_protocol?11:8, hopping_frequency[0]);
A7105_SetPower();
}
else
@@ -72,14 +78,14 @@ uint16_t ReadFlyzone()
return 1500;
}
uint16_t initFlyzone()
uint16_t initHeight()
{
A7105_Init();
hopping_frequency[0]=((random(0xfefefefe) & 0x0F)+2)<<2;
hopping_frequency[1]=hopping_frequency[0]+0x50;
#ifdef FLYZONE_FORCEID
#ifdef HEIGHT_FORCEID
rx_tx_addr[2]=0x35;
rx_tx_addr[3]=0xD0;
hopping_frequency[0]=0x18;
@@ -87,7 +93,7 @@ uint16_t initFlyzone()
#endif
phase=255;
bind_counter = FLYZONE_BIND_COUNT;
bind_counter = HEIGHT_BIND_COUNT;
return 2400;
}
#endif

View File

@@ -165,7 +165,7 @@ static void __attribute__((unused)) HITEC_build_packet()
packet[0] = 0x1A; // 26 bytes to follow
for(uint8_t i=0;i<9;i++)
{
uint16_t ch = convert_channel_16b_nolimit(i,0x1B87,0x3905);
uint16_t ch = convert_channel_16b_nolimit(i,0x1B87,0x3905,false);
packet[4+2*i] = ch >> 8;
packet[5+2*i] = ch & 0xFF;
}

View File

@@ -38,7 +38,7 @@ enum{
#define HONTAI_POLY 0x8408
static void __attribute__((unused)) crc16(uint8_t *data_p, uint8_t length)
{
uint16_t crc = 0xffff;
crc = 0xffff;
length -= 2;
do

View File

@@ -59,7 +59,7 @@ static void __attribute__((unused)) j6pro_build_data_packet()
packet[0] = 0xaa; //FIXME what is this?
for (i = 0; i < 12; i++)
{
value = convert_channel_10b(CH_AETR[i]);
value = convert_channel_10b(CH_AETR[i], false);
packet[i+1] = value & 0xff;
upperbits |= (value >> 8) << (i * 2);
}
@@ -111,8 +111,8 @@ static void __attribute__((unused)) cyrf_datainit()
{
/* Use when already bound */
uint8_t sop_idx = (0xff & (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + cyrfmfg_id[3] - cyrfmfg_id[5])) % 19;
uint16_t crc = (0xff & (cyrfmfg_id[1] - cyrfmfg_id[4] + cyrfmfg_id[5])) |
((0xff & (cyrfmfg_id[2] + cyrfmfg_id[3] - cyrfmfg_id[4] + cyrfmfg_id[5])) << 8);
crc = (0xff & (cyrfmfg_id[1] - cyrfmfg_id[4] + cyrfmfg_id[5])) |
((0xff & (cyrfmfg_id[2] + cyrfmfg_id[3] - cyrfmfg_id[4] + cyrfmfg_id[5])) << 8);
//CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24);
CYRF_PROGMEM_ConfigSOPCode(DEVO_j6pro_sopcodes[sop_idx]);
CYRF_ConfigCRCSeed(crc);

View File

@@ -24,6 +24,7 @@
#define JJRC345_INITIAL_WAIT 500
#define JJRC345_PACKET_SIZE 16
#define JJRC345_RF_BIND_CHANNEL 5
#define SKYTMBLR_RF_BIND_CHANNEL 40
#define JJRC345_BIND_COUNT 500
#define JJRC345_NUM_CHANNELS 4
@@ -32,6 +33,12 @@ enum JJRC345_FLAGS {
// flags going to packet[8]
JJRC345_FLAG_HEADLESS = 0x40,
JJRC345_FLAG_RTH = 0x80,
// flags going to packet[9]
SKYTMBLR_FLAG_UNK1 = 0x40,
SKYTMBLR_FLAG_UNK2 = 0x80,
// flags going to packet[10]
SKYTMBLR_FLAG_LED = 0x40,
SKYTMBLR_FLAG_UNK3 = 0x80,
};
static uint8_t __attribute__((unused)) JJRC345_convert_channel(uint8_t num)
@@ -55,7 +62,7 @@ static void __attribute__((unused)) JJRC345_send_packet()
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[1] = (sub_protocol == JJRC345 ? JJRC345_RF_BIND_CHANNEL:SKYTMBLR_RF_BIND_CHANNEL);
packet[4] = hopping_frequency[0];
packet[5] = hopping_frequency[1];
packet[6] = hopping_frequency[2];
@@ -92,10 +99,14 @@ static void __attribute__((unused)) JJRC345_send_packet()
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
| GET_FLAG(CH6_SW ,JJRC345_FLAG_HEADLESS) // 0x40 HeadLess
| GET_FLAG(CH7_SW ,JJRC345_FLAG_RTH); // 0x80 RTH
packet[9] = 0x00 // Elevator trim, 00 when not used, 20..25 when trimmed up, 0..1F when trimmed down
| GET_FLAG(CH9_SW ,SKYTMBLR_FLAG_UNK1) // 0x40 Unknown
| GET_FLAG(CH10_SW,SKYTMBLR_FLAG_UNK2); // 0x80 Unknown
packet[10] = 0x00 // Aileron trim, 00 when not used, 00..1F when trimmed left, 21..3F when trimmed right
| GET_FLAG(!CH8_SW,SKYTMBLR_FLAG_LED) // 0x40 LED
| GET_FLAG(CH11_SW,SKYTMBLR_FLAG_UNK3); // 0x80 Unknown
packet[11] = hopping_frequency[0]; // First hopping frequency
@@ -124,7 +135,7 @@ 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_WriteReg(NRF24L01_05_RF_CH, sub_protocol == JJRC345 ? JJRC345_RF_BIND_CHANNEL:SKYTMBLR_RF_BIND_CHANNEL); // Bind channel
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
@@ -152,7 +163,7 @@ uint16_t JJRC345_callback()
static void __attribute__((unused)) JJRC345_initialize_txid()
{
calc_fh_channels(4);
calc_fh_channels(JJRC345_NUM_CHANNELS);
#ifdef JJRC345_FORCE_ID
//TX 1

View File

@@ -125,16 +125,16 @@ static void __attribute__((unused)) kn_bind_init()
static void __attribute__((unused)) kn_update_packet_control_data()
{
uint16_t value;
value = convert_channel_10b(THROTTLE);
value = convert_channel_10b(THROTTLE, false);
packet[0] = (value >> 8) & 0xFF;
packet[1] = value & 0xFF;
value = convert_channel_10b(AILERON);
value = convert_channel_10b(AILERON, false);
packet[2] = (value >> 8) & 0xFF;
packet[3] = value & 0xFF;
value = convert_channel_10b(ELEVATOR);
value = convert_channel_10b(ELEVATOR, false);
packet[4] = (value >> 8) & 0xFF;
packet[5] = value & 0xFF;
value = convert_channel_10b(RUDDER);
value = convert_channel_10b(RUDDER, false);
packet[6] = (value >> 8) & 0xFF;
packet[7] = value & 0xFF;
// Trims, middle is 0x64 (100) range 0-200

View File

@@ -0,0 +1,202 @@
/*
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(KYOSHO_A7105_INO)
#include "iface_a7105.h"
//#define KYOSHO_FORCE_ID_FHSS
//#define KYOSHO_FORCE_ID_HYPE
//Kyosho constants & variables
#define KYOSHO_BIND_COUNT 2500
static void __attribute__((unused)) kyosho_send_packet()
{
//ID
packet[1] = rx_tx_addr[0];
packet[2] = rx_tx_addr[1];
packet[3] = rx_tx_addr[2];
packet[4] = rx_tx_addr[3];
//unknown may be RX ID on some other remotes
memset(packet+5,0xFF,4);
if(IS_BIND_IN_PROGRESS)
{
packet[ 0] = 0xBC; // bind indicator
packet[ 9] &= 0x01;
packet[ 9] ^= 0x01; // high/ low part of the RF table
packet[10] = 0x00;
//RF table
for(uint8_t i=0; i<16;i++)
packet[i+11]=hopping_frequency[i+(packet[9]<<4)];
//unknwon
packet[27] = 0x05;
packet[28] = 0x00;
memset(packet+29,0xFF,8);
//frequency hop during bind
if(packet[9])
rf_ch_num=0x8C;
else
rf_ch_num=0x0D;
}
else
{
packet[ 0] = 0x58; // normal packet
//14 channels: steering, throttle, ...
for(uint8_t i = 0; i < 14; i++)
{
uint16_t temp=convert_channel_ppm(i);
packet[9 + i*2]=temp&0xFF; // low byte of servo timing(1000-2000us)
packet[10 + i*2]=(temp>>8)&0xFF; // high byte of servo timing(1000-2000us)
}
rf_ch_num=hopping_frequency[hopping_frequency_no];
hopping_frequency_no++;
packet[34] |= (hopping_frequency_no&0x0F)<<4;
packet[36] |= (hopping_frequency_no&0xF0); // last byte is ending with F on the dumps so let's see
hopping_frequency_no &= 0x1F;
}
#if 0
debug("ch=%02X P=",rf_ch_num);
for(uint8_t i=0; i<37; i++)
debug("%02X ", packet[i]);
debugln("");
#endif
A7105_WriteData(37, rf_ch_num);
}
static void __attribute__((unused)) kyosho_hype_send_packet()
{
if(IS_BIND_IN_PROGRESS)
{
if(packet_sent==0)
{//build the packet and send it
packet[0] = rx_tx_addr[1];
packet[1] = rx_tx_addr[3];
//RF table
for(uint8_t i=0; i<15;i++)
packet[i+2]=hopping_frequency[i];
A7105_WriteData(17, 0x01);
packet_sent++;
packet_period=1421;
#if 0
debug("ch=01 P=");
for(uint8_t i=0; i<17; i++)
debug("%02X ", packet[i]);
debugln("");
#endif
}
else
A7105_Strobe(A7105_TX); //only send
}
else
{
//original TX is only refreshing the packet every 20ms and keep repeating the same packet in between (STROBE_TX)
//build packet=6 channels with order AETR
for(uint8_t i=0;i<6;i++)
packet[i] = convert_channel_8b(CH_AETR[i]);
//set RF channel
rf_ch_num=hopping_frequency[hopping_frequency_no];
hopping_frequency_no++;
if(hopping_frequency_no>14)
hopping_frequency_no = 0;
//send it
A7105_WriteData(6, rf_ch_num);
packet_period=931; //packet period fluctuates a lot on the original TX from one packet to the other but stable if looking over a period of 40ms
#if 0
debug("ch=%02X P=",rf_ch_num);
for(uint8_t i=0; i<6; i++)
debug("%02X ", packet[i]);
debugln("");
#endif
}
}
uint16_t ReadKyosho()
{
#ifndef FORCE_KYOSHO_TUNING
A7105_AdjustLOBaseFreq(1);
#endif
if(IS_BIND_IN_PROGRESS)
{
bind_counter--;
if (bind_counter==0)
{
BIND_DONE;
if(sub_protocol==KYOSHO_HYPE)
{
A7105_WriteID(MProtocol_id);
A7105_WriteReg(A7105_03_FIFOI,0x05);
}
}
}
else
{
if(hopping_frequency_no==0)
A7105_SetPower();
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
}
if(sub_protocol==KYOSHO_FHSS)
kyosho_send_packet();
else//HYPE
kyosho_hype_send_packet();
return packet_period;
}
uint16_t initKyosho()
{
A7105_Init();
// compute channels from ID
calc_fh_channels(sub_protocol==KYOSHO_FHSS?32:15);
hopping_frequency_no=0;
#ifdef KYOSHO_FORCE_ID_FHSS
if(sub_protocol==KYOSHO_FHSS)
{
memcpy(rx_tx_addr,"\x3A\x39\x37\x00",4);
memcpy(hopping_frequency,"\x29\x4C\x67\x92\x31\x1C\x77\x18\x23\x6E\x81\x5C\x8F\x5A\x51\x94\x7A\x12\x45\x6C\x7F\x1E\x0D\x88\x63\x8C\x4F\x37\x26\x61\x2C\x8A",32);
}
#endif
if(sub_protocol==KYOSHO_HYPE)
{
MProtocol_id &= 0x00FF00FF;
rx_tx_addr[0] = 0xAF - (rx_tx_addr[1]&0x0F);
rx_tx_addr[2] = 0xFF - rx_tx_addr[3];
MProtocol_id |= (rx_tx_addr[0]<<24) + (rx_tx_addr[2]<<8);
#ifdef KYOSHO_FORCE_ID_HYPE
MProtocol_id=0xAF90738C;
set_rx_tx_addr(MProtocol_id);
memcpy(hopping_frequency,"\x27\x1B\x63\x75\x03\x39\x57\x69\x87\x0F\x7B\x3F\x33\x51\x6F",15);
#endif
if(IS_BIND_IN_PROGRESS)
A7105_WriteID(0xAF00FF00);
else
{
A7105_WriteID(MProtocol_id);
A7105_WriteReg(A7105_03_FIFOI,0x05);
}
}
if(IS_BIND_IN_PROGRESS)
bind_counter = KYOSHO_BIND_COUNT;
packet_sent=0;
packet_period=3852; //FHSS
return 2000;
}
#endif

View File

@@ -0,0 +1,314 @@
/*
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(LOLI_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define LOLI_BIND_CHANNEL 33
#define LOLI_PACKET_SIZE 11
#define LOLI_NUM_CHANNELS 5
static void __attribute__((unused)) LOLI_init()
{
NRF24L01_Initialize();
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, 0x03); // 5-bytes RX/TX address
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"LOVE!", 5);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"LOVE!", 5);
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // No retransmits
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, LOLI_PACKET_SIZE); // RX FIFO size
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
NRF24L01_SetPower();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_SetTxRxMode(TX_EN);
}
// flags going to packet[1] for packet type 0xa2 (Rx config)
#define LOLI_FLAG_PWM7 0x02
#define LOLI_FLAG_PWM2 0x04
#define LOLI_FLAG_PWM1 0x08
#define LOLI_FLAG_SBUS 0x40
#define LOLI_FLAG_PPM 0x80
// flags going to packet[2] for packet type 0xa2 (Rx config)
#define LOLI_FLAG_SW8 0x01
#define LOLI_FLAG_SW7 0x02
#define LOLI_FLAG_SW6 0x04
#define LOLI_FLAG_SW5 0x08
#define LOLI_FLAG_SW4 0x10
#define LOLI_FLAG_SW3 0x20
#define LOLI_FLAG_SW2 0x40
#define LOLI_FLAG_SW1 0x80
#ifdef LOLI_NRF24L01_INO
uint8_t LOLI_P1, LOLI_P2;
#endif
static void __attribute__((unused)) LOLI_send_packet()
{
if(IS_BIND_IN_PROGRESS)
{
packet[0] = 0xa0;
memcpy(&packet[1], hopping_frequency, LOLI_NUM_CHANNELS);
memcpy(&packet[6], rx_tx_addr, 5);
rf_ch_num = LOLI_BIND_CHANNEL;
}
else
{
//Check RX config
uint8_t P1=0;
uint8_t P2=0;
//ch1: PWM/PPM
if(Channel_data[CH1+8] > CHANNEL_MAX_COMMAND)
P1|=LOLI_FLAG_PWM1;
else if(Channel_data[CH1+8] > CHANNEL_SWITCH)
P1|=LOLI_FLAG_PPM;
//ch2: PWM
if(Channel_data[CH2+8] > CHANNEL_MAX_COMMAND)
P1|=LOLI_FLAG_PWM2;
//ch5: SBUS
if(Channel_data[CH5+8] > CHANNEL_SWITCH)
P1|=LOLI_FLAG_SBUS;
//ch7: PWM
if(Channel_data[CH7+8] > CHANNEL_MAX_COMMAND)
P1|=LOLI_FLAG_PWM7;
//switches
for(uint8_t i=0;i<8;i++)
if(Channel_data[i+8]<CHANNEL_MIN_COMMAND)
P2 |= 1 << (7-i);
if(LOLI_P1!=P1 || LOLI_P2!=P2)
flags=10;
if(flags)
{// Send RX config since P1 or P2 have changed
LOLI_P1=P1;LOLI_P2=P2;
packet[0] = 0xa2;
packet[1] = LOLI_P1; // CH1:LOLI_FLAG_PPM || LOLI_FLAG_PWM1, CH2:LOLI_FLAG_PWM2, CH5:LOLI_FLAG_SBUS, CH7:LOLI_FLAG_PWM7
packet[2] = LOLI_P2; // CHx switch bit(8-x)=1
flags--;
}
else
{// Normal packet
#ifdef FAILSAFE_ENABLE
packet[0] = IS_FAILSAFE_VALUES_on ? 0xa0 : 0xa1;
#else
packet[0] = 0xa1;
#endif
//Build channels
uint8_t ch=0, offset=1;
uint16_t val;
for(uint8_t i=0;i<2;i++)
{
val = convert_channel_10b(ch++, IS_FAILSAFE_VALUES_on);
packet[offset++] = val >> 2;
packet[offset ] = val << 6;
val = convert_channel_10b(ch++, IS_FAILSAFE_VALUES_on);
packet[offset++]|= val >> 4;
packet[offset ] = val << 4;
val = convert_channel_10b(ch++, IS_FAILSAFE_VALUES_on);
packet[offset++]|= val >> 6;
packet[offset ] = val << 2;
val = convert_channel_10b(ch++, IS_FAILSAFE_VALUES_on);
packet[offset++]|= val >> 8;
packet[offset++] = val & 0xff;
}
FAILSAFE_VALUES_off; // Failsafe values are sent if they were available
}
if (++hopping_frequency_no > LOLI_NUM_CHANNELS-1)
hopping_frequency_no = 0;
rf_ch_num = hopping_frequency[hopping_frequency_no];
}
#if 0
debug("P(%02X):",rf_ch_num);
for(uint8_t i=0; i<LOLI_PACKET_SIZE; i++)
debug(" %02X",packet[i]);
debugln("");
#endif
//Send packet
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch_num);
NRF24L01_SetPower();
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0a); // 8bit CRC, TX
NRF24L01_FlushTx();
NRF24L01_WritePayload(packet, LOLI_PACKET_SIZE);
}
enum{
LOLI_BIND1,
LOLI_BIND2,
LOLI_BIND3,
LOLI_PREP_DATA,
LOLI_DATA1,
LOLI_DATA2,
LOLI_SET_RX_CONFIG,
LOLI_SET_FAILSAFE
};
#define LOLI_WRITE_TIME 1000
uint16_t LOLI_callback()
{
switch (phase)
{
case LOLI_BIND1:
if(bind_counter)
{
bind_counter--;
if(bind_counter==0)
{
phase=LOLI_PREP_DATA;
break;
}
}
// send bind packet
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0a); // 8bit CRC, TX
LOLI_send_packet();
phase++;
return 2000;
case LOLI_BIND2:
// switch to RX mode
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();
NRF24L01_SetTxRxMode(RX_EN);
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x3b); // 8bit CRC, RX
phase++;
packet_count = 0;
return 2000;
case LOLI_BIND3:
// got bind response ?
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{
NRF24L01_ReadPayload(packet, LOLI_PACKET_SIZE);
if (packet[0] == 'O' && packet[1] == 'K')
{
debugln("Bind OK");
phase++; // LOLI_PREP_DATA
break;
}
}
packet_count++;
if (packet_count > 50)
phase = LOLI_BIND1;
return 1000;
case LOLI_PREP_DATA:
BIND_DONE;
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushRx();
packet_count = 0;
//defaut RX config with servo outputs
LOLI_P1=0;LOLI_P2=0;flags=10;
phase++;
case LOLI_DATA1:
#ifdef LOLI_HUB_TELEMETRY
// Check telemetry
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // RX fifo data ready
NRF24L01_ReadPayload(packet, LOLI_PACKET_SIZE);
#if 0
debug("T:");
for(uint8_t i=0; i<LOLI_PACKET_SIZE; i++)
debug(" %02X",packet[i]);
debugln("");
#endif
RX_RSSI = packet[0]<<1;
uint16_t val=((packet[1] << 8) | packet[2])/10;
if(val > 255) val=255;
v_lipo1 = val;
val=((packet[3] << 8) | packet[4])/10;
if(val > 255) val=255;
v_lipo2 = val;
telemetry_link = 1;
telemetry_counter++; // TX LQI counter
if(telemetry_lost)
{
telemetry_lost = 0;
packet_count = 100;
telemetry_counter = 100;
}
}
//LQI
packet_count++;
if(packet_count>=100)
{
packet_count=0;
TX_LQI=telemetry_counter;
if(telemetry_counter==0)
telemetry_lost = 1;
telemetry_counter = 0;
}
#endif
// Send data packet
LOLI_send_packet();
#ifdef LOLI_HUB_TELEMETRY
phase ++;
return LOLI_WRITE_TIME;
case LOLI_DATA2:
// Wait for packet to be sent
while( (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)) == 0);
// Switch to RX mode
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();
NRF24L01_SetTxRxMode(RX_EN);
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x3b); // 8bit CRC, RX
phase = LOLI_DATA1;
return 20000 - LOLI_WRITE_TIME;
#else
break;
#endif
}
return 20000;
}
uint16_t initLOLI()
{
rx_tx_addr[1] %= 0x30;
calc_fh_channels(LOLI_NUM_CHANNELS);
for (uint8_t i=0; i < LOLI_NUM_CHANNELS; i++)
if (hopping_frequency[i] == LOLI_BIND_CHANNEL)
hopping_frequency[i]++;
if (IS_BIND_IN_PROGRESS)
{
bind_counter=250;
phase = LOLI_BIND1;
}
else
phase = LOLI_PREP_DATA;
LOLI_init();
return 500;
}
#endif

View File

@@ -0,0 +1,513 @@
/*
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(MLINK_CYRF6936_INO)
#include "iface_cyrf6936.h"
#undef MLINK_HUB_TELEMETRY
#define MLINK_FORCE_ID
#define MLINK_BIND_COUNT 696 // around 20s
#define MLINK_NUM_FREQ 78
#define MLINK_BIND_CHANNEL 0x01
#define MLINK_PACKET_SIZE 8
enum {
MLINK_BIND_TX=0,
MLINK_BIND_PREP_RX,
MLINK_BIND_RX,
MLINK_PREP_DATA,
MLINK_SEND1,
MLINK_CHECK1,
MLINK_SEND2,
MLINK_CHECK2,
MLINK_SEND3,
MLINK_CHECK3,
MLINK_RX,
MLINK_CHECK4,
};
uint8_t MLINK_Data_Code[16], MLINK_CRC_Init, MLINK_Unk_6_2;
const uint8_t PROGMEM MLINK_init_vals[][2] = {
//Init from dump
{ CYRF_01_TX_LENGTH, 0x08 }, // Length of packet
{ CYRF_02_TX_CTRL, 0x40 }, // Clear TX Buffer
{ CYRF_03_TX_CFG, 0x3C }, //0x3E in normal mode, 0x3C in bind mode: SDR 64 chip codes (=8 bytes data code used)
{ CYRF_05_RX_CTRL, 0x00 },
{ CYRF_06_RX_CFG, 0x93 }, // AGC enabled, overwrite enable, valid flag enable
{ CYRF_0B_PWR_CTRL, 0x00 },
//{ CYRF_0C_XTAL_CTRL, 0x00 }, // Set to GPIO on reset
//{ CYRF_0D_IO_CFG, 0x00 }, // Set to GPIO on reset
//{ CYRF_0E_GPIO_CTRL, 0x00 }, // Set by the CYRF_SetTxRxMode function
{ CYRF_0F_XACT_CFG, 0x04 }, // end state idle
{ CYRF_10_FRAMING_CFG, 0x00 }, // SOP disabled
{ CYRF_11_DATA32_THOLD, 0x05 }, // not used???
{ CYRF_12_DATA64_THOLD, 0x0F }, // 64 Chip Data PN Code Correlator Threshold
{ CYRF_14_EOP_CTRL, 0x05 }, // 5 consecutive noncorrelations symbol for EOP
{ CYRF_15_CRC_SEED_LSB, 0x00 }, // not used???
{ CYRF_16_CRC_SEED_MSB, 0x00 }, // not used???
{ CYRF_1B_TX_OFFSET_LSB,0x00 },
{ CYRF_1C_TX_OFFSET_MSB,0x00 },
{ CYRF_1D_MODE_OVERRIDE,0x00 },
{ CYRF_1E_RX_OVERRIDE, 0x14 }, // RX CRC16 is disabled and Force Receive Data Rate
{ CYRF_1F_TX_OVERRIDE, 0x04 }, // TX CRC16 is disabled
{ CYRF_26_XTAL_CFG, 0x08 },
{ CYRF_29_RX_ABORT, 0x00 },
{ CYRF_32_AUTO_CAL_TIME,0x3C },
{ CYRF_35_AUTOCAL_OFFSET,0x14 },
{ CYRF_39_ANALOG_CTRL, 0x03 }, // Receive invert and all slow
};
static void __attribute__((unused)) MLINK_cyrf_config()
{
for(uint8_t i = 0; i < sizeof(MLINK_init_vals) / 2; i++)
CYRF_WriteRegister(pgm_read_byte_near(&MLINK_init_vals[i][0]), pgm_read_byte_near(&MLINK_init_vals[i][1]));
CYRF_WritePreamble(0x333304);
CYRF_SetTxRxMode(TX_EN);
}
static void __attribute__((unused)) MLINK_send_bind_data_packet()
{
uint8_t p_c=packet_count>>1;
memset(packet, p_c<0x16?0x00:0xFF, MLINK_PACKET_SIZE-1);
packet[0]=0x0F; // bind
packet[1]=p_c;
switch(p_c)
{
case 0x00:
packet[2]=0x40; //unknown but seems constant
packet[4]=0x01; //unknown but seems constant
packet[5]=0x03; //unknown but seems constant
packet[6]=0xE3; //unknown but seems constant
break;
case 0x05:
packet[6]=MLINK_CRC_Init; //CRC init value
break;
case 0x06:
packet[2]=MLINK_Unk_6_2; //unknown and different
//Start of hopping frequencies
for(uint8_t i=0;i<4;i++)
packet[i+3]=hopping_frequency[i];
break;
case 0x15:
packet[6]=0x51; //unknown but seems constant
break;
case 0x16:
packet[2]=0x51; //unknown but seems constant
packet[3]=0xEC; //unknown but seems constant
packet[4]=0x05; //unknown but seems constant
break;
case 0x1A:
packet[1]=0xFF;
memset(&packet[2],0x00,5);
break;
}
if(p_c>=0x01 && p_c<=0x04)
{//DATA_CODE
uint8_t p_c_5=(p_c-1)*5;
for(uint8_t i=0;i<5;i++)
if(i+p_c_5<16)
packet[i+2]=MLINK_Data_Code[i+p_c_5];
}
else
if(p_c>=0x07 && p_c<=0x15)
{//Hopping frequencies
uint8_t p_c_5=5*(p_c-6)-1;
for(uint8_t i=0;i<5;i++)
if(i+p_c_5<MLINK_NUM_FREQ)
packet[i+2]=hopping_frequency[i+p_c_5];
}
else
if(p_c>0x19)
{
packet[1]=0xFF;
memset(&packet[2], 0x00, MLINK_PACKET_SIZE-3);
}
//Calculate CRC
crc8=0xFF; // Init = 0xFF
for(uint8_t i=0;i<MLINK_PACKET_SIZE-1;i++)
crc8_update(bit_reverse(packet[i]));
packet[7] = bit_reverse(crc8); // CRC reflected out
//Debug
#if 1
debug("P(%02d):",p_c);
for(uint8_t i=0;i<8;i++)
debug(" %02X",packet[i]);
debugln("");
#endif
//Send packet
CYRF_WriteDataPacketLen(packet, MLINK_PACKET_SIZE);
}
static void __attribute__((unused)) MLINK_build_data_packet()
{
static uint8_t tog=0;
if(hopping_frequency_no==0)
tog=1;
//Channels to be sent
if(phase==MLINK_SEND1 || ((hopping_frequency_no%5==0) && (phase==MLINK_SEND2)))
{
if((hopping_frequency_no&1)==0)
packet[0] = 0x09; //10,8,6
else
packet[0] = 0x01; //11,9,7
}
else
if(phase==MLINK_SEND2)
{
if(tog)
packet[0] = 0x02; //x,15,13
else
packet[0] = 0x0A; //x,14,12
tog^=1;
}
else
{//phase==MLINK_SEND3
if((hopping_frequency_no&1)==0)
packet[0] = 0x88; //4,2,0
else
packet[0] = 0x80; //5,3,1
}
//Start channel
uint8_t ch=4+6*(packet[0]&3);
if((packet[0]&0x08)==0)
ch++;
//Channels 426..1937..3448
for(uint8_t i=0;i<3;i++)
{
uint16_t tmp=ch<16 ? convert_channel_16b_nolimit(ch,426,3448,false) : 0x0000;
ch-=2; // switch to next channel
packet[i*2+1]=tmp>>8;
packet[i*2+2]=tmp;
}
//Calculate CRC
crc8=bit_reverse(hopping_frequency_no + MLINK_CRC_Init); // Init = relected freq index + offset
for(uint8_t i=0;i<MLINK_PACKET_SIZE-1;i++)
crc8_update(bit_reverse(packet[i]));
packet[7] = bit_reverse(crc8); // CRC reflected out
//Debug
#if 0
debug("P(%02d):",hopping_frequency_no);
for(uint8_t i=0;i<8;i++)
debug(" %02X",packet[i]);
debugln("");
#endif
}
#ifdef MLINK_HUB_TELEMETRY
static void __attribute__((unused)) MLINK_Send_Telemetry()
{
if(packet[0]==0x03)
{//Basic telemetry
//Incoming packet values
RX_RSSI = packet_in[2*2]; // Looks to be the RX RSSI value
RX_LQI = packet_in[5*2]; // Looks to be connection lost
}
// Read TX RSSI
TX_RSSI = CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;
telemetry_counter++; // TX LQI counter
telemetry_link = 1;
if(telemetry_lost)
{
telemetry_lost = 0;
packet_count = 100;
telemetry_counter = 100;
}
}
#endif
uint16_t ReadMLINK()
{
uint8_t status;//,len,sum=0,check=0;
uint8_t start;
//uint16_t sum=0;
//static uint8_t retry;
switch(phase)
{
case MLINK_BIND_RX:
//debugln("RX");
status=CYRF_ReadRegister(CYRF_05_RX_CTRL);
if( (status&0x80) == 0 )
{//Packet received
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
debugln("L=%02X",len)
if( len==8 )
{
CYRF_ReadDataPacketLen(packet, len*2);
debug("RX=");
for(uint8_t i=0;i<8;i++)
debug(" %02X",packet[i*2]);
debugln("");
//Check CRC
crc8=0xFF; // Init = 0xFF
for(uint8_t i=0;i<MLINK_PACKET_SIZE-1;i++)
crc8_update(bit_reverse(packet[i<<1]));
if(packet[14] == bit_reverse(crc8))
{// CRC is ok
debugln("CRC ok");
if(packet[0]==0x7F)
packet_count=3; // Start sending bind payload
else if(packet_count > 0x19*2)
{
if(packet[0] == 0x8F)
packet_count++;
else if(packet[0] == 0x9F)
packet_count=0x80; // End bind
else
packet_count=0; // Restart bind...
}
}
}
}
else
packet_count=0;
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
phase=MLINK_BIND_TX; // Retry sending bind packet
CYRF_SetTxRxMode(TX_EN); // Transmit mode
if(packet_count)
return 18136;
case MLINK_BIND_TX:
if(--bind_counter==0 || packet_count>=0x1B*2)
{ // Switch to normal mode
BIND_DONE;
phase=MLINK_PREP_DATA;
return 22720;
}
MLINK_send_bind_data_packet();
if(packet_count == 0 || packet_count > 0x19*2)
{
phase++; // MLINK_BIND_PREP_RX
return 4700; // Original is 4900
}
packet_count++;
if(packet_count&1)
return 6000;
return 22720;
case MLINK_BIND_PREP_RX:
start=micros();
while ((uint8_t)((uint8_t)micros()-(uint8_t)start) < 200) // Wait max 200µs for TX to finish
if((CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80) == 0x00)
break; // Packet transmission complete
CYRF_SetTxRxMode(RX_EN); // Receive mode
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x82); // Prepare to receive
phase++; //MLINK_BIND_RX
return 28712-4700;
case MLINK_PREP_DATA:
CYRF_ConfigDataCode(MLINK_Data_Code,16);
MLINK_CRC_Init += 0xED;
hopping_frequency_no = 0x00;
CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]);
CYRF_SetPower(0x38);
#ifdef MLINK_HUB_TELEMETRY
packet_count = 0;
telemetry_lost = 1;
#endif
phase++;
case MLINK_SEND1:
MLINK_build_data_packet();
CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x40);
CYRF_WriteRegisterMulti(CYRF_20_TX_BUFFER, packet, MLINK_PACKET_SIZE);
CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x82);
phase++;
return 4880;
case MLINK_CHECK1:
status=CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS);
//debugln("C1:%02X",status);
CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x00);
phase++;
return 1111;
case MLINK_SEND2:
MLINK_build_data_packet();
CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x40);
CYRF_WriteRegisterMulti(CYRF_20_TX_BUFFER, packet, MLINK_PACKET_SIZE);
CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x82);
phase++;
return 4617;
case MLINK_CHECK2:
status=CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS);
//debugln("C2:%02X",status);
CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x00);
phase++;
if(hopping_frequency_no%5==0)
return 1017;
return 1422;
case MLINK_SEND3:
MLINK_build_data_packet();
CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x40);
CYRF_WriteRegisterMulti(CYRF_20_TX_BUFFER, packet, MLINK_PACKET_SIZE);
CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x82);
phase++;
return 4611;
case MLINK_CHECK3:
status=CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS);
//debugln("C3:%02X",status);
CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x00);
//check RX but there is nothing to check...
status=CYRF_ReadRegister(CYRF_05_RX_CTRL);
//debugln("CTRL:%02X",status);
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
//debugln("L=%02X",len)
if( len && len<=8 )
CYRF_ReadDataPacketLen(packet, len*2);
CYRF_WriteRegister(CYRF_05_RX_CTRL,0x00);
//Next channel
hopping_frequency_no++;
if(hopping_frequency_no>=MLINK_NUM_FREQ)
hopping_frequency_no=0;
CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]);
//Receive telemetry
if(hopping_frequency_no%5==0)
{//Receive telemetry
CYRF_SetTxRxMode(RX_EN); // Receive mode
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x82); // Prepare to receive
phase++; //MLINK_RX
return 8038;
}
else
CYRF_SetPower(0x38);
phase=MLINK_SEND1;
return 4470;
case MLINK_RX:
#ifdef MLINK_HUB_TELEMETRY
//TX LQI calculation
packet_count++;
if(packet_count>=100)
{
packet_count=0;
TX_LQI=telemetry_counter;
if(telemetry_counter==0)
telemetry_lost = 1;
telemetry_counter = 0;
}
#endif
status=CYRF_ReadRegister(CYRF_05_RX_CTRL);//CYRF_07_RX_IRQ_STATUS);
debug("T(%02X):",status);
//status=CYRF_ReadRegister(CYRF_05_RX_CTRL);
//if( (status&0x80) == 0 )
{//Packet received
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
debug("(%X)",len)
if( len && len<=8 )
{
CYRF_ReadDataPacketLen(packet_in, len*2);
#ifdef MLINK_HUB_TELEMETRY
if(len==8)
{
//Check CRC
crc8=bit_reverse(MLINK_CRC_Init);
for(uint8_t i=0;i<MLINK_PACKET_SIZE-1;i++)
crc8_update(bit_reverse(packet[i<<1]));
if(packet_in[14] == bit_reverse(crc8)) // Packet CRC is ok
{
MLINK_Send_Telemetry();
for(uint8_t i=0;i<8;i++)
debug(" %02X",packet_in[i*2]);
}
}
#endif
}
}
debugln("");
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
CYRF_SetTxRxMode(TX_EN); // Transmit mode
phase++;
return 2434;
case MLINK_CHECK4:
status=CYRF_ReadRegister(CYRF_05_RX_CTRL);
debugln("C4: CTRL:%02X",status);
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
debugln("L=%02X",len)
if( len && len<=8 )
CYRF_ReadDataPacketLen(packet, len*2);
CYRF_WriteRegister(CYRF_05_RX_CTRL,0x00);
phase=MLINK_SEND2;
return 410;
}
return 1000;
}
uint16_t initMLINK()
{
MLINK_cyrf_config();
#ifdef MLINK_FORCE_ID
//Cockpit SX
memcpy(MLINK_Data_Code,"\x4C\x97\x9D\xBF\xB8\x3D\xB5\xBE",8);
memcpy(hopping_frequency,"\x0D\x41\x09\x43\x17\x2D\x05\x31\x13\x3B\x1B\x3D\x0B\x41\x11\x45\x09\x2B\x17\x4D\x19\x3F\x03\x3F\x0F\x37\x1F\x47\x1B\x49\x07\x35\x27\x2F\x15\x33\x23\x39\x1F\x33\x19\x45\x0D\x2D\x11\x35\x0B\x47\x25\x3D\x21\x37\x1D\x3B\x05\x2F\x21\x39\x23\x4B\x03\x31\x25\x29\x07\x4F\x1D\x4B\x15\x4D\x13\x4F\x0F\x49\x29\x2B\x27\x43",78);
MLINK_Unk_6_2 = 0x3A; //unknown value sent during bind but doesn't seem to matter
MLINK_CRC_Init = 0x07; //value sent during bind then used to init the CRC
//HFM3
memcpy(MLINK_Data_Code,"\xC0\x90\x8F\xBB\x7C\x8E\x2B\x8E",8);
memcpy(hopping_frequency,"\x05\x41\x27\x4B\x17\x33\x11\x39\x0F\x3F\x05\x2F\x13\x2D\x25\x31\x1F\x2D\x25\x35\x03\x41\x1B\x43\x09\x3D\x1F\x29\x1D\x35\x0D\x3B\x19\x49\x23\x3B\x17\x47\x1D\x2B\x13\x37\x0B\x31\x23\x33\x29\x3F\x07\x37\x07\x43\x11\x2B\x1B\x39\x0B\x4B\x03\x4F\x21\x47\x0F\x4D\x15\x45\x21\x4F\x09\x3D\x19\x2F\x15\x45\x0D\x49\x27\x4D",78);
MLINK_Unk_6_2 = 0x02; //unknown value but doesn't seem to matter
MLINK_CRC_Init = 0x3E; //value sent during bind then used to init the CRC
//Other TX
//MLINK_Unk_6_2 = 0x7e; //unknown value but doesn't seem to matter
//MLINK_CRC_Init = 0xA2; //value sent during bind then used to init the CRC
#endif
for(uint8_t i=0;i<8;i++)
MLINK_Data_Code[i+8]=MLINK_Data_Code[7-i];
debug("ID:")
for(uint8_t i=0;i<16;i++)
debug(" %02X", MLINK_Data_Code[i]);
debugln("");
debugln("CRC init: %02X", MLINK_CRC_Init)
debug("RF:")
for(uint8_t i=0;i<MLINK_NUM_FREQ;i++)
debug(" %02X", hopping_frequency[i]);
debugln("");
if(IS_BIND_IN_PROGRESS)
{
packet_count = 0;
bind_counter = MLINK_BIND_COUNT;
CYRF_ConfigDataCode((uint8_t*)"\x6F\xBE\x32\x01\xDB\xF1\x2B\x01\xE3\x5C\xFA\x02\x97\x93\xF9\x02",16); //Bind data code
CYRF_ConfigRFChannel(MLINK_BIND_CHANNEL);
phase = MLINK_BIND_TX;
}
else
phase = MLINK_PREP_DATA;
return 10000;
}
#endif

View File

@@ -2,8 +2,8 @@
2,Hubsan,H107,H301,H501
3,FrskyD,D8,Cloned
4,Hisky,Hisky,HK310
5,V2x2,V2x2,JXD506
6,DSM,DSM2-22,DSM2-11,DSMX-22,DSMX-11,AUTO
5,V2x2,V2x2,JXD506,MR101
6,DSM,DSM2_1F,DSM2_2F,DSMX_1F,DSMX_2F,AUTO
7,Devo,8CH,10CH,12CH,6CH,7CH
8,YD717,YD717,SKYWLKR,SYMAX4,XINXUN,NIHUI
9,KN,WLTOYS,FEILUN
@@ -11,21 +11,21 @@
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,DHD_D4
15,FrskyX,CH_16,CH_8,EU_16,EU_8,Cloned
14,Bayang,Bayang,H8S3D,X16_AH,IRDRONE,DHD_D4,QX100
15,FrskyX,CH_16,CH_8,EU_16,EU_8,Cloned,Clon_8
16,ESky,Std,ET4
17,MT99xx,MT,H7,YZ,LS,FY805
18,MJXq,WLH08,X600,X800,H26D,E010,H26WH,PHOENIX
19,Shenqi
20,FY326,FY326,FY319
21,SFHSS
21,Futaba,SFHSS
22,J6PRO
23,FQ777
24,ASSAN
25,FrskyV
26,HONTAI,HONTAI,JJRCX1,X5C1,FQ777_951
27,OpnLrs
28,AFHDS2A,PWM_IBUS,PPM_IBUS,PWM_SBUS,PPM_SBUS
28,AFHDS2A,PWM_IBUS,PPM_IBUS,PWM_SBUS,PPM_SBUS,PWM_IB16,PPM_IB16
29,Q2X2,Q222,Q242,Q282
30,WK2x01,WK2801,WK2401,W6_5_1,W6_6_1,W6_HEL,W6_HEL_I
31,Q303,Q303,CX35,CX10D,CX10WD
@@ -37,7 +37,7 @@
37,CORONA,COR_V1,COR_V2,FD_V3
38,CFlie
39,Hitec,OPT_FW,OPT_HUB,MINIMA
40,WFLY
40,WFLY,WFR0x
41,BUGS
42,BUGSMINI,BUGSMINI,BUGS3H
43,Traxxas,RX6519
@@ -45,26 +45,39 @@
45,E01X,E012,E015,E016H
46,V911S,V911S,E119
47,GD00x,GD_V1,GD_V2
48,V761
48,V761,3CH,4CH
49,KF606
50,Redpine,Fast,Slow
51,Potensic,A20
52,ZSX,280
53,Flyzone,FZ-410
53,Height,5ch,8ch
54,Scanner
55,Frsky_RX,RX,CloneTX
56,AFHDS2A_RX
57,HoTT
57,HoTT,Sync,No_Sync
58,FX816,P38
59,Bayang_RX
60,Pelikan
60,Pelikan,Pro,Lite
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
65,FrSkyR9,915MHz,868MHz,915_8ch,868_8ch,FCC,--,FCC_8ch,--_8ch
66,PROPEL,74-Z
67,LR12,LR12,LR12_6ch
68,Skyartec
69,ESKYv2,150V2
70,DSM_RX
70,DSM_RX
71,JJRC345,JJRC345,SkyTmblr
72,Q90C
73,Kyosho,FHSS,Hype
74,RadioLink,Surface,Air,DumboRC
75,---
76,Realacc,R11
77,OMP
78,M-Link
79,WFLY,RF20x
80,E016H,E016Hv2
81,E010r5
82,LOLI
83,E129

View File

@@ -38,17 +38,18 @@ 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_FUTABA[] ="Futaba";
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_AFHDS2A[] ="FlSky2A";
const char STR_Q2X2[] ="Q2x2";
const char STR_WK2x01[] ="Walkera";
const char STR_Q303[] ="Q303";
const char STR_Q90C[] ="Q90C";
const char STR_GW008[] ="GW008";
const char STR_DM002[] ="DM002";
const char STR_CABELL[] ="Cabell";
@@ -58,7 +59,8 @@ 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_WFLY[] ="WFLY";
const char STR_WFLY2[] ="WFLY2";
const char STR_BUGS[] ="Bugs";
const char STR_BUGSMINI[] ="BugMini";
const char STR_TRAXXAS[] ="Traxxas";
@@ -71,7 +73,7 @@ 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_HEIGHT[] ="Height";
const char STR_SCANNER[] ="Scanner";
const char STR_FRSKY_RX[] ="FrSkyRX";
const char STR_AFHDS2A_RX[] ="FS2A_RX";
@@ -83,16 +85,27 @@ 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_PROPEL[] ="Propel";
const char STR_SKYARTEC[] ="Skyartc";
const char STR_KYOSHO[] ="Kyosho";
const char STR_RLINK[] ="RadLink";
const char STR_REALACC[] ="Realacc";
const char STR_OMP[] ="OMP";
const char STR_MLINK[] ="M-Link";
const char STR_TEST[] ="Test";
const char STR_NANORF[] ="NanoRF";
const char STR_E016HV2[] ="E016Hv2";
const char STR_E010R5[] ="E010r5";
const char STR_LOLI[] ="LOLI";
const char STR_E129[] ="E129";
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_FRSKYX[] = "\x07""D16\0 ""D16 8ch""LBT(EU)""LBT 8ch""Cloned\0""Clo 8ch";
const char STR_SUBTYPE_HISKY[] = "\x05""Std\0 ""HK310";
const char STR_SUBTYPE_V2X2[] = "\x06""Std\0 ""JXD506";
const char STR_SUBTYPE_DSM[] = "\x06""2 22ms""2 11ms""X 22ms""X 11ms";
const char STR_SUBTYPE_V2X2[] = "\x06""Std\0 ""JXD506""MR101\0";
const char STR_SUBTYPE_DSM[] = "\x04""2 1F""2 2F""X 1F""X 2F""Auto";
const char STR_SUBTYPE_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";
@@ -100,12 +113,12 @@ 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_BAYANG[] = "\x07""Std\0 ""H8S3D\0 ""X16 AH\0""IRDrone""DHD D4\0""QX100\0 ";
const char STR_SUBTYPE_MT99[] = "\x06""MT99\0 ""H7\0 ""YZ\0 ""LS\0 ""FY805";
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_AFHDS2A[] = "\x08""PWM,IBUS""PPM,IBUS""PWM,SBUS""PPM,SBUS""PWM,IB16""PPM,IB16""PWM,SB16""PPM,SB16";
const char STR_SUBTYPE_Q2X2[] = "\x04""Q222""Q242""Q282";
const char STR_SUBTYPE_WK2x01[] = "\x06""WK2801""WK2401""W6_5_1""W6_6_1""W6_HeL""W6_HeI";
const char STR_SUBTYPE_Q303[] = "\x06""Std\0 ""CX35\0 ""CX10D\0""CX10WD";
@@ -120,19 +133,28 @@ 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_HEIGHT[] = "\x03""5ch""8ch";
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_XN297DUMP[] = "\x07""250Kbps""1Mbps\0 ""2Mbps\0 ""Auto\0 ""NRF\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_FRSKYR9[] = "\x07""915MHz\0""868MHz\0""915 8ch""868 8ch""FCC\0 ""--\0 ""FCC 8ch""-- 8ch\0";
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";
const char STR_SUBTYPE_WFLY[] = "\x05""WFR0x";
const char STR_SUBTYPE_WFLY2[] = "\x05""RF20x";
const char STR_SUBTYPE_HOTT[] = "\x07""Sync\0 ""No_Sync";
const char STR_SUBTYPE_PELIKAN[] = "\x04""Pro\0""Lite";
const char STR_SUBTYPE_V761[] = "\x03""3ch""4ch";
const char STR_SUBTYPE_RLINK[] = "\x07""Surface""Air\0 ""DumboRC";
const char STR_SUBTYPE_REALACC[] = "\x03""R11";
const char STR_SUBTYPE_KYOSHO[] = "\x04""FHSS""Hype";
const char STR_SUBTYPE_FUTABA[] = "\x05""SFHSS";
const char STR_SUBTYPE_JJRC345[] = "\x08""JJRC345\0""SkyTmblr";
enum
{
@@ -144,7 +166,8 @@ enum
OPTION_TELEM,
OPTION_SRVFREQ,
OPTION_MAXTHR,
OPTION_RFCHAN
OPTION_RFCHAN,
OPTION_RFPOWER,
};
#define NO_SUBTYPE nullptr
@@ -155,7 +178,7 @@ const mm_protocol_definition multi_protocols[] = {
{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 },
{PROTO_BAYANG, STR_BAYANG, 6, STR_SUBTYPE_BAYANG, OPTION_TELEM },
#endif
#if defined(BAYANG_RX_NRF24L01_INO)
{PROTO_BAYANG_RX, STR_BAYANG_RX, 0, NO_SUBTYPE, OPTION_NONE },
@@ -172,9 +195,6 @@ const mm_protocol_definition multi_protocols[] = {
#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
@@ -191,11 +211,23 @@ const mm_protocol_definition multi_protocols[] = {
{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 },
{PROTO_DSM, STR_DSM, 5, 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(E010R5_CYRF6936_INO)
{PROTO_E010R5, STR_E010R5, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(E016HV2_CC2500_INO)
{PROTO_E016HV2, STR_E016HV2, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(E01X_NRF24L01_INO)
{PROTO_E01X, STR_E01X, 3, STR_SUBTYPE_E01X, OPTION_OPTION },
#endif
#if defined(E129_CYRF6936_INO)
{PROTO_E129, STR_E129, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(ESKY_NRF24L01_INO)
{PROTO_ESKY, STR_ESKY, 2, STR_SUBTYPE_ESKY, OPTION_NONE },
#endif
@@ -209,14 +241,11 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_FLYSKY, STR_FLYSKY, 5, STR_SUBTYPE_FLYSKY, OPTION_NONE },
#endif
#if defined(AFHDS2A_A7105_INO)
{PROTO_AFHDS2A, STR_AFHDS2A, 4, STR_SUBTYPE_AFHDS2A, OPTION_SRVFREQ },
{PROTO_AFHDS2A, STR_AFHDS2A, 8, STR_SUBTYPE_AFHDS2A, OPTION_SRVFREQ },
#endif
#if defined(AFHDS2A_RX_A7105_INO)
{PROTO_AFHDS2A_RX, STR_AFHDS2A_RX,0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(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
@@ -231,15 +260,18 @@ const mm_protocol_definition multi_protocols[] = {
{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 },
{PROTO_FRSKYX, STR_FRSKYX, 6, STR_SUBTYPE_FRSKYX, OPTION_RFTUNE },
{PROTO_FRSKYX2, STR_FRSKYX2, 6, 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 },
{PROTO_FRSKY_R9, STR_FRSKYR9, 8, STR_SUBTYPE_FRSKYR9, OPTION_NONE },
#endif
#if defined(FUTABA_CC2500_INO)
{PROTO_FUTABA, STR_FUTABA, 1, STR_SUBTYPE_FUTABA, OPTION_RFTUNE },
#endif
#if defined(FX816_NRF24L01_INO)
{PROTO_FX816, STR_FX816, 1, STR_SUBTYPE_FX816, OPTION_NONE },
@@ -256,6 +288,9 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(H8_3D_NRF24L01_INO)
{PROTO_H8_3D, STR_H8_3D, 4, STR_SUBTYPE_H83D, OPTION_NONE },
#endif
#if defined(HEIGHT_A7105_INO)
{PROTO_HEIGHT, STR_HEIGHT, 2, STR_SUBTYPE_HEIGHT, OPTION_NONE },
#endif
#if defined(HISKY_NRF24L01_INO)
{PROTO_HISKY, STR_HISKY, 2, STR_SUBTYPE_HISKY, OPTION_NONE },
#endif
@@ -266,7 +301,7 @@ const mm_protocol_definition multi_protocols[] = {
{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 },
{PROTO_HOTT, STR_HOTT, 2, STR_SUBTYPE_HOTT, OPTION_RFTUNE },
#endif
#if defined(HUBSAN_A7105_INO)
{PROTO_HUBSAN, STR_HUBSAN, 3, STR_SUBTYPE_HUBSAN, OPTION_VIDFREQ },
@@ -275,7 +310,7 @@ const mm_protocol_definition multi_protocols[] = {
{PROTO_J6PRO, STR_J6PRO, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(JJRC345_NRF24L01_INO)
{PROTO_JJRC345, STR_JJRC345, 0, NO_SUBTYPE, OPTION_NONE },
{PROTO_JJRC345, STR_JJRC345, 2, STR_SUBTYPE_JJRC345, OPTION_NONE },
#endif
#if defined(KF606_NRF24L01_INO)
{PROTO_KF606, STR_KF606, 0, NO_SUBTYPE, OPTION_RFTUNE },
@@ -283,23 +318,35 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(KN_NRF24L01_INO)
{PROTO_KN, STR_KN, 2, STR_SUBTYPE_KN, OPTION_NONE },
#endif
#if defined(KYOSHO_A7105_INO)
{PROTO_KYOSHO, STR_KYOSHO, 2, STR_SUBTYPE_KYOSHO, OPTION_NONE },
#endif
#if defined(LOLI_NRF24L01_INO)
{PROTO_LOLI, STR_LOLI, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(MJXQ_NRF24L01_INO)
{PROTO_MJXQ, STR_MJXQ, 7, STR_SUBTYPE_MJXQ, OPTION_RFTUNE },
#endif
#if defined(MLINK_CYRF6936_INO)
{PROTO_MLINK, STR_MLINK, 0, NO_SUBTYPE, OPTION_NONE },
#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(OMP_CC2500_INO)
{PROTO_OMP, STR_OMP, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(PELIKAN_A7105_INO)
{PROTO_PELIKAN, STR_PELIKAN , 0, NO_SUBTYPE, OPTION_NONE },
{PROTO_PELIKAN, STR_PELIKAN , 2, STR_SUBTYPE_PELIKAN, 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 },
{PROTO_PROPEL, STR_PROPEL, 1, STR_SUBTYPE_PROPEL, OPTION_NONE },
#endif
#if defined(CX10_NRF24L01_INO)
{PROTO_Q2X2, STR_Q2X2, 3, STR_SUBTYPE_Q2X2, OPTION_NONE },
@@ -307,15 +354,21 @@ const mm_protocol_definition multi_protocols[] = {
#if defined(Q303_NRF24L01_INO)
{PROTO_Q303, STR_Q303, 4, STR_SUBTYPE_Q303, OPTION_NONE },
#endif
#if defined(Q90C_NRF24L01_INO)
{PROTO_Q90C, STR_Q90C, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(RLINK_CC2500_INO)
{PROTO_RLINK, STR_RLINK, 3, STR_SUBTYPE_RLINK, OPTION_RFTUNE },
#endif
#if defined(REALACC_NRF24L01_INO)
{PROTO_REALACC, STR_REALACC, 1, STR_SUBTYPE_REALACC, 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
@@ -335,31 +388,40 @@ const mm_protocol_definition multi_protocols[] = {
{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 },
{PROTO_V2X2, STR_V2X2, 3, STR_SUBTYPE_V2X2, OPTION_NONE },
#endif
#if defined(V761_NRF24L01_INO)
{PROTO_V761, STR_V761, 0, NO_SUBTYPE, OPTION_NONE },
{PROTO_V761, STR_V761, 2, STR_SUBTYPE_V761, OPTION_NONE },
#endif
#if defined(V911S_NRF24L01_INO)
{PROTO_V911S, STR_V911S, 2, STR_SUBTYPE_V911S, OPTION_RFTUNE },
#endif
#if defined(WK2x01_CYRF6936_INO)
{PROTO_WK2x01, STR_WK2x01, 6, STR_SUBTYPE_WK2x01, OPTION_NONE },
#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 },
#if defined(WFLY2_A7105_INO)
{PROTO_WFLY2, STR_WFLY2, 1, STR_SUBTYPE_WFLY2, OPTION_OPTION },
#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 },
{PROTO_XN297DUMP, STR_XN297DUMP, 5, 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
#if defined(TEST_CC2500_INO)
{PROTO_TEST, STR_TEST, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(NANORF_NRF24L01_INO)
{PROTO_NANORF, STR_NANORF, 0, NO_SUBTYPE, OPTION_NONE },
#endif
{0x00, nullptr, 0, nullptr, 0 }
};

View File

@@ -18,8 +18,8 @@
//******************
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_REVISION 1
#define VERSION_PATCH_LEVEL 1
#define VERSION_REVISION 2
#define VERSION_PATCH_LEVEL 11
//******************
// Protocols
@@ -47,7 +47,7 @@ enum PROTOCOLS
PROTO_MJXQ = 18, // =>NRF24L01
PROTO_SHENQI = 19, // =>NRF24L01
PROTO_FY326 = 20, // =>NRF24L01
PROTO_SFHSS = 21, // =>CC2500
PROTO_FUTABA = 21, // =>CC2500
PROTO_J6PRO = 22, // =>CYRF6936
PROTO_FQ777 = 23, // =>NRF24L01
PROTO_ASSAN = 24, // =>NRF24L01
@@ -79,7 +79,7 @@ enum PROTOCOLS
PROTO_REDPINE = 50, // =>CC2500
PROTO_POTENSIC = 51, // =>NRF24L01
PROTO_ZSX = 52, // =>NRF24L01
PROTO_FLYZONE = 53, // =>A7105
PROTO_HEIGHT = 53, // =>A7105
PROTO_SCANNER = 54, // =>CC2500
PROTO_FRSKY_RX = 55, // =>CC2500
PROTO_AFHDS2A_RX= 56, // =>A7105
@@ -98,6 +98,20 @@ enum PROTOCOLS
PROTO_ESKY150V2 = 69, // =>CC2500+NRF24L01
PROTO_DSM_RX = 70, // =>CYRF6936
PROTO_JJRC345 = 71, // =>NRF24L01
PROTO_Q90C = 72, // =>NRF24L01 or CC2500
PROTO_KYOSHO = 73, // =>A7105
PROTO_RLINK = 74, // =>CC2500
PROTO_REALACC = 76, // =>NRF24L01
PROTO_OMP = 77, // =>CC2500 & NRF24L01
PROTO_MLINK = 78, // =>CYRF6936
PROTO_WFLY2 = 79, // =>A7105
PROTO_E016HV2 = 80, // =>CC2500 & NRF24L01
PROTO_E010R5 = 81, // =>CYRF6936
PROTO_LOLI = 82, // =>NRF24L01
PROTO_E129 = 83, // =>CYRF6936
PROTO_NANORF = 126, // =>NRF24L01
PROTO_TEST = 127, // =>CC2500
};
enum Flysky
@@ -108,7 +122,7 @@ enum Flysky
V912 = 3,
CX20 = 4,
};
enum Flyzone
enum Height
{
FZ410 = 0,
};
@@ -124,6 +138,8 @@ enum AFHDS2A
PPM_IBUS = 1,
PWM_SBUS = 2,
PPM_SBUS = 3,
PWM_IB16 = 4,
PPM_IB16 = 5,
};
enum Hisky
{
@@ -194,6 +210,7 @@ enum BAYANG
X16_AH = 2,
IRDRONE = 3,
DHD_D4 = 4,
QX100 = 5,
};
enum MT99XX
{
@@ -220,11 +237,12 @@ enum FRSKYD
};
enum FRSKYX
{
CH_16 = 0,
CH_8 = 1,
EU_16 = 2,
EU_8 = 3,
XCLONE = 4,
CH_16 = 0,
CH_8 = 1,
EU_16 = 2,
EU_8 = 3,
XCLONE_16 = 4,
XCLONE_8 = 5,
};
enum HONTAI
{
@@ -237,6 +255,7 @@ enum V2X2
{
V2X2 = 0,
JXD506 = 1,
V2X2_MR101 = 2,
};
enum FY326
{
@@ -338,6 +357,10 @@ enum FRSKY_R9
R9_868 = 1,
R9_915_8CH = 2,
R9_868_8CH = 3,
R9_FCC = 4,
R9_EU = 5,
R9_FCC_8CH = 6,
R9_EU_8CH = 7,
};
enum ESKY
{
@@ -357,6 +380,49 @@ enum FRSKYL
LR12_6CH = 1,
};
enum HOTT
{
HOTT_SYNC = 0,
HOTT_NO_SYNC= 1,
};
enum PELIKAN
{
PELIKAN_PRO = 0,
PELIKAN_LITE= 1,
};
enum V761
{
V761_3CH = 0,
V761_4CH = 1,
};
enum HEIGHT
{
HEIGHT_5CH = 0,
HEIGHT_8CH = 1,
};
enum KYOSHO
{
KYOSHO_FHSS = 0,
KYOSHO_HYPE = 1,
};
enum JJRC345
{
JJRC345 = 0,
SKYTMBLR = 1,
};
enum RLINK
{
RLINK_SURFACE = 0,
RLINK_AIR = 1,
RLINK_DUMBORC = 2,
};
#define NONE 0
#define P_HIGH 1
#define P_LOW 0
@@ -399,8 +465,8 @@ enum MultiPacketTypes
//***************
//*** 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)
#define IS_FAILSAFE_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_FUTABA || protocol==PROTO_WK2x01 || protocol== PROTO_HOTT || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKY_R9 || protocol==PROTO_WFLY2 || protocol==PROTO_LOLI)
#define IS_CHMAP_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_FUTABA || protocol==PROTO_WK2x01 || protocol== PROTO_DSM || protocol==PROTO_SLT || protocol==PROTO_FLYSKY || (protocol==PROTO_KYOSHO && sub_protocol==KYOSHO_HYPE) || protocol==PROTO_ESKY || protocol==PROTO_J6PRO || protocol==PROTO_PELIKAN || protocol==PROTO_SKYARTEC || protocol==PROTO_ESKY150V2 || protocol==PROTO_DSM_RX)
//***************
//*** Flags ***
@@ -563,17 +629,17 @@ enum {
};
// A7105 power
// Power amp is ~+16dBm so:
// The numbers do not take into account any outside amplifier
enum A7105_POWER
{
A7105_POWER_0 = 0x00<<3 | 0x00, // TXPOWER_100uW = -23dBm == PAC=0 TBG=0
A7105_POWER_1 = 0x00<<3 | 0x01, // TXPOWER_300uW = -20dBm == PAC=0 TBG=1
A7105_POWER_2 = 0x00<<3 | 0x02, // TXPOWER_1mW = -16dBm == PAC=0 TBG=2
A7105_POWER_3 = 0x00<<3 | 0x04, // TXPOWER_3mW = -11dBm == PAC=0 TBG=4
A7105_POWER_4 = 0x01<<3 | 0x05, // TXPOWER_10mW = -6dBm == PAC=1 TBG=5
A7105_POWER_5 = 0x02<<3 | 0x07, // TXPOWER_30mW = 0dBm == PAC=2 TBG=7
A7105_POWER_6 = 0x03<<3 | 0x07, // TXPOWER_100mW = 1dBm == PAC=3 TBG=7
A7105_POWER_7 = 0x03<<3 | 0x07 // TXPOWER_150mW = 1dBm == PAC=3 TBG=7
A7105_POWER_0 = 0x00<<3 | 0x00, // -23dBm == PAC=0 TBG=0
A7105_POWER_1 = 0x00<<3 | 0x01, // -20dBm == PAC=0 TBG=1
A7105_POWER_2 = 0x00<<3 | 0x02, // -16dBm == PAC=0 TBG=2
A7105_POWER_3 = 0x00<<3 | 0x04, // -11dBm == PAC=0 TBG=4
A7105_POWER_4 = 0x01<<3 | 0x05, // -6dBm == PAC=1 TBG=5
A7105_POWER_5 = 0x02<<3 | 0x07, // 0dBm == PAC=2 TBG=7
A7105_POWER_6 = 0x03<<3 | 0x07, // +1dBm == PAC=3 TBG=7
A7105_POWER_7 = 0x03<<3 | 0x07 // +1dBm == PAC=3 TBG=7
};
#define A7105_HIGH_POWER A7105_POWER_7
#define A7105_LOW_POWER A7105_POWER_3
@@ -581,14 +647,13 @@ enum A7105_POWER
#define A7105_BIND_POWER A7105_POWER_0
// NRF Power
// Power setting is 0..3 for nRF24L01
// Claimed power amp for nRF24L01 from eBay is 20dBm.
// The numbers do not take into account any outside amplifier
enum NRF_POWER
{ // Raw w 20dBm PA
NRF_POWER_0 = 0x00, // 0 : -18dBm (16uW) 2dBm (1.6mW)
NRF_POWER_1 = 0x01, // 1 : -12dBm (60uW) 8dBm (6mW)
NRF_POWER_2 = 0x02, // 2 : -6dBm (250uW) 14dBm (25mW)
NRF_POWER_3 = 0x03 // 3 : 0dBm (1mW) 20dBm (100mW)
{
NRF_POWER_0 = 0x00, // -18dBm
NRF_POWER_1 = 0x01, // -12dBm
NRF_POWER_2 = 0x02, // -6dBm
NRF_POWER_3 = 0x03 // 0dBm
};
#define NRF_HIGH_POWER NRF_POWER_3
#define NRF_LOW_POWER NRF_POWER_1
@@ -625,6 +690,7 @@ enum CC2500_POWER
#define CC2500_BIND_POWER CC2500_POWER_1
// CYRF power
// The numbers do not take into account any outside amplifier
enum CYRF_POWER
{
CYRF_POWER_0 = 0x00, // -35dbm
@@ -679,6 +745,15 @@ enum {
#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
/* STM32 Flash Size */
#ifndef DISABLE_FLASH_SIZE_CHECK
#ifdef MCU_STM32F103C8
#define MCU_EXPECTED_FLASH_SIZE 64 // STM32F103C8 has 64KB of flash space
#else
#define MCU_EXPECTED_FLASH_SIZE 128 // STM32F103CB has 128KB of flash space
#endif
#endif
//****************************************
//*** MULTI protocol serial definition ***
//****************************************
@@ -693,8 +768,9 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
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
Note: V2 adds the 2 top bits to extend the number of protocols to 256 in Stream[26]
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 | 0x56
sub_protocol is 0..31 (bits 0..4)
Reserved 0
Flysky 1
Hubsan 2
@@ -716,7 +792,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
MJXQ 18
SHENQI 19
FY326 20
SFHSS 21
Futaba 21
J6PRO 22
FQ777 23
ASSAN 24
@@ -748,7 +824,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
REDPINE 50
POTENSIC 51
ZSX 52
FLYZONE 53
HEIGHT 53
SCANNER 54
FRSKY_RX 55
AFHDS2A_RX 56
@@ -767,6 +843,17 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
ESKY150V2 69
DSM_RX 70
JJRC345 71
Q90C 72
KYOSHO 73
RLINK 74
REALACC 76
OMP 77
MLINK 78
WFLY2 79
E016HV2 80
E010R5 81
LOLI 82
E129 83
BindBit=> 0x80 1=Bind/0=No
AutoBindBit=> 0x40 1=Yes /0=No
RangeCheck=> 0x20 1=Yes /0=No
@@ -864,9 +951,12 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
PPM_IBUS 1
PWM_SBUS 2
PPM_SBUS 3
PWM_IB16 4
PPM_IB16 5
sub_protocol==V2X2
V2X2 0
JXD506 1
V2X2_MR101 2
sub_protocol==FY326
FY326 0
FY319 1
@@ -932,6 +1022,10 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
R9_868 1
R9_915_8CH 2
R9_868_8CH 3
R9_FCC 4
R9_EU 5
R9_FCC_8CH 6
R9_EU_8CH 7
sub_protocol==ESKY
ESKY_STD 0
ESKY_ET4 1
@@ -941,6 +1035,25 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
sub_protocol==FRSKYL
LR12 0
LR12_6CH 1
sub_protocol==HOTT
HOTT_SYNC 0
HOTT_NO_SYNC 1
sub_protocol==PELIKAN
PELIKAN_PRO 0
PELIKAN_LITE 1
sub_protocol==V761
V761_3CH 0
V761_4CH 1
sub_protocol==HEIGHT
HEIGHT_5CH 0
HEIGHT_8CH 1
sub_protocol==JJRC345
JJRC345 0
SKYTMBLR 1
sub_protocol==RLINK
RLINK_SURFACE 0
RLINK_AIR 1
RLINK_DUMBORC 2
Power value => 0x80 0=High/1=Low
Stream[3] = option_protocol;
@@ -967,6 +1080,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
FrSkyX and FrSkyX2: Stream[27] during bind Telem on=0x00,off=0x01 | CH1-8=0x00,CH9-16=0x02
FrSkyX and FrSkyX2: Stream[27..34] during normal operation unstuffed SPort data to be sent
HoTT: Stream[27] 1 byte for telemetry type
DSM: Stream[27..33] Forward Programming
*/
/*
Multimodule Status
@@ -1047,6 +1161,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
OPTION_SRVFREQ 6
OPTION_MAXTHR 7
OPTION_RFCHAN 8
OPTION_RFPOWER 9
[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.

View File

@@ -75,7 +75,7 @@ uint32_t blink=0,last_signal=0;
//
uint16_t counter;
uint8_t channel;
#ifdef ESKY150V2_CC2500_INO
#if defined(ESKY150V2_CC2500_INO)
uint8_t packet[150];
#else
uint8_t packet[50];
@@ -101,8 +101,8 @@ uint16_t packet_period;
uint8_t packet_count;
uint8_t packet_sent;
uint8_t packet_length;
#if defined(HOTT_CC2500_INO) || defined(ESKY150V2_CC2500_INO)
uint8_t hopping_frequency[75];
#if defined(HOTT_CC2500_INO) || defined(ESKY150V2_CC2500_INO) || defined(MLINK_CYRF6936_INO)
uint8_t hopping_frequency[78];
#else
uint8_t hopping_frequency[50];
#endif
@@ -112,18 +112,22 @@ uint8_t rf_ch_num;
uint8_t throttle, rudder, elevator, aileron;
uint8_t flags;
uint16_t crc;
uint16_t crc16_polynomial;
uint8_t crc8;
uint8_t crc8_polynomial;
uint16_t seed;
uint16_t failsafe_count;
uint16_t state;
uint8_t len;
uint8_t armed, arm_flags, arm_channel_previous;
uint8_t num_ch;
uint32_t pps_timer;
uint16_t pps_counter;
#ifdef CC2500_INSTALLED
#ifdef SCANNER_CC2500_INO
uint8_t calData[255];
#elif defined(HOTT_CC2500_INO)
#elif defined(HOTT_CC2500_INO) || defined(ESKY150V2_CC2500_INO)
uint8_t calData[75];
#else
uint8_t calData[50];
@@ -254,6 +258,10 @@ uint8_t packet_in[TELEMETRY_BUFFER_SIZE];//telemetry receiving packets
uint8_t HoTT_SerialRX_val=0;
bool HoTT_SerialRX=false;
#endif
#ifdef DSM_FWD_PGM
uint8_t DSM_SerialRX_val[7];
bool DSM_SerialRX=false;
#endif
#endif // TELEMETRY
// Callback
@@ -300,15 +308,16 @@ void setup()
PORTE.DIRCLR = 0x02 ;
// Timer1 config
// TCC1 16-bit timer, clocked at 0.5uS
EVSYS.CH3MUX = 0x80 + 0x04 ; // Prescaler of 16
EVSYS.CH3MUX = 0x80 + 0x04 ; // Prescaler of 16
TCC1.CTRLB = 0; TCC1.CTRLC = 0; TCC1.CTRLD = 0; TCC1.CTRLE = 0;
TCC1.INTCTRLA = 0; TIMSK1 = 0;
TCC1.PER = 0xFFFF ;
TCNT1 = 0 ;
TCC1.CTRLA = 0x0B ; // Event3 (prescale of 16)
TCC1.CTRLA = 0x0B ; // Event3 (prescale of 16)
#elif defined STM32_BOARD
//STM32
afio_cfg_debug_ports(AFIO_DEBUG_NONE);
pinMode(LED_pin,OUTPUT);
pinMode(LED2_pin,OUTPUT);
pinMode(A7105_CSN_pin,OUTPUT);
pinMode(CC25_CSN_pin,OUTPUT);
@@ -322,7 +331,7 @@ void setup()
pinMode(RX_INV_pin,OUTPUT);
#if defined TELEMETRY
#if defined INVERT_SERIAL
TX_INV_on; //activate inverter for both serial TX and RX signals
TX_INV_on; // activate inverter for both serial TX and RX signals
RX_INV_on;
#else
TX_INV_off;
@@ -331,11 +340,20 @@ void setup()
#endif
pinMode(BIND_pin,INPUT_PULLUP);
pinMode(PPM_pin,INPUT);
pinMode(S1_pin,INPUT_PULLUP);//dial switch
pinMode(S1_pin,INPUT_PULLUP); // dial switch
pinMode(S2_pin,INPUT_PULLUP);
pinMode(S3_pin,INPUT_PULLUP);
pinMode(S4_pin,INPUT_PULLUP);
#ifdef MULTI_5IN1_INTERNAL
//pinMode(SX1276_RST_pin,OUTPUT); // already done by LED2_pin
pinMode(SX1276_TXEN_pin,OUTPUT); // PB0
pinMode(SX1276_DIO0_pin,INPUT_PULLUP);
#else
//Random pin
pinMode(RND_pin, INPUT_ANALOG); // set up PB0 pin for analog input
#endif
#if defined ENABLE_DIRECT_INPUTS
#if defined (DI1_PIN)
pinMode(DI1_PIN,INPUT_PULLUP);
@@ -350,12 +368,52 @@ void setup()
pinMode(DI4_PIN,INPUT_PULLUP);
#endif
#endif
//Random pins
pinMode(PB0, INPUT_ANALOG); // set up pin for analog input
//Timers
init_HWTimer(); //0.5us
init_HWTimer(); //0.5us
//Read module flash size
#ifndef DISABLE_FLASH_SIZE_CHECK
unsigned short *flashSize = (unsigned short *) (0x1FFFF7E0);// Address register
debugln("Module Flash size: %dKB",(int)(*flashSize & 0xffff));
if((int)(*flashSize & 0xffff) < MCU_EXPECTED_FLASH_SIZE) // Not supported by this project
while (true) { //SOS
for(uint8_t i=0; i<3;i++)
{
LED_on;
delay(100);
LED_off;
delay(100);
}
for(uint8_t i=0; i<3;i++)
{
LED_on;
delay(500);
LED_off;
delay(100);
}
for(uint8_t i=0; i<3;i++)
{
LED_on;
delay(100);
LED_off;
delay(100);
}
LED_off;
delay(1000);
}
#endif
// Initialize the EEPROM
uint16_t eepromStatus = EEPROM.init();
debugln("EEPROM initialized: %d",eepromStatus);
// If there was no valid EEPROM page the EEPROM is corrupt or uninitialized and should be formatted
if( eepromStatus == EEPROM_NO_VALID_PAGE )
{
EEPROM.format();
debugln("No valid EEPROM page, EEPROM formatted");
}
#else
//ATMEGA328p
// all inputs
@@ -410,6 +468,10 @@ void setup()
#ifdef NRF_CSN_pin
NRF_CSN_on;
#endif
#ifdef SPI_CSN_pin
SPI_CSN_on;
#endif
// Set SPI lines
#ifdef STM32_BOARD
initSPI2();
@@ -473,7 +535,12 @@ void setup()
#ifdef STM32_BOARD
uint32_t seed=0;
for(uint8_t i=0;i<4;i++)
seed=(seed<<8) | (analogRead(PB0)& 0xFF);
#ifdef RND_pin
seed=(seed<<8) | (analogRead(RND_pin)& 0xFF);
#else
//TODO find something to randomize...
seed=(seed<<8);
#endif
randomSeed(seed);
#else
//Init the seed with a random value created from watchdog timer for all protocols requiring random values
@@ -485,7 +552,7 @@ void setup()
MProtocol_id_master=random_id(EEPROM_ID_OFFSET,false);
debugln("Module Id: %lx", MProtocol_id_master);
#ifdef ENABLE_PPM
//Protocol and interrupts initialization
if(mode_select != MODE_SERIAL)
@@ -519,13 +586,13 @@ void setup()
else
#endif
#if defined(FORCE_FRSKYX_TUNING) && defined(FRSKYX_CC2500_INO)
if(protocol==PROTO_FRSKYX)
if(protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2)
option = FORCE_FRSKYX_TUNING; // Use config-defined tuning value for FrSkyX
else
#endif
#if defined(FORCE_SFHSS_TUNING) && defined(SFHSS_CC2500_INO)
if (protocol==PROTO_SFHSS)
option = FORCE_SFHSS_TUNING; // Use config-defined tuning value for SFHSS
#if defined(FORCE_FUTABA_TUNING) && defined(FUTABA_CC2500_INO)
if (protocol==PROTO_FUTABA)
option = FORCE_FUTABA_TUNING; // Use config-defined tuning value for SFHSS
else
#endif
#if defined(FORCE_CORONA_TUNING) && defined(CORONA_CC2500_INO)
@@ -543,6 +610,11 @@ void setup()
option = FORCE_REDPINE_TUNING; // Use config-defined tuning value for REDPINE
else
#endif
#if defined(FORCE_RADIOLINK_TUNING) && defined(RADIOLINK_CC2500_INO)
if (protocol==PROTO_RADIOLINK)
option = FORCE_RADIOLINK_TUNING; // Use config-defined tuning value for RADIOLINK
else
#endif
#if defined(FORCE_HITEC_TUNING) && defined(HITEC_CC2500_INO)
if (protocol==PROTO_HITEC)
option = FORCE_HITEC_TUNING; // Use config-defined tuning value for HITEC
@@ -597,8 +669,8 @@ void setup()
#endif
#endif //ENABLE_SERIAL
}
LED2_on;
debugln("Init complete");
LED2_on;
}
// Main
@@ -676,6 +748,18 @@ void loop()
}
}
void End_Bind()
{
//Request protocol to terminate bind
if(protocol==PROTO_FRSKYD || protocol==PROTO_FRSKYL || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKYV || protocol==PROTO_FRSKY_R9
|| protocol==PROTO_DSM_RX || protocol==PROTO_AFHDS2A_RX || protocol==PROTO_FRSKY_RX || protocol==PROTO_BAYANG_RX
|| protocol==PROTO_AFHDS2A || protocol==PROTO_BUGS || protocol==PROTO_BUGSMINI || protocol==PROTO_HOTT || protocol==PROTO_ASSAN)
BIND_DONE;
else
if(bind_counter>2)
bind_counter=2;
}
bool Update_All()
{
#ifdef ENABLE_SERIAL
@@ -751,7 +835,7 @@ bool Update_All()
update_led_status();
#if defined(TELEMETRY)
#if ( !( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) ) )
if((protocol == PROTO_BAYANG_RX) || (protocol == PROTO_AFHDS2A_RX) || (protocol == PROTO_FRSKY_RX) || (protocol == PROTO_SCANNER) || (protocol==PROTO_FRSKYD) || (protocol==PROTO_BAYANG) || (protocol==PROTO_NCC1701) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_FRSKYX) || (protocol==PROTO_DSM) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_HOTT) || (protocol==PROTO_FRSKYX2) || (protocol==PROTO_PROPEL) || (protocol==PROTO_DEVO) || (protocol==PROTO_DSM_RX))
if((protocol == PROTO_BAYANG_RX) || (protocol == PROTO_AFHDS2A_RX) || (protocol == PROTO_FRSKY_RX) || (protocol == PROTO_SCANNER) || (protocol==PROTO_FRSKYD) || (protocol==PROTO_BAYANG) || (protocol==PROTO_NCC1701) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_FRSKYX) || (protocol==PROTO_FRSKYX2) || (protocol==PROTO_DSM) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_HOTT) || (protocol==PROTO_PROPEL) || (protocol==PROTO_OMP) || (protocol==PROTO_DEVO) || (protocol==PROTO_DSM_RX) || (protocol==PROTO_FRSKY_R9) || (protocol==PROTO_RLINK) || (protocol==PROTO_WFLY2) || (protocol==PROTO_LOLI))
#endif
if(IS_DISABLE_TELEM_off)
TelemetryUpdate();
@@ -766,14 +850,7 @@ bool Update_All()
if(IS_AUTOBIND_FLAG_on && IS_BIND_CH_PREV_on && Channel_data[BIND_CH-1]<CHANNEL_MIN_COMMAND)
{ // Autobind is on and BIND_CH went down
BIND_CH_PREV_off;
//Request protocol to terminate bind
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYL_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYV_CC2500_INO) || defined(AFHDS2A_A7105_INO)
if(protocol==PROTO_FRSKYD || protocol==PROTO_FRSKYL || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKYV || protocol==PROTO_AFHDS2A )
BIND_DONE;
else
#endif
if(bind_counter>2)
bind_counter=2;
End_Bind();
}
#endif //ENABLE_BIND_CH
if(IS_CHANGE_PROTOCOL_FLAG_on)
@@ -1015,6 +1092,9 @@ static void protocol_init()
next_callback=0; // Default is immediate call back
LED_off; // Led off during protocol init
modules_reset(); // Reset all modules
crc16_polynomial = 0x1021; // Default CRC crc16_polynomial
crc8_polynomial = 0x31; // Default CRC crc8_polynomial
prev_option = option;
// reset telemetry
#ifdef TELEMETRY
@@ -1026,6 +1106,8 @@ static void protocol_init()
#endif
tx_pause();
init_frskyd_link_telemetry();
pps_timer=millis();
pps_counter=0;
#ifdef BASH_SERIAL
TIMSK0 = 0 ; // Stop all timer 0 interrupts
#ifdef INVERT_SERIAL
@@ -1048,7 +1130,8 @@ static void protocol_init()
rx_rc_chan[ch] = 1024;
#endif
#endif
binding_idx=0;
//Set global ID and rx_tx_addr
MProtocol_id = RX_num + MProtocol_id_master;
set_rx_tx_addr(MProtocol_id);
@@ -1095,11 +1178,11 @@ static void protocol_init()
remote_callback = ReadBUGS;
break;
#endif
#if defined(FLYZONE_A7105_INO)
case PROTO_FLYZONE:
#if defined(HEIGHT_A7105_INO)
case PROTO_HEIGHT:
PE1_off; //antenna RF1
next_callback = initFlyzone();
remote_callback = ReadFlyzone;
next_callback = initHeight();
remote_callback = ReadHeight;
break;
#endif
#if defined(AFHDS2A_RX_A7105_INO)
@@ -1116,6 +1199,20 @@ static void protocol_init()
remote_callback = ReadPelikan;
break;
#endif
#if defined(KYOSHO_A7105_INO)
case PROTO_KYOSHO:
PE1_off; //antenna RF1
next_callback = initKyosho();
remote_callback = ReadKyosho;
break;
#endif
#if defined(WFLY2_A7105_INO)
case PROTO_WFLY2:
PE1_off; //antenna RF1
next_callback = initWFLY2();
remote_callback = ReadWFLY2;
break;
#endif
#endif
#ifdef CC2500_INSTALLED
#if defined(FRSKYD_CC2500_INO)
@@ -1145,14 +1242,18 @@ static void protocol_init()
#if defined(FRSKYX_CC2500_INO)
case PROTO_FRSKYX:
case PROTO_FRSKYX2:
#ifdef EU_MODULE
if(sub_protocol<2)
break;
#endif
PE1_off; //antenna RF2
PE2_on;
next_callback = initFrSkyX();
remote_callback = ReadFrSkyX;
break;
#endif
#if defined(SFHSS_CC2500_INO)
case PROTO_SFHSS:
#if defined(FUTABA_CC2500_INO)
case PROTO_FUTABA:
PE1_off; //antenna RF2
PE2_on;
next_callback = initSFHSS();
@@ -1223,6 +1324,22 @@ static void protocol_init()
remote_callback = ESKY150V2_callback;
break;
#endif
#if defined(RLINK_CC2500_INO)
case PROTO_RLINK:
PE1_off;
PE2_on; //antenna RF2
next_callback = initRLINK();
remote_callback = RLINK_callback;
break;
#endif
#if defined(E016HV2_CC2500_INO)
case PROTO_E016HV2:
PE1_off;
PE2_on; //antenna RF2
next_callback = initE016HV2();
remote_callback = E016HV2_callback;
break;
#endif
#endif
#ifdef CYRF6936_INSTALLED
#if defined(DSM_CYRF6936_INO)
@@ -1246,6 +1363,27 @@ static void protocol_init()
remote_callback = ReadWFLY;
break;
#endif
#if defined(MLINK_CYRF6936_INO)
case PROTO_MLINK:
PE2_on; //antenna RF4
next_callback = initMLINK();
remote_callback = ReadMLINK;
break;
#endif
#if defined(E010R5_CYRF6936_INO)
case PROTO_E010R5:
PE2_on; //antenna RF4
next_callback = initE010R5();
remote_callback = ReadE010R5;
break;
#endif
#if defined(E129_CYRF6936_INO)
case PROTO_E129:
PE2_on; //antenna RF4
next_callback = initE129();
remote_callback = ReadE129;
break;
#endif
#if defined(DEVO_CYRF6936_INO)
case PROTO_DEVO:
#ifdef ENABLE_PPM
@@ -1374,6 +1512,12 @@ static void protocol_init()
remote_callback = MT99XX_callback;
break;
#endif
#if defined(LOLI_NRF24L01_INO)
case PROTO_LOLI:
next_callback=initLOLI();
remote_callback = LOLI_callback;
break;
#endif
#if defined(MJXQ_NRF24L01_INO)
case PROTO_MJXQ:
next_callback=initMJXQ();
@@ -1548,6 +1692,36 @@ static void protocol_init()
remote_callback = JJRC345_callback;
break;
#endif
#if defined(Q90C_NRF24L01_INO)
case PROTO_Q90C:
next_callback=initQ90C();
remote_callback = Q90C_callback;
break;
#endif
#if defined(REALACC_NRF24L01_INO)
case PROTO_REALACC:
next_callback=initREALACC();
remote_callback = REALACC_callback;
break;
#endif
#if defined(OMP_CC2500_INO)
case PROTO_OMP:
next_callback=initOMP();
remote_callback = OMP_callback;
break;
#endif
#if defined(TEST_CC2500_INO)
case PROTO_TEST:
next_callback=initTEST();
remote_callback = TEST_callback;
break;
#endif
#if defined(NANORF_NRF24L01_INO)
case PROTO_NANORF:
next_callback=initNANORF();
remote_callback = NANORF_callback;
break;
#endif
#endif
#ifdef SX1276_INSTALLED
#if defined(FRSKYR9_SX1276_INO)
@@ -1670,13 +1844,13 @@ void update_serial_data()
else
#endif
#if defined(FORCE_FRSKYX_TUNING) && defined(FRSKYX_CC2500_INO)
if(protocol==PROTO_FRSKYX)
if(protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2)
option=FORCE_FRSKYX_TUNING; // Use config-defined tuning value for FrSkyX
else
#endif
#if defined(FORCE_SFHSS_TUNING) && defined(SFHSS_CC2500_INO)
if (protocol==PROTO_SFHSS)
option=FORCE_SFHSS_TUNING; // Use config-defined tuning value for SFHSS
#if defined(FORCE_FUTABA_TUNING) && defined(FUTABA_CC2500_INO)
if (protocol==PROTO_FUTABA)
option=FORCE_FUTABA_TUNING; // Use config-defined tuning value for SFHSS
else
#endif
#if defined(FORCE_CORONA_TUNING) && defined(CORONA_CC2500_INO)
@@ -1694,6 +1868,11 @@ void update_serial_data()
option=FORCE_REDPINE_TUNING; // Use config-defined tuning value for REDPINE
else
#endif
#if defined(FORCE_RADIOLINK_TUNING) && defined(RADIOLINK_CC2500_INO)
if (protocol==PROTO_RADIOLINK)
option = FORCE_RADIOLINK_TUNING; // Use config-defined tuning value for RADIOLINK
else
#endif
#if defined(FORCE_HITEC_TUNING) && defined(HITEC_CC2500_INO)
if (protocol==PROTO_HITEC)
option=FORCE_HITEC_TUNING; // Use config-defined tuning value for HITEC
@@ -1781,13 +1960,7 @@ void update_serial_data()
else
if( ((rx_ok_buff[1]&0x80)==0) && ((cur_protocol[1]&0x80)!=0) ) // Bind flag has been reset
{ // Request protocol to end bind
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYL_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYV_CC2500_INO) || defined(AFHDS2A_A7105_INO) || defined(FRSKYR9_SX1276_INO)
if(protocol==PROTO_FRSKYD || protocol==PROTO_FRSKYL || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKYV || protocol==PROTO_AFHDS2A || protocol==PROTO_FRSKY_R9 )
BIND_DONE;
else
#endif
if(bind_counter>2)
bind_counter=2;
End_Bind();
}
//store current protocol values
@@ -1841,14 +2014,14 @@ void update_serial_data()
#endif
if(rx_len>27)
{ // Data available for the current protocol
#if defined FRSKYX_CC2500_INO
if((protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2) && rx_len==28)
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYR9_SX1276_INO)
if((protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKY_R9) && rx_len==28)
{//Protocol waiting for 1 byte during bind
binding_idx=rx_ok_buff[27];
}
#endif
#ifdef SPORT_SEND
if((protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2) && rx_len==35)
if((protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKY_R9) && rx_len==27+8)
{//Protocol waiting for 8 bytes
#define BYTE_STUFF 0x7D
#define STUFF_MASK 0x20
@@ -1892,12 +2065,19 @@ void update_serial_data()
}
#endif //SPORT_SEND
#ifdef HOTT_FW_TELEMETRY
if(protocol==PROTO_HOTT && rx_len==28)
if(protocol==PROTO_HOTT && rx_len==27+1)
{//Protocol waiting for 1 byte
HoTT_SerialRX_val=rx_ok_buff[27];
HoTT_SerialRX=true;
}
#endif
#ifdef DSM_FWD_PGM
if(protocol==PROTO_DSM && rx_len==27+7)
{//Protocol waiting for 7 bytes
memcpy(DSM_SerialRX_val, (const void *)&rx_ok_buff[27],7);
DSM_SerialRX=true;
}
#endif
}
RX_DONOTUPDATE_off;
@@ -2142,7 +2322,7 @@ void pollBoot()
#if defined(TELEMETRY)
void PPM_Telemetry_serial_init()
{
if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_BAYANG)|| (protocol==PROTO_NCC1701) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_PROPEL)
if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_BAYANG)|| (protocol==PROTO_NCC1701) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_PROPEL) || (protocol==PROTO_OMP) || (protocol==PROTO_RLINK) || (protocol==PROTO_WFLY2) || (protocol==PROTO_LOLI)
#ifdef TELEMETRY_FRSKYX_TO_FRSKYD
|| (protocol==PROTO_FRSKYX) || (protocol==PROTO_FRSKYX2)
#endif
@@ -2253,6 +2433,37 @@ static void __attribute__((unused)) calc_fh_channels(uint8_t num_ch)
}
}
static uint8_t __attribute__((unused)) bit_reverse(uint8_t b_in)
{
uint8_t b_out = 0;
for (uint8_t i = 0; i < 8; ++i)
{
b_out = (b_out << 1) | (b_in & 1);
b_in >>= 1;
}
return b_out;
}
static void __attribute__((unused)) crc16_update(uint8_t a, uint8_t bits)
{
crc ^= a << 8;
while(bits--)
if (crc & 0x8000)
crc = (crc << 1) ^ crc16_polynomial;
else
crc = crc << 1;
}
static void __attribute__((unused)) crc8_update(uint8_t byte)
{
crc8 = crc8 ^ byte;
for ( uint8_t j = 0; j < 8; j++ )
if ( crc8 & 0x80 )
crc8 = (crc8<<1) ^ crc8_polynomial;
else
crc8 <<= 1;
}
/**************************/
/**************************/
/** Interrupt routines **/
@@ -2405,7 +2616,7 @@ static void __attribute__((unused)) calc_fh_channels(uint8_t num_ch)
ISR(TIMER1_COMPB_vect)
#endif
{ // Timer1 compare B interrupt
if(rx_idx>=26 && rx_idx<RXBUFFER_SIZE)
if(rx_idx>=26 && rx_idx<=RXBUFFER_SIZE)
{
// A full frame has been received
if(!IS_RX_DONOTUPDATE_on)
@@ -2424,7 +2635,7 @@ static void __attribute__((unused)) calc_fh_channels(uint8_t num_ch)
}
#ifdef DEBUG_SERIAL
else
debugln("RX frame too short");
debugln("RX frame size incorrect");
#endif
discard_frame=true;
#ifdef STM32_BOARD

View File

@@ -58,11 +58,11 @@ static void __attribute__((unused)) NCC_init()
const uint8_t NCC_xor[]={0x80, 0x44, 0x64, 0x75, 0x6C, 0x71, 0x2A, 0x36, 0x7C, 0xF1, 0x6E, 0x52, 0x09, 0x9D};
static void __attribute__((unused)) NCC_Crypt_Packet()
{
uint16_t crc=0;
crc=0;
for(uint8_t i=0; i< NCC_TX_PACKET_LEN-2; i++)
{
packet[i]^=NCC_xor[i];
crc=crc16_update(crc, packet[i], 8);
crc16_update(packet[i], 8);
}
crc^=0x60DE;
packet[NCC_TX_PACKET_LEN-2]=crc>>8;
@@ -70,11 +70,11 @@ static void __attribute__((unused)) NCC_Crypt_Packet()
}
static boolean __attribute__((unused)) NCC_Decrypt_Packet()
{
uint16_t crc=0;
crc=0;
debug("RX: ");
for(uint8_t i=0; i< NCC_RX_PACKET_LEN-2; i++)
{
crc=crc16_update(crc, packet[i], 8);
crc16_update( packet[i], 8);
packet[i]^=NCC_xor[i];
debug("%02X ",packet[i]);
}

View File

@@ -300,29 +300,6 @@ const uint16_t xn297_crc_xorout_enhanced[] = {
0xABFC, 0xE68E, 0x0DE7, 0x28A2, 0x1965 };
#endif
static uint8_t bit_reverse(uint8_t b_in)
{
uint8_t b_out = 0;
for (uint8_t i = 0; i < 8; ++i)
{
b_out = (b_out << 1) | (b_in & 1);
b_in >>= 1;
}
return b_out;
}
static const uint16_t polynomial = 0x1021;
static uint16_t crc16_update(uint16_t crc, uint8_t a, uint8_t bits)
{
crc ^= a << 8;
while(bits--)
if (crc & 0x8000)
crc = (crc << 1) ^ polynomial;
else
crc = crc << 1;
return crc;
}
void XN297_SetTXAddr(const uint8_t* addr, uint8_t len)
{
if (len > 5) len = 5;
@@ -401,9 +378,9 @@ void XN297_WritePayload(uint8_t* msg, uint8_t len)
if (xn297_crc)
{
uint8_t offset = xn297_addr_len < 4 ? 1 : 0;
uint16_t crc = 0xb5d2;
crc = 0xb5d2;
for (uint8_t i = offset; i < last; ++i)
crc = crc16_update(crc, buf[i], 8);
crc16_update( buf[i], 8);
if(xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
else
@@ -466,10 +443,10 @@ void XN297_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
if (xn297_crc)
{
uint8_t offset = xn297_addr_len < 4 ? 1 : 0;
uint16_t crc = 0xb5d2;
crc = 0xb5d2;
for (uint8_t i = offset; i < last; ++i)
crc = crc16_update(crc, packet[i], 8);
crc = crc16_update(crc, packet[last] & 0xc0, 2);
crc16_update( packet[i], 8);
crc16_update( packet[last] & 0xc0, 2);
if (xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
//else
@@ -505,18 +482,18 @@ boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
return true; // No CRC so OK by default...
// Calculate CRC
uint16_t crc = 0xb5d2;
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);
crc16_update( b_in, 8);
}
//process payload
for (uint8_t i = 0; i < len; ++i)
crc = crc16_update(crc, buf[i], 8);
crc16_update( buf[i], 8);
//xorout
if(xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
@@ -529,7 +506,7 @@ boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
}
uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
{ //!!! Don't forget do a +2 and if using CRC add +2 on any of the used NRF24L01_11_RX_PW_Px !!!
{ //!!! Don't forget do a +2 and if using CRC add +4 on any of the used NRF24L01_11_RX_PW_Px !!!
uint8_t buffer[32];
uint8_t pcf_size; // pcf payload size
if (xn297_crc)
@@ -552,19 +529,19 @@ uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
return pcf_size; // No CRC so OK by default...
// Calculate CRC
uint16_t crc = 0xb5d2;
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);
crc16_update( 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);
crc16_update( buffer[i], 8);
crc16_update( buffer[len+1] & 0xc0, 2);
//xorout
if (xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
@@ -606,9 +583,10 @@ void HS6200_SetTXAddr(const uint8_t* addr, uint8_t len)
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\xaa\xaa\xaa\xaa\xaa", 5);
// precompute address crc
hs6200_crc_init = 0xffff;
crc = 0xffff;
for(int i=0; i<len; i++)
hs6200_crc_init = crc16_update(hs6200_crc_init, addr[len-1-i], 8);
crc16_update(addr[len-1-i], 8);
hs6200_crc_init=crc;
memcpy(hs6200_tx_addr, addr, len);
hs6200_address_length = len;
}
@@ -616,14 +594,14 @@ void HS6200_SetTXAddr(const uint8_t* addr, uint8_t len)
static uint16_t hs6200_calc_crc(uint8_t* msg, uint8_t len)
{
uint8_t pos;
uint16_t crc = hs6200_crc_init;
crc = hs6200_crc_init;
// pcf + payload
for(pos=0; pos < len-1; pos++)
crc = crc16_update(crc, msg[pos], 8);
crc16_update(msg[pos], 8);
// last byte (1 bit only)
if(len > 0)
crc = crc16_update(crc, msg[pos+1], 1);
crc16_update(msg[pos+1], 1);
return crc;
}
@@ -797,7 +775,8 @@ void LT8900_SetAddress(uint8_t *address,uint8_t addr_size)
uint8_t LT8900_ReadPayload(uint8_t* msg, uint8_t len)
{
uint8_t i,pos=0,shift,end,buffer[32];
unsigned int crc=LT8900_CRC_Initial_Data,a;
unsigned int a;
crc=LT8900_CRC_Initial_Data;
pos=LT8900_buffer_overhead_bits/8-LT8900_buffer_start;
end=pos+len+(LT8900_Flags&_BV(LT8900_PACKET_LENGTH_EN)?1:0)+(LT8900_Flags&_BV(LT8900_CRC_ON)?2:0);
//Read payload
@@ -817,14 +796,14 @@ uint8_t LT8900_ReadPayload(uint8_t* msg, uint8_t len)
//Check len
if(LT8900_Flags&_BV(LT8900_PACKET_LENGTH_EN))
{
crc=crc16_update(crc,buffer[pos],8);
crc16_update(buffer[pos],8);
if(bit_reverse(len)!=buffer[pos++])
return 0; // wrong len...
}
//Decode message
for(i=0;i<len;i++)
{
crc=crc16_update(crc,buffer[pos],8);
crc16_update(buffer[pos],8);
msg[i]=bit_reverse(buffer[pos++]);
}
//Check CRC
@@ -839,21 +818,22 @@ uint8_t LT8900_ReadPayload(uint8_t* msg, uint8_t len)
void LT8900_WritePayload(uint8_t* msg, uint8_t len)
{
unsigned int crc=LT8900_CRC_Initial_Data,a,mask;
unsigned int a,mask;
uint8_t i, pos=0,tmp, buffer[64], pos_final,shift;
crc=LT8900_CRC_Initial_Data;
//Add packet len
if(LT8900_Flags&_BV(LT8900_PACKET_LENGTH_EN))
{
tmp=bit_reverse(len);
buffer[pos++]=tmp;
crc=crc16_update(crc,tmp,8);
crc16_update(tmp,8);
}
//Add payload
for(i=0;i<len;i++)
{
tmp=bit_reverse(msg[i]);
buffer[pos++]=tmp;
crc=crc16_update(crc,tmp,8);
crc16_update(tmp,8);
}
//Add CRC
if(LT8900_Flags&_BV(LT8900_CRC_ON))

View File

@@ -17,6 +17,7 @@
static void __attribute__((unused)) XN297L_Init()
{
prev_option = option;
#ifdef CC2500_INSTALLED
if(option==0)
#endif
@@ -38,56 +39,10 @@ static void __attribute__((unused)) XN297L_Init()
//CC2500
#ifdef CC2500_INSTALLED
debugln("Using CC2500");
xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
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
CC2500_250K_Init();
#endif
}
@@ -126,7 +81,6 @@ static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t le
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)
@@ -147,9 +101,9 @@ static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t le
}
// crc
uint16_t crc = initial;
crc = 0xb5d2;
for (uint8_t i = 0; i < last; ++i)
crc = crc16_update(crc, buf[i], 8);
crc16_update( buf[i], 8);
if(xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
else
@@ -192,13 +146,6 @@ static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, ui
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];
@@ -235,11 +182,10 @@ static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, ui
// 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);
crc = 0xb5d2;
for (uint8_t i = 0; i < last; ++i)
crc16_update( buf[i], 8);
crc16_update( buf[last] & 0xc0, 2);
if (xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
//else
@@ -275,14 +221,7 @@ static void __attribute__((unused)) XN297L_HoppingCalib(uint8_t num_freq)
#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);
}
CC2500_250K_HoppingCalib(num_freq);
#endif
}
@@ -296,10 +235,7 @@ static void __attribute__((unused)) XN297L_Hopping(uint8_t 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]);
CC2500_250K_Hopping(index);
#endif
}
@@ -313,10 +249,7 @@ static void __attribute__((unused)) XN297L_RFChannel(uint8_t number)
return;
}
#ifdef CC2500_INSTALLED
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, number*3);
CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);
CC2500_250K_RFChannel(number);
#endif
}
@@ -344,9 +277,8 @@ static void __attribute__((unused)) XN297L_SetFreqOffset()
if (prev_option != option)
{
if(prev_option==0 || option==0)
CHANGE_PROTOCOL_FLAG_on;
prev_option = option;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
CHANGE_PROTOCOL_FLAG_on; // switch from NRF <-> CC2500
CC2500_SetFreqOffset();
}
#endif
}
@@ -365,8 +297,7 @@ static void __attribute__((unused)) NRF250K_SetTXAddr(uint8_t* addr, uint8_t len
}
//CC2500
#ifdef CC2500_INSTALLED
xn297_addr_len = len;
memcpy(xn297_tx_addr, addr, len);
CC2500_250K_NRF_SetTXAddr(addr, len);
#endif
}
@@ -383,78 +314,7 @@ static void __attribute__((unused)) NRF250K_WritePayload(uint8_t* msg, uint8_t l
}
//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);
}
CC2500_250K_NRF_WritePayload(msg, len);
#endif
}

View File

@@ -0,0 +1,73 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(NANORF_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define NANORF_PACKET_PERIOD 40000
#define NANORF_INITIAL_WAIT 500
#define NANORF_RF_CHANNEL 40
#define NANORF_PAYLOADSIZE 7
static void __attribute__((unused)) NANORF_send_packet()
{
packet[0] = convert_channel_8b(AILERON);
packet[1] = convert_channel_8b(ELEVATOR);
packet[2] = convert_channel_8b(THROTTLE);
packet[3] = convert_channel_8b(RUDDER);
packet[4] = convert_channel_8b(CH5);
packet[5] = convert_channel_8b(CH6);
packet[6] = 0;
for (uint8_t i=0; i < NANORF_PAYLOADSIZE-1; i++)
packet[6] += packet[i];
packet[6] += 0x55;
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
NRF24L01_WritePayload(packet, NANORF_PAYLOADSIZE);
}
static void __attribute__((unused)) NANORF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR , (uint8_t *)"Nano1",5);
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable all data pipes (even though not used?)
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // 4mS retransmit t/o, 15 tries (retries w/o AA?)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, NANORF_RF_CHANNEL);
NRF24L01_SetBitrate(NRF24L01_BR_1M);
NRF24L01_SetPower(); // Set tx_power
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP)); //
}
uint16_t NANORF_callback()
{
NANORF_send_packet();
return NANORF_PACKET_PERIOD;
}
uint16_t initNANORF()
{
BIND_DONE;
NANORF_init();
return NANORF_INITIAL_WAIT;
}
#endif

View File

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

View File

@@ -19,11 +19,14 @@
#include "iface_a7105.h"
//#define PELIKAN_FORCE_ID
//#define PELIKAN_LITE_FORCE_ID
#define PELIKAN_LITE_FORCE_HOP
#define PELIKAN_BIND_COUNT 400
#define PELIKAN_BIND_RF 0x3C
#define PELIKAN_NUM_RF_CHAN 0x1D
#define PELIKAN_PAQUET_PERIOD 7980
#define PELIKAN_PACKET_PERIOD 7980
#define PELIKAN_LITE_PACKET_PERIOD 18000
static void __attribute__((unused)) pelikan_build_packet()
{
@@ -36,7 +39,10 @@ static void __attribute__((unused)) pelikan_build_packet()
packet[3] = rx_tx_addr[1];
packet[4] = rx_tx_addr[2];
packet[5] = rx_tx_addr[3];
packet[6] = 0x05; //??
if(sub_protocol==PELIKAN_PRO)
packet[6] = 0x05; //sub version??
else //PELIKAN_LITE
packet[6] = 0x03; //sub version??
packet[7] = 0x00; //??
packet[8] = 0x55; //??
packet_length = 10;
@@ -50,16 +56,16 @@ static void __attribute__((unused)) pelikan_build_packet()
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);
uint16_t channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871,false);
uint8_t top=(channel>>2) & 0xC0;
packet[2] = channel;
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871);
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871,false);
top|=(channel>>4) & 0x30;
packet[3] = channel;
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871);
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871,false);
top|=(channel>>6) & 0x0C;
packet[4] = channel;
channel=convert_channel_16b_nolimit(CH_AETR[offset], 153, 871);
channel=convert_channel_16b_nolimit(CH_AETR[offset], 153, 871,false);
top|=(channel>>8) & 0x03;
packet[5] = channel;
packet[6] = top;
@@ -72,7 +78,7 @@ static void __attribute__((unused)) pelikan_build_packet()
packet[9]=upper?0xAA:0x00;
upper=!upper;
//Hopping counters
if(++packet_count>4)
if(sub_protocol==PELIKAN_LITE || ++packet_count>4)
{
packet_count=0;
if(++hopping_frequency_no>=PELIKAN_NUM_RF_CHAN)
@@ -106,24 +112,41 @@ static void __attribute__((unused)) pelikan_build_packet()
uint16_t ReadPelikan()
{
#ifndef FORCE_PELIKAN_TUNING
A7105_AdjustLOBaseFreq(1);
#endif
if(IS_BIND_IN_PROGRESS)
if(phase==0)
{
bind_counter--;
if (bind_counter==0)
#ifndef FORCE_PELIKAN_TUNING
A7105_AdjustLOBaseFreq(1);
#endif
if(IS_BIND_IN_PROGRESS)
{
BIND_DONE;
A7105_Strobe(A7105_STANDBY);
A7105_WriteReg(A7105_03_FIFOI,0x28);
bind_counter--;
if (bind_counter==0)
{
BIND_DONE;
A7105_Strobe(A7105_STANDBY);
if(sub_protocol==PELIKAN_PRO)
A7105_WriteReg(A7105_03_FIFOI,0x28);
else//PELIKAN_LITE
A7105_WriteID(MProtocol_id);
}
}
#ifdef MULTI_SYNC
telemetry_set_input_sync(sub_protocol==PELIKAN_PRO?PELIKAN_PACKET_PERIOD:PELIKAN_LITE_PACKET_PERIOD);
#endif
pelikan_build_packet();
if(sub_protocol==PELIKAN_PRO || IS_BIND_IN_PROGRESS)
return PELIKAN_PACKET_PERIOD;
//PELIKAN_LITE
phase++;
return 942;
}
#ifdef MULTI_SYNC
telemetry_set_input_sync(PELIKAN_PAQUET_PERIOD);
#endif
pelikan_build_packet();
return PELIKAN_PAQUET_PERIOD;
//PELIKAN_LITE
A7105_Strobe(A7105_TX);
phase++;
if(phase==1)
return 942;
phase=0;
return PELIKAN_LITE_PACKET_PERIOD-942-942;
}
static uint8_t pelikan_firstCh(uint8_t u, uint8_t l)
@@ -213,27 +236,58 @@ const uint8_t PROGMEM pelikan_hopp[][PELIKAN_NUM_RF_CHAN] = {
};
#endif
#ifdef PELIKAN_LITE_FORCE_HOP
const uint8_t PROGMEM pelikan_lite_hopp[][PELIKAN_NUM_RF_CHAN] = {
{ 0x46,0x2A,0x3E,0x5A,0x5C,0x24,0x4E,0x32,0x54,0x26,0x2C,0x34,0x56,0x1E,0x3A,0x3C,0x50,0x4A,0x2E,0x42,0x20,0x52,0x28,0x22,0x44,0x58,0x36,0x38,0x4C }
};
#endif
uint16_t initPelikan()
{
A7105_Init();
if(IS_BIND_IN_PROGRESS)
if(IS_BIND_IN_PROGRESS || sub_protocol==PELIKAN_LITE)
A7105_WriteReg(A7105_03_FIFOI,0x10);
pelikan_init_hop();
//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();
#if defined(PELIKAN_FORCE_ID)
if(sub_protocol==PELIKAN_PRO)
{
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]);
}
#endif
#if defined(PELIKAN_LITE_FORCE_ID) || defined(PELIKAN_LITE_FORCE_HOP)
if(sub_protocol==PELIKAN_LITE)
{
#if defined(PELIKAN_LITE_FORCE_ID)
// ID
rx_tx_addr[2]=0x60;
rx_tx_addr[3]=0x18;
#endif
#if defined(PELIKAN_LITE_FORCE_HOP)
// Hop frequency table
rx_tx_addr[0]=0x04; // hopping freq
rx_tx_addr[1]=0x63; // hopping freq
for(uint8_t i=0;i<PELIKAN_NUM_RF_CHAN;i++)
hopping_frequency[i]=pgm_read_byte_near(&pelikan_lite_hopp[0][i]);
#endif
}
#endif
MProtocol_id=((uint32_t)rx_tx_addr[0]<<24)|((uint32_t)rx_tx_addr[1]<<16)|((uint32_t)rx_tx_addr[2]<<8)|(rx_tx_addr[3]);
if(sub_protocol==PELIKAN_LITE && IS_BIND_DONE)
A7105_WriteID(MProtocol_id);
hopping_frequency_no=PELIKAN_NUM_RF_CHAN;
packet_count=5;
phase=0;
return 2400;
}
#endif

View File

@@ -223,6 +223,8 @@
#define S3_pin PA6
#define S4_pin PA7
//
#define RND_pin PB0
//
#define PE1_pin PB4 //PE1
#define PE2_pin PB5 //PE2
//CS pins
@@ -313,6 +315,20 @@
#define DEBUG_PIN_toggle
#endif
#ifdef MULTI_5IN1_INTERNAL
#undef RND_pin
#define SX1276_RST_pin PA2 //LED2 on other modules
#define SX1276_TXEN_pin PB0 //Random gen on other modules
#define SX1276_DIO0_pin PC13 //Unused on other modules
#define SX1276_RST_on digitalWrite(SX1276_RST_pin,HIGH)
#define SX1276_RST_off digitalWrite(SX1276_RST_pin,LOW)
#define SX1276_TXEN_on digitalWrite(SX1276_TXEN_pin,HIGH)
#define SX1276_RXEN_on digitalWrite(SX1276_TXEN_pin,LOW)
#define IS_DIO0_on ( digitalRead(SX1276_DIO0_pin)==HIGH )
#define IS_DIO0_off ( digitalRead(SX1276_DIO0_pin)==LOW )
#endif
#define cli() noInterrupts()
#define sei() interrupts()
#define delayMilliseconds(x) delay(x)

View File

@@ -252,28 +252,30 @@ uint16_t PROPEL_callback()
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;
#ifdef PROPEL_HUB_TELEMETRY
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;
}
}
}
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;
}
#endif
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;

View File

@@ -0,0 +1,176 @@
/*
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 Q90C quad.
#if defined(Q90C_NRF24L01_INO)
#include "iface_nrf250k.h"
//#define FORCE_Q90C_ORIGINAL_ID
#define Q90C_BIND_COUNT 250
#define Q90C_PACKET_PERIOD 7336 // 6200 on saimat's TX...
#define Q90C_INITIAL_WAIT 500
#define Q90C_PACKET_SIZE 12
#define Q90C_RF_BIND_CHANNEL 0x33
#define Q90C_RF_NUM_CHANNELS 3
#define Q90C_ADDRESS_LENGTH 5
bool Q90C_VTX;
int16_t Q90C_channel(uint8_t num, int16_t in_min,int16_t in_max, int16_t out_min,int16_t out_max)
{
int32_t val=Channel_data[num];
if(val<in_min) val=in_min;
else if(val>in_max) val=in_max;
val=(val-in_min)*(out_max-out_min)/(in_max-in_min)+out_min;
return (uint16_t)val;
}
static void __attribute__((unused)) Q90C_send_packet()
{
if(IS_BIND_IN_PROGRESS)
{
memcpy(packet, rx_tx_addr, 4);
memcpy(&packet[4], hopping_frequency, 3);
//packet[7] = 0x1e; // 2e on Saimat 1???
packet[10] = 0x4B;
packet[11] = 0x4E;
}
else
{
XN297L_Hopping(hopping_frequency_no++); // RF Freq
hopping_frequency_no %= Q90C_RF_NUM_CHANNELS;
packet[0]= convert_channel_8b(THROTTLE); // 0..255
// A,E,R have weird scaling, 0x00-0xff range (unsigned) but center isn't 7f or 80
// rudder ff-7a-00
if (Channel_data[RUDDER] <= CHANNEL_MID)
packet[1] = Q90C_channel(RUDDER, CHANNEL_MIN_100, CHANNEL_MID, 0xff, 0x7a );
else
packet[1] = Q90C_channel(RUDDER, CHANNEL_MID, CHANNEL_MAX_100, 0x7a, 0x00 );
// elevator 00-88-ff
if (Channel_data[ELEVATOR] <= CHANNEL_MID)
packet[2] = Q90C_channel(ELEVATOR, CHANNEL_MIN_100, CHANNEL_MID, 0x00, 0x88);
else
packet[2] = Q90C_channel(ELEVATOR, CHANNEL_MID, CHANNEL_MAX_100, 0x88, 0xff);
// aileron ff-88-00
if (Channel_data[AILERON] <= CHANNEL_MID)
packet[3] = Q90C_channel(AILERON, CHANNEL_MIN_100, CHANNEL_MID, 0xff, 0x88);
else
packet[3] = Q90C_channel(AILERON, CHANNEL_MID, CHANNEL_MAX_100, 0x88, 0x00);
// required to "arm" (low throttle + aileron to the right)
if (packet[0] < 5 && packet[3] < 25) {
packet[1] = 0x7a;
packet[2] = 0x88;
}
packet[4] = 0x1e; // T trim 00-1e-3c
packet[5] = 0x1e; // R trim 3c-1e-00
packet[6] = 0x1e; // E trim 00-1e-3c
//packet[7] = 0x1e; // A trim 00-1e-3c
packet[8] |= 0x02; // Rudder rate 0=min,1,2=max
if(state!=Channel_data[CH5])
{
state=Channel_data[CH5];
if(state<CHANNEL_MIN_COMMAND)
packet[8] ^= 0x04; // Angle
else if(state>CHANNEL_MAX_COMMAND)
packet[8] ^= 0x10; // Acro
else
packet[8] ^= 0x08; // Horizon
}
if(!Q90C_VTX && CH6_SW)
packet[8] ^= 0x20; // VTX+
Q90C_VTX=CH6_SW;
debugln("8=%02X",packet[8]);
packet[10] = packet_count++;
}
packet[7] = 0x1e; // bind 1e or 2e, normal: A trim 00-1e-3c
// checksum
if(IS_BIND_DONE)
{
uint8_t sum=0;
for (uint8_t i = 0; i < Q90C_PACKET_SIZE - 1; i++)
sum += packet[i];
packet[11] = sum ^ crc8;
}
XN297L_SetFreqOffset(); // Set frequency offset
XN297L_SetPower(); // Set tx_power
XN297L_WriteEnhancedPayload(packet, Q90C_PACKET_SIZE, 0);
}
static void __attribute__((unused)) Q90C_initialize_txid()
{
calc_fh_channels(Q90C_RF_NUM_CHANNELS);
rx_tx_addr[4]=0x4B;
#ifdef FORCE_Q90C_ORIGINAL_ID
//24 03 01 82 18 26 37 1E 00 00 4B 4E
memcpy(rx_tx_addr, (uint8_t*)"\x24\x03\x01\x82\x4B", Q90C_ADDRESS_LENGTH); //Goebish
memcpy(hopping_frequency, (uint8_t*)"\x18\x26\x37", Q90C_RF_NUM_CHANNELS);
//4C 0A 02 01 17 24 36 2E 00 00 4B 4E
memcpy(rx_tx_addr, (uint8_t*)"\x4C\x0A\x02\x01\x4B", Q90C_ADDRESS_LENGTH); //Saimat 1
memcpy(hopping_frequency, (uint8_t*)"\x17\x24\x36", Q90C_RF_NUM_CHANNELS);
//34 13 02 01 18 26 37 1E 00 00 4B 4E
memcpy(rx_tx_addr, (uint8_t*)"\x34\x13\x02\x01\x4B", Q90C_ADDRESS_LENGTH); //Saimat 2
memcpy(hopping_frequency, (uint8_t*)"\x18\x26\x37", Q90C_RF_NUM_CHANNELS);
#endif
crc8=rx_tx_addr[0]^rx_tx_addr[1]^rx_tx_addr[2]^rx_tx_addr[3];
}
static void __attribute__((unused)) Q90C_init()
{
XN297L_Init();
if(IS_BIND_IN_PROGRESS)
XN297L_SetTXAddr((uint8_t*)"\x4F\x43\x54\x81\x81", Q90C_ADDRESS_LENGTH);
else
XN297L_SetTXAddr(rx_tx_addr, Q90C_ADDRESS_LENGTH);
XN297L_HoppingCalib(Q90C_RF_NUM_CHANNELS); // Calibrate all channels
XN297L_RFChannel(Q90C_RF_BIND_CHANNEL); // Set bind channel
}
uint16_t Q90C_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(Q90C_PACKET_PERIOD);
#endif
if(IS_BIND_IN_PROGRESS)
if(--bind_counter==0)
{
BIND_DONE;
XN297L_SetTXAddr(rx_tx_addr, Q90C_ADDRESS_LENGTH);
}
Q90C_send_packet();
return Q90C_PACKET_PERIOD;
}
uint16_t initQ90C()
{
Q90C_initialize_txid();
Q90C_init();
hopping_frequency_no = 0;
packet_count = 0;
bind_counter=Q90C_BIND_COUNT;
//features
state=Channel_data[CH5];
Q90C_VTX=CH6_SW;
packet[8] = 0x00;
packet[9] = 0x00;
return Q90C_INITIAL_WAIT;
}
#endif

View File

@@ -0,0 +1,157 @@
/*
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 Realacc R11
#if defined(REALACC_NRF24L01_INO)
#include "iface_nrf24l01.h"
#define FORCE_REALACC_ORIGINAL_ID
#define REALACC_INITIAL_WAIT 500
#define REALACC_PACKET_PERIOD 2268
#define REALACC_BIND_RF_CHANNEL 80
#define REALACC_BIND_PAYLOAD_SIZE 10
#define REALACC_PAYLOAD_SIZE 13
#define REALACC_BIND_COUNT 50
#define REALACC_RF_NUM_CHANNELS 5
static void __attribute__((unused)) REALACC_send_packet()
{
packet[ 0]= 0xDC;
packet[ 1]= convert_channel_8b(AILERON); // 00..80..FF
packet[ 2]= convert_channel_8b(ELEVATOR); // 00..80..FF
packet[ 3]= convert_channel_8b(THROTTLE); // 00..FF
packet[ 4]= convert_channel_8b(RUDDER); // 00..80..FF
packet[ 5]= 0x20; // Trim
packet[ 6]= 0x20; // Trim
packet[ 7]= 0x20; // Trim
packet[ 8]= 0x20; // Trim
packet[ 9]= num_ch; // Change at each power up
packet[10]= 0x04 // Flag1
| 0x02 // Rate1=0, Rate2=1, Rate3=2
| GET_FLAG(CH8_SW, 0x20); // Headless
packet[11]= 0x00 // Flag2
| GET_FLAG(CH7_SW, 0x01) // Calib
| GET_FLAG(CH9_SW, 0x20) // Return
| GET_FLAG(CH10_SW,0x80); // Unknown
packet[12]= 0x00 // Flag3
| GET_FLAG(CH5_SW, 0x01) // Flip
| GET_FLAG(CH6_SW, 0x80); // Light
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency_no);
hopping_frequency_no++;
hopping_frequency_no %= REALACC_RF_NUM_CHANNELS;
XN297_WriteEnhancedPayload(packet, REALACC_PAYLOAD_SIZE,0);
}
static void __attribute__((unused)) REALACC_send_bind_packet()
{
packet[0] = 0xB1;
memcpy(&packet[1],rx_tx_addr,4);
memcpy(&packet[5],hopping_frequency,5);
XN297_WriteEnhancedPayload(packet, REALACC_BIND_PAYLOAD_SIZE,1);
}
static void __attribute__((unused)) REALACC_initialize_txid()
{
calc_fh_channels(REALACC_RF_NUM_CHANNELS);
num_ch=random(0xfefefefe); // 00..FF
#ifdef FORCE_REALACC_ORIGINAL_ID
//Dump
rx_tx_addr[0]=0x99;
rx_tx_addr[1]=0x06;
rx_tx_addr[2]=0x00;
rx_tx_addr[3]=0x00;
hopping_frequency[0]=0x55;
hopping_frequency[1]=0x59;
hopping_frequency[2]=0x5A;
hopping_frequency[3]=0x5A;
hopping_frequency[4]=0x62;
num_ch=0xC5; // Value in dumps: C5 A2 77 F0 84 58
#endif
}
static void __attribute__((unused)) REALACC_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*)"MAIN", 4);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, REALACC_BIND_RF_CHANNEL); // Set bind channel
}
uint16_t REALACC_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(REALACC_PACKET_PERIOD);
#endif
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
NRF24L01_SetPower();
if(IS_BIND_IN_PROGRESS)
{
REALACC_send_bind_packet();
if(--bind_counter==0)
{
BIND_DONE;
XN297_SetTXAddr(rx_tx_addr, 4);
}
}
else
REALACC_send_packet();
return REALACC_PACKET_PERIOD;
}
uint16_t initREALACC()
{
BIND_IN_PROGRESS; // autobind protocol
REALACC_initialize_txid();
REALACC_init();
bind_counter=REALACC_BIND_COUNT;
hopping_frequency_no=0;
return REALACC_INITIAL_WAIT;
}
#endif
// XN297 speed 1Mb, scrambled, enhanced
// Bind
// Address = 4D 41 49 4E = 'MAIN'
// Channel = 80 (most likely from dump)
// P(10) = B1 99 06 00 00 55 59 5A 5A 62
// B1 indicates bind packet
// 99 06 00 00 = ID = address of normal packets
// 55 59 5A 5A 62 = 85, 89, 90, 90, 98 = RF channels to be used (kind of match previous dumps)// Normal
// Normal
// Address = 99 06 00 00
// Channels = 84, 89, 90, 90, 98 (guess from bind)
// P(13)= DC 80 80 32 80 20 20 20 20 58 04 00 00
// DC = normal packet
// 80 80 32 80 : AETR 00..80..FF
// 20 20 20 20 : Trims
// 58 : changing every time the TX restart
// 04 : |0x20=headless, |0x01=rate2, |0x02=rate3
// 00 : |0x01=calib, |0x20=return, |0x80=unknown
// 00 : |0x80=light, |0x01=flip

View File

@@ -0,0 +1,104 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef CYRF6936_INSTALLED
#include "iface_rf2500.h"
#define RF2500_ADDR_LENGTH 4
uint8_t RF2500_payload_length, RF2500_tx_addr[RF2500_ADDR_LENGTH], RF2500_buf[80];
bool RF2500_scramble_enabled;
static void __attribute__((unused)) RF2500_Init(uint8_t payload_length, bool scramble)
{
CYRF_GFSK1M_Init( RF2500_ADDR_LENGTH + 2 + (payload_length+2)*4, 2 ); // full payload length with CRC + address + 5 + FEC
RF2500_payload_length=payload_length;
RF2500_scramble_enabled=scramble;
}
static void __attribute__((unused)) RF2500_SetTXAddr(const uint8_t* addr)
{
memcpy(RF2500_tx_addr, addr, RF2500_ADDR_LENGTH);
}
static void __attribute__((unused)) RF2500_BuildPayload(uint8_t* buffer)
{
const uint8_t RF2500_scramble[] = { 0xD0, 0x9E, 0x53, 0x33, 0xD8, 0xBA, 0x98, 0x08, 0x24, 0xCB, 0x3B, 0xFC, 0x71, 0xA3, 0xF4, 0x55 };
const uint16_t RF2500_crc_xorout_scramble = 0xAEE4;
//Scramble the incoming buffer
if(RF2500_scramble_enabled)
for(uint8_t i=0; i<RF2500_payload_length; i++)
buffer[i] ^= RF2500_scramble[i];
//Add CRC to the buffer
crc=0x0000;
for(uint8_t i=0;i<RF2500_payload_length;i++)
crc16_update(bit_reverse(buffer[i]),8);
buffer[RF2500_payload_length ] = bit_reverse(crc>>8);
buffer[RF2500_payload_length+1] = bit_reverse(crc);
if(RF2500_scramble_enabled)
{
buffer[RF2500_payload_length ] ^= RF2500_crc_xorout_scramble>>8;
buffer[RF2500_payload_length+1] ^= RF2500_crc_xorout_scramble;
}
#if 0
debug("B:");
for(uint8_t i=0; i<RF2500_payload_length+2; i++)
debug(" %02X",buffer[i]);
debugln("");
#endif
memcpy(RF2500_buf,RF2500_tx_addr,RF2500_ADDR_LENGTH); // Address
uint8_t pos = RF2500_ADDR_LENGTH;
RF2500_buf[pos++]=0xC3;RF2500_buf[pos++]=0xC3; // 5 FEC encoded
memset(&RF2500_buf[pos],0x00,(RF2500_payload_length+2)*4); // + CRC) * 4 FEC bytes per byte
//FEC encode
for(uint8_t i=0; i<RF2500_payload_length+2; i++) // Include CRC
{
for(uint8_t j=0;j<8;j++)
{
uint8_t offset=pos + (i<<2) + (j>>1);
RF2500_buf[offset] <<= 4;
if( (buffer[i]>>j) & 0x01 )
RF2500_buf[offset] |= 0x0C;
else
RF2500_buf[offset] |= 0x03;
}
}
#if 0
debug("E:");
for(uint8_t i=0; i<RF2500_ADDR_LENGTH+2+(RF2500_payload_length+2)*4; i++)
debug(" %02X",RF2500_buf[i]);
debugln("");
#endif
//CYRF wants LSB first
for(uint8_t i=0; i<RF2500_ADDR_LENGTH+2+(RF2500_payload_length+2)*4; i++)
RF2500_buf[i]=bit_reverse(RF2500_buf[i]);
}
static void __attribute__((unused)) RF2500_SendPayload()
{
CYRF_GFSK1M_SendPayload(RF2500_buf, RF2500_ADDR_LENGTH + 2 + (RF2500_payload_length+2)*4 );
}
#endif

View File

@@ -0,0 +1,319 @@
/*
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/>.
*/
// Radiolink surface protocol. TXs: RC4GS,RC6GS. Compatible RXs:R7FG(Std),R6FG,R6F,R8EF,R8FM,R8F,R4FGM
#if defined(RLINK_CC2500_INO)
#include "iface_cc2500.h"
//#define RLINK_FORCE_ID
#define RLINK_TX_PACKET_LEN 33
#define RLINK_RX_PACKET_LEN 15
#define RLINK_TX_ID_LEN 4
#define RLINK_HOP 16
enum {
RLINK_DATA = 0x00,
RLINK_RX1 = 0x01,
RLINK_RX2 = 0x02,
};
uint32_t RLINK_rand1;
uint32_t RLINK_rand2;
static uint32_t __attribute__((unused)) RLINK_prng_next(uint32_t r)
{
return 0xA5E2A705 * r + 0x754DB79B;
}
static void __attribute__((unused)) RLINK_init_random(uint32_t id)
{
uint32_t result = id;
RLINK_rand2 = result;
for (uint8_t i=0; i<31; i++)
result = RLINK_prng_next(result);
RLINK_rand1 = result;
}
static uint8_t __attribute__((unused)) RLINK_next_random_swap()
{
uint8_t result = (RLINK_rand2 >> 16) + RLINK_rand2 + (RLINK_rand1 >> 16) + RLINK_rand1;
RLINK_rand2 = RLINK_prng_next(RLINK_rand2);
RLINK_rand1 = RLINK_prng_next(RLINK_rand1);
return result & 0x0F;
}
static uint32_t __attribute__((unused)) RLINK_compute_start_id(uint32_t id)
{
return id * 0xF65EF9F9u + 0x2EDDF6CAu;
}
static void __attribute__((unused)) RLINK_shuffle_freqs(uint32_t seed)
{
RLINK_init_random(seed);
for(uint8_t i=0; i<RLINK_HOP; i++)
{
uint8_t r = RLINK_next_random_swap();
uint8_t tmp = hopping_frequency[r];
hopping_frequency[r] = hopping_frequency[i];
hopping_frequency[i] = tmp;
}
}
static void __attribute__((unused)) RLINK_hop()
{
uint8_t inc=3*(rx_tx_addr[0]&3);
// init hop table
for(uint8_t i=0; i<RLINK_HOP; i++)
hopping_frequency[i] = (12*i) + inc;
// shuffle
RLINK_shuffle_freqs(RLINK_compute_start_id(rx_tx_addr[0] + (rx_tx_addr[1] << 8)));
RLINK_shuffle_freqs(RLINK_compute_start_id(rx_tx_addr[2] + (rx_tx_addr[3] << 8)));
// replace one of the channel randomely
rf_ch_num=random(0xfefefefe)%0x11; // 0x00..0x10
if(inc==9) inc=6; // frequency exception
hopping_frequency[rf_ch_num]=12*16+inc;
}
static void __attribute__((unused)) RLINK_init()
{
#ifdef RLINK_FORCE_ID
//surface RC6GS
memcpy(rx_tx_addr,"\x3A\x99\x22\x3A",RLINK_TX_ID_LEN);
//air T8FB
//memcpy(rx_tx_addr,"\xFC\x11\x0D\x20",RLINK_TX_ID_LEN);
#endif
// channels order depend on ID
RLINK_hop();
#if 0
debug("ID:");
for(uint8_t i=0;i<RLINK_TX_ID_LEN;i++)
debug(" 0x%02X",rx_tx_addr[i]);
debugln("");
debug("Hop(%d):", rf_ch_num);
for(uint8_t i=0;i<RLINK_HOP;i++)
debug(" 0x%02X",hopping_frequency[i]);
debugln("");
#endif
}
const PROGMEM uint8_t RLINK_init_values[] = {
/* 00 */ 0x5B, 0x06, 0x5C, 0x07, 0xAB, 0xCD, 0x40, 0x04,
/* 08 */ 0x45, 0x00, 0x00, 0x06, 0x00, 0x5C, 0x62, 0x76,
/* 10 */ 0x7A, 0x7F, 0x13, 0x23, 0xF8, 0x44, 0x07, 0x30,
/* 18 */ 0x18, 0x16, 0x6C, 0x43, 0x40, 0x91, 0x87, 0x6B,
/* 20 */ 0xF8, 0x56, 0x10, 0xA9, 0x0A, 0x00, 0x11
};
static void __attribute__((unused)) RLINK_rf_init()
{
CC2500_Strobe(CC2500_SIDLE);
for (uint8_t i = 0; i < 39; ++i)
CC2500_WriteReg(i, pgm_read_byte_near(&RLINK_init_values[i]));
if(sub_protocol==RLINK_DUMBORC)
{
CC2500_WriteReg(4, 0xBA);
CC2500_WriteReg(5, 0xDC);
}
prev_option = option;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
CC2500_SetTxRxMode(TX_EN);
}
static void __attribute__((unused)) RLINK_tune_freq()
{
if ( prev_option != option )
{
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
prev_option = option ;
}
}
static void __attribute__((unused)) RLINK_send_packet()
{
static uint32_t pseudo=0;
uint32_t bits = 0;
uint8_t bitsavailable = 0;
uint8_t idx = 6;
CC2500_Strobe(CC2500_SIDLE);
// packet length
packet[0] = RLINK_TX_PACKET_LEN;
// header
if(packet_count>3)
packet[1] = 0x02; // 0x02 telemetry request flag
switch(sub_protocol)
{
case RLINK_SURFACE:
packet[1] |= 0x01;
//radiolink additionnal ID which is working only on a small set of RXs
//if(RX_num) packet[1] |= ((RX_num+2)<<4)+4; // RX number limited to 10 values, 0 is a wildcard
break;
case RLINK_AIR:
packet[1] |= 0x21; //air 0x21 on dump but it looks to support telemetry at least RSSI
break;
case RLINK_DUMBORC:
packet[1] = 0x00; //always 0x00 on dump
break;
}
// ID
memcpy(&packet[2],rx_tx_addr,RLINK_TX_ID_LEN);
// pack 16 channels on 11 bits values between 170 and 1876, 1023 middle. The last 8 channels are failsafe values associated to the first 8 values.
for (uint8_t i = 0; i < 16; i++)
{
uint32_t val = convert_channel_16b_nolimit(i,170,1876,false); // allow extended limits
if (val & 0x8000)
val = 0;
else if (val > 2047)
val=2047;
bits |= val << bitsavailable;
bitsavailable += 11;
while (bitsavailable >= 8) {
packet[idx++] = bits & 0xff;
bits >>= 8;
bitsavailable -= 8;
}
}
// hop
pseudo=((pseudo * 0xAA) + 0x03) % 0x7673; // calc next pseudo random value
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[pseudo & 0x0F]);
packet[28]= pseudo;
packet[29]= pseudo >> 8;
packet[30]= 0x00; // unknown
packet[31]= 0x00; // unknown
packet[32]= rf_ch_num; // index of value changed in the RF table
// check
uint8_t sum=0;
for(uint8_t i=1;i<33;i++)
sum+=packet[i];
packet[33]=sum;
// send packet
CC2500_WriteData(packet, RLINK_TX_PACKET_LEN+1);
// packets type
packet_count++;
if(packet_count>5) packet_count=0;
//debugln("C= 0x%02X",hopping_frequency[pseudo & 0x0F]);
//debug("P=");
//for(uint8_t i=1;i<RLINK_TX_PACKET_LEN+1;i++)
// debug(" 0x%02X",packet[i]);
//debugln("");
}
#define RLINK_TIMING_PROTO 20000-100 // -100 for compatibility with R8EF
#define RLINK_TIMING_RFSEND 10500
#define RLINK_TIMING_CHECK 2000
uint16_t RLINK_callback()
{
switch(phase)
{
case RLINK_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(RLINK_TIMING_PROTO);
#endif
CC2500_SetPower();
RLINK_tune_freq();
RLINK_send_packet();
#if not defined RLINK_HUB_TELEMETRY
return RLINK_TIMING_PROTO;
#else
if(!(packet[1]&0x02))
return RLINK_TIMING_PROTO; //Normal packet
//Telemetry packet
phase++; // RX1
return RLINK_TIMING_RFSEND;
case RLINK_RX1:
CC2500_Strobe(CC2500_SIDLE);
CC2500_Strobe(CC2500_SFRX);
CC2500_SetTxRxMode(RX_EN);
CC2500_Strobe(CC2500_SRX);
phase++; // RX2
return RLINK_TIMING_PROTO-RLINK_TIMING_RFSEND-RLINK_TIMING_CHECK;
case RLINK_RX2:
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if (len == RLINK_RX_PACKET_LEN + 1 + 2) //Telemetry frame is 15 bytes + 1 byte for length + 2 bytes for RSSI&LQI&CRC
{
//debug("Telem:");
CC2500_ReadData(packet_in, len);
if(packet_in[0]==RLINK_RX_PACKET_LEN && (packet_in[len-1] & 0x80) && memcmp(&packet[2],rx_tx_addr,RLINK_TX_ID_LEN)==0 && packet_in[6]==packet[1])
{//Correct telemetry received: length, CRC, ID and type
//Debug
//for(uint8_t i=0;i<len;i++)
// debug(" %02X",packet_in[i]);
TX_RSSI = packet_in[len-2];
if(TX_RSSI >=128)
TX_RSSI -= 128;
else
TX_RSSI += 128;
RX_RSSI=packet_in[7]; //Should be packet_in[7]-256 but since it's an uint8_t...
v_lipo1=packet_in[8]<<1; //RX Batt
v_lipo2=packet_in[9]; //Batt
telemetry_link=1; //Send telemetry out
pps_counter++;
packet_count=0;
}
//debugln("");
}
if (millis() - pps_timer >= 2000)
{//1 telemetry packet every 100ms
pps_timer = millis();
if(pps_counter<20)
pps_counter*=5;
else
pps_counter=100;
debugln("%d pps", pps_counter);
TX_LQI = pps_counter; //0..100%
pps_counter = 0;
}
CC2500_SetTxRxMode(TX_EN);
phase=RLINK_DATA; // DATA
return RLINK_TIMING_CHECK;
#endif
}
return 0;
}
uint16_t initRLINK()
{
BIND_DONE; // Not a TX bind protocol
RLINK_init();
RLINK_rf_init();
packet_count = 0;
phase = RLINK_DATA;
return 10000;
}
#endif

View File

@@ -129,7 +129,7 @@ static void __attribute__((unused)) SLT_build_packet()
uint8_t e = 0; // byte where extension 2 bits for every 10-bit channel are packed
for (uint8_t i = 0; i < 4; ++i)
{
uint16_t v = convert_channel_10b(CH_AETR[i]);
uint16_t v = convert_channel_10b(CH_AETR[i], false);
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;
@@ -260,6 +260,7 @@ uint16_t SLT_callback()
uint16_t initSLT()
{
BIND_DONE; // Not a TX bind protocol
packet_count = 0;
packet_sent = 0;
hopping_frequency_no = 0;

View File

@@ -1,6 +1,8 @@
#ifdef SX1276_INSTALLED
#include "iface_sx1276.h"
bool SX1276_Mode_LoRa=false;
void SX1276_WriteReg(uint8_t address, uint8_t data)
{
SPI_CSN_off;
@@ -14,9 +16,8 @@ uint8_t SX1276_ReadReg(uint8_t address)
{
SPI_CSN_off;
SPI_Write(address & 0x7F);
uint8_t result = SPI_Read();
uint8_t result = SPI_Read();
SPI_CSN_on;
return result;
}
@@ -31,20 +32,78 @@ void SX1276_WriteRegisterMulti(uint8_t address, const uint8_t* data, uint8_t len
SPI_CSN_on;
}
void SX1276_ReadRegisterMulti(uint8_t address, uint8_t* data, uint8_t length)
{
SPI_CSN_off;
SPI_Write(address & 0x7F);
for(uint8_t i = 0; i < length; i++)
data[i]=SPI_Read();
SPI_CSN_on;
}
uint8_t SX1276_Reset()
{
//TODO
//TODO when pin is not wired
#ifdef SX1276_RST_pin
SX1276_RST_off;
delayMicroseconds(200);
SX1276_RST_on;
#endif
return 0;
}
bool SX1276_DetectChip() //to be called after reset, verfies the chip has been detected
{
#define SX1276_Detect_MaxAttempts 5
uint8_t i = 0;
bool chipFound = false;
while ((i < SX1276_Detect_MaxAttempts) && !chipFound)
{
uint8_t ChipVersion = SX1276_ReadReg(SX1276_42_VERSION);
if (ChipVersion == 0x12)
{
debugln("SX1276 reg version=%d", ChipVersion);
chipFound = true;
}
else
{
debug("SX1276 not found! attempts: %d", i);
debug(" of ");
debugln("%d SX1276 reg version=%d", SX1276_Detect_MaxAttempts, ChipVersion);
i++;
}
}
if (!chipFound)
{
debugln("SX1276 not detected!!!");
return false;
}
else
{
debugln("Found SX1276 Device!");
return true;
}
}
void SX1276_SetTxRxMode(uint8_t mode)
{
#ifdef SX1276_TXEN_pin
if(mode == TX_EN)
SX1276_TXEN_on;
else
SX1276_RXEN_on;
#endif
}
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;
data[0] = f >> 16;
data[1] = f >> 8;
data[2] = f;
SX1276_WriteRegisterMulti(SX1276_06_FRFMSB, data, 3);
}
@@ -53,6 +112,8 @@ void SX1276_SetMode(bool lora, bool low_freq_mode, uint8_t mode)
{
uint8_t data = 0x00;
SX1276_Mode_LoRa=lora;
if(lora)
{
data = data | (1 << 7);
@@ -89,6 +150,14 @@ void SX1276_ConfigModem1(uint8_t bandwidth, uint8_t coding_rate, bool implicit_h
data = data | implicit_header_mode;
SX1276_WriteReg(SX1276_1D_MODEMCONFIG1, data);
if (bandwidth == SX1276_MODEM_CONFIG1_BW_500KHZ) //datasheet errata reconmendation http://caxapa.ru/thumbs/972894/SX1276_77_8_ErrataNote_1.1_STD.pdf
{
SX1276_WriteReg(SX1276_36_LORA_REGHIGHBWOPTIMIZE1, 0x02);
SX1276_WriteReg(SX1276_3A_LORA_REGHIGHBWOPTIMIZE2, 0x64);
}
else
SX1276_WriteReg(SX1276_36_LORA_REGHIGHBWOPTIMIZE1, 0x03);
}
void SX1276_ConfigModem2(uint8_t spreading_factor, bool tx_continuous_mode, bool rx_payload_crc_on)

View File

@@ -0,0 +1,63 @@
/*
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(TEST_CC2500_INO)
#include "iface_nrf250k.h"
#define TEST_INITIAL_WAIT 500
#define TEST_PACKET_PERIOD 10000
#define TEST_PAYLOAD_SIZE 10
#define TEST_RF_NUM_CHANNELS 3
uint16_t TEST_callback()
{
option=1;
if(phase)
XN297L_WritePayload(packet, TEST_PAYLOAD_SIZE);
else
{
if(Channel_data[CH5]<CHANNEL_MIN_COMMAND)
hopping_frequency_no=0;
else if(Channel_data[CH5]>CHANNEL_MAX_COMMAND)
hopping_frequency_no=2;
else
hopping_frequency_no=1;
XN297L_Hopping(hopping_frequency_no);
CC2500_WriteReg(CC2500_3E_PATABLE,convert_channel_8b(CH6));
debugln("CH:%d, PWR:%d",hopping_frequency_no,convert_channel_8b(CH6));
}
phase ^= 1;
return TEST_PACKET_PERIOD>>1;
}
uint16_t initTEST()
{
option=1;
hopping_frequency[0]=0;
hopping_frequency[1]=40;
hopping_frequency[2]=80;
XN297L_Init();
XN297L_HoppingCalib(TEST_RF_NUM_CHANNELS); // Calibrate all channels
XN297L_SetTXAddr((uint8_t*)"RADIO", 5);
hopping_frequency_no = 0;
phase=0;
for(uint8_t i=0; i<TEST_PAYLOAD_SIZE; i++)
packet[i]= i;
return TEST_INITIAL_WAIT;
}
#endif

View File

@@ -77,19 +77,19 @@ 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);
uint16_t ch = convert_channel_16b_nolimit(RUDDER,500,1000,false);
packet[2]=ch>>8;
packet[3]=ch;
//Throttle
ch = convert_channel_16b_nolimit(THROTTLE,500,1000);
ch = convert_channel_16b_nolimit(THROTTLE,500,1000,false);
packet[4]=ch>>8;
packet[5]=ch;
//AUX3
ch = convert_channel_16b_nolimit(AILERON,500,1000);
ch = convert_channel_16b_nolimit(AILERON,500,1000,false);
packet[6]=ch>>8;
packet[7]=ch;
//AUX4???
ch = convert_channel_16b_nolimit(ELEVATOR,500,1000);
ch = convert_channel_16b_nolimit(ELEVATOR,500,1000,false);
packet[12]=ch>>8;
packet[13]=ch;

View File

@@ -35,16 +35,16 @@
#endif
//Channel MIN MAX values
#define CHANNEL_MAX_100 1844 // 100%
#define CHANNEL_MIN_100 204 // 100%
#define CHANNEL_MAX_125 2047 // 125%
#define CHANNEL_MIN_125 0 // 125%
#define CHANNEL_MAX_100 1844 // +100%
#define CHANNEL_MIN_100 204 // -100%
#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
#define CHANNEL_MIN_COMMAND 409 // -75%
#define CHANNEL_SWITCH 1106 // +10%
#define CHANNEL_MAX_COMMAND 1639 // +75%
//Channel definitions
#define CH1 0

View File

@@ -33,7 +33,6 @@ uint8_t RetrySequence ;
#if defined SPORT_TELEMETRY
#define FRSKY_SPORT_PACKET_SIZE 8
#define FX_BUFFERS 4
uint8_t RxBt = 0;
uint8_t Sport_Data = 0;
uint8_t pktx1[FRSKY_SPORT_PACKET_SIZE*FX_BUFFERS];
@@ -148,7 +147,7 @@ static void multi_send_status()
else if(sub_protocol&0x07)
{
uint8_t nbr=multi_protocols[multi_protocols_index].nbrSubProto;
if(protocol==PROTO_DSM) nbr++; //Auto sub_protocol
//if(protocol==PROTO_DSM) nbr++; //Auto sub_protocol
if((sub_protocol&0x07)>=nbr)
flags &= ~0x04; //Invalid sub protocol
}
@@ -348,26 +347,28 @@ void frskySendStuffed()
Serial_write(START_STOP);
}
void frsky_check_telemetry(uint8_t *packet_in,uint8_t len)
bool frsky_process_telemetry(uint8_t *buffer,uint8_t len)
{
if(packet_in[1] != rx_tx_addr[3] || packet_in[2] != rx_tx_addr[2] || len != packet_in[0] + 3 )
return; // Bad address or length...
if(protocol!=PROTO_FRSKY_R9)
{
if(buffer[1] != rx_tx_addr[3] || buffer[2] != rx_tx_addr[2] || len != buffer[0] + 3 )
return false; // Bad address or length...
// RSSI and LQI are the 2 last bytes
TX_RSSI = buffer[len-2];
if(TX_RSSI >=128)
TX_RSSI -= 128;
else
TX_RSSI += 128;
}
telemetry_link|=1; // Telemetry data is available
// RSSI and LQI are the 2 last bytes
TX_RSSI = packet_in[len-2];
if(TX_RSSI >=128)
TX_RSSI -= 128;
else
TX_RSSI += 128;
TX_LQI = packet_in[len-1]&0x7F;
#if defined FRSKYD_CC2500_INO
if (protocol==PROTO_FRSKYD)
{
TX_LQI = buffer[len-1]&0x7F;
//Save current buffer
for (uint8_t i=3;i<len-2;i++)
telemetry_in_buffer[i]=packet_in[i]; // Buffer telemetry values to be sent
telemetry_in_buffer[i]=buffer[i]; // Buffer telemetry values to be sent
//Check incoming telemetry sequence
if(telemetry_in_buffer[6]>0 && telemetry_in_buffer[6]<=10)
@@ -392,7 +393,7 @@ void frsky_check_telemetry(uint8_t *packet_in,uint8_t len)
}
#endif
#if defined SPORT_TELEMETRY && defined FRSKYX_CC2500_INO
#if defined SPORT_TELEMETRY && (defined FRSKYX_CC2500_INO || defined FRSKYR9_SX1276_INO)
if (protocol==PROTO_FRSKYX||protocol==PROTO_FRSKYX2)
{
/*Telemetry frames(RF) SPORT info
@@ -413,29 +414,30 @@ void frsky_check_telemetry(uint8_t *packet_in,uint8_t len)
[12] STRM6 D1 D1 D0 D0
[13] CHKSUM1 --|2 CRC bytes sent by RX (calculated on RX side crc16/table)
[14] CHKSUM2 --|*/
telemetry_lost=0;
uint16_t lcrc = FrSkyX_crc(&packet_in[3], len-7 ) ;
if ( ( (lcrc >> 8) != packet_in[len-4]) || ( (lcrc & 0x00FF ) != packet_in[len-3]) )
return; // Bad CRC
//len=17 -> len-7=10 -> 3..12
uint16_t lcrc = FrSkyX_crc(&buffer[3], len-7 ) ;
if ( ( (lcrc >> 8) != buffer[len-4]) || ( (lcrc & 0x00FF ) != buffer[len-3]) )
return false; // Bad CRC
if(packet_in[4] & 0x80)
RX_RSSI=packet_in[4] & 0x7F ;
if(buffer[4] & 0x80)
RX_RSSI=buffer[4] & 0x7F ;
else
RxBt = (packet_in[4]<<1) + 1 ;
v_lipo1 = (buffer[4]<<1) + 1 ;
#if defined(TELEMETRY_FRSKYX_TO_FRSKYD) && defined(ENABLE_PPM)
if(mode_select != MODE_SERIAL)
{//PPM
v_lipo1=RxBt;
return;
}
return true;
#endif
}
if (protocol==PROTO_FRSKYX||protocol==PROTO_FRSKYX2||protocol==PROTO_FRSKY_R9)
{
telemetry_lost=0;
//Save outgoing telemetry sequence
FrSkyX_TX_IN_Seq=packet_in[5] >> 4;
FrSkyX_TX_IN_Seq=buffer[5] >> 4;
//Check incoming telemetry sequence
uint8_t packet_seq=packet_in[5] & 0x03;
if ( packet_in[5] & 0x08 )
uint8_t packet_seq=buffer[5] & 0x03;
if ( buffer[5] & 0x08 )
{//Request init
FrSkyX_RX_Seq = 0x08 ;
FrSkyX_RX_NextFrame = 0x00 ;
@@ -448,20 +450,20 @@ void frsky_check_telemetry(uint8_t *packet_in,uint8_t len)
{//In sequence
struct t_FrSkyX_RX_Frame *p ;
uint8_t count ;
// packet_in[4] RSSI
// packet_in[5] sequence control
// packet_in[6] payload count
// packet_in[7-12] payload
// buffer[4] RSSI
// buffer[5] sequence control
// buffer[6] payload count
// buffer[7-12] payload
p = &FrSkyX_RX_Frames[packet_seq] ;
count = packet_in[6]; // Payload length
count = buffer[6]; // Payload length
if ( count <= 6 )
{//Store payload
p->count = count ;
for ( uint8_t i = 0 ; i < count ; i++ )
p->payload[i] = packet_in[i+7] ;
p->payload[i] = buffer[i+7] ;
}
else
p->count = 0 ; // Discard
p->count = 0 ; // Discard
p->valid = true ;
FrSkyX_RX_Seq = ( FrSkyX_RX_Seq + 1 ) & 0x03 ; // Move to next sequence
@@ -477,19 +479,19 @@ void frsky_check_telemetry(uint8_t *packet_in,uint8_t len)
{//Not in sequence
struct t_FrSkyX_RX_Frame *q ;
uint8_t count ;
// packet_in[4] RSSI
// packet_in[5] sequence control
// packet_in[6] payload count
// packet_in[7-12] payload
// buffer[4] RSSI
// buffer[5] sequence control
// buffer[6] payload count
// buffer[7-12] payload
if ( packet_seq == ( ( FrSkyX_RX_Seq +1 ) & 3 ) )
{//Received next sequence -> save it
q = &FrSkyX_RX_Frames[packet_seq] ;
count = packet_in[6]; // Payload length
count = buffer[6]; // Payload length
if ( count <= 6 )
{//Store payload
q->count = count ;
for ( uint8_t i = 0 ; i < count ; i++ )
q->payload[i] = packet_in[i+7] ;
q->payload[i] = buffer[i+7] ;
}
else
q->count = 0 ;
@@ -501,6 +503,7 @@ void frsky_check_telemetry(uint8_t *packet_in,uint8_t len)
}
}
#endif
return true;
}
void init_frskyd_link_telemetry()
@@ -528,7 +531,7 @@ void frsky_link_frame()
telemetry_link |= 2 ; // Send hub if available
}
else
{//PROTO_HUBSAN, PROTO_AFHDS2A, PROTO_BAYANG, PROTO_NCC1701, PROTO_CABELL, PROTO_HITEC, PROTO_BUGS, PROTO_BUGSMINI, PROTO_FRSKYX, PROTO_FRSKYX2, PROTO_PROPEL, PROTO_DEVO
{//PROTO_HUBSAN, PROTO_AFHDS2A, PROTO_BAYANG, PROTO_NCC1701, PROTO_CABELL, PROTO_HITEC, PROTO_BUGS, PROTO_BUGSMINI, PROTO_FRSKYX, PROTO_FRSKYX2, PROTO_PROPEL, PROTO_DEVO, PROTO_RLINK, PROTO_OMP, PROTO_WFLY2, PROTO_LOLI
frame[1] = v_lipo1;
frame[2] = v_lipo2;
frame[3] = RX_RSSI;
@@ -725,7 +728,7 @@ void sportSendFrame()
case 0:
frame[2] = 0x05;
frame[3] = 0xf1;
frame[4] = 0x02 ;//dummy values if swr 20230f00
frame[4] = 0x02; //dummy values if swr 20230f00
frame[5] = 0x23;
frame[6] = 0x0F;
break;
@@ -740,7 +743,7 @@ void sportSendFrame()
case 4: //BATT
frame[2] = 0x04;
frame[3] = 0xf1;
frame[4] = RxBt;//a1;
frame[4] = v_lipo1; //a1;
break;
default:
if(Sport_Data)
@@ -870,7 +873,7 @@ void TelemetryUpdate()
#endif
#endif
#if defined SPORT_TELEMETRY
if ((protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2) && telemetry_link
if ((protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2||protocol==PROTO_FRSKY_R9) && telemetry_link
#ifdef TELEMETRY_FRSKYX_TO_FRSKYD
&& mode_select==MODE_SERIAL
#endif
@@ -949,7 +952,7 @@ void TelemetryUpdate()
#endif
if( telemetry_link & 1 )
{ // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs + BugsMini + NCC1701 + PROPEL
{ // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs + BugsMini + NCC1701 + PROPEL + RLINK + OMP
// FrSkyX telemetry if in PPM
frsky_link_frame();
return;

View File

@@ -19,7 +19,7 @@
#include "iface_nrf24l01.h"
#define V2X2_MR101_FORCE_ID
#define V2X2_BIND_COUNT 1000
// Timeout for callback in uSec, 4ms=4000us for V202
@@ -51,14 +51,6 @@ enum {
//
enum {
V202_INIT2 = 0,
V202_INIT2_NO_BIND,//1
V202_BIND1,//2
V202_BIND2,//3
V202_DATA//4
};
// This is frequency hopping table for V202 protocol
// The table is the first 4 rows of 32 frequency hopping
// patterns, all other rows are derived from the first 4.
@@ -87,39 +79,29 @@ static void __attribute__((unused)) v202_init()
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3F); // Enable all data pipes
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0xFF); // 4ms retransmit t/o, 15 tries
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x08); // Channel 8
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
// NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0xFF); // 4ms retransmit t/o, 15 tries
// NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x08); // Channel 8
NRF24L01_SetBitrate(sub_protocol==V2X2_MR101?NRF24L01_BR_250K:NRF24L01_BR_1M);
NRF24L01_SetPower();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
// NRF24L01_WriteReg(NRF24L01_08_OBSERVE_TX, 0x00); // no write bits in this field
// NRF24L01_WriteReg(NRF24L01_00_CD, 0x00); // same
NRF24L01_WriteReg(NRF24L01_0C_RX_ADDR_P2, 0xC3); // LSB byte of pipe 2 receive address
NRF24L01_WriteReg(NRF24L01_0D_RX_ADDR_P3, 0xC4);
NRF24L01_WriteReg(NRF24L01_0E_RX_ADDR_P4, 0xC5);
NRF24L01_WriteReg(NRF24L01_0F_RX_ADDR_P5, 0xC6);
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, V2X2_PAYLOADSIZE); // bytes of data payload for pipe 1
NRF24L01_WriteReg(NRF24L01_12_RX_PW_P1, V2X2_PAYLOADSIZE);
NRF24L01_WriteReg(NRF24L01_13_RX_PW_P2, V2X2_PAYLOADSIZE);
NRF24L01_WriteReg(NRF24L01_14_RX_PW_P3, V2X2_PAYLOADSIZE);
NRF24L01_WriteReg(NRF24L01_15_RX_PW_P4, V2X2_PAYLOADSIZE);
NRF24L01_WriteReg(NRF24L01_16_RX_PW_P5, V2X2_PAYLOADSIZE);
NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here
// NRF24L01_WriteReg(NRF24L01_0C_RX_ADDR_P2, 0xC3); // LSB byte of pipe 2 receive address
// NRF24L01_WriteReg(NRF24L01_0D_RX_ADDR_P3, 0xC4);
// NRF24L01_WriteReg(NRF24L01_0E_RX_ADDR_P4, 0xC5);
// NRF24L01_WriteReg(NRF24L01_0F_RX_ADDR_P5, 0xC6);
// NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, V2X2_PAYLOADSIZE); // bytes of data payload for pipe 1
// NRF24L01_WriteReg(NRF24L01_12_RX_PW_P1, V2X2_PAYLOADSIZE);
// NRF24L01_WriteReg(NRF24L01_13_RX_PW_P2, V2X2_PAYLOADSIZE);
// NRF24L01_WriteReg(NRF24L01_14_RX_PW_P3, V2X2_PAYLOADSIZE);
// NRF24L01_WriteReg(NRF24L01_15_RX_PW_P4, V2X2_PAYLOADSIZE);
// NRF24L01_WriteReg(NRF24L01_16_RX_PW_P5, V2X2_PAYLOADSIZE);
// NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x66\x88\x68\x68\x68", 5);
NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, (uint8_t *)"\x88\x66\x86\x86\x86", 5);
// NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, (uint8_t *)"\x88\x66\x86\x86\x86", 5);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x66\x88\x68\x68\x68", 5);
}
static void __attribute__((unused)) V202_init2()
{
NRF24L01_FlushTx();
packet_sent = 0;
hopping_frequency_no = 0;
// Turn radio power on
NRF24L01_SetTxRxMode(TX_EN);
//Done by TX_EN??? => NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
}
static void __attribute__((unused)) V2X2_set_tx_id(void)
@@ -135,20 +117,27 @@ static void __attribute__((unused)) V2X2_set_tx_id(void)
// Strange avoidance of channels divisible by 16
hopping_frequency[i] = (val & 0x0f) ? val : val - 3;
}
#ifdef V2X2_MR101_FORCE_ID
if(sub_protocol==V2X2_MR101)
{
rx_tx_addr[1]=0x83;
rx_tx_addr[2]=0x03;
rx_tx_addr[3]=0xAE;
memcpy(hopping_frequency,"\x05\x12\x08\x0C\x04\x0E\x10",7);
}
#endif
}
static void __attribute__((unused)) V2X2_add_pkt_checksum()
static void __attribute__((unused)) V2X2_send_packet()
{
uint8_t sum = 0;
for (uint8_t i = 0; i < 15; ++i)
sum += packet[i];
packet[15] = sum;
}
uint8_t rf_ch = hopping_frequency[hopping_frequency_no >> 1];
hopping_frequency_no = (hopping_frequency_no + 1) & 0x1F;
if(sub_protocol==V2X2_MR101 && hopping_frequency_no>13)
hopping_frequency_no=0;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch);
static void __attribute__((unused)) V2X2_send_packet(uint8_t bind)
{
uint8_t flags2=0;
if (bind)
if (IS_BIND_IN_PROGRESS)
{
flags = V2X2_FLAG_BIND;
packet[0] = 0;
@@ -174,31 +163,35 @@ static void __attribute__((unused)) V2X2_send_packet(uint8_t bind)
flags=0;
// Channel 5
if (CH5_SW) flags = V2X2_FLAG_FLIP;
// Channel 6
if (CH6_SW) flags |= V2X2_FLAG_LIGHT;
// Channel 7
if (CH7_SW) flags |= V2X2_FLAG_CAMERA;
// Channel 8
if (CH8_SW) flags |= V2X2_FLAG_VIDEO;
//Flags2
// Channel 9
if (CH9_SW)
flags2 = V2X2_FLAG_HEADLESS;
if(sub_protocol==JXD506)
{
// Channel 11
if (CH11_SW)
flags2 |= V2X2_FLAG_EMERGENCY;
}
else
{
// Channel 10
if (CH10_SW)
flags2 |= V2X2_FLAG_MAG_CAL_X;
// Channel 11
if (CH11_SW)
flags2 |= V2X2_FLAG_MAG_CAL_Y;
if(sub_protocol!=V2X2_MR101)
{//V2X2 & JXD506
// Channel 6
if (CH6_SW) flags |= V2X2_FLAG_LIGHT;
// Channel 7
if (CH7_SW) flags |= V2X2_FLAG_CAMERA;
// Channel 8
if (CH8_SW) flags |= V2X2_FLAG_VIDEO;
//Flags2
// Channel 9
if (CH9_SW)
flags2 = V2X2_FLAG_HEADLESS;
if(sub_protocol==JXD506)
{
// Channel 11
if (CH11_SW)
flags2 |= V2X2_FLAG_EMERGENCY;
}
else
{//V2X2
// Channel 10
if (CH10_SW)
flags2 |= V2X2_FLAG_MAG_CAL_X;
// Channel 11
if (CH11_SW)
flags2 |= V2X2_FLAG_MAG_CAL_Y;
}
}
}
// TX id
@@ -223,16 +216,26 @@ static void __attribute__((unused)) V2X2_send_packet(uint8_t bind)
packet[12] = 0x40;
packet[13] = 0x40;
}
else if(sub_protocol==V2X2_MR101)
{
if (CH10_SW) packet[11] = 0x04; // Motors start/stop
if (CH11_SW) packet[11] |= 0x40; // Auto Land=-100% Takeoff=+100%
if (CH7_SW) flags |= 0x02; // Picture
if (CH8_SW) flags |= 0x01; // Video
if(IS_BIND_IN_PROGRESS)
flags = 0x80;
flags |= (hopping_frequency_no & 0x01)<<6;
}
packet[14] = flags;
V2X2_add_pkt_checksum();
uint8_t sum = packet[0];
for (uint8_t i = 1; i < 15; ++i)
sum += packet[i];
packet[15] = sum;
packet_sent = 0;
uint8_t rf_ch = hopping_frequency[hopping_frequency_no >> 1];
hopping_frequency_no = (hopping_frequency_no + 1) & 0x1F;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch);
NRF24L01_FlushTx();
NRF24L01_WritePayload(packet, V2X2_PAYLOADSIZE);
packet_sent = 1;
//packet_sent = 1;
if (! hopping_frequency_no)
NRF24L01_SetPower();
@@ -240,35 +243,26 @@ static void __attribute__((unused)) V2X2_send_packet(uint8_t bind)
uint16_t ReadV2x2()
{
switch (phase) {
case V202_INIT2:
V202_init2();
phase = V202_BIND2;
return 150;
break;
case V202_INIT2_NO_BIND:
V202_init2();
phase = V202_DATA;
return 150;
break;
case V202_BIND2:
if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED)
return V2X2_PACKET_CHKTIME;
V2X2_send_packet(1);
if (--bind_counter == 0)
//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();
if(IS_BIND_IN_PROGRESS)
{
if (--bind_counter == 0)
{
BIND_DONE;
if(sub_protocol==V2X2_MR101)
{
phase = V202_DATA;
BIND_DONE;
#ifdef V2X2_MR101_FORCE_ID
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\xC9\x59\xD2\x65\x34", 5);
memcpy(hopping_frequency,"\x03\x05\x15\x0D\x06\x14\x0B",7);
#endif
}
break;
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;
hopping_frequency_no = 0;
}
}
// Packet every 4ms
return V2X2_PACKET_PERIOD;
@@ -276,15 +270,13 @@ uint16_t ReadV2x2()
uint16_t initV2x2()
{
if(sub_protocol==V2X2_MR101)
BIND_IN_PROGRESS;
//packet_sent = 0;
hopping_frequency_no = 0;
bind_counter = V2X2_BIND_COUNT;
v202_init();
//
if (IS_BIND_IN_PROGRESS)
{
bind_counter = V2X2_BIND_COUNT;
phase = V202_INIT2;
}
else
phase = V202_INIT2_NO_BIND;
V2X2_set_tx_id();
return 50000;
}

View File

@@ -17,12 +17,12 @@ Multiprotocol is distributed in the hope that it will be useful,
#include "iface_nrf24l01.h"
//#define V761_FORCE_ID
#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
@@ -53,6 +53,8 @@ static void __attribute__((unused)) V761_set_checksum()
static void __attribute__((unused)) V761_send_packet()
{
static bool calib=false, prev_ch6=false;
if(phase != V761_DATA)
{
packet[0] = rx_tx_addr[0];
@@ -66,23 +68,44 @@ static void __attribute__((unused)) V761_send_packet()
}
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;
packet[0] = convert_channel_8b(THROTTLE); // Throttle
packet[2] = convert_channel_8b(ELEVATOR)>>1; // Elevator
// Channel 5 - Gyro mode is packet 5
if(CH5_SW) // Mode Expert Gyro off
if(sub_protocol==V761_3CH)
{
packet[1] = convert_channel_8b(RUDDER)>>1; // Rudder
packet[3] = convert_channel_8b(AILERON)>>1; // Aileron
}
else
{
packet[1] = convert_channel_8b(AILERON)>>1; // Aileron
packet[3] = convert_channel_8b(RUDDER)>>1; // Rudder
}
packet[5] = (packet_count++ / 3)<<6;
packet[4] = (packet[5] == 0x40) ? 0x1a : 0x20; // ?
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)
flags = 0x08; // Beginer mode (Gyro on, yaw and pitch rate limited)
else
flags = 0x0a; // Mid Mode ( Gyro on no rate limits)
flags = 0x0a; // Mid Mode ( Gyro on no rate limits)
if(!prev_ch6 && CH6_SW) // -100% -> 100% launch gyro calib
calib=!calib;
prev_ch6 = CH6_SW;
if(calib)
flags |= 0x01; // Gyro calibration
packet[5] |= flags;
packet[6] = 0x80; // unknown
packet[6] = GET_FLAG(CH7_SW, 0x20) // Flip
|GET_FLAG(CH8_SW, 0x08) // RTH activation
|GET_FLAG(CH9_SW, 0x10); // RTH on/off
if(sub_protocol==V761_3CH)
packet[6] |= 0x80; // unknown, set on original V761-1 dump but not on eachine dumps, keeping for compatibility
//packet counter
if(packet_count >= 12)
@@ -120,22 +143,40 @@ static void __attribute__((unused)) V761_init()
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;
}
#ifdef V761_FORCE_ID
switch(RX_num%5)
{
case 1: //Dump from air on Protonus TX
memcpy(rx_tx_addr,(uint8_t *)"\xE8\xE4\x45\x09",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x21",2);
break;
case 2: //Dump from air on mshagg2 TX
memcpy(rx_tx_addr,(uint8_t *)"\xAE\xD1\x45\x09",4);
memcpy(hopping_frequency,(uint8_t *)"\x13\x1D",2);
break;
case 3: //Dump from air on MikeHRC Eachine TX
memcpy(rx_tx_addr,(uint8_t *)"\x08\x03\x00\xA0",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x21",2);
break;
case 4: //Dump from air on Crashanium Eachine TX
memcpy(rx_tx_addr,(uint8_t *)"\x58\x08\x00\xA0",4);
memcpy(hopping_frequency,(uint8_t *)"\x0D\x31",2);
break;
default: //Dump from SPI
memcpy(rx_tx_addr,(uint8_t *)"\x6f\x2c\xb1\x93",4);
memcpy(hopping_frequency,(uint8_t *)"\x14\x1e",2);
break;
}
#else
//Tested with Eachine RX
rx_tx_addr[0]+=RX_num;
hopping_frequency[0]=(rx_tx_addr[0]&0x0F)+0x05;
hopping_frequency[1]=hopping_frequency[0]+0x05+(RX_num%0x2D);
#endif
hopping_frequency[2]=hopping_frequency[0]+0x37;
debugln("ID: %02X %02X %02X %02X , HOP: %02X %02X %02X",rx_tx_addr[0],rx_tx_addr[1],rx_tx_addr[2],rx_tx_addr[3],hopping_frequency[0],hopping_frequency[1],hopping_frequency[2]);
}
uint16_t V761_callback()
@@ -185,10 +226,18 @@ uint16_t V761_callback()
uint16_t initV761(void)
{
BIND_IN_PROGRESS;
bind_counter = V761_BIND_COUNT;
V761_initialize_txid();
phase = V761_BIND1;
if(IS_BIND_IN_PROGRESS)
{
bind_counter = V761_BIND_COUNT;
phase = V761_BIND1;
}
else
{
XN297_SetTXAddr(rx_tx_addr, 4);
phase = V761_DATA;
}
V761_init();
hopping_frequency_no = 0;
packet_count = 0;

View File

@@ -4,10 +4,10 @@
#endif
#if not defined (ORANGE_TX) && not defined (STM32_BOARD)
//Atmega328p
#if not defined(ARDUINO_AVR_PRO) && not defined(ARDUINO_MULTI_NO_BOOT) && not defined(ARDUINO_MULTI_FLASH_FROM_TX) && not defined(ARDUINO_AVR_MINI) && not defined(ARDUINO_AVR_NANO)
#if not defined(ARDUINO_AVR_PRO) && not defined(ARDUINO_MULTI_NO_BOOT) && not defined(ARDUINO_MULTI_FLASH_FROM_TX) && not defined(ARDUINO_AVR_MINI) && not defined(ARDUINO_AVR_NANO) && not defined(ARDUINO_AVR_DUEMILANOVE)
#error You must select one of these boards: "Multi 4-in-1", "Arduino Pro or Pro Mini" or "Arduino Mini"
#endif
#if F_CPU != 16000000L || not defined(__AVR_ATmega328P__)
#if F_CPU != 16000000L || not (defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__))
#error You must select the processor type "ATmega328(5V, 16MHz)"
#endif
#endif
@@ -109,9 +109,14 @@
#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."
#ifdef FORCE_RADIOLINK_TUNING
#if ( FORCE_RADIOLINK_TUNING < -127 ) || ( FORCE_RADIOLINK_TUNING > 127 )
#error "The RADIOLINK forced frequency tuning value is outside of the range -127..127."
#endif
#endif
#ifdef FORCE_FUTABA_TUNING
#if ( FORCE_FUTABA_TUNING < -127 ) || ( FORCE_FUTABA_TUNING > 127 )
#error "The Futaba forced frequency tuning value is outside of the range -127..127."
#endif
#endif
#ifdef FORCE_SKYARTEC_TUNING
@@ -135,9 +140,9 @@
#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."
#ifdef FORCE_HEIGHT_TUNING
#if ( FORCE_HEIGHT_TUNING < -300 ) || ( FORCE_HEIGHT_TUNING > 300 )
#error "The Height forced frequency tuning value is outside of the range -300..300."
#endif
#endif
#ifdef FORCE_PELIKAN_TUNING
@@ -150,6 +155,16 @@
#error "The Hubsan forced frequency tuning value is outside of the range -300..300."
#endif
#endif
#ifdef FORCE_KYOSHO_TUNING
#if ( FORCE_KYOSHO_TUNING < -300 ) || ( FORCE_KYOSHO_TUNING > 300 )
#error "The Kyosho forced frequency tuning value is outside of the range -300..300."
#endif
#endif
#ifdef FORCE_WFLY2_TUNING
#if ( FORCE_WFLY2_TUNING < -300 ) || ( FORCE_WFLY2_TUNING > 300 )
#error "The WFLY2 forced frequency tuning value is outside of the range -300..300."
#endif
#endif
#ifndef USE_A7105_CH15_TUNING
#ifndef FORCE_BUGS_TUNING
@@ -158,12 +173,18 @@
#ifndef FORCE_FLYSKY_TUNING
#define FORCE_FLYSKY_TUNING 0
#endif
#ifndef FORCE_FLYZONE_TUNING
#define FORCE_FLYZONE_TUNING 0
#ifndef FORCE_HEIGHT_TUNING
#define FORCE_HEIGHT_TUNING 0
#endif
#ifndef FORCE_PELIKAN_TUNING
#define FORCE_PELIKAN_TUNING 0
#endif
#ifndef FORCE_KYOSHO_TUNING
#define FORCE_KYOSHO_TUNING 0
#endif
#ifndef FORCE_WFLY2_TUNING
#define FORCE_WFLY2_TUNING 0
#endif
#ifndef FORCE_HUBSAN_TUNING
#define FORCE_HUBSAN_TUNING 0
#endif
@@ -185,34 +206,52 @@
#undef CC25_CSN_pin
#undef NRF24L01_INSTALLED // Disable NRF for OrangeTX module
#undef NRF_CSN_pin
#undef SX1276_INSTALLED // Disable NRF for OrangeTX module
#undef SX1276_INSTALLED // Disable SX1276 for OrangeTX module
#define TELEMETRY // Enable telemetry
#define INVERT_TELEMETRY // Enable invert telemetry
#define DSM_TELEMETRY // Enable DSM telemetry
#endif
//Change/Force RF chip configuration if MULTI_5IN1_INTERNAL
#ifdef MULTI_5IN1_INTERNAL
#if not defined(STM32_BOARD)
#error "Error MULTI_5IN1_INTERNAL is only for STM32 boards."
#endif
#define A7105_INSTALLED
#define CYRF6936_INSTALLED
#define CC2500_INSTALLED
#define NRF24L01_INSTALLED
#define SX1276_INSTALLED
#undef ENABLE_PPM
#endif
//Make sure protocols are selected correctly
#ifndef A7105_INSTALLED
#undef AFHDS2A_A7105_INO
#undef AFHDS2A_RX_A7105_INO
#undef BUGS_A7105_INO
#undef FLYSKY_A7105_INO
#undef FLYZONE_A7105_INO
#undef HEIGHT_A7105_INO
#undef HUBSAN_A7105_INO
#undef KYOSHO_A7105_INO
#undef PELIKAN_A7105_INO
#undef WFLY2_A7105_INO
#endif
#ifndef CYRF6936_INSTALLED
#undef DEVO_CYRF6936_INO
#undef DSM_CYRF6936_INO
#undef DSM_RX_CYRF6936_INO
#undef HOTT_CC2500_INO
#undef E010R5_CYRF6936_INO
#undef E129_CYRF6936_INO
#undef J6PRO_CYRF6936_INO
#undef MLINK_CYRF6936_INO
#undef TRAXXAS_CYRF6936_INO
#undef WFLY_CYRF6936_INO
#undef WK2x01_CYRF6936_INO
#endif
#ifndef CC2500_INSTALLED
#undef CORONA_CC2500_INO
#undef E016HV2_CC2500_INO
#undef ESKY150V2_CC2500_INO
#undef FRSKYD_CC2500_INO
#undef FRSKYL_CC2500_INO
@@ -221,9 +260,11 @@
#undef FRSKY_RX_CC2500_INO
#undef HITEC_CC2500_INO
#undef HOTT_CC2500_INO
#undef OMP_CC2500_INO // Use both CC2500 and NRF code
#undef REDPINE_CC2500_INO
#undef RLINK_CC2500_INO
#undef SCANNER_CC2500_INO
#undef SFHSS_CC2500_INO
#undef FUTABA_CC2500_INO
#undef SKYARTEC_CC2500_INO
#endif
#ifndef NRF24L01_INSTALLED
@@ -239,7 +280,6 @@
#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
@@ -251,12 +291,16 @@
#undef JJRC345_NRF24L01_INO
#undef KF606_NRF24L01_INO
#undef KN_NRF24L01_INO
#undef LOLI_NRF24L01_INO
#undef MJXQ_NRF24L01_INO
#undef MT99XX_NRF24L01_INO
#undef NCC1701_NRF24L01_INO
#undef OMP_CC2500_INO // Use both CC2500 and NRF code
#undef POTENSIC_NRF24L01_INO
#undef PROPEL_NRF24L01_INO
#undef Q303_NRF24L01_INO
#undef Q90C_NRF24L01_INO
#undef REALACC_NRF24L01_INO
#undef SHENQI_NRF24L01_INO
#undef SLT_NRF24L01_INO
#undef SYMAX_NRF24L01_INO
@@ -309,7 +353,13 @@
#undef BAYANG_RX_TELEMETRY
#undef BAYANG_RX_NRF24L01_INO
#undef DEVO_HUB_TELEMETRY
#undef PROPEL_HUB_TELEMETRY
#undef OMP_HUB_TELEMETRY
#undef RLINK_HUB_TELEMETRY
#undef DSM_RX_CYRF6936_INO
#undef DSM_FWD_PGM
#undef WFLY2_HUB_TELEMETRY
#undef LOLI_HUB_TELEMETRY
#else
#if defined(MULTI_TELEMETRY) && defined(MULTI_STATUS)
#error You should choose either MULTI_TELEMETRY or MULTI_STATUS but not both.
@@ -336,6 +386,12 @@
#if not defined(DEVO_CYRF6936_INO)
#undef DEVO_HUB_TELEMETRY
#endif
#if not defined(OMP_CC2500_INO)
#undef OMP_HUB_TELEMETRY
#endif
#if not defined(PROPEL_NRF24L01_INO)
#undef PROPEL_HUB_TELEMETRY
#endif
#if not defined(NCC1701_NRF24L01_INO)
#undef NCC1701_HUB_TELEMETRY
#endif
@@ -345,6 +401,9 @@
#if not defined(CABELL_NRF24L01_INO)
#undef CABELL_HUB_TELEMETRY
#endif
#if not defined(RLINK_CC2500_INO)
#undef RLINK_HUB_TELEMETRY
#endif
#if not defined(HUBSAN_A7105_INO)
#undef HUBSAN_HUB_TELEMETRY
#endif
@@ -359,7 +418,7 @@
#if not defined(FRSKYD_CC2500_INO)
#undef HUB_TELEMETRY
#endif
#if not defined(FRSKYX_CC2500_INO)
#if not defined(FRSKYX_CC2500_INO) && not defined(FRSKYR9_SX1276_INO)
#undef SPORT_TELEMETRY
#undef SPORT_SEND
#endif
@@ -372,7 +431,13 @@
#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)
#if not defined(WFLY2_A7105_INO)
#undef WFLY2_HUB_TELEMETRY
#endif
#if not defined(LOLI_NRF24L01_INO)
#undef LOLI_HUB_TELEMETRY
#endif
#if not defined(HOTT_FW_TELEMETRY) && not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BUGS_HUB_TELEMETRY) && not defined(NCC1701_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(RLINK_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS) && not defined(HITEC_HUB_TELEMETRY) && not defined(HITEC_FW_TELEMETRY) && not defined(SCANNER_TELEMETRY) && not defined(FRSKY_RX_TELEMETRY) && not defined(AFHDS2A_RX_TELEMETRY) && not defined(BAYANG_RX_TELEMETRY) && not defined(DEVO_HUB_TELEMETRY) && not defined(PROPEL_HUB_TELEMETRY) && not defined(OMP_HUB_TELEMETRY) && not defined(WFLY2_HUB_TELEMETRY) && not defined(LOLI_HUB_TELEMETRY)
#undef TELEMETRY
#undef INVERT_TELEMETRY
#undef MULTI_TELEMETRY

View File

@@ -0,0 +1,314 @@
/*
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(WFLY2_A7105_INO)
#include "iface_a7105.h"
//#define WFLY2_FORCE_ID
//WFLY2 constants & variables
#define WFLY2_BIND_COUNT 2777 // abort bind after 10sec
#define WFLY2_PACKET_SIZE 32
enum{
WFLY2_DATA,
WFLY2_PLL_TX,
WFLY2_RX,
};
static void __attribute__((unused)) WFLY2_build_packet()
{
static uint16_t pseudo=0;
//End bind
if(IS_BIND_IN_PROGRESS && bind_counter)
{
bind_counter--;
if (bind_counter==0)
{
BIND_DONE;
A7105_WriteID(MProtocol_id);
rf_ch_num = 0;
}
}
memset(packet,0x00,WFLY2_PACKET_SIZE);
if(IS_BIND_IN_PROGRESS)
{
//Header
packet[0] = 0x0F; // Bind packet
//ID
packet[1] = rx_tx_addr[3];
packet[2] = rx_tx_addr[2];
packet[3] = rx_tx_addr[1];
//packet[4] = 0x00; // Should be rx_tx_addr[0]&0x0F but bind is already using 0x00 so ....
//Unknown
packet[5] = 0x01;
//Freq
rf_ch_num = (hopping_frequency_no<<1)+0x08;
packet[6] = rf_ch_num;
hopping_frequency_no++;
if(hopping_frequency_no > 0x17) hopping_frequency_no=0x00;
//Unknown bytes 7..31
}
else
{
//Pseudo
uint16_t high_bit=(pseudo & 0x8000) ^ 0x8000; // toggle 0x8000 every other line
pseudo <<= 1; // *2
if( (pseudo & 0x8000) || pseudo == 0 ) pseudo ^= 0x8A87; // Randomisation, pseudo==0 is a guess but would give the start value seen on the dump when P[2]P[1]=0 at init and will prevent a lock up
pseudo |= high_bit; // include toggle
packet[1] = pseudo;
packet[2] = pseudo>>8;
//RF channel
int8_t prev = rf_ch_num & 0x1F;
rf_ch_num = (pseudo ^ (pseudo >> 7));
rf_ch_num = ((rf_ch_num>>1)&0x08) | (rf_ch_num & 0x47);
rf_ch_num = ((rf_ch_num>>2)&0x10) | (rf_ch_num & 0x1F);
rf_ch_num ^= rx_tx_addr[3] & 0x1F;
if(abs((int8_t)rf_ch_num-prev) <= 9)
{
if(high_bit)
rf_ch_num |= 0x20;
}
else
if(!high_bit)
rf_ch_num |= 0x20;
//Partial ID
packet[3] = rx_tx_addr[3];
packet[4] = rx_tx_addr[2] & 0x03;
//Header
if(prev_option!=option)
{//Set the RX PPM/WBUS on change
packet[0] = 0x05; //PPM/WBUS packet
packet[5] = 0x01;
if(option)
packet[6] = 0x01; // PPM
else
packet[6] = 0x00; // WBUS
prev_option = option;
}
else
{//Normal or Failsafe packets
uint8_t offset=0;
//packet[0] = 0x00; // Normal packet
#ifdef FAILSAFE_ENABLE
if(IS_FAILSAFE_VALUES_on)
{//Failsafe packet
packet[0] = 0x01; //Failsafe packet
packet[5] = 0x58; // unknown, values are counting 58,59,5A,5B and rollover
packet[6] = 0x55; // unknown and constant
offset=2;
}
#endif
//10 channels -100%=0x2C1...0%=0x800...+100%=0xD3F
for(uint8_t i = 0; i < 5; i++)
{
uint16_t temp=convert_channel_16b_nolimit(i*2 , 0x2C1, 0xD3F, IS_FAILSAFE_VALUES_on);
packet[5 + offset + i*3] = temp&0xFF; // low byte
packet[7 + offset + i*3] = (temp>>8)&0x0F; // high byte
temp=convert_channel_16b_nolimit(i*2+1, 0x2C1, 0xD3F, IS_FAILSAFE_VALUES_on);
packet[6 + offset + i*3] = temp&0xFF; // low byte
packet[7 + offset + i*3] |= (temp>>4)&0xF0; // high byte
}
//Unknown bytes 20+offset..31
#ifdef FAILSAFE_ENABLE
FAILSAFE_VALUES_off;
#endif
}
}
//Debug
#if 0
debug("ch=%02X,%02X P=",rf_ch_num,(rf_ch_num<<1)+0x10);
for(uint8_t i=0; i<WFLY2_PACKET_SIZE; i++)
debug("%02X ", packet[i]);
debugln("");
#endif
}
#ifdef WFLY2_HUB_TELEMETRY
static void __attribute__((unused)) WFLY2_Send_Telemetry()
{
//Incoming packet values
v_lipo1=packet[3]<<1; // RX_batt *10 in V
v_lipo2=packet[5]<<1; // Ext_batt*10 in V
RX_RSSI=(255-packet[7])>>1; // Looks to be the RX RSSI value direct from A7105
// Read TX RSSI
TX_RSSI=255-A7105_ReadReg(A7105_1D_RSSI_THOLD);
telemetry_counter++; // LQI counter
telemetry_link=1;
if(telemetry_lost)
{
telemetry_lost = 0;
packet_count = 100;
telemetry_counter = 100;
}
}
#endif
#define WFLY2_PACKET_PERIOD 3600 //3600
#define WFLY2_BUFFER_TIME 1500 //1500
#define WFLY2_WRITE_TIME 800 //942
uint16_t ReadWFLY2()
{
uint16_t start;
uint8_t status;
#ifndef FORCE_WFLY2_TUNING
A7105_AdjustLOBaseFreq(1);
#endif
switch(phase)
{
case WFLY2_DATA:
#ifdef MULTI_SYNC
telemetry_set_input_sync(WFLY2_PACKET_PERIOD);
#endif
//Build data packet
WFLY2_build_packet();
//Fill the TX buffer without sending
A7105_WriteData(WFLY2_PACKET_SIZE,0);
#ifdef WFLY2_HUB_TELEMETRY
//LQI calculation
packet_count++;
if(packet_count>=100)
{
packet_count=0;
TX_LQI=telemetry_counter;
if(telemetry_counter==0)
telemetry_lost = 1;
telemetry_counter = 0;
}
#endif
phase++; // WFLY2_PLL_TX
return WFLY2_BUFFER_TIME;
case WFLY2_PLL_TX:
//Check RX status
status=A7105_ReadReg(A7105_00_MODE);
//debugln("S:%02X", status);
//PLL
A7105_Strobe(A7105_PLL);
//Read incoming packet even if bad/not present to not change too much the TX timing, might want to reorg the code...
A7105_ReadData(WFLY2_PACKET_SIZE);
//Read telemetry
if((status & 0x21)==0)
{ // Packet received and CRC OK
//Debug
#if 1
debug("T:");
for(uint8_t i=0; i<WFLY2_PACKET_SIZE-20; i++) // Can't send the full telemetry at full speed
debug(" %02X", packet[i]);
debugln("");
#endif
if(IS_BIND_IN_PROGRESS)
{
if(packet[0]==0x0F && packet[1]==rx_tx_addr[3] && packet[2]==rx_tx_addr[2] && packet[3]==rx_tx_addr[1] && packet[4]==0x00)
{
bind_counter=1; // End bind
debugln("Bind done");
//packet[5..7] contains the RXID
}
}
#ifdef WFLY2_HUB_TELEMETRY
else
if(packet[0]==0 && packet[1]==rx_tx_addr[3] && packet[2]==(rx_tx_addr[2] & 0x03))
{//Packet match the ID
WFLY2_Send_Telemetry(); // Packet looks good do send telem to the radio
}
#endif
}
//Change RF channel
A7105_WriteReg(A7105_0F_PLL_I, (rf_ch_num<<1)+0x10);
//Switch to TX
A7105_SetPower();
A7105_SetTxRxMode(TX_EN);
A7105_Strobe(A7105_TX);
phase++; // WFLY2_RX
return WFLY2_WRITE_TIME;
case WFLY2_RX:
//Wait for TX completion
start=micros();
while ((uint16_t)((uint16_t)micros()-start) < 700) // Wait max 700µs
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
break;
//Switch to RX
A7105_SetTxRxMode(RX_EN);
A7105_Strobe(A7105_RX);
phase = WFLY2_DATA;
return WFLY2_PACKET_PERIOD-WFLY2_WRITE_TIME-WFLY2_BUFFER_TIME;
}
return WFLY2_PACKET_PERIOD; // never reached, please the compiler
}
uint16_t initWFLY2()
{
A7105_Init();
#ifdef WFLY2_FORCE_ID
MProtocol_id = 0x50002313; //Richard
//MProtocol_id = 0x50000223; //Pascal
#endif
MProtocol_id &= 0x00FFFFFF; // Since the bind ID starts with 50, let's keep only the last 3 bytes of the ID
MProtocol_id |= 0x50000000; // As recommended on the A7105 datasheet
set_rx_tx_addr(MProtocol_id); // Update the ID
if(IS_BIND_IN_PROGRESS)
A7105_WriteID(0x50FFFFFE); // Bind ID
else
A7105_WriteID(MProtocol_id);
hopping_frequency_no=0;
rf_ch_num = 0;
bind_counter = WFLY2_BIND_COUNT;
phase = WFLY2_DATA;
prev_option = option;
#ifdef WFLY2_HUB_TELEMETRY
packet_count = 0;
telemetry_lost = 1;
#endif
return 2000;
}
#endif

View File

@@ -105,23 +105,23 @@ static uint16_t __attribute__((unused)) WFLY_send_data_packet()
len=4;
for(uint8_t i=0;i<3;i++)
{ // Channels
uint16_t ch = convert_channel_16b_nolimit(i*4+0,151,847);
uint16_t ch = convert_channel_16b_nolimit(i*4+0,151,847,false);
uint8_t offset=i*5;
packet[3+offset]|=ch<<6;
packet[4+offset]=ch>>2;
len++;
if(--nbr_ch==0) break;
ch = convert_channel_16b_nolimit(i*4+1,151,847);
ch = convert_channel_16b_nolimit(i*4+1,151,847,false);
packet[5+offset]=ch;
packet[6+offset]=ch>>8;
len+=2;
if(--nbr_ch==0) break;
ch = convert_channel_16b_nolimit(i*4+2,151,847);
ch = convert_channel_16b_nolimit(i*4+2,151,847,false);
packet[6+offset]|=ch<<2;
packet[7+offset]=ch>>6;
len++;
if(--nbr_ch==0) break;
ch = convert_channel_16b_nolimit(i*4+3,151,847);
ch = convert_channel_16b_nolimit(i*4+3,151,847,false);
packet[7+offset]|=ch<<4;
packet[8+offset]=ch>>4;
len++;

View File

@@ -79,7 +79,7 @@ static void __attribute__((unused)) WK_build_bind_pkt(const uint8_t *init)
static int16_t __attribute__((unused)) WK_get_channel(uint8_t ch, int32_t scale, int16_t center, int16_t range)
{
int16_t value = convert_channel_16b_nolimit(CH_AETR[ch],-scale,scale)+center;
int16_t value = convert_channel_16b_nolimit(CH_AETR[ch],-scale,scale,false)+center;
if (value < center - range) value = center - range;
if (value > center + range) value = center + range;
return value;
@@ -451,7 +451,7 @@ uint16_t WK_cb()
}
packet_sent = 0;
uint8_t start=micros();
while ((uint8_t)micros()-start < 100) // Wait max 100µs
while ((uint8_t)((uint8_t)micros()-start) < 100) // Wait max 100µs
if(CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS) & 0x02)
break;
if((packet_count & 0x03) == 0)

View File

@@ -29,7 +29,16 @@ Multiprotocol is distributed in the hope that it will be useful,
static uint16_t __attribute__((unused)) XK_convert_channel(uint8_t num)
{
uint16_t val=convert_channel_10b(num);
uint16_t val;
if(num==RUDDER)
{// introduce deadband on rudder to prevent twitching
//debug("RUD:%d",val);
val=convert_channel_8b_limit_deadband(RUDDER,0x00,0x80, 0xFF, 40)<<2;
//debugln(",%d",val);
}
else
val=convert_channel_10b(num, false);
// 1FF..01=left, 00=center, 200..3FF=right
if(val==0x200)
val=0; // 0
@@ -56,18 +65,18 @@ static void __attribute__((unused)) XK_send_packet()
packet[14] = 0xC0;
else
{
uint16_t val=convert_channel_10b(THROTTLE);
uint16_t val=convert_channel_10b(THROTTLE, false);
packet[0] = val>>2; // 0..255
//packet[12] |= val & 2;
packet[12] |= val & 2;
val=XK_convert_channel(RUDDER);
packet[1] = val>>2;
//packet[12] |= (val & 2)<<2;
packet[12] |= (val & 2)<<2;
val=XK_convert_channel(ELEVATOR);
packet[2] = val>>2;
//packet[13] |= val & 2;
packet[13] |= val & 2;
val=XK_convert_channel(AILERON);
packet[3] = val>>2;
//packet[13] |= (val & 2)<<2;
packet[13] |= (val & 2)<<2;
memset(&packet[4],0x40,3); // Trims
@@ -84,6 +93,7 @@ static void __attribute__((unused)) XK_send_packet()
|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
//debugln("P1:%02X,P12:%02X",packet[1],packet[12]);
}
crc=packet[0];

View File

@@ -23,7 +23,7 @@
// Parameters which can be modified
#define XN297DUMP_PERIOD_SCAN 50000 // 25000
#define XN297DUMP_MAX_RF_CHANNEL 84 // Default 84
#define XN297DUMP_MAX_RF_CHANNEL 127 // Default 84
// Do not touch from there
#define XN297DUMP_INITIAL_WAIT 500
@@ -92,7 +92,7 @@ static boolean __attribute__((unused)) XN297Dump_process_packet(void)
// address
for (uint8_t i = 0; i < address_length; i++)
{
crc = crc16_update(crc, packet[i], 8);
crc16_update( packet[i], 8);
packet_un[address_length-1-i]=packet[i];
packet_sc[address_length-1-i]=packet[i] ^ xn297_scramble[i];
}
@@ -100,7 +100,7 @@ static boolean __attribute__((unused)) XN297Dump_process_packet(void)
// payload
for (uint8_t i = address_length; i < XN297DUMP_MAX_PACKET_LEN-XN297DUMP_CRC_LENGTH; i++)
{
crc = crc16_update(crc, packet[i], 8);
crc16_update( packet[i], 8);
packet_sc[i] = bit_reverse(packet[i]^xn297_scramble[i]);
packet_un[i] = bit_reverse(packet[i]);
// check crc
@@ -125,14 +125,13 @@ static boolean __attribute__((unused)) XN297Dump_process_packet(void)
//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);
crc16_update( packet[i], 8);
crc16_update( 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)
if((crc ^ pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[i - 3])) == crcxored)
{ // Found a valid CRC for the enhanced payload mode
packet_length=i;
scramble=true;
@@ -141,7 +140,7 @@ static boolean __attribute__((unused)) XN297Dump_process_packet(void)
memcpy(packet_un,packet_sc,packet_length+2); // unscramble packet
break;
}
if((crc_enh ^ pgm_read_word(&xn297_crc_xorout_enhanced[i - 3])) == crcxored)
if((crc ^ pgm_read_word(&xn297_crc_xorout_enhanced[i - 3])) == crcxored)
{ // Found a valid CRC for the enhanced payload mode
packet_length=i;
scramble=false;
@@ -278,7 +277,7 @@ static uint16_t XN297Dump_callback()
XN297Dump_overflow();
}
}
else
else if(sub_protocol==XN297DUMP_AUTO)
{
switch(phase)
{
@@ -392,6 +391,9 @@ static uint16_t XN297Dump_callback()
{ // Scan frequencies
hopping_frequency_no++;
bind_counter=0;
if(packet_count && packet_count<=5)
debug("\r\nTrying RF channel: ");
packet_count=0;
if(hopping_frequency_no>XN297DUMP_MAX_RF_CHANNEL)
{
debug("\r\n\r\n%d RF channels identified:",rf_ch_num);
@@ -411,7 +413,7 @@ static uint16_t XN297Dump_callback()
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;
time_rf[hopping_frequency_no]=0xFFFFFFFF;
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency[0]);
uint16_t timeL=TCNT1;
if(TIMER2_BASE->SR & TIMER_SR_UIF)
@@ -472,10 +474,9 @@ static uint16_t XN297Dump_callback()
debug(" %02X",packet[i]);
packet_count++;
if(packet_count>5)
{
{//change channel
bind_counter=XN297DUMP_PERIOD_SCAN+1;
debug("\r\nTrying RF channel: ");
packet_count=0;
}
}
}
@@ -502,7 +503,7 @@ static uint16_t XN297Dump_callback()
do
{
time=time_rf[i];
if(time!=-1)
if(time!=0xFFFFFFFF)
{
next=i;
for(uint8_t j=2;j<rf_ch_num;j++)
@@ -622,6 +623,124 @@ static uint16_t XN297Dump_callback()
break;
}
}
else
{
if(phase==0)
{
address_length=4;
memcpy(rx_tx_addr, (uint8_t *)"\x5A\x20\x12\xAC", address_length); //"\xA3\x05\x22\xC1"
bitrate=XN297DUMP_1M;
packet_length=32;
hopping_frequency_no=60; //bind ?, normal 60
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TXRX_OFF);
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, address_length-2); // RX/TX address length
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, address_length); // set up RX address
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, packet_length); // Enable rx pipe 0
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency_no);
debug("NRF dump, len=%d, rf=%d, address length=%d, bitrate=",packet_length,hopping_frequency_no,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();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX)); //_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) |
phase++;
}
else
{
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
{ // RX fifo data ready
if(NRF24L01_ReadReg(NRF24L01_09_CD))
{
NRF24L01_ReadPayload(packet, packet_length);
bool ok=true;
uint8_t buffer[40];
memcpy(buffer,packet,packet_length);
if(memcmp(&packet_in[0],&packet[0],packet_length))
{
//realign bits
for(uint8_t i=0; i<packet_length; i++)
buffer[i]=buffer[i+2];
//for(uint8_t i=0; i<packet_length; i++)
// buffer[i]=(buffer[i]<<4)+(buffer[i+1]>>4);
//check for validity and decode
memset(packet_in,0,packet_length);
for(uint8_t i=0; i<packet_length-2; i++)
{
for(uint8_t j=0;j<2;j++)
{
packet_in[i>>2] >>= 1;
if( (buffer[i]&0xC0) == 0xC0 && (buffer[i]&0x30) == 0x00 )
packet_in[i>>2] |= 0x80;
else if( (buffer[i]&0xC0) == 0x00 && (buffer[i]&0x30) == 0x30 )
packet_in[i>>2] |= 0x00;
else
ok=false; // error
buffer[i] <<= 4;
}
}
if(ok)
{
debug("P:(%02X,%02X):",packet[0],packet[1]);
for(uint8_t i=0;i<packet_length/4;i++)
debug(" %02X",packet_in[i]);
debugln("");
memcpy(packet_in,packet,packet_length);
}
}
/*crc=0;
for (uint8_t i = 1; i < 12; ++i)
crc16_update( packet[i], 8);
if(packet[12]==((crc>>8)&0xFF) && packet[13]==(crc&0xFF))
if(memcmp(&packet_in[1],&packet[1],packet_length-1))
{
debug("P:");
for(uint8_t i=0;i<packet_length;i++)
debug(" %02X",packet[i]);
debug(" CRC: %04X",crc);
debugln("");
debug("P(%02X):",packet[0]);
for(uint8_t i=1;i<packet_length-2;i++)
debug(" %02X",((bit_reverse(packet[i])<<1)|(bit_reverse(packet[i-1])>>7))&0xFF);
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();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX)); // _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) |
}
}
}
bind_counter++;
if(IS_RX_FLAG_on) // Let the radio update the protocol
{

View File

@@ -16,7 +16,7 @@ Multiprotocol is distributed in the hope that it will be useful,
#if defined(ZSX_NRF24L01_INO)
#include "iface_nrf250k.h"
#include "iface_nrf24l01.h"
//#define FORCE_ZSX_ORIGINAL_ID

View File

@@ -69,9 +69,10 @@
/****************/
/*** RF CHIPS ***/
/****************/
//There are 4 RF components supported. If one of them is not installed you must comment it using "//".
//There are 5 RF components supported. If one of them is not installed you must comment it using "//".
//If a chip is not installed all associated protocols are automatically disabled.
//4-in-1 modules have all RF chips installed
//4-in-1 modules have the A7105, CYRF6936, CC2500 and NRF24L01 RF chips installed
//5-in-1 modules have all RF chips installed
//!!!If a RF chip is present it MUST be marked as installed!!! or weird things will happen you have been warned.
#define A7105_INSTALLED
#define CYRF6936_INSTALLED
@@ -79,13 +80,17 @@
#define NRF24L01_INSTALLED
//#define SX1276_INSTALLED // only supported on STM32 modules
//Uncomment (remove //) if you have an internal 5-in-1 Multi module.
//All components are considered to be installed and specifics to that module are automatically configured
//#define MULTI_5IN1_INTERNAL
/** OrangeRX TX **/
//If you compile for the OrangeRX TX module you need to select the correct board type.
//By default the compilation is done for the GREEN board, to switch to a BLUE board uncomment the line below by removing the "//"
//#define ORANGE_TX_BLUE
/** CC2500 Fine Frequency Tuning **/
//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.
//For optimal performance the CC2500 RF module used by the CORONA, FrSkyD, FrSkyV, FrSkyX, Hitec, HoTT, Futaba/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
@@ -95,11 +100,12 @@
//#define FORCE_FRSKYL_TUNING 0
//#define FORCE_FRSKYV_TUNING 0
//#define FORCE_FRSKYX_TUNING 0
//#define FORCE_SFHSS_TUNING 0
//#define FORCE_SKYARTEC_TUNING 0
//#define FORCE_HITEC_TUNING 0
//#define FORCE_HOTT_TUNING 0
//#define FORCE_RADIOLINK_TUNING 0
//#define FORCE_REDPINE_TUNING 0
//#define FORCE_FUTABA_TUNING 0
//#define FORCE_SKYARTEC_TUNING 0
/** A7105 Fine Frequency Tuning **/
//This is required in rare cases where some A7105 modules and/or RXs have an inaccurate crystal oscillator.
@@ -112,9 +118,11 @@
//#define FORCE_AFHDS2A_TUNING 0
//#define FORCE_BUGS_TUNING 0
//#define FORCE_FLYSKY_TUNING 0
//#define FORCE_FLYZONE_TUNING 0
//#define FORCE_PELIKAN_TUNING 0
//#define FORCE_HEIGHT_TUNING 0
//#define FORCE_HUBSAN_TUNING 0
//#define FORCE_KYOSHO_TUNING 0
//#define FORCE_PELIKAN_TUNING 0
//#define FORCE_WFLY2_TUNING 0
/** CYRF6936 Fine Frequency Tuning **/
//This is required in rare cases where some CYRF6936 modules and/or RXs have an inaccurate crystal oscillator.
@@ -160,17 +168,21 @@
//The protocols below need an A7105 to be installed
#define AFHDS2A_A7105_INO
#define AFHDS2A_RX_A7105_INO
#define AFHDS2A_RX_A7105_INO
#define BUGS_A7105_INO
#define FLYSKY_A7105_INO
#define FLYZONE_A7105_INO
#define HEIGHT_A7105_INO
#define HUBSAN_A7105_INO
#define PELIKAN_A7105_INO
#define KYOSHO_A7105_INO
#define PELIKAN_A7105_INO
#define WFLY2_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 DSM_RX_CYRF6936_INO
#define E010R5_CYRF6936_INO
#define E129_CYRF6936_INO
#define J6PRO_CYRF6936_INO
#define TRAXXAS_CYRF6936_INO
#define WFLY_CYRF6936_INO
@@ -178,7 +190,8 @@
//The protocols below need a CC2500 to be installed
#define CORONA_CC2500_INO
#define ESKY150V2_CC2500_INO //Need both CC2500 and NRF
#define E016HV2_CC2500_INO
#define ESKY150V2_CC2500_INO
#define FRSKYL_CC2500_INO
#define FRSKYD_CC2500_INO
#define FRSKYV_CC2500_INO
@@ -187,9 +200,10 @@
#define HITEC_CC2500_INO
#define HOTT_CC2500_INO
#define SCANNER_CC2500_INO
#define SFHSS_CC2500_INO
#define FUTABA_CC2500_INO
#define SKYARTEC_CC2500_INO
#define REDPINE_CC2500_INO
#define RLINK_CC2500_INO
//The protocols below need a NRF24L01 to be installed
#define ASSAN_NRF24L01_INO
@@ -212,15 +226,19 @@
#define HISKY_NRF24L01_INO
#define HONTAI_NRF24L01_INO
#define H8_3D_NRF24L01_INO
#define JJRC345_NRF24L01_INO
#define JJRC345_NRF24L01_INO
#define KF606_NRF24L01_INO
#define KN_NRF24L01_INO
#define LOLI_NRF24L01_INO
#define MJXQ_NRF24L01_INO
#define MT99XX_NRF24L01_INO
#define NCC1701_NRF24L01_INO
#define OMP_CC2500_INO //Need both CC2500 and NRF
#define POTENSIC_NRF24L01_INO
#define PROPEL_NRF24L01_INO
#define Q303_NRF24L01_INO
#define Q90C_NRF24L01_INO
#define REALACC_NRF24L01_INO
#define SHENQI_NRF24L01_INO
#define SLT_NRF24L01_INO
#define SYMAX_NRF24L01_INO
@@ -233,7 +251,7 @@
#define ZSX_NRF24L01_INO
//The protocols below need a SX1276 to be installed
#define FRSKYR9_SX1276_INO
#define FRSKYR9_SX1276_INO
/***************************/
/*** PROTOCOLS SETTINGS ***/
@@ -250,16 +268,18 @@
// For example, a value of -80% applied on channel 14 will instantly kill the motors on the X-Vert.
#define DSM_THROTTLE_KILL_CH 14
//Enable DSM Forward Programming
#define DSM_FWD_PGM
//AFHDS2A specific settings
//-------------------------
//When enabled (remove the "//"), the below setting makes LQI (Link Quality Indicator) available on one of the RX ouput channel (5-14).
//#define AFHDS2A_LQI_CH 14
/**************************/
/*** FAILSAFE SETTINGS ***/
/**************************/
//The following protocols are supporting failsafe: FrSkyX, Devo, WK2x01, SFHSS, HISKY/HK310 and AFHDS2A
//The following protocols are supporting failsafe: FrSkyX, Devo, WK2x01, Futaba/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 "//".
@@ -304,7 +324,12 @@
#define DEVO_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define HUBSAN_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define NCC1701_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define OMP_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define PROPEL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define CABELL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define RLINK_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define WFLY2_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define LOLI_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
#define 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
@@ -389,7 +414,7 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
/* 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 },
/* 8 */ {PROTO_FUTABA, NONE , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // option=fine freq tuning
/* 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
@@ -499,6 +524,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PPM_IBUS
PWM_SBUS
PPM_SBUS
PWM_IB16
PPM_IB16
PROTO_AFHDS2A_RX
NONE
PROTO_ASSAN
@@ -509,6 +536,7 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
X16_AH
IRDRONE
DHD_D4
QX100
PROTO_BAYANG_RX
NONE
PROTO_BUGS
@@ -548,10 +576,16 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
DSMX_11
PROTO_DSM_RX
NONE
PROTO_E010R5
NONE
PROTO_E016HV2
NONE
PROTO_E01X
E012
E015
E016H
PROTO_E129
NONE
PROTO_ESKY
ESKY_STD
ESKY_ET4
@@ -566,8 +600,6 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
V6X6
V912
CX20
PROTO_FLYZONE
FZ410
PROTO_FQ777
NONE
PROTO_FRSKY_RX
@@ -584,6 +616,10 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
R9_868
R9_915_8CH
R9_868_8CH
R9_FCC
R9_EU
R9_FCC_8CH
R9_EU_8CH
PROTO_FRSKYV
NONE
PROTO_FRSKYX
@@ -591,7 +627,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
CH_8
EU_16
EU_8
XCLONE
XCLONE_16
XCLONE_8
PROTO_FRSKYX2
CH_16
CH_8
@@ -616,6 +653,9 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
H20H
H20MINI
H30MINI
PROTO_HEIGHT
HEIGHT_5CH
HEIGHT_8CH
PROTO_HISKY
Hisky
HK310
@@ -629,7 +669,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
X5C1
FQ777_951
PROTO_HOTT
NONE
HOTT_SYNC
HOTT_NO_SYNC
PROTO_HUBSAN
H107
H301
@@ -637,12 +678,18 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PROTO_J6PRO
NONE
PROTO_JJRC345
NONE
JJRC345
SKYTMBLR
PROTO_KF606
NONE
PROTO_KN
WLTOYS
FEILUN
PROTO_KYOSHO
KYOSHO_FHSS
KYOSHO_HYPE
PROTO_LOLI
NONE
PROTO_MJXQ
WLH08
X600
@@ -651,6 +698,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
E010
H26WH
PHOENIX
PROTO_MLINK
NONE
PROTO_MT99XX
MT99
H7
@@ -659,8 +708,11 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
FY805
PROTO_NCC1701
NONE
PROTO_PELIKAN
PROTO_OMP
NONE
PROTO_PELIKAN
PELIKAN_PRO
PELIKAN_LITE
PROTO_POTENSIC
NONE
PROTO_PROPEL
@@ -674,12 +726,20 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
CX35
CX10D
CX10WD
PROTO_Q90C
NONE
PROTO_REALACC
NONE
PROTO_REDPINE
RED_FAST
RED_SLOW
PROTO_RLINK
RLINK_SURFACE
RLINK_AIR
RLINK_DUMBORC
PROTO_SCANNER
NONE
PROTO_SFHSS
PROTO_FUTABA
NONE
PROTO_SHENQI
NONE
@@ -701,13 +761,17 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
PROTO_V2X2
V2X2
JXD506
V2X2_MR101
PROTO_V761
NONE
V761_3CH
V761_4CH
PROTO_V911S
V911S_STD
V911S_E119
PROTO_WFLY
NONE
PROTO_WFLY2
NONE
PROTO_WK2x01
WK2801
WK2401

View File

@@ -68,7 +68,7 @@
/* 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 },
/* 8 */ {PROTO_HUBSAN, 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

View File

@@ -0,0 +1,14 @@
#ifndef _IFACE_RF2500_H_
#define _IFACE_RF2500_H_
#include "iface_cyrf6936.h"
//RF2500
static void __attribute__((unused)) RF2500_Init(uint8_t, bool);
static void __attribute__((unused)) RF2500_SetTXAddr(const uint8_t*);
static void __attribute__((unused)) RF2500_BuildPayload(uint8_t*);
static void __attribute__((unused)) RF2500_SendPayload();
#define RF2500_SetPower() CYRF_GFSK1M_SetPower()
#define RF2500_RFChannel(X) CYRF_ConfigRFChannel(X)
#endif

View File

@@ -27,6 +27,10 @@ enum
SX1276_0D_FIFOADDRPTR = 0x0D,
SX1276_0E_FIFOTXBASEADDR = 0x0E,
SX1276_11_IRQFLAGSMASK = 0x11,
SX1276_12_REGIRQFLAGS = 0x12,
SX1276_13_REGRXNBBYTES = 0x13,
SX1276_19_PACKETSNR = 0x19,
SX1276_1A_PACKETRSSI = 0x1A,
SX1276_1D_MODEMCONFIG1 = 0x1D,
SX1276_1E_MODEMCONFIG2 = 0x1E,
SX1276_20_PREAMBLEMSB = 0x20,
@@ -40,6 +44,24 @@ enum
SX1276_4D_PADAC = 0x4D
};
enum
{
SX1276_REGIRQFLAGS_CADDETECTED = 0,
SX1276_REGIRQFLAGS_FHSSCHANGECHANNEL = 1,
SX1276_REGIRQFLAGS_CADDONE = 2,
SX1276_REGIRQFLAGS_TXDONE = 3,
SX1276_REGIRQFLAGS_VALIDHEADER = 4,
SX1276_REGIRQFLAGS_PAYLOADCRCERROR = 5,
SX1276_REGIRQFLAGS_RXDONE = 6,
SX1276_REGIRQFLAGS_RXTIMEOUT = 7,
};
enum
{
SX1276_36_LORA_REGHIGHBWOPTIMIZE1 = 0x36,
SX1276_3A_LORA_REGHIGHBWOPTIMIZE2 = 0x3A
};
enum
{
SX1276_OPMODE_SLEEP = 0,

View File

@@ -6,24 +6,20 @@ Here are detailed descriptions of every supported protocols (sorted by RF module
The Deviation project (on which this project was based) have a useful list of models and protocols [here](http://www.deviationtx.com/wiki/supported_models).
## Useful notes and definitions
- **Extended limits supported** - A command range of -125%..+125% will be transmitted. Otherwise the default is -100%..+100% only.
- **Channel Order** - The channel order assumed in all the documentation is AETR. You can change this in the compilation settings. The module will take whatever input channel order and will rearrange them to match the output channel order required by the selected protocol.
- **Channel Order** - The channel order assumed in all the documentation is AETR. You can change this in the compilation settings or by using a precompiled firmware. The module will take whatever input channel order you have choosen and will rearrange them to match the output channel order required by the selected protocol.
- **Channel ranges** - A radio output of -100%..0%..+100% will match on the selected protocol -100%,0%,+100%. No convertion needs to be done.
- **Extended limits supported** - A channel range of -125%..+125% will be transmitted. Otherwise it will be truncated to -100%..+100%.
- **Italic numbers** are referring to protocol/sub_protocol numbers that you should use if the radio (serial mode only) is not displaying (yet) the protocol you want to access.
- **Autobind protocol**:
- **Autobind protocol** - The transmitter will automatically initiate a bind sequence on power up or model/protocol selection. This is for models where the receiver expects to rebind every time it is powered up. In these protocols you do not need to press the bind button at power up to bind, it will be done automatically. In case a protocol is not autobind but you want to enable it, change the "Autobind" or "Bind on channel" on OpenTX setting to Y for the specific model/entry.
1. The transmitter will automatically initiate a bind sequence on power up. This is for models where the receiver expects to rebind every time it is powered up. In these protocols you do not need to press the bind button at power up to bind, it will be done automatically. In case a protocol is not autobind but you want to enable it, change the "Autobind" (or "Bind at powerup" on OpenTX) setting to Y for the specific model/entry.
2. Enable Bind from channel feature:
* Bind from channel can be globally enabled/disabled in _config.h using ENABLE_BIND_CH.
* Bind from channel can be locally enabled/disabled by setting Autobind to Y/N per model for serial or per dial switch number for ppm.
* Bind channel can be choosen on any channel between 5 and 16 using BIND_CH in _config.h. Default is 16.
* Bind will only happen if all these elements are happening at the same time:
- Autobind = Y
## Bind on channel feature
* Bind on channel can be globally enabled/disabled in _config.h using ENABLE_BIND_CH. Any channel between 5 and 16 can be used by configuring BIND_CH in _config.h. Default is 16.
* Bind on channel can be locally enabled/disabled by setting "Bind on channel" or "Autobind" per model for serial or per dial switch number for ppm.
* Once activated, any bind will only happen if all these elements are happening at the same time:
- Bind on channel = Y
- Throttle = LOW (<-95%)
- Bind channel is going from -100% to +100%
* Additional notes:
- **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.
- Bind channel (16 by default) is going from -100% to +100%
- **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.
## Protocol selection in PPM mode
The protocol selection is based on 2 parameters:
@@ -67,8 +63,8 @@ You've upgraded the module but the radio does not display the name of the protoc
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
[Bayang](Protocols_Details.md#BAYANG---14)|14|Bayang|H8S3D|X16_AH|IRDRONE|DHD_D4|QX100|||NRF24L01|XN297
[Bayang RX](Protocols_Details.md#BAYANG-RX---59)|59|RX||||||||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|
@@ -78,62 +74,72 @@ CFlie|38|CFlie||||||||NRF24L01|
[CX10](Protocols_Details.md#CX10---12)|12|GREEN|BLUE|DM007|-|J3015_1|J3015_2|MK33041||NRF24L01|XN297
[Devo](Protocols_Details.md#DEVO---7)|7|Devo|8CH|10CH|12CH|6CH|7CH|||CYRF6936|
[DM002](Protocols_Details.md#DM002---33)|33|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|
[DSM](Protocols_Details.md#DSM---6)|6|DSM2_1F|DSM2_2F|DSMX_1F|DSMX_2F|AUTO||||CYRF6936|
[DSM_RX](Protocols_Details.md#DSM_RX---70)|70|RX||||||||CYRF6936|
[E010R5](Protocols_Details.md#E010R5---81)|81|||||||||CYRF6936/NRF24L01|RF2500
[E016HV2](Protocols_Details.md#E016HV2---80)|80|||||||||CC2500/NRF24L01|unknown
[E01X](Protocols_Details.md#E01X---45)|45|E012|E015|E016H||||||NRF24L01|XN297/HS6200
[ESky](Protocols_Details.md#ESKY---16)|16|ESky|Std|ET4||||||NRF24L01|
[E129](Protocols_Details.md#E129---83)|83|||||||||CYRF6936/NRF24L01|RF2500
[ESky](Protocols_Details.md#ESKY---16)|16|ESky|ET4|||||||NRF24L01|
[ESky150](Protocols_Details.md#ESKY150---35)|35|ESKY150||||||||NRF24L01|
[ESky150V2](Protocols_Details.md#ESKY150V2---69)|69|||||||||CC2500|NRF24L01
[ESky150V2](Protocols_Details.md#ESKY150V2---69)|69|ESky150V2||||||||CC2500|NRF51822
[Flysky](Protocols_Details.md#FLYSKY---1)|1|Flysky|V9x9|V6x6|V912|CX20||||A7105|
[Flysky AFHDS2A](Protocols_Details.md#FLYSKY-AFHDS2A---28)|28|PWM_IBUS|PPM_IBUS|PWM_SBUS|PPM_SBUS|||||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
[Flysky AFHDS2A](Protocols_Details.md#FLYSKY-AFHDS2A---28)|28|PWM_IBUS|PPM_IBUS|PWM_SBUS|PPM_SBUS|PWM_IBUS16|PPM_IBUS16|||A7105|
[Flysky AFHDS2A RX](Protocols_Details.md#FLYSKY-AFHDS2A-RX---56)|56|RX||||||||A7105|
[FQ777](Protocols_Details.md#FQ777---23)|23|FQ777||||||||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|
[FrskyX](Protocols_Details.md#FRSKYX---15)|15|CH_16|CH_8|EU_16|EU_8|Cloned|Cloned_8|||CC2500|
[FrskyX2](Protocols_Details.md#FRSKYX2---64)|64|CH_16|CH_8|EU_16|EU_8|Cloned|Cloned_8|||CC2500|
[Frsky_RX](Protocols_Details.md#FRSKY_RX---55)|55|RX|CloneTX|||||||CC2500|
[Futaba/SFHSS](Protocols_Details.md#Futaba---21)|21|SFHSS||||||||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|
[GD00X](Protocols_Details.md#GD00X---47)|47|GD_V1*|GD_V2*|||||||NRF24L01|XN297L
[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
[Height](Protocols_Details.md#HEIGHT---53)|53|5ch|8ch|||||||A7105|
[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|
[HoTT](Protocols_Details.md#HoTT---57)|57|Sync|No_Sync|||||||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
[J6Pro](Protocols_Details.md#J6Pro---22)|22|J6Pro||||||||CYRF6936|
[JJRC345](Protocols_Details.md#JJRC345---71)|71|JJRC345|SkyTmblr|||||||NRF24L01|XN297
[KF606](Protocols_Details.md#KF606---49)|49|KF606*||||||||NRF24L01|XN297
[KN](Protocols_Details.md#KN---9)|9|WLTOYS|FEILUN|||||||NRF24L01|
[Kyosho](Protocols_Details.md#Kyosho---73)|73|FHSS|Hype|||||||A7105|
[LOLI](Protocols_Details.md#LOLI---82)|82|||||||||NRF24L01|
[MJXq](Protocols_Details.md#MJXQ---18)|18|WLH08|X600|X800|H26D|E010*|H26WH|PHOENIX*||NRF24L01|XN297
[MT99xx](Protocols_Details.md#MT99XX---17)|17|MT|H7|YZ|LS|FY805||||NRF24L01|XN297
[NCC1701](Protocols_Details.md#NCC1701---44)|44|NCC1701||||||||NRF24L01|
[OMP](Protocols_Details.md#OMP---77)|77|||||||||CC2500&NRF24L01|XN297L
[OpenLRS](Protocols_Details.md#OpenLRS---27)|27|||||||||None|
[Pelikan](Protocols_Details.md#Pelikan---60)|60|||||||||A7105|
[Pelikan](Protocols_Details.md#Pelikan---60)|60|Pro|Lite|||||||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|
[Q90C](Protocols_Details.md#Q90C---72)|72|Q90C*||||||||NRF24L01|XN297
[RadioLink](Protocols_Details.md#RadioLink---74)|74|Surface|Air|DumboRC||||||CC2500|
[Realacc](Protocols_Details.md#Realacc---76)|76|R11||||||||NRF24L01|
[Redpine](Protocols_Details.md#Redpine---50)|50|FAST|SLOW|||||||NRF24L01|XN297
[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|
[Shenqi](Protocols_Details.md#Shenqi---19)|19|Shenqi||||||||NRF24L01|LT8900
[Skyartec](Protocols_Details.md#Skyartec---68)|68|Skyartec||||||||CC2500|CC2500
[SLT](Protocols_Details.md#SLT---11)|11|SLT_V1|SLT_V2|Q100|Q200|MR100||||NRF24L01|CC2500
[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|
[Traxxas](Protocols_Details.md#Traxxas---43)|43|6519 RX||||||||CYRF6936|
[V2x2](Protocols_Details.md#V2X2---5)|5|V2x2|JXD506|MR101||||||NRF24L01|
[V761](Protocols_Details.md#V761---48)|48|V761||||||||NRF24L01|XN297
[V911S](Protocols_Details.md#V911S---46)|46|V911S*|E119*|||||||NRF24L01|XN297
[WFly](Protocols_Details.md#WFLY---40)|40|WFLY||||||||CYRF6936|
[WFLY](Protocols_Details.md#WFLY---40)|40|WFR0x||||||||CYRF6936|
[WFLY2](Protocols_Details.md#WFLY2---79)|79|RF20x||||||||A7105|
[WK2x01](Protocols_Details.md#WK2X01---30)|30|WK2801|WK2401|W6_5_1|W6_6_1|W6_HEL|W6_HEL_I|||CYRF6936|
[XK](Protocols_Details.md#XK---62)|62|XK|X450|X420||||||NRF24L01|XN297
[XK](Protocols_Details.md#XK---62)|62|X450|X420|||||||NRF24L01|XN297
[YD717](Protocols_Details.md#YD717---8)|8|YD717|SKYWLKR|SYMAX4|XINXUN|NIHUI||||NRF24L01|
[ZSX](Protocols_Details.md#ZSX---52)|52|280||||||||NRF24L01|XN297
* "*" 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.
@@ -142,6 +148,19 @@ CFlie|38|CFlie||||||||NRF24L01|
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.
## BUGS - *41*
Models: MJX Bugs 3, 6 and 8
Telemetry enabled for RX & TX RSSI, Battery voltage good/bad
**RX_Num is used to give a number to a given model. You must use a different RX_Num per MJX Bugs. A maximum of 16 Bugs are supported.**
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|---
A|E|T|R|ARM|ANGLE|FLIP|PICTURE|VIDEO|LED
ANGLE: angle is +100%, acro is -100%
## FLYSKY - *1*
Extended limits supported
@@ -149,9 +168,15 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8
Note that the RX ouput will be AETR.
RX output will match the Flysky standard AETR independently of the input configuration AETR, RETA... unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
### Sub_protocol Flysky - *0*
Supports a variety of Flysky receivers and integrated boards.
Kyosho FHS MINI-Z also uses this protocol with this channel assignement:
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
Steering|Throttle|Lights|Steering travel|Others:not sure
### Sub_protocol V9X9 - *1*
CH5|CH6|CH7|CH8
@@ -178,29 +203,45 @@ CH5|CH6|CH7
Extended limits and failsafe supported
Telemetry enabled protocol:
- by defaut using FrSky Hub protocol (for example er9x): RX(A1), battery voltage FS-CVT01(A2) and RX&TX RSSI
- by defaut using FrSky Hub protocol (for example er9x): A1=RX voltage (set the ratio to 12.7 and adjust with offset), A2=battery voltage FS-CVT01 (set the ratio to 12.7 and adjust with offset) and RX&TX RSSI
- if using erskyTX and OpenTX: full telemetry information available
- 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).
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 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).
AFHDS2A_LQI_CH is a feature which is disabled by defaut in the _config.h file. When enabled, it makes LQI (Link Quality Indicator) available on one of the RX ouput channel (5-14).
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14
---|---|---|---|---|---|---|---|---|---|---|---|---|---
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14
Note that the RX ouput will be AETR whatever the input channel order is.
RX output will match the Flysky standard AETR independently of the input configuration AETR, RETA... unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
### Sub_protocol PWM_IBUS - *0*
### Sub_protocol PPM_IBUS - *1*
### Sub_protocol PWM_SBUS - *2*
### Sub_protocol PPM_SBUS - *3*
### Sub_protocol PWM_IBUS16 - *4*
3 additional channels. Need recent or updated RXs.
CH15|CH16|CH17
---|---|---
CH15|CH16|LQI
LQI: Link Quality Indicator
### Sub_protocol PPM_IBUS16 - *5*
3 additional channels. Need recent or updated RXs.
CH15|CH16|CH17
---|---|---
CH15|CH16|LQI
LQI: Link Quality Indicator
## FLYSKY AFHDS2A RX - *56*
The Flysky AFHDS2A receiver protocol enables master/slave trainning, separate access from 2 different radios to the same model,...
@@ -211,18 +252,25 @@ 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
## HEIGHT - *53*
Models using the old ARES TX (prior to Hitec RED): Tiger Moth, eRC Micro Stik
### Sub_protocol 5CH - *0*
Models from Height, Flyzone, Rage R/C, eRC and the old ARES (prior to Hitec RED).
CH1|CH2|CH3|CH4
---|---|---|---
A|E|T|R
CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A|E|T|R|Gear
### Sub_protocol 8CH - *1*
Models from Height and Rage R/C.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
A|E|T|R|Gear|Gyro|Flap|Light
## HUBSAN - *2*
Telemetry enabled for battery voltage and TX RSSI
Telemetry enabled for A1=battery voltage (set the ratio to 12.7 and adjust with offset) and TX RSSI
Option=vTX frequency (H107D) 5645 - 5900 MHz
@@ -253,31 +301,55 @@ H122D: FLIP
H123D: FMODES -> -100%=Sport mode 1,0%=Sport mode 2,+100%=Acro
## BUGS - *41*
Models: MJX Bugs 3, 6 and 8
## Kyosho - *73*
Telemetry enabled for RX & TX RSSI, Battery voltage good/bad
### Sub_protocol FHSS - *0*
Surface protocol called FHSS introduced in 2017. Transmitters: KT-531P, KT-431PT...
**RX_Num is used to give a number to a given model. You must use a different RX_Num per MJX Bugs. A maximum of 16 Bugs are supported.**
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14
---|---|---|---|---|---|---|---|---|----|----|----|----|----
STEERING|THROTTLE|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12|CH13|CH14
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|---
A|E|T|R|ARM|ANGLE|FLIP|PICTURE|VIDEO|LED
### Sub_protocol Hype - *1*
Transmitters: ST6DF, HK6S, Flightsport. Receivers: ST6DF, HK6DF.
ANGLE: angle is +100%, acro is -100%
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|CH5|CH6
RX output will match the Hype standard AETR independently of the input configuration AETR, RETA... unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
## 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.
RX output will match the Pelikan standard AETR independently of the input configuration AETR, RETA... unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
### Sub_protocol Pro - *0*
Models: TX: CADET PRO V4, RX: RX-602 V4
### Sub_protocol Lite - *1*
Models: TX: CADET 4 LITE
**Only 1 frequency hopping table**
## WFLY2 - *79*
Receivers: RF201S,RF206S,RF207S,RF209S
Extended limits supported
Failsafe is only supported by value per channel, it's not yet possible to set Hold or No pulse.
Telemetry enabled for A1=RX_Batt (Ratio 12.7), A2=Ext_Batt (Ratio 12.7), RX RSSI, TX RSSI, TX LQI (100=all telem packets received...0=no telem packets).
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|----
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
Option is used to select between WBUS=0 and PPM=1
***
# CC2500 RF Module
@@ -313,6 +385,33 @@ To bind V2 RXs you must follow the below procedure (original):
### Sub_protocol FD_V3 - *2*
FlyDream RXs like IS-4R and IS-4R0
## E016HV2 - *80*
Models: E016H v2
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 or bind won't even work.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|----
A|E|T|R|TAKE_OFF/LANDING|EMERGENCY|FLIP|CALIB|HEADLESS|RTH
TAKE_OFF/LANDING: this is a momentary switch to arm the motors or land the quad. This switch is not really needed as you can start the quad with throttle low then increase throttle until the motor arms, move throttle to mid-stick and then increase it quickly to lift off; To land just bring throttle all the way down, the quad will just stops when touching the ground.
EMERGENCY: Can be used along with the throttle cut switch: Throttle cut=set throttle at -100% and set EMERGENCY to 100%
## 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
## FRSKYV - *25*
Models: FrSky receivers V8R4, V8R7 and V8FR.
- FrSkyV = FrSky 1 way
@@ -411,6 +510,13 @@ 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.
16 channels.
### Sub_protocol Cloned_8 - *5*
Use the identifier learnt from another FrSky radio when binding with the FrSkyRX/CloneTX mode.
8 channels.
## FRSKYX2 - *64*
Same as [FrskyX](Protocols_Details.md#FRSKYX---15) but for D16 v2.1.0 FCC/LBT.
@@ -484,33 +590,73 @@ Basic telemetry using FrSky Hub on er9x, erskyTX, OpenTX and any radio with FrSk
MINIMA, MICRO and RED receivers. Also used by ARES planes.
## HoTT - *57*
Models: Graupner HoTT receivers (tested on GR-12L and GR-16L).
Models: Graupner HoTT receivers (tested on GR-12, GR-12L, GR-16, GR-32 and Vector).
Extended limits and failsafe supported
Extended limits, failsafe and LBT supported.
Full telemetry and full text config mode are available in OpenTX 2.3.8+.
Full telemetry and full text config mode are available starting from OpenTX 2.3.8N226.
**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.**
**RX_Num is used to give a number to 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" .
The RX and sensors/FC features configuration are done through 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
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 Sync - *0*
Recommended for best telemetry performance.
### Sub_protocol No_Sync - *1*
Telemetry compatibility mode when Sync does not work due to an old firmware on the RX.
You should definitively upgrade your receivers/sensors to the latest firmware versions: https://www.rcgroups.com/forums/showpost.php?p=44668015&postcount=18022
## Scanner - *54*
2.4GHz scanner accessible using the OpenTX 2.3 Spectrum Analyser tool.
## SFHSS - *21*
Models: Futaba RXs and XK models.
## RadioLink - *74*
Extended limits
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|CH13|CH14|CH15|CH16
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|FS_CH1|FS_CH2|FS_CH3|FS_CH4|FS_CH5|FS_CH6|FS_CH7|FS_CH8
FS=FailSafe
### Sub_protocol Surface - *0*
Surface protocol. TXs: RC4GS,RC6GS. Compatible RXs: R7FG(Std),R6FG,R6F,R8EF,R8FM,R8F,R4FGM,R4F
CH1=Steering, CH2=Throttle, CH8=Gyro gain
Telemetry: RX_RSSI (for the original value add -256), TX_RSSI, TX_QLY (0..100%), A1=RX_Batt (set the ratio to 12.7 and adjust with offset), A2=Batt (set the ratio to 25.5 and adjust with offset)
### Sub_protocol Air - *1*
Air protocol. TXs: T8FB,T8S. Compatible RXs: R8EF,R8FM,R8SM,R4FG,R4F
Telemetry: RX_RSSI (for the original value add -256), TX_RSSI, TX_QLY (0..100%)
### Sub_protocol DumboRC - *2*
Compatible RXs: X6/X6F/X6FG
## Futaba - *21*
Also called SFHSS depending on radio version.
### Sub_protocol SFHSS - *0*
Models: Futaba SFHSS RXs and XK models.
Extended limits and failsafe supported
RX output will match the Futaba standard servo throw, mid point and the channel order AETR independently of the input configuration AETR, RETA... unless if on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
Option for this protocol corresponds to fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
@@ -541,7 +687,7 @@ A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
RX output will match the Devo standard EATR independently of the input configuration AETR, RETA... unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
Basic telemetry is available if RX supports it: TX_RSSI, A1 and A2
Basic telemetry is available if RX supports it: TX_RSSI, A1 (set the ratio to 12.7) and A2 (set the ratio to 12.7)
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.
@@ -643,39 +789,38 @@ Extended limits supported
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|----|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.
- The "AUTO" sub protocol is recommended to automatically select the best settings for your DSM RX. If the RX doesn't bind or work properly after bind, don't hesitate to test different combinations of sub protocol and number of channels until you have something working.
- Servo refresh rate is 22ms unless you select 11ms available in OpenTX 2.3.10+
- 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 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.
- To allow SAFE to be ON with a switch assignment you must remove the bind plug after powering up the RX but before turning on the TX to bind. If you select Autodetect to bind, The MPM will choose DSMX 11ms and Channels 1-7 ( Change to 1-9 if you wish to assign switch above channel 7 ). Then in order to use the manuals diagram of both sticks "Down-Inside" to set a SAFE Select Switch Designation, you must have Throttle and Elevator channels set to Normal direction but the Aileron and Rudder set to Reverse direction. If setting up a new model with all channels set to Normal you can hold both sticks "Down- OUTSIDE" to assign the switch with 5x flips. Tested on a Mode2 radio.
Option=number of channels from 3 to 12. Option|0x80 enables Max Throw. Option|0x40 enables a servo refresh rate of 11ms.
### Sub_protocol DSM2_22 - *0*
DSM2, Resolution 1024, refresh rate 22ms
### Sub_protocol DSM2_11 - *1*
DSM2, Resolution 2048, refresh rate 11ms
### Sub_protocol DSMX_22 - *2*
DSMX, Resolution 2048, refresh rate 22ms
### Sub_protocol DSMX_11 - *3*
DSMX, Resolution 2048, refresh rate 11ms
### Sub_protocol DSM2_1F - *0*
DSM2, Resolution 1024, servo refresh rate can only be 22ms
### Sub_protocol DSM2_2F - *1*
DSM2, Resolution 2048, servo refresh rate can be 22 or 11ms. 11ms won't be available on all servo outputs when more than 7 channels are used.
### Sub_protocol DSMX_1F - *2*
DSMX, Resolution 2048, servo refresh rate can only be 22ms
### Sub_protocol DSMX_2F - *3*
DSMX, Resolution 2048, servo refresh rate can be 22 or 11ms. 11ms won't be available on all servo outputs when more than 7 channels are used.
### 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 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 erskyTX you can set "Invert COM1" accordinlgy.
"AUTO" is recommended to automatically select the best settings for your DSM RX.
## 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
- Bind should be done with all other modules off in the radio
- Available in OpenTX 2.3.3+, Trainer Mode Master/Multi
- Channels 1..4 are remapped to the module default channel order unless on OpenTX 2.3.3+ you use the "Disable channel mapping" feature on the GUI.
- Extended limits supported
@@ -684,6 +829,28 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
---|---|---|---|---|---|---|---|---|----|----|----
A|E|T|R|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
## E010R5 - *81*
Models: E010 R5 red boards, JJRC H36, H36F and H36S
**Only 3 IDs are available**. More IDs can be added if you send me your "unused" original TX.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|---
A|E|T|R|FLIP|LED|CALIB|HEADLESS|RTH|GLIDE
## E129 - *83*
Models: E129 and E130
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|Take off/Land|Emergency|Trim A|Trim E|Trim R
Trims can be done to some extent on the AETR channels directly but if you push them too far you won't be able to arm like explained below. In this case use the associated trim TrimA/E/R instead.
Take off with a none spring throttle is easier by putting both sticks down outwards (like on the original radio) in Mode 1/2, not sure about other modes.
Calib is the same as the original radio with both sticks down and to the left in Mode 1/2, not sure about other modes.
## J6Pro - *22*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11|CH12
@@ -738,7 +905,7 @@ Models: Eachine H8(C) mini, BayangToys X6/X7/X9, JJRC JJ850, Floureon H101 ...
Option=0 -> normal Bayang protocol
Option=1 -> enable telemetry with [Silverxxx firmware](https://github.com/silver13/H101-acro/tree/master). Value returned to the TX using FrSkyD Hub are RX RSSI, TX RSSI, A1=uncompensated battery voltage, A2=compensated battery voltage
Option=1 -> enable telemetry with [Silverxxx firmware](https://github.com/silver13/H101-acro/tree/master). Value returned to the TX using FrSkyD Hub are RX RSSI, TX RSSI, A1=uncompensated battery voltage (set the ratio to 5.0 and adjust with offset), A2=compensated battery voltage (set the ratio to 5.0 and adjust with offset)
Option=2 -> enable analog aux channels with [NFE Silverware firmware](https://github.com/NotFastEnuf/NFE_Silverware). Two otherwise static bytes in the protocol overridden to add two 'analog' (non-binary) auxiliary channels.
@@ -770,6 +937,9 @@ CH12|CH13
----|----
TAKE_OFF|EMG_STOP
### Sub_protocol QX100 - *5*
Model: REVELL QX100
## BAYANG RX - *59*
The Bayang receiver protocol enables master/slave trainning, separate access from 2 different radios to the same model,...
@@ -954,19 +1124,6 @@ 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
@@ -1099,11 +1256,18 @@ ARM|
### Sub_protocol FQ777_951 - *3*
## JJRC345 - *71*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---|---|---|----|----
A|E|T|R|FLIP|HEADLESS|RTH|LED|UNK1|UNK2|UNK3
### Sub_protocol JJRC345 - *0*
Model: JJRC345
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T|R|FLIP|HEADLESS|RTH
### Sub_protocol SkyTmblr - *1*
Model: DF-Models SkyTumbler
RTH not supported
## KF606 - *49*
Model: KF606
@@ -1116,6 +1280,31 @@ CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A||T||TRIM
## LOLI - *82*
LOLI3 receivers: https://github.com/wooddoor/Loli3
Failsafe supported. Once failsafe values for the 8 channels have been configured in Custom mode, wait for the RX to learn them, then set Failsafe to Receiver.
Telemetry supported: RX RSSI, TX LQI (percentage of received telemetry packets), A1 and A2 with a Ratio=25.5 and Offset=0.
Extended limits supported.
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
Features:
Config on | For channel | Switch | Servo | PPM | SBUS | PWM
----|-----|-------|----|------|---|------
CH9 | CH1 | -100% | 0% | +50% | - | +100%
CH10| CH2 | -100% | 0% | - | - | +100%
CH11| CH3 | -100% | 0% | - | - | -
CH12| CH4 | -100% | 0% | - | - | -
CH13| CH5 | -100% | 0% | - | +50% | -
CH14| CH6 | -100% | 0% | | - | -
CH15| CH7 | -100% | 0% | - | - | +100%
CH16| CH8 | -100% | 0% | - | - | -
## MJXQ - *18*
Autobind protocol
@@ -1200,6 +1389,30 @@ CH1|CH2|CH3|CH4|CH5
---|---|---|---|---
A|E|T|R|Warp
## OMP - *77*
Model: OMPHOBBY M1 & M2 Helis, T720 RC Glider
This protocol requires both a NRF24L01 and CC2500 RF components to operate.
Telemetry supported:
- A1 = battery voltage including "recovered" battery voltage from corrupted telemetry packets
- A2 = battery voltage from only good telemetry packets
- How to calculate accurately the OpenTX Ratio and Offset:
Set the Ratio to 12.7 and Offset to 0, plug 2 batteries with extreme voltage values, write down the values Batt1=12.5V & Telem1=12.2V, Batt2=7V & Telem2=6.6V then calculate/set Ratio=12.7*[(12.5-7)/(12.2-6.6)]=12.47 => 12.5 and Offset=12.5-12.2*[(12.5-7)/(12.2-6.6)]=0.517 => 0.5
- RX_RSSI = TQly = percentage of received telemetry packets (good and corrupted) from the model which has nothing to do with how well the RX is receiving the TX
Option for this protocol corresponds to the CC2500 fine frequency tuning. This value is different for each Module and **must** be accurate otherwise the link will not be stable.
Check the [Frequency Tuning page](/docs/Frequency_Tuning.md) to determine it.
CH1|CH2|CH3|CH4|CH5|CH6|CH7
---|---|---|---|---|---|---
A|E|T_PITCH|R|T_HOLD|IDLE|MODE
IDLE= 3 pos switch: -100% Normal, 0% Idle1, +100% Idle2
From the TX manual: MODE= 3 pos switch -100% Attitude, 0% Attitude(?), +100% 3D
For M2: MODE= 3 pos switch -100% 6G, 0% 3D, +100% 3D
## Potensic - *51*
Model: Potensic A20
@@ -1272,13 +1485,48 @@ Each toggle of VTX will increment the channel.
Gimbal is full range.
### Sub_protocol CX10D - *2* and Sub_protocol CX10WD - *3*
### Sub_protocol CX10D - *2*
Models CX10D and CX33W
CH5|CH6
---|---
ARM|FLIP
ARM is 3 positions: -100%=land / 0%=manual / +100%=take off
### Sub_protocol CX10WD - *3*
CH5|CH6
---|---
ARM|FLIP
ARM is 3 positions: -100%=land / 0%=manual / +100%=take off
## Q90C - *72*
This protocol is known to be problematic because it's using the xn297L emulation with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is an hardware issue with the accuracy of the components.
If the model does not respond well to inputs or hard to bind, you can try to switch the emulation from the default NRF24L01 RF component to the CC2500 by using an option value (freq tuning) different from 0. Option in this case is used for fine frequency tuning like any CC2500 protocols so check the [Frequency Tuning page](/docs/Frequency_Tuning.md).
CH1|CH2|CH3|CH4|CH5|CH6
---|---|---|---|---|---
A|E|T|R|FMODE|VTX+
FMODE: -100% angle, 0% horizon, +100% acro
VTX+: -100%->+100% channel+
## Realacc - *76*
Model: Realacc R11
Untested protocol, let me know if it works.
Autobind protocol
### Sub_protocol R11 - *0*
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10
---|---|---|---|---|---|---|---|---|----
A|E|T|R|FLIP|LIGHT|CALIB|HLESS|RTH|UNK
## Redpine - *50*
[Link to the forum](https://www.rcgroups.com/forums/showthread.php?3236043-Redpine-Lowest-latency-RC-protocol)
@@ -1299,6 +1547,10 @@ Throttle +100%=full forward,0%=stop,-100%=full backward.
## SLT - *11*
Autobind protocol
This protocol is known to be problematic because it's using the NRF24L01 with a transmission speed of 250kbps therefore it doesn't work very well with every modules, this is a hardware issue with the accuracy of the components. (some Jumper models seem to be using a NRF24L01 clone)
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*
CH1|CH2|CH3|CH4|CH5|CH6
@@ -1402,6 +1654,23 @@ CH10|CH11|CH12
---|---|---
Start/Stop|EMERGENCY|CAMERA_UP/DN
### Sub_protocol MR101 - *2*
TX: MR101, model: Dromida XL
**Only 1 ID** available. If you have a TX contact me on GitHub or RCGroups.
Autobind protocol
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9|CH10|CH11
---|---|---|---|---|---|---|---|---|----|----
A|E|T|R|FLIP||PICTURE|VIDEO||MOT_ON_OFF|AUTO
MOT_ON_OFF: momentary switch (you need to maintaint it for at least 1.5sec for on or off)
AUTO: Land=-100% Takeoff=+100%
The model can work with a none centered throttle.
## Tiger - *61*
Autobind protocol
@@ -1412,15 +1681,26 @@ 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
Calib: momentary switch, calib will happen one the channel goes from -100% to +100%
Flip: momentary switch: hold flip(+100%), indicate flip direction with Ele or Ail, release flip(-100%)
RTN_ACT and RTN: -100% disable, +100% enable
### Sub_protocol 3CH - *0*
Model: Volantex V761-1, V761-3 and may be others
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
-|E|T|R|GYRO|CALIB|FLIP|RTN_ACT|RTN
### Sub_protocol 4CH - *1*
Model: Volantex V761-4+ and Eachine P51-D, F4U, F22 and may be others
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8|CH9
---|---|---|---|---|---|---|---|---
A|E|T|R|GYRO|CALIB|FLIP|RTN_ACT|RTN
## 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.
@@ -1481,31 +1761,54 @@ CH1|CH2|CH3|CH4|CH5
# SX1276 RF Module
## FRSKYR9 - *65*
Extended limits supported
**R9 RXs must be flashed with latest ACCST.**
Extended limits and failsafe supported.
Full telemetry supported.
Notes:
- The choices of CH1-8/CH9-16 and Telem ON/OFF is available in OpenTX 2.3.10 nightlies. The default is CH1-8 Telem ON.
- Telemetry from TX to RX is available in OpenTX 2.3.10 nightlies.
- Power adjustment is not supported on the T18.
### Sub_protocol R9_915 - *0*
915MHz, 16 channels
FLEX 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
FLEX 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
FLEX 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
FLEX 868MHz, 8 channels
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
### Sub_protocol R9_FCC - *4*
FCC, 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_FCC_8CH - *6*
FCC, 8 channels
CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
---|---|---|---|---|---|---|---
@@ -1515,4 +1818,3 @@ CH1|CH2|CH3|CH4|CH5|CH6|CH7|CH8
## 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,10 +19,11 @@ 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?branch=master)](https://travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module)
Multiprotocol downloads: <img src=https://img.shields.io/github/downloads/pascallanger/DIY-Multiprotocol-TX-Module/total.svg>
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)
Current Multiprotocol code check status: [<img src=https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/workflows/CI/badge.svg>](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/actions). Download the latest **test** build [here](https://downloads.multi-module.org/latest-test/).
Current Multiprotocol boards check status: [![Travis Build Status for Multi Boards](https://api.travis-ci.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards.svg?branch=master)](https://travis-ci.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards)
## Quicklinks
* [Download latest releases of the firmware](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/releases) and [instructions to upload .hex files](docs/Advanced_Manually_Setting_ATmega328_Fuses.md)

210
_travis.yml Normal file
View File

@@ -0,0 +1,210 @@
os: linux
dist: bionic
language: c
env:
jobs:
- BOARD="multi4in1:avr:multiatmega328p:bootloader=none"
- BOARD="multi4in1:avr:multiatmega328p:bootloader=optiboot"
- BOARD="multi4in1:avr:multixmega32d4"
- BOARD="multi4in1:STM32F1:multi5in1t18int"
- BOARD="multi4in1:STM32F1:multistm32f103cb:debug_option=none"
- BOARD="multi4in1:STM32F1:multistm32f103cb:debug_option=native"
- BOARD="multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi"
- BOARD="multi4in1:STM32F1:multistm32f103c8:debug_option=none"
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}
# 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-cli compile -b $BOARD Multiprotocol/Multiprotocol.ino --build-path ${TRAVIS_BUILD_DIR}/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; }
- export -f buildMulti
# Function to build the release files - dependent on board type.
# Release build scripts are located in buildroot/bin.
- if [[ "$BOARD" == "multi4in1:avr:multixmega32d4" ]]; then
buildReleaseFiles(){
build_release_orx;
};
elif [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=none" ]]; then
buildReleaseFiles(){
build_release_avr_noboot;
};
elif [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=optiboot" ]]; then
buildReleaseFiles(){
build_release_avr_optiboot;
};
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=none" ]]; then
buildReleaseFiles(){
build_release_stm32f1_no_debug;
};
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=native" ]]; then
buildReleaseFiles(){
build_release_stm32f1_native_debug;
};
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi" ]]; then
buildReleaseFiles(){
build_release_stm32f1_serial_debug;
};
elif [[ "$BOARD" == "multi4in1:STM32F1:multi5in1t18int" ]]; then
buildReleaseFiles(){
build_release_stm32f1_t18int;
};
else
buildReleaseFiles() { printf "No release files for this board."; };
fi
install:
# Install Arduino CLI
- mkdir ~/arduino-cli
- curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=~/arduino-cli sh -s 0.13.0;
- export PATH=$PATH:$HOME/arduino-cli
# Update the board url and package index
- arduino-cli core update-index --additional-urls https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/master/package_multi_4in1_board_index.json
# Install the STM32 board if needed
- if [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
arduino-cli core install multi4in1:STM32F1 --additional-urls https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/master/package_multi_4in1_board_index.json;
fi
# Install the AVR board if needed
- if [[ "$BOARD" =~ "multi4in1:avr:" ]]; then
arduino-cli core install arduino:avr;
arduino-cli core install multi4in1:avr --additional-urls https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/master/package_multi_4in1_board_index.json;
fi
before_script:
# Export all the variables
- set -a
# 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)
- CYRF6936_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_CYRF6936_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
- NRF24L01_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_NRF24L01_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
- SX1276_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_SX1276_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
# Get the full set of protocols for each board
- if [[ "$BOARD" =~ "multi4in1:avr:multixmega32d4" ]]; then
ALL_PROTOCOLS=$(echo $CYRF6936_PROTOCOLS);
elif [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:" ]]; then
ALL_PROTOCOLS=$(echo $A7105_PROTOCOLS $CC2500_PROTOCOLS $CYRF6936_PROTOCOLS $NRF24L01_PROTOCOLS);
elif [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
ALL_PROTOCOLS=$(echo $A7105_PROTOCOLS $CC2500_PROTOCOLS $CYRF6936_PROTOCOLS $NRF24L01_PROTOCOLS $SX1276_PROTOCOLS);
fi
- echo $ALL_PROTOCOLS
# Declare all the installed modules
- if [[ "$BOARD" =~ "multi4in1:avr:multixmega32d4" ]]; then
ALL_RFMODULES=$(echo CYRF6936_INSTALLED);
elif [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:" ]]; then
ALL_RFMODULES=$(echo A7105_INSTALLED CYRF6936_INSTALLED CC2500_INSTALLED NRF24L01_INSTALLED);
elif [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
ALL_RFMODULES=$(echo A7105_INSTALLED CYRF6936_INSTALLED CC2500_INSTALLED NRF24L01_INSTALLED SX1276_INSTALLED);
fi
- echo $ALL_RFMODULES
# Disable CHECK_FOR_BOOTLOADER when not needed
- if [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=none" ]]; then
opt_disable CHECK_FOR_BOOTLOADER;
fi
# Trim the enabled protocols down for the STM32F103CB board with debugging
- if [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi" ]] || [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb: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 STM32F103C8 board
- if [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c8:debug_option=none" ]]; 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 default configuration - all protocols are enabled for STM32; a subset of protocols for Atmega or STM32 debugging
- buildDefault
# Serial only
- buildSerialOnly
# PPM only
- buildPPMOnly
# Re-enable PPM and serial
- opt_enable ENABLE_SERIAL
- opt_enable ENABLE_PPM
# Build for each RF module individually
- buildEachRFModule
# Restore the default configuration
- cp ./_Config.h.bak Multiprotocol/_Config.h
# 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
token:
secure: KGXaoqvd8rbZ3AZtL9Rrn1JYiocGsPaihRUyR8gM8vTfvH9WYAE1+h6SzROQOuJSwr89MvTo3SBOTlM/0PDBnEGLec9Irt7cwO0xf9xM2vPuUG8DYcUzmJJzME9dkn/7qHof1JGgRpp1duUAN1triE9NxhKxL1hbs+tUUbDPAejxwoFNfnta/T4PfD6xmkZNJbneIfYFuFgyLpwwFhuUy9JP7s1AFOiT+fCHxPaZrPn5GsXqAi95Cb7Q3w1iVSt3BmrGxL2j3CeNpWzFY1RrMdc8ay+ppOhSPEIl2vyM7VeLRRBL3EVeFWkiS4ywevqw70wOivTczluv3OeuIJAe5o2UU+w5+59c7+i44Nih23PDAZBhAG5JkLUYUN0XUJpXJ5ZlZsb8IS8sI1txlZa5tNVoXO9+soGEY4rKSpZaPptuENm792CzzAjcaUI9pOFJ/0CBoSCbu5MpM/plkJCMd8fY27EE8cNYvolMuRATNlXs7h9mURGR69pmcR1jFShH+A7Kyp1S1sH19sGCEU16rt2aAtf2FadFg/gKACC2y9rB3wBb4Qnapu2AwNRlTYNuU1+G+kb2FXRwMl04q+38S+cIBHH9NHfdftp9MRPf8Ekatojs92be/Ux21S+hcA7sx/DV22Dl45V6l4mXzR7U4x1nQcdn1SGuy5I4lL6IYCk=
skip_cleanup: true
file_glob: true
file: binaries/*
on:
tags: true

View File

@@ -0,0 +1,103 @@
#!/usr/bin/env bash
getMultiVersion() {
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
}
getAllRFModules() {
if [[ "$BOARD" =~ "multi4in1:avr:multixmega32d4" ]]; then
ALL_RFMODULES=$(echo CYRF6936_INSTALLED);
elif [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:" ]]; then
ALL_RFMODULES=$(echo A7105_INSTALLED CYRF6936_INSTALLED CC2500_INSTALLED NRF24L01_INSTALLED);
elif [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
ALL_RFMODULES=$(echo A7105_INSTALLED CYRF6936_INSTALLED CC2500_INSTALLED NRF24L01_INSTALLED SX1276_INSTALLED);
fi
}
getAllProtocols() {
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)
CYRF6936_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_CYRF6936_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
NRF24L01_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_NRF24L01_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
SX1276_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_SX1276_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
if [[ "$BOARD" =~ "multi4in1:avr:multixmega32d4" ]]; then
ALL_PROTOCOLS=$(echo $CYRF6936_PROTOCOLS);
elif [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:" ]]; then
ALL_PROTOCOLS=$(echo $A7105_PROTOCOLS $CC2500_PROTOCOLS $CYRF6936_PROTOCOLS $NRF24L01_PROTOCOLS);
elif [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
ALL_PROTOCOLS=$(echo $A7105_PROTOCOLS $CC2500_PROTOCOLS $CYRF6936_PROTOCOLS $NRF24L01_PROTOCOLS $SX1276_PROTOCOLS);
fi
}
buildMulti() {
echo ::group::_Config.h
git diff Multiprotocol/_Config.h
echo ::endgroup::
BUILDCMD="arduino-cli compile -b $BOARD ${GITHUB_WORKSPACE}/Multiprotocol/Multiprotocol.ino --build-path ${GITHUB_WORKSPACE}/build/";
echo $BUILDCMD;
$BUILDCMD
return $?
}
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\n";
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\n";
buildRFModule $RFMODULE;
if [ $? -ne 0 ]; then exitcodesum=$((exitcodesum + 1)); fi;
done;
return $exitcodesum;
}
buildReleaseFiles(){
if [[ "$BOARD" == "multi4in1:avr:multixmega32d4" ]]; then
build_release_orx;
elif [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=none" ]]; then
build_release_avr_noboot;
elif [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=optiboot" ]]; then
build_release_avr_optiboot;
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=none" ]]; then
build_release_stm32f1_no_debug;
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=native" ]]; then
build_release_stm32f1_native_debug;
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi" ]]; then
build_release_stm32f1_serial_debug;
elif [[ "$BOARD" == "multi4in1:STM32F1:multi5in1t18int" ]]; then
build_release_stm32f1_t18int;
else
printf "No release files for this board.";
fi
}

View File

@@ -0,0 +1,29 @@
#!/usr/bin/env bash
source ./buildroot/bin/buildFunctions;
exitcode=0;
printf "\e[33;1mBuilding multi-avr-usbasp-aetr-A7105-inv-v$MULTI_VERSION.bin\e[0m\n";
opt_disable CHECK_FOR_BOOTLOADER;
opt_disable $ALL_PROTOCOLS;
opt_enable $A7105_PROTOCOLS;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-usbasp-aetr-A7105-inv-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-avr-usbasp-aetr-CC2500-inv-v$MULTI_VERSION.bin\e[0m\n";
opt_disable $ALL_PROTOCOLS;
opt_enable $CC2500_PROTOCOLS;
opt_disable HITEC_CC2500_INO REDPINE_CC2500_INO OMP_CC2500_INO SKYARTEC_CC2500_INO SCANNER_CC2500_INO;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-usbasp-aetr-CC2500-inv-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-avr-usbasp-aetr-CYRF6936-inv-v$MULTI_VERSION.bin\e[0m\n";
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;
exit $exitcode;

View File

@@ -0,0 +1,29 @@
#!/usr/bin/env bash
source ./buildroot/bin/buildFunctions;
exitcode=0;
printf "\e[33;1mBuilding multi-avr-txflash-aetr-A7105-inv-v$MULTI_VERSION.bin\e[0m\n";
opt_enable CHECK_FOR_BOOTLOADER;
opt_disable $ALL_PROTOCOLS;
opt_enable $A7105_PROTOCOLS;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-txflash-aetr-A7105-inv-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-avr-txflash-aetr-CC2500-inv-v$MULTI_VERSION.bin\e[0m\n";
opt_disable $ALL_PROTOCOLS;
opt_enable $CC2500_PROTOCOLS;
opt_disable HITEC_CC2500_INO REDPINE_CC2500_INO OMP_CC2500_INO SKYARTEC_CC2500_INO SCANNER_CC2500_INO;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-txflash-aetr-CC2500-inv-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-avr-txflash-aetr-CYRF6936-inv-v$MULTI_VERSION.bin\e[0m\n";
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;
exit $exitcode;

View File

@@ -0,0 +1,26 @@
#!/usr/bin/env bash
source ./buildroot/bin/buildFunctions;
exitcode=0;
printf "\e[33;1mBuilding multi-orangerx-aetr-green-inv-v$MULTI_VERSION.bin\e[0m\n";
opt_enable $ALL_PROTOCOLS;
opt_disable ORANGE_TX_BLUE;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-orangerx-aetr-green-inv-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-orangerx-aetr-blue-inv-v$MULTI_VERSION.bin\e[0m\n";
opt_enable ORANGE_TX_BLUE;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-orangerx-aetr-blue-inv-v$MULTI_VERSION.bin;
printf "\e[33;1mPackaging ancilliary files for v$MULTI_VERSION\e[0m\n";
cp Multiprotocol/Multi.txt ./binaries/Multi.txt;
mkdir -p SCRIPTS/TOOLS;
cp Lua_scripts/*.lua SCRIPTS/TOOLS/;
cp Lua_scripts/*.txt SCRIPTS/TOOLS/;
zip -q ./binaries/MultiLuaScripts.zip SCRIPTS/TOOLS/*;
exit $exitcode;

View File

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

View File

@@ -0,0 +1,72 @@
#!/usr/bin/env bash
source ./buildroot/bin/buildFunctions;
exitcode=0;
printf "\e[33;1mBuilding multi-stm-serial-aetr-v$MULTI_VERSION.bin\e[0m\n";
opt_disable ENABLE_PPM;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-serial-aetr-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-serial-taer-v$MULTI_VERSION.bin\e[0m\n";
opt_replace AETR TAER;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-serial-taer-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-serial-reta-v$MULTI_VERSION.bin\e[0m\n";
opt_replace TAER RETA;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-serial-reta-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-cc2500-aetr-v$MULTI_VERSION.bin\e[0m\n";
opt_replace RETA AETR;
opt_disable A7105_INSTALLED;
opt_disable CYRF6936_INSTALLED;
opt_disable NRF24L01_INSTALLED;
opt_disable INVERT_TELEMETRY;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-cc2500-aetr-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-cc2500-taer-v$MULTI_VERSION.bin\e[0m\n";
opt_replace AETR TAER;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-cc2500-taer-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-cc2500-reta-v$MULTI_VERSION.bin\e[0m\n";
opt_replace TAER RETA;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-cc2500-reta-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-ppm-aetr-v$MULTI_VERSION.bin\e[0m\n";
opt_enable A7105_INSTALLED;
opt_enable CYRF6936_INSTALLED;
opt_enable NRF24L01_INSTALLED;
opt_enable ENABLE_PPM;
opt_disable ENABLE_SERIAL;
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-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-ppm-taer-v$MULTI_VERSION.bin\e[0m\n";
opt_replace AETR TAER;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-ppm-taer-v$MULTI_VERSION.bin;
printf "\e[33;1mBuilding multi-stm-ppm-reta-v$MULTI_VERSION.bin\e[0m\n";
opt_replace TAER RETA;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-ppm-reta-v$MULTI_VERSION.bin;
exit $exitcode;

View File

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

View File

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

View File

@@ -6,11 +6,12 @@ To get the XN297L dump feature working on your module you must know:
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. Select the protocol XN297DP, 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.
* sub_protocol or type or the second number after "Custom 63" is used to set the transmission speed: 0=250Kbps, 1=1Mbps, 2=2Mbps and 3=Auto.
* Auto is the recommended mode since it gives many information like channels, timing, order as well as finding bytes meaning
* 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
TBC

View File

@@ -23,7 +23,8 @@ Original FrSky, Futaba, Corona Hitec and HoTT receivers have been frequency-tune
The procedure can be performed in serial or PPM mode, but is easier with in serial mode where the effect of the change can be seen in real-time.
### Preparation
The radio needs to be bound with the receiver.
The radio needs to be bound with the receiver in order to fine tune. If the receiver does not bind, use *coarse* tuning (varying the **Freq** value in steps of +/- 40) until the receiver binds.
1. Configure the radio with the appropriate protocol
1. Set the **Freq** value to 0
1. Put the receiver into **Binding** mode
@@ -48,16 +49,16 @@ Connection is lost at -73 and +35; the median is -19:
`(-73 + 35) / 2 = -19`
### Finally
Once the **Freq** value is known it should be applied to all other models which use this protocol and, if they were previously bound, the receivers must be re-bound.
For convenience this can be applied once for all per protocol using the FORCE commands described below in `_Config.h` (or `_MyConfig.h`) configuration file.
Usually all RXs using the same protocol&sub_protocol can use the same **Freq** value but it can't harm to do all of them.
If you change the Freq value it is best to rebind the receiver(s).
#### Forced tuning values
Once known-good tuning values have been determined, they can be stored in the configuration file to be automatically applied to all models which use the given protocol.
For convenience the freq value can be applied once for all per protocol using the FORCE commands described below in `_Config.h` (or `_MyConfig.h`) configuration file.
These settings can also be used to force different tuning values for different multiprotocol modules, removing the need to alter the tuning option on the transmitter when swapping between modules. (Assuming that the modules also share a common hardware ID.)
**Note:** If a forced tuning value is set in the configuration, it cannot be overriden by the protocol's **Freq** option on the radio for any model.
Once known-good tuning values have been determined, they can be stored in the configuration file to be automatically applied to all models which use the given protocol.
**Note:** If a forced tuning value is set in the configuration, the protocol's **Freq** option on the radio GUI will be ignored whatever the value is set to.
```
/*******************************/

View File

@@ -64,8 +64,7 @@ The telemetry mod for these transmitters has evolved. The original and popular
A good tutorial to follow is Oscar Liang's [here](http://blog.oscarliang.net/turnigy-9x-advance-mod/) but when you get to wiring up the Tx Module bay pins, you only need to perform the steps relevant for Pin 5.
You can see Midelic's original instructions [here](http://www.rcgroups.com/forums/showpost.php?p=28359305&postcount=2)
If the telemetry output was wired incorrectly, the Multiprotocol module will not continue past the bootloader (some rapid flashes from the red LED, and then no light).
## Other Notes:

View File

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