Compare commits

...

245 Commits

Author SHA1 Message Date
Pascal Langer
03d0adbd74 CCPM: added comment to disable the telemetry after setup 2021-03-14 19:00:45 +01:00
Pascal Langer
905ee4b1ed Fix module boot issue? 2021-03-14 11:15:24 +01:00
Pascal Langer
dbc33951a4 Fix for module boot issue? 2021-03-13 18:18:07 +01:00
Pascal Langer
732e66cab2 HoTT: fix Text config in Sync mode 2021-03-13 11:01:51 +01:00
pascallanger
0dab92552a Update CPPM_HW_Mod.md 2021-03-08 17:47:28 +01:00
pascallanger
047952537a Update CPPM_HW_Mod.md 2021-03-08 13:39:59 +01:00
pascallanger
d4bf1fb36e Update CPPM_HW_Mod.md 2021-03-08 13:36:43 +01:00
pascallanger
ff817cd098 Update Protocols_Details.md 2021-03-08 11:36:59 +01:00
pascallanger
04ea44ed4b Update CPPM_HW_Mod.md 2021-03-08 11:19:10 +01:00
pascallanger
e23c8e2216 Add files via upload 2021-03-08 10:15:47 +01:00
pascallanger
afb4802a2c Update CPPM_HW_Mod.md 2021-03-07 17:34:16 +01:00
pascallanger
3a5d341514 CPPM hardware mod initial page 2021-03-07 17:31:45 +01:00
pascallanger
b6bcab1604 CPPM hardware mod images 2021-03-07 17:24:15 +01:00
Pascal Langer
0a998d2dc5 Enable CPPM by default 2021-03-07 11:12:49 +01:00
Pascal Langer
7927bc601e CPPM for RX protocols 2021-03-06 18:51:53 +01:00
Pascal Langer
f8cc913898 Update Multiprotocol.ino 2021-03-06 12:00:05 +01:00
Pascal Langer
a5428bc180 Removed SBUS trainer option 2021-03-06 11:33:32 +01:00
Pascal Langer
c0285f81f0 JOYSWAY: fix? 2021-03-05 19:57:33 +01:00
Pascal Langer
600049898a SBUS/CPPM: fixed switching from CPPM to SBUS 2021-03-04 21:28:06 +01:00
Pascal Langer
0e1db8f06b SBUS/CPPM: fixed switching from SBUS to CPPM
There is still an issue from CPPM to SBUS...
2021-03-04 19:02:45 +01:00
Pascal Langer
ec83f1e5a3 Disable SBUS serial when switching to CPPM 2021-03-04 15:23:23 +01:00
Pascal Langer
f8f7769d9c Update DSM subprotocols naming 2021-03-04 10:08:52 +01:00
Pascal Langer
4dacac29c6 SBUS/CPPM: restore normal telemetry on student link lost
Once the setup is done check the "Disable telemetry" box to make sure that there is no interference between the internal module and Multi telemetry.
2021-03-04 09:52:54 +01:00
Pascal Langer
593f3b87f1 SBUS/CPPM: fixed telemetry_link 2021-03-04 09:11:20 +01:00
Pascal Langer
bb70116df0 SBUS and CPPM output 2021-03-03 10:07:19 +01:00
Pascal Langer
d7c24d62ed Update Devo_cyrf6936.ino 2021-03-02 18:32:02 +01:00
Pascal Langer
07df1a8959 DEVO telemetry: reduce the voltage and RSSI refresh frequency 2021-03-02 17:37:28 +01:00
Pascal Langer
ca9e2870ab DEVO: temp telem fix 2021-03-02 16:30:14 +01:00
Pascal Langer
99ca6fa36c DEVO: fix temp telemetry 2021-03-02 16:26:30 +01:00
Pascal Langer
3d82560f71 Update Protocols_Details.md 2021-03-02 16:20:05 +01:00
Pascal Langer
44d362aeb4 DEVO: improve telemetry 2021-03-02 16:14:14 +01:00
Pascal Langer
3d4ed5ad11 SFHSS: Timing debug 2021-03-02 12:01:23 +01:00
Pascal Langer
ca3c2bbdc8 Update Protocols_Details.md 2021-03-02 10:42:25 +01:00
Pascal Langer
90c226c748 LOLI lua script 2021-03-02 10:39:11 +01:00
Pascal Langer
b757283f41 JOYSWAY: new protocol UNTESTED 2021-03-02 10:00:33 +01:00
Pascal Langer
b3132c7bf1 Devo: added telemetry voltage 3 2021-03-02 09:32:59 +01:00
Pascal Langer
9ba56f040a Update Futaba_cc2500.ino 2021-03-01 16:31:11 +01:00
Pascal Langer
ac71b4d981 Update Devo_cyrf6936.ino 2021-03-01 14:02:39 +01:00
Pascal Langer
6bb2c06cf6 Fix compilation 2021-03-01 13:53:39 +01:00
Pascal Langer
2ad3c727fd Few changes... 2021-03-01 13:48:23 +01:00
Pascal Langer
d36af55b84 DEVO: full telemetry 2021-03-01 13:47:44 +01:00
Pascal Langer
f19bb05c7a WFLY: Failsafe values 2021-02-24 16:29:24 +01:00
Pascal Langer
08ea8818fb E010R5: 5th ID 2021-02-24 10:26:58 +01:00
Pascal Langer
59c541d013 MT99xx missing break 2021-02-23 09:52:46 +01:00
Ben Lye
37e2b5f41c Merge pull request #532 from benlye/new-builds
5-in-1 builds for DIY and T-Lite
2021-02-21 19:16:24 +00:00
Ben Lye
614a330cf2 5-in-1 builds for DIY and T-Lite 2021-02-21 18:58:02 +00:00
Pascal Langer
9106548859 T18 default build 2021-02-21 18:56:48 +01:00
Pascal Langer
2f07e79e50 T18 build by default 2021-02-21 18:35:24 +01:00
Pascal Langer
2233f6f862 SX1276: RF power adjustment for DIY & Jumper T-Lite 2021-02-21 16:05:25 +01:00
Pascal Langer
ae842f0bdc MT99XX Dragon telem prep 2021-02-17 10:26:38 +01:00
Ben Lye
4b36656246 Merge pull request #529 from benlye/build-fix
Update MT99xx_nrf24l01.ino
2021-02-16 19:39:55 +00:00
Ben Lye
ea282489f9 Update MT99xx_nrf24l01.ino 2021-02-16 19:34:01 +00:00
Ben Lye
6f2d9430d0 Merge pull request #528 from benlye/build-fix
Disable CCNRF protocols when needed
2021-02-16 18:40:58 +00:00
Pascal Langer
bccd9dc0d9 Fix XK protocol with latest change 2021-02-16 19:38:34 +01:00
Ben Lye
af919fb940 Fix CCNRF_PROTOCOLS 2021-02-16 18:31:40 +00:00
Ben Lye
7dab0de3c5 Update main.yml 2021-02-16 18:26:14 +00:00
Pascal Langer
2c0525421a Update Protocols_Details.md 2021-02-16 19:08:57 +01:00
Pascal Langer
0844ec2efd Add more protocols which can run with the CC2500
Use CC2500 only when emulating NRF250K/XN297_250K
2021-02-16 19:06:23 +01:00
Pascal Langer
49c3af12f9 AFHDS2A: fix issue with fs-x6b 2021-02-14 20:51:15 +01:00
Pascal Langer
96d335f458 Hide scanner from the available protocols 2021-02-13 20:39:00 +01:00
Pascal Langer
eae412fe41 E010r5: 1 more ID 2021-02-13 09:26:03 +01:00
Pascal Langer
0270420531 XN297dump: increase polling 2021-02-12 19:05:39 +01:00
Pascal Langer
93bb117961 RF switch fix... 2021-02-12 16:29:36 +01:00
Pascal Langer
29d1fb00b1 More code optimization 2021-02-12 11:21:42 +01:00
Pascal Langer
5a49d99c4f Update _Config.h 2021-02-11 20:09:40 +01:00
Pascal Langer
d66bf1a5b3 NRF init changed to most likely default 2021-02-11 18:40:29 +01:00
Pascal Langer
b41dccef67 HONTAI: use the global CRC calculation routine 2021-02-11 10:54:55 +01:00
Pascal Langer
addf2c5143 MT99XX/Dragon: beginner and intermediate swapped... 2021-02-11 09:50:41 +01:00
Pascal Langer
ff829f1f7b M-Link telemetry forwarded to OpenTX 2021-02-10 12:31:37 +01:00
Pascal Langer
7ee72976c4 M-Link: added vario 2021-02-10 10:13:51 +01:00
Pascal Langer
dc18e8e5b2 MT99XX: new subproto Dragon 2021-02-10 09:59:30 +01:00
Pascal Langer
97de2aaf3d One file missing in the push... 2021-02-09 18:31:13 +01:00
Pascal Langer
3b8b2ef376 Protocol init function modified 2021-02-09 18:23:33 +01:00
Pascal Langer
d496f62719 Removed depreciated MULTI_STATUS 2021-02-08 09:36:47 +01:00
Pascal Langer
fc978f95ef Disabling AFHDS2A Hub telemetry to fit in flash... 2021-02-07 19:20:12 +01:00
Pascal Langer
596e8c9b55 Update MLINK_cyrf6936.ino 2021-02-07 18:57:59 +01:00
Pascal Langer
0cf58c2990 MLink: added voltage, current, rpm, temp sensors and lqi 2021-02-07 18:51:36 +01:00
Pascal Langer
6ba1c8b118 Update Protocols_Details.md 2021-02-06 10:36:14 +01:00
Pascal Langer
b949ac0fed Update Protocols_Details.md 2021-02-06 10:35:15 +01:00
Pascal Langer
510f892d2f MLink: use only odd channels like original 2021-02-06 10:23:10 +01:00
Pascal Langer
17750e774a M-Link Failsafe 2021-02-06 09:58:36 +01:00
Pascal Langer
be1591c489 Update Protocols_Details.md 2021-02-05 18:44:48 +01:00
Pascal Langer
3b22705166 Exclude MLink from T18 build to save Flash space 2021-02-05 17:21:07 +01:00
Ben Lye
c05c0a5693 Merge pull request #518 from pascallanger/benlye-patch-1
Update main.yml
2021-02-05 16:15:36 +00:00
Ben Lye
d6fc6a3517 Update main.yml
Disable default configuration builds for T18 and 4in1.
2021-02-05 16:09:30 +00:00
Pascal Langer
7bfaee8b4f Update MLINK_cyrf6936.ino 2021-02-05 16:20:42 +01:00
Pascal Langer
89c00e8f17 Initial M-LINK release 2021-02-05 12:28:35 +01:00
pascallanger
447a58966f Update Compiling_STM32.md 2021-02-04 14:19:29 +01:00
pascallanger
74162aa972 Update Compiling_STM32.md 2021-02-04 14:15:57 +01:00
Pascal Langer
78a1e61f7a Update Telemetry.ino 2021-02-04 14:07:15 +01:00
Pascal Langer
a917227ddc Bayang: generic frsky hub function 2021-02-04 12:05:57 +01:00
Pascal Langer
c866d07743 Bayang: add PID to telemetry 2021-02-03 19:44:59 +01:00
Pascal Langer
43d969f962 FrSky RX: sub protocol to erase clone IDs 2021-02-03 16:57:14 +01:00
Pascal Langer
3973b42f81 MT99XX fix bind hopping 2021-02-02 17:55:40 +01:00
Pascal Langer
6046ad81db Update Protocols_Details.md 2021-02-02 14:42:22 +01:00
Pascal Langer
63a9874aea Futaba S-FHSS: another fs throw test 2021-02-02 12:06:54 +01:00
Pascal Langer
89420fe2d4 Futaba S-FHSS: failsafe throw test 2021-02-02 10:06:24 +01:00
Pascal Langer
9769354989 MT99XX: no autobind, 1 ID 2021-02-01 21:31:34 +01:00
Pascal Langer
580b996215 MT99XX: code optimization 2021-02-01 19:26:34 +01:00
Pascal Langer
8f5fb5083f MT99X sub A180: timing 2021-02-01 19:06:47 +01:00
Pascal Langer
821076ce95 MT99XX: code cleanup 2021-02-01 18:25:11 +01:00
Pascal Langer
0bfe1f8e63 MT99XX: new sub protocol A180 2021-02-01 15:21:39 +01:00
Pascal Langer
9c35f6f73c Futaba S-FHSS: Fist attempt to fix failsafe 2021-02-01 11:54:16 +01:00
Pascal Langer
983debe6ce WFLY2: Failsafe working for values, hold and no pulse 2021-01-29 15:41:47 +01:00
Pascal Langer
66704b5a13 AFHDS2A: common timing 2021-01-28 15:41:59 +01:00
Pascal Langer
f11da0c1de DSM: fix low power 2021-01-28 09:09:43 +01:00
Pascal Langer
7676398aab Fix OMP protocol 2021-01-25 11:33:30 +01:00
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
140 changed files with 9110 additions and 5120 deletions

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

@@ -0,0 +1,195 @@
# 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 "CCNRF_INO_PROTOCOLS=$(echo $CCNRF_INO_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: |
# Skip the default build for boards where it's too large now
if [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=none" ]] || [[ "$BOARD" == "multi4in1:STM32F1:multi5in1t18int" ]]; then
printf "Not testing default build for $BOARD.";
else
source ./buildroot/bin/buildFunctions;
buildMulti
fi
- 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,392 +0,0 @@
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: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}
# 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; }
# 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;
mkdir -p SCRIPTS/TOOLS;
cp Lua_scripts/*.lua SCRIPTS/TOOLS/;
cp Lua_scripts/*.txt SCRIPTS/TOOLS/;
zip ./binaries/MultiLuaScripts.zip SCRIPTS/TOOLS/*;
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;
opt_disable HITEC_CC2500_INO REDPINE_CC2500_INO SKYARTEC_CC2500_INO SCANNER_CC2500_INO;
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;
opt_disable HITEC_CC2500_INO REDPINE_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 "\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; };
elif [[ "$BOARD" == "multi4in1:STM32F1:multi5in1t18int" ]]; then
buildReleaseFiles(){
printf "\n\e[33;1mBuilding multi-t18int-opentx-aetr-noinv-v$MULTI_VERSION.bin\e[0m";
opt_disable INVERT_TELEMETRY;
exitcode=0;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-t18int-opentx-aetr-noinv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-t18int-opentx-taer-noinv-v$MULTI_VERSION.bin\e[0m";
opt_replace AETR TAER;
exitcode=0;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-t18int-opentx-taer-noinv-v$MULTI_VERSION.bin;
printf "\n\e[33;1mBuilding multi-t18int-opentx-reta-noinv-v$MULTI_VERSION.bin\e[0m";
opt_replace TAER RETA;
exitcode=0;
buildMulti;
exitcode=$((exitcode+$?));
mv build/Multiprotocol.ino.bin ./binaries/multi-t18int-opentx-reta-noinv-v$MULTI_VERSION.bin;
return $exitcode; };
else
buildReleaseFiles() { echo "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;
- 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:
# 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:STM32F1:" ]]; then
ALL_RFMODULES=$(echo A7105_INSTALLED CYRF6936_INSTALLED CC2500_INSTALLED NRF24L01_INSTALLED SX1276_INSTALLED);
else
ALL_RFMODULES=$(echo A7105_INSTALLED CYRF6936_INSTALLED CC2500_INSTALLED NRF24L01_INSTALLED);
fi
# 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
# 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

@@ -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",
@@ -549,6 +567,73 @@
"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

@@ -6,6 +6,7 @@
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
59,1,BayangRX,CPPM,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,6 +35,7 @@
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
70,1,DSM_RX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH
45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH
45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH
@@ -54,6 +56,7 @@
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
56,1,Flysky2A_RX,CPPM,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
@@ -79,6 +82,8 @@
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
55,2,FrSkyRX,EraseTX,0
55,3,FrSkyRX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
58,0,FX816,P38,1
20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
@@ -99,13 +104,14 @@
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
57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
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,Std,1,Flip,HLess,RTH
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
@@ -122,6 +128,8 @@
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
17,5,MT99XX,A180,0,3D_6G
17,6,MT99XX,Dragon,0,Mode,RTH
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
@@ -138,10 +146,11 @@
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,SFHSS,Std,0,CH5,CH6,CH7,CH8
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
@@ -174,3 +183,10 @@
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,Std,0,CH5,CH6,CH7,CH8,1SwSePpPw,2SwSePw,3SwSe,4SwSe,5SwSeSb,6SwSe,7SwSePw,8SwSe
83,0,E129,E129,1,TakLan,EmStop,TrimA,TrimE,TrimR
84,0,JOYSWAY,Std,0

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 }

View File

@@ -13,7 +13,7 @@ If you like this project and want to support further development please consider
</tr>
</table>
## MultiChannelsUpdater.lua
## MultiChannelsUpdater
Automatically name the channels based on the loaded Multi protocol and sub protocol including the module channel order convention.
@@ -21,7 +21,13 @@ Need OpenTX 2.3.9 or above. Located on the radio SD card under \SCRIPTS\TOOLS. T
[![MultiChannelsUpdater](https://img.youtube.com/vi/L58ayXuewyA/0.jpg)](https://www.youtube.com/watch?v=L58ayXuewyA)
## Graupner HoTT.ua
## 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.
@@ -32,3 +38,19 @@ Notes:
- 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
@@ -207,6 +210,16 @@ void A7105_AdjustLOBaseFreq(uint8_t cmd)
offset=(int16_t)FORCE_KYOSHO_TUNING;
#endif
break;
case PROTO_JOYSWAY:
#ifdef FORCE_JOYSWAY_TUNING
offset=(int16_t)FORCE_JOYSWAY_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
@@ -216,7 +229,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;
@@ -318,6 +331,28 @@ const uint8_t PROGMEM KYOSHO_A7105_regs[] = {
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
#ifdef JOYSWAY_A7105_INO
const uint8_t PROGMEM JOYSWAY_A7105_regs[] = {
0xff, 0x62, 0xff, 0x0F, 0x00, 0xff, 0xff ,0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0xF5, 0x00, 0x15, // 00 - 0f
0x9E, 0x4B, 0x00, 0x03, 0x56, 0x2B, 0x12, 0x4A, 0x02, 0x80, 0x80, 0x00, 0x0E, 0x91, 0x03, 0x0F, // 10 - 1f
0x16, 0x2A, 0x00, 0xff, 0xff, 0xff, 0x3A, 0x06, 0x1F, 0x47, 0x80, 0x01, 0x05, 0x45, 0x18, 0x00, // 20 - 2f
0x01, 0x0f // 30 - 31
};
#endif
#define ID_NORMAL 0x55201041
@@ -327,6 +362,20 @@ void A7105_Init(void)
uint8_t *A7105_Regs=0;
uint8_t vco_calibration0, vco_calibration1;
#ifdef JOYSWAY_A7105_INO
if(protocol==PROTO_JOYSWAY)
{
A7105_Regs=(uint8_t*)JOYSWAY_A7105_regs;
}
else
#endif
#ifdef WFLY2_A7105_INO
if(protocol==PROTO_WFLY2)
{
A7105_Regs=(uint8_t*)WFLY2_A7105_regs;
}
else
#endif
#ifdef HEIGHT_A7105_INO
if(protocol==PROTO_HEIGHT)
{
@@ -363,12 +412,17 @@ void A7105_Init(void)
A7105_Regs=(uint8_t*)FLYSKY_A7105_regs;
#endif
#if defined(AFHDS2A_A7105_INO) || defined(AFHDS2A_RX_A7105_INO)
if(protocol==PROTO_AFHDS2A)
if(protocol==PROTO_AFHDS2A || protocol==PROTO_AFHDS2A_RX)
A7105_Regs=(uint8_t*)AFHDS2A_A7105_regs;
#endif
#ifdef KYOSHO_A7105_INO
if(protocol==PROTO_KYOSHO)
A7105_Regs=(uint8_t*)KYOSHO_A7105_regs;
{
if(sub_protocol==KYOSHO_FHSS)
A7105_Regs=(uint8_t*)KYOSHO_A7105_regs;
else
A7105_Regs=(uint8_t*)KYOSHO_HYPE_A7105_regs;
}
#endif
}
@@ -387,12 +441,12 @@ void A7105_Init(void)
if(protocol==PROTO_HEIGHT && sub_protocol==HEIGHT_8CH)
if(i==0x03) val=0x0A;
#endif
if( val != 0xFF)
if( val != 0xff)
A7105_WriteReg(i, val);
}
A7105_Strobe(A7105_STANDBY);
if(protocol==PROTO_KYOSHO)
if(protocol==PROTO_KYOSHO && sub_protocol==KYOSHO_FHSS)
{//strange calibration...
//IF Filter Bank Calibration
A7105_WriteReg(A7105_02_CALC,0x0F);
@@ -431,7 +485,7 @@ void A7105_Init(void)
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
vco_calibration1 = A7105_ReadReg(A7105_25_VCO_SBCAL_I);
if(protocol==PROTO_BUGS)
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)
@@ -445,8 +499,12 @@ void A7105_Init(void)
vco_calibration1=0x02;
break;
case PROTO_PELIKAN:
case PROTO_KYOSHO: //sub_protocol Hype
vco_calibration1=0x0C;
break;
case PROTO_JOYSWAY:
vco_calibration1=0x09;
break;
default:
vco_calibration1=0x0A;
break;

View File

@@ -24,10 +24,11 @@
enum {
AFHDS2A_RX_BIND1,
AFHDS2A_RX_BIND2,
AFHDS2A_RX_BIND3,
AFHDS2A_RX_DATA
};
static void __attribute__((unused)) AFHDS2A_Rx_build_telemetry_packet()
static void __attribute__((unused)) AFHDS2A_RX_build_telemetry_packet()
{
uint32_t bits = 0;
uint8_t bitsavailable = 0;
@@ -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)&0x0F);
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)
@@ -55,13 +56,13 @@ static void __attribute__((unused)) AFHDS2A_Rx_build_telemetry_packet()
}
}
static uint8_t __attribute__((unused)) AFHDS2A_Rx_data_ready()
static uint8_t __attribute__((unused)) AFHDS2A_RX_data_ready()
{
// check if FECF+CRCF Ok
return !(A7105_ReadReg(A7105_00_MODE) & (1 << 5 | 1 << 6 | 1 << 0));
}
uint16_t initAFHDS2A_Rx()
void AFHDS2A_RX_init()
{
uint8_t i;
A7105_Init();
@@ -83,12 +84,11 @@ uint16_t initAFHDS2A_Rx()
hopping_frequency[i] = eeprom_read_byte((EE_ADDR)temp++);
phase = AFHDS2A_RX_DATA;
}
return 1000;
}
#define AFHDS2A_RX_WAIT_WRITE 0x80
uint16_t AFHDS2A_Rx_callback()
uint16_t AFHDS2A_RX_callback()
{
static int8_t read_retry;
int16_t temp;
@@ -104,24 +104,33 @@ uint16_t AFHDS2A_Rx_callback()
switch(phase) {
case AFHDS2A_RX_BIND1:
if(IS_BIND_DONE) return initAFHDS2A_Rx(); // Abort bind
if (AFHDS2A_Rx_data_ready()) {
if(IS_BIND_DONE)
{
AFHDS2A_RX_init(); // Abort bind
break;
}
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
if(IS_BIND_DONE)
{
AFHDS2A_RX_init(); // Abort bind
break;
}
// got 2nd bind packet from tx ?
if (AFHDS2A_Rx_data_ready()) {
if (AFHDS2A_RX_data_ready()) {
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
if ((packet[0] == 0xBC && packet[9] == 0x02 && packet[10] == 0x00) &&
(memcmp(rx_id, &packet[1], 4) == 0) &&
@@ -132,44 +141,58 @@ 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;
AFHDS2A_RX_init(); // Restart protocol
break;
}
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_SetTxRxMode(RX_EN);
A7105_Strobe(A7105_RX);
case AFHDS2A_RX_BIND3 | AFHDS2A_RX_WAIT_WRITE:
phase &= ~AFHDS2A_RX_WAIT_WRITE;
return 10000;
case AFHDS2A_RX_DATA:
if (AFHDS2A_Rx_data_ready()) {
if (AFHDS2A_RX_data_ready()) {
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
if (memcmp(&packet[1], rx_id, 4) == 0 && memcmp(&packet[5], rx_tx_addr, 4) == 0) {
if (packet[0] == 0x58 && packet[37] == 0x00 && telemetry_link == 0) { // standard packet, send channels to TX
if (packet[0] == 0x58 && packet[37] == 0x00 && (telemetry_link&0x7F) == 0) { // standard packet, send channels to TX
int rssi = min(A7105_ReadReg(A7105_1D_RSSI_THOLD),160);
RX_RSSI = map16b(rssi, 160, 8, 0, 128);
AFHDS2A_Rx_build_telemetry_packet();
AFHDS2A_RX_build_telemetry_packet();
telemetry_link = 1;
#ifdef SEND_CPPM
if(sub_protocol>0)
telemetry_link |= 0x80; // Disable telemetry output
#endif
}
rx_data_started = true;
read_retry = 10; // hop to next channel

View File

@@ -270,11 +270,18 @@ static void AFHDS2A_build_packet(uint8_t type)
}
#define AFHDS2A_WAIT_WRITE 0x80
uint16_t ReadAFHDS2A()
#ifdef STM32_BOARD
#define AFHDS2A_WRITE_TIME 1550
#else
#define AFHDS2A_WRITE_TIME 1700
#endif
uint16_t AFHDS2A_callback()
{
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);
@@ -286,12 +293,12 @@ uint16_t ReadAFHDS2A()
case AFHDS2A_BIND3:
AFHDS2A_build_bind_packet();
A7105_WriteData(AFHDS2A_TXPACKET_SIZE, packet_count%2 ? 0x0d : 0x8c);
if(!(A7105_ReadReg(A7105_00_MODE) & (1<<5 | 1<<6)))
{ // FECF+CRCF Ok
if(!(A7105_ReadReg(A7105_00_MODE) & (1<<5))) // removed FECF check due to issues with fs-x6b -> & (1<<5 | 1<<6)
{ // CRCF Ok
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
@@ -303,23 +310,23 @@ uint16_t ReadAFHDS2A()
}
phase = AFHDS2A_BIND4;
packet_count++;
return 3850;
break;
}
}
packet_count++;
if(IS_BIND_DONE)
{ // exit bind if asked to do so from the GUI
phase = AFHDS2A_BIND4;
return 3850;
break;
}
phase |= AFHDS2A_WAIT_WRITE;
return 1700;
return AFHDS2A_WRITE_TIME;
case AFHDS2A_BIND1|AFHDS2A_WAIT_WRITE:
case AFHDS2A_BIND2|AFHDS2A_WAIT_WRITE:
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();
@@ -329,7 +336,7 @@ uint16_t ReadAFHDS2A()
phase++;
if(phase > AFHDS2A_BIND3)
phase = AFHDS2A_BIND1;
return 2150;
return 3850-AFHDS2A_WRITE_TIME;
case AFHDS2A_BIND4:
AFHDS2A_build_bind_packet();
A7105_WriteData(AFHDS2A_TXPACKET_SIZE, packet_count%2 ? 0x0d : 0x8c);
@@ -341,7 +348,7 @@ uint16_t ReadAFHDS2A()
phase = AFHDS2A_DATA_INIT;
BIND_DONE;
}
return 3850;
break;
case AFHDS2A_DATA_INIT:
packet_counter=0;
packet_type = AFHDS2A_PACKET_STICKS;
@@ -351,10 +358,7 @@ 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
data_rx=A7105_ReadReg(A7105_00_MODE); // Check if something has been received...
A7105_WriteData(AFHDS2A_TXPACKET_SIZE, hopping_frequency[hopping_frequency_no++]);
if(hopping_frequency_no >= AFHDS2A_NUMFREQ)
hopping_frequency_no = 0;
@@ -370,13 +374,13 @@ 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
if(!(A7105_ReadReg(A7105_00_MODE) & (1<<5)) && !(data_rx & 1)) // removed FECF check due to issues with fs-x6b -> & (1<<5 | 1<<6)
{ // RX+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[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
@@ -399,23 +403,23 @@ 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
return 3850;
}
uint16_t initAFHDS2A()
void AFHDS2A_init()
{
A7105_Init();
@@ -428,7 +432,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
@@ -441,6 +445,5 @@ uint16_t initAFHDS2A()
num_ch=17;
else
num_ch=14;
return 50000;
}
#endif

View File

@@ -33,19 +33,14 @@ enum {
ASSAN_DATA5
};
void ASSAN_init()
void ASSAN_RF_init()
{
NRF24L01_Initialize();
//Specifics to ASSAN
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x02); // 4 bytes rx/tx address
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x80\x80\x80\xB8", ASSAN_ADDRESS_LENGTH); // Bind address
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x80\x80\x80\xB8", ASSAN_ADDRESS_LENGTH); // Bind address
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x80\x80\x80\xB8", ASSAN_ADDRESS_LENGTH); // Bind address
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_WriteReg(NRF24L01_11_RX_PW_P0, ASSAN_PACKET_SIZE);
NRF24L01_SetPower();
}
void ASSAN_send_packet()
@@ -169,17 +164,16 @@ static void __attribute__((unused)) ASSAN_initialize_txid()
hopping_frequency[1]=freq2;
}
uint16_t initASSAN()
void ASSAN_init()
{
ASSAN_initialize_txid();
ASSAN_init();
ASSAN_RF_init();
hopping_frequency_no = 0;
if(IS_BIND_IN_PROGRESS)
phase=ASSAN_BIND0;
else
phase=ASSAN_DATA0;
return 1000;
}
#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

@@ -57,22 +57,11 @@ enum {
#define BUGSMINI_FLAG_ANGLE 0x02 // angle/acro mode (set is angle mode)
#define BUGSMINI_FLAG_ALTHOLD 0x04 // angle/altitude hold mode (set is altitude mode)
static void __attribute__((unused)) BUGSMINI_init()
static void __attribute__((unused)) BUGSMINI_RF_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_WriteReg(NRF24L01_11_RX_PW_P0, BUGSMINI_RX_PAYLOAD_SIZE); // bytes of data payload for rx pipe 1
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, 0x07);
NRF24L01_SetBitrate(NRF24L01_BR_1M);
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x00); // Set feature bits on
}
static void __attribute__((unused)) BUGSMINI_check_arming()
@@ -95,7 +84,7 @@ static void __attribute__((unused)) BUGSMINI_check_arming()
}
}
static void __attribute__((unused)) BUGSMINI_send_packet(uint8_t bind)
static void __attribute__((unused)) BUGSMINI_send_packet()
{
BUGSMINI_check_arming(); // sets globals arm_flags and armed
@@ -107,7 +96,7 @@ static void __attribute__((unused)) BUGSMINI_send_packet(uint8_t bind)
packet[1] = BUGSMINI_txid[0];
packet[2] = BUGSMINI_txid[1];
packet[3] = BUGSMINI_txid[2];
if(bind)
if(IS_BIND_IN_PROGRESS)
{
packet[4] = 0x00;
packet[5] = 0x7d;
@@ -159,7 +148,7 @@ static void __attribute__((unused)) BUGSMINI_send_packet(uint8_t bind)
hopping_frequency_no++;
if(hopping_frequency_no >= BUGSMINI_NUM_RF_CHANNELS)
hopping_frequency_no = 0;
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? hopping_frequency[hopping_frequency_no+BUGSMINI_NUM_RF_CHANNELS] : hopping_frequency[hopping_frequency_no]);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? hopping_frequency[hopping_frequency_no+BUGSMINI_NUM_RF_CHANNELS] : hopping_frequency[hopping_frequency_no]);
}
// Power on, TX mode, 2byte CRC
@@ -286,7 +275,7 @@ uint16_t BUGSMINI_callback()
}
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
BUGSMINI_send_packet(1);
BUGSMINI_send_packet();
phase = BUGSMINI_BIND2;
return BUGSMINI_WRITE_WAIT;
case BUGSMINI_BIND2:
@@ -309,7 +298,7 @@ uint16_t BUGSMINI_callback()
}
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
BUGSMINI_send_packet(0);
BUGSMINI_send_packet();
phase = BUGSMINI_DATA2;
return BUGSMINI_WRITE_WAIT;
case BUGSMINI_DATA2:
@@ -357,11 +346,11 @@ static void __attribute__((unused)) BUGSMINI_initialize_txid()
BUGSMINI_txhash = pgm_read_byte_near( &BUGSMINI_tx_hash[rx_tx_addr[3]%BUGSMINI_NUM_TX_RF_MAPS] );
}
uint16_t initBUGSMINI()
void BUGSMINI_init()
{
BUGSMINI_initialize_txid();
memset(packet, (uint8_t)0, BUGSMINI_TX_PAYLOAD_SIZE);
BUGSMINI_init();
BUGSMINI_RF_init();
if(IS_BIND_IN_PROGRESS)
{
XN297_SetTXAddr((const uint8_t*)"mjxRC", 5);
@@ -378,7 +367,6 @@ uint16_t initBUGSMINI()
armed = 0;
arm_flags = BUGSMINI_FLAG_DISARM; // initial value from captures
arm_channel_previous = BUGSMINI_CH_SW_ARM;
return BUGSMINI_INITIAL_WAIT;
}
#endif

View File

@@ -33,18 +33,8 @@ static void __attribute__((unused)) Bayang_Rx_init_nrf24l01()
NRF24L01_Initialize();
XN297_SetTXAddr(bind_address, BAYANG_RX_ADDRESS_LENGTH);
XN297_SetRXAddr(bind_address, BAYANG_RX_ADDRESS_LENGTH);
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, BAYANG_RX_PACKET_SIZE + 2); // 2 extra bytes for xn297 crc
NRF24L01_WriteReg(NRF24L01_05_RF_CH, BAYANG_RX_RF_BIND_CHANNEL);
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
NRF24L01_Activate(0x73);
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();
NRF24L01_SetTxRxMode(RX_EN);
@@ -98,7 +88,7 @@ static void __attribute__((unused)) Bayang_Rx_build_telemetry_packet()
}
}
uint16_t initBayang_Rx()
void BAYANG_RX_init()
{
uint8_t i;
Bayang_Rx_init_nrf24l01();
@@ -119,17 +109,20 @@ uint16_t initBayang_Rx()
XN297_SetRXAddr(rx_tx_addr, BAYANG_RX_ADDRESS_LENGTH);
phase = BAYANG_RX_DATA;
}
return 1000;
}
uint16_t Bayang_Rx_callback()
uint16_t BAYANG_RX_callback()
{
uint8_t i;
static int8_t read_retry;
switch (phase) {
case BAYANG_RX_BIND:
if(IS_BIND_DONE) return initBayang_Rx(); // Abort bind
if(IS_BIND_DONE)
{
BAYANG_RX_init(); // Abort bind
break;
}
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) {
// data received from TX
if (XN297_ReadPayload(packet, BAYANG_RX_PACKET_SIZE) && ( packet[0] == 0xA4 || packet[0] == 0xA2 ) && Bayang_Rx_check_validity()) {
@@ -155,9 +148,13 @@ uint16_t Bayang_Rx_callback()
case BAYANG_RX_DATA:
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) {
if (XN297_ReadPayload(packet, BAYANG_RX_PACKET_SIZE) && packet[0] == 0xA5 && Bayang_Rx_check_validity()) {
if (telemetry_link == 0) {
if ((telemetry_link & 0x7F) == 0) {
Bayang_Rx_build_telemetry_packet();
telemetry_link = 1;
#ifdef SEND_CPPM
if(sub_protocol>0)
telemetry_link |= 0x80; // Disable telemetry output
#endif
}
rx_data_started = true;
rx_data_received = true;

View File

@@ -143,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;
}
@@ -218,7 +218,7 @@ static void __attribute__((unused)) BAYANG_check_rx(void)
for (uint8_t i=1; i < BAYANG_PACKET_SIZE-1; i++)
check += packet[i];
// decode data , check sum is ok as well, since there is no crc
if (packet[0] == 0x85 && packet[14] == check)
if (packet[0] == 0x85 && packet[14] == check && telemetry_link == 0)
{
// uncompensated battery volts*100/2
v_lipo1 = (packet[3]<<7) + (packet[4]>>1);
@@ -230,35 +230,28 @@ static void __attribute__((unused)) BAYANG_check_rx(void)
//Flags
//uint8_t flags = packet[3] >> 3;
// battery low: flags & 1
telemetry_link=1;
#if defined HUB_TELEMETRY
// Multiplexed P, I, D values in packet[8] and packet[9].
// The two most significant bits specify which term is sent.
// Remaining 14 bits represent the value: 0 .. 16383
frsky_send_user_frame(0x24+(packet[8]>>6), packet[9], packet[8] & 0x3F ); //0x24 = ACCEL_X_ID, so ACCEL_X_ID=P, ACCEL_Y_ID=I, ACCEL_Z_ID=D
#endif
telemetry_counter++;
if(telemetry_lost==0)
telemetry_link=1;
if(telemetry_lost)
telemetry_link=0; // Don't send anything yet
}
}
NRF24L01_SetTxRxMode(TXRX_OFF);
}
#endif
static void __attribute__((unused)) BAYANG_init()
static void __attribute__((unused)) BAYANG_RF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t *)"\x00\x00\x00\x00\x00", BAYANG_ADDRESS_LENGTH);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, BAYANG_PACKET_SIZE);
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // No retransmits
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
NRF24L01_Activate(0x73);
switch (sub_protocol)
{
@@ -356,15 +349,14 @@ static void __attribute__((unused)) BAYANG_initialize_txid()
hopping_frequency_no=0;
}
uint16_t initBAYANG(void)
void BAYANG_init(void)
{
BIND_IN_PROGRESS; // autobind protocol
phase=BAYANG_BIND;
bind_counter = BAYANG_BIND_COUNT;
BAYANG_initialize_txid();
BAYANG_init();
BAYANG_RF_init();
packet_count=0;
return BAYANG_INITIAL_WAIT+BAYANG_PACKET_PERIOD;
}
#endif
#endif

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

@@ -315,7 +315,7 @@ static void __attribute__((unused)) BUGS_increment_counts()
// FIFO config is one less than desired value
#define BUGS_FIFO_SIZE_RX 15
#define BUGS_FIFO_SIZE_TX 21
uint16_t ReadBUGS(void)
uint16_t BUGS_callback(void)
{
uint8_t mode, base_adr;
uint16_t rxid;
@@ -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);
@@ -437,7 +437,7 @@ uint16_t ReadBUGS(void)
return packet_period;
}
uint16_t initBUGS(void)
void BUGS_init(void)
{
uint16_t rxid=0;
uint8_t base_adr=BUGS_EEPROM_OFFSET+(RX_num&0x0F)*2;
@@ -459,8 +459,6 @@ uint16_t initBUGS(void)
armed = 0;
arm_flags = BUGS_FLAG_DISARM; // initial value from captures
arm_channel_previous = BUGS_CH_SW_ARM;
return 10000;
}
#endif

View File

@@ -255,7 +255,7 @@ static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode)
*p |= (packet_count++)<<7; // This causes the 8th bit of the first byte to toggle with each xmit so consecutive payloads are not identical.
// This is a work around for a reported bug in clone NRF24L01 chips that mis-took this case for a re-transmit of the same packet.
CABELL_SetPower();
NRF24L01_SetPower();
NRF24L01_WritePayload((uint8_t*)&TxPacket, packetSize);
#if defined CABELL_HUB_TELEMETRY
@@ -356,48 +356,18 @@ static void __attribute__((unused)) CABELL_setAddress()
}
//-----------------------------------------------------------------------------------------
static void __attribute__((unused)) CABELL_init()
static void __attribute__((unused)) CABELL_RF_init()
{
NRF24L01_Initialize();
CABELL_SetPower();
NRF24L01_SetBitrate(NRF24L01_BR_250K); // slower data rate gives better range/reliability
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment on all data pipes
NRF24L01_SetTxRxMode(TX_EN); //Power up and 16 bit CRC
CABELL_setAddress();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01);
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 0x20); // 32 byte packet length
NRF24L01_WriteReg(NRF24L01_12_RX_PW_P1, 0x20); // 32 byte packet length
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x5F); // no retransmits
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3F); // Enable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x04); // Enable dynamic Payload Length
NRF24L01_Activate(0x73);
prev_power = NRF_POWER_0;
}
//-----------------------------------------------------------------------------------------
static void CABELL_SetPower() // This over-ride the standard Set Power to allow an flag in option to indicate max power setting
// Note that on many modules max power may actually be worse than the normal high power setting
// test and only use max if it helps the range
{
if(IS_BIND_DONE && !IS_RANGE_FLAG_on && ((option & CABELL_OPTION_MASK_MAX_POWER_OVERRIDE) != 0))
{ // If we are not in range or bind mode and power setting override is in effect, then set max power, else standard power logic
if(prev_power != NRF_POWER_3) // prev_power is global variable for NRF24L01; NRF_POWER_3 is max power
{
uint8_t rf_setup = NRF24L01_ReadReg(NRF24L01_06_RF_SETUP);
rf_setup = (rf_setup & 0xF9) | (NRF_POWER_3 << 1);
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
prev_power=NRF_POWER_3;
}
}
else
NRF24L01_SetPower();
NRF24L01_SetTxRxMode(TX_EN); // Clear data ready, data sent, retransmit and enable CRC 16bits, ready for TX
}
//-----------------------------------------------------------------------------------------
@@ -414,7 +384,7 @@ uint16_t CABELL_callback()
else if (bind_counter == 0)
{
BIND_DONE;
CABELL_init(); // non-bind address
CABELL_RF_init(); // non-bind address
}
else
{
@@ -425,17 +395,15 @@ uint16_t CABELL_callback()
}
//-----------------------------------------------------------------------------------------
uint16_t initCABELL(void)
void CABELL_init(void)
{
if (IS_BIND_DONE)
bind_counter = 0;
else
bind_counter = CABELL_BIND_COUNT;
CABELL_init();
CABELL_RF_init();
packet_period = CABELL_PACKET_PERIOD;
return packet_period;
}
#endif

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

@@ -644,37 +644,24 @@ static uint8_t crtp_log_setup_state_machine()
return state_machine_completed;
}
static int cflie_init()
static void CFLIE_RF_init()
{
NRF24L01_Initialize();
// CRC, radio on
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x01); // Auto Acknowledgement for data pipe 0
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, TX_ADDR_SIZE-2); // 5-byte RX/TX address
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x13); // 3 retransmits, 500us delay
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch_num); // Defined in initialize_rx_tx_addr
NRF24L01_SetBitrate(data_rate); // Defined in initialize_rx_tx_addr
NRF24L01_SetPower();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, TX_ADDR_SIZE);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, TX_ADDR_SIZE);
// this sequence necessary for module from stock tx
NRF24L01_ReadReg(NRF24L01_1D_FEATURE);
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_ReadReg(NRF24L01_1D_FEATURE);
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x01); // Enable Dynamic Payload Length on pipe 0
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x06); // Enable Dynamic Payload Length, enable Payload with ACK
// 50ms delay in callback
return 50000;
NRF24L01_SetTxRxMode(TX_EN); // Clear data ready, data sent, retransmit and enable CRC 16bits, ready for TX
}
// TODO: Fix telemetry
@@ -749,7 +736,7 @@ static int cflie_init()
// }
// }
static uint16_t cflie_callback()
static uint16_t CFLIE_callback()
{
switch (phase) {
case CFLIE_INIT_SEARCH:
@@ -799,7 +786,7 @@ static uint16_t cflie_callback()
}
// Generate address to use from TX id and manufacturer id (STM32 unique id)
static uint8_t initialize_rx_tx_addr()
static uint8_t CFLIE_initialize_rx_tx_addr()
{
rx_tx_addr[0] =
rx_tx_addr[1] =
@@ -844,19 +831,15 @@ static uint8_t initialize_rx_tx_addr()
return CFLIE_INIT_SEARCH;
}
uint16_t initCFlie(void)
void CFLIE_init(void)
{
BIND_IN_PROGRESS; // autobind protocol
phase = initialize_rx_tx_addr();
phase = CFLIE_initialize_rx_tx_addr();
crtp_log_setup_state = CFLIE_CRTP_LOG_SETUP_STATE_INIT;
packet_count=0;
int delay = cflie_init();
// debugln("CFlie init!");
return delay;
CFLIE_RF_init();
}
#endif

View File

@@ -49,7 +49,7 @@ enum YD829_FLAGS {
YD829_FLAG_STILL = 0x80,
};
static void __attribute__((unused)) CG023_send_packet(uint8_t bind)
static void __attribute__((unused)) CG023_send_packet()
{
// throttle : 0x00 - 0xFF
throttle=convert_channel_8b(THROTTLE);
@@ -62,7 +62,7 @@ static void __attribute__((unused)) CG023_send_packet(uint8_t bind)
// aileron : 0x43 - 0x7F - 0xBB
aileron = convert_channel_16b_limit(AILERON, 0x43, 0xBB);
if (bind)
if (IS_BIND_IN_PROGRESS)
packet[0]= 0xaa;
else
packet[0]= 0x55;
@@ -106,7 +106,7 @@ static void __attribute__((unused)) CG023_send_packet(uint8_t bind)
// Power on, TX mode, 2byte CRC
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
if (bind)
if (IS_BIND_IN_PROGRESS)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, CG023_RF_BIND_CHANNEL);
else
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency_no);
@@ -119,41 +119,25 @@ static void __attribute__((unused)) CG023_send_packet(uint8_t bind)
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) CG023_init()
static void __attribute__((unused)) CG023_RF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t *)"\x26\xA8\x67\x35\xCC", 5);
NRF24L01_Initialize();
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_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
XN297_SetTXAddr((uint8_t *)"\x26\xA8\x67\x35\xCC", 5);
}
uint16_t CG023_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
CG023_send_packet(0);
}
else
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
if(bind_counter)
{
bind_counter--;
if (bind_counter == 0)
BIND_DONE;
else
{
CG023_send_packet(1);
bind_counter--;
}
}
CG023_send_packet();
return packet_period;
}
@@ -165,17 +149,16 @@ static void __attribute__((unused)) CG023_initialize_txid()
hopping_frequency_no = rx_tx_addr[0] - 0x7D; // rf channel for data packets
}
uint16_t initCG023(void)
void CG023_init(void)
{
BIND_IN_PROGRESS; // autobind protocol
bind_counter = CG023_BIND_COUNT;
CG023_initialize_txid();
CG023_init();
CG023_RF_init();
if(sub_protocol==CG023)
packet_period=CG023_PACKET_PERIOD;
else // YD829
packet_period=YD829_PACKET_PERIOD;
return CG023_INITIAL_WAIT+YD829_PACKET_PERIOD;
}
#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
@@ -169,21 +169,14 @@ static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
NRF24L01_SetPower();
}
static void __attribute__((unused)) CX10_init()
static void __attribute__((unused)) CX10_RF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc",5);
XN297_SetRXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc",5);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto 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_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
NRF24L01_WriteReg(NRF24L01_05_RF_CH, CX10_RF_BIND_CHANNEL);
}
uint16_t CX10_callback()
@@ -220,7 +213,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();
@@ -260,9 +254,13 @@ static void __attribute__((unused)) CX10_initialize_txid()
}
}
uint16_t initCX10(void)
void CX10_init(void)
{
BIND_IN_PROGRESS; // autobind protocol
if(protocol == PROTO_Q2X2)
sub_protocol|=0x08; // Increase the number of sub_protocols for CX-10
if(sub_protocol==CX10_BLUE)
{
packet_length = CX10A_PACKET_SIZE;
@@ -285,8 +283,7 @@ uint16_t initCX10(void)
bind_counter = CX10_BIND_COUNT;
}
CX10_initialize_txid();
CX10_init();
return CX10_INITIAL_WAIT+packet_period;
CX10_RF_init();
}
#endif

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

@@ -61,7 +61,6 @@ static void __attribute__((unused)) CORONA_rf_init()
CC2500_WriteReg(CC2500_15_DEVIATN, 0x50);
}
prev_option = option;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
//not sure what they are doing to the PATABLE since basically only the first byte is used and it's only 8 bytes long. So I think they end up filling the PATABLE fully with 0xFF
@@ -72,7 +71,7 @@ static void __attribute__((unused)) CORONA_rf_init()
}
// Generate id and hopping freq
static void __attribute__((unused)) CORONA_init()
static void __attribute__((unused)) CORONA_TXID_init()
{
#ifdef CORONA_FORCE_ID
// Example of ID and channels taken from dumps
@@ -256,17 +255,13 @@ static uint16_t __attribute__((unused)) CORONA_build_packet()
return packet_period;
}
uint16_t ReadCORONA()
uint16_t CORONA_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(22000);
#endif
// Tune frequency if it has been changed
if ( prev_option != option )
{
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
prev_option = option ;
}
CC2500_SetFreqOffset();
if(IS_BIND_IN_PROGRESS)
{
@@ -281,7 +276,7 @@ uint16_t ReadCORONA()
return packet_period;
}
uint16_t initCORONA()
void CORONA_init()
{
switch(sub_protocol)
{
@@ -298,9 +293,8 @@ uint16_t initCORONA()
state=400; // Used by V2 to send RF channels + ID for 2.65s at startup
hopping_frequency_no=0;
fdv3_id_send = 0;
CORONA_init();
CORONA_TXID_init();
CORONA_rf_init();
return 10000;
}
#endif

View File

@@ -37,10 +37,10 @@ enum DM002_FLAGS {
DM002_FLAG_CAMERA2 = 0x80,
};
static void __attribute__((unused)) DM002_send_packet(uint8_t bind)
static void __attribute__((unused)) DM002_send_packet()
{
memcpy(packet+5,(uint8_t *)"\x00\x7F\x7F\x7F\x00\x00\x00",7);
if(bind)
if(IS_BIND_IN_PROGRESS)
{
packet[0] = 0xAA;
packet[1] = rx_tx_addr[0];
@@ -83,10 +83,7 @@ static void __attribute__((unused)) DM002_send_packet(uint8_t bind)
// Power on, TX mode, 2byte CRC
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
if (bind)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, DM002_RF_BIND_CHANNEL);
else
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? DM002_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no]);
// clear packet status bits and TX FIFO
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
@@ -95,43 +92,28 @@ static void __attribute__((unused)) DM002_send_packet(uint8_t bind)
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) DM002_init()
static void __attribute__((unused)) DM002_RF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t *)"\x26\xA8\x67\x35\xCC", 5);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
XN297_SetTXAddr((uint8_t *)"\x26\xA8\x67\x35\xCC", 5);
}
uint16_t DM002_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(DM002_PACKET_PERIOD);
#endif
DM002_send_packet(0);
}
else
#ifdef MULTI_SYNC
telemetry_set_input_sync(DM002_PACKET_PERIOD);
#endif
if (bind_counter)
{
bind_counter--;
if (bind_counter == 0)
{
BIND_DONE;
XN297_SetTXAddr(rx_tx_addr, 5);
}
else
{
DM002_send_packet(1);
bind_counter--;
}
}
DM002_send_packet();
return DM002_PACKET_PERIOD;
}
@@ -155,13 +137,12 @@ static void __attribute__((unused)) DM002_initialize_txid()
}
}
uint16_t initDM002(void)
void DM002_init(void)
{
BIND_IN_PROGRESS; // autobind protocol
bind_counter = DM002_BIND_COUNT;
DM002_initialize_txid();
DM002_init();
return DM002_INITIAL_WAIT;
DM002_RF_init();
}
#endif

View File

@@ -4,7 +4,7 @@
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,
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.
@@ -31,7 +31,7 @@ enum {
DSM_RX_DATA_CH2,
};
static void __attribute__((unused)) DSM_Rx_init()
static void __attribute__((unused)) DSM_RX_RF_init()
{
DSM_cyrf_config();
rx_disable_lna = IS_POWER_FLAG_on;
@@ -63,7 +63,7 @@ uint16_t convert_channel_DSM_nolimit(int32_t val)
return (uint16_t)val;
}
static uint8_t __attribute__((unused)) DSM_Rx_check_packet()
static uint8_t __attribute__((unused)) DSM_RX_check_packet()
{
uint8_t rx_status=CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
if((rx_status & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
@@ -99,7 +99,7 @@ static uint8_t __attribute__((unused)) DSM_Rx_check_packet()
return rx_status; // Return error code
}
static void __attribute__((unused)) DSM_Rx_build_telemetry_packet()
static void __attribute__((unused)) DSM_RX_build_telemetry_packet()
{
uint8_t nbr_bits = 11;
if((DSM_rx_type&0xF0) == 0x00)
@@ -155,9 +155,13 @@ static void __attribute__((unused)) DSM_Rx_build_telemetry_packet()
packet_in[idx++] = bits & 0xff;
// Send telemetry
telemetry_link = 1;
#ifdef SEND_CPPM
if(sub_protocol>0)
telemetry_link |= 0x80; // Disable telemetry output
#endif
}
static bool __attribute__((unused)) DSM_Rx_bind_check_validity()
static bool __attribute__((unused)) DSM_RX_bind_check_validity()
{
uint16_t sum = 384 - 0x10;//
for(uint8_t i = 0; i < 8; i++)
@@ -173,7 +177,7 @@ static bool __attribute__((unused)) DSM_Rx_bind_check_validity()
return true;
}
static void __attribute__((unused)) DSM_Rx_build_bind_packet()
static void __attribute__((unused)) DSM_RX_build_bind_packet()
{
uint16_t sum = 384 - 0x10;//
packet[0] = 0xff ^ cyrfmfg_id[0]; // ID
@@ -205,7 +209,7 @@ static void __attribute__((unused)) DSM_abort_channel_rx(uint8_t ch)
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83); // Prepare to receive
}
uint16_t DSM_Rx_callback()
uint16_t DSM_RX_callback()
{
uint8_t rx_status;
static uint8_t read_retry=0;
@@ -232,7 +236,7 @@ uint16_t DSM_Rx_callback()
if(len==16)
{
CYRF_ReadDataPacketLen(packet_in, 16);
if(DSM_Rx_bind_check_validity())
if(DSM_RX_bind_check_validity())
{
// store tx info into eeprom
uint16_t temp = DSM_RX_EEPROM_OFFSET;
@@ -257,6 +261,7 @@ uint16_t DSM_Rx_callback()
&0x80 => false=DSM2, true=DSMX
&0xF0 => false=1024, true=2048 */
DSM_rx_type=packet_in[12];
debugln(", num_ch=%d, type=%02X",num_ch, DSM_rx_type);
switch(DSM_rx_type)
{
case 0x01:
@@ -274,12 +279,11 @@ uint16_t DSM_Rx_callback()
break;
}
eeprom_write_byte((EE_ADDR)temp, DSM_rx_type);
debugln(", num_ch=%d, type=%02X",num_ch, DSM_rx_type);
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
CYRF_SetTxRxMode(TX_EN); // Force end state TX
CYRF_ConfigDataCode((const uint8_t *)"\x98\x88\x1B\xE4\x30\x79\x03\x84", 16);
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX
DSM_Rx_build_bind_packet();
DSM_RX_build_bind_packet();
bind_counter=500;
phase++; // DSM_RX_BIND2;
return 1000;
@@ -301,11 +305,11 @@ uint16_t DSM_Rx_callback()
if(read_retry==0)
{
packet_count=0;
hopping_frequency_no++; // Change channel
hopping_frequency_no++; // Change channel
hopping_frequency_no %= 0x50;
hopping_frequency_no |= 0x01; // Odd channels only
hopping_frequency_no |= 0x01; // Odd channels only
CYRF_ConfigRFChannel(hopping_frequency_no);
DSM_abort_channel_rx(0); // Abort RX operation and receive
DSM_abort_channel_rx(0); // Abort RX operation and receive
}
}
return 1000;
@@ -346,7 +350,7 @@ uint16_t DSM_Rx_callback()
break;
case DSM2_RX_SCAN: // Scan for DSM2 frequencies
//Received something ?
rx_status = DSM_Rx_check_packet();
rx_status = DSM_RX_check_packet();
if(rx_status == 0x02)
{ // data received with no errors
debugln("CH%d:Found %d",rf_ch_num+1,hopping_frequency[rf_ch_num]);
@@ -401,13 +405,13 @@ uint16_t DSM_Rx_callback()
pps_counter = 0;
}
//Received something ?
rx_status = DSM_Rx_check_packet();
rx_status = DSM_RX_check_packet();
if(rx_status == 0x02)
{ // data received with no errors
#ifdef DSM_DEBUG_RF
debugln("CH1:RX");
#endif
DSM_Rx_build_telemetry_packet();
DSM_RX_build_telemetry_packet();
rx_data_started = true;
pps_counter++;
DSM_abort_channel_rx(2); // Abort RX operation, set sop&data&seed&rf using CH2, DSM2/X and receive
@@ -452,13 +456,13 @@ uint16_t DSM_Rx_callback()
}
return 500;
case DSM_RX_DATA_CH2:
rx_status = DSM_Rx_check_packet();
rx_status = DSM_RX_check_packet();
if(rx_status == 0x02)
{ // data received with no errors
#ifdef DSM_DEBUG_RF
debugln("CH2:RX");
#endif
DSM_Rx_build_telemetry_packet();
DSM_RX_build_telemetry_packet();
pps_counter++;
}
#ifdef DSM_DEBUG_RF
@@ -476,9 +480,9 @@ uint16_t DSM_Rx_callback()
return 10000;
}
uint16_t initDSM_Rx()
void DSM_RX_init()
{
DSM_Rx_init();
DSM_RX_RF_init();
hopping_frequency_no = 0;
if (IS_BIND_IN_PROGRESS)
@@ -499,7 +503,6 @@ uint16_t initDSM_Rx()
debugln(", type=%02X", DSM_rx_type);
phase = DSM_RX_DATA_PREP;
}
return 15000;
}
#endif

View File

@@ -17,6 +17,8 @@
#include "iface_cyrf6936.h"
//#define DSM_DEBUG_FWD_PGM
//#define DSM_GR300
#define DSM_BIND_CHANNEL 0x0d //13 This can be any odd channel
@@ -86,17 +88,17 @@ static void __attribute__((unused)) DSM_build_bind_packet()
else
packet[11] = num_ch;
if (sub_protocol==DSM2_22)
if (sub_protocol==DSM2_1F)
packet[12]=num_ch<8?0x01:0x02; // DSM2/1024 1 or 2 packets depending on the number of channels
else if(sub_protocol==DSM2_11)
else if(sub_protocol==DSM2_2F)
packet[12]=0x12; // DSM2/2048 2 packets
else if(sub_protocol==DSMX_22)
else if(sub_protocol==DSMX_1F)
#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
else // DSMX_11 && DSM_AUTO
else // DSMX_2F && DSM_AUTO
packet[12]=0xb2; // DSMX/2048 2 packets
packet[13] = 0x00; //???
@@ -139,7 +141,7 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
if(prev_option!=option)
DSM_update_channels();
if (sub_protocol==DSMX_11 || sub_protocol==DSMX_22 )
if (sub_protocol==DSMX_2F || sub_protocol==DSMX_1F )
{//DSMX
packet[0] = cyrfmfg_id[2];
packet[1] = cyrfmfg_id[3];
@@ -148,9 +150,10 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
{//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
if(sub_protocol==DSM2_1F)
bits=10; // Only DSM2_1F is using a resolution of 1024
}
#ifdef DSM_THROTTLE_KILL_CH
uint16_t kill_ch=Channel_data[DSM_THROTTLE_KILL_CH-1];
#endif
@@ -176,12 +179,12 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
else
#endif
#ifdef DSM_MAX_THROW
value=Channel_data[CH_TAER[idx]]; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX
value=Channel_data[CH_TAER[idx]]; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX
#else
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
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],0x156,0x6AA); // -100%..+100% => 1100..1900us and -125%..+125% => 1000..2000us based on a DX8 G2 dump
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);
@@ -189,6 +192,23 @@ 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()
@@ -208,7 +228,7 @@ static uint8_t __attribute__((unused)) DSM_Check_RX_packet()
return result;
}
uint16_t ReadDsm()
uint16_t DSM_callback()
{
#define DSM_CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2
#ifdef STM32_BOARD
@@ -300,16 +320,17 @@ uint16_t ReadDsm()
CYRF_SetTxRxMode(TX_EN);
hopping_frequency_no = 0;
phase = DSM_CH1_WRITE_A; // in fact phase++
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11||sub_protocol==DSMX_22);
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_2F||sub_protocol==DSMX_1F);
return 10000;
case DSM_CH1_WRITE_A:
#ifdef MULTI_SYNC
telemetry_set_input_sync(11000); // Always request 11ms spacing even if we don't use half of it in 22ms mode
#endif
CYRF_SetPower(0x28); //Keep transmit power in sync
case DSM_CH1_WRITE_B:
DSM_build_data_packet(phase == DSM_CH1_WRITE_B); // build lower or upper channels
case DSM_CH2_WRITE_A:
case DSM_CH2_WRITE_B:
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
@@ -340,12 +361,10 @@ uint16_t ReadDsm()
CYRF_SetTxRxMode(TX_EN);
}
#endif
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11 || sub_protocol==DSMX_22);
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_2F || sub_protocol==DSMX_1F);
phase++; // change from CH1_CHECK to CH2_WRITE
return DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY;
}
if (phase == DSM_CH2_CHECK_A)
CYRF_SetPower(0x28); //Keep transmit power in sync
#if defined DSM_TELEMETRY
phase++; // change from CH2_CHECK to CH2_READ
CYRF_SetTxRxMode(RX_EN); //Receive mode
@@ -368,11 +387,20 @@ 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;
}
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
if (phase == DSM_CH2_READ_A && (sub_protocol==DSM2_22 || sub_protocol==DSMX_22) && num_ch < 8) // 22ms mode
if (phase == DSM_CH2_READ_A && (sub_protocol==DSM2_1F || sub_protocol==DSMX_1F) && num_ch < 8) // 22ms mode
{
CYRF_SetTxRxMode(RX_EN); // Force end state read
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX operation
@@ -390,14 +418,14 @@ uint16_t ReadDsm()
phase = DSM_CH1_WRITE_A; //Transmit lower
CYRF_SetTxRxMode(TX_EN); //TX mode
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); //Clear abort RX operation
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11||sub_protocol==DSMX_22);
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_2F||sub_protocol==DSMX_1F);
return DSM_READ_DELAY;
#else
// No telemetry
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11||sub_protocol==DSMX_22);
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_2F||sub_protocol==DSMX_1F);
if (phase == DSM_CH2_CHECK_A)
{
if(num_ch > 7 || sub_protocol==DSM2_11 || sub_protocol==DSMX_11)
if(num_ch > 7 || sub_protocol==DSM2_2F || sub_protocol==DSMX_2F)
phase = DSM_CH1_WRITE_B; //11ms mode or upper to transmit change from CH2_CHECK_A to CH1_WRITE_A
else
{ //Normal mode 22ms
@@ -421,7 +449,7 @@ uint16_t ReadDsm()
return 0;
}
uint16_t initDsm()
void DSM_init()
{
CYRF_GetMfgData(cyrfmfg_id);
//Model match
@@ -437,7 +465,7 @@ uint16_t initDsm()
//Calc CRC seed
seed = (cyrfmfg_id[0] << 8) + cyrfmfg_id[1];
//Hopping frequencies
if (sub_protocol == DSMX_11 || sub_protocol == DSMX_22)
if (sub_protocol == DSMX_2F || sub_protocol == DSMX_1F)
DSM_calc_dsmx_channel();
else
{
@@ -468,7 +496,6 @@ uint16_t initDsm()
}
else
phase = DSM_CHANSEL;//
return 10000;
}
#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;
@@ -163,29 +163,147 @@ static void __attribute__((unused)) DEVO_build_data_pkt()
}
#if defined DEVO_HUB_TELEMETRY
static void __attribute__((unused)) DEVO_parse_telemetry_packet()
static uint32_t __attribute__((unused)) DEVO_text_to_int(uint8_t *ptr, uint8_t len)
{
uint32_t value = 0;
for(uint8_t i = 0; i < len; i++)
value = value * 10 + (ptr[i] - '0');
return value;
}
static void __attribute__((unused)) DEVO_float_to_ints(uint8_t *ptr, uint16_t *value, uint16_t *decimal)
{
bool seen_decimal = false;
*value = 0;
*decimal = 0;
for(uint8_t i = 0; i < 7; i++)
{
if(ptr[i] == '.')
{
seen_decimal = true;
continue;
}
if(ptr[i] < '0' || ptr[i] > '9')
{
if(*value != 0 || seen_decimal)
return;
}
else
{
if(seen_decimal)
*decimal = *decimal * 10 + (ptr[i] - '0');
else
*value = *value * 10 + (ptr[i] - '0');
}
}
}
static void __attribute__((unused)) DEVO_parse_telemetry_packet()
{ // Telemetry packets every 2.4ms
DEVO_scramble_pkt(); //This will unscramble the packet
debugln("RX");
if ((((uint32_t)packet[15] << 16) | ((uint32_t)packet[14] << 8) | packet[13]) != (MProtocol_id & 0x00ffffff))
return; // ID does not match
//RSSI
TX_RSSI = CYRF_ReadRegister(CYRF_13_RSSI) & 0x1F;
TX_RSSI = (TX_RSSI << 1) + TX_RSSI;
RX_RSSI = TX_RSSI;
telemetry_link = 1;
//TODO: FW telemetry https://github.com/DeviationTX/deviation/blob/5efb6a28bea697af9a61b5a0ed2528cc8d203f90/src/protocol/devo_cyrf6936.c#L232
debug("P[0]=%02X",packet[0]);
if (packet[0] == 0x30) // Volt packet
if((telemetry_link & 3) != 0)
{
v_lipo1 = packet[1] << 1;
v_lipo2 = packet[3] << 1;
debugln("S%d",telemetry_link);
return; // Previous telemetry not sent yet...
}
//Debug telem RX
//for(uint8_t i=0;i<12;i++)
// debug("%02X ",packet[i]);
//debugln("");
#if defined HUB_TELEMETRY
//Telemetry https://github.com/DeviationTX/deviation/blob/5efb6a28bea697af9a61b5a0ed2528cc8d203f90/src/protocol/devo_cyrf6936.c#L232
uint16_t val, dec;
switch(packet[0])
{
case 0x30: // Volt and RPM packet
//RSSI and voltage
TX_RSSI = CYRF_ReadRegister(CYRF_13_RSSI) & 0x1F;
TX_RSSI = (TX_RSSI << 1) + TX_RSSI;
RX_RSSI = TX_RSSI;
telemetry_link |= 1;
v_lipo1 = packet[1] << 1;
v_lipo2 = packet[3] << 1;
//packet[5] = 127; // 12.7V
if(packet[5] != 0)
{
val = (packet[5]*11)/21; // OpenTX strange transformation??
dec = val;
val /= 10;
dec -= val*10;
frsky_send_user_frame(0x3A, val, 0x00); // volt3
frsky_send_user_frame(0x3B, dec, 0x00); // volt3
}
val = packet[7] * 120; // change to RPM
frsky_send_user_frame(0x03, val, val>>8); // RPM
break;
case 0x31: // Temperature packet
//memcpy(&packet[1],"\x29\x2A\x2B\x00\x00\x00\x00\x00\x00\x00\x00\x00",12); // 21°, 22°, 23°
for(uint8_t i=0; i<2;i++)
if(packet[i+1]!=0xff)
{
val = packet[i+1];
val -= 20;
frsky_send_user_frame(0x02 + i*3, val, val>>8); // temp 1 & 2
}
break;
// GPS Data
case 0x32: // Longitude
//memcpy(&packet[1],"\x30\x33\x30\x32\x30\x2e\x38\x32\x37\x30\x45\xfb",12); // 030°20.8270E
val = DEVO_text_to_int(&packet[1], 3)*100 + DEVO_text_to_int(&packet[4], 2); // dddmm
frsky_send_user_frame(0x12 , val, val>>8);
val = DEVO_text_to_int(&packet[7], 4); // .mmmm
frsky_send_user_frame(0x12+8, val, val>>8);
frsky_send_user_frame(0x1A+8, packet[11], 0x00); // 'E'/'W'
break;
case 0x33: // Latitude
//memcpy(&packet[1],"\x35\x39\x35\x34\x2e\x37\x37\x37\x36\x4e\x07\x00",12); // 59°54.776N
val = DEVO_text_to_int(&packet[1], 2)*100 + DEVO_text_to_int(&packet[3], 2); // ddmm
frsky_send_user_frame(0x13 , val, val>>8);
val = DEVO_text_to_int(&packet[6], 4); // .mmmm
frsky_send_user_frame(0x13+8, val, val>>8);
frsky_send_user_frame(0x1B+8, packet[10], 0x00); // 'N'/'S'
break;
case 0x34: // Altitude
//memcpy(&packet[1],"\x31\x32\x2e\x38\x00\x00\x00\x4d\x4d\x4e\x45\xfb",12); // 12.8 MMNE
DEVO_float_to_ints(&packet[1], &val, &dec);
frsky_send_user_frame(0x10, val, val>>8);
frsky_send_user_frame(0x21, dec, dec>>8);
break;
case 0x35: // Speed
//memcpy(&packet[1],"\x00\x00\x00\x00\x00\x00\x30\x2e\x30\x30\x00\x00",12); // 0.0
DEVO_float_to_ints(&packet[1], &val, &dec);
frsky_send_user_frame(0x11 , val, val>>8);
frsky_send_user_frame(0x11+8, dec, dec>>8);
break;
case 0x36: // Time
//memcpy(&packet[1],"\x31\x38\x32\x35\x35\x32\x31\x35\x31\x30\x31\x32",12); // 2012-10-15 18:25:52 (UTC)
if(packet[1]!=0)
{
frsky_send_user_frame(0x15, DEVO_text_to_int(&packet[9], 2), DEVO_text_to_int(&packet[7], 2)); // month, day
frsky_send_user_frame(0x16, DEVO_text_to_int(&packet[11], 2)+24, 0x00); // year
frsky_send_user_frame(0x17, DEVO_text_to_int(&packet[1], 2), DEVO_text_to_int(&packet[3], 2)); // hour, min
frsky_send_user_frame(0x18, DEVO_text_to_int(&packet[5], 2), 0x00); // second
}
break;
}
#else
if(packet[0] == 0x30)
{
TX_RSSI = CYRF_ReadRegister(CYRF_13_RSSI) & 0x1F;
TX_RSSI = (TX_RSSI << 1) + TX_RSSI;
RX_RSSI = TX_RSSI;
telemetry_link |= 1;
v_lipo1 = packet[1] << 1;
v_lipo2 = packet[3] << 1;
}
#endif
}
#endif
@@ -294,7 +412,7 @@ static void __attribute__((unused)) DEVO_BuildPacket()
packet_count = 0;
}
uint16_t devo_callback()
uint16_t DEVO_callback()
{
static uint8_t txState=0;
@@ -404,8 +522,23 @@ uint16_t devo_callback()
#endif
}
uint16_t DevoInit()
void DEVO_init()
{
#ifdef ENABLE_PPM
if(mode_select) //PPM mode
{
if(IS_BIND_BUTTON_FLAG_on)
{
eeprom_write_byte((EE_ADDR)(MODELMODE_EEPROM_OFFSET+RX_num),0x00); // reset to autobind mode for the current model
option=0;
}
else
{
option=eeprom_read_byte((EE_ADDR)(MODELMODE_EEPROM_OFFSET+RX_num)); // load previous mode: autobind or fixed id
if(option!=1) option=0; // if not fixed id mode then it should be autobind
}
}
#endif //ENABLE_PPM
switch(sub_protocol)
{
case 1:
@@ -453,7 +586,6 @@ uint16_t DevoInit()
bind_counter = 0;
DEVO_cyrf_set_bound_sop_code();
}
return 2400;
}
#endif

View File

@@ -0,0 +1,151 @@
/*
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_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 E010R5_callback()
{
//Bind
if(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;
}
void E010R5_init()
{
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
rx_tx_addr[0]=0x00;
hopping_frequency[0]=0x35; //53
#ifdef E010R5_FORCE_ID
switch(rx_tx_addr[3]%5)
{
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;
case 2:
//TX4
hopping_frequency[0]=0x30; //48
hopping_frequency[1]=0x38; //56
rx_tx_addr[1]=0x2E;
rx_tx_addr[2]=0xAE;
break;
case 3:
//TX5
//hopping_frequency[0]=0x35; //53
hopping_frequency[1]=0x41; //65
rx_tx_addr[0]=0x0D;
rx_tx_addr[1]=0xB9;
rx_tx_addr[2]=0xFC;
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
// 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;
}
#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/>.
*/
#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;
}
void E016HV2_init()
{
//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
}
#endif

View File

@@ -95,14 +95,14 @@ static void __attribute__((unused)) E015_check_arming()
}
}
static void __attribute__((unused)) E01X_send_packet(uint8_t bind)
static void __attribute__((unused)) E01X_send_packet()
{
uint8_t can_flip = 0, calibrate = 1;
if(sub_protocol==E012)
{
packet_length=E012_PACKET_SIZE;
packet[0] = rx_tx_addr[1];
if(bind)
if(IS_BIND_IN_PROGRESS)
{
packet[1] = 0xaa;
memcpy(&packet[2], hopping_frequency, E012_NUM_RF_CHANNELS);
@@ -134,7 +134,7 @@ static void __attribute__((unused)) E01X_send_packet(uint8_t bind)
}
else if(sub_protocol==E015)
{ // E015
if(bind)
if(IS_BIND_IN_PROGRESS)
{
packet[0] = 0x18;
packet[1] = 0x04;
@@ -173,7 +173,7 @@ static void __attribute__((unused)) E01X_send_packet(uint8_t bind)
else
{ // E016H
packet_length=E016H_PACKET_SIZE;
if(bind)
if(IS_BIND_IN_PROGRESS)
{
rf_ch_num=E016H_BIND_CHANNEL;
memcpy(packet, &rx_tx_addr[1], 4);
@@ -244,34 +244,26 @@ static void __attribute__((unused)) E01X_send_packet(uint8_t bind)
NRF24L01_SetPower();
}
static void __attribute__((unused)) E01X_init()
static void __attribute__((unused)) E01X_RF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
if(sub_protocol==E012)
HS6200_SetTXAddr((uint8_t *)"\x55\x42\x9C\x8F\xC9", E01X_ADDRESS_LENGTH);
else if(sub_protocol==E015)
HS6200_SetTXAddr((uint8_t *)"\x62\x54\x79\x38\x53", E01X_ADDRESS_LENGTH);
else //E016H
XN297_SetTXAddr((uint8_t *)"\x5a\x53\x46\x30\x31", 5); // bind address
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_03_SETUP_AW, 0x03);
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1 Mbps
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01); // Set feature bits on
NRF24L01_Activate(0x73);
}
uint16_t E01X_callback()
{
if(IS_BIND_IN_PROGRESS)
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
if(bind_counter)
{
bind_counter--;
if (bind_counter == 0)
{
if(sub_protocol==E016H)
@@ -280,19 +272,8 @@ uint16_t E01X_callback()
HS6200_SetTXAddr(rx_tx_addr, E01X_ADDRESS_LENGTH);
BIND_DONE;
}
else
{
E01X_send_packet(1);
bind_counter--;
}
}
else
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
E01X_send_packet(0);
}
E01X_send_packet();
return packet_period;
}
@@ -322,7 +303,7 @@ static void __attribute__((unused)) E016H_initialize_txid()
}
}
uint16_t initE01X()
void E01X_init()
{
BIND_IN_PROGRESS;
if(sub_protocol==E012)
@@ -343,10 +324,9 @@ uint16_t initE01X()
E016H_initialize_txid();
packet_period=E016H_PACKET_PERIOD;
}
E01X_init();
E01X_RF_init();
bind_counter = E01X_BIND_COUNT;
hopping_frequency_no = 0;
return E01X_INITIAL_WAIT;
}
#endif

View File

@@ -0,0 +1,148 @@
/*
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 E129_callback()
{
//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)
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;
}
void E129_init()
{
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;
}
#endif

View File

@@ -23,7 +23,7 @@
#define ESKY150_BINDING_PACKET_PERIOD 2000
#define ESKY150_SENDING_PACKET_PERIOD 4800
static void __attribute__((unused)) ESKY150_init()
static void __attribute__((unused)) ESKY150_RF_init()
{
//Original TX always sets for channelx 0x22 and 0x4a
// Use channels 2..79
@@ -31,25 +31,16 @@ static void __attribute__((unused)) ESKY150_init()
hopping_frequency[1] = hopping_frequency[0] + 40;
NRF24L01_Initialize();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO)));
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x02); // 4-byte RX/TX address
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0); // Disable retransmit
NRF24L01_SetPower();
NRF24L01_SetBitrate(NRF24L01_BR_2M);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, ESKY150_PAYLOADSIZE); // bytes of data payload for pipe 0
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, ESKY150_TX_ADDRESS_SIZE);
NRF24L01_Activate(0x73);
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 1); // Dynamic payload for data pipe 0
// Enable: Dynamic Payload Length, Payload with ACK , W_TX_PAYLOAD_NOACK
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, _BV(NRF2401_1D_EN_DPL) | _BV(NRF2401_1D_EN_ACK_PAY) | _BV(NRF2401_1D_EN_DYN_ACK));
NRF24L01_Activate(0x73);
NRF24L01_FlushTx();
// Turn radio power on
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_SetTxRxMode(TX_EN); // Clear data ready, data sent, retransmit and enable CRC 16bits, ready for TX
}
static void __attribute__((unused)) ESKY150_bind_init()
@@ -171,16 +162,15 @@ uint16_t ESKY150_callback()
return ESKY150_SENDING_PACKET_PERIOD;
}
uint16_t initESKY150(void)
void ESKY150_init(void)
{
ESKY150_init();
ESKY150_RF_init();
if(IS_BIND_IN_PROGRESS)
{
bind_counter=3000;
ESKY150_bind_init();
}
hopping_frequency_no=0;
return 10000;
}
#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,12 +74,11 @@ 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()
{
if(option==0) option=1; //Trick the RF component auto select system
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
@@ -90,14 +89,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;
@@ -105,10 +104,9 @@ uint16_t ESKY150V2_callback()
return ESKY150V2_PACKET_PERIOD;
}
uint16_t initESKY150V2()
void ESKY150V2_init()
{
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 +118,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,8 +132,7 @@ uint16_t initESKY150V2()
bind_counter=100;
}
else
NRF250K_SetTXAddr(rx_tx_addr, ESKY150V2_TXID_SIZE);
return 50000;
CC2500_250K_NRF_SetTXAddr(rx_tx_addr, ESKY150V2_TXID_SIZE);
}
#endif

View File

@@ -35,14 +35,10 @@ static void __attribute__((unused)) ESKY_set_data_address()
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 4);
}
static void __attribute__((unused)) ESKY_init()
static void __attribute__((unused)) ESKY_RF_init()
{
NRF24L01_Initialize();
// 2-bytes CRC, radio off
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
if (IS_BIND_IN_PROGRESS)
{
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // 3-byte RX/TX address for bind packets
@@ -51,11 +47,7 @@ static void __attribute__((unused)) ESKY_init()
}
else
ESKY_set_data_address();
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0); // No auto retransmission
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 50); // Channel 50 for bind packets
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, ESKY_PAYLOAD_SIZE); // bytes of data payload for pipe 0
NRF24L01_WriteReg(NRF24L01_12_RX_PW_P1, ESKY_PAYLOAD_SIZE);
NRF24L01_WriteReg(NRF24L01_13_RX_PW_P2, ESKY_PAYLOAD_SIZE);
@@ -65,7 +57,7 @@ static void __attribute__((unused)) ESKY_init()
NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here
}
static void __attribute__((unused)) ESKY_init2()
static void __attribute__((unused)) ESKY_TXID_init()
{
NRF24L01_FlushTx();
if(sub_protocol==ESKY_STD)
@@ -187,7 +179,7 @@ uint16_t ESKY_callback()
return ESKY_STD_PACKET_PERIOD;
}
uint16_t initESKY(void)
void ESKY_init(void)
{
bind_counter = ESKY_BIND_COUNT;
rx_tx_addr[2] = rx_tx_addr[3]; // Model match
@@ -200,10 +192,9 @@ uint16_t initESKY(void)
}
#endif
rx_tx_addr[3] = 0xBB;
ESKY_init();
ESKY_init2();
ESKY_RF_init();
ESKY_TXID_init();
packet_count=0;
return 50000;
}
#endif

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,20 +72,20 @@ 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;
}
static void __attribute__((unused)) FQ777_send_packet(uint8_t bind)
static void __attribute__((unused)) FQ777_send_packet()
{
uint8_t packet_len = FQ777_PACKET_SIZE;
uint8_t packet_ori[8];
if (bind)
if (IS_BIND_IN_PROGRESS)
{
// 4,5,6 = address fields
// last field is checksum of address fields
@@ -144,7 +138,7 @@ static void __attribute__((unused)) FQ777_send_packet(uint8_t bind)
packet_count++;
}
ssv_pack_dpl( (0 == bind) ? rx_tx_addr : FQ777_bind_addr, hopping_frequency_no, &packet_len, packet_ori, packet);
ssv_pack_dpl( IS_BIND_IN_PROGRESS ? FQ777_bind_addr : rx_tx_addr, hopping_frequency_no, &packet_len, packet_ori, packet);
NRF24L01_WriteReg(NRF24L01_00_CONFIG,_BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]);
@@ -156,30 +150,21 @@ static void __attribute__((unused)) FQ777_send_packet(uint8_t bind)
NRF24L01_WritePayload(packet, packet_len);
}
static void __attribute__((unused)) FQ777_init()
static void __attribute__((unused)) FQ777_RF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, FQ777_bind_addr, 5);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x00);
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_SetBitrate(NRF24L01_BR_250K);
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
NRF24L01_Activate(0x73);
}
uint16_t FQ777_callback()
{
if(bind_counter!=0)
#ifdef MULTI_SYNC
telemetry_set_input_sync(FQ777_PACKET_PERIOD);
#endif
if(bind_counter)
{
FQ777_send_packet(1);
bind_counter--;
if (bind_counter == 0)
{
@@ -187,17 +172,11 @@ uint16_t FQ777_callback()
BIND_DONE;
}
}
else
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(FQ777_PACKET_PERIOD);
#endif
FQ777_send_packet(0);
}
FQ777_send_packet();
return FQ777_PACKET_PERIOD;
}
uint16_t initFQ777(void)
void FQ777_init(void)
{
BIND_IN_PROGRESS; // autobind protocol
bind_counter = FQ777_BIND_COUNT;
@@ -210,8 +189,7 @@ uint16_t initFQ777(void)
rx_tx_addr[2] = 0x00;
rx_tx_addr[3] = 0xe7;
rx_tx_addr[4] = 0x67;
FQ777_init();
return FQ777_INITIAL_WAIT;
FQ777_RF_init();
}
#endif

View File

@@ -58,23 +58,11 @@ static void __attribute__((unused)) FX816_send_packet()
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) FX816_init()
static void __attribute__((unused)) FX816_RF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc", 5);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // No retransmits
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
NRF24L01_Activate(0x73);
}
static void __attribute__((unused)) FX816_initialize_txid()
@@ -93,21 +81,20 @@ uint16_t FX816_callback()
#ifdef MULTI_SYNC
telemetry_set_input_sync(FX816_PACKET_PERIOD);
#endif
if(IS_BIND_IN_PROGRESS)
if(bind_counter)
if(--bind_counter==0)
BIND_DONE;
FX816_send_packet();
return FX816_PACKET_PERIOD;
}
uint16_t initFX816()
void FX816_init()
{
BIND_IN_PROGRESS; // autobind protocol
FX816_initialize_txid();
FX816_init();
FX816_RF_init();
hopping_frequency_no = 0;
bind_counter=FX816_BIND_COUNT;
return FX816_INITIAL_WAIT;
}
#endif

View File

@@ -88,34 +88,25 @@ static void __attribute__((unused)) FY326_send_packet(uint8_t bind)
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) FY326_init()
static void __attribute__((unused)) FY326_RF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
if(sub_protocol==FY319)
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // Five-byte rx/tx address
else
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // Three-byte rx/tx address
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x15\x59\x23\xc6\x29", 5);
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x15\x59\x23\xc6\x29", 5);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, FY326_PACKET_SIZE);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, FY326_RF_BIND_CHANNEL);
NRF24L01_SetBitrate(NRF24L01_BR_250K);
NRF24L01_SetPower();
NRF24L01_Activate(0x73);
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f);
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07);
NRF24L01_Activate(0x73);
//Switch to RX
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_FlushRx();
NRF24L01_SetTxRxMode(RX_EN);
}
@@ -209,20 +200,19 @@ static void __attribute__((unused)) FY326_initialize_txid()
hopping_frequency[i]=rx_tx_addr[0] & ~0x80;
}
uint16_t initFY326(void)
void FY326_init(void)
{
BIND_IN_PROGRESS; // autobind protocol
rxid = 0xAA;
bind_counter = FY326_BIND_COUNT;
FY326_initialize_txid();
FY326_init();
FY326_RF_init();
if(sub_protocol==FY319)
{
phase=FY319_BIND1;
}
else
phase=FY326_BIND1;
return FY326_INITIAL_WAIT;
}
#endif

View File

@@ -0,0 +1,108 @@
/*
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(FAKE_NRF24L01_INO)
#include "iface_nrf250k.h"
static void __attribute__((unused)) FAKE_send_packet()
{
for(uint8_t i=0;i<5;i++)
packet[i]=i;
NRF24L01_WriteReg(NRF24L01_07_STATUS, (_BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT)));
NRF24L01_FlushTx();
NRF24L01_WritePayload(packet, 5);
}
static void __attribute__((unused)) FAKE_init()
{
// BIND_IN_PROGRESS;
//CC2500
option=1;
XN297L_Init();
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x01); // Packet Automation Control
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x00); // Packet Automation Control
CC2500_WriteReg(CC2500_12_MDMCFG2, 0x12); // Modem Configuration
CC2500_WriteReg(CC2500_13_MDMCFG1, 0x13); // Modem Configuration
CC2500_WriteReg(CC2500_04_SYNC1, 0x11);
CC2500_WriteReg(CC2500_05_SYNC0, 0x33);
CC2500_WriteReg(CC2500_09_ADDR, 0x99);
CC2500_WriteReg(CC2500_06_PKTLEN, 10);
CC2500_SetTxRxMode(RX_EN);
CC2500_Strobe(CC2500_SIDLE);
CC2500_Strobe(CC2500_SRX);
//CC2500_SetTxRxMode(TX_EN);
XN297L_RFChannel(0);
//NRF
/* option=0;
PE1_on; //NRF24L01 antenna RF3 by default
PE2_off; //NRF24L01 antenna RF3 by default
NRF24L01_Initialize();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x7f);
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00);//0x3f); // AA on all pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3f); // Enable all pipes
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte address
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x36); // retransmit 1ms, 6 times
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 1Mbps
NRF24L01_SetPower();
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x99\x33\x11\xAA\xAA", 5); //Bind address
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x99\x33\x11\xAA\xAA", 5); //Bind address
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0);
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // Enable dynamic payload length
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Enable all features
*/
/*NRF24L01_FlushTx();
NRF24L01_SetTxRxMode(TX_EN);*/
}
uint16_t FAKE_callback()
{
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
if(len) debug("L=%d, ",len);
if(len && len < sizeof(packet_in))
{
CC2500_ReadData(packet_in, len);
debug("P:");
for(uint8_t i=0;i<len;i++)
debug(" %02X", packet_in[i]);
}
if(len) debugln("");
CC2500_Strobe(CC2500_SFRX);
CC2500_Strobe(CC2500_SIDLE);
CC2500_Strobe(CC2500_SRX);
option=0;
//FAKE_send_packet();
PE1_off; //antenna RF2
PE2_on;
/*packet[0]=0x99;
for(uint8_t i=1;i<5;i++)
packet[i]=i;
CC2500_WriteData(packet, 5);*/
return 10000;
}
uint16_t initFAKE()
{
FAKE_init();
return 5000;
}
#endif

View File

@@ -12,7 +12,7 @@
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
// Last sync with hexfet new_protocols/flysky_a7105.c dated 2015-09-28
// Last sync with hexfet new_protocols/FLYSKY_a7105.c dated 2015-09-28
#if defined(FLYSKY_A7105_INO)
@@ -53,7 +53,7 @@ enum {
const uint8_t PROGMEM V912_X17_SEQ[10] = { 0x14, 0x31, 0x40, 0x49, 0x49, // sometime first byte is 0x15 ?
0x49, 0x49, 0x49, 0x49, 0x49, };
static void __attribute__((unused)) flysky_apply_extension_flags()
static void __attribute__((unused)) FLYSKY_apply_extension_flags()
{
switch(sub_protocol)
{
@@ -129,7 +129,7 @@ static void __attribute__((unused)) flysky_apply_extension_flags()
}
}
static void __attribute__((unused)) flysky_build_packet(uint8_t init)
static void __attribute__((unused)) FLYSKY_send_packet()
{
uint8_t i;
//servodata timing range for flysky.
@@ -137,7 +137,7 @@ static void __attribute__((unused)) flysky_build_packet(uint8_t init)
//+100% =~ 0x07ca//=1994us(max)
//Center = 0x5d9//=1497us(center)
//channel order AIL;ELE;THR;RUD;CH5;CH6;CH7;CH8
packet[0] = init ? 0xaa : 0x55;
packet[0] = IS_BIND_IN_PROGRESS ? 0xaa : 0x55;
packet[1] = rx_tx_addr[3];
packet[2] = rx_tx_addr[2];
packet[3] = rx_tx_addr[1];
@@ -150,36 +150,32 @@ static void __attribute__((unused)) flysky_build_packet(uint8_t init)
packet[5 + i*2]=temp&0xFF; //low byte of servo timing(1000-2000us)
packet[6 + i*2]=(temp>>8)&0xFF; //high byte of servo timing(1000-2000us)
}
flysky_apply_extension_flags();
FLYSKY_apply_extension_flags();
A7105_SetPower();
A7105_WriteData(21, IS_BIND_IN_PROGRESS ? 0x01:hopping_frequency[hopping_frequency_no & 0x0F]);
hopping_frequency_no++;
}
uint16_t ReadFlySky()
uint16_t FLYSKY_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
#ifndef FORCE_FLYSKY_TUNING
A7105_AdjustLOBaseFreq(1);
#endif
if(IS_BIND_IN_PROGRESS)
if(bind_counter)
{
flysky_build_packet(1);
A7105_WriteData(21, 1);
bind_counter--;
if (bind_counter==0)
BIND_DONE;
}
else
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
flysky_build_packet(0);
A7105_WriteData(21, hopping_frequency[hopping_frequency_no & 0x0F]);
A7105_SetPower();
}
hopping_frequency_no++;
FLYSKY_send_packet();
return packet_period;
}
const uint8_t PROGMEM tx_channels[8][4] = {
const uint8_t PROGMEM FLYSKY_tx_channels[8][4] = {
{ 0x12, 0x34, 0x56, 0x78},
{ 0x18, 0x27, 0x36, 0x45},
{ 0x41, 0x82, 0x36, 0x57},
@@ -190,7 +186,7 @@ const uint8_t PROGMEM tx_channels[8][4] = {
{ 0x71, 0x86, 0x43, 0x52}
};
uint16_t initFlySky()
void FLYSKY_init()
{
uint8_t chanrow;
uint8_t chanoffset;
@@ -208,7 +204,7 @@ uint16_t initFlySky()
chanoffset=rx_tx_addr[3]/16;
for(uint8_t i=0;i<16;i++)
{
temp=pgm_read_byte_near(&tx_channels[chanrow>>1][i>>2]);
temp=pgm_read_byte_near(&FLYSKY_tx_channels[chanrow>>1][i>>2]);
if(i&0x02)
temp&=0x0F;
else
@@ -242,6 +238,5 @@ uint16_t initFlySky()
bind_counter = FLYSKY_BIND_COUNT;
else
bind_counter = 0;
return 2400;
}
#endif

View File

@@ -375,7 +375,6 @@ void Frsky_init_clone(void)
val=option;
CC2500_WriteReg(reg,val);
}
prev_option = option ; // Save option to monitor FSCTRL0 change
for(uint8_t i=0;i<17;i++)
{
uint8_t reg=pgm_read_byte_near(&FRSKY_common_end_cc2500_conf[i][0]);
@@ -406,7 +405,7 @@ void Frsky_init_clone(void)
{
for (uint8_t i=start+1;i<=end;i++)
packet[i]=0;
packet[start] = FrSkyX_RX_Seq << 4; //TX=8 at startup
packet[start] = FrSkyX_RX_Seq << 4;
#ifdef SPORT_SEND
if (FrSkyX_TX_IN_Seq!=0xFF)
{//RX has replied at least once
@@ -509,7 +508,7 @@ static void __attribute__((unused)) FrSkyX_set_start(uint8_t ch )
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[ch]);
}
static void __attribute__((unused)) FrSkyX_init()
static void __attribute__((unused)) FrSkyX_RF_init()
{
if(protocol==PROTO_FRSKYL)
FRSKY_init_cc2500(FRSKYL_cc2500_conf);

View File

@@ -17,12 +17,12 @@
#include "iface_cc2500.h"
static void __attribute__((unused)) frsky2way_init(uint8_t bind)
static void __attribute__((unused)) FRSKYD_RF_init()
{
FRSKY_init_cc2500(FRSKYD_cc2500_conf);
CC2500_WriteReg(CC2500_1B_AGCCTRL2, bind ? 0x43 : 0x03);
CC2500_WriteReg(CC2500_09_ADDR, bind ? 0x03 : rx_tx_addr[3]);
CC2500_WriteReg(CC2500_1B_AGCCTRL2, IS_BIND_IN_PROGRESS ? 0x43 : 0x03);
CC2500_WriteReg(CC2500_09_ADDR, IS_BIND_IN_PROGRESS ? 0x03 : rx_tx_addr[3]);
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05);
CC2500_Strobe(CC2500_SIDLE); // Go to idle...
//
@@ -32,7 +32,7 @@ static void __attribute__((unused)) frsky2way_init(uint8_t bind)
//#######END INIT########
}
static void __attribute__((unused)) frsky2way_build_bind_packet()
static void __attribute__((unused)) FRSKYD_build_bind_packet()
{
//11 03 01 d7 2d 00 00 1e 3c 5b 78 00 00 00 00 00 00 01
//11 03 01 19 3e 00 02 8e 2f bb 5c 00 00 00 00 00 00 01
@@ -57,7 +57,7 @@ static void __attribute__((unused)) frsky2way_build_bind_packet()
packet[17] = rx_tx_addr[1];
}
static void __attribute__((unused)) frsky2way_data_frame()
static void __attribute__((unused)) FRSKYD_data_frame()
{//pachet[4] is telemetry user frame counter(hub)
//11 d7 2d 22 00 01 c9 c9 ca ca 88 88 ca ca c9 ca 88 88
//11 57 12 00 00 01 f2 f2 f2 f2 06 06 ca ca ca ca 18 18
@@ -94,7 +94,7 @@ static void __attribute__((unused)) frsky2way_data_frame()
}
}
uint16_t initFrSky_2way()
void FRSKYD_init(void)
{
//FrskyD init hop
if (sub_protocol==DCLONE)
@@ -116,21 +116,20 @@ uint16_t initFrSky_2way()
packet_count=0;
if(IS_BIND_IN_PROGRESS)
{
frsky2way_init(1);
FRSKYD_RF_init();
state = FRSKY_BIND;
}
else
{
state = FRSKY_BIND_DONE;
}
return 10000;
}
uint16_t ReadFrSky_2way()
uint16_t FRSKYD_callback(void)
{
if (state < FRSKY_BIND_DONE)
{
frsky2way_build_bind_packet();
FRSKYD_build_bind_packet();
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, 0x00);
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
@@ -144,10 +143,10 @@ uint16_t ReadFrSky_2way()
}
if (state == FRSKY_BIND_DONE)
{
state = FRSKY_DATA2;
frsky2way_init(0);
counter = 0;
BIND_DONE;
FRSKYD_RF_init();
counter = 0;
state = FRSKY_DATA2;
}
else
if (state == FRSKY_DATA5)
@@ -203,14 +202,10 @@ uint16_t ReadFrSky_2way()
}
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[counter % 47]);
if ( prev_option != option )
{
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack
prev_option = option ;
}
CC2500_SetFreqOffset();
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
CC2500_Strobe(CC2500_SFRX);
frsky2way_data_frame();
FRSKYD_data_frame();
CC2500_WriteData(packet, packet[0]+1);
state++;
}

View File

@@ -137,7 +137,7 @@ static void __attribute__((unused)) FrSkyL_encode_packet(bool type)
}
}
uint16_t ReadFrSkyL()
uint16_t FRSKYL_callback()
{
static uint8_t written=0, send=0;
switch(send)
@@ -200,11 +200,7 @@ uint16_t ReadFrSkyL()
break;
case FRSKY_DATA1:
if ( prev_option != option )
{
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); //Frequency offset hack
prev_option = option ;
}
CC2500_SetFreqOffset();
FrSkyX_set_start(hopping_frequency_no);
FrSkyL_build_packet();
FrSkyL_encode_packet(true);
@@ -216,7 +212,7 @@ uint16_t ReadFrSkyL()
return 1;
}
uint16_t initFrSkyL()
void FRSKYL_init()
{
set_rx_tx_addr(MProtocol_id_master);
rx_tx_addr[1]=0x02; // ID related, hw version?
@@ -231,7 +227,7 @@ uint16_t initFrSkyL()
while(!FrSkyX_chanskip)
FrSkyX_chanskip=random(0xfefefefe)%47;
FrSkyX_init();
FrSkyX_RF_init();
//Prepare frame
memset(FrSkyL_buffer,0x00,FRSKYL_PACKET_LEN-3);
@@ -257,6 +253,5 @@ uint16_t initFrSkyL()
state = FRSKY_DATA1;
FrSkyX_initialize_data(0);
}
return 10000;
}
#endif

View File

@@ -157,7 +157,7 @@ static void __attribute__((unused)) FrSkyR9_build_EU_packet()
packet[13] = FrSkyR9_CRC8(packet, 13);
}
uint16_t initFrSkyR9()
void FRSKYR9_init()
{
//Check frequencies
#ifdef DISP_FREQ_TABLE
@@ -205,7 +205,14 @@ uint16_t initFrSkyR9()
SX1276_SetDetectionThreshold(SX1276_MODEM_DETECTION_THRESHOLD_SF6);
SX1276_SetLna(1, true);
SX1276_SetHopPeriod(0); // 0 = disabled, we hop frequencies manually
SX1276_SetPaDac(true);
//RF Power
SX1276_SetPaDac(false); // Disable 20dBm mode
#if MULTI_5IN1_INTERNAL == JP_T18
SX1276_SetPaConfig(true, 7, 0); // Lowest power for the T18: 2dBm
#else
SX1276_SetPaConfig(true, 7, option); // Use PA_HP on PA_BOOST, power=17-(15-option) dBm with option equal or lower to 15
#endif
SX1276_SetOcp(true,27); // Set OCP to max 240mA
SX1276_SetTxRxMode(TX_EN); // Set RF switch to TX
//Enable all IRQ flags
SX1276_WriteReg(SX1276_11_IRQFLAGSMASK,0x00);
@@ -213,10 +220,9 @@ uint16_t initFrSkyR9()
hopping_frequency_no=0;
phase=FRSKYR9_FREQ;
return 20000; // Start calling FrSkyR9_callback in 20 milliseconds
}
uint16_t FrSkyR9_callback()
uint16_t FRSKYR9_callback()
{
switch (phase)
{
@@ -227,8 +233,14 @@ uint16_t FrSkyR9_callback()
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
// output_power: 2 dBm ( (if pa_boost_pin == true))
#if MULTI_5IN1_INTERNAL != JP_T18
if(option != prev_option)
{ // Set RF power if it has changed
SX1276_SetPaConfig(true, 7, option); // Use PA_HP on PA_BOOST, power=17-(15-option) dBm with option equal or lower to 15
prev_option = option;
}
#endif
//Build packet
if( packet_length == 26 )
FrSkyR9_build_packet();

View File

@@ -113,7 +113,7 @@ static void __attribute__((unused)) FRSKYV_build_data_packet()
packet[14] = FRSKYV_crc8(crc8, packet, 14);
}
uint16_t ReadFRSKYV()
uint16_t FRSKYV_callback(void)
{
if(IS_BIND_DONE)
{ // Normal operation
@@ -122,11 +122,7 @@ uint16_t ReadFRSKYV()
#endif
uint8_t chan = FRSKYV_calc_channel();
CC2500_Strobe(CC2500_SIDLE);
if (option != prev_option)
{
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
prev_option=option;
}
CC2500_SetFreqOffset();
CC2500_WriteReg(CC2500_0A_CHANNR, chan * 5 + 6);
FRSKYV_build_data_packet();
@@ -152,7 +148,7 @@ uint16_t ReadFRSKYV()
return 53460;
}
uint16_t initFRSKYV()
void FRSKYV_init(void)
{
//ID is 15 bits. Using rx_tx_addr[2] and rx_tx_addr[3] since we want to use RX_Num for model match
rx_tx_addr[2]&=0x7F;
@@ -162,7 +158,6 @@ uint16_t initFRSKYV()
seed = 1;
binding_idx=0;
phase = FRSKYV_DATA1;
return 10000;
}
#endif

View File

@@ -116,7 +116,7 @@ static void __attribute__((unused)) FrSkyX_build_packet()
debugln("");*/
}
uint16_t ReadFrSkyX()
uint16_t FRSKYX_callback()
{
switch(state)
{
@@ -142,11 +142,7 @@ uint16_t ReadFrSkyX()
case FRSKY_DATA1:
CC2500_Strobe(CC2500_SIDLE);
if ( prev_option != option )
{
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); //Frequency offset hack
prev_option = option ;
}
CC2500_SetFreqOffset();
FrSkyX_set_start(hopping_frequency_no);
FrSkyX_build_packet();
if(FrSkyFormat & 2)
@@ -245,7 +241,7 @@ uint16_t ReadFrSkyX()
return 1;
}
uint16_t initFrSkyX()
void FRSKYX_init()
{
set_rx_tx_addr(MProtocol_id_master);
FrSkyFormat = sub_protocol;
@@ -272,7 +268,7 @@ uint16_t initFrSkyX()
while(!FrSkyX_chanskip)
FrSkyX_chanskip=random(0xfefefefe)%47;
FrSkyX_init();
FrSkyX_RF_init();
if(IS_BIND_IN_PROGRESS)
{
@@ -285,6 +281,5 @@ uint16_t initFrSkyX()
FrSkyX_initialize_data(0);
}
FrSkyX_telem_init();
return 10000;
}
#endif

View File

@@ -40,7 +40,7 @@ enum {
FRSKY_RX_DATA,
};
const PROGMEM uint8_t frsky_rx_common_reg[][2] = {
const PROGMEM uint8_t FRSKY_RX_common_reg[][2] = {
{CC2500_02_IOCFG0, 0x01},
{CC2500_18_MCSM0, 0x18},
{CC2500_07_PKTCTRL1, 0x05},
@@ -68,7 +68,7 @@ const PROGMEM uint8_t frsky_rx_common_reg[][2] = {
{CC2500_09_ADDR, 0x03},
};
const PROGMEM uint8_t frsky_rx_d16fcc_reg[][2] = {
const PROGMEM uint8_t FRSKY_RX_d16fcc_reg[][2] = {
{CC2500_17_MCSM1, 0x0C},
{CC2500_0E_FREQ1, 0x76},
{CC2500_0F_FREQ0, 0x27},
@@ -81,7 +81,7 @@ const PROGMEM uint8_t frsky_rx_d16fcc_reg[][2] = {
{CC2500_15_DEVIATN, 0x51},
};
const PROGMEM uint8_t frsky_rx_d16lbt_reg[][2] = {
const PROGMEM uint8_t FRSKY_RX_d16lbt_reg[][2] = {
{CC2500_17_MCSM1, 0x0E},
{CC2500_0E_FREQ1, 0x80},
{CC2500_0F_FREQ0, 0x00},
@@ -94,7 +94,7 @@ const PROGMEM uint8_t frsky_rx_d16lbt_reg[][2] = {
{CC2500_15_DEVIATN, 0x53},
};
const PROGMEM uint8_t frsky_rx_d8_reg[][2] = {
const PROGMEM uint8_t FRSKY_RX_d8_reg[][2] = {
{CC2500_17_MCSM1, 0x0C},
{CC2500_0E_FREQ1, 0x76},
{CC2500_0F_FREQ0, 0x27},
@@ -107,32 +107,32 @@ const PROGMEM uint8_t frsky_rx_d8_reg[][2] = {
{CC2500_15_DEVIATN, 0x42},
};
static uint8_t frsky_rx_chanskip;
static int8_t frsky_rx_finetune;
static uint8_t frsky_rx_format;
static uint8_t FRSKY_RX_chanskip;
static int8_t FRSKY_RX_finetune;
static uint8_t FRSKY_RX_format;
static void __attribute__((unused)) frsky_rx_strobe_rx()
static void __attribute__((unused)) FRSKY_RX_strobe_rx()
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_Strobe(CC2500_SFRX);
CC2500_Strobe(CC2500_SRX);
}
static void __attribute__((unused)) frsky_rx_initialise_cc2500() {
const uint8_t frsky_rx_length[] = { FRSKY_RX_D8_LENGTH, FRSKY_RX_D16FCC_LENGTH, FRSKY_RX_D16LBT_LENGTH, FRSKY_RX_D16v2_LENGTH, FRSKY_RX_D16v2_LENGTH };
packet_length = frsky_rx_length[frsky_rx_format];
static void __attribute__((unused)) FRSKY_RX_initialise_cc2500() {
const uint8_t FRSKY_RX_length[] = { FRSKY_RX_D8_LENGTH, FRSKY_RX_D16FCC_LENGTH, FRSKY_RX_D16LBT_LENGTH, FRSKY_RX_D16v2_LENGTH, FRSKY_RX_D16v2_LENGTH };
packet_length = FRSKY_RX_length[FRSKY_RX_format];
CC2500_Reset();
CC2500_Strobe(CC2500_SIDLE);
for (uint8_t i = 0; i < sizeof(frsky_rx_common_reg) / 2; i++)
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_common_reg[i][0]), pgm_read_byte_near(&frsky_rx_common_reg[i][1]));
for (uint8_t i = 0; i < sizeof(FRSKY_RX_common_reg) / 2; i++)
CC2500_WriteReg(pgm_read_byte_near(&FRSKY_RX_common_reg[i][0]), pgm_read_byte_near(&FRSKY_RX_common_reg[i][1]));
switch (frsky_rx_format)
switch (FRSKY_RX_format)
{
case FRSKY_RX_D16v2FCC:
case FRSKY_RX_D16FCC:
for (uint8_t i = 0; i < sizeof(frsky_rx_d16fcc_reg) / 2; i++)
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_d16fcc_reg[i][0]), pgm_read_byte_near(&frsky_rx_d16fcc_reg[i][1]));
if(frsky_rx_format==FRSKY_RX_D16v2FCC)
for (uint8_t i = 0; i < sizeof(FRSKY_RX_d16fcc_reg) / 2; i++)
CC2500_WriteReg(pgm_read_byte_near(&FRSKY_RX_d16fcc_reg[i][0]), pgm_read_byte_near(&FRSKY_RX_d16fcc_reg[i][1]));
if(FRSKY_RX_format==FRSKY_RX_D16v2FCC)
{
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Enable CRC
CC2500_WriteReg(CC2500_17_MCSM1, 0x0E); // Go/Stay in RX mode
@@ -141,36 +141,36 @@ static void __attribute__((unused)) frsky_rx_initialise_cc2500() {
break;
case FRSKY_RX_D16v2LBT:
case FRSKY_RX_D16LBT:
for (uint8_t i = 0; i < sizeof(frsky_rx_d16lbt_reg) / 2; i++)
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_d16lbt_reg[i][0]), pgm_read_byte_near(&frsky_rx_d16lbt_reg[i][1]));
if(frsky_rx_format==FRSKY_RX_D16v2LBT)
for (uint8_t i = 0; i < sizeof(FRSKY_RX_d16lbt_reg) / 2; i++)
CC2500_WriteReg(pgm_read_byte_near(&FRSKY_RX_d16lbt_reg[i][0]), pgm_read_byte_near(&FRSKY_RX_d16lbt_reg[i][1]));
if(FRSKY_RX_format==FRSKY_RX_D16v2LBT)
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Enable CRC
break;
case FRSKY_RX_D8:
for (uint8_t i = 0; i < sizeof(frsky_rx_d8_reg) / 2; i++)
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_d8_reg[i][0]), pgm_read_byte_near(&frsky_rx_d8_reg[i][1]));
for (uint8_t i = 0; i < sizeof(FRSKY_RX_d8_reg) / 2; i++)
CC2500_WriteReg(pgm_read_byte_near(&FRSKY_RX_d8_reg[i][0]), pgm_read_byte_near(&FRSKY_RX_d8_reg[i][1]));
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
break;
}
CC2500_WriteReg(CC2500_0A_CHANNR, 0); // bind channel
rx_disable_lna = IS_POWER_FLAG_on;
CC2500_SetTxRxMode(rx_disable_lna ? TXRX_OFF : RX_EN); // lna disable / enable
frsky_rx_strobe_rx();
FRSKY_RX_strobe_rx();
delayMicroseconds(1000); // wait for RX to activate
}
static void __attribute__((unused)) frsky_rx_set_channel(uint8_t channel)
static void __attribute__((unused)) FRSKY_RX_set_channel(uint8_t channel)
{
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[channel]);
if(frsky_rx_format == FRSKY_RX_D8)
if(FRSKY_RX_format == FRSKY_RX_D8)
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
CC2500_WriteReg(CC2500_25_FSCAL1, calData[channel]);
frsky_rx_strobe_rx();
FRSKY_RX_strobe_rx();
}
static void __attribute__((unused)) frsky_rx_calibrate()
static void __attribute__((unused)) FRSKY_RX_calibrate()
{
frsky_rx_strobe_rx();
FRSKY_RX_strobe_rx();
for (unsigned c = 0; c < 47; c++)
{
CC2500_Strobe(CC2500_SIDLE);
@@ -193,7 +193,7 @@ static uint8_t __attribute__((unused)) frskyx_rx_check_crc_id(bool bind,bool ini
uint8_t offset=bind?3:1;
// Check D8 checksum
if (frsky_rx_format == FRSKY_RX_D8)
if (FRSKY_RX_format == FRSKY_RX_D8)
{
if((packet[packet_length+1] & 0x80) != 0x80) // Check CRC_OK flag in status byte 2
return false; // Bad CRC
@@ -210,7 +210,7 @@ static uint8_t __attribute__((unused)) frskyx_rx_check_crc_id(bool bind,bool ini
}
// Check D16v2 checksum
if (frsky_rx_format == FRSKY_RX_D16v2LBT || frsky_rx_format == FRSKY_RX_D16v2FCC)
if (FRSKY_RX_format == FRSKY_RX_D16v2LBT || FRSKY_RX_format == FRSKY_RX_D16v2FCC)
if((packet[packet_length+1] & 0x80) != 0x80) // Check CRC_OK flag in status byte 2
return false;
//debugln("HW Checksum ok");
@@ -222,12 +222,12 @@ static uint8_t __attribute__((unused)) frskyx_rx_check_crc_id(bool bind,bool ini
return false; // Bad CRC
//debugln("Checksum ok");
if (bind && (frsky_rx_format == FRSKY_RX_D16v2LBT || frsky_rx_format == FRSKY_RX_D16v2FCC))
if (bind && (FRSKY_RX_format == FRSKY_RX_D16v2LBT || FRSKY_RX_format == FRSKY_RX_D16v2FCC))
for(uint8_t i=3; i<packet_length-2; i++) //unXOR bind packet
packet[i] ^= 0xA7;
uint8_t offset2=0;
if (bind && (frsky_rx_format == FRSKY_RX_D16LBT || frsky_rx_format == FRSKY_RX_D16FCC))
if (bind && (FRSKY_RX_format == FRSKY_RX_D16LBT || FRSKY_RX_format == FRSKY_RX_D16FCC))
offset2=6;
if(init)
{//Save TXID
@@ -248,7 +248,7 @@ static uint8_t __attribute__((unused)) frskyx_rx_check_crc_id(bool bind,bool ini
return true; // Full match
}
static void __attribute__((unused)) frsky_rx_build_telemetry_packet()
static void __attribute__((unused)) FRSKY_RX_build_telemetry_packet()
{
uint16_t raw_channel[8];
uint32_t bits = 0;
@@ -256,7 +256,7 @@ static void __attribute__((unused)) frsky_rx_build_telemetry_packet()
uint8_t idx = 0;
uint8_t i;
if (frsky_rx_format == FRSKY_RX_D8)
if (FRSKY_RX_format == FRSKY_RX_D8)
{// decode D8 channels
raw_channel[0] = ((packet[10] & 0x0F) << 8 | packet[6]);
raw_channel[1] = ((packet[10] & 0xF0) << 4 | packet[7]);
@@ -299,7 +299,7 @@ static void __attribute__((unused)) frsky_rx_build_telemetry_packet()
packet_in[idx++] = RX_LQI;
packet_in[idx++] = RX_RSSI;
packet_in[idx++] = 0; // start channel
packet_in[idx++] = frsky_rx_format == FRSKY_RX_D8 ? 8 : 16; // number of channels in packet
packet_in[idx++] = FRSKY_RX_format == FRSKY_RX_D8 ? 8 : 16; // number of channels in packet
// pack channels
for (i = 0; i < packet_in[3]; i++) {
@@ -313,29 +313,29 @@ static void __attribute__((unused)) frsky_rx_build_telemetry_packet()
}
}
static void __attribute__((unused)) frsky_rx_data()
static void __attribute__((unused)) FRSKY_RX_data()
{
uint16_t temp = FRSKY_RX_EEPROM_OFFSET;
frsky_rx_format = eeprom_read_byte((EE_ADDR)temp++) % FRSKY_RX_FORMATS;
FRSKY_RX_format = eeprom_read_byte((EE_ADDR)temp++) % FRSKY_RX_FORMATS;
rx_tx_addr[3] = eeprom_read_byte((EE_ADDR)temp++);
rx_tx_addr[2] = eeprom_read_byte((EE_ADDR)temp++);
rx_tx_addr[1] = eeprom_read_byte((EE_ADDR)temp++);
rx_tx_addr[0] = RX_num;
frsky_rx_finetune = eeprom_read_byte((EE_ADDR)temp++);
debug("format=%d, ", frsky_rx_format);
FRSKY_RX_finetune = eeprom_read_byte((EE_ADDR)temp++);
debug("format=%d, ", FRSKY_RX_format);
debug("addr[3]=%02X, ", rx_tx_addr[3]);
debug("addr[2]=%02X, ", rx_tx_addr[2]);
debug("addr[1]=%02X, ", rx_tx_addr[1]);
debug("rx_num=%02X, ", rx_tx_addr[0]);
debugln("tune=%d", (int8_t)frsky_rx_finetune);
if(frsky_rx_format != FRSKY_RX_D16v2LBT && frsky_rx_format != FRSKY_RX_D16v2FCC)
debugln("tune=%d", (int8_t)FRSKY_RX_finetune);
if(FRSKY_RX_format != FRSKY_RX_D16v2LBT && FRSKY_RX_format != FRSKY_RX_D16v2FCC)
{//D8 & D16v1
for (uint8_t ch = 0; ch < 47; ch++)
hopping_frequency[ch] = eeprom_read_byte((EE_ADDR)temp++);
}
else
{
FrSkyFormat=frsky_rx_format == FRSKY_RX_D16v2FCC?0:2;
FrSkyFormat=FRSKY_RX_format == FRSKY_RX_D16v2FCC?0:2;
FrSkyX2_init_hop();
}
debug("ch:");
@@ -343,51 +343,74 @@ static void __attribute__((unused)) frsky_rx_data()
debug(" %02X", hopping_frequency[ch]);
debugln("");
frsky_rx_initialise_cc2500();
frsky_rx_calibrate();
FRSKY_RX_initialise_cc2500();
FRSKY_RX_calibrate();
CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // FS_AUTOCAL = manual
CC2500_WriteReg(CC2500_09_ADDR, rx_tx_addr[3]); // set address
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05); // check address
if (option == 0)
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
else
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
frsky_rx_set_channel(hopping_frequency_no);
FRSKY_RX_set_channel(hopping_frequency_no);
phase = FRSKY_RX_DATA;
}
uint16_t initFrSky_Rx()
void FRSKY_RX_init()
{
frsky_rx_chanskip = 1;
hopping_frequency_no = 0;
rx_data_started = false;
frsky_rx_finetune = 0;
telemetry_link = 0;
packet_count = 0;
if (IS_BIND_IN_PROGRESS)
if(sub_protocol == FRSKY_ERASE)
{
frsky_rx_format = FRSKY_RX_D8;
frsky_rx_initialise_cc2500();
phase = FRSKY_RX_TUNE_START;
debugln("FRSKY_RX_TUNE_START");
if(IS_BIND_IN_PROGRESS)
{// Clear all cloned addresses
uint16_t addr[]={ FRSKYD_CLONE_EEPROM_OFFSET+1, FRSKYX_CLONE_EEPROM_OFFSET+1, FRSKYX2_CLONE_EEPROM_OFFSET+1 };
for(uint8_t i=0; i<3;i++)
for(uint8_t j=0; j<3;j++)
eeprom_write_byte((EE_ADDR)(addr[i]+j), 0xFF);
packet_count = 100;
}
}
else
frsky_rx_data();
return 1000;
{
FRSKY_RX_chanskip = 1;
hopping_frequency_no = 0;
rx_data_started = false;
FRSKY_RX_finetune = 0;
telemetry_link = 0;
packet_count = 0;
if (IS_BIND_IN_PROGRESS)
{
FRSKY_RX_format = FRSKY_RX_D8;
FRSKY_RX_initialise_cc2500();
phase = FRSKY_RX_TUNE_START;
debugln("FRSKY_RX_TUNE_START");
}
else
FRSKY_RX_data();
}
}
uint16_t FrSky_Rx_callback()
uint16_t FRSKY_RX_callback()
{
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(sub_protocol == FRSKY_ERASE)
{
if(packet_count)
packet_count--;
else
BIND_DONE;
return 10000; // Nothing to do...
}
if(IS_BIND_DONE && phase != FRSKY_RX_DATA)
FRSKY_RX_init(); // Abort bind
if ((prev_option != option) && (phase >= FRSKY_RX_DATA))
{
if (option == 0)
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
else
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
prev_option = option;
@@ -408,20 +431,20 @@ uint16_t FrSky_Rx_callback()
CC2500_ReadData(packet, len);
if(frskyx_rx_check_crc_id(true,true))
{
frsky_rx_finetune = -127;
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
FRSKY_RX_finetune = -127;
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
phase = FRSKY_RX_TUNE_LOW;
debugln("FRSKY_RX_TUNE_LOW");
frsky_rx_strobe_rx();
FRSKY_RX_strobe_rx();
state = 0;
return 1000;
}
}
frsky_rx_format = (frsky_rx_format + 1) % FRSKY_RX_FORMATS; // switch to next format (D8, D16FCC, D16LBT, D16v2FCC, D16v2LBT)
frsky_rx_initialise_cc2500();
frsky_rx_finetune += 10;
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
frsky_rx_strobe_rx();
FRSKY_RX_format = (FRSKY_RX_format + 1) % FRSKY_RX_FORMATS; // switch to next format (D8, D16FCC, D16LBT, D16v2FCC, D16v2LBT)
FRSKY_RX_initialise_cc2500();
FRSKY_RX_finetune += 10;
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
FRSKY_RX_strobe_rx();
return 18000;
case FRSKY_RX_TUNE_LOW:
@@ -429,18 +452,18 @@ uint16_t FrSky_Rx_callback()
{
CC2500_ReadData(packet, len);
if(frskyx_rx_check_crc_id(true,false)) {
tune_low = frsky_rx_finetune;
frsky_rx_finetune = 127;
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
tune_low = FRSKY_RX_finetune;
FRSKY_RX_finetune = 127;
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
phase = FRSKY_RX_TUNE_HIGH;
debugln("FRSKY_RX_TUNE_HIGH");
frsky_rx_strobe_rx();
FRSKY_RX_strobe_rx();
return 1000;
}
}
frsky_rx_finetune += 1;
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
frsky_rx_strobe_rx();
FRSKY_RX_finetune += 1;
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
FRSKY_RX_strobe_rx();
return 18000;
case FRSKY_RX_TUNE_HIGH:
@@ -448,9 +471,9 @@ uint16_t FrSky_Rx_callback()
{
CC2500_ReadData(packet, len);
if(frskyx_rx_check_crc_id(true,false)) {
tune_high = frsky_rx_finetune;
frsky_rx_finetune = (tune_low + tune_high) / 2;
CC2500_WriteReg(CC2500_0C_FSCTRL0, (int8_t)frsky_rx_finetune);
tune_high = FRSKY_RX_finetune;
FRSKY_RX_finetune = (tune_low + tune_high) / 2;
CC2500_WriteReg(CC2500_0C_FSCTRL0, (int8_t)FRSKY_RX_finetune);
if(tune_low < tune_high)
{
phase = FRSKY_RX_BIND;
@@ -461,13 +484,13 @@ uint16_t FrSky_Rx_callback()
phase = FRSKY_RX_TUNE_START;
debugln("FRSKY_RX_TUNE_START");
}
frsky_rx_strobe_rx();
FRSKY_RX_strobe_rx();
return 1000;
}
}
frsky_rx_finetune -= 1;
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
frsky_rx_strobe_rx();
FRSKY_RX_finetune -= 1;
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
FRSKY_RX_strobe_rx();
return 18000;
case FRSKY_RX_BIND:
@@ -475,7 +498,7 @@ uint16_t FrSky_Rx_callback()
{
CC2500_ReadData(packet, len);
if(frskyx_rx_check_crc_id(true,false)) {
if(frsky_rx_format != FRSKY_RX_D16v2LBT && frsky_rx_format != FRSKY_RX_D16v2FCC)
if(FRSKY_RX_format != FRSKY_RX_D16v2LBT && FRSKY_RX_format != FRSKY_RX_D16v2FCC)
{// D8 & D16v1
if(packet[5] <= 0x2D)
{
@@ -494,27 +517,27 @@ uint16_t FrSky_Rx_callback()
uint16_t temp = FRSKY_RX_EEPROM_OFFSET;
if(sub_protocol==FRSKY_CLONE)
{
if(frsky_rx_format==FRSKY_RX_D8)
if(FRSKY_RX_format==FRSKY_RX_D8)
temp=FRSKYD_CLONE_EEPROM_OFFSET;
else if(frsky_rx_format == FRSKY_RX_D16FCC || frsky_rx_format == FRSKY_RX_D16LBT)
else if(FRSKY_RX_format == FRSKY_RX_D16FCC || FRSKY_RX_format == FRSKY_RX_D16LBT)
temp=FRSKYX_CLONE_EEPROM_OFFSET;
else
temp=FRSKYX2_CLONE_EEPROM_OFFSET;
}
eeprom_write_byte((EE_ADDR)temp++, frsky_rx_format);
eeprom_write_byte((EE_ADDR)temp++, FRSKY_RX_format);
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[3]);
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[2]);
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[1]);
if(sub_protocol==FRSKY_RX)
eeprom_write_byte((EE_ADDR)temp++, frsky_rx_finetune);
if(frsky_rx_format != FRSKY_RX_D16v2FCC && frsky_rx_format != FRSKY_RX_D16v2LBT)
if(sub_protocol == FRSKY_RX || sub_protocol == FRSKY_CPPM) // FRSKY_RX, FRSKY_CPPM
eeprom_write_byte((EE_ADDR)temp++, FRSKY_RX_finetune);
if(FRSKY_RX_format != FRSKY_RX_D16v2FCC && FRSKY_RX_format != FRSKY_RX_D16v2LBT)
for (ch = 0; ch < 47; ch++)
eeprom_write_byte((EE_ADDR)temp++, hopping_frequency[ch]);
frsky_rx_data();
FRSKY_RX_data();
debugln("FRSKY_RX_DATA");
}
}
frsky_rx_strobe_rx();
FRSKY_RX_strobe_rx();
}
return 1000;
@@ -531,31 +554,35 @@ uint16_t FrSky_Rx_callback()
RX_RSSI += 128;
bool chanskip_valid=true;
// hop to next channel
if (frsky_rx_format != FRSKY_RX_D8)
if (FRSKY_RX_format != FRSKY_RX_D8)
{//D16v1 & D16v2
if(rx_data_started)
{
if(frsky_rx_chanskip != (((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2)))
if(FRSKY_RX_chanskip != (((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2)))
{
chanskip_valid=false; // chanskip value has changed which surely indicates a bad frame
packet_count++;
if(packet_count>5) // the TX must have changed chanskip...
frsky_rx_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); // chanskip init
FRSKY_RX_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); // chanskip init
}
else
packet_count=0;
}
else
frsky_rx_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); // chanskip init
FRSKY_RX_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); // chanskip init
}
hopping_frequency_no = (hopping_frequency_no + frsky_rx_chanskip) % 47;
frsky_rx_set_channel(hopping_frequency_no);
hopping_frequency_no = (hopping_frequency_no + FRSKY_RX_chanskip) % 47;
FRSKY_RX_set_channel(hopping_frequency_no);
if(chanskip_valid)
{
if (telemetry_link == 0)
if ((telemetry_link & 0x7F) == 0)
{ // send channels to TX
frsky_rx_build_telemetry_packet();
FRSKY_RX_build_telemetry_packet();
telemetry_link = 1;
#ifdef SEND_CPPM
if(sub_protocol == FRSKY_CPPM)
telemetry_link |= 0x80; // Disable telemetry output
#endif
}
pps_counter++;
}
@@ -579,8 +606,8 @@ uint16_t FrSky_Rx_callback()
// skip channel if no packet received in time
if (read_retry++ >= 9) {
hopping_frequency_no = (hopping_frequency_no + frsky_rx_chanskip) % 47;
frsky_rx_set_channel(hopping_frequency_no);
hopping_frequency_no = (hopping_frequency_no + FRSKY_RX_chanskip) % 47;
FRSKY_RX_set_channel(hopping_frequency_no);
if(rx_data_started)
read_retry = 0;
else

View File

@@ -14,10 +14,12 @@
*/
// 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"
//#define SFHSS_DEBUG_TIMING
#define SFHSS_COARSE 0
#define SFHSS_PACKET_LEN 13
@@ -79,7 +81,6 @@ static void __attribute__((unused)) SFHSS_rf_init()
for (uint8_t i = 0; i < 39; ++i)
CC2500_WriteReg(i, pgm_read_byte_near(&SFHSS_init_values[i]));
prev_option = option;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
CC2500_SetTxRxMode(TX_EN);
@@ -125,7 +126,7 @@ static void __attribute__((unused)) SFHSS_calc_next_chan()
// Channel values are 12-bit values between 1020 and 2020, 1520 is the middle.
// Futaba @140% is 2070...1520...970
// Values grow down and to the right.
static void __attribute__((unused)) SFHSS_build_data_packet()
static void __attribute__((unused)) SFHSS_send_packet()
{
uint16_t ch[4];
// command.bit0 is the packet number indicator: =0 -> SFHSS_DATA1, =1 -> SFHSS_DATA2
@@ -165,16 +166,14 @@ static void __attribute__((unused)) SFHSS_build_data_packet()
// 3584-4095 -> looks to be used for the throttle channel with values ranging from 880µs to 1520µs
for(uint8_t i=0;i<4;i++)
{
ch[i]=Failsafe_data[CH_AETR[ch_offset+i]];
if(ch[i]==FAILSAFE_CHANNEL_HOLD)
uint16_t val=Failsafe_data[CH_AETR[ch_offset+i]];
if(val==FAILSAFE_CHANNEL_HOLD)
ch[i]=1024;
else if(ch[i]==FAILSAFE_CHANNEL_NOPULSES)
else if(val==FAILSAFE_CHANNEL_NOPULSES)
ch[i]=0;
else
{ //Use channel value
ch[i]=(ch[i]>>1)+2560;
//if(IS_DISABLE_CH_MAP_off && ch_offset+i==CH3 && ch[i]<3072) // Throttle
// ch[i]+=1024;
ch[i] = convert_channel_16b_nolimit(CH_AETR[ch_offset+i],3571,2571,true); //3472,2672: not enough throw
}
}
}
@@ -182,7 +181,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);
}
@@ -203,15 +202,17 @@ static void __attribute__((unused)) SFHSS_build_data_packet()
packet[10] = (ch[2] << 7) | ((ch[3] >> 5) & 0x7F );
packet[11] = (ch[3] << 3) | ((fhss_code >> 2) & 0x07 );
packet[12] = (fhss_code << 6) | command;
}
static void __attribute__((unused)) SFHSS_send_packet()
{
CC2500_WriteData(packet, SFHSS_PACKET_LEN);
}
uint16_t ReadSFHSS()
uint16_t SFHSS_callback()
{
#ifdef SFHSS_DEBUG_TIMING
static uint16_t prev_adjust_timing=1024;
uint16_t adjust_timing = (Channel_data[CH15]>>3) - (1024>>3); // +-102 @ 100%
#endif
switch(phase)
{
case SFHSS_START:
@@ -238,16 +239,27 @@ uint16_t ReadSFHSS()
#ifdef MULTI_SYNC
telemetry_set_input_sync(6800);
#endif
SFHSS_build_data_packet();
SFHSS_send_packet();
phase = SFHSS_DATA2;
#ifdef SFHSS_DEBUG_TIMING
return SFHSS_DATA2_TIMING - adjust_timing;
#else
return SFHSS_DATA2_TIMING; // original 1650
#endif
case SFHSS_DATA2:
SFHSS_build_data_packet();
SFHSS_send_packet();
SFHSS_calc_next_chan();
phase = SFHSS_TUNE;
return (SFHSS_PACKET_PERIOD -2000 -SFHSS_DATA2_TIMING); // original 2000
#ifdef SFHSS_DEBUG_TIMING
if(prev_adjust_timing != adjust_timing)
{
debugln("A:%d",(uint16_t)(SFHSS_DATA2_TIMING - adjust_timing));
prev_adjust_timing = adjust_timing;
}
return SFHSS_PACKET_PERIOD -2000 -(SFHSS_DATA2_TIMING - adjust_timing);
#else
return SFHSS_PACKET_PERIOD -2000 -SFHSS_DATA2_TIMING; // original 2000
#endif
case SFHSS_TUNE:
phase = SFHSS_DATA1;
SFHSS_tune_freq();
@@ -288,7 +300,7 @@ static void __attribute__((unused)) SFHSS_get_tx_id()
rx_tx_addr[1] = fixed_id >> 0;
}
uint16_t initSFHSS()
void SFHSS_init()
{
BIND_DONE; // Not a TX bind protocol
SFHSS_get_tx_id();
@@ -297,7 +309,6 @@ uint16_t initSFHSS()
SFHSS_rf_init();
phase = SFHSS_START;
return 10000;
}
#endif

View File

@@ -14,7 +14,7 @@ Multiprotocol is distributed in the hope that it will be useful,
*/
// Compatible with GD005 C-17 and GD006 DA62 planes.
#if defined(GD00X_NRF24L01_INO)
#if defined(GD00X_CCNRF_INO)
#include "iface_nrf250k.h"
@@ -127,7 +127,7 @@ static void __attribute__((unused)) GD00X_send_packet()
XN297L_SetFreqOffset(); // Set frequency offset
}
static void __attribute__((unused)) GD00X_init()
static void __attribute__((unused)) GD00X_RF_init()
{
XN297L_Init();
if(sub_protocol==GD_V1)
@@ -204,28 +204,27 @@ static void __attribute__((unused)) GD00X_initialize_txid()
uint16_t GD00X_callback()
{
if(IS_BIND_IN_PROGRESS)
if(--bind_counter==0)
BIND_DONE;
GD00X_send_packet();
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
if(bind_counter)
if(--bind_counter==0)
BIND_DONE;
GD00X_send_packet();
return packet_period;
}
uint16_t initGD00X()
void GD00X_init()
{
BIND_IN_PROGRESS; // autobind protocol
GD00X_initialize_txid();
GD00X_init();
GD00X_RF_init();
hopping_frequency_no = 0;
bind_counter=GD00X_BIND_COUNT;
packet_period=sub_protocol==GD_V1?GD00X_PACKET_PERIOD:GD00X_V2_BIND_PACKET_PERIOD;
packet_length=sub_protocol==GD_V1?GD00X_PAYLOAD_SIZE:GD00X_V2_PAYLOAD_SIZE;
packet_count=0;
len=0;
return GD00X_INITIAL_WAIT;
}
#endif

View File

@@ -32,10 +32,10 @@ enum {
GW008_DATA
};
static void __attribute__((unused)) GW008_send_packet(uint8_t bind)
static void __attribute__((unused)) GW008_send_packet()
{
packet[0] = rx_tx_addr[0];
if(bind)
if(IS_BIND_IN_PROGRESS)
{
packet[1] = 0x55;
packet[2] = hopping_frequency[0];
@@ -65,7 +65,7 @@ static void __attribute__((unused)) GW008_send_packet(uint8_t bind)
// Power on, TX mode, CRC enabled
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? GW008_RF_BIND_CHANNEL : hopping_frequency[(hopping_frequency_no++)/2]);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? GW008_RF_BIND_CHANNEL : hopping_frequency[(hopping_frequency_no++)/2]);
hopping_frequency_no %= 8;
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
@@ -75,26 +75,13 @@ static void __attribute__((unused)) GW008_send_packet(uint8_t bind)
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) GW008_init()
static void __attribute__((unused)) GW008_RF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
XN297_SetRXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01);
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, GW008_PAYLOAD_SIZE+2); // payload + 2 bytes for pcf
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_SetBitrate(NRF24L01_BR_1M);
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01); // Set feature bits on
NRF24L01_Activate(0x73);
}
static void __attribute__((unused)) GW008_initialize_txid()
@@ -123,7 +110,7 @@ uint16_t GW008_callback()
{
NRF24L01_SetTxRxMode(TXRX_OFF);
NRF24L01_SetTxRxMode(TX_EN);
GW008_send_packet(1);
GW008_send_packet();
phase = GW008_BIND2;
return 850; // minimum value 750 for STM32
}
@@ -142,20 +129,19 @@ uint16_t GW008_callback()
#ifdef MULTI_SYNC
telemetry_set_input_sync(GW008_PACKET_PERIOD);
#endif
GW008_send_packet(0);
GW008_send_packet();
break;
}
return GW008_PACKET_PERIOD;
}
uint16_t initGW008()
void GW008_init()
{
BIND_IN_PROGRESS; // autobind protocol
GW008_initialize_txid();
phase = GW008_BIND1;
GW008_init();
GW008_RF_init();
hopping_frequency_no = 0;
return GW008_INITIAL_WAIT;
}
#endif

View File

@@ -50,7 +50,7 @@ enum H8_3D_FLAGS_2 {
H8_3D_FLAG_CAM_UP = 0x04,
};
static void __attribute__((unused)) H8_3D_send_packet(uint8_t bind)
static void __attribute__((unused)) H8_3D_send_packet()
{
if(sub_protocol==H20H)
packet[0] = 0x14;
@@ -63,7 +63,7 @@ static void __attribute__((unused)) H8_3D_send_packet(uint8_t bind)
packet[4] = rx_tx_addr[3];
packet[8] = rx_tx_addr[0]+rx_tx_addr[1]+rx_tx_addr[2]+rx_tx_addr[3]; // txid checksum
memset(&packet[9], 0, 10);
if (bind)
if (IS_BIND_IN_PROGRESS)
{
packet[5] = 0x00;
packet[6] = 0x00;
@@ -127,13 +127,13 @@ static void __attribute__((unused)) H8_3D_send_packet(uint8_t bind)
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
if(sub_protocol!=H20H)
{ // H8_3D, H20MINI, H30MINI
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? hopping_frequency[0] : hopping_frequency[hopping_frequency_no++]);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? hopping_frequency[0] : hopping_frequency[hopping_frequency_no++]);
hopping_frequency_no %= H8_3D_RF_NUM_CHANNELS;
}
else
{ //H20H
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? H20H_BIND_RF : hopping_frequency[packet_count>>3]);
if(!bind)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? H20H_BIND_RF : hopping_frequency[packet_count>>3]);
if(IS_BIND_DONE)
{
packet_count++;
if(packet_count>15)
@@ -155,47 +155,33 @@ static void __attribute__((unused)) H8_3D_send_packet(uint8_t bind)
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) H8_3D_init()
static void __attribute__((unused)) H8_3D_RF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_Initialize();
if(sub_protocol==H20H)
XN297_SetTXAddr((uint8_t *)"\xEE\xDD\xCC\xBB\x11", 5);
else // H8_3D, H20MINI, H30MINI
XN297_SetTXAddr((uint8_t *)"\xC4\x57\x09\x65\x21", 5);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
}
uint16_t H8_3D_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
H8_3D_send_packet(0);
}
else
if(bind_counter)
{
bind_counter--;
if (bind_counter == 0)
{
BIND_DONE;
packet_count=0;
}
else
{
H8_3D_send_packet(1);
bind_counter--;
}
}
#ifdef MULTI_SYNC
else
telemetry_set_input_sync(packet_period);
#endif
H8_3D_send_packet();
return packet_period;
}
@@ -238,12 +224,12 @@ static void __attribute__((unused)) H8_3D_initialize_txid()
}
}
uint16_t initH8_3D(void)
void H8_3D_init(void)
{
BIND_IN_PROGRESS; // autobind protocol
bind_counter = H8_3D_BIND_COUNT;
H8_3D_initialize_txid();
H8_3D_init();
H8_3D_RF_init();
switch(sub_protocol)
{
case H8_3D:
@@ -257,7 +243,6 @@ uint16_t initH8_3D(void)
packet_period=H20MINI_PACKET_PERIOD;
break;
}
return H8_3D_INITIAL_WAIT;
}
#endif

View File

@@ -86,7 +86,6 @@ static void __attribute__((unused)) HOTT_rf_init()
for (uint8_t i = 0; i < 39; ++i)
CC2500_WriteReg(i, pgm_read_byte_near(&HOTT_init_values[i]));
prev_option = option;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
CC2500_SetTxRxMode(TX_EN);
@@ -138,7 +137,7 @@ const uint8_t PROGMEM HOTT_hop[][HOTT_NUM_RF_CHANNELS]=
};
const uint16_t PROGMEM HOTT_hop_val[] = { 0xC06B, 0xC34A, 0xDB24, 0x8E09, 0x272E, 0x217F, 0x155B, 0xEDE8, 0x1D31, 0x0986, 0x56F7, 0x6454, 0xC42D, 0x01D2, 0xC253, 0x1180 };
static void __attribute__((unused)) HOTT_init()
static void __attribute__((unused)) HOTT_TXID_init()
{
packet[0] = pgm_read_word_near( &HOTT_hop_val[num_ch] );
packet[1] = pgm_read_word_near( &HOTT_hop_val[num_ch] )>>8;
@@ -159,7 +158,7 @@ static void __attribute__((unused)) HOTT_init()
else
{
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++)
{
@@ -172,10 +171,11 @@ static void __attribute__((unused)) HOTT_init()
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)
@@ -195,13 +195,16 @@ static void __attribute__((unused)) HOTT_prep_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
@@ -212,7 +215,7 @@ static void __attribute__((unused)) HOTT_prep_data_packet()
}
else if(failsafe_count==2)
{ // second failsafe packet=timing?
packet[3]=0x50;
packet[3] |= 0x50;
if(i==4)
val=2;
else
@@ -222,6 +225,10 @@ static void __attribute__((unused)) HOTT_prep_data_packet()
packet[i] = val;
packet[i+1] = val>>8;
}
upper ^= 0x01; // toggle between CH9..CH12 and CH13..16
packet[28] = 0x80; // no sensor
packet[29] = 0x02; // 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets, 0x01->text config menu, 0x0A->no more RX telemetry
#ifdef HOTT_FW_TELEMETRY
if(IS_BIND_DONE)
{
@@ -239,25 +246,23 @@ static void __attribute__((unused)) HOTT_prep_data_packet()
}
else
packet[28] = HoTT_SerialRX_val | 0x0F; // no button pressed
packet[29] = 0x01; // 0x01->Text config menu
}
else
packet[28] = 0x0F; // RX, no button pressed
if(sub_protocol == HOTT_SYNC)
packet[29] = ((HOTT_sensor_seq+1)<<3) | 1; // Telemetry packet sequence
else
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[29] = 0x02;
//debugln("28=%02X,29=%02X",packet[28],packet[29]);
}
//debugln("28=%02X,29=%02X",packet[28],packet[29]);
}
else
#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_WriteReg(CC2500_06_PKTLEN, HOTT_TX_PACKET_LEN);
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, packet, HOTT_TX_PACKET_LEN);
@@ -272,7 +277,7 @@ static void __attribute__((unused)) HOTT_prep_data_packet()
rf_ch_num=hopping_frequency[hopping_frequency_no];
}
uint16_t ReadHOTT()
uint16_t HOTT_callback()
{
switch(phase)
{
@@ -345,7 +350,7 @@ uint16_t ReadHOTT()
CC2500_Strobe(CC2500_SFRX);
//RX
if(packet[29] & 0xF8)
{// binary telemetry
{// Sync telemetry
CC2500_WriteReg(CC2500_04_SYNC1, 0x2C);
CC2500_WriteReg(CC2500_05_SYNC0, 0x6E);
}
@@ -374,11 +379,11 @@ uint16_t ReadHOTT()
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;
HOTT_init();
HOTT_TXID_init();
}
#ifdef HOTT_FW_TELEMETRY
else
@@ -408,8 +413,10 @@ uint16_t ReadHOTT()
packet_in[0]= packet_in[HOTT_RX_PACKET_LEN];
packet_in[1]= TX_LQI;
bool send_telem=true;
if(packet[29]==1)
HOTT_sensor_seq++; // Increment RX sequence counter
if(packet[29] & 1)
{ //Text mode
HOTT_sensor_seq %= 19; // 19 pages in Text mode
HOTT_sensor_pages = 0;
HOTT_sensor_valid = false;
packet_in[10] = 0x80; // Marking telem Text mode
@@ -419,7 +426,6 @@ uint16_t ReadHOTT()
}
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
@@ -504,10 +510,10 @@ uint16_t ReadHOTT()
return 0;
}
uint16_t initHOTT()
void HOTT_init()
{
num_ch=random(0xfefefefe)%16;
HOTT_init();
HOTT_TXID_init();
HOTT_rf_init();
#ifdef HOTT_FW_TELEMETRY
HoTT_SerialRX_val=0;
@@ -521,8 +527,8 @@ uint16_t initHOTT()
packet_count=0;
state=HOTT_SENSOR_SEARCH_PERIOD;
#endif
packet_sent = 0;
phase = HOTT_START;
return 10000;
}
#endif

View File

@@ -41,7 +41,7 @@ static void __attribute__((unused)) HEIGHT_build_packet()
}
}
uint16_t ReadHeight()
uint16_t HEIGHT_callback()
{
#ifndef FORCE_HEIGHT_TUNING
A7105_AdjustLOBaseFreq(1);
@@ -78,7 +78,7 @@ uint16_t ReadHeight()
return 1500;
}
uint16_t initHeight()
void HEIGHT_init()
{
A7105_Init();
@@ -94,7 +94,6 @@ uint16_t initHeight()
phase=255;
bind_counter = HEIGHT_BIND_COUNT;
return 2400;
}
#endif
// Normal packet is 8 bytes: 0xA5 0xAF 0x59 0x84 0x7A 0x00 0x80 0xFF

View File

@@ -24,44 +24,7 @@
//
uint8_t bind_buf_arry[4][10];
// HiSky protocol uses TX id as an address for nRF24L01, and uses frequency hopping sequence
// which does not depend on this id and is passed explicitly in binding sequence. So we are free
// to generate this sequence as we wish. It should be in the range [02..77]
static void __attribute__((unused)) calc_fh_channels()
{
uint8_t idx = 0;
uint32_t rnd = MProtocol_id;
while (idx < HISKY_FREQUENCE_NUM)
{
uint8_t i;
uint8_t count_2_26 = 0, count_27_50 = 0, count_51_74 = 0;
rnd = rnd * 0x0019660D + 0x3C6EF35F; // Randomization
// Use least-significant byte. 73 is prime, so channels 76..77 are unused
uint8_t next_ch = ((rnd >> 8) % 73) + 2;
// Keep the distance 2 between the channels - either odd or even
if (((next_ch ^ (uint8_t)rx_tx_addr[3]) & 0x01 )== 0)
continue;
// Check that it's not duplicated and spread uniformly
for (i = 0; i < idx; i++) {
if(hopping_frequency[i] == next_ch)
break;
if(hopping_frequency[i] <= 26)
count_2_26++;
else if (hopping_frequency[i] <= 50)
count_27_50++;
else
count_51_74++;
}
if (i != idx)
continue;
if ( (next_ch <= 26 && count_2_26 < 8) || (next_ch >= 27 && next_ch <= 50 && count_27_50 < 8) || (next_ch >= 51 && count_51_74 < 8) )
hopping_frequency[idx++] = next_ch;//find hopping frequency
}
}
static void __attribute__((unused)) build_binding_packet(void)
static void __attribute__((unused)) HISKY_build_binding_packet(void)
{
uint8_t i;
uint16_t sum=0;
@@ -95,28 +58,21 @@ static void __attribute__((unused)) build_binding_packet(void)
}
}
static void __attribute__((unused)) hisky_init()
static void __attribute__((unused)) HISKY_RF_init()
{
NRF24L01_Initialize();
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable p0 rx
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address (byte -2)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 81); // binding packet must be set in channel 81
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 10); // payload size = 10
if(sub_protocol==HK310)
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
else
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower(); // Set power
NRF24L01_SetTxRxMode(TX_EN); // TX mode, 2-bytes CRC, radio on
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
}
// HiSky channel sequence: AILE ELEV THRO RUDD GEAR PITCH, channel data value is from 0 to 1000
// Channel 7 - Gyro mode, 0 - 6 axis, 3 - 3 axis
static void __attribute__((unused)) build_ch_data()
static void __attribute__((unused)) HISKY_build_ch_data()
{
uint16_t temp;
uint8_t i,j;
@@ -133,7 +89,7 @@ static void __attribute__((unused)) build_ch_data()
}
}
uint16_t hisky_cb()
uint16_t HISKY_callback()
{
phase++;
if(sub_protocol==HK310)
@@ -223,7 +179,7 @@ uint16_t hisky_cb()
#ifdef MULTI_SYNC
telemetry_set_input_sync(9000);
#endif
build_ch_data();
HISKY_build_ch_data();
break;
case 8:
break;
@@ -236,7 +192,7 @@ uint16_t hisky_cb()
return 1000; // send 1 binding packet and 1 data packet per 9ms
}
static void __attribute__((unused)) initialize_tx_id()
static void __attribute__((unused)) HISKY_initialize_tx_id()
{
//Generate frequency hopping table
if(sub_protocol==HK310)
@@ -248,14 +204,17 @@ static void __attribute__((unused)) initialize_tx_id()
hopping_frequency[i]=hopping_frequency_no++; // Sequential order hop channels...
}
else
calc_fh_channels();
calc_fh_channels(HISKY_FREQUENCE_NUM);
// HiSky air protocol uses TX id as an address for nRF24L01, and uses frequency hopping sequence
// which does not depend on this id and is passed explicitly in binding sequence. So we are free
// to generate this sequence as we wish. It should be in the range [02..77]
}
uint16_t initHiSky()
void HISKY_init()
{
initialize_tx_id();
build_binding_packet();
hisky_init();
HISKY_initialize_tx_id();
HISKY_build_binding_packet();
HISKY_RF_init();
phase = 0;
hopping_frequency_no = 0;
binding_idx = 0;
@@ -264,7 +223,6 @@ uint16_t initHiSky()
bind_counter = HISKY_BIND_COUNT;
else
bind_counter = 0;
return 1000;
}
#endif

View File

@@ -54,7 +54,6 @@ static void __attribute__((unused)) HITEC_CC2500_init()
for (uint8_t i = 0; i < 39; ++i)
CC2500_WriteReg(i, pgm_read_byte_near(&HITEC_init_values[i]));
prev_option = option;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
CC2500_SetTxRxMode(TX_EN);
@@ -165,7 +164,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;
}
@@ -220,7 +219,7 @@ static void __attribute__((unused)) HITEC_send_packet()
packet[23] >>= 1; // packet sequence
}
uint16_t ReadHITEC()
uint16_t HITEC_callback()
{
switch(phase)
{
@@ -390,7 +389,7 @@ uint16_t ReadHITEC()
return 0;
}
uint16_t initHITEC()
void HITEC_init()
{
HITEC_RF_channels();
#ifdef HITEC_FORCE_ID // ID and channels taken from dump
@@ -400,7 +399,6 @@ uint16_t initHITEC()
memcpy((void *)hopping_frequency,(void *)"\x00\x3A\x4A\x32\x0C\x58\x2A\x10\x26\x20\x08\x60\x68\x70\x78\x80\x88\x56\x5E\x66\x6E",HITEC_NUM_FREQUENCE);
#endif
phase = HITEC_START;
return 10000;
}
/* Full telemetry

View File

@@ -34,37 +34,13 @@ enum{
HONTAI_FLAG_CALIBRATE = 0x20,
};
// proudly swiped from http://www.drdobbs.com/implementing-the-ccitt-cyclical-redundan/199904926
#define HONTAI_POLY 0x8408
static void __attribute__((unused)) crc16(uint8_t *data_p, uint8_t length)
static void __attribute__((unused)) HONTAI_send_packet()
{
uint16_t crc = 0xffff;
length -= 2;
do
{
for (uint8_t i = 0, data = (uint8_t)*data_p++;
i < 8;
i++, data >>= 1)
{
if ((crc & 0x01) ^ (data & 0x01))
crc = (crc >> 1) ^ HONTAI_POLY;
else
crc >>= 1;
}
} while (--length);
crc = ~crc;
*data_p++ = crc & 0xff;
*data_p = crc >> 8;
}
static void __attribute__((unused)) HONTAI_send_packet(uint8_t bind)
{
if (bind)
if (IS_BIND_IN_PROGRESS)
{
memcpy(packet, rx_tx_addr, 5);
memset(&packet[5], 0, 3);
packet_length = HONTAI_BIND_PACKET_SIZE;
}
else
{
@@ -125,8 +101,16 @@ static void __attribute__((unused)) HONTAI_send_packet(uint8_t bind)
packet[6] |= GET_FLAG(CH9_SW, 0x40); // Headless
break;
}
packet_length = HONTAI_PACKET_SIZE;
}
crc16(packet, bind ? HONTAI_BIND_PACKET_SIZE:HONTAI_PACKET_SIZE);
// CRC 16 bits reflected in and out
crc=0xFFFF;
for(uint8_t i=0; i< packet_length-2; i++)
crc16_update(bit_reverse(packet[i]),8);
crc ^= 0xFFFF;
packet[packet_length-2]=bit_reverse(crc>>8);
packet[packet_length-1]=bit_reverse(crc);
// Power on, TX mode, 2byte CRC
if(sub_protocol == JJRCX1)
@@ -134,51 +118,37 @@ static void __attribute__((unused)) HONTAI_send_packet(uint8_t bind)
else
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? HONTAI_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no++]);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? HONTAI_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no++]);
hopping_frequency_no %= 3;
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
if(sub_protocol == JJRCX1)
NRF24L01_WritePayload(packet, bind ? HONTAI_BIND_PACKET_SIZE:HONTAI_PACKET_SIZE);
NRF24L01_WritePayload(packet, packet_length);
else
XN297_WritePayload(packet, bind ? HONTAI_BIND_PACKET_SIZE:HONTAI_PACKET_SIZE);
XN297_WritePayload(packet, packet_length);
NRF24L01_SetPower();
}
static void __attribute__((unused)) HONTAI_init()
static void __attribute__((unused)) HONTAI_RF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
if(sub_protocol == JJRCX1)
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\xd2\xb5\x99\xb3\x4a", 5);
else
XN297_SetTXAddr((const uint8_t*)"\xd2\xb5\x99\xb3\x4a", 5);
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_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
if(sub_protocol == JJRCX1)
{
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0xff); // JJRC uses dynamic payload length
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // match other stock settings even though AA disabled...
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07);
}
else
{
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x00);
}
NRF24L01_Activate(0x73); // Deactivate feature register
NRF24L01_SetTxRxMode(TX_EN); // Clear data ready, data sent, retransmit and enable CRC 16bits, ready for TX
}
const uint8_t PROGMEM HONTAI_hopping_frequency_nonels[][3] = {
@@ -231,9 +201,11 @@ static void __attribute__((unused)) HONTAI_initialize_txid()
uint16_t HONTAI_callback()
{
if(bind_counter!=0)
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
if(bind_counter)
{
HONTAI_send_packet(1);
bind_counter--;
if (bind_counter == 0)
{
@@ -241,24 +213,16 @@ uint16_t HONTAI_callback()
BIND_DONE;
}
}
else
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
HONTAI_send_packet(0);
}
HONTAI_send_packet();
return packet_period;
}
uint16_t initHONTAI()
void HONTAI_init()
{
BIND_IN_PROGRESS; // autobind protocol
bind_counter = HONTAI_BIND_COUNT;
HONTAI_initialize_txid();
HONTAI_init();
HONTAI_RF_init();
packet_period = sub_protocol == FQ777_951 ? FQ777_951_PACKET_PERIOD : HONTAI_PACKET_PERIOD;
return HONTAI_INITIAL_WAIT;
}
#endif

View File

@@ -285,7 +285,7 @@ static uint8_t __attribute__((unused)) hubsan_check_integrity()
}
#endif
uint16_t ReadHubsan()
uint16_t HUBSAN_callback()
{
#ifdef HUBSAN_HUB_TELEMETRY
static uint8_t rfMode=0;
@@ -446,7 +446,7 @@ uint16_t ReadHubsan()
return 0;
}
uint16_t initHubsan()
void HUBSAN_init()
{
const uint8_t allowed_ch[] = {0x14, 0x1e, 0x28, 0x32, 0x3c, 0x46, 0x50, 0x5a, 0x64, 0x6e, 0x78, 0x82};
A7105_Init();
@@ -467,7 +467,6 @@ uint16_t initHubsan()
}
packet_count=0;
bind_phase=0;
return 10000;
}
#endif

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);
@@ -126,7 +126,7 @@ static void __attribute__((unused)) j6pro_set_radio_channels()
hopping_frequency[3] = hopping_frequency[0];
}
uint16_t ReadJ6Pro()
uint16_t J6PRO_callback()
{
uint16_t start;
@@ -226,7 +226,7 @@ uint16_t ReadJ6Pro()
return 0;
}
uint16_t initJ6Pro()
void J6PRO_init()
{
j6pro_cyrf_init();
@@ -234,7 +234,6 @@ uint16_t initJ6Pro()
phase = J6PRO_BIND;
else
phase = J6PRO_CHANSEL;
return 2400;
}
#endif

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
@@ -119,19 +130,12 @@ static void __attribute__((unused)) JJRC345_send_packet()
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) JJRC345_init()
static void __attribute__((unused)) JJRC345_RF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, JJRC345_RF_BIND_CHANNEL); // Bind channel
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1 Mbps
NRF24L01_SetPower();
NRF24L01_WriteReg(NRF24L01_05_RF_CH, sub_protocol == JJRC345 ? JJRC345_RF_BIND_CHANNEL:SKYTMBLR_RF_BIND_CHANNEL); // Bind channel
}
uint16_t JJRC345_callback()
@@ -139,11 +143,10 @@ uint16_t JJRC345_callback()
#ifdef MULTI_SYNC
telemetry_set_input_sync(JJRC345_PACKET_PERIOD);
#endif
if(IS_BIND_IN_PROGRESS)
if(bind_counter)
{
if (bind_counter)
bind_counter--;
else
bind_counter--;
if (bind_counter==0)
BIND_DONE;
}
JJRC345_send_packet();
@@ -172,13 +175,12 @@ static void __attribute__((unused)) JJRC345_initialize_txid()
#endif
}
uint16_t initJJRC345(void)
void JJRC345_init(void)
{
BIND_IN_PROGRESS; // autobind protocol
bind_counter = JJRC345_BIND_COUNT;
JJRC345_initialize_txid();
JJRC345_init();
return JJRC345_INITIAL_WAIT;
JJRC345_RF_init();
}
#endif

View File

@@ -0,0 +1,115 @@
/*
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(JOYSWAY_A7105_INO)
#include "iface_a7105.h"
//#define JOYSWAY_FORCE_ID
static void __attribute__((unused)) JOYSWAY_send_packet()
{
static uint8_t next_ch = 0x30;
//RF frequency
if (packet_count == 254)
{
packet_count = 0;
A7105_WriteID(0x5475c52a);
rf_ch_num = 0x0a;
}
else if (packet_count == 2)
{
A7105_WriteID(MProtocol_id);
rf_ch_num = 0x30;
}
else
{
if (packet_count & 0x01)
rf_ch_num = 0x30;
else
rf_ch_num = next_ch;
}
if (! (packet_count & 0x01))
{
next_ch++;
if (next_ch >= 0x45)
next_ch = 0x30;
}
//Payload
packet[0] = packet_count == 0 ? 0xdd : 0xff;
//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];
packet[5] = 0x00;
//Channels
for (uint8_t i = 0; i < 4; i++)
packet[ 6 + (i & 0x01) + ((i & 0x02)<<1)] = convert_channel_16b_limit(i, 0x00, 0xCC);
packet[8] = 0x64;
packet[9] = 0x64;
packet[12] = 0x64;
packet[13] = 0x64;
packet[14] = packet_count == 0 ? 0x30 : 0xaa;
//Check
uint8_t value = 0;
for (uint8_t i = 0; i < 15; i++)
value += packet[i];
packet[15] = value;
//Send
#if 0
debug("ch=%02X P=",rf_ch_num);
for(uint8_t i=0; i<16; i++)
debug("%02X ", packet[i]);
debugln("");
#endif
A7105_WriteData(16, rf_ch_num);
A7105_SetPower();
packet_count++;
}
uint16_t JOYSWAY_callback()
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(6000);
#endif
#ifndef FORCE_JOYSWAY_TUNING
A7105_AdjustLOBaseFreq(1);
#endif
JOYSWAY_send_packet();
return 6000;
}
void JOYSWAY_init()
{
BIND_DONE; // not a bind protocol
MProtocol_id &= 0x00FFFFFF;
MProtocol_id |= 0xF8000000;
#ifdef JOYSWAY_FORCE_ID
MProtocol_id = 0xf82dcaa0;
#endif
set_rx_tx_addr(MProtocol_id);
A7105_Init();
packet_count = 2;
}
#endif

View File

@@ -14,7 +14,7 @@ Multiprotocol is distributed in the hope that it will be useful,
*/
// Compatible with KF606 plane.
#if defined(KF606_NRF24L01_INO)
#if defined(KF606_CCNRF_INO)
#include "iface_nrf250k.h"
@@ -76,7 +76,7 @@ static void __attribute__((unused)) KF606_initialize_txid()
#endif
}
static void __attribute__((unused)) KF606_init()
static void __attribute__((unused)) KF606_RF_init()
{
XN297L_Init();
XN297L_SetTXAddr((uint8_t*)"\xe7\xe7\xe7\xe7\xe7", 5);
@@ -89,24 +89,23 @@ uint16_t KF606_callback()
#ifdef MULTI_SYNC
telemetry_set_input_sync(KF606_PACKET_PERIOD);
#endif
if(IS_BIND_IN_PROGRESS)
if(bind_counter)
if(--bind_counter==0)
{
BIND_DONE;
XN297_SetTXAddr(rx_tx_addr, 3);
XN297L_SetTXAddr(rx_tx_addr, 3);
}
KF606_send_packet();
return KF606_PACKET_PERIOD;
}
uint16_t initKF606()
void KF606_init()
{
BIND_IN_PROGRESS; // autobind protocol
KF606_initialize_txid();
KF606_init();
KF606_RF_init();
hopping_frequency_no = 0;
bind_counter=KF606_BIND_COUNT;
return KF606_INITIAL_WAIT;
}
#endif

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
@@ -239,40 +239,25 @@ static void __attribute__((unused)) kn_calculate_freqency_hopping_channels()
// V977 needs payload length in the packet. We should configure 24L01 to enable Packet Control Field(PCF)
// Some RX reg settings are actually for enable PCF
//-------------------------------------------------------------------------------------------------
static void __attribute__((unused)) kn_init()
static void __attribute__((unused)) KN_RF_init()
{
kn_calculate_tx_addr();
kn_calculate_freqency_hopping_channels();
NRF24L01_Initialize();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0); // Disable retransmit
NRF24L01_SetPower();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 0x20); // bytes of data payload for pipe 0
NRF24L01_Activate(0x73);
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 1); // Dynamic payload for data pipe 0
// Enable: Dynamic Payload Length to enable PCF
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, _BV(NRF2401_1D_EN_DPL));
NRF24L01_SetPower();
NRF24L01_FlushTx();
// Turn radio power on
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_SetBitrate(NRF24L01_BR_1M); //USE1MBPS_YES ? NRF24L01_BR_1M : NRF24L01_BR_250K;
NRF24L01_SetTxRxMode(TX_EN); // Clear data ready, data sent, retransmit and enable CRC 16bits, ready for TX
}
//================================================================================================
// Private Functions
//================================================================================================
uint16_t initKN()
void KN_init()
{
if(sub_protocol==WLTOYS)
{
@@ -288,13 +273,11 @@ uint16_t initKN()
packet_count = KN_FX_PACKET_SEND_COUNT;
seed = KN_FX_PACKET_SEND_COUNT * KN_FX_SENDING_PACKET_PERIOD;
}
kn_init();
KN_RF_init();
phase = IS_BIND_IN_PROGRESS ? KN_PHASE_PRE_BIND : KN_PHASE_PRE_SEND;
return KN_INIT_WAIT_MS;
}
uint16_t kn_callback()
uint16_t KN_callback()
{
switch (phase)
{

View File

@@ -17,12 +17,13 @@
#include "iface_a7105.h"
//#define KYOSHO_FORCE_ID
//#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()
static void __attribute__((unused)) KYOSHO_send_packet()
{
//ID
packet[1] = rx_tx_addr[0];
@@ -67,14 +68,63 @@ static void __attribute__((unused)) kyosho_send_packet()
packet[36] |= (hopping_frequency_no&0xF0); // last byte is ending with F on the dumps so let's see
hopping_frequency_no &= 0x1F;
}
// debug("ch=%02X P=",rf_ch_num);
// for(uint8_t i=0; i<37; i++)
// debug("%02X ", packet[i]);
// debugln("");
#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);
}
uint16_t ReadKyosho()
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 KYOSHO_callback()
{
#ifndef FORCE_KYOSHO_TUNING
A7105_AdjustLOBaseFreq(1);
@@ -83,34 +133,69 @@ uint16_t ReadKyosho()
{
bind_counter--;
if (bind_counter==0)
{
BIND_DONE;
if(sub_protocol==KYOSHO_HYPE)
{
A7105_WriteID(MProtocol_id);
A7105_WriteReg(A7105_03_FIFOI,0x05);
}
}
}
else
{
A7105_SetPower();
if(hopping_frequency_no==0)
A7105_SetPower();
#ifdef MULTI_SYNC
telemetry_set_input_sync(3852);
telemetry_set_input_sync(packet_period);
#endif
}
kyosho_send_packet();
return 3852;
if(sub_protocol==KYOSHO_FHSS)
KYOSHO_send_packet();
else//HYPE
KYOSHO_hype_send_packet();
return packet_period;
}
uint16_t initKyosho()
void KYOSHO_init()
{
A7105_Init();
// compute 32 channels from ID
calc_fh_channels(32);
// compute channels from ID
calc_fh_channels(sub_protocol==KYOSHO_FHSS?32:15);
hopping_frequency_no=0;
#ifdef KYOSHO_FORCE_ID
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);
#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;
return 2000;
packet_sent=0;
packet_period=3852; //FHSS
}
#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(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_RF_init()
{
NRF24L01_Initialize();
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"LOVE!", 5);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"LOVE!", 5);
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, LOLI_PACKET_SIZE); // RX FIFO size
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
}
// 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)
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;
}
void LOLI_init()
{
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_RF_init();
}
#endif

View File

@@ -223,7 +223,7 @@ static void __attribute__((unused)) MJXQ_send_packet(uint8_t bind)
hopping_frequency_no %= 2 * MJXQ_RF_NUM_CHANNELS; // channels repeated
}
static void __attribute__((unused)) MJXQ_init()
static void __attribute__((unused)) MJXQ_RF_init()
{
uint8_t addr[MJXQ_ADDRESS_LENGTH];
memcpy(addr, "\x6d\x6a\x77\x77\x77", MJXQ_ADDRESS_LENGTH);
@@ -246,25 +246,15 @@ static void __attribute__((unused)) MJXQ_init()
else
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
if (sub_protocol == H26D || sub_protocol == H26WH)
{
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr, MJXQ_ADDRESS_LENGTH);
}
else
XN297_SetTXAddr(addr, MJXQ_ADDRESS_LENGTH);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, MJXQ_PACKET_SIZE);
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
}
}
@@ -350,14 +340,13 @@ uint16_t MJXQ_callback()
return MJXQ_PACKET_PERIOD;
}
uint16_t initMJXQ(void)
void MJXQ_init(void)
{
BIND_IN_PROGRESS; // autobind protocol
bind_counter = MJXQ_BIND_COUNT;
MJXQ_initialize_txid();
MJXQ_init();
MJXQ_RF_init();
packet_count=0;
return MJXQ_INITIAL_WAIT+MJXQ_PACKET_PERIOD;
}
#endif

View File

@@ -0,0 +1,608 @@
/*
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"
//#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_SEND2,
MLINK_SEND3,
MLINK_CHECK3,
MLINK_RX,
MLINK_BUILD4,
};
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_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 0
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_send_data_packet()
{
static uint8_t tog=0;
uint8_t start;
#ifdef FAILSAFE_ENABLE
static uint8_t fs=0;
if(IS_FAILSAFE_VALUES_on && phase==MLINK_SEND1)
{
fs=10; // Original radio is sending 70 packets
FAILSAFE_VALUES_off;
}
if(fs)
{// Failsafe packets
switch(phase)
{
case MLINK_SEND2:
packet[0]=0x06;
start=17;
break;
case MLINK_SEND3:
packet[0]=0x84;
start=5;
fs--;
break;
default: //MLINK_SEND1:
packet[0]=0x05;
start=11;
break;
}
//Pack 6 channels per packet
for(uint8_t i=0;i<6;i++)
{
uint8_t val=start<16 ? convert_channel_16b_nolimit(start,426 >> 4,3448 >> 4,true) : 0x00;
start--; // switch to next channel
packet[i+1]=val;
}
}
else
#endif
{// Normal packets
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
start=4+6*(packet[0]&3);
if((packet[0]&0x08)==0)
start++;
//Channels 426..1937..3448
for(uint8_t i=0;i<3;i++)
{
uint16_t val=start<16 ? convert_channel_16b_nolimit(start,426,3448,false) : 0x0000;
start-=2; // switch to next channel
packet[i*2+1]=val>>8;
packet[i*2+2]=val;
}
}
//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
//Send
CYRF_WriteDataPacketLen(packet, MLINK_PACKET_SIZE);
//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()
{ // not sure how MLINK telemetry works, the 2 RXs I have are sending something completly different...
telemetry_counter += 2; // TX LQI counter
telemetry_link = 1;
if(packet_in[0]==0x13)
{ // RX-9-DR : 13 1A C8 00 01 64 00
uint8_t id;
for(uint8_t i=1; i<5; i+=3)
{//2 sensors per packet
id=0x00;
switch(packet_in[i]&0x0F)
{
case 1: //voltage
if((packet_in[i]&0xF0) == 0x00)
v_lipo1 = packet_in[i+1]; // Rx_Batt*20
else
v_lipo2 = packet_in[i+1];
break;
case 2: //current
id = 0x28;
break;
case 3: //vario
id = 0x30;
break;
case 5: //rpm
id = 0x03;
break;
case 6: //temp
id = 0x02;
break;
case 10: //lqi
RX_RSSI=RX_LQI=packet_in[i+1]>>1;
break;
}
#if defined HUB_TELEMETRY
if(id)
{
uint16_t val=((packet_in[i+2]&0x80)<<8)|((packet_in[i+2]&0x7F)<<7)|(packet_in[i+1]>>1); //remove the alarm LSB bit, move the sign bit to MSB
frsky_send_user_frame(id, val, val>>8);
}
#endif
}
}
else
if(packet_in[0]==0x03)
{ // RX-5 : 03 15 23 00 00 01 02
//Incoming packet values
RX_RSSI = packet_in[2]<<1; // Looks to be the RX RSSI value
RX_LQI = packet_in[5]; // Looks to be connection lost
}
else
RX_RSSI = TX_LQI;
// Read TX RSSI
TX_RSSI = CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;
if(telemetry_lost)
{
telemetry_lost = 0;
packet_count = 50;
telemetry_counter = 100;
}
}
#endif
#ifdef MLINK_FW_TELEMETRY
static void __attribute__((unused)) MLINK_Send_Telemetry()
{
telemetry_counter += 2; // TX LQI counter
telemetry_link = 4;
// Read TX RSSI
TX_RSSI = CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;
if(telemetry_lost)
{
telemetry_lost = 0;
packet_count = 50;
telemetry_counter = 100;
}
}
#endif
uint16_t MLINK_callback()
{
uint8_t status;
uint16_t start;
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_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 ((uint16_t)((uint16_t)micros()-(uint16_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
if(packet_count > 0x19*2)
return 28712; // Give more time to the RX to confirm that the bind is ok...
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);
#if defined(MLINK_HUB_TELEMETRY) || defined(MLINK_FW_TELEMETRY)
packet_count = 0;
telemetry_lost = 1;
#endif
phase++;
case MLINK_SEND1:
MLINK_send_data_packet();
phase++;
return 4880+1111;
case MLINK_SEND2:
MLINK_send_data_packet();
phase++;
if(hopping_frequency_no%5==0)
return 4617+1017;
return 4617+1422;
case MLINK_SEND3:
MLINK_send_data_packet();
phase++;
return 4611;
case MLINK_CHECK3:
//Switch to 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+2434+410-1000;
}
else
CYRF_SetPower(0x38);
phase=MLINK_SEND1;
return 4470;
case MLINK_RX:
#if defined(MLINK_HUB_TELEMETRY) || defined(MLINK_FW_TELEMETRY)
//TX LQI calculation
packet_count++;
if(packet_count>=50)
{
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);
debug("T(%02X):",status);
if( (status&0x80) == 0 )
{//Packet received
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
debug("(%X)",len)
if( len && len <= MLINK_PACKET_SIZE )
{
CYRF_ReadDataPacketLen(packet_in, len*2);
#if defined(MLINK_HUB_TELEMETRY) || defined(MLINK_FW_TELEMETRY)
if(len==MLINK_PACKET_SIZE)
{
for(uint8_t i=0;i<8;i++)
//Check CRC
crc8=bit_reverse(MLINK_CRC_Init);
for(uint8_t i=0;i<MLINK_PACKET_SIZE-1;i++)
{
packet_in[i]=packet_in[i<<1];
crc8_update(bit_reverse(packet_in[i]));
debug(" %02X",packet_in[i]);
}
if(packet_in[14] == bit_reverse(crc8)) // Packet CRC is ok
MLINK_Send_Telemetry();
else
debug(" NOK");
}
#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=MLINK_SEND2;
return 1000;
}
return 1000;
}
static void __attribute__((unused)) MLINK_shuffle_freqs(uint32_t seed, uint8_t *hop)
{
randomSeed(seed);
for(uint8_t i=0; i < MLINK_NUM_FREQ/2; i++)
{
uint8_t r = random(0xfefefefe) % (MLINK_NUM_FREQ/2);
uint8_t tmp = hop[r];
hop[r] = hop[i];
hop[i] = tmp;
}
}
void MLINK_init()
{
MLINK_cyrf_config();
//Init ID and RF freqs
for(uint8_t i=0; i < MLINK_NUM_FREQ/2; i++)
{
hopping_frequency[i ] = (i<<1) + 3;
hopping_frequency[i+MLINK_NUM_FREQ/2] = (i<<1) + 3;
}
// part1
memcpy(MLINK_Data_Code ,rx_tx_addr,4);
MLINK_shuffle_freqs(MProtocol_id, hopping_frequency);
// part2
MProtocol_id ^= 0x6FBE3201;
set_rx_tx_addr(MProtocol_id);
memcpy(MLINK_Data_Code+4,rx_tx_addr,4);
MLINK_shuffle_freqs(MProtocol_id, &hopping_frequency[MLINK_NUM_FREQ/2]);
// part3
MLINK_CRC_Init = rx_tx_addr[3]; //value sent during bind then used to init the CRC
MLINK_Unk_6_2 = 0x3A; //unknown value sent during bind but doesn't seem to matter
#ifdef MLINK_FORCE_ID
if(RX_num)
{
//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",MLINK_NUM_FREQ);
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
}
else
{
//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",MLINK_NUM_FREQ);
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;
}
#endif

View File

@@ -18,20 +18,23 @@
#if defined(MT99XX_NRF24L01_INO)
#include "iface_nrf24l01.h"
#include "iface_nrf250k.h"
#define MT99XX_BIND_COUNT 928
#define MT99XX_PACKET_PERIOD_FY805 2460
#define MT99XX_PACKET_PERIOD_MT 2625
#define MT99XX_PACKET_PERIOD_YZ 3125
#define MT99XX_INITIAL_WAIT 500
#define MT99XX_PACKET_SIZE 9
#define MT99XX_BIND_COUNT 928
#define MT99XX_PACKET_PERIOD_FY805 2460
#define MT99XX_PACKET_PERIOD_MT 2625
#define MT99XX_PACKET_PERIOD_YZ 3125
#define MT99XX_PACKET_PERIOD_A180 3400 // timing changes between the packets 2 x 27220 then 1x 26080, it seems that it is only on the first RF channel which jitters by 1.14ms but hard to pinpoint with XN297dump
#define MT99XX_PACKET_PERIOD_DRAGON 1038 // there is a pause of 2x1038 between the packets 3 and 4 from what XN297dump detects which I think are used for telemetry
#define MT99XX_INITIAL_WAIT 500
#define MT99XX_PACKET_SIZE 9
#define checksum_offset rf_ch_num
#define channel_offset phase
//#define FORCE_A180_ID
//#define FORCE_DRAGON_ID
enum{
// flags going to packet[6] (MT99xx, H7)
FLAG_MT_RATE1 = 0x01, // (H7 high rate)
FLAG_MT_RATE1 = 0x01, // (H7 & A180 high rate)
FLAG_MT_RATE2 = 0x02, // (MT9916 only)
FLAG_MT_VIDEO = 0x10,
FLAG_MT_SNAPSHOT= 0x20,
@@ -53,6 +56,19 @@ enum{
FLAG_FY805_HEADLESS= 0x10,
};
enum{
// flags going to packet[6] (A180)
FLAG_A180_3D6G = 0x01,
FLAG_A180_RATE = 0x02,
};
enum{
// flags going to packet[6] (DRAGON)
FLAG_DRAGON_RATE = 0x01,
FLAG_DRAGON_RTH = 0x80,
FLAG_DRAGON_UNK = 0x04,
};
enum {
MT99XX_INIT = 0,
MT99XX_BIND,
@@ -64,89 +80,170 @@ const uint8_t h7_mys_byte[] = {
0x05, 0x15, 0x06, 0x16, 0x07, 0x17, 0x00, 0x10
};
static const uint8_t ls_mys_byte[] = {
const uint8_t ls_mys_byte[] = {
0x05, 0x15, 0x25, 0x06, 0x16, 0x26,
0x07, 0x17, 0x27, 0x00, 0x10, 0x20,
0x01, 0x11, 0x21, 0x02, 0x12, 0x22,
0x03, 0x13, 0x23, 0x04, 0x14, 0x24
};
const uint8_t yz_p4_seq[] = {0xa0, 0x20, 0x60};
#ifdef DRAGON_HUB_TELEMETRY
const uint8_t DRAGON_seq[] = {0x20, 0x60, 0x20, 0x80};
#endif
static void __attribute__((unused)) MT99XX_send_packet()
{
const uint8_t yz_p4_seq[] = {0xa0, 0x20, 0x60};
static uint8_t yz_seq_num=0;
static uint8_t ls_counter=0;
static uint8_t seq_num=0;
if(sub_protocol != YZ)
{ // MT99XX & H7 & LS
packet[0] = convert_channel_16b_limit(THROTTLE,0xE1,0x00); // throttle
packet[1] = convert_channel_16b_limit(RUDDER ,0x00,0xE1); // rudder
packet[2] = convert_channel_16b_limit(AILERON ,0xE1,0x00); // aileron
packet[3] = convert_channel_16b_limit(ELEVATOR,0x00,0xE1); // elevator
packet[4] = 0x20; // pitch trim (0x3f-0x20-0x00)
packet[5] = 0x20; // roll trim (0x00-0x20-0x3f)
packet[6] = GET_FLAG( CH5_SW, FLAG_MT_FLIP );
packet[7] = h7_mys_byte[hopping_frequency_no]; // next rf channel index ?
if(IS_BIND_IN_PROGRESS)
{
//Bind packet
packet[0] = 0x20;
switch(sub_protocol)
{
case YZ:
packet_period = MT99XX_PACKET_PERIOD_YZ;
packet[1] = 0x15;
packet[2] = 0x05;
packet[3] = 0x06;
break;
case LS:
packet[1] = 0x14;
packet[2] = 0x05;
packet[3] = 0x11;
break;
case FY805:
packet_period = MT99XX_PACKET_PERIOD_FY805;
packet[1] = 0x15;
packet[2] = 0x12;
packet[3] = 0x17;
break;
case A180:
packet_period = MT99XX_PACKET_PERIOD_A180;
default: // MT99 & H7 & A180 & DRAGON
packet[1] = 0x14;
packet[2] = 0x03;
packet[3] = 0x25;
break;
}
packet[4] = rx_tx_addr[0];
packet[5] = rx_tx_addr[1];
packet[6] = rx_tx_addr[2];
packet[7] = crc8; // checksum offset
packet[8] = 0xAA; // fixed
}
else
{
if(sub_protocol != YZ)
{ // MT99XX & H7 & LS & FY805 & A180 & DRAGON
packet[0] = convert_channel_16b_limit(THROTTLE,0xE1,0x00); // throttle
packet[1] = convert_channel_16b_limit(RUDDER ,0x00,0xE1); // rudder
packet[2] = convert_channel_16b_limit(AILERON ,0xE1,0x00); // aileron
packet[3] = convert_channel_16b_limit(ELEVATOR,0x00,0xE1); // elevator
packet[4] = 0x20; // pitch trim (0x3f-0x20-0x00)
packet[5] = 0x20; // roll trim (0x00-0x20-0x3f)
packet[6] = GET_FLAG( CH5_SW, FLAG_MT_FLIP );
packet[7] = h7_mys_byte[hopping_frequency_no]; // next rf channel index ?
if(sub_protocol==H7)
packet[6]|=FLAG_MT_RATE1; // max rate on H7
else
if(sub_protocol==MT99)
packet[6] |= 0x40 | FLAG_MT_RATE2
| GET_FLAG( CH7_SW, FLAG_MT_SNAPSHOT )
| GET_FLAG( CH8_SW, FLAG_MT_VIDEO ); // max rate on MT99xx
else
if(sub_protocol==FY805)
{
switch(sub_protocol)
{
case MT99:
packet[6] |= 0x40 | FLAG_MT_RATE2 // max rate on MT99xx
| GET_FLAG( CH7_SW, FLAG_MT_SNAPSHOT )
| GET_FLAG( CH8_SW, FLAG_MT_VIDEO );
break;
case H7:
packet[6] |= FLAG_MT_RATE1; // max rate on H7
break;
case LS:
packet[6] |= FLAG_LS_RATE // max rate
| GET_FLAG( CH6_SW, FLAG_LS_INVERT ) // invert
| GET_FLAG( CH7_SW, FLAG_LS_SNAPSHOT ) // snapshot
| GET_FLAG( CH8_SW, FLAG_LS_VIDEO ) // video
| GET_FLAG( CH9_SW, FLAG_LS_HEADLESS ); // Headless
packet[7] = ls_mys_byte[seq_num++];
if(seq_num >= sizeof(ls_mys_byte))
seq_num=0;
break;
case FY805:
packet[6]=0x20;
//Rate 0x01?
//Flip ?
packet[7]=0x01
|GET_FLAG( CH5_SW, FLAG_MT_FLIP )
|GET_FLAG( CH9_SW, FLAG_FY805_HEADLESS ); //HEADLESS
checksum_offset=0;
}
else //LS
{
packet[6] |= FLAG_LS_RATE // max rate
| GET_FLAG( CH6_SW, FLAG_LS_INVERT ) //INVERT
| GET_FLAG( CH7_SW, FLAG_LS_SNAPSHOT ) //SNAPSHOT
| GET_FLAG( CH8_SW, FLAG_LS_VIDEO ) //VIDEO
| GET_FLAG( CH9_SW, FLAG_LS_HEADLESS ); //HEADLESS
packet[7] = ls_mys_byte[ls_counter++];
if(ls_counter >= sizeof(ls_mys_byte))
ls_counter=0;
}
uint8_t result=checksum_offset;
for(uint8_t i=0; i<8; i++)
result += packet[i];
packet[8] = result;
}
else
{ // YZ
packet[0] = convert_channel_16b_limit(THROTTLE,0x00,0x64); // throttle
packet[1] = convert_channel_16b_limit(RUDDER ,0x64,0x00); // rudder
packet[2] = convert_channel_16b_limit(ELEVATOR,0x00,0x64); // elevator
packet[3] = convert_channel_16b_limit(AILERON ,0x64,0x00); // aileron
if(packet_count++ >= 23)
{
yz_seq_num ++;
if(yz_seq_num > 2)
yz_seq_num = 0;
packet_count=0;
|GET_FLAG( CH9_SW, FLAG_FY805_HEADLESS ); //HEADLESS
crc8=0;
break;
case A180:
packet[6] = FLAG_A180_RATE
| GET_FLAG( CH5_SW, FLAG_A180_3D6G );
packet[7] = 0x00;
break;
case DRAGON:
if(CH5_SW) // Advanced mode
packet[5] |= 0x80;
else
if(Channel_data[CH5] > CHANNEL_MIN_COMMAND) // Beginner mode
packet[5] |= 0x40;
packet[6] = FLAG_DRAGON_RATE
| GET_FLAG( CH6_SW, FLAG_DRAGON_RTH );
#ifdef DRAGON_HUB_TELEMETRY
//Telemetry
// C=48 S=Y A= 6C 00 22 CC CC P(9)= 6C 00 22 27 00 00 00 00 60
// C=48 S=Y A= 6C 00 22 CC CC P(9)= 6C 00 22 28 00 00 00 00 61
// C=18 S=Y A= 6C 00 22 CC CC P(9)= 6C 00 22 24 00 00 00 00 5D
// 6C 00 22 = TX address, 27/28/24=vbatt, check = sum(P[0..7]) + AB, where AB comes from? Is it constant?
if(hopping_frequency_no == 0)
{
seq_num++;
seq_num &= 0x03;
packet_count++;
if(packet_count > 11)
packet_count = 0;
}
if(packet_count > 10) // Telemetry packet request every 10 or 11 packets
packet[6] |= 0x04; // Request telemetry flag
packet[7] = DRAGON_seq[seq_num]; // seq: 20 80 20 60 20 80 20 60... 80 changes to 80+batt from telem
if(seq_num==3)
packet[7] |= v_lipo1;
#else
packet[7] = 0x20;
#endif
break;
}
uint8_t result=crc8;
for(uint8_t i=0; i<8; i++)
result += packet[i];
packet[8] = result;
}
else
{ // YZ
packet[0] = convert_channel_16b_limit(THROTTLE,0x00,0x64); // throttle
packet[1] = convert_channel_16b_limit(RUDDER ,0x64,0x00); // rudder
packet[2] = convert_channel_16b_limit(ELEVATOR,0x00,0x64); // elevator
packet[3] = convert_channel_16b_limit(AILERON ,0x64,0x00); // aileron
if(packet_count++ >= 23)
{
seq_num ++;
if(seq_num > 2)
seq_num = 0;
packet_count=0;
}
packet[4] = yz_p4_seq[seq_num];
packet[5] = 0x02 // expert ? (0=unarmed, 1=normal)
| GET_FLAG(CH8_SW, 0x10) //VIDEO
| GET_FLAG(CH5_SW, 0x80) //FLIP
| GET_FLAG(CH9_SW, 0x04) //HEADLESS
| GET_FLAG(CH7_SW, 0x20); //SNAPSHOT
packet[6] = GET_FLAG(CH6_SW, 0x80); //LED
packet[7] = packet[0];
for(uint8_t idx = 1; idx < MT99XX_PACKET_SIZE-2; idx++)
packet[7] += packet[idx];
packet[8] = 0xff;
}
packet[4] = yz_p4_seq[yz_seq_num];
packet[5] = 0x02 // expert ? (0=unarmed, 1=normal)
| GET_FLAG(CH8_SW, 0x10) //VIDEO
| GET_FLAG(CH5_SW, 0x80) //FLIP
| GET_FLAG(CH9_SW, 0x04) //HEADLESS
| GET_FLAG(CH7_SW, 0x20); //SNAPSHOT
packet[6] = GET_FLAG(CH6_SW, 0x80); //LED
packet[7] = packet[0];
for(uint8_t idx = 1; idx < MT99XX_PACKET_SIZE-2; idx++)
packet[7] += packet[idx];
packet[8] = 0xff;
}
if(sub_protocol == LS)
@@ -154,14 +251,23 @@ static void __attribute__((unused)) MT99XX_send_packet()
else
if(sub_protocol==FY805)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x4B); // FY805 always transmits on the same channel
else
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no] + channel_offset);
else // MT99 & H7 & YZ & A180 & DRAGON
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(packet, MT99XX_PACKET_SIZE);
if(sub_protocol == DRAGON)
{
if(hopping_frequency_no == 6)
packet_period = 3 * MT99XX_PACKET_PERIOD_DRAGON; // hole probably for the telemetry
else
packet_period = MT99XX_PACKET_PERIOD_DRAGON;
}
hopping_frequency_no++;
if(sub_protocol == YZ)
if(sub_protocol == YZ || sub_protocol == A180 || sub_protocol == DRAGON )
hopping_frequency_no++; // skip every other channel
if(hopping_frequency_no > 15)
@@ -170,141 +276,109 @@ static void __attribute__((unused)) MT99XX_send_packet()
NRF24L01_SetPower();
}
static void __attribute__((unused)) MT99XX_init()
static void __attribute__((unused)) MT99XX_RF_init()
{
NRF24L01_Initialize();
if(sub_protocol == YZ)
XN297_SetScrambledMode(XN297_UNSCRAMBLED);
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_FlushTx();
XN297_SetTXAddr((uint8_t *)"\xCC\xCC\xCC\xCC\xCC", 5);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5 bytes address
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no auto retransmit
if(sub_protocol == YZ)
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps (nRF24L01+ only)
else
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) );
}
static void __attribute__((unused)) MT99XX_initialize_txid()
{
rx_tx_addr[3] = 0xCC;
rx_tx_addr[4] = 0xCC;
if(sub_protocol == YZ)
rx_tx_addr[1] = rx_tx_addr[3]; // RX_Num
switch(protocol)
{
rx_tx_addr[0] = 0x53; // test (SB id)
rx_tx_addr[1] = 0x00;
rx_tx_addr[2] = 0x00;
}
else
if(sub_protocol == FY805)
{
rx_tx_addr[0] = 0x81; // test (SB id)
case YZ:
rx_tx_addr[0] = 0x53; // test (SB id)
rx_tx_addr[1] = 0x00;
rx_tx_addr[2] = 0x00;
break;
case FY805:
rx_tx_addr[0] = 0x81; // test (SB id)
rx_tx_addr[1] = 0x0F;
rx_tx_addr[2] = 0x00;
}
else
if(sub_protocol == LS)
rx_tx_addr[0] = 0xCC;
else //MT99 & H7
rx_tx_addr[2] = 0x00;
checksum_offset = rx_tx_addr[0] + rx_tx_addr[1] + rx_tx_addr[2];
channel_offset = (((checksum_offset & 0xf0)>>4) + (checksum_offset & 0x0f)) % 8;
break;
case LS:
rx_tx_addr[0] = 0xCC;
break;
#ifdef FORCE_A180_ID
case A180:
rx_tx_addr[0] = 0x84; // MikeHRC ID
rx_tx_addr[1] = 0x62;
rx_tx_addr[2] = 0x4A;
//crc8 = 0x30
//channel_offset = 0x03;
break;
#endif
#ifdef FORCE_DRAGON_ID
case DRAGON:
rx_tx_addr[0] = 0x6C; // Laurie ID
rx_tx_addr[1] = 0x00;
rx_tx_addr[2] = 0x22;
//crc8 = 0x8E
//channel_offset = 0x06
break;
#endif
default: //MT99 & H7 & A180 & DRAGON
rx_tx_addr[2] = 0x00;
break;
}
rx_tx_addr[3] = 0xCC;
rx_tx_addr[4] = 0xCC;
crc8 = rx_tx_addr[0] + rx_tx_addr[1] + rx_tx_addr[2];
//memcpy(hopping_frequency,"\x02\x48\x0C\x3e\x16\x34\x20\x2A\x2A\x20\x34\x16\x3e\x0c\x48\x02",16);
for(uint8_t i=0; i<8; i++)
{
hopping_frequency[(i<<1) ]=0x02 + (10*i);
hopping_frequency[(i<<1)+1]=0x48 - (10*i);
}
hopping_frequency_no=0;
}
uint16_t MT99XX_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
MT99XX_send_packet();
}
else
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
if(bind_counter)
{
bind_counter--;
if (bind_counter == 0)
{
// set tx address for data packets
XN297_SetTXAddr(rx_tx_addr, 5);
// set tx address for data packets
XN297_SetTXAddr(rx_tx_addr, 5);
// set rf channels
uint8_t channel_offset = ((crc8>>4) + (crc8 & 0x0f)) % 8;
for(uint8_t i=0;i<16;i++)
hopping_frequency[i] += channel_offset;
BIND_DONE;
}
else
{
if(sub_protocol == LS)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x2D); // LS always transmits on the same channel
else
if(sub_protocol==FY805)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x4B); // FY805 always transmits on the same channel
else
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(packet, MT99XX_PACKET_SIZE); // bind packet
hopping_frequency_no++;
if(sub_protocol == YZ)
hopping_frequency_no++; // skip every other channel
if(hopping_frequency_no > 15)
hopping_frequency_no = 0;
bind_counter--;
}
}
MT99XX_send_packet();
return packet_period;
}
uint16_t initMT99XX(void)
void MT99XX_init(void)
{
BIND_IN_PROGRESS; // autobind protocol
if(sub_protocol != A180 && sub_protocol != DRAGON)
BIND_IN_PROGRESS; // autobind protocol
bind_counter = MT99XX_BIND_COUNT;
memcpy(hopping_frequency,"\x02\x48\x0C\x3e\x16\x34\x20\x2A\x2A\x20\x34\x16\x3e\x0c\x48\x02",16);
hopping_frequency_no=0;
MT99XX_initialize_txid();
MT99XX_init();
MT99XX_RF_init();
packet[0] = 0x20;
packet_period = MT99XX_PACKET_PERIOD_MT;
switch(sub_protocol)
{ // MT99 & H7
case MT99:
case H7:
packet[1] = 0x14;
packet[2] = 0x03;
packet[3] = 0x25;
break;
case YZ:
packet_period = MT99XX_PACKET_PERIOD_YZ;
packet[1] = 0x15;
packet[2] = 0x05;
packet[3] = 0x06;
break;
case LS:
packet[1] = 0x14;
packet[2] = 0x05;
packet[3] = 0x11;
break;
case FY805:
packet_period = MT99XX_PACKET_PERIOD_FY805;
packet[1] = 0x15;
packet[2] = 0x12;
packet[3] = 0x17;
break;
}
packet[4] = rx_tx_addr[0];
packet[5] = rx_tx_addr[1];
packet[6] = rx_tx_addr[2];
packet[7] = checksum_offset; // checksum offset
packet[8] = 0xAA; // fixed
packet_count=0;
return MT99XX_INITIAL_WAIT+MT99XX_PACKET_PERIOD_MT;
}
#endif

View File

@@ -14,11 +14,11 @@
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
17,MT99xx,MT,H7,YZ,LS,FY805,A180,Dragon
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
@@ -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
@@ -52,11 +52,11 @@
52,ZSX,280
53,Height,5ch,8ch
54,Scanner
55,Frsky_RX,RX,CloneTX
56,AFHDS2A_RX
55,Frsky_RX,Multi,CloneTX,EraseTX,CPPM
56,AFHDS2A_RX,Multi,CPPM
57,HoTT,Sync,No_Sync
58,FX816,P38
59,Bayang_RX
59,Bayang_RX,Multi,CPPM
60,Pelikan,Pro,Lite
61,Tiger
62,XK,X450,X420
@@ -67,10 +67,18 @@
67,LR12,LR12,LR12_6ch
68,Skyartec
69,ESKYv2,150V2
70,DSM_RX
71,JJRC345
70,DSM_RX,Multi,CPPM
71,JJRC345,JJRC345,SkyTmblr
72,Q90C
73,Kyosho
74,RadioLink,Surface
73,Kyosho,FHSS,Hype
74,RadioLink,Surface,Air,DumboRC
75,---
76,Realacc,R11
77,OMP
77,OMP
78,M-Link
79,WFLY,RF20x
80,E016H,E016Hv2
81,E010r5
82,LOLI
83,E129
84,JOYSWAY

View File

@@ -1,401 +0,0 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(MULTI_NAMES)
const char STR_FLYSKY[] ="FlySky";
const char STR_HUBSAN[] ="Hubsan";
const char STR_FRSKYD[] ="FrSky D";
const char STR_HISKY[] ="Hisky";
const char STR_V2X2[] ="V2x2";
const char STR_DSM[] ="DSM";
const char STR_DSM_RX[] ="DSM_RX";
const char STR_DEVO[] ="Devo";
const char STR_YD717[] ="YD717";
const char STR_KN[] ="KN";
const char STR_SYMAX[] ="SymaX";
const char STR_SLT[] ="SLT";
const char STR_CX10[] ="CX10";
const char STR_CG023[] ="CG023";
const char STR_BAYANG[] ="Bayang";
const char STR_FRSKYL[] ="FrSky L";
const char STR_FRSKYX[] ="FrSky X";
const char STR_FRSKYX2[] ="FrSkyX2";
const char STR_ESKY[] ="ESky";
const char STR_MT99XX[] ="MT99XX";
const char STR_MJXQ[] ="MJXq";
const char STR_SHENQI[] ="Shenqi";
const char STR_FY326[] ="FY326";
const char STR_SFHSS[] ="SFHSS";
const char STR_J6PRO[] ="J6 Pro";
const char STR_JJRC345[] ="JJRC345";
const char STR_FQ777[] ="FQ777";
const char STR_ASSAN[] ="Assan";
const char STR_FRSKYV[] ="FrSky V";
const char STR_HONTAI[] ="Hontai";
const char STR_AFHDS2A[] ="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";
const char STR_ESKY150[] ="Esky150";
const char STR_ESKY150V2[] ="EskyV2";
const char STR_H8_3D[] ="H8 3D";
const char STR_CORONA[] ="Corona";
const char STR_CFLIE[] ="CFlie";
const char STR_HITEC[] ="Hitec";
const char STR_WFLY[] ="WFly";
const char STR_BUGS[] ="Bugs";
const char STR_BUGSMINI[] ="BugMini";
const char STR_TRAXXAS[] ="Traxxas";
const char STR_NCC1701[] ="NCC1701";
const char STR_E01X[] ="E01X";
const char STR_V911S[] ="V911S";
const char STR_GD00X[] ="GD00x";
const char STR_V761[] ="V761";
const char STR_KF606[] ="KF606";
const char STR_REDPINE[] ="Redpine";
const char STR_POTENSIC[] ="Potensi";
const char STR_ZSX[] ="ZSX";
const char STR_HEIGHT[] ="Height";
const char STR_SCANNER[] ="Scanner";
const char STR_FRSKY_RX[] ="FrSkyRX";
const char STR_AFHDS2A_RX[] ="FS2A_RX";
const char STR_HOTT[] ="HoTT";
const char STR_FX816[] ="FX816";
const char STR_BAYANG_RX[] ="BayanRX";
const char STR_PELIKAN[] ="Pelikan";
const char STR_TIGER[] ="Tiger";
const char STR_XK[] ="XK";
const char STR_XN297DUMP[] ="XN297DP";
const char STR_FRSKYR9[] ="FrSkyR9";
const char STR_PROPEL[] ="Propel";
const char STR_SKYARTEC[] ="Skyartc";
const char STR_KYOSHO[] ="Kyosho";
const char STR_RLINK[] ="RadLink";
const char STR_REALACC[] ="Realacc";
const char STR_OMP[] ="OMP";
const char STR_TEST[] ="Test";
const char STR_FAKE[] ="Fake";
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""Clo 8ch";
const char STR_SUBTYPE_HISKY[] = "\x05""Std\0 ""HK310";
const char STR_SUBTYPE_V2X2[] = "\x06""Std\0 ""JXD506""MR101\0";
const char STR_SUBTYPE_DSM[] = "\x04""2 1F""2 2F""X 1F""X 2F""Auto";
const char STR_SUBTYPE_DEVO[] = "\x04""8ch\0""10ch""12ch""6ch\0""7ch\0";
const char STR_SUBTYPE_YD717[] = "\x07""Std\0 ""SkyWlkr""Syma X4""XINXUN\0""NIHUI\0 ";
const char STR_SUBTYPE_KN[] = "\x06""WLtoys""FeiLun";
const char STR_SUBTYPE_SYMAX[] = "\x03""Std""X5C";
const char STR_SUBTYPE_SLT[] = "\x06""V1_6ch""V2_8ch""Q100\0 ""Q200\0 ""MR100\0";
const char STR_SUBTYPE_CX10[] = "\x07""Green\0 ""Blue\0 ""DM007\0 ""-\0 ""JC3015a""JC3015b""MK33041";
const char STR_SUBTYPE_CG023[] = "\x05""Std\0 ""YD829";
const char STR_SUBTYPE_BAYANG[] = "\x07""Std\0 ""H8S3D\0 ""X16 AH\0""IRDrone""DHD D4\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""PWM,IB16""PPM,IB16";
const char STR_SUBTYPE_Q2X2[] = "\x04""Q222""Q242""Q282";
const char STR_SUBTYPE_WK2x01[] = "\x06""WK2801""WK2401""W6_5_1""W6_6_1""W6_HeL""W6_HeI";
const char STR_SUBTYPE_Q303[] = "\x06""Std\0 ""CX35\0 ""CX10D\0""CX10WD";
const char STR_SUBTYPE_CABELL[] = "\x07""V3\0 ""V3 Telm""-\0 ""-\0 ""-\0 ""-\0 ""F-Safe\0""Unbind\0";
const char STR_SUBTYPE_H83D[] = "\x07""Std\0 ""H20H\0 ""H20Mini""H30Mini";
const char STR_SUBTYPE_CORONA[] = "\x05""V1\0 ""V2\0 ""FD V3";
const char STR_SUBTYPE_HITEC[] = "\x07""Optima\0""Opt Hub""Minima\0";
const char STR_SUBTYPE_BUGS_MINI[] = "\x06""Std\0 ""Bugs3H";
const char STR_SUBTYPE_TRAXXAS[] = "\x04""6519";
const char STR_SUBTYPE_E01X[] = "\x05""E012\0""E015\0""E016H";
const char STR_SUBTYPE_GD00X[] = "\x05""GD_V1""GD_V2";
const char STR_SUBTYPE_REDPINE[] = "\x04""Fast""Slow";
const char STR_SUBTYPE_POTENSIC[] = "\x03""A20";
const char STR_SUBTYPE_ZSX[] = "\x07""280JJRC";
const char STR_SUBTYPE_HEIGHT[] = "\x03""5ch""8ch";
const char STR_SUBTYPE_FX816[] = "\x03""P38";
const char STR_SUBTYPE_XN297DUMP[] = "\x07""250Kbps""1Mbps\0 ""2Mbps\0 ""Auto\0 ""NRF\0 ";
const char STR_SUBTYPE_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""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_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 ";
const char STR_SUBTYPE_REALACC[] = "\x03""R11";
enum
{
OPTION_NONE,
OPTION_OPTION,
OPTION_RFTUNE,
OPTION_VIDFREQ,
OPTION_FIXEDID,
OPTION_TELEM,
OPTION_SRVFREQ,
OPTION_MAXTHR,
OPTION_RFCHAN,
OPTION_RFPOWER,
};
#define NO_SUBTYPE nullptr
const mm_protocol_definition multi_protocols[] = {
// Protocol number, Protocol String, Number of sub_protocols, Sub_protocol strings, Option type
#if defined(ASSAN_NRF24L01_INO)
{PROTO_ASSAN, STR_ASSAN, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(BAYANG_NRF24L01_INO)
{PROTO_BAYANG, STR_BAYANG, 6, STR_SUBTYPE_BAYANG, OPTION_TELEM },
#endif
#if defined(BAYANG_RX_NRF24L01_INO)
{PROTO_BAYANG_RX, STR_BAYANG_RX, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(BUGS_A7105_INO)
{PROTO_BUGS, STR_BUGS, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(BUGSMINI_NRF24L01_INO)
{PROTO_BUGSMINI, STR_BUGSMINI, 2, STR_SUBTYPE_BUGS_MINI, OPTION_NONE },
#endif
#if defined(CABELL_NRF24L01_INO)
{PROTO_CABELL, STR_CABELL, 8, STR_SUBTYPE_CABELL, OPTION_OPTION },
#endif
#if defined(CFLIE_NRF24L01_INO)
{PROTO_CFLIE, STR_CFLIE, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(CG023_NRF24L01_INO)
{PROTO_CG023, STR_CG023, 2, STR_SUBTYPE_CG023, OPTION_NONE },
#endif
#if defined(CORONA_CC2500_INO)
{PROTO_CORONA, STR_CORONA, 3, STR_SUBTYPE_CORONA, OPTION_RFTUNE },
#endif
#if defined(CX10_NRF24L01_INO)
{PROTO_CX10, STR_CX10, 7, STR_SUBTYPE_CX10, OPTION_NONE },
#endif
#if defined(DEVO_CYRF6936_INO)
{PROTO_DEVO, STR_DEVO, 5, STR_SUBTYPE_DEVO, OPTION_FIXEDID },
#endif
#if defined(DM002_NRF24L01_INO)
{PROTO_DM002, STR_DM002, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(DSM_CYRF6936_INO)
{PROTO_DSM, STR_DSM, 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(E01X_NRF24L01_INO)
{PROTO_E01X, STR_E01X, 3, STR_SUBTYPE_E01X, OPTION_OPTION },
#endif
#if defined(ESKY_NRF24L01_INO)
{PROTO_ESKY, STR_ESKY, 2, STR_SUBTYPE_ESKY, OPTION_NONE },
#endif
#if defined(ESKY150_NRF24L01_INO)
{PROTO_ESKY150, STR_ESKY150, 2, STR_SUBTYPE_ESKY150, OPTION_NONE },
#endif
#if defined(ESKY150V2_CC2500_INO)
{PROTO_ESKY150V2, STR_ESKY150V2, 1, STR_SUBTYPE_ESKY150V2, OPTION_RFTUNE },
#endif
#if defined(FLYSKY_A7105_INO)
{PROTO_FLYSKY, STR_FLYSKY, 5, STR_SUBTYPE_FLYSKY, OPTION_NONE },
#endif
#if defined(AFHDS2A_A7105_INO)
{PROTO_AFHDS2A, STR_AFHDS2A, 6, 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(HEIGHT_A7105_INO)
{PROTO_HEIGHT, STR_HEIGHT, 2, STR_SUBTYPE_HEIGHT, OPTION_NONE },
#endif
#if defined(FQ777_NRF24L01_INO)
{PROTO_FQ777, STR_FQ777, 0, NO_SUBTYPE, OPTION_NONE },
#endif
//OpenTX 2.3.x issue: DO NOT CHANGE ORDER below
#if defined(FRSKY_RX_CC2500_INO)
{PROTO_FRSKY_RX, STR_FRSKY_RX, 2, STR_SUBTYPE_FRSKY_RX, OPTION_RFTUNE },
#endif
#if defined(FRSKYD_CC2500_INO)
{PROTO_FRSKYD, STR_FRSKYD, 2, STR_SUBTYPE_FRSKYD, OPTION_RFTUNE },
#endif
#if defined(FRSKYV_CC2500_INO)
{PROTO_FRSKYV, STR_FRSKYV, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(FRSKYX_CC2500_INO)
{PROTO_FRSKYX, STR_FRSKYX, 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, 8, STR_SUBTYPE_FRSKYR9, OPTION_NONE },
#endif
#if defined(FX816_NRF24L01_INO)
{PROTO_FX816, STR_FX816, 1, STR_SUBTYPE_FX816, OPTION_NONE },
#endif
#if defined(FY326_NRF24L01_INO)
{PROTO_FY326, STR_FY326, 2, STR_SUBTYPE_FY326, OPTION_NONE },
#endif
#if defined(GD00X_NRF24L01_INO)
{PROTO_GD00X, STR_GD00X, 2, STR_SUBTYPE_GD00X, OPTION_RFTUNE },
#endif
#if defined(GW008_NRF24L01_INO)
{PROTO_GW008, STR_GW008, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(H8_3D_NRF24L01_INO)
{PROTO_H8_3D, STR_H8_3D, 4, STR_SUBTYPE_H83D, OPTION_NONE },
#endif
#if defined(HISKY_NRF24L01_INO)
{PROTO_HISKY, STR_HISKY, 2, STR_SUBTYPE_HISKY, OPTION_NONE },
#endif
#if defined(HITEC_CC2500_INO)
{PROTO_HITEC, STR_HITEC, 3, STR_SUBTYPE_HITEC, OPTION_RFTUNE },
#endif
#if defined(HONTAI_NRF24L01_INO)
{PROTO_HONTAI, STR_HONTAI, 4, STR_SUBTYPE_HONTAI, OPTION_NONE },
#endif
#if defined(HOTT_CC2500_INO)
{PROTO_HOTT, STR_HOTT, 2, STR_SUBTYPE_HOTT, OPTION_RFTUNE },
#endif
#if defined(HUBSAN_A7105_INO)
{PROTO_HUBSAN, STR_HUBSAN, 3, STR_SUBTYPE_HUBSAN, OPTION_VIDFREQ },
#endif
#if defined(J6PRO_CYRF6936_INO)
{PROTO_J6PRO, STR_J6PRO, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(JJRC345_NRF24L01_INO)
{PROTO_JJRC345, STR_JJRC345, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(KF606_NRF24L01_INO)
{PROTO_KF606, STR_KF606, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(KN_NRF24L01_INO)
{PROTO_KN, STR_KN, 2, STR_SUBTYPE_KN, OPTION_NONE },
#endif
#if defined(KYOSHO_A7105_INO)
{PROTO_KYOSHO, STR_KYOSHO, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(MJXQ_NRF24L01_INO)
{PROTO_MJXQ, STR_MJXQ, 7, STR_SUBTYPE_MJXQ, OPTION_RFTUNE },
#endif
#if defined(MT99XX_NRF24L01_INO)
{PROTO_MT99XX, STR_MT99XX, 5, STR_SUBTYPE_MT99, OPTION_NONE },
#endif
#if defined(NCC1701_NRF24L01_INO)
{PROTO_NCC1701, STR_NCC1701, 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(OMP_NRF24L01_INO)
{PROTO_OMP, STR_OMP, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(PELIKAN_A7105_INO)
{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, 1, STR_SUBTYPE_PROPEL, OPTION_NONE },
#endif
#if defined(CX10_NRF24L01_INO)
{PROTO_Q2X2, STR_Q2X2, 3, STR_SUBTYPE_Q2X2, OPTION_NONE },
#endif
#if defined(Q303_NRF24L01_INO)
{PROTO_Q303, STR_Q303, 4, STR_SUBTYPE_Q303, OPTION_NONE },
#endif
#if defined(Q90C_NRF24L01_INO)
{PROTO_Q90C, STR_Q90C, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(RLINK_CC2500_INO)
{PROTO_RLINK, STR_RLINK, 2, 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
#if defined(SKYARTEC_CC2500_INO)
{PROTO_SKYARTEC, STR_SKYARTEC, 0, NO_SUBTYPE, OPTION_RFTUNE },
#endif
#if defined(SLT_NRF24L01_INO)
{PROTO_SLT, STR_SLT, 5, STR_SUBTYPE_SLT, OPTION_RFTUNE },
#endif
#if defined(SYMAX_NRF24L01_INO)
{PROTO_SYMAX, STR_SYMAX, 2, STR_SUBTYPE_SYMAX, OPTION_NONE },
#endif
#if defined(TIGER_NRF24L01_INO)
{PROTO_TIGER, STR_TIGER , 0, NO_SUBTYPE, OPTION_NONE },
#endif
#if defined(TRAXXAS_CYRF6936_INO)
{PROTO_TRAXXAS, STR_TRAXXAS, 1, STR_SUBTYPE_TRAXXAS, OPTION_NONE },
#endif
#if defined(V2X2_NRF24L01_INO)
{PROTO_V2X2, STR_V2X2, 3, STR_SUBTYPE_V2X2, OPTION_NONE },
#endif
#if defined(V761_NRF24L01_INO)
{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(XK_NRF24L01_INO)
{PROTO_XK, STR_XK , 2, STR_SUBTYPE_XK, OPTION_RFTUNE },
#endif
#if defined(XN297DUMP_NRF24L01_INO)
{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(FAKE_NRF24L01_INO)
{PROTO_FAKE, STR_FAKE, 0, NO_SUBTYPE, OPTION_NONE },
#endif
{0x00, nullptr, 0, nullptr, 0 }
};
#endif

View File

@@ -0,0 +1,449 @@
/*
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/>.
*/
const char STR_FLYSKY[] ="FlySky";
const char STR_HUBSAN[] ="Hubsan";
const char STR_FRSKYD[] ="FrSky D";
const char STR_HISKY[] ="Hisky";
const char STR_V2X2[] ="V2x2";
const char STR_DSM[] ="DSM";
const char STR_DSM_RX[] ="DSM_RX";
const char STR_DEVO[] ="Devo";
const char STR_YD717[] ="YD717";
const char STR_KN[] ="KN";
const char STR_SYMAX[] ="SymaX";
const char STR_SLT[] ="SLT";
const char STR_CX10[] ="CX10";
const char STR_CG023[] ="CG023";
const char STR_BAYANG[] ="Bayang";
const char STR_FRSKYL[] ="FrSky L";
const char STR_FRSKYX[] ="FrSky X";
const char STR_FRSKYX2[] ="FrSkyX2";
const char STR_ESKY[] ="ESky";
const char STR_MT99XX[] ="MT99XX";
const char STR_MJXQ[] ="MJXq";
const char STR_SHENQI[] ="Shenqi";
const char STR_FY326[] ="FY326";
const char STR_FUTABA[] ="Futaba";
const char STR_J6PRO[] ="J6 Pro";
const char STR_JJRC345[] ="JJRC345";
const char STR_JOYSWAY[] ="JOYSWAY";
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[] ="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";
const char STR_ESKY150[] ="Esky150";
const char STR_ESKY150V2[] ="EskyV2";
const char STR_H8_3D[] ="H8 3D";
const char STR_CORONA[] ="Corona";
const char STR_CFLIE[] ="CFlie";
const char STR_HITEC[] ="Hitec";
const char STR_WFLY[] ="WFLY";
const char STR_WFLY2[] ="WFLY2";
const char STR_BUGS[] ="Bugs";
const char STR_BUGSMINI[] ="BugMini";
const char STR_TRAXXAS[] ="Traxxas";
const char STR_NCC1701[] ="NCC1701";
const char STR_E01X[] ="E01X";
const char STR_V911S[] ="V911S";
const char STR_GD00X[] ="GD00x";
const char STR_V761[] ="V761";
const char STR_KF606[] ="KF606";
const char STR_REDPINE[] ="Redpine";
const char STR_POTENSIC[] ="Potensi";
const char STR_ZSX[] ="ZSX";
const char STR_HEIGHT[] ="Height";
const char STR_SCANNER[] ="Scanner";
const char STR_FRSKY_RX[] ="FrSkyRX";
const char STR_AFHDS2A_RX[] ="FS2A_RX";
const char STR_HOTT[] ="HoTT";
const char STR_FX816[] ="FX816";
const char STR_BAYANG_RX[] ="BayanRX";
const char STR_PELIKAN[] ="Pelikan";
const char STR_TIGER[] ="Tiger";
const char STR_XK[] ="XK";
const char STR_XN297DUMP[] ="XN297DP";
const char STR_FRSKYR9[] ="FrSkyR9";
const char STR_PROPEL[] ="Propel";
const char STR_SKYARTEC[] ="Skyartc";
const char STR_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""Clo 8ch";
const char STR_SUBTYPE_HISKY[] = "\x05""Std\0 ""HK310";
const char STR_SUBTYPE_V2X2[] = "\x06""Std\0 ""JXD506""MR101\0";
const char STR_SUBTYPE_DSM[] = "\x04""2 1F""2 2F""X 1F""X 2F""Auto";
const char STR_SUBTYPE_DEVO[] = "\x04""8ch\0""10ch""12ch""6ch\0""7ch\0";
const char STR_SUBTYPE_YD717[] = "\x07""Std\0 ""SkyWlkr""Syma X4""XINXUN\0""NIHUI\0 ";
const char STR_SUBTYPE_KN[] = "\x06""WLtoys""FeiLun";
const char STR_SUBTYPE_SYMAX[] = "\x03""Std""X5C";
const char STR_SUBTYPE_SLT[] = "\x06""V1_6ch""V2_8ch""Q100\0 ""Q200\0 ""MR100\0";
const char STR_SUBTYPE_CX10[] = "\x07""Green\0 ""Blue\0 ""DM007\0 ""-\0 ""JC3015a""JC3015b""MK33041";
const char STR_SUBTYPE_CG023[] = "\x05""Std\0 ""YD829";
const char STR_SUBTYPE_BAYANG[] = "\x07""Std\0 ""H8S3D\0 ""X16 AH\0""IRDrone""DHD D4\0""QX100\0 ";
const char STR_SUBTYPE_MT99[] = "\x06""MT99\0 ""H7\0 ""YZ\0 ""LS\0 ""FY805\0""A180\0 ""Dragon";
const char STR_SUBTYPE_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""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";
const char STR_SUBTYPE_CABELL[] = "\x07""V3\0 ""V3 Telm""-\0 ""-\0 ""-\0 ""-\0 ""F-Safe\0""Unbind\0";
const char STR_SUBTYPE_H83D[] = "\x07""Std\0 ""H20H\0 ""H20Mini""H30Mini";
const char STR_SUBTYPE_CORONA[] = "\x05""V1\0 ""V2\0 ""FD V3";
const char STR_SUBTYPE_HITEC[] = "\x07""Optima\0""Opt Hub""Minima\0";
const char STR_SUBTYPE_BUGS_MINI[] = "\x06""Std\0 ""Bugs3H";
const char STR_SUBTYPE_TRAXXAS[] = "\x04""6519";
const char STR_SUBTYPE_E01X[] = "\x05""E012\0""E015\0""E016H";
const char STR_SUBTYPE_GD00X[] = "\x05""GD_V1""GD_V2";
const char STR_SUBTYPE_REDPINE[] = "\x04""Fast""Slow";
const char STR_SUBTYPE_POTENSIC[] = "\x03""A20";
const char STR_SUBTYPE_ZSX[] = "\x07""280JJRC";
const char STR_SUBTYPE_HEIGHT[] = "\x03""5ch""8ch";
const char STR_SUBTYPE_FX816[] = "\x03""P38";
const char STR_SUBTYPE_XN297DUMP[] = "\x07""250Kbps""1Mbps\0 ""2Mbps\0 ""Auto\0 ""NRF\0 ";
const char STR_SUBTYPE_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""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_FRSKYL[] = "\x08""LR12\0 ""LR12 6ch";
const char STR_SUBTYPE_WFLY[] = "\x05""WFR0x";
const char STR_SUBTYPE_WFLY2[] = "\x05""RF20x";
const char STR_SUBTYPE_HOTT[] = "\x07""Sync\0 ""No_Sync";
const char STR_SUBTYPE_PELIKAN[] = "\x04""Pro\0""Lite";
const char STR_SUBTYPE_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";
#define NO_SUBTYPE nullptr
#ifdef SEND_CPPM
const char STR_SUB_FRSKY_RX[] = "\x07""Multi\0 ""CloneTX""EraseTX""CPPM\0 ";
#define FRCPPM 4
const char STR_CPPM[] = "\x05""Multi""CPPM\0";
#define NBR_CPPM 2
#else
const char STR_SUB_FRSKY_RX[] = "\x07""Multi\0 ""CloneTX""EraseTX";
#define FRCPPM 3
#define STR_CPPM NO_SUBTYPE
#define NBR_CPPM 0
#endif
enum
{
OPTION_NONE,
OPTION_OPTION,
OPTION_RFTUNE,
OPTION_VIDFREQ,
OPTION_FIXEDID,
OPTION_TELEM,
OPTION_SRVFREQ,
OPTION_MAXTHR,
OPTION_RFCHAN,
OPTION_RFPOWER,
OPTION_WBUS,
};
const mm_protocol_definition multi_protocols[] = {
// Protocol number, Protocol String, Sub_protocol strings, Number of sub_protocols, Option type, Failsafe, ChMap, RF switch, Init, Callback
#if defined(MULTI_CONFIG_INO)
{PROTO_CONFIG, STR_CONFIG, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, 0, CONFIG_init, CONFIG_callback },
#endif
#if defined(ASSAN_NRF24L01_INO)
{PROTO_ASSAN, STR_ASSAN, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, ASSAN_init, ASSAN_callback },
#endif
#if defined(BAYANG_NRF24L01_INO)
{PROTO_BAYANG, STR_BAYANG, STR_SUBTYPE_BAYANG, 6, OPTION_TELEM, 0, 0, SW_NRF, BAYANG_init, BAYANG_callback },
#endif
#if defined(BAYANG_RX_NRF24L01_INO)
{PROTO_BAYANG_RX, STR_BAYANG_RX, STR_CPPM, NBR_CPPM, OPTION_NONE, 0, 0, SW_NRF, BAYANG_RX_init, BAYANG_RX_callback },
#endif
#if defined(BUGS_A7105_INO)
{PROTO_BUGS, STR_BUGS, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_A7105, BUGS_init, BUGS_callback },
#endif
#if defined(BUGSMINI_NRF24L01_INO)
{PROTO_BUGSMINI, STR_BUGSMINI, STR_SUBTYPE_BUGS_MINI, 2, OPTION_NONE, 0, 0, SW_NRF, BUGSMINI_init, BUGSMINI_callback },
#endif
#if defined(CABELL_NRF24L01_INO)
{PROTO_CABELL, STR_CABELL, STR_SUBTYPE_CABELL, 8, OPTION_OPTION, 0, 0, SW_NRF, CABELL_init, CABELL_callback },
#endif
#if defined(CFLIE_NRF24L01_INO)
{PROTO_CFLIE, STR_CFLIE, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, CFLIE_init, CFLIE_callback }, // review protocol
#endif
#if defined(CG023_NRF24L01_INO)
{PROTO_CG023, STR_CG023, STR_SUBTYPE_CG023, 2, OPTION_NONE, 0, 0, SW_NRF, CG023_init, CG023_callback },
#endif
#if defined(CORONA_CC2500_INO)
{PROTO_CORONA, STR_CORONA, STR_SUBTYPE_CORONA, 3, OPTION_RFTUNE, 0, 0, SW_CC2500, CORONA_init, CORONA_callback },
#endif
#if defined(CX10_NRF24L01_INO)
{PROTO_CX10, STR_CX10, STR_SUBTYPE_CX10, 7, OPTION_NONE, 0, 0, SW_NRF, CX10_init, CX10_callback },
#endif
#if defined(DEVO_CYRF6936_INO)
{PROTO_DEVO, STR_DEVO, STR_SUBTYPE_DEVO, 5, OPTION_FIXEDID, 1, 1, SW_CYRF, DEVO_init, DEVO_callback },
#endif
#if defined(DM002_NRF24L01_INO)
{PROTO_DM002, STR_DM002, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, DM002_init, DM002_callback },
#endif
#if defined(DSM_CYRF6936_INO)
{PROTO_DSM, STR_DSM, STR_SUBTYPE_DSM, 5, OPTION_MAXTHR, 0, 1, SW_CYRF, DSM_init, DSM_callback },
#endif
#if defined(DSM_RX_CYRF6936_INO)
{PROTO_DSM_RX, STR_DSM_RX, STR_CPPM, NBR_CPPM, OPTION_NONE, 0, 1, SW_CYRF, DSM_RX_init, DSM_RX_callback },
#endif
#if defined(E010R5_CYRF6936_INO)
{PROTO_E010R5, STR_E010R5, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_CYRF, E010R5_init, E010R5_callback },
#endif
#if defined(E016HV2_CC2500_INO)
{PROTO_E016HV2, STR_E016HV2, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_CC2500, E016HV2_init, E016HV2_callback },
#endif
#if defined(E01X_NRF24L01_INO)
{PROTO_E01X, STR_E01X, STR_SUBTYPE_E01X, 3, OPTION_OPTION, 0, 0, SW_NRF, E01X_init, E01X_callback },
#endif
#if defined(E129_CYRF6936_INO)
{PROTO_E129, STR_E129, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_CYRF, E129_init, E129_callback },
#endif
#if defined(ESKY_NRF24L01_INO)
{PROTO_ESKY, STR_ESKY, STR_SUBTYPE_ESKY, 2, OPTION_NONE, 0, 1, SW_NRF, ESKY_init, ESKY_callback },
#endif
#if defined(ESKY150_NRF24L01_INO)
{PROTO_ESKY150, STR_ESKY150, STR_SUBTYPE_ESKY150, 2, OPTION_NONE, 0, 0, SW_NRF, ESKY150_init, ESKY150_callback },
#endif
#if defined(ESKY150V2_CC2500_INO)
{PROTO_ESKY150V2, STR_ESKY150V2, STR_SUBTYPE_ESKY150V2, 1, OPTION_RFTUNE, 0, 1, SW_CC2500, ESKY150V2_init, ESKY150V2_callback },
#endif
#if defined(FLYSKY_A7105_INO)
{PROTO_FLYSKY, STR_FLYSKY, STR_SUBTYPE_FLYSKY, 5, OPTION_NONE, 0, 1, SW_A7105, FLYSKY_init, FLYSKY_callback },
#endif
#if defined(AFHDS2A_A7105_INO)
{PROTO_AFHDS2A, STR_AFHDS2A, STR_SUBTYPE_AFHDS2A, 8, OPTION_SRVFREQ, 1, 1, SW_A7105, AFHDS2A_init, AFHDS2A_callback },
#endif
#if defined(AFHDS2A_RX_A7105_INO)
{PROTO_AFHDS2A_RX, STR_AFHDS2A_RX,STR_CPPM, NBR_CPPM, OPTION_NONE, 0, 0, SW_A7105, AFHDS2A_RX_init, AFHDS2A_RX_callback },
#endif
#if defined(FQ777_NRF24L01_INO)
{PROTO_FQ777, STR_FQ777, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, FQ777_init, FQ777_callback },
#endif
//OpenTX 2.3.x issue: DO NOT CHANGE ORDER below
#if defined(FRSKY_RX_CC2500_INO)
{PROTO_FRSKY_RX, STR_FRSKY_RX, STR_SUB_FRSKY_RX, FRCPPM, OPTION_RFTUNE, 0, 0, SW_CC2500, FRSKY_RX_init, FRSKY_RX_callback },
#endif
#if defined(FRSKYD_CC2500_INO)
{PROTO_FRSKYD, STR_FRSKYD, STR_SUBTYPE_FRSKYD, 2, OPTION_RFTUNE, 0, 0, SW_CC2500, FRSKYD_init, FRSKYD_callback },
#endif
#if defined(FRSKYV_CC2500_INO)
{PROTO_FRSKYV, STR_FRSKYV, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_CC2500, FRSKYV_init, FRSKYV_callback },
#endif
#if defined(FRSKYX_CC2500_INO)
{PROTO_FRSKYX, STR_FRSKYX, STR_SUBTYPE_FRSKYX, 6, OPTION_RFTUNE, 1, 0, SW_CC2500, FRSKYX_init, FRSKYX_callback },
{PROTO_FRSKYX2, STR_FRSKYX2, STR_SUBTYPE_FRSKYX, 6, OPTION_RFTUNE, 1, 0, SW_CC2500, FRSKYX_init, FRSKYX_callback },
#endif
//OpenTX 2.3.x issue: DO NOT CHANGE ORDER above
#if defined(FRSKYL_CC2500_INO)
{PROTO_FRSKYL, STR_FRSKYL, STR_SUBTYPE_FRSKYL, 2, OPTION_RFTUNE, 0, 0, SW_CC2500, FRSKYL_init, FRSKYL_callback },
#endif
#if defined(FRSKYR9_SX1276_INO)
#if MULTI_5IN1_INTERNAL == T18
{PROTO_FRSKY_R9, STR_FRSKYR9, STR_SUBTYPE_FRSKYR9, 8, OPTION_NONE, 1, 0, 0, FRSKYR9_init, FRSKYR9_callback },
#else // DIY & T-Lite
{PROTO_FRSKY_R9, STR_FRSKYR9, STR_SUBTYPE_FRSKYR9, 8, OPTION_RFPOWER, 1, 0, 0, FRSKYR9_init, FRSKYR9_callback },
#endif
#endif
#if defined(FUTABA_CC2500_INO)
{PROTO_FUTABA, STR_FUTABA, STR_SUBTYPE_FUTABA, 1, OPTION_RFTUNE, 1, 1, SW_CC2500, SFHSS_init, SFHSS_callback },
#endif
#if defined(FX816_NRF24L01_INO)
{PROTO_FX816, STR_FX816, STR_SUBTYPE_FX816, 1, OPTION_NONE, 0, 0, SW_NRF, FX816_init, FX816_callback },
#endif
#if defined(FY326_NRF24L01_INO)
{PROTO_FY326, STR_FY326, STR_SUBTYPE_FY326, 2, OPTION_NONE, 0, 0, SW_NRF, FY326_init, FY326_callback },
#endif
#if defined(GD00X_CCNRF_INO)
{PROTO_GD00X, STR_GD00X, STR_SUBTYPE_GD00X, 2, OPTION_RFTUNE, 0, 0, SW_NRF, GD00X_init, GD00X_callback },
#endif
#if defined(GW008_NRF24L01_INO)
{PROTO_GW008, STR_GW008, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, GW008_init, GW008_callback },
#endif
#if defined(H8_3D_NRF24L01_INO)
{PROTO_H8_3D, STR_H8_3D, STR_SUBTYPE_H83D, 4, OPTION_NONE, 0, 0, SW_NRF, H8_3D_init, H8_3D_callback },
#endif
#if defined(HEIGHT_A7105_INO)
{PROTO_HEIGHT, STR_HEIGHT, STR_SUBTYPE_HEIGHT, 2, OPTION_NONE, 0, 0, SW_A7105, HEIGHT_init, HEIGHT_callback },
#endif
#if defined(HISKY_NRF24L01_INO)
{PROTO_HISKY, STR_HISKY, STR_SUBTYPE_HISKY, 2, OPTION_NONE, 1, 1, SW_NRF, HISKY_init, HISKY_callback },
#endif
#if defined(HITEC_CC2500_INO)
{PROTO_HITEC, STR_HITEC, STR_SUBTYPE_HITEC, 3, OPTION_RFTUNE, 0, 0, SW_CC2500, HITEC_init, HITEC_callback },
#endif
#if defined(HONTAI_NRF24L01_INO)
{PROTO_HONTAI, STR_HONTAI, STR_SUBTYPE_HONTAI, 4, OPTION_NONE, 0, 0, SW_NRF, HONTAI_init, HONTAI_callback },
#endif
#if defined(HOTT_CC2500_INO)
{PROTO_HOTT, STR_HOTT, STR_SUBTYPE_HOTT, 2, OPTION_RFTUNE, 1, 0, SW_CC2500, HOTT_init, HOTT_callback },
#endif
#if defined(HUBSAN_A7105_INO)
{PROTO_HUBSAN, STR_HUBSAN, STR_SUBTYPE_HUBSAN, 3, OPTION_VIDFREQ, 0, 0, SW_A7105, HUBSAN_init, HUBSAN_callback },
#endif
#if defined(J6PRO_CYRF6936_INO)
{PROTO_J6PRO, STR_J6PRO, NO_SUBTYPE, 0, OPTION_NONE, 0, 1, SW_CYRF, J6PRO_init, J6PRO_callback },
#endif
#if defined(JJRC345_NRF24L01_INO)
{PROTO_JJRC345, STR_JJRC345, STR_SUBTYPE_JJRC345, 2, OPTION_NONE, 0, 0, SW_NRF, JJRC345_init, JJRC345_callback },
#endif
#if defined(JOYSWAY_A7105_INO)
{PROTO_JOYSWAY, STR_JOYSWAY, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_A7105, JOYSWAY_init, JOYSWAY_callback },
#endif
#if defined(KF606_CCNRF_INO)
{PROTO_KF606, STR_KF606, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, KF606_init, KF606_callback },
#endif
#if defined(KN_NRF24L01_INO)
{PROTO_KN, STR_KN, STR_SUBTYPE_KN, 2, OPTION_NONE, 0, 0, SW_NRF, KN_init, KN_callback },
#endif
#if defined(KYOSHO_A7105_INO)
{PROTO_KYOSHO, STR_KYOSHO, STR_SUBTYPE_KYOSHO, 2, OPTION_NONE, 0, 1, SW_A7105, KYOSHO_init, KYOSHO_callback },
#endif
#if defined(LOLI_NRF24L01_INO)
{PROTO_LOLI, STR_LOLI, NO_SUBTYPE, 0, OPTION_NONE, 1, 0, SW_NRF, LOLI_init, LOLI_callback },
#endif
#if defined(MJXQ_NRF24L01_INO)
{PROTO_MJXQ, STR_MJXQ, STR_SUBTYPE_MJXQ, 7, OPTION_RFTUNE, 0, 0, SW_NRF, MJXQ_init, MJXQ_callback },
#endif
#if defined(MLINK_CYRF6936_INO)
{PROTO_MLINK, STR_MLINK, NO_SUBTYPE, 0, OPTION_NONE, 1, 0, SW_CYRF, MLINK_init, MLINK_callback },
#endif
#if defined(MT99XX_NRF24L01_INO)
{PROTO_MT99XX, STR_MT99XX, STR_SUBTYPE_MT99, 7, OPTION_NONE, 0, 0, SW_NRF, MT99XX_init, MT99XX_callback },
#endif
#if defined(NCC1701_NRF24L01_INO)
{PROTO_NCC1701, STR_NCC1701, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, NCC_init, NCC_callback },
#endif
#if defined(OMP_CC2500_INO)
{PROTO_OMP, STR_OMP, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, OMP_init, OMP_callback },
#endif
#if defined(PELIKAN_A7105_INO)
{PROTO_PELIKAN, STR_PELIKAN, STR_SUBTYPE_PELIKAN, 2, OPTION_NONE, 0, 1, SW_A7105, PELIKAN_init, PELIKAN_callback },
#endif
#if defined(POTENSIC_NRF24L01_INO)
{PROTO_POTENSIC, STR_POTENSIC, STR_SUBTYPE_POTENSIC, 1, OPTION_NONE, 0, 0, SW_NRF, POTENSIC_init, POTENSIC_callback },
#endif
#if defined(PROPEL_NRF24L01_INO)
{PROTO_PROPEL, STR_PROPEL, STR_SUBTYPE_PROPEL, 1, OPTION_NONE, 0, 0, SW_NRF, PROPEL_init, PROPEL_callback },
#endif
#if defined(CX10_NRF24L01_INO)
{PROTO_Q2X2, STR_Q2X2, STR_SUBTYPE_Q2X2, 3, OPTION_NONE, 0, 0, SW_NRF, CX10_init, CX10_callback },
#endif
#if defined(Q303_NRF24L01_INO)
{PROTO_Q303, STR_Q303, STR_SUBTYPE_Q303, 4, OPTION_NONE, 0, 0, SW_NRF, Q303_init, Q303_callback },
#endif
#if defined(Q90C_CCNRF_INO)
{PROTO_Q90C, STR_Q90C, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, Q90C_init, Q90C_callback },
#endif
#if defined(RLINK_CC2500_INO)
{PROTO_RLINK, STR_RLINK, STR_SUBTYPE_RLINK, 3, OPTION_RFTUNE, 0, 0, SW_CC2500, RLINK_init, RLINK_callback },
#endif
#if defined(REALACC_NRF24L01_INO)
{PROTO_REALACC, STR_REALACC, STR_SUBTYPE_REALACC, 1, OPTION_NONE, 0, 0, SW_NRF, REALACC_init, REALACC_callback },
#endif
#if defined(REDPINE_CC2500_INO)
{PROTO_REDPINE, STR_REDPINE, STR_SUBTYPE_REDPINE, 2, OPTION_RFTUNE, 0, 0, SW_CC2500, REDPINE_init, REDPINE_callback },
#endif
#if defined(SCANNER_CC2500_INO)
{PROTO_SCANNER, STR_SCANNER, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_CC2500, SCANNER_init, SCANNER_callback },
#endif
#if defined(SHENQI_NRF24L01_INO)
{PROTO_SHENQI, STR_SHENQI, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, SHENQI_init, SHENQI_callback },
#endif
#if defined(SKYARTEC_CC2500_INO)
{PROTO_SKYARTEC, STR_SKYARTEC, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 1, SW_CC2500, SKYARTEC_init, SKYARTEC_callback },
#endif
#if defined(SLT_CCNRF_INO)
{PROTO_SLT, STR_SLT, STR_SUBTYPE_SLT, 5, OPTION_RFTUNE, 0, 1, SW_NRF, SLT_init, SLT_callback },
#endif
#if defined(SYMAX_NRF24L01_INO)
{PROTO_SYMAX, STR_SYMAX, STR_SUBTYPE_SYMAX, 2, OPTION_NONE, 0, 0, SW_NRF, SYMAX_init, SYMAX_callback },
#endif
#if defined(TIGER_NRF24L01_INO)
{PROTO_TIGER, STR_TIGER, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, TIGER_init, TIGER_callback },
#endif
#if defined(TRAXXAS_CYRF6936_INO)
{PROTO_TRAXXAS, STR_TRAXXAS, STR_SUBTYPE_TRAXXAS, 1, OPTION_NONE, 0, 0, SW_CYRF, TRAXXAS_init, TRAXXAS_callback },
#endif
#if defined(V2X2_NRF24L01_INO)
{PROTO_V2X2, STR_V2X2, STR_SUBTYPE_V2X2, 3, OPTION_NONE, 0, 0, SW_NRF, V2X2_init, V2X2_callback },
#endif
#if defined(V761_NRF24L01_INO)
{PROTO_V761, STR_V761, STR_SUBTYPE_V761, 2, OPTION_NONE, 0, 0, SW_NRF, V761_init, V761_callback },
#endif
#if defined(V911S_CCNRF_INO)
{PROTO_V911S, STR_V911S, STR_SUBTYPE_V911S, 2, OPTION_RFTUNE, 0, 0, SW_NRF, V911S_init, V911S_callback },
#endif
#if defined(WK2x01_CYRF6936_INO)
{PROTO_WK2x01, STR_WK2x01, STR_SUBTYPE_WK2x01, 6, OPTION_NONE, 1, 1, SW_CYRF, WK_init, WK_callback },
#endif
#if defined(WFLY_CYRF6936_INO)
{PROTO_WFLY, STR_WFLY, STR_SUBTYPE_WFLY, 1, OPTION_NONE, 1, 0, SW_CYRF, WFLY_init, WFLY_callback },
#endif
#if defined(WFLY2_A7105_INO)
{PROTO_WFLY2, STR_WFLY2, STR_SUBTYPE_WFLY2, 1, OPTION_OPTION, 1, 0, SW_A7105, WFLY2_init, WFLY2_callback },
// {PROTO_WFLY2, STR_WFLY2, STR_SUBTYPE_WFLY2, 1, OPTION_WBUS, 1, 0, SW_A7105, WFLY2_init, WFLY2_callback },// crash OpenTX...
#endif
#if defined(XK_NRF24L01_INO)
{PROTO_XK, STR_XK, STR_SUBTYPE_XK, 2, OPTION_RFTUNE, 0, 0, SW_NRF, XK_init, XK_callback },
#endif
#if defined(XN297DUMP_NRF24L01_INO)
{PROTO_XN297DUMP, STR_XN297DUMP, STR_SUBTYPE_XN297DUMP, 5, OPTION_RFCHAN, 0, 0, SW_NRF, XN297Dump_init, XN297Dump_callback },
#endif
#if defined(YD717_NRF24L01_INO)
{PROTO_YD717, STR_YD717, STR_SUBTYPE_YD717, 5, OPTION_NONE, 0, 0, SW_NRF, YD717_init, YD717_callback },
#endif
#if defined(ZSX_NRF24L01_INO)
{PROTO_ZSX, STR_ZSX, STR_SUBTYPE_ZSX, 1, OPTION_NONE, 0, 0, SW_NRF, ZSX_init, ZSX_callback },
#endif
#if defined(TEST_CC2500_INO)
{PROTO_TEST, STR_TEST, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, TEST_init, TEST_callback },
#endif
#if defined(NANORF_NRF24L01_INO)
{PROTO_NANORF, STR_NANORF, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, NANORF_init, NANORF_callback },
#endif
{0x00, nullptr, nullptr, 0, 0, 0, 0, 0, nullptr, nullptr }
};

View File

@@ -18,15 +18,17 @@
//******************
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_REVISION 1
#define VERSION_PATCH_LEVEL 59
#define VERSION_REVISION 2
#define VERSION_PATCH_LEVEL 61
#define MODE_SERIAL 0
//******************
// Protocols
//******************
enum PROTOCOLS
{
MODE_SERIAL = 0, // Serial commands
PROTO_CONFIG = 0, // Module config
PROTO_FLYSKY = 1, // =>A7105
PROTO_HUBSAN = 2, // =>A7105
PROTO_FRSKYD = 3, // =>CC2500
@@ -47,7 +49,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
@@ -102,9 +104,16 @@ enum PROTOCOLS
PROTO_KYOSHO = 73, // =>A7105
PROTO_RLINK = 74, // =>CC2500
PROTO_REALACC = 76, // =>NRF24L01
PROTO_OMP = 77, // =>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_JOYSWAY = 84, // =>A7105
PROTO_FAKE = 126, // =>CC2500+NRF24L01
PROTO_NANORF = 126, // =>NRF24L01
PROTO_TEST = 127, // =>CC2500
};
@@ -142,10 +151,10 @@ enum Hisky
};
enum DSM
{
DSM2_22 = 0,
DSM2_11 = 1,
DSMX_22 = 2,
DSMX_11 = 3,
DSM2_1F = 0,
DSM2_2F = 1,
DSMX_1F = 2,
DSMX_2F = 3,
DSM_AUTO = 4,
};
enum YD717
@@ -213,6 +222,8 @@ enum MT99XX
YZ = 2,
LS = 3,
FY805 = 4,
A180 = 5,
DRAGON = 6,
};
enum MJXQ
{
@@ -366,6 +377,8 @@ enum FRSKY_RX
{
FRSKY_RX = 0,
FRSKY_CLONE = 1,
FRSKY_ERASE = 2,
FRSKY_CPPM = 3,
};
enum FRSKYL
@@ -398,12 +411,32 @@ enum HEIGHT
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
#define AUTOBIND 1
#define NO_AUTOBIND 0
//PPM protocols
struct PPM_Parameters
{
uint8_t protocol;
@@ -415,6 +448,33 @@ struct PPM_Parameters
uint32_t chan_order;
};
//Callback
typedef uint16_t (*uint16_function_t) (void); //pointer to a function with no parameters which return an uint16_t integer
typedef void (*void_function_t ) (void); //pointer to a function with no parameters which returns nothing
//Protocols definition
struct mm_protocol_definition {
uint8_t protocol;
const char *ProtoString;
const char *SubProtoString;
uint8_t nbrSubProto : 4;
uint8_t optionType : 4;
uint8_t failSafe : 1;
uint8_t chMap : 1;
uint8_t rfSwitch : 2;
void_function_t Init;
uint16_function_t CallBack;
};
extern const mm_protocol_definition multi_protocols[];
enum RF_SWITCH
{
SW_A7105 = 0, //antenna RF1
SW_CC2500 = 1, //antenna RF2
SW_NRF = 2, //antenna RF3
SW_CYRF = 3, //antenna RF4
};
// Telemetry
enum MultiPacketTypes
{
@@ -432,17 +492,13 @@ enum MultiPacketTypes
MULTI_TELEMETRY_AFHDS2A_AC = 12,
MULTI_TELEMETRY_RX_CHANNELS = 13,
MULTI_TELEMETRY_HOTT = 14,
MULTI_TELEMETRY_MLINK = 15,
MULTI_TELEMETRY_CONFIG = 16,
};
// Macros
#define NOP() __asm__ __volatile__("nop")
//***************
//*** Tests ***
//***************
#define IS_FAILSAFE_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_SFHSS || protocol==PROTO_WK2x01 || protocol== PROTO_HOTT || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKY_R9)
#define IS_CHMAP_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_SFHSS || protocol==PROTO_WK2x01 || protocol== PROTO_DSM || protocol==PROTO_SLT || protocol==PROTO_FLYSKY || protocol==PROTO_ESKY || protocol==PROTO_J6PRO || protocol==PROTO_PELIKAN || protocol==PROTO_SKYARTEC || protocol==PROTO_ESKY150V2 || protocol==PROTO_DSM_RX)
//***************
//*** Flags ***
//***************
@@ -547,8 +603,9 @@ enum MultiPacketTypes
//********************
#if defined(STM32_BOARD) && (defined (DEBUG_SERIAL) || defined (ARDUINO_MULTI_DEBUG))
uint16_t debug_time=0;
#define debug(msg, ...) {char debug_buf[64]; sprintf(debug_buf, msg, ##__VA_ARGS__); Serial.write(debug_buf);}
#define debugln(msg, ...) {char debug_buf[64]; sprintf(debug_buf, msg "\r\n", ##__VA_ARGS__); Serial.write(debug_buf);}
char debug_buf[64];
#define debug(msg, ...) { sprintf(debug_buf, msg, ##__VA_ARGS__); Serial.write(debug_buf);}
#define debugln(msg, ...) { sprintf(debug_buf, msg "\r\n", ##__VA_ARGS__); Serial.write(debug_buf);}
#define debug_time(msg) { uint16_t debug_time_TCNT1=TCNT1; debug_time=debug_time_TCNT1-debug_time; debug(msg "%u", debug_time>>1); debug_time=debug_time_TCNT1; }
#define debugln_time(msg) { uint16_t debug_time_TCNT1=TCNT1; debug_time=debug_time_TCNT1-debug_time; debug(msg "%u\r\n", debug_time>>1); debug_time=debug_time_TCNT1; }
#else
@@ -682,6 +739,10 @@ enum CYRF_POWER
#define CYRF_RANGE_POWER CYRF_POWER_1 // 1/30 of the full power distance
#define CYRF_BIND_POWER CYRF_POWER_0
// SX1276
#define JP_T18 1
#define JP_TLite 2
enum TXRX_State {
TXRX_OFF,
TX_EN,
@@ -720,6 +781,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 ***
//****************************************
@@ -734,8 +804,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
@@ -757,7 +828,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
MJXQ 18
SHENQI 19
FY326 20
SFHSS 21
Futaba 21
J6PRO 22
FQ777 23
ASSAN 24
@@ -813,6 +884,12 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
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
@@ -833,10 +910,10 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
Hisky 0
HK310 1
sub_protocol==DSM
DSM2_22 0
DSM2_11 1
DSMX_22 2
DSMX_11 3
DSM2_1F 0
DSM2_2F 1
DSMX_1F 2
DSMX_2F 3
DSM_AUTO 4
sub_protocol==YD717
YD717 0
@@ -1006,6 +1083,13 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
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;
@@ -1032,37 +1116,11 @@ 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
Based on #define MULTI_STATUS
Serial: 100000 Baud 8e2 (same as input)
Format: header (2 bytes) + data (variable)
[0] = 'M' (0x4d)
[1] Length (excluding the 2 header bytes)
[2-xx] data
Type = 0x01 Multimodule Status:
[2] Flags
0x01 = Input signal detected
0x02 = Serial mode enabled
0x04 = Protocol is valid
0x08 = Module is in binding mode
0x10 = Module waits a bind event to load the protocol
0x20 = Current protocol supports failsafe
0x40 = Current protocol supports disable channel mapping
0x80 = Data buffer is almost full
[3] major
[4] minor
[5] revision
[6] patchlevel,
version of multi code, should be displayed as major.minor.revision.patchlevel
*/
/*
Multiprotocol telemetry/command definition for OpenTX
Based on #define MULTI_TELEMETRY enables OpenTX to get the multimodule status and select the correct telemetry type automatically.
Multiprotocol telemetry/command definition for OpenTX and erskyTX
Based on #define MULTI_TELEMETRY enables OpenTX and erskyTX to get the multimodule status and select the correct telemetry type automatically.
Serial: 100000 Baud 8e2 (same as input)
@@ -1103,16 +1161,17 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
[11] Prev valid protocol number, can be used to skip invalid protocols
[12..18] Protocol name [7], not null terminated if prototcol len == 7
[19>>4] Option text to be displayed:
OPTION_NONE 0
OPTION_OPTION 1
OPTION_RFTUNE 2
OPTION_VIDFREQ 3
OPTION_FIXEDID 4
OPTION_TELEM 5
OPTION_SRVFREQ 6
OPTION_MAXTHR 7
OPTION_RFCHAN 8
OPTION_RFPOWER 9
OPTION_NONE 0 Hidden field
OPTION_OPTION 1 "Option:" value=-128..0(default)..127
OPTION_RFTUNE 2 "RF freq tune:" value=-128..0(default)..127
OPTION_VIDFREQ 3 "Video freq:" value=-128..0(default)..127
OPTION_FIXEDID 4 "ID type:" value="Auto":0(default), "Fixed":1
OPTION_TELEM 5 "Telem:" value="Off":0(default), "On":1, "Off+Aux":2, "On+Aux":3
OPTION_SRVFREQ 6 "Servo freq(Hz):" value="50":0(default).."400":70 => display=50+5*option with option=0..70
OPTION_MAXTHR 7 "Max throw:" value="Disabled":0, "Enabled":1
OPTION_RFCHAN 8 "Select RF chan:" value=-128..0(default)..127
OPTION_RFPOWER 9 "RF power:" "1.6mW":0(default),"2.0mW":1,"2.5mW":2,"3.2mW":3,"4.0mW":4,"5.0mW":5,"6.3mW":6,"7.9mW":7,"10mW\0":8,"13mW\0":9,"16mW\0":10,"20mW\0":11,"25mW\0":12,"32mW\0":13,"40mW\0":14,"50mW\0":15
OPTION_WBUS 10 "Output:" "WBUS":0(default),"PPM":1
[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.
@@ -1186,4 +1245,10 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
data[3] = page
data[4-13] = data
Type 0x0F M-Link telemetry
length: 10
data[0] = TX_RSSI
data[1] = TX_LQI
data[2] = telem_type
data[3-9] = data
*/

File diff suppressed because it is too large Load Diff

View File

@@ -31,25 +31,16 @@ enum {
NCC_RX3,
};
static void __attribute__((unused)) NCC_init()
static void __attribute__((unused)) NCC_RF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\xE7\xE7\xC7\xD7\x67",5);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\xE7\xE7\xC7\xD7\x67",5);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, NCC_RX_PACKET_LEN); // Enable rx pipe 0
NRF24L01_SetBitrate(NRF24L01_BR_250K); // NRF24L01_BR_1M, NRF24L01_BR_2M, NRF24L01_BR_250K
NRF24L01_SetPower();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC) // switch to TX mode and disable CRC
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, NCC_RX_PACKET_LEN); // Enable rx pipe 0
NRF24L01_SetBitrate(NRF24L01_BR_250K); // NRF24L01_BR_1M, NRF24L01_BR_2M, NRF24L01_BR_250K
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC) // switch to TX mode and disable CRC
| (1 << NRF24L01_00_CRCO)
| (1 << NRF24L01_00_PWR_UP)
| (0 << NRF24L01_00_PRIM_RX));
@@ -58,11 +49,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 +61,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]);
}
@@ -247,7 +238,7 @@ const uint8_t PROGMEM NCC_TX_DATA[][6]= {
{ 0xC2, 0x93, 0x55, 0x44, 0x4C, 0x0B },
};
uint16_t initNCC(void)
void NCC_init(void)
{
BIND_IN_PROGRESS; // autobind protocol
@@ -269,9 +260,8 @@ uint16_t initNCC(void)
hopping_frequency[4]=0x08; // bind channel 1
hopping_frequency[5]=0x2A; // bind channel 2
hopping_frequency_no=4; // start with bind
NCC_init();
NCC_RF_init();
phase=NCC_BIND_TX1;
return 10000;
}
#endif

View File

@@ -16,7 +16,7 @@
#ifdef NRF24L01_INSTALLED
#include "iface_nrf24l01.h"
#include "iface_xn297.h"
//---------------------------
// NRF24L01+ SPI Specific Functions
@@ -29,6 +29,19 @@ void NRF24L01_Initialize()
rf_setup = 0x09;
prev_power = 0x00; // Make sure prev_power is inline with current power
XN297_SetScrambledMode(XN297_SCRAMBLED);
//Load most likely default NRF config
NRF24L01_FlushTx();
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_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01); // Set feature bits off and enable the command NRF24L01_B0_TX_PYLD_NOACK
NRF24L01_SetPower();
NRF24L01_SetTxRxMode(TX_EN); // Clear data ready, data sent, retransmit and enable CRC 16bits, ready for TX
}
void NRF24L01_WriteReg(uint8_t reg, uint8_t data)
@@ -117,13 +130,13 @@ static uint8_t NRF24L01_GetDynamicPayloadSize()
return len;
}
void NRF24L01_Activate(uint8_t code)
/*void NRF24L01_Activate(uint8_t code)
{
NRF_CSN_off;
SPI_Write(ACTIVATE);
SPI_Write(code);
NRF_CSN_on;
}
}*/
void NRF24L01_SetBitrate(uint8_t bitrate)
{
@@ -217,13 +230,6 @@ void NRF24L01_SetTxRxMode(enum TXRX_State mode)
void NRF24L01_Reset()
{
//** not in deviation but needed to hot switch between models
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x00); // Set feature bits off
NRF24L01_Activate(0x73);
//**
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_Strobe(0xff); // NOP
@@ -244,342 +250,6 @@ uint8_t NRF24L01_packet_ack()
return PKT_PENDING;
}
///////////////
// XN297 emulation layer
uint8_t xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
uint8_t xn297_addr_len;
uint8_t xn297_tx_addr[5];
uint8_t xn297_rx_addr[5];
uint8_t xn297_crc = 0;
// xn297 address / pcf / payload scramble table
const uint8_t xn297_scramble[] = {
0xE3, 0xB1, 0x4B, 0xEA, 0x85, 0xBC, 0xE5, 0x66,
0x0D, 0xAE, 0x8C, 0x88, 0x12, 0x69, 0xEE, 0x1F,
0xC7, 0x62, 0x97, 0xD5, 0x0B, 0x79, 0xCA, 0xCC,
0x1B, 0x5D, 0x19, 0x10, 0x24, 0xD3, 0xDC, 0x3F,
0x8E, 0xC5, 0x2F, 0xAA, 0x16, 0xF3, 0x95 };
// scrambled, standard mode crc xorout table
const uint16_t PROGMEM xn297_crc_xorout_scrambled[] = {
0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C,
0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B,
0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7,
0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,
0x2138, 0x129F, 0xB3A0, 0x2988, 0x23CA, 0xC0CB,
0x0C6C, 0xB329, 0xA0A1, 0x0A16, 0xA9D0 };
// unscrambled, standard mode crc xorout table
const uint16_t PROGMEM xn297_crc_xorout[] = {
0x0000, 0x3D5F, 0xA6F1, 0x3A23, 0xAA16, 0x1CAF,
0x62B2, 0xE0EB, 0x0821, 0xBE07, 0x5F1A, 0xAF15,
0x4F0A, 0xAD24, 0x5E48, 0xED34, 0x068C, 0xF2C9,
0x1852, 0xDF36, 0x129D, 0xB17C, 0xD5F5, 0x70D7,
0xB798, 0x5133, 0x67DB, 0xD94E, 0x0A5B, 0xE445,
0xE6A5, 0x26E7, 0xBDAB, 0xC379, 0x8E20 };
// scrambled enhanced mode crc xorout table
const uint16_t PROGMEM xn297_crc_xorout_scrambled_enhanced[] = {
0x0000, 0x7EBF, 0x3ECE, 0x07A4, 0xCA52, 0x343B,
0x53F8, 0x8CD0, 0x9EAC, 0xD0C0, 0x150D, 0x5186,
0xD251, 0xA46F, 0x8435, 0xFA2E, 0x7EBD, 0x3C7D,
0x94E0, 0x3D5F, 0xA685, 0x4E47, 0xF045, 0xB483,
0x7A1F, 0xDEA2, 0x9642, 0xBF4B, 0x032F, 0x01D2,
0xDC86, 0x92A5, 0x183A, 0xB760, 0xA953 };
// unscrambled enhanced mode crc xorout table
// unused so far
#ifdef XN297DUMP_NRF24L01_INO
const uint16_t xn297_crc_xorout_enhanced[] = {
0x0000, 0x8BE6, 0xD8EC, 0xB87A, 0x42DC, 0xAA89,
0x83AF, 0x10E4, 0xE83E, 0x5C29, 0xAC76, 0x1C69,
0xA4B2, 0x5961, 0xB4D3, 0x2A50, 0xCB27, 0x5128,
0x7CDB, 0x7A14, 0xD5D2, 0x57D7, 0xE31D, 0xCE42,
0x648D, 0xBF2D, 0x653B, 0x190C, 0x9117, 0x9A97,
0xABFC, 0xE68E, 0x0DE7, 0x28A2, 0x1965 };
#endif
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;
if (len < 3) len = 3;
uint8_t buf[] = { 0x55, 0x0F, 0x71, 0x0C, 0x00 }; // bytes for XN297 preamble 0xC710F55 (28 bit)
xn297_addr_len = len;
if (xn297_addr_len < 4)
for (uint8_t i = 0; i < 4; ++i)
buf[i] = buf[i+1];
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, buf, 5);
// Receive address is complicated. We need to use scrambled actual address as a receive address
// but the TX code now assumes fixed 4-byte transmit address for preamble. We need to adjust it
// first. Also, if the scrambled address begins with 1 nRF24 will look for preamble byte 0xAA
// instead of 0x55 to ensure enough 0-1 transitions to tune the receiver. Still need to experiment
// with receiving signals.
memcpy(xn297_tx_addr, addr, len);
}
void XN297_SetRXAddr(const uint8_t* addr, uint8_t len)
{
if (len > 5) len = 5;
if (len < 3) len = 3;
uint8_t buf[] = { 0, 0, 0, 0, 0 };
memcpy(buf, addr, len);
memcpy(xn297_rx_addr, addr, len);
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
buf[i] = xn297_rx_addr[i];
if(xn297_scramble_enabled)
buf[i] ^= xn297_scramble[xn297_addr_len-i-1];
}
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, buf, 5);
}
void XN297_Configure(uint8_t flags)
{
xn297_crc = !!(flags & _BV(NRF24L01_00_EN_CRC));
flags &= ~(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xFF);
}
void XN297_SetScrambledMode(const uint8_t mode)
{
xn297_scramble_enabled = mode;
}
void XN297_WritePayload(uint8_t* msg, uint8_t len)
{
uint8_t buf[32];
uint8_t last = 0;
if (xn297_addr_len < 4)
{
// If address length (which is defined by receive address length)
// is less than 4 the TX address can't fit the preamble, so the last
// byte goes here
buf[last++] = 0x55;
}
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
buf[last] = xn297_tx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[i];
last++;
}
for (uint8_t i = 0; i < len; ++i)
{
// bit-reverse bytes in packet
buf[last] = bit_reverse(msg[i]);
if(xn297_scramble_enabled)
buf[last] ^= xn297_scramble[xn297_addr_len+i];
last++;
}
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);
if(xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
else
crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]);
buf[last++] = crc >> 8;
buf[last++] = crc & 0xff;
}
NRF24L01_WritePayload(buf, last);
}
void XN297_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
{
uint8_t packet[32];
uint8_t scramble_index=0;
uint8_t last = 0;
static uint8_t pid=0;
// address
if (xn297_addr_len < 4)
{
// If address length (which is defined by receive address length)
// is less than 4 the TX address can't fit the preamble, so the last
// byte goes here
packet[last++] = 0x55;
}
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
packet[last] = xn297_tx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
last++;
}
// pcf
packet[last] = (len << 1) | (pid>>1);
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
last++;
packet[last] = (pid << 7) | (noack << 6);
// payload
packet[last]|= bit_reverse(msg[0]) >> 2; // first 6 bit of payload
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
for (uint8_t i = 0; i < len-1; ++i)
{
last++;
packet[last] = (bit_reverse(msg[i]) << 6) | (bit_reverse(msg[i+1]) >> 2);
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++];
}
last++;
packet[last] = bit_reverse(msg[len-1]) << 6; // last 2 bit of payload
if(xn297_scramble_enabled)
packet[last] ^= xn297_scramble[scramble_index++] & 0xc0;
// 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, packet[i], 8);
crc = crc16_update(crc, packet[last] & 0xc0, 2);
if (xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
//else
// crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
packet[last++] |= (crc >> 8) >> 2;
packet[last++] = ((crc >> 8) << 6) | ((crc & 0xff) >> 2);
packet[last++] = (crc & 0xff) << 6;
}
NRF24L01_WritePayload(packet, last);
pid++;
if(pid>3)
pid=0;
}
boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
{ //!!! Don't forget if using CRC to do a +2 on any of the used NRF24L01_11_RX_PW_Px !!!
uint8_t buf[32];
if (xn297_crc)
NRF24L01_ReadPayload(buf, len+2); // Read payload + CRC
else
NRF24L01_ReadPayload(buf, len);
// Decode payload
for(uint8_t i=0; i<len; i++)
{
uint8_t b_in=buf[i];
if(xn297_scramble_enabled)
b_in ^= xn297_scramble[i+xn297_addr_len];
msg[i] = bit_reverse(b_in);
}
if (!xn297_crc)
return true; // No CRC so OK by default...
// Calculate CRC
uint16_t crc = 0xb5d2;
//process address
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
uint8_t b_in=xn297_rx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
b_in ^= xn297_scramble[i];
crc = crc16_update(crc, b_in, 8);
}
//process payload
for (uint8_t i = 0; i < len; ++i)
crc = crc16_update(crc, buf[i], 8);
//xorout
if(xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
else
crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]);
//test
if( (crc >> 8) == buf[len] && (crc & 0xff) == buf[len+1])
return true; // CRC OK
return false; // CRC NOK
}
uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
{ //!!! Don't forget do a +2 and if using CRC add +2 on any of the used NRF24L01_11_RX_PW_Px !!!
uint8_t buffer[32];
uint8_t pcf_size; // pcf payload size
if (xn297_crc)
NRF24L01_ReadPayload(buffer, len+4); // Read pcf + payload + CRC
else
NRF24L01_ReadPayload(buffer, len+2); // Read pcf + payload
pcf_size = buffer[0];
if(xn297_scramble_enabled)
pcf_size ^= xn297_scramble[xn297_addr_len];
pcf_size = pcf_size >> 1;
for(int i=0; i<len; i++)
{
msg[i] = bit_reverse((buffer[i+1] << 2) | (buffer[i+2] >> 6));
if(xn297_scramble_enabled)
msg[i] ^= bit_reverse((xn297_scramble[xn297_addr_len+i+1] << 2) |
(xn297_scramble[xn297_addr_len+i+2] >> 6));
}
if (!xn297_crc)
return pcf_size; // No CRC so OK by default...
// Calculate CRC
uint16_t crc = 0xb5d2;
//process address
for (uint8_t i = 0; i < xn297_addr_len; ++i)
{
uint8_t b_in=xn297_rx_addr[xn297_addr_len-i-1];
if(xn297_scramble_enabled)
b_in ^= xn297_scramble[i];
crc = crc16_update(crc, b_in, 8);
}
//process payload
for (uint8_t i = 0; i < len+1; ++i)
crc = crc16_update(crc, buffer[i], 8);
crc = crc16_update(crc, buffer[len+1] & 0xc0, 2);
//xorout
if (xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
#ifdef XN297DUMP_NRF24L01_INO
else
crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
#endif
uint16_t crcxored=(buffer[len+1]<<10)|(buffer[len+2]<<2)|(buffer[len+3]>>6) ;
if( crc == crcxored)
return pcf_size; // CRC OK
return 0; // CRC NOK
}
// End of XN297 emulation
//
// HS6200 emulation layer
///////////////////////////
@@ -606,9 +276,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 +287,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 +468,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 +489,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 +511,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

@@ -12,121 +12,45 @@
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef NRF24L01_INSTALLED
#if defined(CC2500_INSTALLED) || defined(NRF24L01_INSTALLED)
#include "iface_nrf250k.h"
#include "iface_xn297.h"
static void __attribute__((unused)) XN297L_Init()
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
debugln("Using NRF");
PE1_on; //NRF24L01 antenna RF3 by default
PE2_off; //NRF24L01 antenna RF3 by default
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
NRF24L01_SetPower();
return;
}
//CC2500
#ifdef CC2500_INSTALLED
#if defined(CC2500_INSTALLED)
debugln("Using CC2500");
PE1_off; // antenna RF2
PE2_on;
CC2500_Reset();
CC2500_Strobe(CC2500_SIDLE);
// Address Config = No address check
// Base Frequency = 2400
// CRC Autoflush = false
// CRC Enable = false
// Channel Spacing = 333.251953
// Data Format = Normal mode
// Data Rate = 249.939
// Deviation = 126.953125
// Device Address = 0
// Manchester Enable = false
// Modulated = true
// Modulation Format = GFSK
// Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word
// RX Filter BW = 203.125000
// Sync Word Qualifier Mode = No preamble/sync
// TX Power = 0
// Whitening = false
// Fast Frequency Hopping - no PLL auto calibration
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x01); // Packet Automation Control
CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0A); // Frequency Synthesizer Control
CC2500_WriteReg(CC2500_0C_FSCTRL0, option); // Frequency offset hack
CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // Frequency Control Word, High Byte
CC2500_WriteReg(CC2500_0E_FREQ1, 0x4E); // Frequency Control Word, Middle Byte
CC2500_WriteReg(CC2500_0F_FREQ0, 0xC3); // Frequency Control Word, Low Byte
CC2500_WriteReg(CC2500_10_MDMCFG4, 0x8D); // Modem Configuration
CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration
CC2500_WriteReg(CC2500_12_MDMCFG2, 0x10); // Modem Configuration
CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // Modem Configuration
CC2500_WriteReg(CC2500_14_MDMCFG0, 0xA4); // Modem Configuration
CC2500_WriteReg(CC2500_15_DEVIATN, 0x62); // Modem Deviation Setting
CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // Main Radio Control State Machine Configuration
CC2500_WriteReg(CC2500_19_FOCCFG, 0x1D); // Frequency Offset Compensation Configuration
CC2500_WriteReg(CC2500_1A_BSCFG, 0x1C); // Bit Synchronization Configuration
CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xC7); // AGC Control
CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x00); // AGC Control
CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0xB0); // AGC Control
CC2500_WriteReg(CC2500_21_FREND1, 0xB6); // Front End RX Configuration
CC2500_WriteReg(CC2500_23_FSCAL3, 0xEA); // Frequency Synthesizer Calibration
CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // Frequency Synthesizer Calibration
CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // Frequency Synthesizer Calibration
CC2500_SetTxRxMode(TX_EN);
CC2500_SetPower();
xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
rf_switch(SW_CC2500);
CC2500_250K_Init();
#elif defined(NRF24L01_INSTALLED)
debugln("Using NRF");
rf_switch(SW_NRF);
NRF24L01_Initialize();
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
#endif
}
static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t* addr, uint8_t len)
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
XN297_SetTXAddr(addr,len);
return;
}
//CC2500
#ifdef CC2500_INSTALLED
#if defined(CC2500_INSTALLED)
if (len > 5) len = 5;
if (len < 3) len = 3;
xn297_addr_len = len;
memcpy(xn297_tx_addr, addr, len);
#elif defined(NRF24L01_INSTALLED)
XN297_SetTXAddr(addr,len);
#endif
}
static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t len)
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(msg, len);
return;
}
//CC2500
#ifdef CC2500_INSTALLED
#if defined(CC2500_INSTALLED)
uint8_t buf[32];
uint8_t last = 0;
uint8_t i;
static const uint16_t initial = 0xb5d2;
// address
for (i = 0; i < xn297_addr_len; ++i)
@@ -147,9 +71,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
@@ -169,23 +93,17 @@ static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t le
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last);
// transmit
CC2500_Strobe(CC2500_STX);
#elif defined(NRF24L01_INSTALLED)
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WritePayload(msg, len);
#endif
}
static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WriteEnhancedPayload(msg, len, noack);
return;
}
//CC2500
#ifdef CC2500_INSTALLED
#if defined(CC2500_INSTALLED)
uint8_t buf[32];
uint8_t scramble_index=0;
uint8_t last = 0;
@@ -228,10 +146,10 @@ static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, ui
// crc
//if (xn297_crc)
{
uint16_t crc = 0xb5d2;
crc = 0xb5d2;
for (uint8_t i = 0; i < last; ++i)
crc = crc16_update(crc, buf[i], 8);
crc = crc16_update(crc, buf[last] & 0xc0, 2);
crc16_update( buf[i], 8);
crc16_update( buf[last] & 0xc0, 2);
if (xn297_scramble_enabled)
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
//else
@@ -257,89 +175,54 @@ static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, ui
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last);
// transmit
CC2500_Strobe(CC2500_STX);
#elif defined(NRF24L01_INSTALLED)
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
NRF24L01_FlushTx();
XN297_WriteEnhancedPayload(msg, len, noack);
#endif
}
static void __attribute__((unused)) XN297L_HoppingCalib(uint8_t num_freq)
{ //calibrate hopping frequencies
#ifdef CC2500_INSTALLED
if(option==0)
#endif
return; //NRF
#ifdef CC2500_INSTALLED
for (uint8_t i = 0; i < num_freq; i++)
{
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[i]*3);
CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);
calData[i]=CC2500_ReadReg(CC2500_25_FSCAL1);
}
#if defined(CC2500_INSTALLED)
CC2500_250K_HoppingCalib(num_freq);
#elif defined(NRF24L01_INSTALLED)
(void)num_freq;
#endif
}
static void __attribute__((unused)) XN297L_Hopping(uint8_t index)
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
#if defined(CC2500_INSTALLED)
CC2500_250K_Hopping(index);
#elif defined(NRF24L01_INSTALLED)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[index]);
return;
}
#ifdef CC2500_INSTALLED
// spacing is 333.25 kHz, must multiply xn297 channel by 3
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[index] * 3);
// set PLL calibration
CC2500_WriteReg(CC2500_25_FSCAL1, calData[index]);
#endif
}
static void __attribute__((unused)) XN297L_RFChannel(uint8_t number)
{ //change channel
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
#if defined(CC2500_INSTALLED)
CC2500_250K_RFChannel(number);
#elif defined(NRF24L01_INSTALLED)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, number);
return;
}
#ifdef CC2500_INSTALLED
CC2500_Strobe(CC2500_SIDLE);
CC2500_WriteReg(CC2500_0A_CHANNR, number*3);
CC2500_Strobe(CC2500_SCAL);
delayMicroseconds(900);
#endif
}
static void __attribute__((unused)) XN297L_SetPower()
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
NRF24L01_SetPower();
return;
}
#ifdef CC2500_INSTALLED
#if defined(CC2500_INSTALLED)
CC2500_SetPower();
#elif defined(NRF24L01_INSTALLED)
NRF24L01_SetPower();
#endif
}
static void __attribute__((unused)) XN297L_SetFreqOffset()
{ // Frequency offset
#ifdef CC2500_INSTALLED
if(option==0 && prev_option==0)
#endif
return; //NRF
#ifdef CC2500_INSTALLED
if (prev_option != option)
{
if(prev_option==0 || option==0)
CHANGE_PROTOCOL_FLAG_on;
prev_option = option;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
}
#if defined(CC2500_INSTALLED)
CC2500_SetFreqOffset();
#endif
}
@@ -347,118 +230,31 @@ static void __attribute__((unused)) NRF250K_SetTXAddr(uint8_t* addr, uint8_t len
{
if (len > 5) len = 5;
if (len < 3) len = 3;
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
#if defined(CC2500_INSTALLED)
CC2500_250K_NRF_SetTXAddr(addr, len);
#elif defined(NRF24L01_INSTALLED)
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr, len);
return;
}
//CC2500
#ifdef CC2500_INSTALLED
xn297_addr_len = len;
memcpy(xn297_tx_addr, addr, len);
#endif
}
static void __attribute__((unused)) NRF250K_WritePayload(uint8_t* msg, uint8_t len)
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{//NRF
#if defined(CC2500_INSTALLED)
CC2500_250K_NRF_WritePayload(msg, len);
#elif defined(NRF24L01_INSTALLED)
NRF24L01_FlushTx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_MAX_RT));
NRF24L01_WritePayload(msg, len);
return;
}
//CC2500
#ifdef CC2500_INSTALLED
#if defined(ESKY150V2_CC2500_INO)
uint8_t buf[158];
#else
uint8_t buf[35];
#endif
uint8_t last = 0;
uint8_t i;
//nrf preamble
if(xn297_tx_addr[xn297_addr_len - 1] & 0x80)
buf[0]=0xAA;
else
buf[0]=0x55;
last++;
// address
for (i = 0; i < xn297_addr_len; ++i)
buf[last++] = xn297_tx_addr[xn297_addr_len - i - 1];
// payload
for (i = 0; i < len; ++i)
buf[last++] = msg[i];
// crc
uint16_t crc = 0xffff;
for (uint8_t i = 1; i < last; ++i)
crc = crc16_update(crc, buf[i], 8);
buf[last++] = crc >> 8;
buf[last++] = crc & 0xff;
buf[last++] = 0;
//for(uint8_t i=0;i<last;i++)
// debug("%02X ",buf[i]);
//debugln("");
// stop TX/RX
CC2500_Strobe(CC2500_SIDLE);
// flush tx FIFO
CC2500_Strobe(CC2500_SFTX);
// packet length
CC2500_WriteReg(CC2500_3F_TXFIFO, last);
// transmit nrf packet
uint8_t *buff=buf;
uint8_t status;
if(last>63)
{
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, 63);
CC2500_Strobe(CC2500_STX);
last-=63;
buff+=63;
while(last)
{//Loop until all the data is sent
do
{// Wait for the FIFO to become available
status=CC2500_ReadReg(CC2500_3A_TXBYTES | CC2500_READ_BURST);
}
while((status&0x7F)>31 && (status&0x80)==0);
if(last>31)
{//Send 31 bytes
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, 31);
last-=31;
buff+=31;
}
else
{//Send last bytes
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, last);
last=0;
}
}
}
else
{//Send packet
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, last);
CC2500_Strobe(CC2500_STX);
}
#endif
}
static boolean __attribute__((unused)) NRF250K_IsPacketSent()
{
#ifdef CC2500_INSTALLED
if(option==0)
#endif
{ //NRF
#if defined(CC2500_INSTALLED)
return true; // don't know on the CC2500 how to detect if the packet has been transmitted...
#elif defined(NRF24L01_INSTALLED)
return NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS);
}
return true; // don't know on the CC2500 how to detect if the packet has been transmitted...
#endif
}
#endif
#endif

View File

@@ -0,0 +1,65 @@
/*
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_RF_init()
{
NRF24L01_Initialize();
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR , (uint8_t *)"Nano1",5);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, NANORF_RF_CHANNEL);
}
uint16_t NANORF_callback()
{
NANORF_send_packet();
return NANORF_PACKET_PERIOD;
}
void NANORF_init()
{
BIND_DONE;
NANORF_RF_init();
}
#endif

View File

@@ -0,0 +1,298 @@
/*
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)
#ifndef NRF24L01_INSTALLED
#undef OMP_HUB_TELEMETRY
#endif
#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
rf_switch(SW_CC2500);
#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_RF_init()
{
//Config CC2500
XN297L_Init();
XN297L_SetTXAddr((uint8_t*)"FLPBD", 5);
XN297L_HoppingCalib(OMP_RF_NUM_CHANNELS); // Calibrate all channels
XN297L_RFChannel(OMP_RF_BIND_CHANNEL); // Set bind channel
#ifdef OMP_HUB_TELEMETRY
//Config NRF
NRF24L01_Initialize();
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
XN297_Configure(_BV(NRF24L01_00_EN_CRC));
XN297_SetRXAddr(rx_tx_addr, 5); // Set the RX address
NRF24L01_SetTxRxMode(TXRX_OFF); // Turn it off for now
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, OMP_PAYLOAD_SIZE + 4); // packet length +4 bytes of PCF+CRC
#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;
rf_switch(SW_NRF);
phase = OMP_DATA;
return OMP_PACKET_PERIOD-OMP_WRITE_TIME;
#endif
}
return OMP_PACKET_PERIOD;
}
void OMP_init()
{
OMP_initialize_txid();
OMP_RF_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;
}
#endif

View File

@@ -1,140 +0,0 @@
/*
This project is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Multiprotocol is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(OMP_NRF24L01_INO)
#include "iface_nrf250k.h"
//#define FORCE_OMP_ORIGINAL_ID
#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()
{
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);
//hopping frequency
packet[0 ] = hopping_frequency_no; // |0x40 to request RX telemetry
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, IS_BIND_IN_PROGRESS);
}
static void __attribute__((unused)) OMP_init()
{
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
}
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
}
uint16_t OMP_callback()
{
if(IS_BIND_IN_PROGRESS)
if(--bind_counter==0)
{
BIND_DONE;
XN297L_SetTXAddr(rx_tx_addr, 5);
}
OMP_send_packet();
#ifdef MULTI_SYNC
telemetry_set_input_sync(OMP_PACKET_PERIOD);
#endif
return OMP_PACKET_PERIOD;
}
uint16_t initOMP()
{
OMP_initialize_txid();
OMP_init();
hopping_frequency_no = 0;
if(IS_BIND_IN_PROGRESS)
bind_counter=OMP_BIND_COUNT;
else
XN297L_SetTXAddr(rx_tx_addr, 5);
return OMP_INITIAL_WAIT;
}
#endif

View File

@@ -71,26 +71,14 @@ static void __attribute__((unused)) POTENSIC_send_packet()
NRF24L01_SetPower();
}
static void __attribute__((unused)) POTENSIC_init()
static void __attribute__((unused)) POTENSIC_RF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
if(IS_BIND_IN_PROGRESS)
XN297_SetTXAddr((uint8_t*)"\x01\x01\x01\x01\x06", 5); // Bind address
else
XN297_SetTXAddr(rx_tx_addr,5); // Normal address
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // set address length (5 bytes)
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
NRF24L01_Activate(0x73);
}
static void __attribute__((unused)) POTENSIC_initialize_txid()
@@ -103,26 +91,25 @@ static void __attribute__((unused)) POTENSIC_initialize_txid()
uint16_t POTENSIC_callback()
{
if(IS_BIND_IN_PROGRESS)
#ifdef MULTI_SYNC
telemetry_set_input_sync(POTENSIC_PACKET_PERIOD);
#endif
if(bind_counter)
if(--bind_counter==0)
{
BIND_DONE;
XN297_SetTXAddr(rx_tx_addr,5);
}
#ifdef MULTI_SYNC
telemetry_set_input_sync(POTENSIC_PACKET_PERIOD);
#endif
POTENSIC_send_packet();
return POTENSIC_PACKET_PERIOD;
}
uint16_t initPOTENSIC(void)
void POTENSIC_init(void)
{
bind_counter = POTENSIC_BIND_COUNT;
POTENSIC_initialize_txid();
POTENSIC_init();
POTENSIC_RF_init();
hopping_frequency_no = 0;
return POTENSIC_INITIAL_WAIT;
}
#endif

View File

@@ -56,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;
@@ -110,7 +110,7 @@ static void __attribute__((unused)) pelikan_build_packet()
A7105_SetPower();
}
uint16_t ReadPelikan()
uint16_t PELIKAN_callback()
{
if(phase==0)
{
@@ -242,7 +242,7 @@ const uint8_t PROGMEM pelikan_lite_hopp[][PELIKAN_NUM_RF_CHAN] = {
};
#endif
uint16_t initPelikan()
void PELIKAN_init()
{
A7105_Init();
if(IS_BIND_IN_PROGRESS || sub_protocol==PELIKAN_LITE)
@@ -288,6 +288,5 @@ uint16_t initPelikan()
hopping_frequency_no=PELIKAN_NUM_RF_CHAN;
packet_count=5;
phase=0;
return 2400;
}
#endif

View File

@@ -155,27 +155,21 @@ static void __attribute__((unused)) PROPEL_data_packet()
NRF24L01_WritePayload(packet, PROPEL_PACKET_SIZE);
}
static void __attribute__((unused)) PROPEL_init()
static void __attribute__((unused)) PROPEL_RF_init()
{
NRF24L01_Initialize();
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x7f);
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x3f); // AA on all pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3f); // Enable all pipes
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte address
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x36); // retransmit 1ms, 6 times
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x07); // ?? match protocol capture
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x3f); // AA on all pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3f); // Enable all pipes
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x36); // retransmit 1ms, 6 times
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x99\x77\x55\x33\x11", PROPEL_ADDRESS_LENGTH); //Bind address
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x99\x77\x55\x33\x11", PROPEL_ADDRESS_LENGTH); //Bind address
NRF24L01_WriteReg(NRF24L01_05_RF_CH, PROPEL_BIND_RF_CHANNEL);
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // Enable dynamic payload length
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Enable all features
// Beken 2425 register bank 1 initialized here in stock tx capture
// Hopefully won't matter for nRF compatibility
NRF24L01_FlushTx();
NRF24L01_SetTxRxMode(TX_EN);
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // Enable dynamic payload length
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Enable all features
NRF24L01_SetTxRxMode(TX_EN); // Clear data ready, data sent, retransmit and enable CRC 16bits, ready for TX
}
const uint8_t PROGMEM PROPEL_hopping []= { 0x47,0x36,0x27,0x44,0x33,0x0D,0x3C,0x2E,0x1B,0x39,0x2A,0x18 };
@@ -281,14 +275,13 @@ uint16_t PROPEL_callback()
return PROPEL_PACKET_PERIOD;
}
uint16_t initPROPEL()
void PROPEL_init()
{
BIND_IN_PROGRESS; // autobind protocol
PROPEL_initialize_txid();
PROPEL_init();
PROPEL_RF_init();
hopping_frequency_no = 0;
phase=PROPEL_BIND1;
return PROPEL_INITIAL_WAIT;
}
#endif

View File

@@ -174,10 +174,10 @@ static uint8_t __attribute__((unused)) cx35_lastButton()
return command;
}
static void __attribute__((unused)) Q303_send_packet(uint8_t bind)
static void __attribute__((unused)) Q303_send_packet()
{
uint16_t aileron, elevator, throttle, rudder, slider;
if(bind)
if(IS_BIND_IN_PROGRESS)
{
packet[0] = 0xaa;
memcpy(&packet[1], rx_tx_addr + 1, 4);
@@ -270,7 +270,7 @@ static void __attribute__((unused)) Q303_send_packet(uint8_t bind)
// Power on, TX mode, CRC enabled
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? Q303_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no++]);
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? Q303_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no++]);
hopping_frequency_no %= rf_ch_num;
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
@@ -281,37 +281,18 @@ static void __attribute__((unused)) Q303_send_packet(uint8_t bind)
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) Q303_init()
static void __attribute__((unused)) Q303_RF_init()
{
const uint8_t bind_address[] = {0xcc,0xcc,0xcc,0xcc,0xcc};
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
switch(sub_protocol)
if(sub_protocol==Q303)
{
case CX35:
case CX10D:
case CX10WD:
NRF24L01_SetBitrate(NRF24L01_BR_1M);
break;
case Q303:
XN297_SetScrambledMode(XN297_UNSCRAMBLED);
NRF24L01_SetBitrate(NRF24L01_BR_250K);
break;
XN297_SetScrambledMode(XN297_UNSCRAMBLED);
NRF24L01_SetBitrate(NRF24L01_BR_250K);
}
XN297_SetTXAddr(bind_address, 5);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01);
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01); // Set feature bits on
NRF24L01_Activate(0x73);
}
static void __attribute__((unused)) Q303_initialize_txid()
@@ -353,34 +334,27 @@ static void __attribute__((unused)) Q303_initialize_txid()
uint16_t Q303_callback()
{
if(IS_BIND_DONE)
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
Q303_send_packet(0);
}
else
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
if(bind_counter)
{
bind_counter--;
if (bind_counter == 0)
{
XN297_SetTXAddr(rx_tx_addr, 5);
packet_count = 0;
BIND_DONE;
}
else
{
Q303_send_packet(1);
bind_counter--;
}
}
Q303_send_packet();
return packet_period;
}
uint16_t initQ303()
void Q303_init()
{
Q303_initialize_txid();
Q303_init();
Q303_RF_init();
bind_counter = Q303_BIND_COUNT;
switch(sub_protocol)
{
@@ -407,7 +381,6 @@ uint16_t initQ303()
}
hopping_frequency_no = 0;
BIND_IN_PROGRESS; // autobind protocol
return Q303_INITIAL_WAIT;
}
#endif

View File

@@ -14,7 +14,7 @@ Multiprotocol is distributed in the hope that it will be useful,
*/
// Compatible with Q90C quad.
#if defined(Q90C_NRF24L01_INO)
#if defined(Q90C_CCNRF_INO)
#include "iface_nrf250k.h"
@@ -131,7 +131,7 @@ static void __attribute__((unused)) Q90C_initialize_txid()
crc8=rx_tx_addr[0]^rx_tx_addr[1]^rx_tx_addr[2]^rx_tx_addr[3];
}
static void __attribute__((unused)) Q90C_init()
static void __attribute__((unused)) Q90C_RF_init()
{
XN297L_Init();
if(IS_BIND_IN_PROGRESS)
@@ -147,7 +147,7 @@ uint16_t Q90C_callback()
#ifdef MULTI_SYNC
telemetry_set_input_sync(Q90C_PACKET_PERIOD);
#endif
if(IS_BIND_IN_PROGRESS)
if(bind_counter)
if(--bind_counter==0)
{
BIND_DONE;
@@ -157,10 +157,10 @@ uint16_t Q90C_callback()
return Q90C_PACKET_PERIOD;
}
uint16_t initQ90C()
void Q90C_init()
{
Q90C_initialize_txid();
Q90C_init();
Q90C_RF_init();
hopping_frequency_no = 0;
packet_count = 0;
bind_counter=Q90C_BIND_COUNT;
@@ -170,7 +170,6 @@ uint16_t initQ90C()
Q90C_VTX=CH6_SW;
packet[8] = 0x00;
packet[9] = 0x00;
return Q90C_INITIAL_WAIT;
}
#endif

View File

@@ -86,17 +86,10 @@ static void __attribute__((unused)) REALACC_initialize_txid()
#endif
}
static void __attribute__((unused)) REALACC_init()
static void __attribute__((unused)) REALACC_RF_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
}
@@ -124,14 +117,13 @@ uint16_t REALACC_callback()
return REALACC_PACKET_PERIOD;
}
uint16_t initREALACC()
void REALACC_init()
{
BIND_IN_PROGRESS; // autobind protocol
REALACC_initialize_txid();
REALACC_init();
REALACC_RF_init();
bind_counter=REALACC_BIND_COUNT;
hopping_frequency_no=0;
return REALACC_INITIAL_WAIT;
}
#endif

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

@@ -31,87 +31,63 @@ enum {
RLINK_RX2 = 0x02,
};
const PROGMEM uint8_t RLINK_hopping[][8] = {
/* 4C494E4B */ { 0xBC, 0x5A, 0x70, 0x4E, 0xDF, 0x32, 0x16, 0x89 },
/* 4D494E4B */ { 0x4C, 0xF3, 0xEA, 0x5B, 0x62, 0x9D, 0x01, 0x87 },
/* 4E494E4B */ { 0x86, 0xEA, 0xD0, 0xC9, 0x2B, 0x53, 0x7F, 0x41 },
/* 4F494E4B */ { 0xAC, 0x91, 0x7D, 0x48, 0xE0, 0xB5, 0x32, 0xF6 },
/* 50494E4B */ { 0xD6, 0x7C, 0xA4, 0x93, 0x5F, 0xE1, 0x02, 0xB8 },
/* 51494E4B */ { 0xED, 0x04, 0x73, 0xC8, 0x56, 0xB9, 0x1F, 0xA2 },
/* 52494E4B */ { 0xA7, 0xF0, 0x36, 0xB2, 0x95, 0x4E, 0x1C, 0xD8 },
/* 53494E4B */ { 0x76, 0x8B, 0xA0, 0x3E, 0x51, 0x4C, 0x9D, 0x2F },
/* 54494E4B */ { 0x07, 0x23, 0x16, 0xFD, 0xC9, 0x5B, 0x84, 0xAE },
/* 55494E4B */ { 0xD3, 0xA0, 0x69, 0xBF, 0x12, 0x8C, 0x4E, 0x57 },
/* 56494E4B */ { 0xA6, 0xBE, 0x91, 0xD3, 0x7C, 0x4F, 0x82, 0x50 },
/* 57494E4B */ { 0x91, 0xDA, 0xBC, 0x75, 0x82, 0x36, 0x4E, 0xF0 },
/* 58494E4B */ { 0x9A, 0x27, 0x5C, 0xF4, 0xD8, 0xB0, 0x36, 0xE1 },
/* 59494E4B */ { 0x92, 0xF1, 0x34, 0xA7, 0x5B, 0x0C, 0xED, 0x86 },
/* 5A494E4B */ { 0x8C, 0x2B, 0x51, 0xF9, 0x3E, 0x4A, 0x67, 0xD0 },
/* 5B494E4B */ { 0x5E, 0x3D, 0x67, 0x9B, 0xA2, 0x84, 0xFC, 0x01 },
/* 5C494E4B */ { 0xF9, 0x35, 0xBD, 0x78, 0x26, 0x1C, 0x0E, 0xA4 },
/* 5D494E4B */ { 0xD9, 0x7B, 0x48, 0x0E, 0x2A, 0xCF, 0x13, 0x65 },
/* 5E494E4B */ { 0x07, 0xE4, 0xF9, 0x8A, 0x3C, 0x21, 0xB5, 0xD6 },
/* 5F494E4B */ { 0xEB, 0xFA, 0x29, 0xD1, 0x54, 0x3C, 0x07, 0x86 },
/* 60494E4B */ { 0xDF, 0xCE, 0x0A, 0x32, 0x71, 0x5B, 0x96, 0x48 },
/* 61494E4B */ { 0x19, 0x86, 0xF5, 0x3A, 0x27, 0xDC, 0x0E, 0xB4 },
/* 62494E4B */ { 0xF8, 0x47, 0x9C, 0xE0, 0x2D, 0xBA, 0x15, 0x36 },
/* 63494E4B */ { 0xED, 0x78, 0x01, 0xA3, 0x2B, 0x6C, 0x45, 0xF9 },
/* 64494E4B */ { 0xE0, 0xA2, 0xD4, 0x6B, 0xF5, 0x18, 0x3C, 0x79 },
/* 65494E4B */ { 0x26, 0x90, 0x8B, 0x5D, 0x31, 0xCF, 0xE7, 0x4A },
/* 66494E4B */ { 0x7B, 0x12, 0xA8, 0x4F, 0xC0, 0x65, 0xD9, 0x3E },
/* 67494E4B */ { 0x35, 0xA2, 0x14, 0xBE, 0x06, 0x7D, 0x98, 0xFC },
/* 68494E4B */ { 0xD2, 0xA9, 0x7E, 0x40, 0x6F, 0x83, 0x5C, 0xB1 },
/* 69494E4B */ { 0xE5, 0xB9, 0xC1, 0x04, 0x83, 0x27, 0xA6, 0xFD },
/* 6A494E4B */ { 0x8E, 0x0C, 0x4A, 0x51, 0xFB, 0x63, 0x92, 0x7D },
/* 6B494E4B */ { 0xC7, 0x1D, 0x02, 0x93, 0x45, 0xF8, 0xA6, 0xBE },
/* 6C494E4B */ { 0xC1, 0x64, 0x59, 0x0A, 0x7D, 0x3F, 0x28, 0xEB },
/* 6D494E4B */ { 0xEF, 0x75, 0xAB, 0x94, 0xD2, 0x83, 0x1C, 0x60 },
/* 6E494E4B */ { 0xA1, 0x20, 0x54, 0x68, 0x9E, 0x7B, 0x3D, 0xFC },
/* 6F494E4B */ { 0x3E, 0x60, 0x28, 0xFC, 0xDA, 0x45, 0x9B, 0x71 },
/* 70494E4B */ { 0xB7, 0x0E, 0xA8, 0x23, 0xFC, 0x65, 0x4D, 0x91 },
/* 71494E4B */ { 0x29, 0x34, 0x51, 0x7C, 0xB8, 0xFD, 0x0E, 0x6A },
/* 72494E4B */ { 0x1B, 0x06, 0x3C, 0x89, 0xF5, 0x2A, 0x7E, 0xD4 },
/* 73494E4B */ { 0xF2, 0xC9, 0x63, 0x57, 0x0A, 0xB1, 0x48, 0xDE },
/* 74494E4B */ { 0x24, 0xAE, 0x0C, 0x19, 0x53, 0x7B, 0xF6, 0x8D },
/* 75494E4B */ { 0xEC, 0xD8, 0xF2, 0x4B, 0xA3, 0x51, 0x09, 0x76 },
/* 76494E4B */ { 0x98, 0x71, 0x5E, 0xAD, 0xFC, 0x04, 0x3B, 0x62 },
/* 77494E4B */ { 0xAE, 0xF6, 0xB7, 0x01, 0x52, 0x34, 0x9D, 0x8C },
/* 78494E4B */ { 0x69, 0x48, 0xF1, 0x3C, 0xDB, 0x0E, 0x25, 0xA7 },
/* 79494E4B */ { 0xCF, 0x60, 0x94, 0xAD, 0xB1, 0x82, 0x73, 0xE5 },
/* 7A494E4B */ { 0xFA, 0xC1, 0xD7, 0xB0, 0x53, 0x92, 0x6E, 0x48 },
/* 7B494E4B */ { 0xAC, 0x7D, 0xE5, 0x8B, 0x41, 0x96, 0x2F, 0x30 },
/* 7C494E4B */ { 0xFD, 0xC1, 0xB9, 0x02, 0xE4, 0x87, 0x56, 0x3A },
/* 7D494E4B */ { 0x30, 0xDA, 0x4F, 0x8E, 0x5C, 0xB9, 0x26, 0x71 },
/* 7E494E4B */ { 0xDC, 0xF9, 0x57, 0x30, 0x82, 0x1E, 0x6A, 0x4B },
/* 7F494E4B */ { 0x84, 0x1D, 0x7E, 0x29, 0x3C, 0x65, 0xA0, 0xBF },
/* 80494E4B */ { 0x01, 0xA3, 0xF6, 0xE2, 0x4C, 0x8B, 0x5D, 0x79 },
/* 81494E4B */ { 0xA1, 0x32, 0xE7, 0x08, 0x4D, 0x5B, 0x9F, 0x6C },
/* 82494E4B */ { 0x31, 0x40, 0x67, 0x8F, 0xBA, 0x95, 0x2C, 0xED },
/* 83494E4B */ { 0x91, 0x76, 0xFA, 0x83, 0x20, 0x4B, 0xEC, 0x5D },
/* 84494E4B */ { 0xDB, 0x54, 0xC2, 0x61, 0xF0, 0xA9, 0x87, 0x3E },
/* 85494E4B */ { 0xC0, 0xB4, 0x61, 0xD3, 0x7A, 0x5F, 0x82, 0x9E },
/* 86494E4B */ { 0xD6, 0xCF, 0x9B, 0x75, 0xE1, 0x42, 0x3A, 0x80 },
/* 87494E4B */ { 0xFE, 0xA2, 0xB4, 0x9C, 0x10, 0x7D, 0x56, 0x83 },
/* 88494E4B */ { 0xD2, 0x79, 0x54, 0xEF, 0xC8, 0x0B, 0x36, 0xA1 },
/* 89494E4B */ { 0x8D, 0xCF, 0x23, 0x64, 0xE5, 0x0B, 0x1A, 0x97 },
/* 8A494E4B */ { 0x07, 0xC4, 0xEF, 0x9A, 0x61, 0xD8, 0xB3, 0x52 },
/* 8B494E4B */ { 0x45, 0x6E, 0xBF, 0x8C, 0x9A, 0x2D, 0x31, 0x70 },
#ifdef RLINK_FORCE_ID
/* 3A99223A */ { 0x1F, 0x89, 0x25, 0x06, 0x4E, 0xBD, 0x3A, 0xC7 },
/* FC110D20 */ { 0xBC, 0xFE, 0x59, 0x84, 0x37, 0xA1, 0xD0, 0x62 }
#endif
};
uint32_t RLINK_rand1;
uint32_t RLINK_rand2;
static void __attribute__((unused)) RLINK_load_hopp(uint8_t num)
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);
for (uint8_t i = 0; i < RLINK_HOP>>1; i++)
{
uint8_t val=pgm_read_byte_near(&RLINK_hopping[num][i]);
hopping_frequency[ i<<1 ]=12*(val>>4 )+inc;
hopping_frequency[(i<<1)+1]=12*(val&0x0F)+inc;
}
// 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
@@ -119,32 +95,27 @@ static void __attribute__((unused)) RLINK_load_hopp(uint8_t num)
hopping_frequency[rf_ch_num]=12*16+inc;
}
static void __attribute__((unused)) RLINK_init()
static void __attribute__((unused)) RLINK_TXID_init()
{
// channels order depend on ID and currently unknown so using a table of 64 entries...
uint8_t id=rx_tx_addr[3]&0x3F;
memcpy(rx_tx_addr,"\x4C\x49\x4E\x4B",RLINK_TX_ID_LEN);
rx_tx_addr[0] += id;
RLINK_load_hopp(id);
#ifdef RLINK_FORCE_ID
//surface RC6GS
memcpy(rx_tx_addr,"\x3A\x99\x22\x3A",RLINK_TX_ID_LEN);
RLINK_load_hopp(64);
//air T8FB
//memcpy(rx_tx_addr,"\xFC\x11\x0D\x20",RLINK_TX_ID_LEN);
//RLINK_load_hopp(65);
#endif
// channels order depend on ID
RLINK_hop();
/* 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("");
*/
#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[] = {
@@ -162,21 +133,17 @@ static void __attribute__((unused)) RLINK_rf_init()
for (uint8_t i = 0; i < 39; ++i)
CC2500_WriteReg(i, pgm_read_byte_near(&RLINK_init_values[i]));
prev_option = option;
if(sub_protocol==RLINK_DUMBORC)
{
CC2500_WriteReg(4, 0xBA);
CC2500_WriteReg(5, 0xDC);
}
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;
@@ -189,16 +156,22 @@ static void __attribute__((unused)) RLINK_send_packet()
// packet length
packet[0] = RLINK_TX_PACKET_LEN;
// header
if(sub_protocol)
packet[1] = 0x21; //air 0x21 on dump but it looks to support telemetry at least RSSI
else
{//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
}
if(packet_count>3)
packet[1] |= 0x02; // 0x02 telemetry request flag
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);
@@ -206,7 +179,7 @@ static void __attribute__((unused)) RLINK_send_packet()
// 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); // allow extended limits
uint32_t val = convert_channel_16b_nolimit(i,170,1876,false); // allow extended limits
if (val & 0x8000)
val = 0;
else if (val > 2047)
@@ -262,7 +235,7 @@ uint16_t RLINK_callback()
telemetry_set_input_sync(RLINK_TIMING_PROTO);
#endif
CC2500_SetPower();
RLINK_tune_freq();
CC2500_SetFreqOffset();
RLINK_send_packet();
#if not defined RLINK_HUB_TELEMETRY
return RLINK_TIMING_PROTO;
@@ -323,14 +296,13 @@ uint16_t RLINK_callback()
return 0;
}
uint16_t initRLINK()
void RLINK_init()
{
BIND_DONE; // Not a TX bind protocol
RLINK_init();
RLINK_TXID_init();
RLINK_rf_init();
packet_count = 0;
phase = RLINK_DATA;
return 10000;
}
#endif

View File

@@ -96,17 +96,13 @@ static void REDPINE_data_frame() {
packet[10] = REDPINE_LOOPTIME_SLOW;
}
static uint16_t ReadREDPINE()
uint16_t REDPINE_callback()
{
if ( prev_option != option )
{ // Frequency adjust
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
prev_option = option ;
}
CC2500_SetFreqOffset();
if(IS_BIND_IN_PROGRESS)
{
if (state == REDPINE_BIND) {
REDPINE_init(0);
REDPINE_RF_init(0);
}
REDPINE_set_channel(49);
CC2500_SetTxRxMode(TX_EN);
@@ -118,26 +114,22 @@ static uint16_t ReadREDPINE()
if(--bind_counter==0)
{
BIND_DONE;
REDPINE_init(sub_protocol);
REDPINE_RF_init(sub_protocol);
}
return 4000;
}
else
{
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
CC2500_SetTxRxMode(TX_EN);
REDPINE_set_channel(hopping_frequency_no);
CC2500_SetPower();
CC2500_Strobe(CC2500_SFRX);
REDPINE_data_frame();
CC2500_Strobe(CC2500_SIDLE);
hopping_frequency_no = (hopping_frequency_no + 1) % 49;
CC2500_WriteData(packet, REDPINE_PACKET_SIZE);
return packet_period;
}
return 1;
#ifdef MULTI_SYNC
telemetry_set_input_sync(packet_period);
#endif
CC2500_SetTxRxMode(TX_EN);
REDPINE_set_channel(hopping_frequency_no);
CC2500_SetPower();
CC2500_Strobe(CC2500_SFRX);
REDPINE_data_frame();
CC2500_Strobe(CC2500_SIDLE);
hopping_frequency_no = (hopping_frequency_no + 1) % 49;
CC2500_WriteData(packet, REDPINE_PACKET_SIZE);
return packet_period;
}
// register, fast 250k, slow
@@ -179,7 +171,7 @@ static const uint8_t REDPINE_init_data[][3] = {
{CC2500_3E_PATABLE, 0xff, 0xff}
};
static void REDPINE_init(uint8_t format)
static void REDPINE_RF_init(uint8_t format)
{
CC2500_Reset();
@@ -189,7 +181,6 @@ static void REDPINE_init(uint8_t format)
CC2500_WriteReg(REDPINE_init_data[i][0], REDPINE_init_data[i][format+1]);
}
prev_option = option;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
CC2500_Strobe(CC2500_SIDLE);
@@ -204,7 +195,7 @@ static void REDPINE_init(uint8_t format)
}
}
static uint16_t initREDPINE()
void REDPINE_init()
{
hopping_frequency_no = 0;
// Used from kn_nrf24l01.c : kn_calculate_freqency_hopping_channels
@@ -237,8 +228,7 @@ static uint16_t initREDPINE()
packet_period = REDPINE_LOOPTIME_SLOW*1000;
bind_counter=REDPINE_BIND;
REDPINE_init(sub_protocol);
REDPINE_RF_init(sub_protocol);
CC2500_SetTxRxMode(TX_EN); // enable PA
return 10000;
}
#endif

View File

@@ -29,15 +29,9 @@ const uint8_t PROGMEM SHENQI_Freq[] = {
10,60,10,50,30,40,
20,10,40,30,60,20 };
void SHENQI_init()
void SHENQI_RF_init()
{
NRF24L01_Initialize();
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_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_SetPower();
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5 bytes rx/tx address
LT8900_Config(4, 8, _BV(LT8900_CRC_ON)|_BV(LT8900_PACKET_LENGTH_EN), 0xAA);
LT8900_SetChannel(2);
@@ -116,14 +110,13 @@ uint16_t SHENQI_callback()
return packet_period;
}
uint16_t initSHENQI()
void SHENQI_init()
{
BIND_IN_PROGRESS; // autobind protocol
SHENQI_init();
SHENQI_RF_init();
hopping_frequency_no = 0;
packet_count=0;
packet_period=500;
return 1000;
}
#endif

View File

@@ -1,281 +1,281 @@
/*
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/>.
*/
// Last sync with deviation main github branch
#if defined(SLT_NRF24L01_INO)
#include "iface_nrf250k.h"
//#define SLT_Q200_FORCE_ID
// For code readability
#define SLT_PAYLOADSIZE_V1 7
#define SLT_PAYLOADSIZE_V2 11
#define SLT_NFREQCHANNELS 15
#define SLT_TXID_SIZE 4
#define SLT_BIND_CHANNEL 0x50
enum{
// flags going to packet[6] (Q200)
FLAG_Q200_FMODE = 0x20,
FLAG_Q200_VIDON = 0x10,
FLAG_Q200_FLIP = 0x08,
FLAG_Q200_VIDOFF= 0x04,
};
enum{
// flags going to packet[6] (MR100 & Q100)
FLAG_MR100_FMODE = 0x20,
FLAG_MR100_FLIP = 0x04,
FLAG_MR100_VIDEO = 0x02,
FLAG_MR100_PICTURE = 0x01,
};
enum {
SLT_BUILD=0,
SLT_DATA1,
SLT_DATA2,
SLT_DATA3,
SLT_BIND1,
SLT_BIND2,
};
static void __attribute__((unused)) SLT_init()
{
NRF250K_Init();
NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE);
}
static void __attribute__((unused)) SLT_set_freq(void)
{
// Frequency hopping sequence generation
for (uint8_t i = 0; i < SLT_TXID_SIZE; ++i)
{
uint8_t next_i = (i+1) % SLT_TXID_SIZE; // is & 3 better than % 4 ?
uint8_t base = i < 2 ? 0x03 : 0x10;
hopping_frequency[i*4 + 0] = (rx_tx_addr[i] & 0x3f) + base;
hopping_frequency[i*4 + 1] = (rx_tx_addr[i] >> 2) + base;
hopping_frequency[i*4 + 2] = (rx_tx_addr[i] >> 4) + (rx_tx_addr[next_i] & 0x03)*0x10 + base;
hopping_frequency[i*4 + 3] = (rx_tx_addr[i] >> 6) + (rx_tx_addr[next_i] & 0x0f)*0x04 + base;
}
// Unique freq
uint8_t max_freq=0x50; //V1 and V2
if(sub_protocol==Q200)
max_freq=45;
for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i)
{
if(sub_protocol==Q200 && hopping_frequency[i] >= max_freq)
hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03;
uint8_t done = 0;
while (!done)
{
done = 1;
for (uint8_t j = 0; j < i; ++j)
if (hopping_frequency[i] == hopping_frequency[j])
{
done = 0;
hopping_frequency[i] += 7;
if (hopping_frequency[i] >= max_freq)
hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03;
}
}
}
//Bind channel
hopping_frequency[SLT_NFREQCHANNELS]=SLT_BIND_CHANNEL;
//Calib all channels
NRF250K_HoppingCalib(SLT_NFREQCHANNELS+1);
}
static void __attribute__((unused)) SLT_wait_radio()
{
if (packet_sent)
while (!NRF250K_IsPacketSent());
packet_sent = 0;
}
static void __attribute__((unused)) SLT_send_packet(uint8_t len)
{
SLT_wait_radio();
NRF250K_WritePayload(packet, len);
packet_sent = 1;
}
static void __attribute__((unused)) SLT_build_packet()
{
static uint8_t calib_counter=0;
// Set radio channel - once per packet batch
NRF250K_SetFreqOffset(); // Set frequency offset
NRF250K_Hopping(hopping_frequency_no);
if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
hopping_frequency_no = 0;
// aileron, elevator, throttle, rudder, gear, pitch
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]);
if(sub_protocol>SLT_V2 && (i==CH2 || i==CH3) )
v=1023-v; // reverse throttle and elevator channels for Q100/Q200/MR100 protocols
packet[i] = v;
e = (e >> 2) | (uint8_t) ((v >> 2) & 0xC0);
}
// Extra bits for AETR
packet[4] = e;
// 8-bit channels
packet[5] = convert_channel_8b(CH5);
packet[6] = convert_channel_8b(CH6);
if(sub_protocol!=SLT_V1)
{
if(sub_protocol==Q200)
packet[6] = GET_FLAG(CH9_SW , FLAG_Q200_FMODE)
|GET_FLAG(CH10_SW, FLAG_Q200_FLIP)
|GET_FLAG(CH11_SW, FLAG_Q200_VIDON)
|GET_FLAG(CH12_SW, FLAG_Q200_VIDOFF);
else if(sub_protocol==MR100 || sub_protocol==Q100)
packet[6] = GET_FLAG(CH9_SW , FLAG_MR100_FMODE)
|GET_FLAG(CH10_SW, FLAG_MR100_FLIP)
|GET_FLAG(CH11_SW, FLAG_MR100_VIDEO) // Does not exist on the Q100 but...
|GET_FLAG(CH12_SW, FLAG_MR100_PICTURE); // Does not exist on the Q100 but...
packet[7]=convert_channel_8b(CH7);
packet[8]=convert_channel_8b(CH8);
packet[9]=0xAA; //normal mode for Q100/Q200, unknown for V2/MR100
packet[10]=0x00; //normal mode for Q100/Q200, unknown for V2/MR100
if((sub_protocol==Q100 || sub_protocol==Q200) && CH13_SW)
{//Calibrate
packet[9]=0x77; //enter calibration
if(calib_counter>=20 && calib_counter<=25) // 7 packets for Q100 / 3 packets for Q200
packet[10]=0x20; //launch calibration
calib_counter++;
if(calib_counter>250) calib_counter=250;
}
else
calib_counter=0;
}
}
static void __attribute__((unused)) SLT_send_bind_packet()
{
SLT_wait_radio();
NRF250K_Hopping(SLT_NFREQCHANNELS); //Bind channel
BIND_IN_PROGRESS; //Limit TX power to bind level
NRF250K_SetPower();
BIND_DONE;
NRF250K_SetTXAddr((uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
memcpy((void*)packet,(void*)rx_tx_addr,SLT_TXID_SIZE);
if(phase==SLT_BIND2)
SLT_send_packet(SLT_TXID_SIZE);
else // SLT_BIND1
SLT_send_packet(SLT_PAYLOADSIZE_V2);
}
#define SLT_TIMING_BUILD 1000
#define SLT_V1_TIMING_PACKET 1000
#define SLT_V2_TIMING_PACKET 2042
#define SLT_V1_TIMING_BIND2 1000
#define SLT_V2_TIMING_BIND1 6507
#define SLT_V2_TIMING_BIND2 2112
uint16_t SLT_callback()
{
switch (phase)
{
case SLT_BUILD:
#ifdef MULTI_SYNC
telemetry_set_input_sync(sub_protocol==SLT_V1?20000:13730);
#endif
SLT_build_packet();
NRF250K_SetPower(); //Change power level
NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE);
phase++;
return SLT_TIMING_BUILD;
case SLT_DATA1:
case SLT_DATA2:
phase++;
if(sub_protocol==SLT_V1)
{
SLT_send_packet(SLT_PAYLOADSIZE_V1);
return SLT_V1_TIMING_PACKET;
}
else //V2
{
SLT_send_packet(SLT_PAYLOADSIZE_V2);
return SLT_V2_TIMING_PACKET;
}
case SLT_DATA3:
if(sub_protocol==SLT_V1)
SLT_send_packet(SLT_PAYLOADSIZE_V1);
else //V2
SLT_send_packet(SLT_PAYLOADSIZE_V2);
if (++packet_count >= 100)
{// Send bind packet
packet_count = 0;
if(sub_protocol==SLT_V1)
{
phase=SLT_BIND2;
return SLT_V1_TIMING_BIND2;
}
else //V2
{
phase=SLT_BIND1;
return SLT_V2_TIMING_BIND1;
}
}
else
{// Continue to send normal packets
phase = SLT_BUILD;
if(sub_protocol==SLT_V1)
return 20000-SLT_TIMING_BUILD;
else //V2
return 13730-SLT_TIMING_BUILD;
}
case SLT_BIND1:
SLT_send_bind_packet();
phase++;
return SLT_V2_TIMING_BIND2;
case SLT_BIND2:
SLT_send_bind_packet();
phase = SLT_BUILD;
if(sub_protocol==SLT_V1)
return 20000-SLT_TIMING_BUILD-SLT_V1_TIMING_BIND2;
else //V2
return 13730-SLT_TIMING_BUILD-SLT_V2_TIMING_BIND1-SLT_V2_TIMING_BIND2;
}
return 19000;
}
uint16_t initSLT()
{
packet_count = 0;
packet_sent = 0;
hopping_frequency_no = 0;
if(sub_protocol==Q200)
{ //Q200: Force high part of the ID otherwise it won't bind
rx_tx_addr[0]=0x01;
rx_tx_addr[1]=0x02;
#ifdef SLT_Q200_FORCE_ID // ID taken from TX dumps
rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x6A;rx_tx_addr[3]=0x31;
/* rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x0B;rx_tx_addr[3]=0x57;*/
#endif
}
SLT_init();
SLT_set_freq();
phase = SLT_BUILD;
return 50000;
}
#endif
/*
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/>.
*/
// Last sync with deviation main github branch
#if defined(SLT_CCNRF_INO)
#include "iface_nrf250k.h"
//#define SLT_Q200_FORCE_ID
// For code readability
#define SLT_PAYLOADSIZE_V1 7
#define SLT_PAYLOADSIZE_V2 11
#define SLT_NFREQCHANNELS 15
#define SLT_TXID_SIZE 4
#define SLT_BIND_CHANNEL 0x50
enum{
// flags going to packet[6] (Q200)
FLAG_Q200_FMODE = 0x20,
FLAG_Q200_VIDON = 0x10,
FLAG_Q200_FLIP = 0x08,
FLAG_Q200_VIDOFF= 0x04,
};
enum{
// flags going to packet[6] (MR100 & Q100)
FLAG_MR100_FMODE = 0x20,
FLAG_MR100_FLIP = 0x04,
FLAG_MR100_VIDEO = 0x02,
FLAG_MR100_PICTURE = 0x01,
};
enum {
SLT_BUILD=0,
SLT_DATA1,
SLT_DATA2,
SLT_DATA3,
SLT_BIND1,
SLT_BIND2,
};
static void __attribute__((unused)) SLT_RF_init()
{
NRF250K_Init();
NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE);
}
static void __attribute__((unused)) SLT_set_freq(void)
{
// Frequency hopping sequence generation
for (uint8_t i = 0; i < SLT_TXID_SIZE; ++i)
{
uint8_t next_i = (i+1) % SLT_TXID_SIZE; // is & 3 better than % 4 ?
uint8_t base = i < 2 ? 0x03 : 0x10;
hopping_frequency[i*4 + 0] = (rx_tx_addr[i] & 0x3f) + base;
hopping_frequency[i*4 + 1] = (rx_tx_addr[i] >> 2) + base;
hopping_frequency[i*4 + 2] = (rx_tx_addr[i] >> 4) + (rx_tx_addr[next_i] & 0x03)*0x10 + base;
hopping_frequency[i*4 + 3] = (rx_tx_addr[i] >> 6) + (rx_tx_addr[next_i] & 0x0f)*0x04 + base;
}
// Unique freq
uint8_t max_freq=0x50; //V1 and V2
if(sub_protocol==Q200)
max_freq=45;
for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i)
{
if(sub_protocol==Q200 && hopping_frequency[i] >= max_freq)
hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03;
uint8_t done = 0;
while (!done)
{
done = 1;
for (uint8_t j = 0; j < i; ++j)
if (hopping_frequency[i] == hopping_frequency[j])
{
done = 0;
hopping_frequency[i] += 7;
if (hopping_frequency[i] >= max_freq)
hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03;
}
}
}
//Bind channel
hopping_frequency[SLT_NFREQCHANNELS]=SLT_BIND_CHANNEL;
//Calib all channels
NRF250K_HoppingCalib(SLT_NFREQCHANNELS+1);
}
static void __attribute__((unused)) SLT_wait_radio()
{
if (packet_sent)
while (!NRF250K_IsPacketSent());
packet_sent = 0;
}
static void __attribute__((unused)) SLT_send_packet(uint8_t len)
{
SLT_wait_radio();
NRF250K_WritePayload(packet, len);
packet_sent = 1;
}
static void __attribute__((unused)) SLT_build_packet()
{
static uint8_t calib_counter=0;
// Set radio channel - once per packet batch
NRF250K_SetFreqOffset(); // Set frequency offset
NRF250K_Hopping(hopping_frequency_no);
if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
hopping_frequency_no = 0;
// aileron, elevator, throttle, rudder, gear, pitch
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], 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;
e = (e >> 2) | (uint8_t) ((v >> 2) & 0xC0);
}
// Extra bits for AETR
packet[4] = e;
// 8-bit channels
packet[5] = convert_channel_8b(CH5);
packet[6] = convert_channel_8b(CH6);
if(sub_protocol!=SLT_V1)
{
if(sub_protocol==Q200)
packet[6] = GET_FLAG(CH9_SW , FLAG_Q200_FMODE)
|GET_FLAG(CH10_SW, FLAG_Q200_FLIP)
|GET_FLAG(CH11_SW, FLAG_Q200_VIDON)
|GET_FLAG(CH12_SW, FLAG_Q200_VIDOFF);
else if(sub_protocol==MR100 || sub_protocol==Q100)
packet[6] = GET_FLAG(CH9_SW , FLAG_MR100_FMODE)
|GET_FLAG(CH10_SW, FLAG_MR100_FLIP)
|GET_FLAG(CH11_SW, FLAG_MR100_VIDEO) // Does not exist on the Q100 but...
|GET_FLAG(CH12_SW, FLAG_MR100_PICTURE); // Does not exist on the Q100 but...
packet[7]=convert_channel_8b(CH7);
packet[8]=convert_channel_8b(CH8);
packet[9]=0xAA; //normal mode for Q100/Q200, unknown for V2/MR100
packet[10]=0x00; //normal mode for Q100/Q200, unknown for V2/MR100
if((sub_protocol==Q100 || sub_protocol==Q200) && CH13_SW)
{//Calibrate
packet[9]=0x77; //enter calibration
if(calib_counter>=20 && calib_counter<=25) // 7 packets for Q100 / 3 packets for Q200
packet[10]=0x20; //launch calibration
calib_counter++;
if(calib_counter>250) calib_counter=250;
}
else
calib_counter=0;
}
}
static void __attribute__((unused)) SLT_send_bind_packet()
{
SLT_wait_radio();
NRF250K_Hopping(SLT_NFREQCHANNELS); //Bind channel
BIND_IN_PROGRESS; //Limit TX power to bind level
NRF250K_SetPower();
BIND_DONE;
NRF250K_SetTXAddr((uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
memcpy((void*)packet,(void*)rx_tx_addr,SLT_TXID_SIZE);
if(phase==SLT_BIND2)
SLT_send_packet(SLT_TXID_SIZE);
else // SLT_BIND1
SLT_send_packet(SLT_PAYLOADSIZE_V2);
}
#define SLT_TIMING_BUILD 1000
#define SLT_V1_TIMING_PACKET 1000
#define SLT_V2_TIMING_PACKET 2042
#define SLT_V1_TIMING_BIND2 1000
#define SLT_V2_TIMING_BIND1 6507
#define SLT_V2_TIMING_BIND2 2112
uint16_t SLT_callback()
{
switch (phase)
{
case SLT_BUILD:
#ifdef MULTI_SYNC
telemetry_set_input_sync(sub_protocol==SLT_V1?20000:13730);
#endif
SLT_build_packet();
NRF250K_SetPower(); //Change power level
NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE);
phase++;
return SLT_TIMING_BUILD;
case SLT_DATA1:
case SLT_DATA2:
phase++;
if(sub_protocol==SLT_V1)
{
SLT_send_packet(SLT_PAYLOADSIZE_V1);
return SLT_V1_TIMING_PACKET;
}
else //V2
{
SLT_send_packet(SLT_PAYLOADSIZE_V2);
return SLT_V2_TIMING_PACKET;
}
case SLT_DATA3:
if(sub_protocol==SLT_V1)
SLT_send_packet(SLT_PAYLOADSIZE_V1);
else //V2
SLT_send_packet(SLT_PAYLOADSIZE_V2);
if (++packet_count >= 100)
{// Send bind packet
packet_count = 0;
if(sub_protocol==SLT_V1)
{
phase=SLT_BIND2;
return SLT_V1_TIMING_BIND2;
}
else //V2
{
phase=SLT_BIND1;
return SLT_V2_TIMING_BIND1;
}
}
else
{// Continue to send normal packets
phase = SLT_BUILD;
if(sub_protocol==SLT_V1)
return 20000-SLT_TIMING_BUILD;
else //V2
return 13730-SLT_TIMING_BUILD;
}
case SLT_BIND1:
SLT_send_bind_packet();
phase++;
return SLT_V2_TIMING_BIND2;
case SLT_BIND2:
SLT_send_bind_packet();
phase = SLT_BUILD;
if(sub_protocol==SLT_V1)
return 20000-SLT_TIMING_BUILD-SLT_V1_TIMING_BIND2;
else //V2
return 13730-SLT_TIMING_BUILD-SLT_V2_TIMING_BIND1-SLT_V2_TIMING_BIND2;
}
return 19000;
}
void SLT_init()
{
BIND_DONE; // Not a TX bind protocol
packet_count = 0;
packet_sent = 0;
hopping_frequency_no = 0;
if(sub_protocol==Q200)
{ //Q200: Force high part of the ID otherwise it won't bind
rx_tx_addr[0]=0x01;
rx_tx_addr[1]=0x02;
#ifdef SLT_Q200_FORCE_ID // ID taken from TX dumps
rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x6A;rx_tx_addr[3]=0x31;
/* rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x0B;rx_tx_addr[3]=0x57;*/
#endif
}
SLT_RF_init();
SLT_set_freq();
phase = SLT_BUILD;
}
#endif

View File

@@ -230,11 +230,16 @@ void SX1276_SetPaConfig(bool pa_boost_pin, uint8_t max_power, uint8_t output_pow
uint8_t data = 0x00;
data = data | (pa_boost_pin << 7);
data = data | (max_power << 4);
data = data | output_power;
data = data | (output_power & 0x0F);
SX1276_WriteReg(SX1276_09_PACONFIG, data);
}
void SX1276_SetOcp(bool OcpOn, uint8_t OcpTrim)
{
SX1276_WriteReg(SX1276_0B_OCP, (OcpOn << 5) | OcpTrim);
}
void SX1276_WritePayloadToFifo(uint8_t* payload, uint8_t length)
{
SX1276_WriteReg(SX1276_22_PAYLOAD_LENGTH, length);

View File

@@ -93,7 +93,7 @@ static int __attribute__((unused)) Scanner_scan_rssi()
return rssi_rel;
}
uint16_t Scanner_callback()
uint16_t SCANNER_callback()
{
uint8_t rssi,max_rssi;
@@ -131,7 +131,7 @@ uint16_t Scanner_callback()
return 0;
}
uint16_t initScanner(void)
void SCANNER_init(void)
{
rf_ch_num = 0;
telemetry_link = 0;
@@ -141,7 +141,6 @@ uint16_t initScanner(void)
CC2500_Strobe(CC2500_SIDLE);
CC2500_SetTxRxMode(RX_EN);
CC2500_Strobe(CC2500_SRX); // Receive mode
return 1250;
}
#endif

View File

@@ -54,7 +54,6 @@ static void __attribute__((unused)) SKYARTEC_rf_init()
for (uint8_t i = 4; i <= 0x2E; ++i)
CC2500_WriteReg(i, pgm_read_byte_near(&SKYARTEC_init_values[i-4]));
prev_option = option;
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
CC2500_SetTxRxMode(TX_EN);
@@ -121,7 +120,7 @@ static void __attribute__((unused)) SKYARTEC_send_bind_packet()
CC2500_WriteData(packet, 12);
}
uint16_t ReadSKYARTEC()
uint16_t SKYARTEC_callback()
{
if (phase & 0x01)
{
@@ -130,11 +129,7 @@ uint16_t ReadSKYARTEC()
{
CC2500_SetPower();
// Tune frequency if it has been changed
if ( prev_option != option )
{
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
prev_option = option ;
}
CC2500_SetFreqOffset();
phase = SKYARTEC_PKT1;
}
else
@@ -159,7 +154,7 @@ uint16_t ReadSKYARTEC()
return 3000;
}
uint16_t initSKYARTEC()
void SKYARTEC_init()
{
SKYARTEC_rf_init();
@@ -173,7 +168,6 @@ uint16_t initSKYARTEC()
bind_counter = 250;
phase = SKYARTEC_PKT1;
return 10000;
}
#endif

View File

@@ -189,23 +189,17 @@ static void __attribute__((unused)) SYMAX_send_packet(uint8_t bind)
NRF24L01_SetPower(); // Set tx_power
}
static void __attribute__((unused)) symax_init()
static void __attribute__((unused)) symax_rf_init()
{
NRF24L01_Initialize();
//
NRF24L01_SetTxRxMode(TX_EN);
//
NRF24L01_ReadReg(NRF24L01_07_STATUS);
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3F); // 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, 0xff); // 4mS retransmit t/o, 15 tries (retries w/o AA?)
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x08);
if (sub_protocol==SYMAX5C)
{
NRF24L01_SetBitrate(NRF24L01_BR_1M);
//NRF24L01_SetBitrate(NRF24L01_BR_1M);
packet_length = 16;
}
else
@@ -214,8 +208,6 @@ static void __attribute__((unused)) symax_init()
packet_length = 10;
}
//
NRF24L01_SetPower();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_08_OBSERVE_TX, 0x00);
NRF24L01_WriteReg(NRF24L01_09_CD, 0x00);
NRF24L01_WriteReg(NRF24L01_0C_RX_ADDR_P2, 0xC3); // LSB byte of pipe 2 receive address
@@ -231,14 +223,6 @@ static void __attribute__((unused)) symax_init()
NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR , sub_protocol==SYMAX5C ? (uint8_t *)"\x6D\x6A\x73\x73\x73" : (uint8_t *)"\xAB\xAC\xAD\xAE\xAF" ,5);
NRF24L01_ReadReg(NRF24L01_07_STATUS);
NRF24L01_FlushTx();
NRF24L01_ReadReg(NRF24L01_07_STATUS);
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x0e);
NRF24L01_ReadReg(NRF24L01_00_CONFIG);
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0c);
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0e); // power on
}
static void __attribute__((unused)) symax_init1()
@@ -331,7 +315,7 @@ static uint8_t chans_data_x5c[] = {0x1d, 0x2f, 0x26, 0x3d, 0x15, 0x2b, 0x25, 0x2
packet_count = 0;
}
uint16_t symax_callback()
uint16_t SYMAX_callback()
{
switch (phase)
{
@@ -368,14 +352,13 @@ uint16_t symax_callback()
return SYMAX_PACKET_PERIOD;
}
uint16_t initSymax()
void SYMAX_init()
{
packet_count = 0;
flags = 0;
BIND_IN_PROGRESS; // autobind protocol
symax_init();
symax_rf_init();
phase = SYMAX_INIT1;
return SYMAX_INITIAL_WAIT;
}
#endif

View File

@@ -43,7 +43,7 @@ uint16_t TEST_callback()
return TEST_PACKET_PERIOD>>1;
}
uint16_t initTEST()
void TEST_init()
{
option=1;
@@ -57,7 +57,6 @@ uint16_t initTEST()
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;
@@ -97,7 +97,7 @@ static void __attribute__((unused)) TRAXXAS_send_data_packet()
CYRF_WriteDataPacketLen(packet, TRAXXAS_PACKET_SIZE);
}
uint16_t ReadTRAXXAS()
uint16_t TRAXXAS_callback()
{
uint8_t status;
@@ -171,10 +171,8 @@ uint16_t ReadTRAXXAS()
return 13940;
}
uint16_t initTRAXXAS()
void TRAXXAS_init()
{
CYRF_Reset();
//Config CYRF registers
for(uint8_t i = 0; i < sizeof(TRAXXAS_init_vals) / 2; i++)
CYRF_WriteRegister(pgm_read_byte_near(&TRAXXAS_init_vals[i][0]), pgm_read_byte_near(&TRAXXAS_init_vals[i][1]));
@@ -199,7 +197,6 @@ uint16_t initTRAXXAS()
}
else
phase = TRAXXAS_PREP_DATA;
return 1000;
}
/*

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

@@ -19,7 +19,7 @@
uint8_t RetrySequence ;
#if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) )
#ifdef MULTI_TELEMETRY
uint32_t lastMulti = 0;
#define MULTI_TIME 500 //in ms
#ifdef MULTI_SYNC
@@ -28,7 +28,7 @@ uint8_t RetrySequence ;
uint32_t lastInputSync = 0;
uint16_t inputDelay = 0;
#endif // MULTI_SYNC
#endif // MULTI_TELEMETRY/MULTI_STATUS
#endif // MULTI_TELEMETRY
#if defined SPORT_TELEMETRY
#define FRSKY_SPORT_PACKET_SIZE 8
@@ -53,6 +53,14 @@ uint8_t RetrySequence ;
#if defined HUB_TELEMETRY
#define USER_MAX_BYTES 6
uint8_t prev_index;
struct t_FrSkyD_User_Frame
{
uint8_t ID;
uint8_t low;
uint8_t high;
} FrSkyD_User_Frame[8];
uint8_t FrSkyD_User_Frame_Start=0, FrSkyD_User_Frame_End=0;
#endif // HUB_TELEMETRY
#define START_STOP 0x7e
@@ -62,16 +70,12 @@ uint8_t RetrySequence ;
uint8_t pktx[MAX_PKTX];
uint8_t frame[18];
#if ( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) )
#ifdef MULTI_TELEMETRY
static void multi_send_header(uint8_t type, uint8_t len)
{
Serial_write('M');
#ifdef MULTI_TELEMETRY
Serial_write('P');
Serial_write(type);
#else
(void)type;
#endif
Serial_write('P');
Serial_write(type);
Serial_write(len);
}
@@ -119,15 +123,7 @@ static void telemetry_set_input_sync(uint16_t refreshRate)
static void multi_send_status()
{
#ifdef MULTI_TELEMETRY
#ifdef MULTI_NAMES
multi_send_header(MULTI_TELEMETRY_STATUS, 24);
#else
multi_send_header(MULTI_TELEMETRY_STATUS, 5);
#endif
#else
multi_send_header(MULTI_TELEMETRY_STATUS, 5);
#endif
multi_send_header(MULTI_TELEMETRY_STATUS, 24);
// Build flags
uint8_t flags=0;
@@ -138,34 +134,32 @@ static void multi_send_status()
if (remote_callback != 0)
{
flags |= 0x04;
#ifdef MULTI_NAMES
if(multi_protocols_index == 0xFF)
{
if(protocol!=PROTO_SCANNER)
flags &= ~0x04; //Invalid protocol
}
else if(sub_protocol&0x07)
{
uint8_t nbr=multi_protocols[multi_protocols_index].nbrSubProto;
//if(protocol==PROTO_DSM) nbr++; //Auto sub_protocol
if((sub_protocol&0x07)>=nbr)
flags &= ~0x04; //Invalid sub protocol
}
#else
if(remote_callback==0)
if(multi_protocols_index == 0xFF)
{
if(protocol!=PROTO_SCANNER)
flags &= ~0x04; //Invalid protocol
#endif
}
else if(sub_protocol&0x07)
{
uint8_t nbr=multi_protocols[multi_protocols_index].nbrSubProto;
//if(protocol==PROTO_DSM) nbr++; //Auto sub_protocol
if((sub_protocol&0x07)>=nbr)
flags &= ~0x04; //Invalid sub protocol
}
if (IS_WAIT_BIND_on)
flags |= 0x10;
else
if (IS_BIND_IN_PROGRESS)
flags |= 0x08;
if(IS_CHMAP_PROTOCOL)
flags |= 0x40; //Disable_ch_mapping supported
#ifdef FAILSAFE_ENABLE
if(IS_FAILSAFE_PROTOCOL)
flags |= 0x20; //Failsafe supported
#endif
if(multi_protocols_index != 0xFF)
{
if(multi_protocols[multi_protocols_index].chMap)
flags |= 0x40; //Disable_ch_mapping supported
#ifdef FAILSAFE_ENABLE
if(multi_protocols[multi_protocols_index].failSafe)
flags |= 0x20; //Failsafe supported
#endif
}
if(IS_DATA_BUFFER_LOW_on)
flags |= 0x80;
}
@@ -177,89 +171,109 @@ static void multi_send_status()
Serial_write(VERSION_REVISION);
Serial_write(VERSION_PATCH_LEVEL);
#ifdef MULTI_TELEMETRY
// Channel order
Serial_write(RUDDER<<6|THROTTLE<<4|ELEVATOR<<2|AILERON);
#endif
// Channel order
Serial_write(RUDDER<<6|THROTTLE<<4|ELEVATOR<<2|AILERON);
#ifdef MULTI_NAMES
if(multi_protocols_index == 0xFF) // selection out of list... send first available protocol
if(multi_protocols_index == 0xFF) // selection out of list... send first available protocol
{
Serial_write(multi_protocols[0].protocol); // begining of list
Serial_write(multi_protocols[0].protocol); // begining of list
for(uint8_t i=0;i<16;i++)
Serial_write(0x00); // everything else is invalid
}
else
{
// Protocol next/prev
if(multi_protocols[multi_protocols_index+1].protocol != 0)
{
Serial_write(multi_protocols[0].protocol); // begining of list
Serial_write(multi_protocols[0].protocol); // begining of list
for(uint8_t i=0;i<16;i++)
Serial_write(0x00); // everything else is invalid
if(multi_protocols[multi_protocols_index+1].protocol == PROTO_SCANNER)
{// if next is scanner
if(multi_protocols[multi_protocols_index+2].protocol != 0)
Serial_write(multi_protocols[multi_protocols_index+2].protocol); // skip to next protocol number
else
Serial_write(multi_protocols[multi_protocols_index].protocol); // or end of list
}
else
Serial_write(multi_protocols[multi_protocols_index+1].protocol); // next protocol number
}
else
Serial_write(multi_protocols[multi_protocols_index].protocol); // end of list
if(multi_protocols_index>0)
{
// Protocol next/prev
if(multi_protocols[multi_protocols_index+1].protocol != 0)
Serial_write(multi_protocols[multi_protocols_index+1].protocol); // next protocol number
else
Serial_write(multi_protocols[multi_protocols_index].protocol); // end of list
if(multi_protocols_index>0)
Serial_write(multi_protocols[multi_protocols_index-1].protocol); // prev protocol number
else
Serial_write(multi_protocols[multi_protocols_index].protocol); // begining of list
// Protocol
for(uint8_t i=0;i<7;i++)
Serial_write(multi_protocols[multi_protocols_index].ProtoString[i]); // protocol name
// Sub-protocol
uint8_t nbr=multi_protocols[multi_protocols_index].nbrSubProto;
Serial_write(nbr | (multi_protocols[multi_protocols_index].optionType<<4)); // number of sub protocols && option type
uint8_t j=0;
if(nbr && (sub_protocol&0x07)<nbr)
{
uint8_t len=multi_protocols[multi_protocols_index].SubProtoString[0];
uint8_t offset=len*(sub_protocol&0x07)+1;
for(;j<len;j++)
Serial_write(multi_protocols[multi_protocols_index].SubProtoString[j+offset]); // current sub protocol name
if(multi_protocols[multi_protocols_index-1].protocol==PROTO_SCANNER)
{// if prev is scanner
if(multi_protocols_index > 1)
Serial_write(multi_protocols[multi_protocols_index-2].protocol); // skip to prev protocol number
else
Serial_write(multi_protocols[multi_protocols_index].protocol); // begining of list
}
for(;j<8;j++)
Serial_write(0x00);
else
Serial_write(multi_protocols[multi_protocols_index-1].protocol); // prev protocol number
}
// Channels function
//TODO
#endif
else
Serial_write(multi_protocols[multi_protocols_index].protocol); // begining of list
// Protocol
for(uint8_t i=0;i<7;i++)
Serial_write(multi_protocols[multi_protocols_index].ProtoString[i]); // protocol name
// Sub-protocol
uint8_t nbr=multi_protocols[multi_protocols_index].nbrSubProto;
Serial_write(nbr | (multi_protocols[multi_protocols_index].optionType<<4)); // number of sub protocols && option type
uint8_t j=0;
if(nbr && (sub_protocol&0x07)<nbr)
{
uint8_t len=multi_protocols[multi_protocols_index].SubProtoString[0];
uint8_t offset=len*(sub_protocol&0x07)+1;
for(;j<len;j++)
Serial_write(multi_protocols[multi_protocols_index].SubProtoString[j+offset]); // current sub protocol name
}
for(;j<8;j++)
Serial_write(0x00);
}
}
#ifdef MULTI_CONFIG_INO
void CONFIG_frame()
{
multi_send_header(MULTI_TELEMETRY_CONFIG, packet_in[0]);
for (uint8_t i = 1; i <= packet_in[0]; i++) // config data
Serial_write(packet_in[i]);
}
#endif
#ifdef MLINK_FW_TELEMETRY
void MLINK_frame()
{
multi_send_header(MULTI_TELEMETRY_MLINK, 10);
Serial_write(TX_RSSI); // RSSI
Serial_write(TX_LQI); // LQI
for (uint8_t i = 0; i < 8; i++) // followed by 8 bytes of telemetry data
Serial_write(packet_in[i]);
}
#endif
#ifdef DSM_TELEMETRY
#ifdef MULTI_TELEMETRY
void DSM_frame()
void DSM_frame()
{
if (packet_in[0] == 0x80)
{
if (packet_in[0] == 0x80)
{
multi_send_header(MULTI_TELEMETRY_DSMBIND, 10);
for (uint8_t i = 1; i < 11; i++) // 10 bytes of DSM bind response
Serial_write(packet_in[i]);
multi_send_header(MULTI_TELEMETRY_DSMBIND, 10);
for (uint8_t i = 1; i < 11; i++) // 10 bytes of DSM bind response
Serial_write(packet_in[i]);
}
else
{
multi_send_header(MULTI_TELEMETRY_DSM, 17);
for (uint8_t i = 0; i < 17; i++) // RSSI value followed by 16 bytes of telemetry data
Serial_write(packet_in[i]);
}
}
#else
void DSM_frame()
else
{
Serial_write(0xAA); // Telemetry packet
for (uint8_t i = 0; i < 17; i++) // RSSI value followed by 16 bytes of telemetry data
multi_send_header(MULTI_TELEMETRY_DSM, 17);
for (uint8_t i = 0; i < 17; i++) // RSSI value followed by 16 bytes of telemetry data
Serial_write(packet_in[i]);
}
#endif
}
#endif
#ifdef SCANNER_TELEMETRY
void spectrum_scanner_frame()
{
#if defined MULTI_TELEMETRY
multi_send_header(MULTI_TELEMETRY_SCANNER, SCAN_CHANS_PER_PACKET + 1);
#else
Serial_write(0xAA); // Telemetry packet
#endif
multi_send_header(MULTI_TELEMETRY_SCANNER, SCAN_CHANS_PER_PACKET + 1);
Serial_write(packet_in[0]); // start channel
for(uint8_t ch = 0; ch < SCAN_CHANS_PER_PACKET; ch++)
Serial_write(packet_in[ch+1]); // RSSI power levels
@@ -274,11 +288,7 @@ static void multi_send_status()
len = 4 + (len / 8);
else
len = 5 + (len / 8);
#if defined MULTI_TELEMETRY
multi_send_header(MULTI_TELEMETRY_RX_CHANNELS, len);
#else
Serial_write(0xAA); // Telemetry packet
#endif
multi_send_header(MULTI_TELEMETRY_RX_CHANNELS, len);
for (uint8_t i = 0; i < len; i++)
Serial_write(packet_in[i]); // pps, rssi, ch start, ch count, 16x ch data
}
@@ -287,11 +297,7 @@ static void multi_send_status()
#ifdef AFHDS2A_FW_TELEMETRY
void AFHDSA_short_frame()
{
#if defined MULTI_TELEMETRY
multi_send_header(packet_in[29]==0xAA?MULTI_TELEMETRY_AFHDS2A:MULTI_TELEMETRY_AFHDS2A_AC, 29);
#else
Serial_write(packet_in[29]); // Telemetry packet 0xAA or 0xAC
#endif
multi_send_header(packet_in[29]==0xAA?MULTI_TELEMETRY_AFHDS2A:MULTI_TELEMETRY_AFHDS2A_AC, 29);
for (uint8_t i = 0; i < 29; i++) // RSSI value followed by 4*7 bytes of telemetry data
Serial_write(packet_in[i]);
}
@@ -300,11 +306,7 @@ static void multi_send_status()
#ifdef HITEC_FW_TELEMETRY
void HITEC_short_frame()
{
#if defined MULTI_TELEMETRY
multi_send_header(MULTI_TELEMETRY_HITEC, 8);
#else
Serial_write(0xAA); // Telemetry packet
#endif
multi_send_header(MULTI_TELEMETRY_HITEC, 8);
for (uint8_t i = 0; i < 8; i++) // TX RSSI and TX LQI values followed by frame number and 5 bytes of telemetry data
Serial_write(packet_in[i]);
}
@@ -313,24 +315,20 @@ static void multi_send_status()
#ifdef HOTT_FW_TELEMETRY
void HOTT_short_frame()
{
#if defined MULTI_TELEMETRY
multi_send_header(MULTI_TELEMETRY_HOTT, 14);
#else
Serial_write(0xAA); // Telemetry packet
#endif
multi_send_header(MULTI_TELEMETRY_HOTT, 14);
for (uint8_t i = 0; i < 14; i++) // TX RSSI and TX LQI values followed by frame number and telemetry data
Serial_write(packet_in[i]);
}
#endif
#ifdef MULTI_TELEMETRY
static void multi_send_frskyhub()
{
multi_send_header(MULTI_TELEMETRY_HUB, 9);
for (uint8_t i = 0; i < 9; i++)
Serial_write(frame[i]);
}
#endif
#endif //MULTI_TELEMETRY
void frskySendStuffed()
{
@@ -517,6 +515,9 @@ void init_frskyd_link_telemetry()
TX_RSSI=0;
RX_LQI=0;
TX_LQI=0;
#if defined HUB_TELEMETRY
FrSkyD_User_Frame_Start=FrSkyD_User_Frame_End=0;
#endif
}
void frsky_link_frame()
@@ -531,11 +532,11 @@ void frsky_link_frame()
telemetry_link |= 2 ; // Send hub if available
}
else
{//PROTO_HUBSAN, PROTO_AFHDS2A, PROTO_BAYANG, PROTO_NCC1701, PROTO_CABELL, PROTO_HITEC, PROTO_BUGS, PROTO_BUGSMINI, PROTO_FRSKYX, PROTO_FRSKYX2, PROTO_PROPEL, PROTO_DEVO, PROTO_RLINK
{//PROTO_HUBSAN, PROTO_AFHDS2A, PROTO_BAYANG, PROTO_NCC1701, PROTO_CABELL, PROTO_HITEC, PROTO_BUGS, PROTO_BUGSMINI, PROTO_FRSKYX, PROTO_FRSKYX2, PROTO_PROPEL, PROTO_DEVO, PROTO_RLINK, PROTO_OMP, PROTO_WFLY2, PROTO_LOLI, PROTO_MLINK
frame[1] = v_lipo1;
frame[2] = v_lipo2;
frame[3] = RX_RSSI;
telemetry_link=0;
telemetry_link &= ~1 ; // Sent
}
frame[4] = TX_RSSI;
frame[5] = RX_LQI;
@@ -563,7 +564,7 @@ void frsky_user_frame()
else
{
frame[1]=telemetry_in_buffer[6]; // packet size
telemetry_link=0; // only 1 packet or processing second packet
telemetry_link &= ~2; // only 1 packet or processing second packet
}
frame[2] = telemetry_in_buffer[7];
for(uint8_t i=0;i<USER_MAX_BYTES;i++)
@@ -578,7 +579,7 @@ void frsky_user_frame()
#endif
}
else
telemetry_link=0;
telemetry_link &= ~2;
}
/*
HuB RX packets.
@@ -594,6 +595,54 @@ packet_in[6]|(counter++)|00 01 02 03 04 05 06 07 08 09
0A 0F 5E 3A 06 00 5E 5E 3B 09 00 5E
05 10 5E 06 16 72 5E 5E 3A 06 00 5E
*/
static void __attribute__((unused)) frsky_write_user_frame(uint8_t ID, uint8_t low, uint8_t high)
{
telemetry_in_buffer[6] = 0x04; // number of bytes in the payload
telemetry_in_buffer[7] = 0x00; // unknown?
telemetry_in_buffer[8] = 0x5E; // start of payload
telemetry_in_buffer[9] = ID; // ID must be less than 0x40
uint8_t pos=10;
uint8_t value = low;
for(uint8_t i=0;i<2;i++)
{// Byte stuffing
if(value == 0x5D || value == 0x5E)
{// Byte stuffing
telemetry_in_buffer[pos+1] = value ^ 0x60;
telemetry_in_buffer[pos] = 0x5D;
telemetry_in_buffer[6]++; // 1 more byte in the payload
pos += 2;
}
else
telemetry_in_buffer[pos++] = value;
value = high;
}
telemetry_link |= 2; // request to send frame
}
static void __attribute__((unused)) frsky_send_user_frame(uint8_t ID, uint8_t low, uint8_t high)
{
if(telemetry_link&2)
{ // add to buffer
uint8_t test = (FrSkyD_User_Frame_End + 1) & 0x07;
if(test == FrSkyD_User_Frame_Start)
return; // buffer full...
FrSkyD_User_Frame_End = test;
FrSkyD_User_Frame[FrSkyD_User_Frame_End].ID = ID;
FrSkyD_User_Frame[FrSkyD_User_Frame_End].low = low;
FrSkyD_User_Frame[FrSkyD_User_Frame_End].high = high;
}
else // send to TX direct
frsky_write_user_frame(ID, low, high);
}
static void __attribute__((unused)) frsky_check_user_frame()
{
if((telemetry_link&2) || FrSkyD_User_Frame_Start == FrSkyD_User_Frame_End)
return; // need to wait that the last frame is sent or buffer is empty
frsky_write_user_frame(FrSkyD_User_Frame[FrSkyD_User_Frame_Start].ID, FrSkyD_User_Frame[FrSkyD_User_Frame_Start].low, FrSkyD_User_Frame[FrSkyD_User_Frame_Start].high);
FrSkyD_User_Frame_Start++;
FrSkyD_User_Frame_Start &= 0x07;
}
#endif
@@ -854,7 +903,7 @@ void TelemetryUpdate()
debugln("TEL_BUF %d",t);
*/
#endif
#if defined(MULTI_TELEMETRY) || defined(MULTI_STATUS)
#ifdef MULTI_TELEMETRY
uint32_t now = millis();
if ((IS_SEND_MULTI_STATUS_on || ((now - lastMulti) > MULTI_TIME))&& protocol != PROTO_SCANNER)
{
@@ -900,67 +949,84 @@ void TelemetryUpdate()
}
#endif // SPORT_TELEMETRY
#if defined DSM_TELEMETRY
if(telemetry_link && protocol == PROTO_DSM)
{ // DSM
DSM_frame();
telemetry_link=0;
return;
}
#endif
#if defined AFHDS2A_FW_TELEMETRY
if(telemetry_link == 2 && protocol == PROTO_AFHDS2A)
{
AFHDSA_short_frame();
telemetry_link=0;
return;
}
#endif
#if defined HITEC_FW_TELEMETRY
if(telemetry_link == 2 && protocol == PROTO_HITEC)
{
HITEC_short_frame();
telemetry_link=0;
return;
}
#endif
#if defined HOTT_FW_TELEMETRY
if(telemetry_link == 2 && protocol == PROTO_HOTT)
{
HOTT_short_frame();
telemetry_link=0;
return;
}
#endif
#if defined SCANNER_TELEMETRY
if (telemetry_link && protocol == PROTO_SCANNER)
{
spectrum_scanner_frame();
telemetry_link = 0;
return;
}
#endif
#if defined (FRSKY_RX_TELEMETRY) || defined(AFHDS2A_RX_TELEMETRY) || defined (BAYANG_RX_TELEMETRY) || defined (DSM_RX_CYRF6936_INO)
if ((telemetry_link & 1) && (protocol == PROTO_FRSKY_RX || protocol == PROTO_AFHDS2A_RX || protocol == PROTO_BAYANG_RX || protocol == PROTO_DSM_RX) )
{
receiver_channels_frame();
telemetry_link &= ~1;
return;
}
#endif
if( telemetry_link & 1 )
{ // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs + BugsMini + NCC1701 + PROPEL + RLINK
// FrSkyX telemetry if in PPM
frsky_link_frame();
return;
}
#ifdef MULTI_TELEMETRY
#if defined MULTI_CONFIG_INO
if(telemetry_link && protocol == PROTO_CONFIG)
{
CONFIG_frame();
telemetry_link=0;
return;
}
#endif
#if defined MLINK_FW_TELEMETRY
if(telemetry_link && protocol == PROTO_MLINK)
{
MLINK_frame();
telemetry_link=0;
return;
}
#endif
#if defined DSM_TELEMETRY
if(telemetry_link && protocol == PROTO_DSM)
{ // DSM
DSM_frame();
telemetry_link=0;
return;
}
#endif
#if defined AFHDS2A_FW_TELEMETRY
if(telemetry_link == 2 && protocol == PROTO_AFHDS2A)
{
AFHDSA_short_frame();
telemetry_link=0;
return;
}
#endif
#if defined HITEC_FW_TELEMETRY
if(telemetry_link == 2 && protocol == PROTO_HITEC)
{
HITEC_short_frame();
telemetry_link=0;
return;
}
#endif
#if defined HOTT_FW_TELEMETRY
if(telemetry_link == 2 && protocol == PROTO_HOTT)
{
HOTT_short_frame();
telemetry_link=0;
return;
}
#endif
#if defined SCANNER_TELEMETRY
if (telemetry_link && protocol == PROTO_SCANNER)
{
spectrum_scanner_frame();
telemetry_link = 0;
return;
}
#endif
#if defined (FRSKY_RX_TELEMETRY) || defined(AFHDS2A_RX_TELEMETRY) || defined (BAYANG_RX_TELEMETRY) || defined (DSM_RX_CYRF6936_INO)
if ((telemetry_link & 1) && (protocol == PROTO_FRSKY_RX || protocol == PROTO_AFHDS2A_RX || protocol == PROTO_BAYANG_RX || protocol == PROTO_DSM_RX) )
{
receiver_channels_frame();
telemetry_link &= ~1;
return;
}
#endif
#endif //MULTI_TELEMETRY
if( telemetry_link & 1 )
{ // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs + BugsMini + NCC1701 + PROPEL + RLINK + OMP + MLINK + DEVO
// FrSkyX telemetry if in PPM
frsky_link_frame();
return;
}
#if defined HUB_TELEMETRY
if((telemetry_link & 2) && protocol == PROTO_FRSKYD)
{ // FrSkyD
if((telemetry_link & 2) && ( protocol == PROTO_FRSKYD || protocol == PROTO_BAYANG || protocol == PROTO_MLINK || protocol == PROTO_DEVO ) )
{ // FrSkyD + Bayang + MLINK + DEVO
frsky_user_frame();
frsky_check_user_frame();
return;
}
#endif
@@ -1000,7 +1066,6 @@ void TelemetryUpdate()
#else
#ifdef STM32_BOARD
usart3_begin(9600,SERIAL_8N1); //USART3
USART3_BASE->CR1 &= ~ USART_CR1_RE; //disable RX leave TX enabled
#else
UBRR0H = 0x00;
UBRR0L = 0x67;
@@ -1021,7 +1086,6 @@ void TelemetryUpdate()
#else
#ifdef STM32_BOARD
usart3_begin(57600,SERIAL_8N1); //USART3
USART3_BASE->CR1 &= ~ USART_CR1_RE; //disable RX leave TX enabled
#else
UBRR0H = 0x00;
UBRR0L = 0x22;
@@ -1042,7 +1106,6 @@ void TelemetryUpdate()
#else
#ifdef STM32_BOARD
usart3_begin(125000,SERIAL_8N1); //USART3
USART3_BASE->CR1 &= ~ USART_CR1_RE; //disable RX leave TX enabled
#else
UBRR0H = 0x00;
UBRR0L = 0x07;

View File

@@ -88,23 +88,11 @@ static void __attribute__((unused)) TIGER_send_packet()
NRF24L01_SetPower();
}
static void __attribute__((unused)) TIGER_init()
static void __attribute__((unused)) TIGER_RF_init()
{
NRF24L01_Initialize();
NRF24L01_SetTxRxMode(TX_EN);
XN297_SetTXAddr((uint8_t *)"\x68\x94\xA6\xD5\xC3", 5);
NRF24L01_FlushTx();
NRF24L01_FlushRx();
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // No retransmits
NRF24L01_SetPower();
NRF24L01_Activate(0x73); // Activate feature register
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
NRF24L01_Activate(0x73);
// Power on, TX mode, 2byte CRC
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
}
@@ -132,7 +120,7 @@ uint16_t TIGER_callback()
#ifdef MULTI_SYNC
telemetry_set_input_sync(TIGER_PACKET_PERIOD);
#endif
if(IS_BIND_IN_PROGRESS)
if(bind_counter)
if(--bind_counter==0)
{
BIND_DONE;
@@ -142,14 +130,13 @@ uint16_t TIGER_callback()
return TIGER_PACKET_PERIOD;
}
uint16_t initTIGER()
void TIGER_init()
{
BIND_IN_PROGRESS; // autobind protocol
TIGER_initialize_txid();
TIGER_init();
TIGER_RF_init();
hopping_frequency_no = 0;
bind_counter=TIGER_BIND_COUNT;
return TIGER_INITIAL_WAIT;
}
#endif

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