mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-11-26 05:59:41 +00:00
Compare commits
300 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96263ed8a6 | ||
|
|
7bb1cb9ae3 | ||
|
|
20e32c4cb0 | ||
|
|
b4421306c0 | ||
|
|
e53f723fdb | ||
|
|
832a331437 | ||
|
|
12e66bd84f | ||
|
|
d290cc519f | ||
|
|
f4b19fe33e | ||
|
|
767d2c079a | ||
|
|
7750310be5 | ||
|
|
6de4e1e1dd | ||
|
|
627d47f139 | ||
|
|
36675cf729 | ||
|
|
33d8234eb3 | ||
|
|
347eb11328 | ||
|
|
5ed61f30e1 | ||
|
|
a633f46f4f | ||
|
|
baf9a0f978 | ||
|
|
c98b8fc8bf | ||
|
|
2fae0a35b8 | ||
|
|
b04f38ed3d | ||
|
|
60d5dd4101 | ||
|
|
75b7dd1dd7 | ||
|
|
aa2717d6ab | ||
|
|
4058f04b39 | ||
|
|
25ebd55c85 | ||
|
|
d00b58c8ed | ||
|
|
e7eb07a5a4 | ||
|
|
a4cac50261 | ||
|
|
4f8da64822 | ||
|
|
4f89721cd0 | ||
|
|
43c2843490 | ||
|
|
c152265284 | ||
|
|
b591b92b4e | ||
|
|
090388aa1b | ||
|
|
c6ab696949 | ||
|
|
df45a3ff83 | ||
|
|
fedd04b724 | ||
|
|
d8630da09d | ||
|
|
6192f7287e | ||
|
|
5b8a08ab22 | ||
|
|
313b03fb84 | ||
|
|
5639def6fb | ||
|
|
15a254879c | ||
|
|
5baa9bd256 | ||
|
|
d5346c0eaf | ||
|
|
a2213fd6dc | ||
|
|
9b07f12f90 | ||
|
|
c9b49483e0 | ||
|
|
e2972a5823 | ||
|
|
d5b3ed832d | ||
|
|
9fcc030c15 | ||
|
|
fc81b7ee5a | ||
|
|
f168abc2bb | ||
|
|
fe6778635e | ||
|
|
65a6c19d02 | ||
|
|
a32b5561a1 | ||
|
|
4b4393952e | ||
|
|
ea205b1e69 | ||
|
|
748140cdee | ||
|
|
e8037c857f | ||
|
|
15e37cefee | ||
|
|
b1e4daf1c2 | ||
|
|
4e0fccfc63 | ||
|
|
48b90029c4 | ||
|
|
8b189af2f9 | ||
|
|
030cdd35a2 | ||
|
|
3789998ba9 | ||
|
|
ea24ab6032 | ||
|
|
1408431649 | ||
|
|
6810372064 | ||
|
|
708e2ac5f6 | ||
|
|
2178f6761d | ||
|
|
aa5fd82004 | ||
|
|
660282db2e | ||
|
|
fdd357619b | ||
|
|
5f12f99761 | ||
|
|
3d98abb6d4 | ||
|
|
e35879a5d0 | ||
|
|
37138f03ae | ||
|
|
51d39bbd8c | ||
|
|
0932a1c93f | ||
|
|
19164521e4 | ||
|
|
df28cfe3cc | ||
|
|
354878d542 | ||
|
|
695264d59a | ||
|
|
de190f3349 | ||
|
|
b049385094 | ||
|
|
75dc616130 | ||
|
|
b542f5e7cd | ||
|
|
f3bee3cded | ||
|
|
a9b7ab9a06 | ||
|
|
ed019e954e | ||
|
|
65186b4356 | ||
|
|
e1d4f9a270 | ||
|
|
69c95ca153 | ||
|
|
e6976fb08d | ||
|
|
f502ba3659 | ||
|
|
e6ccc7e7cc | ||
|
|
da9d8851c2 | ||
|
|
ad48291d2a | ||
|
|
d6da230369 | ||
|
|
f8ac406a94 | ||
|
|
e691ecd167 | ||
|
|
930c26a111 | ||
|
|
64419a6cf4 | ||
|
|
5c59cddc7a | ||
|
|
4c7a51be46 | ||
|
|
7dad0fb89f | ||
|
|
adebb3fc5c | ||
|
|
5ab00b9d18 | ||
|
|
fbd5d7cf48 | ||
|
|
84132678cc | ||
|
|
78421748ba | ||
|
|
7112f58dae | ||
|
|
e56f737b34 | ||
|
|
49d993f613 | ||
|
|
63dd8a9215 | ||
|
|
d5f819dd59 | ||
|
|
a68787f16e | ||
|
|
858ef5801c | ||
|
|
9e0bd29cee | ||
|
|
15395de579 | ||
|
|
db4aad04a7 | ||
|
|
466e4cf227 | ||
|
|
05a3780c38 | ||
|
|
85ea91cdbb | ||
|
|
985d7a6fd9 | ||
|
|
2a19b8dd45 | ||
|
|
b2b3078861 | ||
|
|
2ac92f5725 | ||
|
|
e2f5afd71e | ||
|
|
e094ee036d | ||
|
|
2ad7f3e9f2 | ||
|
|
8e1f2258f8 | ||
|
|
5c01bbf284 | ||
|
|
647425fc1a | ||
|
|
7286049d07 | ||
|
|
ce67a065cd | ||
|
|
8948cb6287 | ||
|
|
4daa5fa2bb | ||
|
|
c49a7dae0a | ||
|
|
890a042a43 | ||
|
|
c95e576ef3 | ||
|
|
2aa96dd129 | ||
|
|
908634474b | ||
|
|
79b525ee71 | ||
|
|
872b8259ab | ||
|
|
a14c82708f | ||
|
|
7e53778680 | ||
|
|
210fbe3b9e | ||
|
|
0a5fd72bdc | ||
|
|
6e1701ecc5 | ||
|
|
a5f627a2d6 | ||
|
|
b4a1f175c6 | ||
|
|
e0690fa661 | ||
|
|
bd962eff35 | ||
|
|
b515355249 | ||
|
|
d1feef97be | ||
|
|
f52f96d44e | ||
|
|
944ec62f49 | ||
|
|
30905014d2 | ||
|
|
32dbdfc6e3 | ||
|
|
b2e312b41e | ||
|
|
52f4096197 | ||
|
|
c547ea0c0f | ||
|
|
c73ee61128 | ||
|
|
90b287f1f4 | ||
|
|
0316c9eea9 | ||
|
|
374b46966c | ||
|
|
3705415927 | ||
|
|
bff68f482e | ||
|
|
32ed758072 | ||
|
|
5ce99ee419 | ||
|
|
ceea384a36 | ||
|
|
fd3b026e12 | ||
|
|
7e451c13a8 | ||
|
|
3dcf74c2e4 | ||
|
|
50f1eca4be | ||
|
|
0d97af5ae2 | ||
|
|
aeb8d67219 | ||
|
|
1f65025036 | ||
|
|
8df3687684 | ||
|
|
adf59a9d0d | ||
|
|
b9f00bdbc5 | ||
|
|
a10e169573 | ||
|
|
317b9a8156 | ||
|
|
1c632d462f | ||
|
|
c46b49ccf1 | ||
|
|
e70708b133 | ||
|
|
62486c2220 | ||
|
|
cffe66747a | ||
|
|
b31bbfa04f | ||
|
|
48e4cad3ad | ||
|
|
53f58ce2e1 | ||
|
|
eb8b5eac01 | ||
|
|
02008a8b2e | ||
|
|
5b82599eb9 | ||
|
|
a5e4b2c6fa | ||
|
|
987753ff73 | ||
|
|
ee080839b1 | ||
|
|
4290c75478 | ||
|
|
cc6be6027d | ||
|
|
4cfde0a80a | ||
|
|
a77aee0e1a | ||
|
|
6f36473975 | ||
|
|
f5720d38bb | ||
|
|
23478d3d21 | ||
|
|
ba72b6dedd | ||
|
|
103f595891 | ||
|
|
957d623b4b | ||
|
|
2be757e609 | ||
|
|
c4be660a05 | ||
|
|
c1c5f9fe3a | ||
|
|
53c0637a85 | ||
|
|
4ae30dc3b0 | ||
|
|
fc5fbc9899 | ||
|
|
2397bf365b | ||
|
|
42cd17d5f2 | ||
|
|
a35e01bbeb | ||
|
|
b21e8030b3 | ||
|
|
0984a42fe5 | ||
|
|
ed50d60108 | ||
|
|
a7f72a73e5 | ||
|
|
1c02cb46f5 | ||
|
|
da8fd21177 | ||
|
|
7e5cd9819a | ||
|
|
00aecb3ab1 | ||
|
|
cde77a88fd | ||
|
|
08a555f187 | ||
|
|
4039cbf8af | ||
|
|
3f652fa06c | ||
|
|
272d2be3ae | ||
|
|
7e461344a8 | ||
|
|
8af985a2cb | ||
|
|
08eee34446 | ||
|
|
0a5b97a177 | ||
|
|
cab782b38e | ||
|
|
d1518d763b | ||
|
|
44a676b809 | ||
|
|
d66709ea87 | ||
|
|
358a77cf7c | ||
|
|
1a631908f4 | ||
|
|
9f32a1f22b | ||
|
|
dfd3386319 | ||
|
|
3df836e6b8 | ||
|
|
2b8ed25843 | ||
|
|
62250d2f25 | ||
|
|
a4e9082f53 | ||
|
|
7217e8c41d | ||
|
|
a7ac093753 | ||
|
|
5503502bad | ||
|
|
5124c2a96d | ||
|
|
73d7728e08 | ||
|
|
8b7bd00a48 | ||
|
|
68a6af0eb5 | ||
|
|
693f9f58eb | ||
|
|
4a01e2d472 | ||
|
|
e4fd1f4399 | ||
|
|
0d5fcb0849 | ||
|
|
2236c256ba | ||
|
|
945ad2e7bd | ||
|
|
6f9740f03f | ||
|
|
f9fa4dff73 | ||
|
|
77bf17967d | ||
|
|
7281c0b5bf | ||
|
|
e6cab65560 | ||
|
|
cc115323e1 | ||
|
|
58665ea7a7 | ||
|
|
3920644caf | ||
|
|
25aecbf15e | ||
|
|
e18d8868d2 | ||
|
|
c6e5d00a2b | ||
|
|
7a5b4dea1a | ||
|
|
5df877f32c | ||
|
|
c5c7dda2e0 | ||
|
|
492b9e5ed4 | ||
|
|
9f721c528d | ||
|
|
7f3c80c2a9 | ||
|
|
8f789607e4 | ||
|
|
6a9b6ed4be | ||
|
|
953a97dae4 | ||
|
|
86778c5997 | ||
|
|
8c32cdf5fd | ||
|
|
d092593e5c | ||
|
|
edbf4b6908 | ||
|
|
43f688d011 | ||
|
|
054c3088c3 | ||
|
|
0cedd5bb66 | ||
|
|
1961579fe4 | ||
|
|
6906f1652e | ||
|
|
e2bbe8a422 | ||
|
|
8ea4e00d31 | ||
|
|
917e27280f | ||
|
|
ec92edfc85 | ||
|
|
afd2be6c59 | ||
|
|
a23d50bf0d | ||
|
|
cace1144db | ||
|
|
0d646ed1a6 |
262
.travis.yml
262
.travis.yml
@@ -1,17 +1,17 @@
|
||||
os: linux
|
||||
dist: bionic
|
||||
sudo: true
|
||||
language: c
|
||||
|
||||
env:
|
||||
global:
|
||||
- IDE_VERSION=1.8.9
|
||||
matrix:
|
||||
jobs:
|
||||
- BOARD="multi4in1:avr:multiatmega328p:bootloader=none"
|
||||
- BOARD="multi4in1:avr:multiatmega328p:bootloader=optiboot"
|
||||
- BOARD="multi4in1:avr:multixmega32d4"
|
||||
- BOARD="multi4in1:STM32F1:multistm32f103c:debug_option=none"
|
||||
- BOARD="multi4in1:STM32F1:multistm32f103c:debug_option=native"
|
||||
- BOARD="multi4in1:STM32F1:multistm32f103c:debug_option=ftdi"
|
||||
- BOARD="multi4in1:STM32F1:multi5in1t18int"
|
||||
- BOARD="multi4in1:STM32F1:multistm32f103cb:debug_option=none"
|
||||
- BOARD="multi4in1:STM32F1:multistm32f103cb:debug_option=native"
|
||||
- BOARD="multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi"
|
||||
- BOARD="multi4in1:STM32F1:multistm32f103c8:debug_option=none"
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
@@ -24,16 +24,8 @@ before_install:
|
||||
- chmod +x ${TRAVIS_BUILD_DIR}/buildroot/bin/*
|
||||
- export PATH=${TRAVIS_BUILD_DIR}/buildroot/bin/:${PATH}
|
||||
|
||||
# Arduino IDE adds a lot of noise caused by network traffic; firewall it
|
||||
- sudo iptables -P INPUT DROP
|
||||
- sudo iptables -P FORWARD DROP
|
||||
- sudo iptables -P OUTPUT ACCEPT
|
||||
- sudo iptables -A INPUT -i lo -j ACCEPT
|
||||
- sudo iptables -A OUTPUT -o lo -j ACCEPT
|
||||
- sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
# Helper functions for the builds
|
||||
- buildMulti() { start_fold config_diff; travis_time_start; git diff Multiprotocol/_Config.h; end_fold config_diff; exitcode=0; BUILDCMD="arduino --verify --board $BOARD Multiprotocol/Multiprotocol.ino --pref build.path=./build/"; echo $BUILDCMD; $BUILDCMD; if [ $? -ne 0 ]; then exitcode=1; fi; echo; return $exitcode; }
|
||||
- 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; }
|
||||
@@ -41,201 +33,66 @@ before_install:
|
||||
- buildDefault() { exitcode=0; printf "\n\e[33;1mBuilding default configuration\e[0m\n"; buildMulti; if [ $? -ne 0 ]; then exitcode=1; fi; return $exitcode; }
|
||||
- buildSerialOnly() { exitcode=0; printf "\n\e[33;1mBuilding serial mode only\e[0m\n"; opt_disable ENABLE_PPM; opt_enable ENABLE_SERIAL; buildMulti; if [ $? -ne 0 ]; then exitcode=1; fi; return $exitcode; }
|
||||
- buildPPMOnly() { exitcode=0; printf "\n\e[33;1mBuilding PPM mode only\e[0m\n"; opt_enable ENABLE_PPM; opt_disable ENABLE_SERIAL; buildMulti; if [ $? -ne 0 ]; then exitcode=1; fi; return $exitcode; }
|
||||
- export -f buildMulti
|
||||
|
||||
# Function to build the release files - dependent on board type
|
||||
# Function to build the release files - dependent on board type.
|
||||
# Release build scripts are located in buildroot/bin.
|
||||
- if [[ "$BOARD" == "multi4in1:avr:multixmega32d4" ]]; then
|
||||
buildReleaseFiles(){
|
||||
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;
|
||||
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;
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-orangerx-aetr-blue-inv-v$MULTI_VERSION.bin;
|
||||
cp Multiprotocol/Multi.txt ./binaries/Multi.txt; };
|
||||
build_release_orx;
|
||||
};
|
||||
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";
|
||||
opt_disable CHECK_FOR_BOOTLOADER;
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable $A7105_PROTOCOLS;
|
||||
buildMulti;
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-usbasp-aetr-A7105-inv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-avr-usbasp-aetr-CC2500-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable $CC2500_PROTOCOLS;
|
||||
buildMulti;
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-usbasp-aetr-CC2500-inv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-avr-usbasp-aetr-CYRF6936-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable $CYRF6936_PROTOCOLS;
|
||||
buildMulti;
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-usbasp-aetr-CYRF6936-inv-v$MULTI_VERSION.bin; };
|
||||
build_release_avr_noboot;
|
||||
};
|
||||
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";
|
||||
opt_enable CHECK_FOR_BOOTLOADER;
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable $A7105_PROTOCOLS;
|
||||
buildMulti;
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-txflash-aetr-A7105-inv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-avr-txflash-aetr-CC2500-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable $CC2500_PROTOCOLS;
|
||||
buildMulti;
|
||||
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;
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-txflash-aetr-CYRF6936-inv-v$MULTI_VERSION.bin; };
|
||||
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c:debug_option=none" ]]; then
|
||||
build_release_avr_optiboot;
|
||||
};
|
||||
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=none" ]]; then
|
||||
buildReleaseFiles(){
|
||||
printf "\n\e[33;1mBuilding multi-stm-erskytx-aetr-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_enable CHECK_FOR_BOOTLOADER;
|
||||
opt_enable $ALL_PROTOCOLS;
|
||||
opt_enable MULTI_STATUS;
|
||||
opt_disable MULTI_TELEMETRY;
|
||||
buildMulti;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-ppm-reta-noinv-v$MULTI_VERSION.bin; };
|
||||
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c:debug_option=native" ]]; then
|
||||
build_release_stm32f1_no_debug;
|
||||
};
|
||||
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=native" ]]; then
|
||||
buildReleaseFiles(){
|
||||
printf "\n\e[33;1mBuilding multi-stm-erskytx-xn297dump-inv-usbdebug-v$MULTI_VERSION.bin\e[0m";
|
||||
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;
|
||||
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;
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-xn297dump-inv-usbdebug-v$MULTI_VERSION.bin; };
|
||||
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c:debug_option=ftdi" ]]; then
|
||||
build_release_stm32f1_native_debug;
|
||||
};
|
||||
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi" ]]; then
|
||||
buildReleaseFiles(){
|
||||
printf "\n\e[33;1mBuilding multi-stm-erskytx-xn297dump-inv-ftdidebug-v$MULTI_VERSION.bin\e[0m";
|
||||
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;
|
||||
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;
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-xn297dump-inv-ftdidebug-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-erskytx-aetr-inv-ftdidebug-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_enable $ALL_PROTOCOLS;
|
||||
opt_enable MULTI_STATUS;
|
||||
opt_disable MULTI_TELEMETRY;
|
||||
buildMulti;
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-aetr-inv-ftdidebug-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-opentx-aetr-inv-ftdidebug-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_disable MULTI_STATUS;
|
||||
opt_enable MULTI_TELEMETRY;
|
||||
buildMulti;
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-aetr-inv-ftdidebug-v$MULTI_VERSION.bin; };
|
||||
build_release_stm32f1_serial_debug;
|
||||
};
|
||||
elif [[ "$BOARD" == "multi4in1:STM32F1:multi5in1t18int" ]]; then
|
||||
buildReleaseFiles(){
|
||||
build_release_stm32f1_t18int;
|
||||
};
|
||||
else
|
||||
buildReleaseFiles() { echo "No release files for this board."; };
|
||||
buildReleaseFiles() { printf "No release files for this board."; };
|
||||
fi
|
||||
|
||||
install:
|
||||
# Install Arduino IDE
|
||||
- wget http://downloads.arduino.cc/arduino-$IDE_VERSION-linux64.tar.xz
|
||||
- tar xf arduino-$IDE_VERSION-linux64.tar.xz
|
||||
- mv arduino-$IDE_VERSION $HOME/arduino-ide
|
||||
- export PATH=$PATH:$HOME/arduino-ide
|
||||
# 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
|
||||
|
||||
# Set the Multi boards package URL
|
||||
- arduino --pref "boardsmanager.additional.urls=https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/master/package_multi_4in1_board_index.json" --save-prefs
|
||||
# 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 --install-boards multi4in1:STM32F1;
|
||||
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 --install-boards multi4in1:avr;
|
||||
arduino-cli core install arduino:avr;
|
||||
arduino-cli core install multi4in1:avr --additional-urls https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/master/package_multi_4in1_board_index.json;
|
||||
fi
|
||||
|
||||
before_script:
|
||||
# Export all the variables
|
||||
- set -a
|
||||
|
||||
# Change current working directory to the build dir
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
|
||||
@@ -260,24 +117,43 @@ before_script:
|
||||
- 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);
|
||||
else
|
||||
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
|
||||
- ALL_RFMODULES=$(echo A7105_INSTALLED CYRF6936_INSTALLED CC2500_INSTALLED NRF24L01_INSTALLED);
|
||||
- if [[ "$BOARD" =~ "multi4in1:avr:multixmega32d4" ]]; then
|
||||
ALL_RFMODULES=$(echo CYRF6936_INSTALLED);
|
||||
elif [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:" ]]; then
|
||||
ALL_RFMODULES=$(echo A7105_INSTALLED CYRF6936_INSTALLED CC2500_INSTALLED NRF24L01_INSTALLED);
|
||||
elif [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
|
||||
ALL_RFMODULES=$(echo A7105_INSTALLED CYRF6936_INSTALLED CC2500_INSTALLED NRF24L01_INSTALLED SX1276_INSTALLED);
|
||||
fi
|
||||
- echo $ALL_RFMODULES
|
||||
|
||||
# Disable CHECK_FOR_BOOTLOADER when not needed
|
||||
- if [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=none" ]]; then
|
||||
opt_disable CHECK_FOR_BOOTLOADER;
|
||||
fi
|
||||
|
||||
# Trim the enabled protocols down for the STM32 board with USB debugging
|
||||
- if [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c:debug_option=native" ]]; then
|
||||
opt_disable AFHDS2A_RX_A7105_INO FRSKY_RX_CC2500_INO SCANNER_CC2500_INO WK2x01_CYRF6936_INO HUBSAN_A7105_INO;
|
||||
# Trim the enabled protocols down for the STM32F103CB board with debugging
|
||||
- if [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi" ]] || [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=native" ]]; then
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable FRSKYX_CC2500_INO AFHDS2A_A7105_INO MJXQ_NRF24L01_INO DSM_CYRF6936_INO;
|
||||
fi
|
||||
|
||||
# Trim the enabled protocols down for the STM32F103C8 board
|
||||
- if [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c8:debug_option=none" ]]; then
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable FRSKYX_CC2500_INO AFHDS2A_A7105_INO MJXQ_NRF24L01_INO DSM_CYRF6936_INO;
|
||||
fi
|
||||
|
||||
# Trim the enabled protocols down for the Atmega328p board
|
||||
@@ -295,7 +171,7 @@ before_script:
|
||||
- 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
|
||||
# Build with default configuration - all protocols are enabled for STM32; a subset of protocols for Atmega or STM32 debugging
|
||||
- buildDefault
|
||||
|
||||
# Serial only
|
||||
@@ -325,7 +201,7 @@ script:
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
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
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
@echo off
|
||||
|
||||
echo Installing Maple DFU driver...
|
||||
"%~dp0wdi-simple" --vid 0x1EAF --pid 0x0003 --type 1 --name "Maple DFU" --dest "%~dp0maple-dfu"
|
||||
echo Installing MULTI-Module DFU Bootloader Driver...
|
||||
"%~dp0wdi-simple" --vid 0x1EAF --pid 0x0003 --type 2 --name "MULTI-Module DFU Bootloader" --dest "%~dp0MULTI-DFU-Bootloader" -b
|
||||
echo.
|
||||
|
||||
echo Installing Maple Serial driver...
|
||||
"%~dp0wdi-simple" --vid 0x1EAF --pid 0x0004 --type 3 --name "Maple Serial" --dest "%~dp0maple-serial"
|
||||
echo Installing MULTI-Module USB Serial Driver...
|
||||
"%~dp0wdi-simple" --vid 0x1EAF --pid 0x0004 --type 3 --name "MULTI-Module USB Serial" --dest "%~dp0MULTI-USB-Serial" -b
|
||||
echo.
|
||||
|
||||
pause
|
||||
|
||||
@@ -527,6 +527,28 @@
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi X-in-1 STM32 Boards",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.1.8",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.8.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.8.tar.gz",
|
||||
"checksum": "SHA-256:e9ed8055ebf72abf37e60e1b8d1c6ee5472132ea7c0a3c4a63fbb8442613e4c2",
|
||||
"size": "7481800",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (STM32F103C)"},
|
||||
{"name": "Multi 5-in-1 (Jumper T18 Internal)"}
|
||||
],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 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
601
Lua_scripts/DSM FwdPrg.lua
Normal 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 }
|
||||
171
Lua_scripts/Graupner HoTT.lua
Normal file
171
Lua_scripts/Graupner HoTT.lua
Normal file
@@ -0,0 +1,171 @@
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
|
||||
--###############################################################################
|
||||
-- Multi buffer for HoTT description
|
||||
-- To start operation:
|
||||
-- Write "HoTT" at address 0..3
|
||||
-- Write 0xFF at address 4 will request the buffer to be cleared
|
||||
-- Write 0x0F at address 5
|
||||
-- Read buffer from address 6 access the RX text for 168 bytes, 21 caracters
|
||||
-- by 8 lines
|
||||
-- Write at address 5 sends an order to the RX: 0xXF=start, 0xX7=prev page,
|
||||
-- 0xXE=next page, 0xX9=enter, 0xXD=next or 0xXB=prev with X being the sensor
|
||||
-- to request data from 8=RX only, 9=Vario, A=GPS, B=Cust, C=ESC, D=GAM, E=EAM
|
||||
-- Write at address 4 the value 0xFF will request the buffer to be cleared
|
||||
-- !! Before exiting the script must write 0 at address 0 for normal operation !!
|
||||
--###############################################################################
|
||||
|
||||
HoTT_Sensor = 0
|
||||
Timer_128 = 100
|
||||
|
||||
local function HoTT_Release()
|
||||
multiBuffer( 0, 0 )
|
||||
end
|
||||
|
||||
local function HoTT_Send(button)
|
||||
multiBuffer( 5, 0x80+(HoTT_Sensor*16) + button)
|
||||
end
|
||||
|
||||
local function HoTT_Sensor_Inc()
|
||||
local detected_sensors=multiBuffer( 4 )
|
||||
local a
|
||||
if detected_sensors ~= 0xFF then
|
||||
repeat
|
||||
HoTT_Sensor=(HoTT_Sensor+1)%7 -- Switch to next sensor
|
||||
if HoTT_Sensor ~= 0 then
|
||||
a = math.floor(detected_sensors/ (2^(HoTT_Sensor-1))) -- shift right
|
||||
end
|
||||
until HoTT_Sensor==0 or a % 2 == 1
|
||||
HoTT_Send( 0x0F )
|
||||
end
|
||||
end
|
||||
|
||||
local function HoTT_Draw_LCD()
|
||||
local i
|
||||
local value
|
||||
local line
|
||||
local result
|
||||
local offset=0
|
||||
|
||||
local sensor_name = { "", "+Vario", "+GPS", "+Cust", "+ESC", "+GAM", "+EAM" }
|
||||
|
||||
lcd.clear()
|
||||
|
||||
if LCD_W == 480 then
|
||||
--Draw title
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||
lcd.drawText(1, 5, "Graupner HoTT: config RX" .. sensor_name[HoTT_Sensor+1] .. " - Menu cycle Sensors", MENU_TITLE_COLOR)
|
||||
--Draw RX Menu
|
||||
if multiBuffer( 4 ) == 0xFF then
|
||||
lcd.drawText(10,50,"No HoTT telemetry...", BLINK)
|
||||
else
|
||||
for line = 0, 7, 1 do
|
||||
for i = 0, 21-1, 1 do
|
||||
value=multiBuffer( line*21+6+i )
|
||||
if value > 0x80 then
|
||||
value = value - 0x80
|
||||
lcd.drawText(10+i*16,32+20*line,string.char(value).." ",INVERS)
|
||||
else
|
||||
lcd.drawText(10+i*16,32+20*line,string.char(value))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
--Draw RX Menu on LCD_W=128
|
||||
if multiBuffer( 4 ) == 0xFF then
|
||||
lcd.drawText(2,17,"No HoTT telemetry...",SMLSIZE)
|
||||
else
|
||||
if Timer_128 ~= 0 then
|
||||
--Intro page
|
||||
Timer_128 = Timer_128 - 1
|
||||
lcd.drawScreenTitle("Graupner Hott",0,0)
|
||||
lcd.drawText(2,17,"Configuration of RX" .. sensor_name[HoTT_Sensor+1] ,SMLSIZE)
|
||||
lcd.drawText(2,37,"Press menu to cycle Sensors" ,SMLSIZE)
|
||||
else
|
||||
--Menu page
|
||||
for line = 0, 7, 1 do
|
||||
for i = 0, 21-1, 1 do
|
||||
value=multiBuffer( line*21+6+i )
|
||||
if value > 0x80 then
|
||||
value = value - 0x80
|
||||
lcd.drawText(2+i*6,1+8*line,string.char(value).." ",SMLSIZE+INVERS)
|
||||
else
|
||||
lcd.drawText(2+i*6,1+8*line,string.char(value),SMLSIZE)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function HoTT_Init()
|
||||
--Set protocol to talk to
|
||||
multiBuffer( 0, string.byte('H') )
|
||||
--test if value has been written
|
||||
if multiBuffer( 0 ) ~= string.byte('H') then
|
||||
error("Not enough memory!")
|
||||
return 2
|
||||
end
|
||||
multiBuffer( 1, string.byte('o') )
|
||||
multiBuffer( 2, string.byte('T') )
|
||||
multiBuffer( 3, string.byte('T') )
|
||||
--Request init of the RX buffer
|
||||
multiBuffer( 4, 0xFF )
|
||||
--Request RX to send the config menu
|
||||
HoTT_Send( 0x0F )
|
||||
HoTT_Sensor = 0;
|
||||
HoTT_Detected_Sensors=0;
|
||||
Timer_128 = 100
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function HoTT_Run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_EXIT then
|
||||
HoTT_Release()
|
||||
return 2
|
||||
else
|
||||
if event == EVT_VIRTUAL_PREV_PAGE then
|
||||
killEvents(event)
|
||||
HoTT_Send( 0x07 )
|
||||
elseif event == EVT_VIRTUAL_ENTER then
|
||||
HoTT_Send( 0x09 )
|
||||
elseif event == EVT_VIRTUAL_PREV then
|
||||
HoTT_Send( 0x0B )
|
||||
elseif event == EVT_VIRTUAL_NEXT then
|
||||
HoTT_Send( 0x0D )
|
||||
elseif event == EVT_VIRTUAL_NEXT_PAGE then
|
||||
HoTT_Send( 0x0E )
|
||||
elseif event == EVT_VIRTUAL_MENU then
|
||||
Timer_128 = 100
|
||||
HoTT_Sensor_Inc()
|
||||
else
|
||||
HoTT_Send( 0x0F )
|
||||
end
|
||||
HoTT_Draw_LCD()
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
return { init=HoTT_Init, run=HoTT_Run }
|
||||
178
Lua_scripts/MultiChan.txt
Normal file
178
Lua_scripts/MultiChan.txt
Normal file
@@ -0,0 +1,178 @@
|
||||
24,0,Assan,Std,0,CH5,CH6,CH7,CH8
|
||||
14,0,Bayang,Std,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,n-a,n-a,AnAux1,AnAux2
|
||||
14,1,Bayang,H8S3D,1,Flip,RTH,Pict,Video,HLess,Invert,Rates
|
||||
14,2,Bayang,X16_AH,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf
|
||||
14,3,Bayang,IRDRONE,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
|
||||
14,4,Bayang,DHD_D4,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
|
||||
14,5,Bayang,QX100,1,Flip,RTH,Pict,Video,HLess,Invert,Rates,TakeOf,EmStop
|
||||
59,0,BayangRX,RX,1,AnAux1,AnAux2,Flip,RTH,Pict,Video
|
||||
41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED
|
||||
42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED
|
||||
42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol
|
||||
34,0,Cabell,V3,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
34,1,Cabell,V3Telem,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
13,0,CG023,Std,1,Flip,Light,Pict,Video,HLess
|
||||
13,1,CG023,YD829,1,Flip,n-a,Pict,Video,HLess
|
||||
37,0,Corona,COR_V1,0,CH5,CH6,CH7,CH8
|
||||
37,1,Corona,COR_V2,0,CH5,CH6,CH7,CH8
|
||||
37,2,Corona,FD_V3,0,CH5,CH6,CH7,CH8
|
||||
12,0,CX10,Green,1,Flip,Rate
|
||||
12,1,CX10,Blue,1,Flip,Rate,Pict,Video
|
||||
12,2,CX10,DM007,1,Flip,Mode,Pict,Video,HLess
|
||||
12,4,CX10,JC3015_1,1,Flip,Mode,Pict,Video
|
||||
12,5,CX10,JC3015_2,1,Flip,Mode,LED,DFlip
|
||||
12,6,CX10,MK33041,1,Flip,Mode,Pict,Video,HLess,RTH
|
||||
7,0,Devo,8CH,0,CH5,CH6,CH7,CH8
|
||||
7,1,Devo,10CH,0,CH5,CH6,CH7,CH8,CH9,CH10
|
||||
7,2,Devo,12CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||
7,3,Devo,6CH,0,CH5,CH6
|
||||
7,4,Devo,7CH,0,CH5,CH6,CH7
|
||||
33,0,DM022,Std,1,Flip,LED,Cam1,Cam2,HLess,RTH,RLow
|
||||
6,0,DSM,2_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||
6,1,DSM,2_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||
6,2,DSM,X_22,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||
6,3,DSM,X_11,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||
6,4,DSM,AUTO,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,n-a,ThKill
|
||||
70,0,DSM_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||
45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH
|
||||
45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH
|
||||
45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH
|
||||
16,0,ESKY,Std,0,Gyro,Pitch
|
||||
16,1,ESKY,ET4,0,Gyro,Pitch
|
||||
35,0,ESKY150,4CH,0
|
||||
35,1,ESKY150,7CH,0,FMode,Aux6,Aux7
|
||||
69,0,ESKY150V2,Std,0,CH5_RA,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
1,0,Flysky,Flysky,0,CH5,CH6,CH7,CH8
|
||||
1,1,Flysky,V9x9,1,Flip,Light,Pict,Video
|
||||
1,2,Flysky,V6x6,1,Flip,Light,Pict,Video,HLess,RTH,XCAL,YCAL
|
||||
1,3,Flysky,V912,1,BtmBtn,TopBtn
|
||||
1,4,Flysky,CX20,0,CH5,CH6,CH7
|
||||
28,0,Flysky_AFHDS2A,PWM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
28,1,Flysky_AFHDS2A,PPM_IBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
28,2,Flysky_AFHDS2A,PWM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
28,3,Flysky_AFHDS2A,PPM_SBUS,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
28,4,Flysky_AFHDS2A,PWM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
28,5,Flysky_AFHDS2A,PPM_IB16,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
56,0,Flysky2A_RX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
53,0,Height,5ch,0,Gear
|
||||
53,1,Height,8ch,0,Gear,Gyro,Flap,Light
|
||||
25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8
|
||||
3,0,FrSkyD,D8,0,CH5,CH6,CH7,CH8
|
||||
3,0,FrSkyD,D8Cloned,0,CH5,CH6,CH7,CH8
|
||||
67,0,FrSkyL,LR12,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||
67,1,FrSkyL,LR12_6CH,0,CH5,CH6
|
||||
15,0,FrSkyX,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
15,1,FrSkyX,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
|
||||
15,2,FrSkyX,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
15,3,FrSkyX,D16_8CH_LBT,0,CH5,CH6,CH7,CH8
|
||||
15,4,FrSkyX,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
15,5,FrSkyX,D16Cloned_8CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
64,0,FrSkyX2,D16_FCC,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
64,1,FrSkyX2,D16_8CH_FCC,0,CH5,CH6,CH7,CH8
|
||||
64,2,FrSkyX2,D16_LBT,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
64,3,FrSkyX2,D16_8CH_LBT,1,CH5,CH6,CH7,CH8
|
||||
64,4,FrSkyX2,D16Cloned,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
64,5,FrSkyX2,D16Cloned_8CH,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
65,0,FrSkyR9,R9_915,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
65,1,FrSkyR9,R9_868,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
65,2,FrSkyR9,R9_915_8CH,0,CH5,CH6,CH7,CH8
|
||||
65,3,FrSkyR9,R9_968_8CH,0,CH5,CH6,CH7,CH8
|
||||
55,0,FrSkyRX,RX,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
55,1,FrSkyRX,CloneTX,0
|
||||
58,0,FX816,P38,1
|
||||
20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
|
||||
20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
|
||||
23,0,FY326,FY326,1,Flip,RTH,HLess,Expert
|
||||
47,0,GD00x,V1,1,Trim,LED,Rate
|
||||
47,1,GD00x,V2,1,Trim,LED,Rate
|
||||
32,0,GW008,FY326,1,Flip
|
||||
36,0,H8_3D,Std,1,Flip,Light,Pict,Video,RTH,FlMode,Cal1
|
||||
36,1,H8_3D,H20H,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||
36,2,H8_3D,H20,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||
36,3,H8_3D,H30,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||
4,0,Hisky,Std,0,Gear,Pitch,Gyro,CH8
|
||||
4,1,Hisky,HK310,0,Aux
|
||||
39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9
|
||||
39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9
|
||||
39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9
|
||||
26,0,Hontai,Std,1,Flip,LED,Pict,Video,HLess,RTH,Calib
|
||||
26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||
26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||
26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||
57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||
57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||
2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess
|
||||
2,1,Hubsan,H301,0,RTH,Light,Stab,Video
|
||||
2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes
|
||||
22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||
71,0,JJRC345,JJRC345,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
|
||||
71,1,JJRC345,SkyTmblr,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
|
||||
49,0,KF606,Std,1,Trim
|
||||
9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
|
||||
9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
|
||||
73,0,Kyosho,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
18,0,MJXQ,WHL08,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,1,MJXQ,X600,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,2,MJXQ,X800,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,3,MJXQ,H26D,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,4,MJXQ,E010,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,5,MJXQ,H26WH,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,6,MJXQ,Phoenix,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
17,0,MT99XX,Std,1,Flip,LED,Pict,Video,HLess
|
||||
17,1,MT99XX,H7,1,Flip,LED,Pict,Video,HLess
|
||||
17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess
|
||||
17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess
|
||||
17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess
|
||||
44,0,NCC1701,Std,1,Warp
|
||||
77,0,OMP,M2,0,THold,IdleUp,6G_3D
|
||||
60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
|
||||
60,1,Pelikan,LITE_V4,0,CH5,CH6,CH7,CH8
|
||||
51,0,Potensic,A20,1,TakLan,Emerg,Mode,HLess
|
||||
66,0,Propel,74-Z,1,LEDs,RollCW,RolCCW,Fire,Weapon,Calib,AltHol,TakeOf,Land,Train
|
||||
29,0,Q2x2,Q222,1,Flip,LED,Mod2,Mod1,HLess,RTH,XCal,YCal
|
||||
29,1,Q2x2,Q242,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
|
||||
29,2,Q2x2,Q282,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
|
||||
31,0,Q303,Q303,1,AltHol,Flip,Pict,Video,HLess,RTH,Gimbal
|
||||
31,1,Q303,C35,1,Arm,VTX,Pict,Video,n-a,RTH,Gimbal
|
||||
31,2,Q303,CX10D,1,Arm,Flip
|
||||
31,3,Q303,CX10WD,1,Arm,Flip
|
||||
72,0,Q90C,Std,0,FMode,VTX+
|
||||
74,0,RadioLink,Surface,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
|
||||
74,1,RadioLink,Air,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
|
||||
76,0,Realacc,R11,1,Flip,Light,Calib,HLess,RTH,UNK
|
||||
50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
||||
50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
||||
21,0,Futaba,SFHSS,0,CH5,CH6,CH7,CH8
|
||||
19,0,Shenqi,Cycle,1
|
||||
68,0,Skyartec,Std,0,CH5,CH6,CH7
|
||||
11,0,SLT,V1,0,Gear,Pitch
|
||||
11,1,SLT,V2,0,CH5,CH6,CH7,CH8
|
||||
11,2,SLT,Q100,0,Rates,n-a,CH7,CH8,Mode,Flip,n-a,n-a,Calib
|
||||
11,3,SLT,Q200,0,Rates,n-a,CH7,CH8,Mode,VidOn,VidOff,Calib
|
||||
11,4,SLT,MR100,0,Rates,n-a,CH7,CH8,Mode,Flip,Video,Pict
|
||||
10,0,Symax,Std,1,Flip,Rates,Pict,Video,HLess
|
||||
10,1,Symax,X5C,1,Flip,Rates,Pict,Video,HLess
|
||||
61,0,Tiger,Std,1,Flip,Light
|
||||
43,0,Traxxas,6519,0
|
||||
5,0,V2x2,Std,1,Flip,Light,Pict,Video,HLess,CalX,CalY
|
||||
5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD
|
||||
48,0,V761,3CH,0,Gyro,Calib,Flip,RtnAct,Rtn
|
||||
48,1,V761,4CH,0,Gyro,Calib,Flip,RtnAct,Rtn
|
||||
46,0,V911s,V911s,1,Calib
|
||||
46,1,V911s,E119,1,Calib
|
||||
22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
|
||||
30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8
|
||||
30,1,WK2x01,WK2401,0
|
||||
30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro
|
||||
30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro
|
||||
30,4,WK2x01,W6HEL,0,Gear,Col,Gyro
|
||||
30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro
|
||||
62,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
|
||||
62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
|
||||
8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess
|
||||
8,1,YD717,SkyWlkr,1,Flip,Light,Pict,Video,HLess
|
||||
8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess
|
||||
8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess
|
||||
8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess
|
||||
52,0,ZSX,280,1,Light
|
||||
78,0,M-Link,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
311
Lua_scripts/MultiChannelsUpdater.lua
Normal file
311
Lua_scripts/MultiChannelsUpdater.lua
Normal file
@@ -0,0 +1,311 @@
|
||||
|
||||
local toolName = "TNS|Multi chan namer|TNE"
|
||||
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
local protocol_name = ""
|
||||
local sub_protocol_name = ""
|
||||
local bind_ch = 0
|
||||
local module_conf = {}
|
||||
local module_pos = "Internal"
|
||||
local file_ok = 0
|
||||
local done = 0
|
||||
local protocol = 0
|
||||
local sub_protocol = 0
|
||||
local f_seek = 0
|
||||
local channel_names={}
|
||||
local num_search = "Searching"
|
||||
|
||||
local function drawScreenTitle(title)
|
||||
if LCD_W == 480 then
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||
lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
|
||||
else
|
||||
lcd.drawScreenTitle(title, 0, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function bitand(a, b)
|
||||
local result = 0
|
||||
local bitval = 1
|
||||
while a > 0 and b > 0 do
|
||||
if a % 2 == 1 and b % 2 == 1 then -- test the rightmost bits
|
||||
result = result + bitval -- set the current bit
|
||||
end
|
||||
bitval = bitval * 2 -- shift left
|
||||
a = math.floor(a/2) -- shift right
|
||||
b = math.floor(b/2)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local function Multi_Draw_LCD(event)
|
||||
local line = 0
|
||||
|
||||
lcd.clear()
|
||||
drawScreenTitle("Multi channels namer")
|
||||
|
||||
--Display settings
|
||||
local lcd_opt = 0
|
||||
if LCD_W == 480 then
|
||||
x_pos = 10
|
||||
y_pos = 32
|
||||
y_inc = 20
|
||||
else
|
||||
x_pos = 0
|
||||
y_pos = 9
|
||||
y_inc = 8
|
||||
lcd_opt = SMLSIZE
|
||||
end
|
||||
|
||||
--Multi Module detection
|
||||
if module_conf["Type"] ~= 6 then
|
||||
if LCD_W == 480 then
|
||||
lcd.drawText(10,50,"No Multi module configured...", BLINK)
|
||||
else
|
||||
--Draw on LCD_W=128
|
||||
lcd.drawText(2,17,"No Multi module configured...",SMLSIZE)
|
||||
end
|
||||
return
|
||||
else
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,module_pos .. " Multi detected.", lcd_opt)
|
||||
line = line + 1
|
||||
end
|
||||
|
||||
--Channel order
|
||||
if (ch_order == -1) then
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Channels order can't be read from Multi...", lcd_opt)
|
||||
line = line + 1
|
||||
end
|
||||
|
||||
--Can't open file MultiChan.txt
|
||||
if file_ok == 0 then
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Can't read MultiChan.txt file...", lcd_opt)
|
||||
return
|
||||
end
|
||||
|
||||
if ( protocol_name == "" or sub_protocol_name == "" ) and f_seek ~=-1 then
|
||||
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
|
||||
if f == nil then return end
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,num_search, lcd_opt)
|
||||
num_search = num_search .. "."
|
||||
if #num_search > 15 then
|
||||
num_search = string.sub(num_search,1,9)
|
||||
end
|
||||
local proto = 0
|
||||
local sub_proto = 0
|
||||
local proto_name = ""
|
||||
local sub_proto_name = ""
|
||||
local channels = ""
|
||||
local nbr_try = 0
|
||||
local nbr_car = 0
|
||||
repeat
|
||||
io.seek(f, f_seek)
|
||||
local data = io.read(f, 100) -- read 100 characters
|
||||
if #data ==0 then
|
||||
f_seek = -1 -- end of file
|
||||
break
|
||||
end
|
||||
proto, sub_proto, proto_name, sub_proto_name, bind_ch, channels = string.match(data,'(%d+),(%d),([%w-_ ]+),([%w-_ ]+),(%d)(.+)')
|
||||
if proto ~= nil and sub_proto ~= nil and protocol_name ~= nil and sub_protocol_name ~= nil and bind_ch ~= nil then
|
||||
if tonumber(proto) == protocol and tonumber(sub_proto) == sub_protocol then
|
||||
protocol_name = proto_name
|
||||
sub_protocol_name = sub_proto_name
|
||||
bind_ch = tonumber(bind_ch)
|
||||
if channels ~= nil then
|
||||
--extract channel names
|
||||
nbr_car = string.find(channels, "\r")
|
||||
if nbr_car == nil then nbr_car = string.find(channels, "\n") end
|
||||
if nbr_car ~= nil then
|
||||
channels = string.sub(channels,1,nbr_car-1)
|
||||
end
|
||||
local i = 5
|
||||
for k in string.gmatch(channels, ",([%w-_ ]+)") do
|
||||
channel_names[i] = k
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
f_seek = -1 -- protocol found
|
||||
break
|
||||
end
|
||||
end
|
||||
if f_seek ~= -1 then
|
||||
nbr_car = string.find(data, "\n")
|
||||
if nbr_car == nil then nbr_car = string.find(data, "\r") end
|
||||
if nbr_car == nil then
|
||||
f_seek = -1 -- end of file
|
||||
break
|
||||
end
|
||||
f_seek = f_seek + nbr_car -- seek to next line
|
||||
nbr_try = nbr_try + 1
|
||||
end
|
||||
until nbr_try > 20 or f_seek == -1
|
||||
io.close(f)
|
||||
end
|
||||
|
||||
if f_seek ~= -1 then
|
||||
return -- continue searching...
|
||||
end
|
||||
|
||||
--Protocol & Sub_protocol
|
||||
if protocol_name == "" or sub_protocol_name == "" then
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Unknown protocol "..tostring(protocol).."/"..tostring(sub_protocol).." ...", lcd_opt)
|
||||
return
|
||||
elseif LCD_W > 128 then
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name .. " / SubProtocol: " .. sub_protocol_name, lcd_opt)
|
||||
line = line + 1
|
||||
else
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Protocol: " .. protocol_name, lcd_opt)
|
||||
line = line + 1
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"SubProtocol: " .. sub_protocol_name, lcd_opt)
|
||||
line = line + 1
|
||||
end
|
||||
|
||||
text1=""
|
||||
text2=""
|
||||
for i,v in ipairs(channel_names) do
|
||||
if i<=8 then
|
||||
if i==1 then
|
||||
text1 = v
|
||||
else
|
||||
text1=text1 .. "," .. v
|
||||
end
|
||||
else
|
||||
if i==9 then
|
||||
text2 = v
|
||||
else
|
||||
text2=text2 .. "," .. v
|
||||
end
|
||||
end
|
||||
end
|
||||
if LCD_W > 128 then
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Channels: " .. text1, lcd_opt)
|
||||
line = line + 1
|
||||
if text2 ~= "" then
|
||||
lcd.drawText(x_pos*9, y_pos+y_inc*line,text2, lcd_opt)
|
||||
line = line + 1
|
||||
end
|
||||
end
|
||||
|
||||
if event ~= EVT_VIRTUAL_ENTER and done == 0 then
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"<ENT> Save", lcd_opt + INVERS + BLINK)
|
||||
return
|
||||
end
|
||||
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Setting channel names.", lcd_opt)
|
||||
line = line + 1
|
||||
local output, nbr
|
||||
if done == 0 then
|
||||
for i,v in ipairs(channel_names) do
|
||||
output = model.getOutput(i-1)
|
||||
output["name"] = v
|
||||
model.setOutput(i-1,output)
|
||||
nbr = i
|
||||
end
|
||||
for i = nbr, 15 do
|
||||
output = model.getOutput(i)
|
||||
output["name"] = "n-a"
|
||||
model.setOutput(i,output)
|
||||
end
|
||||
if bind_ch == 1 then
|
||||
output = model.getOutput(15)
|
||||
output["name"] = "BindCH"
|
||||
model.setOutput(15,output)
|
||||
end
|
||||
done = 1
|
||||
end
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line,"Done!", lcd_opt)
|
||||
line = line + 1
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function Multi_Init()
|
||||
module_conf = model.getModule(0)
|
||||
if module_conf["Type"] ~= 6 then
|
||||
module_pos = "External"
|
||||
module_conf = model.getModule(1)
|
||||
if module_conf["Type"] ~= 6 then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
protocol = module_conf["protocol"]
|
||||
sub_protocol = module_conf["subProtocol"]
|
||||
|
||||
--Exceptions on first 4 channels...
|
||||
local stick_names = { "Rud", "Ele", "Thr", "Ail" }
|
||||
if ( protocol == 4 and sub_protocol == 1 ) or protocol == 19 or protocol == 52 then -- Hisky/HK310, Shenqi, ZSX
|
||||
stick_names[2] = "n-a"
|
||||
stick_names[4] = "n-a"
|
||||
elseif protocol == 43 then -- Traxxas
|
||||
stick_names[2] = "Aux4"
|
||||
stick_names[4] = "Aux3"
|
||||
elseif ( protocol == 48 and sub_protocol == 0 ) then -- V761 3CH
|
||||
stick_names[4] = "n-a"
|
||||
elseif protocol == 47 or protocol == 49 or protocol == 58 then -- GD00x, KF606, FX816
|
||||
stick_names[1] = "n-a"
|
||||
stick_names[2] = "n-a"
|
||||
end
|
||||
|
||||
--Determine fist 4 channels order
|
||||
local ch_order=module_conf["channelsOrder"]
|
||||
if (ch_order == -1) then
|
||||
channel_names[1] = stick_names[defaultChannel(0)+1]
|
||||
channel_names[2] = stick_names[defaultChannel(1)+1]
|
||||
channel_names[3] = stick_names[defaultChannel(2)+1]
|
||||
channel_names[4] = stick_names[defaultChannel(3)+1]
|
||||
else
|
||||
channel_names[bitand(ch_order,3)+1] = stick_names[4]
|
||||
ch_order = math.floor(ch_order/4)
|
||||
channel_names[bitand(ch_order,3)+1] = stick_names[2]
|
||||
ch_order = math.floor(ch_order/4)
|
||||
channel_names[bitand(ch_order,3)+1] = stick_names[3]
|
||||
ch_order = math.floor(ch_order/4)
|
||||
channel_names[bitand(ch_order,3)+1] = stick_names[1]
|
||||
end
|
||||
|
||||
--Exceptions on first 4 channels...
|
||||
if ( protocol == 73 or (protocol == 74 and sub_protocol == 0) ) then -- Kyosho or RadioLink Surface
|
||||
channel_names[1] = "ST"
|
||||
channel_names[2] = "THR"
|
||||
channel_names[3] = "CH3"
|
||||
channel_names[4] = "CH4"
|
||||
end
|
||||
|
||||
--Check MultiChan.txt
|
||||
local f = io.open("/SCRIPTS/TOOLS/MultiChan.txt", "r")
|
||||
if f == nil then return end
|
||||
file_ok = 1
|
||||
io.close(f)
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function Multi_Run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
else
|
||||
Multi_Draw_LCD(event)
|
||||
if event == EVT_VIRTUAL_EXIT then
|
||||
return 2
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
return { init=Multi_Init, run=Multi_Run }
|
||||
44
Lua_scripts/README.md
Normal file
44
Lua_scripts/README.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Multiprotocol TX Module OpenTX LUA scripts
|
||||
<img align="right" width=300 src="../docs/images/multi.png" />
|
||||
|
||||
If you like this project and want to support further development please consider making a [donation](../docs/Donations.md).
|
||||
|
||||
<table cellspacing=0>
|
||||
<tr>
|
||||
<td align=center width=200><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=VF2K9T23DRY56&lc=US&item_name=DIY%20Multiprotocol¤cy_code=EUR&amount=5&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted"><img src="../docs/images/donate_button.png" border="0" name="submit" title="PayPal - Donate €5" alt="Donate €5"/></a><br><b>€5</b></td>
|
||||
<td align=center width=200><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=VF2K9T23DRY56&lc=US&item_name=DIY%20Multiprotocol¤cy_code=EUR&amount=10&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted"><img src="../docs/images/donate_button.png" border="0" name="submit" title="PayPal - Donate €10" alt="Donate €10"/></a><br><b>€10</b></td>
|
||||
<td align=center width=200><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=VF2K9T23DRY56&lc=US&item_name=DIY%20Multiprotocol¤cy_code=EUR&amount=15&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted"><img src="../docs/images/donate_button.png" border="0" name="submit" title="PayPal - Donate €15" alt="Donate €10"/></a><br><b>€15</b></td>
|
||||
<td align=center width=200><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=VF2K9T23DRY56&lc=US&item_name=DIY%20Multiprotocol¤cy_code=EUR&amount=25&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted"><img src="../docs/images/donate_button.png" border="0" name="submit" title="PayPal - Donate €25" alt="Donate €25"/></a><br><b>€25</b></td>
|
||||
<td align=center width=200><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=VF2K9T23DRY56&lc=US&item_name=DIY%20Multiprotocol¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted"><img src="../docs/images/donate_button.png" border="0" name="submit" title="PayPal - Donate" alt="Donate"/></a><br><b>Other</b></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## MultiChannelsUpdater.lua
|
||||
|
||||
Automatically name the channels based on the loaded Multi protocol and sub protocol including the module channel order convention.
|
||||
|
||||
Need OpenTX 2.3.9 or above. Located on the radio SD card under \SCRIPTS\TOOLS. This script needs MultiChan.txt to be present in the same folder.
|
||||
|
||||
[](https://www.youtube.com/watch?v=L58ayXuewyA)
|
||||
|
||||
## 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.
|
||||
|
||||
[](https://www.youtube.com/watch?v=sjIaDw5j9nE)
|
||||
|
||||
## Graupner HoTT.ua
|
||||
|
||||
Enable text configuration of the HoTT RX and sensors: Vario, GPS, ESC, GAM and EAM.
|
||||
|
||||
Need OpenTX 2.3.9 or above. Located on the radio SD card under \SCRIPTS\TOOLS.
|
||||
|
||||
Notes:
|
||||
- Menu/MDL/Model is used to cycle through the detected sensors.
|
||||
- It's normal to lose the telemetry feed while using the text mode configuration. Telemetry will resume properly if the script is exited by doing a short press on the exit button.
|
||||
|
||||
[](https://www.youtube.com/watch?v=81wd8NlF3Qw)
|
||||
@@ -27,7 +27,7 @@ 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_FLYSKY || protocol==PROTO_KYOSHO))
|
||||
{
|
||||
A7105_Strobe(A7105_STANDBY); //Force standby mode, ie cancel any TX or RX...
|
||||
A7105_SetTxRxMode(TX_EN); //Switch to PA
|
||||
@@ -192,9 +192,19 @@ void A7105_AdjustLOBaseFreq(uint8_t cmd)
|
||||
offset=(int16_t)FORCE_FLYSKY_TUNING;
|
||||
#endif
|
||||
break;
|
||||
case PROTO_FLYZONE:
|
||||
#ifdef FORCE_FLYZONE_TUNING
|
||||
offset=(int16_t)FORCE_FLYZONE_TUNING;
|
||||
case PROTO_HEIGHT:
|
||||
#ifdef FORCE_HEIGHT_TUNING
|
||||
offset=(int16_t)FORCE_HEIGHT_TUNING;
|
||||
#endif
|
||||
break;
|
||||
case PROTO_PELIKAN:
|
||||
#ifdef FORCE_PELIKAN_TUNING
|
||||
offset=(int16_t)FORCE_PELIKAN_TUNING;
|
||||
#endif
|
||||
break;
|
||||
case PROTO_KYOSHO:
|
||||
#ifdef FORCE_KYOSHO_TUNING
|
||||
offset=(int16_t)FORCE_KYOSHO_TUNING;
|
||||
#endif
|
||||
break;
|
||||
case PROTO_AFHDS2A:
|
||||
@@ -277,8 +287,8 @@ const uint8_t PROGMEM FLYSKY_A7105_regs[] = {
|
||||
0x01, 0x0f // 30 - 31
|
||||
};
|
||||
#endif
|
||||
#ifdef FLYZONE_A7105_INO
|
||||
const uint8_t PROGMEM FLYZONE_A7105_regs[] = {
|
||||
#ifdef HEIGHT_A7105_INO
|
||||
const uint8_t PROGMEM HEIGHT_A7105_regs[] = {
|
||||
0xff, 0x42, 0x00, 0x07, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x01, 0x50, // 00 - 0f
|
||||
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x1f, // 10 - 1f
|
||||
0x12, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3a, 0x00, 0x3f, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f
|
||||
@@ -293,6 +303,28 @@ const uint8_t PROGMEM HUBSAN_A7105_regs[] = {
|
||||
0xFF, 0xFF // 30 - 31
|
||||
};
|
||||
#endif
|
||||
#ifdef PELIKAN_A7105_INO
|
||||
const uint8_t PROGMEM PELIKAN_A7105_regs[] = {
|
||||
0xff, 0x42, 0x00, 0x0F, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x01, 0x50, // 00 - 0f
|
||||
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x07, // 10 - 1f
|
||||
0x16, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3b, 0x00, 0x1f, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f
|
||||
0x01, 0x0f // 30 - 31
|
||||
};
|
||||
#endif
|
||||
#ifdef KYOSHO_A7105_INO
|
||||
const uint8_t PROGMEM KYOSHO_A7105_regs[] = {
|
||||
0xff, 0x42, 0xff, 0x25, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50, // 00 - 0f
|
||||
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x40, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0x03, 0x1f, // 10 - 1f
|
||||
0x1e, 0x00, 0x00, 0xff, 0x00, 0x00, 0x23, 0x70, 0x1F, 0x47, 0x80, 0x57, 0x01, 0x45, 0x19, 0x00, // 20 - 2f
|
||||
0x01, 0x0f // 30 - 31
|
||||
};
|
||||
const uint8_t PROGMEM KYOSHO_HYPE_A7105_regs[] = {
|
||||
0xff, 0x42, 0x00, 0x10, 0xC0, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0x05, 0x01, 0x04, // 00 - 0f
|
||||
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x96, 0xc2, 0x1f, // 10 - 1f
|
||||
0x12, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3a, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f
|
||||
0x01, 0x0f // 30 - 31
|
||||
};
|
||||
#endif
|
||||
|
||||
#define ID_NORMAL 0x55201041
|
||||
#define ID_PLUS 0xAA201041
|
||||
@@ -301,14 +333,22 @@ void A7105_Init(void)
|
||||
uint8_t *A7105_Regs=0;
|
||||
uint8_t vco_calibration0, vco_calibration1;
|
||||
|
||||
#ifdef FLYZONE_A7105_INO
|
||||
if(protocol==PROTO_FLYZONE)
|
||||
#ifdef HEIGHT_A7105_INO
|
||||
if(protocol==PROTO_HEIGHT)
|
||||
{
|
||||
A7105_Regs=(uint8_t*)FLYZONE_A7105_regs;
|
||||
A7105_Regs=(uint8_t*)HEIGHT_A7105_regs;
|
||||
A7105_WriteID(0x25A53C45);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef PELIKAN_A7105_INO
|
||||
if(protocol==PROTO_PELIKAN)
|
||||
{
|
||||
A7105_Regs=(uint8_t*)PELIKAN_A7105_regs;
|
||||
A7105_WriteID(0x06230623);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef BUGS_A7105_INO
|
||||
if(protocol==PROTO_BUGS)
|
||||
A7105_Regs=(uint8_t*)BUGS_A7105_regs;
|
||||
@@ -327,13 +367,20 @@ void A7105_Init(void)
|
||||
#ifdef FLYSKY_A7105_INO
|
||||
if(protocol==PROTO_FLYSKY)
|
||||
A7105_Regs=(uint8_t*)FLYSKY_A7105_regs;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#if defined(AFHDS2A_A7105_INO) || defined(AFHDS2A_RX_A7105_INO)
|
||||
if(protocol==PROTO_AFHDS2A)
|
||||
A7105_Regs=(uint8_t*)AFHDS2A_A7105_regs;
|
||||
#endif
|
||||
#ifdef KYOSHO_A7105_INO
|
||||
if(protocol==PROTO_KYOSHO)
|
||||
{
|
||||
if(sub_protocol==KYOSHO_FHSS)
|
||||
A7105_Regs=(uint8_t*)KYOSHO_A7105_regs;
|
||||
else
|
||||
A7105_Regs=(uint8_t*)KYOSHO_HYPE_A7105_regs;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 0x32; i++)
|
||||
@@ -347,11 +394,28 @@ void A7105_Init(void)
|
||||
if(i==0x20) val=0x1E;
|
||||
}
|
||||
#endif
|
||||
#ifdef HEIGHT_A7105_INO
|
||||
if(protocol==PROTO_HEIGHT && sub_protocol==HEIGHT_8CH)
|
||||
if(i==0x03) val=0x0A;
|
||||
#endif
|
||||
if( val != 0xFF)
|
||||
A7105_WriteReg(i, val);
|
||||
}
|
||||
A7105_Strobe(A7105_STANDBY);
|
||||
|
||||
if(protocol==PROTO_KYOSHO && sub_protocol==KYOSHO_FHSS)
|
||||
{//strange calibration...
|
||||
//IF Filter Bank Calibration
|
||||
A7105_WriteReg(A7105_02_CALC,0x0F);
|
||||
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
|
||||
// A7105_ReadReg(A7105_22_IF_CALIB_I);
|
||||
// A7105_ReadReg(A7105_24_VCO_CURCAL);
|
||||
// A7105_ReadReg(25_VCO_SBCAL_I);
|
||||
// A7105_ReadReg(1A_RX_GAIN_II);
|
||||
// A7105_ReadReg(1B_RX_GAIN_III);
|
||||
}
|
||||
else
|
||||
{
|
||||
//IF Filter Bank Calibration
|
||||
A7105_WriteReg(A7105_02_CALC,1);
|
||||
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
|
||||
@@ -388,20 +452,26 @@ void A7105_Init(void)
|
||||
case PROTO_FLYSKY:
|
||||
vco_calibration1=0x08;
|
||||
break;
|
||||
case PROTO_FLYZONE:
|
||||
case PROTO_HEIGHT:
|
||||
vco_calibration1=0x02;
|
||||
break;
|
||||
case PROTO_PELIKAN:
|
||||
case PROTO_KYOSHO: //sub_protocol Hype
|
||||
vco_calibration1=0x0C;
|
||||
break;
|
||||
default:
|
||||
vco_calibration1=0x0A;
|
||||
break;
|
||||
}
|
||||
A7105_WriteReg(A7105_25_VCO_SBCAL_I,vco_calibration1); //Reset VCO Band calibration
|
||||
}
|
||||
|
||||
}
|
||||
A7105_SetTxRxMode(TX_EN);
|
||||
A7105_SetPower();
|
||||
|
||||
#ifdef USE_A7105_CH15_TUNING
|
||||
A7105_AdjustLOBaseFreq(0);
|
||||
#endif
|
||||
|
||||
A7105_Strobe(A7105_STANDBY);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ static void __attribute__((unused)) AFHDS2A_Rx_build_telemetry_packet()
|
||||
packet_in[idx++] = 14; // number of channels in packet
|
||||
// pack channels
|
||||
for (uint8_t i = 0; i < 14; i++) {
|
||||
uint32_t val = packet[9+i*2] | (packet[10+i*2] << 8);
|
||||
uint32_t val = packet[9+i*2] | ((packet[10+i*2] << 8)&0x0F);
|
||||
if (val < 860)
|
||||
val = 860;
|
||||
// convert ppm (860-2140) to Multi (0-2047)
|
||||
@@ -90,8 +90,6 @@ uint16_t initAFHDS2A_Rx()
|
||||
|
||||
uint16_t AFHDS2A_Rx_callback()
|
||||
{
|
||||
static uint32_t pps_timer = 0;
|
||||
static uint16_t pps_counter = 0;
|
||||
static int8_t read_retry;
|
||||
int16_t temp;
|
||||
uint8_t i;
|
||||
@@ -106,6 +104,7 @@ 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()) {
|
||||
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
|
||||
if ((packet[0] == 0xbb && packet[9] == 0x01) || (packet[0] == 0xbc && packet[9] <= 0x02)) {
|
||||
@@ -120,6 +119,7 @@ uint16_t AFHDS2A_Rx_callback()
|
||||
return 10000;
|
||||
|
||||
case AFHDS2A_RX_BIND2:
|
||||
if(IS_BIND_DONE) return initAFHDS2A_Rx(); // Abort bind
|
||||
// got 2nd bind packet from tx ?
|
||||
if (AFHDS2A_Rx_data_ready()) {
|
||||
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
|
||||
@@ -145,6 +145,7 @@ uint16_t AFHDS2A_Rx_callback()
|
||||
packet[9] = 0x01;
|
||||
packet[10] = 0x00;
|
||||
memset(&packet[11], 0xFF, 26);
|
||||
A7105_SetTxRxMode(TX_EN);
|
||||
A7105_WriteData(AFHDS2A_RX_RXPACKET_SIZE, packet_count++ & 1 ? 0x0D : 0x8C);
|
||||
phase |= AFHDS2A_RX_WAIT_WRITE;
|
||||
return 1700;
|
||||
@@ -155,6 +156,7 @@ uint16_t AFHDS2A_Rx_callback()
|
||||
while (micros() - pps_timer < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
|
||||
if (!(A7105_ReadReg(A7105_00_MODE) & 0x01))
|
||||
break;
|
||||
A7105_SetTxRxMode(RX_EN);
|
||||
A7105_Strobe(A7105_RX);
|
||||
phase &= ~AFHDS2A_RX_WAIT_WRITE;
|
||||
return 10000;
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
#define AFHDS2A_RXPACKET_SIZE 37
|
||||
#define AFHDS2A_NUMFREQ 16
|
||||
|
||||
#if not defined TELEMETRY
|
||||
uint8_t RX_LQI=0;
|
||||
#endif
|
||||
|
||||
enum{
|
||||
AFHDS2A_PACKET_STICKS,
|
||||
AFHDS2A_PACKET_SETTINGS,
|
||||
@@ -65,7 +69,6 @@ static void AFHDS2A_calc_channels()
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(AFHDS2A_FW_TELEMETRY) || defined(AFHDS2A_HUB_TELEMETRY)
|
||||
// telemetry sensors ID
|
||||
enum{
|
||||
AFHDS2A_SENSOR_RX_VOLTAGE = 0x00,
|
||||
@@ -76,10 +79,9 @@ enum{
|
||||
AFHDS2A_SENSOR_A3_VOLTAGE = 0x03,
|
||||
};
|
||||
|
||||
#if defined(AFHDS2A_FW_TELEMETRY) || defined(AFHDS2A_HUB_TELEMETRY)
|
||||
static void AFHDS2A_update_telemetry()
|
||||
{
|
||||
if(packet[0]==0xAA && packet[9]==0xFD)
|
||||
return; // ignore packets which contain the RX configuration: FD FF 32 00 01 00 FF FF FF 05 DC 05 DE FA FF FF FF FF FF FF FF FF FF FF FF FF FF FF
|
||||
// Read TX RSSI
|
||||
int16_t temp=256-(A7105_ReadReg(A7105_1D_RSSI_THOLD)*8)/5; // value from A7105 is between 8 for maximum signal strength to 160 or less
|
||||
if(temp<0) temp=0;
|
||||
@@ -183,33 +185,60 @@ static void AFHDS2A_build_packet(uint8_t type)
|
||||
{
|
||||
case AFHDS2A_PACKET_STICKS:
|
||||
packet[0] = 0x58;
|
||||
for(uint8_t ch=0; ch<14; ch++)
|
||||
//16 channels + RX_LQI on channel 17
|
||||
for(uint8_t ch=0; ch<num_ch; ch++)
|
||||
{
|
||||
uint16_t channelMicros = convert_channel_ppm(CH_AETR[ch]);
|
||||
packet[9 + ch*2] = channelMicros&0xFF;
|
||||
packet[10 + ch*2] = (channelMicros>>8)&0xFF;
|
||||
}
|
||||
if(ch == 16 // CH17=RX_LQI
|
||||
#ifdef AFHDS2A_LQI_CH
|
||||
// override channel with LQI
|
||||
val = 2000 - 10*RX_LQI;
|
||||
packet[9+((AFHDS2A_LQI_CH-1)*2)] = val & 0xff;
|
||||
packet[10+((AFHDS2A_LQI_CH-1)*2)] = (val >> 8) & 0xff;
|
||||
|| ch == (AFHDS2A_LQI_CH-1) // override channel with LQI
|
||||
#endif
|
||||
)
|
||||
val = 2000 - 10*RX_LQI;
|
||||
else
|
||||
val = convert_channel_ppm(CH_AETR[ch]);
|
||||
if(ch<14)
|
||||
{
|
||||
packet[9 + ch*2] = val;
|
||||
packet[10 + ch*2] = (val>>8)&0x0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[10 + (ch-14)*6] |= (val)<<4;
|
||||
packet[12 + (ch-14)*6] |= (val)&0xF0;
|
||||
packet[14 + (ch-14)*6] |= (val>>4)&0xF0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AFHDS2A_PACKET_FAILSAFE:
|
||||
packet[0] = 0x56;
|
||||
for(uint8_t ch=0; ch<14; ch++)
|
||||
for(uint8_t ch=0; ch<num_ch; ch++)
|
||||
{
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
uint16_t failsafeMicros = Failsafe_data[CH_AETR[ch]];
|
||||
if( failsafeMicros!=FAILSAFE_CHANNEL_HOLD && failsafeMicros!=FAILSAFE_CHANNEL_NOPULSES)
|
||||
if(ch<16)
|
||||
val = Failsafe_data[CH_AETR[ch]];
|
||||
else
|
||||
val = FAILSAFE_CHANNEL_NOPULSES;
|
||||
if(val!=FAILSAFE_CHANNEL_HOLD && val!=FAILSAFE_CHANNEL_NOPULSES)
|
||||
{ // Failsafe values
|
||||
failsafeMicros = (((failsafeMicros<<2)+failsafeMicros)>>3)+860;
|
||||
packet[9 + ch*2] = failsafeMicros & 0xff;
|
||||
packet[10+ ch*2] = ( failsafeMicros >> 8) & 0xff;
|
||||
val = (((val<<2)+val)>>3)+860;
|
||||
if(ch<14)
|
||||
{
|
||||
packet[9 + ch*2] = val;
|
||||
packet[10 + ch*2] = (val>>8)&0x0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[10 + (ch-14)*6] &= 0x0F;
|
||||
packet[10 + (ch-14)*6] |= (val)<<4;
|
||||
packet[12 + (ch-14)*6] &= 0x0F;
|
||||
packet[12 + (ch-14)*6] |= (val)&0xF0;
|
||||
packet[14 + (ch-14)*6] &= 0x0F;
|
||||
packet[14 + (ch-14)*6] |= (val>>4)&0xF0;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if(ch<14)
|
||||
{ // no values
|
||||
packet[9 + ch*2] = 0xff;
|
||||
packet[10+ ch*2] = 0xff;
|
||||
@@ -224,17 +253,14 @@ static void AFHDS2A_build_packet(uint8_t type)
|
||||
if(val<50 || val>400) val=50; // default is 50Hz
|
||||
packet[11]= val;
|
||||
packet[12]= val >> 8;
|
||||
if(sub_protocol == PPM_IBUS || sub_protocol == PPM_SBUS)
|
||||
packet[13] = 0x01; // PPM output enabled
|
||||
else
|
||||
packet[13] = 0x00;
|
||||
packet[13] = sub_protocol & 0x01; // 1 -> PPM output enabled
|
||||
packet[14]= 0x00;
|
||||
for(uint8_t i=15; i<37; i++)
|
||||
packet[i] = 0xff;
|
||||
packet[18] = 0x05; // ?
|
||||
packet[19] = 0xdc; // ?
|
||||
packet[20] = 0x05; // ?
|
||||
if(sub_protocol == PWM_SBUS || sub_protocol == PPM_SBUS)
|
||||
if(sub_protocol&2)
|
||||
packet[21] = 0xdd; // SBUS output enabled
|
||||
else
|
||||
packet[21] = 0xde; // IBUS
|
||||
@@ -244,11 +270,18 @@ static void AFHDS2A_build_packet(uint8_t type)
|
||||
}
|
||||
|
||||
#define AFHDS2A_WAIT_WRITE 0x80
|
||||
|
||||
#ifdef STM32_BOARD
|
||||
#define AFHDS2A_WRITE_TIME 1550
|
||||
#else
|
||||
#define AFHDS2A_WRITE_TIME 1700
|
||||
#endif
|
||||
|
||||
uint16_t ReadAFHDS2A()
|
||||
{
|
||||
static uint8_t packet_type;
|
||||
static uint16_t packet_counter;
|
||||
uint8_t data_rx;
|
||||
uint8_t data_rx=0;
|
||||
uint16_t start;
|
||||
#ifndef FORCE_AFHDS2A_TUNING
|
||||
A7105_AdjustLOBaseFreq(1);
|
||||
@@ -325,9 +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
|
||||
if((A7105_ReadReg(A7105_00_MODE) & 0x01)==0) // Check if something has been received...
|
||||
data_rx=1; // Yes
|
||||
A7105_WriteData(AFHDS2A_TXPACKET_SIZE, hopping_frequency[hopping_frequency_no++]);
|
||||
if(hopping_frequency_no >= AFHDS2A_NUMFREQ)
|
||||
@@ -352,13 +383,10 @@ uint16_t ReadAFHDS2A()
|
||||
if(packet[0] == 0xAA && packet[9] == 0xFC)
|
||||
packet_type=AFHDS2A_PACKET_SETTINGS; // RX is asking for settings
|
||||
else
|
||||
if(packet[0] == 0xAA || packet[0] == 0xAC)
|
||||
{
|
||||
if((packet[0] == 0xAA && packet[9]!=0xFD) || packet[0] == 0xAC)
|
||||
{// Normal telemetry packet, ignore packets which contain the RX configuration: AA FD FF 32 00 01 00 FF FF FF 05 DC 05 DE FA FF FF FF FF FF FF FF FF FF FF FF FF FF FF
|
||||
if(!memcmp(&packet[1], rx_tx_addr, 4))
|
||||
{ // TX address validated
|
||||
#ifdef AFHDS2A_LQI_CH
|
||||
if(packet[0]==0xAA && packet[9]!=0xFD)
|
||||
{// Normal telemetry packet
|
||||
for(uint8_t sensor=0; sensor<7; sensor++)
|
||||
{//read LQI value for RX output
|
||||
uint8_t index = 9+(4*sensor);
|
||||
@@ -368,8 +396,6 @@ uint16_t ReadAFHDS2A()
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(AFHDS2A_FW_TELEMETRY) || defined(AFHDS2A_HUB_TELEMETRY)
|
||||
AFHDS2A_update_telemetry();
|
||||
#endif
|
||||
@@ -378,7 +404,7 @@ 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();
|
||||
@@ -389,7 +415,7 @@ uint16_t ReadAFHDS2A()
|
||||
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
|
||||
}
|
||||
@@ -416,6 +442,10 @@ uint16_t initAFHDS2A()
|
||||
rx_id[i]=eeprom_read_byte((EE_ADDR)(addr+i));
|
||||
}
|
||||
hopping_frequency_no = 0;
|
||||
if(sub_protocol&0x04)
|
||||
num_ch=17;
|
||||
else
|
||||
num_ch=14;
|
||||
return 50000;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -126,11 +126,10 @@ uint16_t Bayang_Rx_callback()
|
||||
{
|
||||
uint8_t i;
|
||||
static int8_t read_retry;
|
||||
static uint16_t pps_counter;
|
||||
static uint32_t pps_timer = 0;
|
||||
|
||||
switch (phase) {
|
||||
case BAYANG_RX_BIND:
|
||||
if(IS_BIND_DONE) return initBayang_Rx(); // Abort bind
|
||||
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) {
|
||||
// data received from TX
|
||||
if (XN297_ReadPayload(packet, BAYANG_RX_PACKET_SIZE) && ( packet[0] == 0xA4 || packet[0] == 0xA2 ) && Bayang_Rx_check_validity()) {
|
||||
|
||||
@@ -20,7 +20,8 @@ Multiprotocol is distributed in the hope that it will be useful,
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#define BAYANG_BIND_COUNT 1000
|
||||
#define BAYANG_PACKET_PERIOD 1000
|
||||
#define BAYANG_PACKET_PERIOD 2000
|
||||
#define BAYANG_PACKET_TELEM_PERIOD 5000
|
||||
#define BAYANG_INITIAL_WAIT 500
|
||||
#define BAYANG_PACKET_SIZE 15
|
||||
#define BAYANG_RF_NUM_CHANNELS 4
|
||||
@@ -46,10 +47,10 @@ enum BAYANG_OPTION_FLAGS {
|
||||
BAYANG_OPTION_FLAG_ANALOGAUX = 0x02,
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
|
||||
static void __attribute__((unused)) BAYANG_send_packet()
|
||||
{
|
||||
uint8_t i;
|
||||
if (bind)
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
#ifdef BAYANG_HUB_TELEMETRY
|
||||
if(option & BAYANG_OPTION_FLAG_TELEMETRY)
|
||||
@@ -66,12 +67,16 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
|
||||
else
|
||||
#endif
|
||||
packet[0]= 0xA4;
|
||||
if(sub_protocol==QX100)
|
||||
packet[0] = 0x53;
|
||||
|
||||
for(i=0;i<5;i++)
|
||||
packet[i+1]=rx_tx_addr[i];
|
||||
for(i=0;i<4;i++)
|
||||
packet[i+6]=hopping_frequency[i];
|
||||
switch (sub_protocol)
|
||||
{
|
||||
case QX100:
|
||||
case X16_AH:
|
||||
packet[10] = 0x00;
|
||||
packet[11] = 0x00;
|
||||
@@ -160,6 +165,7 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
|
||||
packet[12] = rx_tx_addr[2]; // txid[2]
|
||||
packet[13] = 0x34;
|
||||
break;
|
||||
case QX100:
|
||||
case X16_AH:
|
||||
packet[12] = 0;
|
||||
packet[13] = 0;
|
||||
@@ -186,29 +192,15 @@ static void __attribute__((unused)) BAYANG_send_packet(uint8_t bind)
|
||||
for (uint8_t i=0; i < BAYANG_PACKET_SIZE-1; i++)
|
||||
packet[14] += packet[i];
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? rf_ch_num:hopping_frequency[hopping_frequency_no++]);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? rf_ch_num:hopping_frequency[hopping_frequency_no++]);
|
||||
hopping_frequency_no%=BAYANG_RF_NUM_CHANNELS;
|
||||
|
||||
// clear packet status bits and TX FIFO
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
|
||||
XN297_WritePayload(packet, BAYANG_PACKET_SIZE);
|
||||
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
// Power on, TX mode, 2byte CRC
|
||||
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
|
||||
#ifdef BAYANG_HUB_TELEMETRY
|
||||
if (option & BAYANG_OPTION_FLAG_TELEMETRY)
|
||||
{ // switch radio to rx as soon as packet is sent
|
||||
while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)));
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x03);
|
||||
}
|
||||
#endif
|
||||
XN297_WritePayload(packet, BAYANG_PACKET_SIZE);
|
||||
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
@@ -229,11 +221,12 @@ static void __attribute__((unused)) BAYANG_check_rx(void)
|
||||
if (packet[0] == 0x85 && packet[14] == check)
|
||||
{
|
||||
// uncompensated battery volts*100/2
|
||||
v_lipo1 = (packet[3]<<7) + (packet[4]>>2);
|
||||
v_lipo1 = (packet[3]<<7) + (packet[4]>>1);
|
||||
// compensated battery volts*100/2
|
||||
v_lipo2 = (packet[5]<<7) + (packet[6]>>2);
|
||||
v_lipo2 = (packet[5]<<7) + (packet[6]>>1);
|
||||
// reception in packets / sec
|
||||
RX_RSSI = packet[7];
|
||||
RX_LQI = packet[7];
|
||||
RX_RSSI = RX_LQI;
|
||||
//Flags
|
||||
//uint8_t flags = packet[3] >> 3;
|
||||
// battery low: flags & 1
|
||||
@@ -242,6 +235,7 @@ static void __attribute__((unused)) BAYANG_check_rx(void)
|
||||
telemetry_link=1;
|
||||
}
|
||||
}
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -278,58 +272,73 @@ static void __attribute__((unused)) BAYANG_init()
|
||||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
BAYANG_BIND=0,
|
||||
BAYANG_WRITE,
|
||||
BAYANG_CHECK,
|
||||
BAYANG_READ,
|
||||
};
|
||||
|
||||
#define BAYANG_CHECK_DELAY 1000 // Time after write phase to check write complete
|
||||
#define BAYANG_READ_DELAY 600 // Time before read phase
|
||||
|
||||
uint16_t BAYANG_callback()
|
||||
{
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
if(packet_count==0)
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync((option & BAYANG_OPTION_FLAG_TELEMETRY)?5*BAYANG_PACKET_PERIOD:2*BAYANG_PACKET_PERIOD);
|
||||
#endif
|
||||
BAYANG_send_packet(0);
|
||||
}
|
||||
packet_count++;
|
||||
#ifdef BAYANG_HUB_TELEMETRY
|
||||
if (option & BAYANG_OPTION_FLAG_TELEMETRY)
|
||||
{ // telemetry is enabled
|
||||
state++;
|
||||
if (state > 1000)
|
||||
{
|
||||
//calculate telemetry reception packet rate - packets per 1000ms
|
||||
TX_RSSI = telemetry_counter;
|
||||
telemetry_counter = 0;
|
||||
state = 0;
|
||||
telemetry_lost=0;
|
||||
}
|
||||
|
||||
if (packet_count > 1)
|
||||
BAYANG_check_rx();
|
||||
|
||||
packet_count %= 5;
|
||||
}
|
||||
else
|
||||
uint16_t start;
|
||||
#endif
|
||||
packet_count%=2;
|
||||
}
|
||||
else
|
||||
switch(phase)
|
||||
{
|
||||
if (bind_counter == 0)
|
||||
case BAYANG_BIND:
|
||||
if (--bind_counter == 0)
|
||||
{
|
||||
XN297_SetTXAddr(rx_tx_addr, BAYANG_ADDRESS_LENGTH);
|
||||
#ifdef BAYANG_HUB_TELEMETRY
|
||||
XN297_SetRXAddr(rx_tx_addr, BAYANG_ADDRESS_LENGTH);
|
||||
#endif
|
||||
BIND_DONE;
|
||||
phase++; //WRITE
|
||||
}
|
||||
else
|
||||
BAYANG_send_packet();
|
||||
break;
|
||||
case BAYANG_WRITE:
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync((option & BAYANG_OPTION_FLAG_TELEMETRY)?BAYANG_PACKET_TELEM_PERIOD:BAYANG_PACKET_PERIOD);
|
||||
#endif
|
||||
BAYANG_send_packet();
|
||||
#ifdef BAYANG_HUB_TELEMETRY
|
||||
if (option & BAYANG_OPTION_FLAG_TELEMETRY)
|
||||
{ // telemetry is enabled
|
||||
state++;
|
||||
if (state > 200)
|
||||
{
|
||||
if(packet_count==0)
|
||||
BAYANG_send_packet(1);
|
||||
packet_count++;
|
||||
packet_count%=4;
|
||||
bind_counter--;
|
||||
state = 0;
|
||||
//telemetry reception packet rate - packets per second
|
||||
TX_LQI = telemetry_counter>>1;
|
||||
telemetry_counter = 0;
|
||||
telemetry_lost=0;
|
||||
}
|
||||
phase++; //CHECK
|
||||
return BAYANG_CHECK_DELAY;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
#ifdef BAYANG_HUB_TELEMETRY
|
||||
case BAYANG_CHECK:
|
||||
// switch radio to rx as soon as packet is sent
|
||||
start=(uint16_t)micros();
|
||||
while ((uint16_t)((uint16_t)micros()-(uint16_t)start) < 1000) // Wait max 1ms
|
||||
if((NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)))
|
||||
break;
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x03);
|
||||
phase++; // READ
|
||||
return BAYANG_PACKET_TELEM_PERIOD - BAYANG_CHECK_DELAY - BAYANG_READ_DELAY;
|
||||
case BAYANG_READ:
|
||||
BAYANG_check_rx();
|
||||
phase=BAYANG_WRITE;
|
||||
return BAYANG_READ_DELAY;
|
||||
#endif
|
||||
}
|
||||
return BAYANG_PACKET_PERIOD;
|
||||
}
|
||||
@@ -350,6 +359,7 @@ static void __attribute__((unused)) BAYANG_initialize_txid()
|
||||
uint16_t initBAYANG(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
phase=BAYANG_BIND;
|
||||
bind_counter = BAYANG_BIND_COUNT;
|
||||
BAYANG_initialize_txid();
|
||||
BAYANG_init();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -150,6 +150,11 @@ void CC2500_SetPower()
|
||||
#else
|
||||
power=CC2500_HIGH_POWER;
|
||||
#endif
|
||||
if(IS_LBT_POWER_on)
|
||||
{
|
||||
power=CC2500_LBT_POWER;
|
||||
LBT_POWER_off; // Only accept once
|
||||
}
|
||||
if(IS_RANGE_FLAG_on)
|
||||
power=CC2500_RANGE_POWER;
|
||||
if(prev_power != power)
|
||||
|
||||
@@ -284,7 +284,7 @@ void CYRF_FindBestChannels(uint8_t *channels, uint8_t len, uint8_t minspace, uin
|
||||
}
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
|
||||
CYRF_SetTxRxMode(TX_EN);
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Clear abort RX
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX
|
||||
}
|
||||
|
||||
#if defined(DEVO_CYRF6936_INO) || defined(J6PRO_CYRF6936_INO)
|
||||
@@ -313,6 +313,7 @@ const uint8_t PROGMEM DEVO_j6pro_sopcodes[][8] = {
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
static void __attribute__((unused)) CYRF_PROGMEM_ConfigSOPCode(const uint8_t *data)
|
||||
{
|
||||
uint8_t code[8];
|
||||
|
||||
@@ -140,3 +140,25 @@ uint16_t convert_channel_frsky(uint8_t num)
|
||||
uint16_t val=Channel_data[num];
|
||||
return ((val*15)>>4)+1290;
|
||||
}
|
||||
|
||||
// 0-2047, 0 = 817, 1024 = 1500, 2047 = 2182
|
||||
//64=860,1024=1500,1984=2140//Taranis 125%
|
||||
static uint16_t __attribute__((unused)) FrSkyX_scaleForPXX( uint8_t i, uint8_t num_chan=8)
|
||||
{ //mapped 860,2140(125%) range to 64,1984(PXX values);
|
||||
uint16_t chan_val=convert_channel_frsky(i)-1226;
|
||||
if(i>=num_chan) chan_val|=2048; // upper channels offset
|
||||
return chan_val;
|
||||
}
|
||||
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
static uint16_t __attribute__((unused)) FrSkyX_scaleForPXX_FS( uint8_t i )
|
||||
{ //mapped 1,2046(125%) range to 64,1984(PXX values);
|
||||
uint16_t chan_val=((Failsafe_data[i]*15)>>4)+64;
|
||||
if(Failsafe_data[i]==FAILSAFE_CHANNEL_NOPULSES)
|
||||
chan_val=FAILSAFE_CHANNEL_NOPULSES;
|
||||
else if(Failsafe_data[i]==FAILSAFE_CHANNEL_HOLD)
|
||||
chan_val=FAILSAFE_CHANNEL_HOLD;
|
||||
if(i>7) chan_val|=2048; // upper channels offset
|
||||
return chan_val;
|
||||
}
|
||||
#endif
|
||||
|
||||
182
Multiprotocol/DSM.ino
Normal file
182
Multiprotocol/DSM.ino
Normal file
@@ -0,0 +1,182 @@
|
||||
#if defined(DSM_CYRF6936_INO) || defined(DSM_RX_CYRF6936_INO)
|
||||
|
||||
#include "iface_cyrf6936.h"
|
||||
|
||||
uint8_t sop_col;
|
||||
|
||||
const uint8_t PROGMEM DSM_pncodes[5][9][8] = {
|
||||
/* Note these are in order transmitted (LSB 1st) */
|
||||
{ /* Row 0 */
|
||||
/* Col 0 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8},
|
||||
/* Col 1 */ {0x88, 0x17, 0x13, 0x3B, 0x2D, 0xBF, 0x06, 0xD6},
|
||||
/* Col 2 */ {0xF1, 0x94, 0x30, 0x21, 0xA1, 0x1C, 0x88, 0xA9},
|
||||
/* Col 3 */ {0xD0, 0xD2, 0x8E, 0xBC, 0x82, 0x2F, 0xE3, 0xB4},
|
||||
/* Col 4 */ {0x8C, 0xFA, 0x47, 0x9B, 0x83, 0xA5, 0x66, 0xD0},
|
||||
/* Col 5 */ {0x07, 0xBD, 0x9F, 0x26, 0xC8, 0x31, 0x0F, 0xB8},
|
||||
/* Col 6 */ {0xEF, 0x03, 0x95, 0x89, 0xB4, 0x71, 0x61, 0x9D},
|
||||
/* Col 7 */ {0x40, 0xBA, 0x97, 0xD5, 0x86, 0x4F, 0xCC, 0xD1},
|
||||
/* Col 8 */ {0xD7, 0xA1, 0x54, 0xB1, 0x5E, 0x89, 0xAE, 0x86}
|
||||
},
|
||||
{ /* Row 1 */
|
||||
/* Col 0 */ {0x83, 0xF7, 0xA8, 0x2D, 0x7A, 0x44, 0x64, 0xD3},
|
||||
/* Col 1 */ {0x3F, 0x2C, 0x4E, 0xAA, 0x71, 0x48, 0x7A, 0xC9},
|
||||
/* Col 2 */ {0x17, 0xFF, 0x9E, 0x21, 0x36, 0x90, 0xC7, 0x82},
|
||||
/* Col 3 */ {0xBC, 0x5D, 0x9A, 0x5B, 0xEE, 0x7F, 0x42, 0xEB},
|
||||
/* Col 4 */ {0x24, 0xF5, 0xDD, 0xF8, 0x7A, 0x77, 0x74, 0xE7},
|
||||
/* Col 5 */ {0x3D, 0x70, 0x7C, 0x94, 0xDC, 0x84, 0xAD, 0x95},
|
||||
/* Col 6 */ {0x1E, 0x6A, 0xF0, 0x37, 0x52, 0x7B, 0x11, 0xD4},
|
||||
/* Col 7 */ {0x62, 0xF5, 0x2B, 0xAA, 0xFC, 0x33, 0xBF, 0xAF},
|
||||
/* Col 8 */ {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97}
|
||||
},
|
||||
{ /* Row 2 */
|
||||
/* Col 0 */ {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97},
|
||||
/* Col 1 */ {0x8E, 0x4A, 0xD0, 0xA9, 0xA7, 0xFF, 0x20, 0xCA},
|
||||
/* Col 2 */ {0x4C, 0x97, 0x9D, 0xBF, 0xB8, 0x3D, 0xB5, 0xBE},
|
||||
/* Col 3 */ {0x0C, 0x5D, 0x24, 0x30, 0x9F, 0xCA, 0x6D, 0xBD},
|
||||
/* Col 4 */ {0x50, 0x14, 0x33, 0xDE, 0xF1, 0x78, 0x95, 0xAD},
|
||||
/* Col 5 */ {0x0C, 0x3C, 0xFA, 0xF9, 0xF0, 0xF2, 0x10, 0xC9},
|
||||
/* Col 6 */ {0xF4, 0xDA, 0x06, 0xDB, 0xBF, 0x4E, 0x6F, 0xB3},
|
||||
/* Col 7 */ {0x9E, 0x08, 0xD1, 0xAE, 0x59, 0x5E, 0xE8, 0xF0},
|
||||
/* Col 8 */ {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E}
|
||||
},
|
||||
{ /* Row 3 */
|
||||
/* Col 0 */ {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E},
|
||||
/* Col 1 */ {0x80, 0x69, 0x26, 0x80, 0x08, 0xF8, 0x49, 0xE7},
|
||||
/* Col 2 */ {0x7D, 0x2D, 0x49, 0x54, 0xD0, 0x80, 0x40, 0xC1},
|
||||
/* Col 3 */ {0xB6, 0xF2, 0xE6, 0x1B, 0x80, 0x5A, 0x36, 0xB4},
|
||||
/* Col 4 */ {0x42, 0xAE, 0x9C, 0x1C, 0xDA, 0x67, 0x05, 0xF6},
|
||||
/* Col 5 */ {0x9B, 0x75, 0xF7, 0xE0, 0x14, 0x8D, 0xB5, 0x80},
|
||||
/* Col 6 */ {0xBF, 0x54, 0x98, 0xB9, 0xB7, 0x30, 0x5A, 0x88},
|
||||
/* Col 7 */ {0x35, 0xD1, 0xFC, 0x97, 0x23, 0xD4, 0xC9, 0x88},
|
||||
/* Col 8 */ {0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93}
|
||||
// Wrong values used by Orange TX/RX
|
||||
// /* Col 8 */ {0x88, 0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40}
|
||||
},
|
||||
{ /* Row 4 */
|
||||
/* Col 0 */ {0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93},
|
||||
/* Col 1 */ {0xDC, 0x68, 0x08, 0x99, 0x97, 0xAE, 0xAF, 0x8C},
|
||||
/* Col 2 */ {0xC3, 0x0E, 0x01, 0x16, 0x0E, 0x32, 0x06, 0xBA},
|
||||
/* Col 3 */ {0xE0, 0x83, 0x01, 0xFA, 0xAB, 0x3E, 0x8F, 0xAC},
|
||||
/* Col 4 */ {0x5C, 0xD5, 0x9C, 0xB8, 0x46, 0x9C, 0x7D, 0x84},
|
||||
/* Col 5 */ {0xF1, 0xC6, 0xFE, 0x5C, 0x9D, 0xA5, 0x4F, 0xB7},
|
||||
/* Col 6 */ {0x58, 0xB5, 0xB3, 0xDD, 0x0E, 0x28, 0xF1, 0xB0},
|
||||
/* Col 7 */ {0x5F, 0x30, 0x3B, 0x56, 0x96, 0x45, 0xF4, 0xA1},
|
||||
/* Col 8 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8}
|
||||
},
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) DSM_read_code(uint8_t *buf, uint8_t row, uint8_t col, uint8_t len)
|
||||
{
|
||||
for(uint8_t i=0;i<len;i++)
|
||||
buf[i]=pgm_read_byte_near( &DSM_pncodes[row][col][i] );
|
||||
}
|
||||
|
||||
const uint8_t PROGMEM DSM_init_vals[][2] = {
|
||||
{CYRF_02_TX_CTRL, 0x00}, // All TX interrupt disabled
|
||||
{CYRF_05_RX_CTRL, 0x00}, // All RX interrupt disabled
|
||||
{CYRF_28_CLK_EN, 0x02}, // Force receive clock enable
|
||||
{CYRF_32_AUTO_CAL_TIME, 0x3c}, // Default init value
|
||||
{CYRF_35_AUTOCAL_OFFSET, 0x14}, // Default init value
|
||||
{CYRF_26_XTAL_CFG, 0x08}, // Start delay
|
||||
{CYRF_06_RX_CFG, 0x4A}, // LNA enabled, RX override enabled, Fast turn mode enabled, RX is 1MHz below TX
|
||||
{CYRF_1B_TX_OFFSET_LSB, 0x55}, // Default init value
|
||||
{CYRF_1C_TX_OFFSET_MSB, 0x05}, // Default init value
|
||||
{CYRF_39_ANALOG_CTRL, 0x01}, // All slow for synth setting time
|
||||
{CYRF_01_TX_LENGTH, 0x10}, // 16 bytes packet
|
||||
{CYRF_14_EOP_CTRL, 0x02}, // Set EOP Symbol Count to 2
|
||||
{CYRF_12_DATA64_THOLD, 0x0a}, // 64 Chip Data PN corelator threshold, default datasheet value is 0x0E
|
||||
//Below is for bind only
|
||||
{CYRF_03_TX_CFG, 0x38 | CYRF_BIND_POWER}, //64 chip codes, SDR mode
|
||||
{CYRF_10_FRAMING_CFG, 0x4a}, // SOP disabled, no LEN field and SOP correlator of 0x0a but since SOP is disabled...
|
||||
{CYRF_1F_TX_OVERRIDE, 0x04}, // Disable TX CRC, no ACK, use TX synthesizer
|
||||
{CYRF_1E_RX_OVERRIDE, 0x14}, // Disable RX CRC, Force receive data rate, use RX synthesizer
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM DSM_data_vals[][2] = {
|
||||
{CYRF_29_RX_ABORT, 0x20}, // Abort RX operation in case we are coming from bind
|
||||
{CYRF_0F_XACT_CFG, 0x24}, // Force Idle
|
||||
{CYRF_29_RX_ABORT, 0x00}, // Clear abort RX
|
||||
{CYRF_03_TX_CFG, 0x28 | CYRF_HIGH_POWER}, // 64 chip codes, 8DR mode
|
||||
{CYRF_10_FRAMING_CFG, 0xea}, // SOP enabled, SOP_CODE_ADR 64 chips, Packet len enabled, SOP correlator 0x0A
|
||||
{CYRF_1F_TX_OVERRIDE, 0x00}, // CRC16 enabled, no ACK
|
||||
{CYRF_1E_RX_OVERRIDE, 0x00}, // CRC16 enabled, no ACK
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) DSM_cyrf_config()
|
||||
{
|
||||
for(uint8_t i = 0; i < sizeof(DSM_init_vals) / 2; i++)
|
||||
CYRF_WriteRegister(pgm_read_byte_near(&DSM_init_vals[i][0]), pgm_read_byte_near(&DSM_init_vals[i][1]));
|
||||
CYRF_WritePreamble(0x333304);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DSM_cyrf_configdata()
|
||||
{
|
||||
for(uint8_t i = 0; i < sizeof(DSM_data_vals) / 2; i++)
|
||||
CYRF_WriteRegister(pgm_read_byte_near(&DSM_data_vals[i][0]), pgm_read_byte_near(&DSM_data_vals[i][1]));
|
||||
}
|
||||
|
||||
static uint8_t __attribute__((unused)) DSM_get_pn_row(uint8_t channel, bool dsmx)
|
||||
{
|
||||
return (dsmx ? (channel - 2) % 5 : channel % 5);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DSM_set_sop_data_crc(bool ch2, bool dsmx)
|
||||
{
|
||||
//The crc for channel '1' is NOT(mfgid[0] << 8 + mfgid[1])
|
||||
//The crc for channel '2' is (mfgid[0] << 8 + mfgid[1])
|
||||
if(ch2)
|
||||
CYRF_ConfigCRCSeed(seed); //CH2
|
||||
else
|
||||
CYRF_ConfigCRCSeed(~seed); //CH1
|
||||
|
||||
uint8_t pn_row = DSM_get_pn_row(hopping_frequency[hopping_frequency_no], dsmx);
|
||||
uint8_t code[16];
|
||||
DSM_read_code(code,pn_row,sop_col,8); // pn_row between 0 and 4, sop_col between 1 and 7
|
||||
CYRF_ConfigSOPCode(code);
|
||||
DSM_read_code(code,pn_row,7 - sop_col,8); // 7-sop_col between 0 and 6
|
||||
DSM_read_code(code+8,pn_row,7 - sop_col + 1,8); // 7-sop_col+1 between 1 and 7
|
||||
CYRF_ConfigDataCode(code, 16);
|
||||
|
||||
CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]);
|
||||
hopping_frequency_no++;
|
||||
if(dsmx)
|
||||
hopping_frequency_no %=23;
|
||||
else
|
||||
hopping_frequency_no %=2;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DSM_calc_dsmx_channel()
|
||||
{
|
||||
uint8_t idx = 0;
|
||||
uint32_t id = ~(((uint32_t)cyrfmfg_id[0] << 24) | ((uint32_t)cyrfmfg_id[1] << 16) | ((uint32_t)cyrfmfg_id[2] << 8) | (cyrfmfg_id[3] << 0));
|
||||
uint32_t id_tmp = id;
|
||||
while(idx < 23)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t count_3_27 = 0, count_28_51 = 0, count_52_76 = 0;
|
||||
id_tmp = id_tmp * 0x0019660D + 0x3C6EF35F; // Randomization
|
||||
uint8_t next_ch = ((id_tmp >> 8) % 0x49) + 3; // Use least-significant byte and must be larger than 3
|
||||
if ( (next_ch ^ cyrfmfg_id[3]) & 0x01 )
|
||||
continue;
|
||||
for (i = 0; i < idx; i++)
|
||||
{
|
||||
if(hopping_frequency[i] == next_ch)
|
||||
break;
|
||||
if(hopping_frequency[i] <= 27)
|
||||
count_3_27++;
|
||||
else
|
||||
if (hopping_frequency[i] <= 51)
|
||||
count_28_51++;
|
||||
else
|
||||
count_52_76++;
|
||||
}
|
||||
if (i != idx)
|
||||
continue;
|
||||
if ((next_ch < 28 && count_3_27 < 8)
|
||||
||(next_ch >= 28 && next_ch < 52 && count_28_51 < 7)
|
||||
||(next_ch >= 52 && count_52_76 < 8))
|
||||
hopping_frequency[idx++] = next_ch;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
505
Multiprotocol/DSM_Rx_cyrf6936.ino
Normal file
505
Multiprotocol/DSM_Rx_cyrf6936.ino
Normal file
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(DSM_RX_CYRF6936_INO)
|
||||
|
||||
#include "iface_cyrf6936.h"
|
||||
|
||||
//#define DSM_DEBUG_RF
|
||||
//#define DSM_DEBUG_CH
|
||||
|
||||
uint8_t DSM_rx_type;
|
||||
|
||||
enum {
|
||||
DSM_RX_BIND1 = 0,
|
||||
DSM_RX_BIND2,
|
||||
DSM_RX_DATA_PREP,
|
||||
DSM2_RX_SCAN,
|
||||
DSM_RX_DATA_CH1,
|
||||
DSM_RX_DATA_CH2,
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) DSM_Rx_init()
|
||||
{
|
||||
DSM_cyrf_config();
|
||||
rx_disable_lna = IS_POWER_FLAG_on;
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
//64 SDR Mode is configured so only the 8 first values are needed but need to write 16 values...
|
||||
uint8_t code[16];
|
||||
DSM_read_code(code,0,8,8);
|
||||
CYRF_ConfigDataCode(code, 16);
|
||||
CYRF_ConfigRFChannel(1);
|
||||
CYRF_SetTxRxMode(RX_EN); // Force end state read
|
||||
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83); // Prepare to receive
|
||||
}
|
||||
else
|
||||
{
|
||||
DSM_cyrf_configdata();
|
||||
CYRF_WriteRegister(CYRF_06_RX_CFG, rx_disable_lna ? 0x0A:0x4A); // AGC disabled, LNA disabled/enabled, Attenuator disabled, RX override enabled, Fast turn mode enabled, RX is 1MHz below TX
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t convert_channel_DSM_nolimit(int32_t val)
|
||||
{
|
||||
val=(val-0x150)*(CHANNEL_MAX_100-CHANNEL_MIN_100)/(0x6B0-0x150)+CHANNEL_MIN_100;
|
||||
if(val<0)
|
||||
val=0;
|
||||
else
|
||||
if(val>2047)
|
||||
val=2047;
|
||||
return (uint16_t)val;
|
||||
}
|
||||
|
||||
static uint8_t __attribute__((unused)) DSM_Rx_check_packet()
|
||||
{
|
||||
uint8_t rx_status=CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
|
||||
if((rx_status & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
|
||||
rx_status |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
|
||||
if((rx_status & 0x07) == 0x02)
|
||||
{ // data received with no errors
|
||||
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
|
||||
#ifdef DSM_DEBUG_RF
|
||||
debugln("l=%d",len);
|
||||
#endif
|
||||
if(len>=2 && len<=16)
|
||||
{
|
||||
// Read packet
|
||||
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // Need to set RXOW before data read
|
||||
CYRF_ReadDataPacketLen(packet, len);
|
||||
|
||||
// Check packet ID
|
||||
if ((DSM_rx_type&0x80) == 0)
|
||||
{//DSM2
|
||||
packet[0] ^= 0xff;
|
||||
packet[1] ^= 0xff;
|
||||
}
|
||||
#ifdef DSM_DEBUG_CH
|
||||
for(uint8_t i=0;i<len;i++)
|
||||
debug("%02X ",packet[i]);
|
||||
debugln("");
|
||||
#endif
|
||||
if(packet[0] == cyrfmfg_id[2] && packet[1] == cyrfmfg_id[3])
|
||||
return 0x02; // Packet ok
|
||||
}
|
||||
return 0x00; // Wrong size or ID -> nothing received
|
||||
}
|
||||
return rx_status; // Return error code
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DSM_Rx_build_telemetry_packet()
|
||||
{
|
||||
uint8_t nbr_bits = 11;
|
||||
if((DSM_rx_type&0xF0) == 0x00)
|
||||
nbr_bits=10; // Only DSM_22 is using a resolution of 1024
|
||||
|
||||
// Use packet length to calculate the number of channels
|
||||
len -= 2; // Remove header length
|
||||
len >>= 1; // Channels are on 2 bytes
|
||||
if(len==0) return; // No channels...
|
||||
|
||||
// Extract channels
|
||||
uint8_t idx;
|
||||
for (uint8_t i = 0; i < len; i++)
|
||||
{
|
||||
uint16_t value=(packet[i*2+2]<<8) | packet[i*2+3];
|
||||
if(value!=0xFFFF)
|
||||
{
|
||||
idx=(value&0x7FFF)>>nbr_bits; // retrieve channel index
|
||||
#ifdef DSM_DEBUG_CH
|
||||
debugln("i=%d,v=%d,u=%X",idx,value&0x7FF,value&0x8000);
|
||||
#endif
|
||||
if(idx<13)
|
||||
{
|
||||
if(nbr_bits==10) value <<= 1; // switch to 11 bits
|
||||
value &= 0x7FF;
|
||||
rx_rc_chan[CH_TAER[idx]]=convert_channel_DSM_nolimit(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Buid telemetry packet
|
||||
idx=0;
|
||||
packet_in[idx++] = RX_LQI;
|
||||
packet_in[idx++] = RX_LQI;
|
||||
packet_in[idx++] = 0; // start channel
|
||||
packet_in[idx++] = 12; // number of channels in packet
|
||||
|
||||
// Pack channels
|
||||
uint32_t bits = 0;
|
||||
uint8_t bitsavailable = 0;
|
||||
for (uint8_t i = 0; i < 12; i++)
|
||||
{
|
||||
bits |= ((uint32_t)rx_rc_chan[i]) << bitsavailable;
|
||||
bitsavailable += 11;
|
||||
while (bitsavailable >= 8)
|
||||
{
|
||||
packet_in[idx++] = bits & 0xff;
|
||||
bits >>= 8;
|
||||
bitsavailable -= 8;
|
||||
}
|
||||
}
|
||||
if(bitsavailable)
|
||||
packet_in[idx++] = bits & 0xff;
|
||||
// Send telemetry
|
||||
telemetry_link = 1;
|
||||
}
|
||||
|
||||
static bool __attribute__((unused)) DSM_Rx_bind_check_validity()
|
||||
{
|
||||
uint16_t sum = 384 - 0x10;//
|
||||
for(uint8_t i = 0; i < 8; i++)
|
||||
sum += packet_in[i];
|
||||
if( packet_in[8] != (sum>>8) || packet_in[9] != (sum&0xFF)) //Checksum
|
||||
return false;
|
||||
for(uint8_t i = 8; i < 14; i++)
|
||||
sum += packet_in[i];
|
||||
if( packet_in[14] != (sum>>8) || packet_in[15] != (sum&0xFF)) //Checksum
|
||||
return false;
|
||||
if(memcmp(packet_in,packet_in+4,4)) //Check ID
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DSM_Rx_build_bind_packet()
|
||||
{
|
||||
uint16_t sum = 384 - 0x10;//
|
||||
packet[0] = 0xff ^ cyrfmfg_id[0]; // ID
|
||||
packet[1] = 0xff ^ cyrfmfg_id[1];
|
||||
packet[2] = 0xff ^ cyrfmfg_id[2];
|
||||
packet[3] = 0xff ^ cyrfmfg_id[3];
|
||||
packet[4] = 0x01; // RX version
|
||||
packet[5] = num_ch; // Number of channels
|
||||
packet[6] = DSM_rx_type; // DSM type, let's just send back whatever the TX gave us...
|
||||
packet[7] = 0x00; // Unknown
|
||||
for(uint8_t i = 0; i < 8; i++)
|
||||
sum += packet[i];
|
||||
packet[8] = sum >> 8;
|
||||
packet[9] = sum & 0xff;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DSM_abort_channel_rx(uint8_t ch)
|
||||
{
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
|
||||
CYRF_SetTxRxMode(IS_POWER_FLAG_on ? TXRX_OFF:RX_EN); // Force end state read
|
||||
if (rx_disable_lna != IS_POWER_FLAG_on && IS_BIND_DONE)
|
||||
{
|
||||
rx_disable_lna = IS_POWER_FLAG_on;
|
||||
CYRF_WriteRegister(CYRF_06_RX_CFG, rx_disable_lna ? 0x0A:0x4A); // AGC disabled, LNA disabled/enabled, Attenuator disabled, RX override enabled, Fast turn mode enabled, RX is 1MHz below TX
|
||||
}
|
||||
if(ch&0x02) DSM_set_sop_data_crc(true ,DSM_rx_type&0x80); // Set sop data,crc seed and rf channel using CH1, DSM2/X
|
||||
if(ch&0x01) DSM_set_sop_data_crc(false,DSM_rx_type&0x80); // Set sop data,crc seed and rf channel using CH1, DSM2/X
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX operation
|
||||
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83); // Prepare to receive
|
||||
}
|
||||
|
||||
uint16_t DSM_Rx_callback()
|
||||
{
|
||||
uint8_t rx_status;
|
||||
static uint8_t read_retry=0;
|
||||
|
||||
switch (phase)
|
||||
{
|
||||
case DSM_RX_BIND1:
|
||||
if(IS_BIND_DONE) // Abort bind
|
||||
{
|
||||
phase = DSM_RX_DATA_PREP;
|
||||
break;
|
||||
}
|
||||
if(packet_count==0)
|
||||
read_retry=0;
|
||||
//Check received data
|
||||
rx_status = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
|
||||
if((rx_status & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
|
||||
rx_status |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
|
||||
if((rx_status & 0x07) == 0x02)
|
||||
{ // data received with no errors
|
||||
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // Need to set RXOW before data read
|
||||
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
|
||||
debugln("RX:%d, CH:%d",len,hopping_frequency_no);
|
||||
if(len==16)
|
||||
{
|
||||
CYRF_ReadDataPacketLen(packet_in, 16);
|
||||
if(DSM_Rx_bind_check_validity())
|
||||
{
|
||||
// store tx info into eeprom
|
||||
uint16_t temp = DSM_RX_EEPROM_OFFSET;
|
||||
debug("ID=");
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
{
|
||||
cyrfmfg_id[i]=packet_in[i]^0xFF;
|
||||
eeprom_write_byte((EE_ADDR)temp++, cyrfmfg_id[i]);
|
||||
debug(" %02X", cyrfmfg_id[i]);
|
||||
}
|
||||
// check num_ch
|
||||
num_ch=packet_in[11];
|
||||
if(num_ch>12) num_ch=12;
|
||||
//check DSM_rx_type
|
||||
/*packet[12] 1 byte -> max DSM type allowed:
|
||||
0x01 => 22ms 1024 DSM2 1 packet => number of channels is <8
|
||||
0x02 => 22ms 1024 DSM2 2 packets => either a number of channel >7
|
||||
0x12 => 11ms 2048 DSM2 2 packets => can be any number of channels
|
||||
0xA2 => 22ms 2048 DSMX 1 packet => number of channels is <8
|
||||
0xB2 => 11ms 2048 DSMX => can be any number of channels
|
||||
(0x01 or 0xA2) and num_ch < 7 => 22ms else 11ms
|
||||
&0x80 => false=DSM2, true=DSMX
|
||||
&0xF0 => false=1024, true=2048 */
|
||||
DSM_rx_type=packet_in[12];
|
||||
switch(DSM_rx_type)
|
||||
{
|
||||
case 0x01:
|
||||
if(num_ch>7) DSM_rx_type = 0x02; // Can't be 0x01 with this number of channels
|
||||
break;
|
||||
case 0xA2:
|
||||
if(num_ch>7) DSM_rx_type = 0xB2; // Can't be 0xA2 with this number of channels
|
||||
break;
|
||||
case 0x02:
|
||||
case 0x12:
|
||||
case 0xB2:
|
||||
break;
|
||||
default: // Unknown type, default to DSMX 11ms
|
||||
DSM_rx_type = 0xB2;
|
||||
break;
|
||||
}
|
||||
eeprom_write_byte((EE_ADDR)temp, DSM_rx_type);
|
||||
debugln(", num_ch=%d, type=%02X",num_ch, DSM_rx_type);
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
|
||||
CYRF_SetTxRxMode(TX_EN); // Force end state TX
|
||||
CYRF_ConfigDataCode((const uint8_t *)"\x98\x88\x1B\xE4\x30\x79\x03\x84", 16);
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX
|
||||
DSM_Rx_build_bind_packet();
|
||||
bind_counter=500;
|
||||
phase++; // DSM_RX_BIND2;
|
||||
return 1000;
|
||||
}
|
||||
}
|
||||
DSM_abort_channel_rx(0); // Abort RX operation and receive
|
||||
if(read_retry==0)
|
||||
read_retry=8;
|
||||
}
|
||||
else
|
||||
if(rx_status & 0x02) // RX error
|
||||
DSM_abort_channel_rx(0); // Abort RX operation and receive
|
||||
packet_count++;
|
||||
if(packet_count>12)
|
||||
{
|
||||
packet_count=1;
|
||||
if(read_retry)
|
||||
read_retry--;
|
||||
if(read_retry==0)
|
||||
{
|
||||
packet_count=0;
|
||||
hopping_frequency_no++; // Change channel
|
||||
hopping_frequency_no %= 0x50;
|
||||
hopping_frequency_no |= 0x01; // Odd channels only
|
||||
CYRF_ConfigRFChannel(hopping_frequency_no);
|
||||
DSM_abort_channel_rx(0); // Abort RX operation and receive
|
||||
}
|
||||
}
|
||||
return 1000;
|
||||
case DSM_RX_BIND2:
|
||||
//Transmit settings back
|
||||
CYRF_WriteDataPacketLen(packet,10); // Send packet
|
||||
if(bind_counter--==0)
|
||||
{
|
||||
BIND_DONE;
|
||||
phase++; // DSM_RX_DATA_PREP
|
||||
}
|
||||
break;
|
||||
case DSM_RX_DATA_PREP:
|
||||
hopping_frequency_no = 0;
|
||||
read_retry=0;
|
||||
rx_data_started = false;
|
||||
pps_counter = 0;
|
||||
RX_LQI = 100;
|
||||
DSM_cyrf_configdata();
|
||||
pps_timer=millis();
|
||||
sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;
|
||||
seed = (cyrfmfg_id[0] << 8) + cyrfmfg_id[1];
|
||||
if(DSM_rx_type&0x80)
|
||||
{ // DSMX
|
||||
DSM_calc_dsmx_channel(); // Build hop table
|
||||
DSM_abort_channel_rx(1); // Abort RX operation, set sop&data&seed&rf using CH1, DSM2/X and receive
|
||||
phase=DSM_RX_DATA_CH1;
|
||||
}
|
||||
else
|
||||
{ // DSM2
|
||||
rf_ch_num=0;
|
||||
hopping_frequency_no = 0;
|
||||
hopping_frequency[0] = 3;
|
||||
hopping_frequency[1] = 0;
|
||||
DSM_abort_channel_rx(1); // Abort RX operation, set sop&data&seed&rf using CH1, DSM2/X and receive
|
||||
phase=DSM2_RX_SCAN;
|
||||
}
|
||||
break;
|
||||
case DSM2_RX_SCAN: // Scan for DSM2 frequencies
|
||||
//Received something ?
|
||||
rx_status = DSM_Rx_check_packet();
|
||||
if(rx_status == 0x02)
|
||||
{ // data received with no errors
|
||||
debugln("CH%d:Found %d",rf_ch_num+1,hopping_frequency[rf_ch_num]);
|
||||
read_retry=0;
|
||||
if(rf_ch_num)
|
||||
{ // Both CH1 and CH2 found
|
||||
read_retry=0;
|
||||
hopping_frequency_no=0;
|
||||
DSM_abort_channel_rx(1); // Abort RX operation, set sop&data&seed&rf using CH1, DSM2/X and receive
|
||||
pps_timer=millis();
|
||||
phase++; // DSM_RX_DATA_CH1
|
||||
}
|
||||
else
|
||||
{
|
||||
rf_ch_num++; // CH1 found, scan for CH2
|
||||
hopping_frequency_no = 1;
|
||||
if(hopping_frequency[1] < 3) // If no CH2 keep then restart from current
|
||||
hopping_frequency[1]=hopping_frequency[0]+1;
|
||||
DSM_abort_channel_rx(2); // Abort RX operation, set sop&data&seed&rf using CH2, DSM2/X and receive
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
read_retry++;
|
||||
if(read_retry>50) // After 50ms
|
||||
{ // Try next channel
|
||||
debugln("CH%d:Next channel",rf_ch_num+1);
|
||||
read_retry=0;
|
||||
hopping_frequency_no = rf_ch_num;
|
||||
hopping_frequency[rf_ch_num]++;
|
||||
if(hopping_frequency[rf_ch_num] > 73) hopping_frequency[rf_ch_num] = 3;
|
||||
DSM_abort_channel_rx(rf_ch_num+1); // Abort RX operation, set sop&data&seed&rf using CH1/2, DSM2/X and receive
|
||||
}
|
||||
else if(rx_status & 0x02)
|
||||
{ // data received with errors
|
||||
if((rx_status & 0x01) && rf_ch_num==0)
|
||||
hopping_frequency[1] = hopping_frequency[0];// Might be CH2 since it's a CRC error so keep it
|
||||
debugln("CH%d:RX error",rf_ch_num+1);
|
||||
DSM_abort_channel_rx(0); // Abort RX operation and receive
|
||||
}
|
||||
}
|
||||
return 1000;
|
||||
case DSM_RX_DATA_CH1:
|
||||
//Packets per second
|
||||
if (millis() - pps_timer >= 1000)
|
||||
{//182pps @11ms, 91pps @22ms
|
||||
pps_timer = millis();
|
||||
if(DSM_rx_type!=0xA2 && DSM_rx_type!=0x01) // if 11ms
|
||||
pps_counter >>=1; // then /2
|
||||
debugln("%d pps", pps_counter);
|
||||
RX_LQI = pps_counter; // max=91pps
|
||||
pps_counter = 0;
|
||||
}
|
||||
//Received something ?
|
||||
rx_status = DSM_Rx_check_packet();
|
||||
if(rx_status == 0x02)
|
||||
{ // data received with no errors
|
||||
#ifdef DSM_DEBUG_RF
|
||||
debugln("CH1:RX");
|
||||
#endif
|
||||
DSM_Rx_build_telemetry_packet();
|
||||
rx_data_started = true;
|
||||
pps_counter++;
|
||||
DSM_abort_channel_rx(2); // Abort RX operation, set sop&data&seed&rf using CH2, DSM2/X and receive
|
||||
phase++;
|
||||
return 5000;
|
||||
}
|
||||
else
|
||||
{
|
||||
read_retry++;
|
||||
if(rx_data_started && read_retry>6) // After 6*500=3ms
|
||||
{ // skip to CH2
|
||||
#ifdef DSM_DEBUG_RF
|
||||
debugln("CH1:Skip to CH2");
|
||||
#endif
|
||||
DSM_abort_channel_rx(2); // Abort RX operation, set sop&data&seed&rf using CH2, DSM2/X and receive
|
||||
phase++;
|
||||
return 4000;
|
||||
}
|
||||
if(rx_data_started && RX_LQI==0)
|
||||
{ // communication lost
|
||||
#ifdef DSM_DEBUG_RF
|
||||
debugln("CH1:Restart...");
|
||||
#endif
|
||||
phase=DSM_RX_DATA_PREP;
|
||||
return 1000;
|
||||
}
|
||||
if(read_retry>250)
|
||||
{ // move to next RF channel
|
||||
#ifdef DSM_DEBUG_RF
|
||||
debugln("CH1:Scan");
|
||||
#endif
|
||||
DSM_abort_channel_rx(3); // Abort RX operation, set sop&data&seed&rf using CH2 then CH1, DSM2/X and receive
|
||||
read_retry=0;
|
||||
}
|
||||
else if(rx_status & 0x02)
|
||||
{ // data received with errors
|
||||
#ifdef DSM_DEBUG_RF
|
||||
debugln("CH1:RX error %02X",rx_status);
|
||||
#endif
|
||||
DSM_abort_channel_rx(0); // Abort RX operation and receive
|
||||
}
|
||||
}
|
||||
return 500;
|
||||
case DSM_RX_DATA_CH2:
|
||||
rx_status = DSM_Rx_check_packet();
|
||||
if(rx_status == 0x02)
|
||||
{ // data received with no errors
|
||||
#ifdef DSM_DEBUG_RF
|
||||
debugln("CH2:RX");
|
||||
#endif
|
||||
DSM_Rx_build_telemetry_packet();
|
||||
pps_counter++;
|
||||
}
|
||||
#ifdef DSM_DEBUG_RF
|
||||
else
|
||||
debugln("CH2:No RX");
|
||||
#endif
|
||||
DSM_abort_channel_rx(1); // Abort RX operation, set sop&data&seed&rf using CH1, DSM2/X and receive
|
||||
read_retry=0;
|
||||
phase=DSM_RX_DATA_CH1;
|
||||
if(DSM_rx_type==0xA2) //|| DSM_rx_type==0x01 -> not needed for DSM2 since we are ok to listen even if there will be nothing
|
||||
return 15000; //22ms
|
||||
else
|
||||
return 4000; //11ms
|
||||
}
|
||||
return 10000;
|
||||
}
|
||||
|
||||
uint16_t initDSM_Rx()
|
||||
{
|
||||
DSM_Rx_init();
|
||||
hopping_frequency_no = 0;
|
||||
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet_count=0;
|
||||
phase = DSM_RX_BIND1;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t temp = DSM_RX_EEPROM_OFFSET;
|
||||
debug("ID=");
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
{
|
||||
cyrfmfg_id[i]=eeprom_read_byte((EE_ADDR)temp++);
|
||||
debug(" %02X", cyrfmfg_id[i]);
|
||||
}
|
||||
DSM_rx_type=eeprom_read_byte((EE_ADDR)temp);
|
||||
debugln(", type=%02X", DSM_rx_type);
|
||||
phase = DSM_RX_DATA_PREP;
|
||||
}
|
||||
return 15000;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -17,6 +17,10 @@
|
||||
|
||||
#include "iface_cyrf6936.h"
|
||||
|
||||
//#define DSM_DEBUG_FWD_PGM
|
||||
|
||||
//#define DSM_GR300
|
||||
|
||||
#define DSM_BIND_CHANNEL 0x0d //13 This can be any odd channel
|
||||
|
||||
//During binding we will send BIND_COUNT/2 packets
|
||||
@@ -41,10 +45,10 @@ enum {
|
||||
};
|
||||
|
||||
//
|
||||
uint8_t sop_col;
|
||||
uint8_t ch_map[14];
|
||||
const uint8_t PROGMEM DSM_ch_map_progmem[][14] = {
|
||||
//22+11ms for 4..7 channels
|
||||
//22+11ms for 3..7 channels
|
||||
{1, 0, 2, 0xff, 0xff, 0xff, 0xff, 1, 0, 2, 0xff, 0xff, 0xff, 0xff}, //3ch - Guess
|
||||
{1, 0, 2, 3, 0xff, 0xff, 0xff, 1, 0, 2, 3, 0xff, 0xff, 0xff}, //4ch - Guess
|
||||
{1, 0, 2, 3, 4, 0xff, 0xff, 1, 0, 2, 3, 4, 0xff, 0xff}, //5ch - Guess
|
||||
{1, 5, 2, 3, 0, 4, 0xff, 1, 5, 2, 3, 0, 4, 0xff}, //6ch - HP6DSM
|
||||
@@ -54,123 +58,14 @@ const uint8_t PROGMEM DSM_ch_map_progmem[][14] = {
|
||||
{1, 5, 2, 3, 6, 0xff, 0xff, 4, 0, 7, 8, 0xff, 0xff, 0xff}, //9ch - Guess
|
||||
{1, 5, 2, 3, 6, 0xff, 0xff, 4, 0, 7, 8, 9, 0xff, 0xff}, //10ch - Guess
|
||||
{1, 5, 2, 3, 6, 10, 0xff, 4, 0, 7, 8, 9, 0xff, 0xff}, //11ch - Guess
|
||||
{1, 5, 2, 4, 6, 10, 0xff, 0, 7, 3, 8, 9 , 11 , 0xff}, //12ch - DX18
|
||||
//11ms for 8..12 channels
|
||||
{1, 5, 2, 4, 6, 10, 0xff, 0, 7, 3, 8, 9 , 11 , 0xff}, //12ch - DX18/DX8G2
|
||||
//11ms for 8..11 channels
|
||||
{1, 5, 2, 3, 6, 7, 0xff, 1, 5, 2, 4, 0, 0xff, 0xff}, //8ch - DX7
|
||||
{1, 5, 2, 3, 6, 7, 0xff, 1, 5, 2, 4, 0, 8, 0xff}, //9ch - Guess
|
||||
{1, 5, 2, 3, 4, 8, 9, 1, 5, 2, 3, 0, 7, 6 }, //10ch - DX18
|
||||
{1, 5, 2, 3, 4, 8, 9, 1, 10, 2, 3, 0, 7, 6 }, //11ch - Guess
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM DSM_pncodes[5][8][8] = {
|
||||
/* Note these are in order transmitted (LSB 1st) */
|
||||
{ /* Row 0 */
|
||||
/* Col 0 */ {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8},
|
||||
/* Col 1 */ {0x88, 0x17, 0x13, 0x3B, 0x2D, 0xBF, 0x06, 0xD6},
|
||||
/* Col 2 */ {0xF1, 0x94, 0x30, 0x21, 0xA1, 0x1C, 0x88, 0xA9},
|
||||
/* Col 3 */ {0xD0, 0xD2, 0x8E, 0xBC, 0x82, 0x2F, 0xE3, 0xB4},
|
||||
/* Col 4 */ {0x8C, 0xFA, 0x47, 0x9B, 0x83, 0xA5, 0x66, 0xD0},
|
||||
/* Col 5 */ {0x07, 0xBD, 0x9F, 0x26, 0xC8, 0x31, 0x0F, 0xB8},
|
||||
/* Col 6 */ {0xEF, 0x03, 0x95, 0x89, 0xB4, 0x71, 0x61, 0x9D},
|
||||
/* Col 7 */ {0x40, 0xBA, 0x97, 0xD5, 0x86, 0x4F, 0xCC, 0xD1},
|
||||
/* Col 8 {0xD7, 0xA1, 0x54, 0xB1, 0x5E, 0x89, 0xAE, 0x86}*/
|
||||
},
|
||||
{ /* Row 1 */
|
||||
/* Col 0 */ {0x83, 0xF7, 0xA8, 0x2D, 0x7A, 0x44, 0x64, 0xD3},
|
||||
/* Col 1 */ {0x3F, 0x2C, 0x4E, 0xAA, 0x71, 0x48, 0x7A, 0xC9},
|
||||
/* Col 2 */ {0x17, 0xFF, 0x9E, 0x21, 0x36, 0x90, 0xC7, 0x82},
|
||||
/* Col 3 */ {0xBC, 0x5D, 0x9A, 0x5B, 0xEE, 0x7F, 0x42, 0xEB},
|
||||
/* Col 4 */ {0x24, 0xF5, 0xDD, 0xF8, 0x7A, 0x77, 0x74, 0xE7},
|
||||
/* Col 5 */ {0x3D, 0x70, 0x7C, 0x94, 0xDC, 0x84, 0xAD, 0x95},
|
||||
/* Col 6 */ {0x1E, 0x6A, 0xF0, 0x37, 0x52, 0x7B, 0x11, 0xD4},
|
||||
/* Col 7 */ {0x62, 0xF5, 0x2B, 0xAA, 0xFC, 0x33, 0xBF, 0xAF},
|
||||
/* Col 8 {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97} */
|
||||
},
|
||||
{ /* Row 2 */
|
||||
/* Col 0 */ {0x40, 0x56, 0x32, 0xD9, 0x0F, 0xD9, 0x5D, 0x97},
|
||||
/* Col 1 */ {0x8E, 0x4A, 0xD0, 0xA9, 0xA7, 0xFF, 0x20, 0xCA},
|
||||
/* Col 2 */ {0x4C, 0x97, 0x9D, 0xBF, 0xB8, 0x3D, 0xB5, 0xBE},
|
||||
/* Col 3 */ {0x0C, 0x5D, 0x24, 0x30, 0x9F, 0xCA, 0x6D, 0xBD},
|
||||
/* Col 4 */ {0x50, 0x14, 0x33, 0xDE, 0xF1, 0x78, 0x95, 0xAD},
|
||||
/* Col 5 */ {0x0C, 0x3C, 0xFA, 0xF9, 0xF0, 0xF2, 0x10, 0xC9},
|
||||
/* Col 6 */ {0xF4, 0xDA, 0x06, 0xDB, 0xBF, 0x4E, 0x6F, 0xB3},
|
||||
/* Col 7 */ {0x9E, 0x08, 0xD1, 0xAE, 0x59, 0x5E, 0xE8, 0xF0},
|
||||
/* Col 8 {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E} */
|
||||
},
|
||||
{ /* Row 3 */
|
||||
/* Col 0 */ {0xC0, 0x90, 0x8F, 0xBB, 0x7C, 0x8E, 0x2B, 0x8E},
|
||||
/* Col 1 */ {0x80, 0x69, 0x26, 0x80, 0x08, 0xF8, 0x49, 0xE7},
|
||||
/* Col 2 */ {0x7D, 0x2D, 0x49, 0x54, 0xD0, 0x80, 0x40, 0xC1},
|
||||
/* Col 3 */ {0xB6, 0xF2, 0xE6, 0x1B, 0x80, 0x5A, 0x36, 0xB4},
|
||||
/* Col 4 */ {0x42, 0xAE, 0x9C, 0x1C, 0xDA, 0x67, 0x05, 0xF6},
|
||||
/* Col 5 */ {0x9B, 0x75, 0xF7, 0xE0, 0x14, 0x8D, 0xB5, 0x80},
|
||||
/* Col 6 */ {0xBF, 0x54, 0x98, 0xB9, 0xB7, 0x30, 0x5A, 0x88},
|
||||
/* Col 7 */ {0x35, 0xD1, 0xFC, 0x97, 0x23, 0xD4, 0xC9, 0x88},
|
||||
/* Col 8 {0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93} */
|
||||
// Wrong values used by Orange TX/RX
|
||||
// /* Col 8 */ {0x88, 0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40}
|
||||
},
|
||||
{ /* Row 4 */
|
||||
/* Col 0 */ {0xE1, 0xD6, 0x31, 0x26, 0x5F, 0xBD, 0x40, 0x93},
|
||||
/* Col 1 */ {0xDC, 0x68, 0x08, 0x99, 0x97, 0xAE, 0xAF, 0x8C},
|
||||
/* Col 2 */ {0xC3, 0x0E, 0x01, 0x16, 0x0E, 0x32, 0x06, 0xBA},
|
||||
/* Col 3 */ {0xE0, 0x83, 0x01, 0xFA, 0xAB, 0x3E, 0x8F, 0xAC},
|
||||
/* Col 4 */ {0x5C, 0xD5, 0x9C, 0xB8, 0x46, 0x9C, 0x7D, 0x84},
|
||||
/* Col 5 */ {0xF1, 0xC6, 0xFE, 0x5C, 0x9D, 0xA5, 0x4F, 0xB7},
|
||||
/* Col 6 */ {0x58, 0xB5, 0xB3, 0xDD, 0x0E, 0x28, 0xF1, 0xB0},
|
||||
/* Col 7 */ {0x5F, 0x30, 0x3B, 0x56, 0x96, 0x45, 0xF4, 0xA1},
|
||||
/* Col 8 {0x03, 0xBC, 0x6E, 0x8A, 0xEF, 0xBD, 0xFE, 0xF8} */
|
||||
},
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) DSM_read_code(uint8_t *buf, uint8_t row, uint8_t col, uint8_t len)
|
||||
{
|
||||
for(uint8_t i=0;i<len;i++)
|
||||
buf[i]=pgm_read_byte_near( &DSM_pncodes[row][col][i] );
|
||||
}
|
||||
|
||||
static uint8_t __attribute__((unused)) DSM_get_pn_row(uint8_t channel)
|
||||
{
|
||||
return ((sub_protocol == DSMX_11 || sub_protocol == DSMX_22 )? (channel - 2) % 5 : channel % 5);
|
||||
}
|
||||
|
||||
const uint8_t PROGMEM DSM_init_vals[][2] = {
|
||||
{CYRF_02_TX_CTRL, 0x00}, // All TX interrupt disabled
|
||||
{CYRF_05_RX_CTRL, 0x00}, // All RX interrupt disabled
|
||||
{CYRF_28_CLK_EN, 0x02}, // Force receive clock enable
|
||||
{CYRF_32_AUTO_CAL_TIME, 0x3c}, // Default init value
|
||||
{CYRF_35_AUTOCAL_OFFSET, 0x14}, // Default init value
|
||||
{CYRF_06_RX_CFG, 0x4A}, // LNA enabled, RX override enabled, Fast turn mode enabled, RX is 1MHz below TX
|
||||
{CYRF_1B_TX_OFFSET_LSB, 0x55}, // Default init value
|
||||
{CYRF_1C_TX_OFFSET_MSB, 0x05}, // Default init value
|
||||
{CYRF_39_ANALOG_CTRL, 0x01}, // All slow for synth setting time
|
||||
{CYRF_01_TX_LENGTH, 0x10}, // 16 bytes packet
|
||||
{CYRF_14_EOP_CTRL, 0x02}, // Set EOP Symbol Count to 2
|
||||
{CYRF_12_DATA64_THOLD, 0x0a}, // 64 Chip Data PN corelator threshold, default datasheet value is 0x0E
|
||||
//Below is for bind only
|
||||
{CYRF_03_TX_CFG, 0x38 | CYRF_BIND_POWER}, //64 chip codes, SDR mode
|
||||
{CYRF_10_FRAMING_CFG, 0x4a}, // SOP disabled, no LEN field and SOP correlator of 0x0a but since SOP is disabled...
|
||||
{CYRF_1F_TX_OVERRIDE, 0x04}, // Disable TX CRC, no ACK, use TX synthesizer
|
||||
{CYRF_1E_RX_OVERRIDE, 0x14}, // Disable RX CRC, Force receive data rate, use RX synthesizer
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM DSM_data_vals[][2] = {
|
||||
{CYRF_29_RX_ABORT, 0x20}, // Abort RX operation in case we are coming from bind
|
||||
{CYRF_0F_XACT_CFG, 0x24}, // Force Idle
|
||||
{CYRF_29_RX_ABORT, 0x00}, // Clear abort RX
|
||||
{CYRF_03_TX_CFG, 0x28 | CYRF_HIGH_POWER}, // 64 chip codes, 8DR mode
|
||||
{CYRF_10_FRAMING_CFG, 0xea}, // SOP enabled, SOP_CODE_ADR 64 chips, Packet len enabled, SOP correlator 0x0A
|
||||
{CYRF_1F_TX_OVERRIDE, 0x00}, // CRC16 enabled, no ACK
|
||||
{CYRF_1E_RX_OVERRIDE, 0x00}, // CRC16 enabled, no ACK
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) DSM_cyrf_config()
|
||||
{
|
||||
for(uint8_t i = 0; i < sizeof(DSM_init_vals) / 2; i++)
|
||||
CYRF_WriteRegister(pgm_read_byte_near(&DSM_init_vals[i][0]), pgm_read_byte_near(&DSM_init_vals[i][1]));
|
||||
CYRF_WritePreamble(0x333304);
|
||||
CYRF_ConfigRFChannel(0x61);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DSM_build_bind_packet()
|
||||
{
|
||||
uint8_t i;
|
||||
@@ -188,20 +83,23 @@ static void __attribute__((unused)) DSM_build_bind_packet()
|
||||
packet[8] = sum >> 8;
|
||||
packet[9] = sum & 0xff;
|
||||
packet[10] = 0x01; // ???
|
||||
if(sub_protocol==DSM_AUTO)
|
||||
packet[11] = 12;
|
||||
else
|
||||
packet[11] = num_ch;
|
||||
|
||||
if (sub_protocol==DSM2_22)
|
||||
packet[12]=num_ch<8?0x01:0x02; // DSM2/1024 1 or 2 packets depending on the number of channels
|
||||
if(sub_protocol==DSM2_11)
|
||||
else if(sub_protocol==DSM2_11)
|
||||
packet[12]=0x12; // DSM2/2048 2 packets
|
||||
if(sub_protocol==DSMX_22)
|
||||
else if(sub_protocol==DSMX_22)
|
||||
#if defined DSM_TELEMETRY
|
||||
packet[12] = 0xb2; // DSMX/2048 2 packets
|
||||
#else
|
||||
packet[12] = num_ch<8? 0xa2 : 0xb2; // DSMX/2048 1 or 2 packets depending on the number of channels
|
||||
#endif
|
||||
if(sub_protocol==DSMX_11 || sub_protocol==DSM_AUTO) // Force DSMX/1024 in mode Auto
|
||||
packet[12]=0xb2; // DSMX/1024 2 packets
|
||||
else // DSMX_11 && DSM_AUTO
|
||||
packet[12]=0xb2; // DSMX/2048 2 packets
|
||||
|
||||
packet[13] = 0x00; //???
|
||||
for(i = 8; i < 14; i++)
|
||||
@@ -214,30 +112,24 @@ static void __attribute__((unused)) DSM_initialize_bind_phase()
|
||||
{
|
||||
CYRF_ConfigRFChannel(DSM_BIND_CHANNEL); //This seems to be random?
|
||||
//64 SDR Mode is configured so only the 8 first values are needed but need to write 16 values...
|
||||
CYRF_ConfigDataCode((const uint8_t*)"\xD7\xA1\x54\xB1\x5E\x89\xAE\x86\xc6\x94\x22\xfe\x48\xe6\x57\x4e", 16);
|
||||
uint8_t code[16];
|
||||
DSM_read_code(code,0,8,8);
|
||||
CYRF_ConfigDataCode(code, 16);
|
||||
DSM_build_bind_packet();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DSM_cyrf_configdata()
|
||||
{
|
||||
for(uint8_t i = 0; i < sizeof(DSM_data_vals) / 2; i++)
|
||||
CYRF_WriteRegister(pgm_read_byte_near(&DSM_data_vals[i][0]), pgm_read_byte_near(&DSM_data_vals[i][1]));
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DSM_update_channels()
|
||||
{
|
||||
prev_option=option;
|
||||
if(sub_protocol==DSM_AUTO)
|
||||
num_ch=12; // Force 12 channels in mode Auto
|
||||
else
|
||||
num_ch=option & 0x7F; // Remove the Max Throw flag
|
||||
if(num_ch<4 || num_ch>12)
|
||||
num_ch=option & 0x0F; // Remove flags 0x80=max_throw, 0x40=11ms
|
||||
|
||||
if(num_ch<3 || num_ch>12)
|
||||
num_ch=6; // Default to 6 channels if invalid choice...
|
||||
|
||||
// Create channel map based on number of channels and refresh rate
|
||||
uint8_t idx=num_ch-4;
|
||||
if(num_ch>7 && num_ch<11 && (sub_protocol==DSM2_11 || sub_protocol==DSMX_11))
|
||||
idx+=5; // In 11ms mode change index only for channels 8..10
|
||||
uint8_t idx=num_ch-3;
|
||||
if((option & 0x40) && num_ch>7 && num_ch<12)
|
||||
idx+=5; // In 11ms mode change index only for channels 8..11
|
||||
for(uint8_t i=0;i<14;i++)
|
||||
ch_map[i]=pgm_read_byte_near(&DSM_ch_map_progmem[idx][i]);
|
||||
}
|
||||
@@ -250,24 +142,27 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
|
||||
DSM_update_channels();
|
||||
|
||||
if (sub_protocol==DSMX_11 || sub_protocol==DSMX_22 )
|
||||
{
|
||||
{//DSMX
|
||||
packet[0] = cyrfmfg_id[2];
|
||||
packet[1] = cyrfmfg_id[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
{//DSM2
|
||||
packet[0] = (0xff ^ cyrfmfg_id[2]);
|
||||
packet[1] = (0xff ^ cyrfmfg_id[3]);
|
||||
if(sub_protocol==DSM2_22)
|
||||
bits=10; // Only DSM_22 is using a resolution of 1024
|
||||
bits=10; // Only DSM2_22 is using a resolution of 1024
|
||||
}
|
||||
|
||||
#ifdef DSM_THROTTLE_KILL_CH
|
||||
uint16_t kill_ch=Channel_data[DSM_THROTTLE_KILL_CH-1];
|
||||
#endif
|
||||
for (uint8_t i = 0; i < 7; i++)
|
||||
{
|
||||
uint8_t idx = ch_map[(upper?7:0) + i]; // 1,5,2,3,0,4
|
||||
uint16_t value = 0xffff;;
|
||||
uint16_t value = 0xffff;
|
||||
if((option&0x40) == 0 && num_ch < 8 && upper)
|
||||
idx=0xff; // in 22ms do not transmit upper channels if <8, is it the right method???
|
||||
if (idx != 0xff)
|
||||
{
|
||||
/* Spektrum own remotes transmit normal values during bind and actually use this (e.g. Nano CP X) to
|
||||
@@ -289,7 +184,7 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
|
||||
if(option & 0x80)
|
||||
value=Channel_data[CH_TAER[idx]]; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX
|
||||
else
|
||||
value=convert_channel_16b_nolimit(CH_TAER[idx],0x150,0x6B0); // -100%..+100% => 1100..1900us and -125%..+125% => 1000..2000us based on Redcon 6 channel DSM2 RX
|
||||
value=convert_channel_16b_nolimit(CH_TAER[idx],0x156,0x6AA); // -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);
|
||||
@@ -297,66 +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;
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DSM_set_sop_data_crc()
|
||||
#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++)
|
||||
{
|
||||
//The crc for channel '1' is NOT(mfgid[0] << 8 + mfgid[1])
|
||||
//The crc for channel '2' is (mfgid[0] << 8 + mfgid[1])
|
||||
uint16_t crc = (cyrfmfg_id[0] << 8) + cyrfmfg_id[1];
|
||||
if(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B)
|
||||
CYRF_ConfigCRCSeed(crc); //CH2
|
||||
else
|
||||
CYRF_ConfigCRCSeed(~crc); //CH1
|
||||
|
||||
uint8_t pn_row = DSM_get_pn_row(hopping_frequency[hopping_frequency_no]);
|
||||
uint8_t code[16];
|
||||
DSM_read_code(code,pn_row,sop_col,8); // pn_row between 0 and 4, sop_col between 1 and 7
|
||||
CYRF_ConfigSOPCode(code);
|
||||
DSM_read_code(code,pn_row,7 - sop_col,8); // 7-sop_col between 0 and 6
|
||||
DSM_read_code(code+8,pn_row,7 - sop_col + 1,8); // 7-sop_col+1 between 1 and 7
|
||||
CYRF_ConfigDataCode(code, 16);
|
||||
|
||||
CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]);
|
||||
hopping_frequency_no++;
|
||||
if(sub_protocol == DSMX_11 || sub_protocol == DSMX_22)
|
||||
hopping_frequency_no %=23;
|
||||
else
|
||||
hopping_frequency_no %=2;
|
||||
packet[i*2+4]=0x70+i;
|
||||
packet[i*2+5]=DSM_SerialRX_val[i+1];
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DSM_calc_dsmx_channel()
|
||||
{
|
||||
uint8_t idx = 0;
|
||||
uint32_t id = ~(((uint32_t)cyrfmfg_id[0] << 24) | ((uint32_t)cyrfmfg_id[1] << 16) | ((uint32_t)cyrfmfg_id[2] << 8) | (cyrfmfg_id[3] << 0));
|
||||
uint32_t id_tmp = id;
|
||||
while(idx < 23)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t count_3_27 = 0, count_28_51 = 0, count_52_76 = 0;
|
||||
id_tmp = id_tmp * 0x0019660D + 0x3C6EF35F; // Randomization
|
||||
uint8_t next_ch = ((id_tmp >> 8) % 0x49) + 3; // Use least-significant byte and must be larger than 3
|
||||
if ( (next_ch ^ cyrfmfg_id[3]) & 0x01 )
|
||||
continue;
|
||||
for (i = 0; i < idx; i++)
|
||||
{
|
||||
if(hopping_frequency[i] == next_ch)
|
||||
break;
|
||||
if(hopping_frequency[i] <= 27)
|
||||
count_3_27++;
|
||||
else
|
||||
if (hopping_frequency[i] <= 51)
|
||||
count_28_51++;
|
||||
else
|
||||
count_52_76++;
|
||||
}
|
||||
if (i != idx)
|
||||
continue;
|
||||
if ((next_ch < 28 && count_3_27 < 8)
|
||||
||(next_ch >= 28 && next_ch < 52 && count_28_51 < 7)
|
||||
||(next_ch >= 52 && count_52_76 < 8))
|
||||
hopping_frequency[idx++] = next_ch;
|
||||
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()
|
||||
@@ -391,6 +243,11 @@ uint16_t ReadDsm()
|
||||
#endif
|
||||
uint8_t start;
|
||||
|
||||
#ifdef DSM_GR300
|
||||
uint16_t timing=5000+(convert_channel_8b(CH13)*100);
|
||||
debugln("T=%u",timing);
|
||||
#endif
|
||||
|
||||
switch(phase)
|
||||
{
|
||||
case DSM_BIND_WRITE:
|
||||
@@ -405,7 +262,7 @@ uint16_t ReadDsm()
|
||||
#if defined DSM_TELEMETRY
|
||||
case DSM_BIND_CHECK:
|
||||
//64 SDR Mode is configured so only the 8 first values are needed but we need to write 16 values...
|
||||
CYRF_ConfigDataCode((const uint8_t *)"\x98\x88\x1B\xE4\x30\x79\x03\x84\xC9\x2C\x06\x93\x86\xB9\x9E\xD7", 16);
|
||||
CYRF_ConfigDataCode((const uint8_t *)"\x98\x88\x1B\xE4\x30\x79\x03\x84", 16);
|
||||
CYRF_SetTxRxMode(RX_EN); //Receive mode
|
||||
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //Prepare to receive
|
||||
bind_counter=2*DSM_BIND_COUNT; //Timeout of 4.2s if no packet received
|
||||
@@ -418,19 +275,30 @@ uint16_t ReadDsm()
|
||||
rx_phase |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
|
||||
if((rx_phase & 0x07) == 0x02)
|
||||
{ // data received with no errors
|
||||
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read
|
||||
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
|
||||
if(len>TELEMETRY_BUFFER_SIZE-2)
|
||||
len=TELEMETRY_BUFFER_SIZE-2;
|
||||
CYRF_ReadDataPacketLen(packet_in+1, len);
|
||||
if(len==10 && DSM_Check_RX_packet())
|
||||
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80);// Need to set RXOW before data read
|
||||
if(CYRF_ReadRegister(CYRF_09_RX_COUNT)==10) // Len
|
||||
{
|
||||
CYRF_ReadDataPacketLen(packet_in+1, 10);
|
||||
if(DSM_Check_RX_packet())
|
||||
{
|
||||
debug("Bind");
|
||||
for(uint8_t i=0;i<10;i++)
|
||||
debug(" %02X",packet_in[i+1]);
|
||||
debugln("");
|
||||
packet_in[0]=0x80;
|
||||
telemetry_link=1; // send received data on serial
|
||||
packet_in[6]&=0x0F; // It looks like there is a flag 0x40 being added by some receivers
|
||||
if(packet_in[6]>12) packet_in[6]=12;
|
||||
else if(packet_in[6]<3) packet_in[6]=6;
|
||||
telemetry_link=1; // Send received data on serial
|
||||
phase++;
|
||||
return 2000;
|
||||
}
|
||||
}
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
|
||||
CYRF_SetTxRxMode(RX_EN); // Force end state read
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX operation
|
||||
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x83); // Prepare to receive
|
||||
}
|
||||
else
|
||||
if((rx_phase & 0x02) != 0x02)
|
||||
{ // data received with errors
|
||||
@@ -452,18 +320,23 @@ uint16_t ReadDsm()
|
||||
CYRF_SetTxRxMode(TX_EN);
|
||||
hopping_frequency_no = 0;
|
||||
phase = DSM_CH1_WRITE_A; // in fact phase++
|
||||
DSM_set_sop_data_crc();
|
||||
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11||sub_protocol==DSMX_22);
|
||||
return 10000;
|
||||
case DSM_CH1_WRITE_A:
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(11000); // Always request 11ms spacing even if we don't use half of it in 22ms mode
|
||||
#endif
|
||||
case DSM_CH1_WRITE_B:
|
||||
DSM_build_data_packet(phase == DSM_CH1_WRITE_B); // build lower or upper channels
|
||||
case DSM_CH2_WRITE_A:
|
||||
case DSM_CH2_WRITE_B:
|
||||
DSM_build_data_packet(phase == DSM_CH1_WRITE_B||phase == DSM_CH2_WRITE_B); // build lower or upper channels
|
||||
CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS); // clear IRQ flags
|
||||
CYRF_WriteDataPacket(packet);
|
||||
#if 0
|
||||
for(uint8_t i=0;i<16;i++)
|
||||
debug(" %02X", packet[i]);
|
||||
debugln("");
|
||||
#endif
|
||||
phase++; // change from WRITE to CHECK mode
|
||||
return DSM_WRITE_DELAY;
|
||||
case DSM_CH1_CHECK_A:
|
||||
@@ -487,7 +360,7 @@ uint16_t ReadDsm()
|
||||
CYRF_SetTxRxMode(TX_EN);
|
||||
}
|
||||
#endif
|
||||
DSM_set_sop_data_crc();
|
||||
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11 || sub_protocol==DSMX_22);
|
||||
phase++; // change from CH1_CHECK to CH2_WRITE
|
||||
return DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY;
|
||||
}
|
||||
@@ -497,6 +370,10 @@ uint16_t ReadDsm()
|
||||
phase++; // change from CH2_CHECK to CH2_READ
|
||||
CYRF_SetTxRxMode(RX_EN); //Receive mode
|
||||
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //0x80??? //Prepare to receive
|
||||
#ifdef DSM_GR300
|
||||
if(num_ch==3)
|
||||
return timing - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY;
|
||||
#endif
|
||||
return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY - DSM_READ_DELAY;
|
||||
case DSM_CH2_READ_A:
|
||||
case DSM_CH2_READ_B:
|
||||
@@ -511,6 +388,15 @@ uint16_t ReadDsm()
|
||||
if(len>TELEMETRY_BUFFER_SIZE-2)
|
||||
len=TELEMETRY_BUFFER_SIZE-2;
|
||||
CYRF_ReadDataPacketLen(packet_in+1, len);
|
||||
#ifdef DSM_DEBUG_FWD_PGM
|
||||
//debug(" %02X", packet_in[1]);
|
||||
if(packet_in[1]==9)
|
||||
{
|
||||
for(uint8_t i=0;i<len;i++)
|
||||
debug(" %02X", packet_in[i+1]);
|
||||
debugln("");
|
||||
}
|
||||
#endif
|
||||
packet_in[0]=CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;// store RSSI of the received telemetry signal
|
||||
telemetry_link=1;
|
||||
}
|
||||
@@ -521,6 +407,10 @@ uint16_t ReadDsm()
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX operation
|
||||
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //0x80??? //Prepare to receive
|
||||
phase = DSM_CH2_READ_B;
|
||||
#ifdef DSM_GR300
|
||||
if(num_ch==3)
|
||||
return timing;
|
||||
#endif
|
||||
return 11000;
|
||||
}
|
||||
if (phase == DSM_CH2_READ_A)
|
||||
@@ -529,11 +419,11 @@ uint16_t ReadDsm()
|
||||
phase = DSM_CH1_WRITE_A; //Transmit lower
|
||||
CYRF_SetTxRxMode(TX_EN); //TX mode
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); //Clear abort RX operation
|
||||
DSM_set_sop_data_crc();
|
||||
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11||sub_protocol==DSMX_22);
|
||||
return DSM_READ_DELAY;
|
||||
#else
|
||||
// No telemetry
|
||||
DSM_set_sop_data_crc();
|
||||
DSM_set_sop_data_crc(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B, sub_protocol==DSMX_11||sub_protocol==DSMX_22);
|
||||
if (phase == DSM_CH2_CHECK_A)
|
||||
{
|
||||
if(num_ch > 7 || sub_protocol==DSM2_11 || sub_protocol==DSMX_11)
|
||||
@@ -541,11 +431,19 @@ uint16_t ReadDsm()
|
||||
else
|
||||
{ //Normal mode 22ms
|
||||
phase = DSM_CH1_WRITE_A; // change from CH2_CHECK_A to CH1_WRITE_A (ie no upper)
|
||||
#ifdef DSM_GR300
|
||||
if(num_ch==3)
|
||||
return timing - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
|
||||
#endif
|
||||
return 22000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
|
||||
}
|
||||
}
|
||||
else
|
||||
phase = DSM_CH1_WRITE_A; // change from CH2_CHECK_B to CH1_WRITE_A (upper already transmitted so transmit lower)
|
||||
#ifdef DSM_GR300
|
||||
if(num_ch==3)
|
||||
return timing - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY ;
|
||||
#endif
|
||||
return 11000 - DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY;
|
||||
#endif
|
||||
}
|
||||
@@ -565,6 +463,8 @@ uint16_t initDsm()
|
||||
cyrfmfg_id[rx_tx_addr[0]%3]^=0x01; //Change a bit so sop_col will be different from 0
|
||||
sop_col = (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + 2) & 0x07;
|
||||
}
|
||||
//Calc CRC seed
|
||||
seed = (cyrfmfg_id[0] << 8) + cyrfmfg_id[1];
|
||||
//Hopping frequencies
|
||||
if (sub_protocol == DSMX_11 || sub_protocol == DSMX_22)
|
||||
DSM_calc_dsmx_channel();
|
||||
|
||||
@@ -162,6 +162,33 @@ static void __attribute__((unused)) DEVO_build_data_pkt()
|
||||
DEVO_add_pkt_suffix();
|
||||
}
|
||||
|
||||
#if defined DEVO_HUB_TELEMETRY
|
||||
static void __attribute__((unused)) DEVO_parse_telemetry_packet()
|
||||
{
|
||||
DEVO_scramble_pkt(); //This will unscramble the packet
|
||||
|
||||
debugln("RX");
|
||||
if ((((uint32_t)packet[15] << 16) | ((uint32_t)packet[14] << 8) | packet[13]) != (MProtocol_id & 0x00ffffff))
|
||||
return; // ID does not match
|
||||
|
||||
//RSSI
|
||||
TX_RSSI = CYRF_ReadRegister(CYRF_13_RSSI) & 0x1F;
|
||||
TX_RSSI = (TX_RSSI << 1) + TX_RSSI;
|
||||
RX_RSSI = TX_RSSI;
|
||||
telemetry_link = 1;
|
||||
|
||||
//TODO: FW telemetry https://github.com/DeviationTX/deviation/blob/5efb6a28bea697af9a61b5a0ed2528cc8d203f90/src/protocol/devo_cyrf6936.c#L232
|
||||
|
||||
debug("P[0]=%02X",packet[0]);
|
||||
|
||||
if (packet[0] == 0x30) // Volt packet
|
||||
{
|
||||
v_lipo1 = packet[1] << 1;
|
||||
v_lipo2 = packet[3] << 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void __attribute__((unused)) DEVO_cyrf_set_bound_sop_code()
|
||||
{
|
||||
/* crc == 0 isn't allowed, so use 1 if the math results in 0 */
|
||||
@@ -270,6 +297,82 @@ static void __attribute__((unused)) DEVO_BuildPacket()
|
||||
uint16_t devo_callback()
|
||||
{
|
||||
static uint8_t txState=0;
|
||||
|
||||
#if defined DEVO_HUB_TELEMETRY
|
||||
int delay;
|
||||
|
||||
if (txState == 0)
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(2400);
|
||||
#endif
|
||||
DEVO_BuildPacket();
|
||||
CYRF_WriteDataPacket(packet);
|
||||
txState = 1;
|
||||
return 900;
|
||||
}
|
||||
if (txState == 1)
|
||||
{
|
||||
int i = 0;
|
||||
uint8_t reg;
|
||||
while (! ((reg = CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS)) & 0x02))
|
||||
{
|
||||
if (++i >= DEVO_NUM_WAIT_LOOPS)
|
||||
break;
|
||||
}
|
||||
if (((reg & 0x22) == 0x20) || (CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80))
|
||||
{
|
||||
CYRF_Reset();
|
||||
DEVO_cyrf_init();
|
||||
DEVO_cyrf_set_bound_sop_code();
|
||||
CYRF_ConfigRFChannel(*hopping_frequency_ptr);
|
||||
//printf("Rst CYRF\n");
|
||||
delay = 1500;
|
||||
txState = 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (phase == DEVO_BOUND)
|
||||
{
|
||||
/* exit binding state */
|
||||
phase = DEVO_BOUND_3;
|
||||
DEVO_cyrf_set_bound_sop_code();
|
||||
}
|
||||
if((packet_count != 0) && (bind_counter == 0))
|
||||
{
|
||||
CYRF_SetTxRxMode(RX_EN); //Receive mode
|
||||
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //0x80??? //Prepare to receive
|
||||
txState = 2;
|
||||
return 1300;
|
||||
}
|
||||
}
|
||||
if(packet_count == 0)
|
||||
{
|
||||
CYRF_SetPower(0x08); //Keep tx power updated
|
||||
hopping_frequency_ptr = hopping_frequency_ptr == &hopping_frequency[2] ? hopping_frequency : hopping_frequency_ptr + 1;
|
||||
CYRF_ConfigRFChannel(*hopping_frequency_ptr);
|
||||
}
|
||||
delay = 1500;
|
||||
}
|
||||
if(txState == 2)
|
||||
{
|
||||
uint8_t rx_state = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
|
||||
if((rx_state & 0x03) == 0x02)
|
||||
{ // RXC=1, RXE=0 then 2nd check is required (debouncing)
|
||||
rx_state |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
|
||||
}
|
||||
if((rx_state & 0x07) == 0x02)
|
||||
{ // good data (complete with no errors)
|
||||
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read
|
||||
CYRF_ReadDataPacketLen(packet, CYRF_ReadRegister(CYRF_09_RX_COUNT));
|
||||
DEVO_parse_telemetry_packet();
|
||||
}
|
||||
CYRF_SetTxRxMode(TX_EN); //Write mode
|
||||
delay = 200;
|
||||
}
|
||||
txState = 0;
|
||||
return delay;
|
||||
#else
|
||||
if (txState == 0)
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
@@ -298,6 +401,7 @@ uint16_t devo_callback()
|
||||
CYRF_ConfigRFChannel(*hopping_frequency_ptr);
|
||||
}
|
||||
return 1200;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t DevoInit()
|
||||
|
||||
141
Multiprotocol/ESky150v2_cc2500.ino
Normal file
141
Multiprotocol/ESky150v2_cc2500.ino
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(ESKY150V2_CC2500_INO)
|
||||
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
//#define ESKY150V2_FORCE_ID
|
||||
|
||||
#define ESKY150V2_PAYLOADSIZE 40
|
||||
#define ESKY150V2_BINDPAYLOADSIZE 150
|
||||
#define ESKY150V2_NFREQCHANNELS 70
|
||||
#define ESKY150V2_TXID_SIZE 4
|
||||
#define ESKY150V2_BIND_CHANNEL 0x00
|
||||
#define ESKY150V2_PACKET_PERIOD 10000
|
||||
#define ESKY150V2_BINDING_PACKET_PERIOD 57000
|
||||
|
||||
#ifdef ESKY150V2_FORCE_ID
|
||||
const uint8_t PROGMEM ESKY150V2_hop[ESKY150V2_NFREQCHANNELS]= {
|
||||
0x07, 0x47, 0x09, 0x27, 0x0B, 0x42, 0x0D, 0x35, 0x17, 0x40, 0x26, 0x3D, 0x16, 0x43, 0x06, 0x2A, 0x24, 0x44,
|
||||
0x0E, 0x38, 0x20, 0x48, 0x22, 0x2D, 0x2B, 0x39, 0x0F, 0x36, 0x23, 0x46, 0x14, 0x3B, 0x1A, 0x41, 0x10, 0x2E,
|
||||
0x1E, 0x28, 0x0C, 0x49, 0x1D, 0x3E, 0x29, 0x2C, 0x25, 0x30, 0x1C, 0x2F, 0x1B, 0x33, 0x13, 0x31, 0x0A, 0x37,
|
||||
0x12, 0x3C, 0x18, 0x4B, 0x11, 0x45, 0x21, 0x4A, 0x1F, 0x3F, 0x15, 0x32, 0x08, 0x3A, 0x19, 0x34 };
|
||||
/*const uint8_t PROGMEM ESKY150V2_hop2[40]= {
|
||||
0x19, 0x23, 0x13, 0x1B, 0x09, 0x22, 0x14, 0x27, 0x06, 0x26, 0x16, 0x24, 0x0B, 0x2A, 0x0E, 0x1C, 0x11, 0x1E,
|
||||
0x08, 0x29, 0x0D, 0x28, 0x18, 0x2D, 0x12, 0x20, 0x0C, 0x1A, 0x10, 0x1D, 0x07, 0x2C, 0x0A, 0x2B, 0x0F, 0x25,
|
||||
0x15, 0x1F, 0x17, 0x21 };*/
|
||||
#endif
|
||||
|
||||
static void __attribute__((unused)) ESKY150V2_set_freq(void)
|
||||
{
|
||||
calc_fh_channels(ESKY150V2_NFREQCHANNELS);
|
||||
|
||||
#ifdef ESKY150V2_FORCE_ID
|
||||
for(uint8_t i=0; i<ESKY150V2_NFREQCHANNELS; i++)
|
||||
hopping_frequency[i]=pgm_read_byte_near( &ESKY150V2_hop[i] );
|
||||
#endif
|
||||
|
||||
//Bind channel
|
||||
hopping_frequency[ESKY150V2_NFREQCHANNELS]=ESKY150V2_BIND_CHANNEL;
|
||||
|
||||
//Calib all channels
|
||||
NRF250K_SetFreqOffset(); // Set frequency offset
|
||||
NRF250K_HoppingCalib(ESKY150V2_NFREQCHANNELS+1);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) ESKY150V2_send_packet()
|
||||
{
|
||||
NRF250K_SetFreqOffset(); // Set frequency offset
|
||||
NRF250K_Hopping(hopping_frequency_no);
|
||||
if (++hopping_frequency_no >= ESKY150V2_NFREQCHANNELS)
|
||||
hopping_frequency_no = 0;
|
||||
NRF250K_SetPower(); //Set power level
|
||||
|
||||
packet[0] = 0xFA; // Unknown
|
||||
packet[1] = 0x41; // Unknown
|
||||
packet[2] = 0x08; // Unknown
|
||||
packet[3] = 0x00; // Unknown
|
||||
for(uint8_t i=0;i<16;i++)
|
||||
{
|
||||
uint16_t channel=convert_channel_16b_limit(CH_TAER[i],200,1000);
|
||||
packet[4+2*i] = channel;
|
||||
packet[5+2*i] = channel>>8;
|
||||
}
|
||||
NRF250K_WritePayload(packet, ESKY150V2_PAYLOADSIZE);
|
||||
}
|
||||
|
||||
uint16_t ESKY150V2_callback()
|
||||
{
|
||||
if(option==0) option=1; //Trick the RF component auto select system
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(ESKY150V2_PACKET_PERIOD);
|
||||
#endif
|
||||
ESKY150V2_send_packet();
|
||||
}
|
||||
else
|
||||
{
|
||||
BIND_DONE; //Need full power for bind to work...
|
||||
NRF250K_SetPower(); //Set power level
|
||||
BIND_IN_PROGRESS;
|
||||
NRF250K_WritePayload(packet, ESKY150V2_BINDPAYLOADSIZE);
|
||||
if (--bind_counter == 0)
|
||||
{
|
||||
BIND_DONE;
|
||||
// Change TX address from bind to normal mode
|
||||
NRF250K_SetTXAddr(rx_tx_addr, ESKY150V2_TXID_SIZE);
|
||||
memset(packet,0x00,ESKY150V2_PAYLOADSIZE);
|
||||
}
|
||||
return 30000; //ESKY150V2_BINDING_PACKET_PERIOD;
|
||||
}
|
||||
return ESKY150V2_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initESKY150V2()
|
||||
{
|
||||
if(option==0) option=1; // Trick the RF component auto select system
|
||||
NRF250K_Init();
|
||||
ESKY150V2_set_freq();
|
||||
hopping_frequency_no = 0;
|
||||
|
||||
#ifdef ESKY150V2_FORCE_ID // ID taken from TX dump
|
||||
rx_tx_addr[0]=0x87;rx_tx_addr[1]=0x5B;rx_tx_addr[2]=0x2C;rx_tx_addr[3]=0x5D;
|
||||
#endif
|
||||
|
||||
memset(packet,0x00,ESKY150V2_BINDPAYLOADSIZE);
|
||||
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
NRF250K_SetTXAddr((uint8_t *)"\x73\x73\x74\x63", ESKY150V2_TXID_SIZE); //Bind address
|
||||
NRF250K_Hopping(ESKY150V2_NFREQCHANNELS); //Bind channel
|
||||
memcpy(packet,"\x73\x73\x74\x63", ESKY150V2_TXID_SIZE);
|
||||
memcpy(&packet[ESKY150V2_TXID_SIZE],rx_tx_addr, ESKY150V2_TXID_SIZE);
|
||||
packet[8]=0x41; //Unknown
|
||||
packet[9]=0x88; //Unknown
|
||||
packet[10]=0x41; //Unknown
|
||||
memset(&packet[11],0xAA,4); //Unknown
|
||||
memcpy(&packet[15],hopping_frequency,ESKY150V2_NFREQCHANNELS); // hop table
|
||||
//for(uint8_t i=0; i<40; i++) // Does not seem to be needed
|
||||
// packet[i+85]=pgm_read_byte_near( &ESKY150V2_hop2[i] );
|
||||
bind_counter=100;
|
||||
}
|
||||
else
|
||||
NRF250K_SetTXAddr(rx_tx_addr, ESKY150V2_TXID_SIZE);
|
||||
return 50000;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -18,8 +18,13 @@
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
//#define ESKY_ET4_FORCE_ID
|
||||
|
||||
#define ESKY_BIND_COUNT 1000
|
||||
#define ESKY_PACKET_PERIOD 3333
|
||||
#define ESKY_STD_PACKET_PERIOD 3333
|
||||
#define ESKY_ET4_PACKET_PERIOD 1190
|
||||
#define ESKY_ET4_TOTAL_PACKET_PERIOD 20300
|
||||
#define ESKY_ET4_BIND_PACKET_PERIOD 5000
|
||||
#define ESKY_PAYLOAD_SIZE 13
|
||||
#define ESKY_PACKET_CHKTIME 100 // Time to wait for packet to be sent (no ACK, so very short)
|
||||
|
||||
@@ -63,7 +68,8 @@ static void __attribute__((unused)) ESKY_init()
|
||||
static void __attribute__((unused)) ESKY_init2()
|
||||
{
|
||||
NRF24L01_FlushTx();
|
||||
hopping_frequency_no = 0;
|
||||
if(sub_protocol==ESKY_STD)
|
||||
{
|
||||
uint16_t channel_ord = rx_tx_addr[0] % 74;
|
||||
hopping_frequency[12] = 10 + (uint8_t)channel_ord; //channel_code
|
||||
uint8_t channel1, channel2;
|
||||
@@ -84,6 +90,14 @@ static void __attribute__((unused)) ESKY_init2()
|
||||
hopping_frequency[9] = 6;
|
||||
hopping_frequency[10] = channel1*2;
|
||||
hopping_frequency[11] = channel2*2;
|
||||
}
|
||||
else
|
||||
{ // ESKY_ET4
|
||||
hopping_frequency[0] = 0x29; //41
|
||||
hopping_frequency[1] = 0x12; //18
|
||||
hopping_frequency[6] = 0x87; //135 payload end byte
|
||||
hopping_frequency[12] = 0x84; //132 indicates which channels to use
|
||||
}
|
||||
|
||||
// Turn radio power on
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
@@ -111,20 +125,32 @@ static void __attribute__((unused)) ESKY_send_packet(uint8_t bind)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Regular packet
|
||||
// Each data packet is repeated 3 times on one channel, and 3 times on another channel
|
||||
// For arithmetic simplicity, channels are repeated in rf_channels array
|
||||
if (hopping_frequency_no == 0)
|
||||
if (packet_count == 0)
|
||||
for (uint8_t i = 0; i < 6; i++)
|
||||
{
|
||||
uint16_t val=convert_channel_ppm(CH_AETR[i]);
|
||||
packet[i*2] = val>>8; //high byte of servo timing(1000-2000us)
|
||||
packet[i*2+1] = val&0xFF; //low byte of servo timing(1000-2000us)
|
||||
}
|
||||
rf_ch = hopping_frequency[hopping_frequency_no];
|
||||
packet[12] = hopping_frequency[hopping_frequency_no+6]; // end_bytes
|
||||
hopping_frequency_no++;
|
||||
if (hopping_frequency_no > 6) hopping_frequency_no = 0;
|
||||
if(sub_protocol==ESKY_STD)
|
||||
{
|
||||
// Regular packet
|
||||
// Each data packet is repeated 3 times on one channel, and 3 times on another channel
|
||||
// For arithmetic simplicity, channels are repeated in rf_channels array
|
||||
rf_ch = hopping_frequency[packet_count];
|
||||
packet[12] = hopping_frequency[packet_count+6]; // end_bytes
|
||||
packet_count++;
|
||||
if (packet_count > 6) packet_count = 0;
|
||||
}
|
||||
else
|
||||
{ // ESKY_ET4
|
||||
// Regular packet
|
||||
// Each data packet is repeated 14 times alternating between 2 channels
|
||||
rf_ch = hopping_frequency[packet_count&1];
|
||||
packet_count++;
|
||||
if(packet_count>14) packet_count=0;
|
||||
packet[12] = hopping_frequency[6]; // end_byte
|
||||
}
|
||||
}
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch);
|
||||
NRF24L01_FlushTx();
|
||||
@@ -137,9 +163,17 @@ uint16_t ESKY_callback()
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(ESKY_PACKET_PERIOD);
|
||||
if(packet_count==0)
|
||||
telemetry_set_input_sync(sub_protocol==ESKY_STD?ESKY_STD_PACKET_PERIOD*6:ESKY_ET4_TOTAL_PACKET_PERIOD);
|
||||
#endif
|
||||
ESKY_send_packet(0);
|
||||
if(sub_protocol==ESKY_ET4)
|
||||
{
|
||||
if(packet_count==0)
|
||||
return ESKY_ET4_TOTAL_PACKET_PERIOD-ESKY_ET4_PACKET_PERIOD*13;
|
||||
else
|
||||
return ESKY_ET4_PACKET_PERIOD;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -150,16 +184,25 @@ uint16_t ESKY_callback()
|
||||
BIND_DONE;
|
||||
}
|
||||
}
|
||||
return ESKY_PACKET_PERIOD;
|
||||
return ESKY_STD_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initESKY(void)
|
||||
{
|
||||
bind_counter = ESKY_BIND_COUNT;
|
||||
rx_tx_addr[2] = rx_tx_addr[3]; // Model match
|
||||
#ifdef ESKY_ET4_FORCE_ID
|
||||
if(sub_protocol==ESKY_ET4)
|
||||
{
|
||||
rx_tx_addr[0]=0x72;
|
||||
rx_tx_addr[1]=0xBB;
|
||||
rx_tx_addr[2]=0xCC;
|
||||
}
|
||||
#endif
|
||||
rx_tx_addr[3] = 0xBB;
|
||||
ESKY_init();
|
||||
ESKY_init2();
|
||||
packet_count=0;
|
||||
return 50000;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,12 @@
|
||||
/** FrSky D and X routines **/
|
||||
/******************************/
|
||||
|
||||
#if defined(FRSKYX_CC2500_INO) || defined(FRSKY_RX_CC2500_INO)
|
||||
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO) || defined(FRSKY_RX_CC2500_INO) || defined(FRSKYR9_SX1276_INO)
|
||||
uint8_t FrSkyFormat=0;
|
||||
uint8_t FrSkyX_chanskip;
|
||||
#endif
|
||||
|
||||
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO) || defined(FRSKY_RX_CC2500_INO) || defined(FRSKYR9_SX1276_INO)
|
||||
//**CRC**
|
||||
const uint16_t PROGMEM FrSkyX_CRC_Short[]={
|
||||
0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
|
||||
@@ -29,17 +34,84 @@ static uint16_t __attribute__((unused)) FrSkyX_CRCTable(uint8_t val)
|
||||
val /= 16 ;
|
||||
return word ^ (0x1081 * val) ;
|
||||
}
|
||||
uint16_t FrSkyX_crc(uint8_t *data, uint8_t len)
|
||||
uint16_t FrSkyX_crc(uint8_t *data, uint8_t len, uint16_t init=0)
|
||||
{
|
||||
uint16_t crc = 0;
|
||||
uint16_t crc = init;
|
||||
for(uint8_t i=0; i < len; i++)
|
||||
crc = (crc<<8) ^ FrSkyX_CRCTable((uint8_t)(crc>>8) ^ *data++);
|
||||
return crc;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYR9_SX1276_INO)
|
||||
static void __attribute__((unused)) FrSkyX_channels(uint8_t offset)
|
||||
{
|
||||
static uint8_t chan_start=0;
|
||||
|
||||
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO)
|
||||
//packet[7] = FLAGS 00 - standard packet
|
||||
//10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
|
||||
//20 - range check packet
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
#define FRSKYX_FAILSAFE_TIMEOUT 1032
|
||||
static uint16_t failsafe_count=0;
|
||||
static uint8_t FS_flag=0,failsafe_chan=0;
|
||||
if (FS_flag == 0 && failsafe_count > FRSKYX_FAILSAFE_TIMEOUT && chan_start == 0 && IS_FAILSAFE_VALUES_on)
|
||||
{
|
||||
FS_flag = 0x10;
|
||||
failsafe_chan = 0;
|
||||
} else if (FS_flag & 0x10 && failsafe_chan < (FrSkyFormat & 0x01 ? 8-1:16-1))
|
||||
{
|
||||
FS_flag = 0x10 | ((FS_flag + 2) & 0x0F); //10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
|
||||
failsafe_chan ++;
|
||||
} else if (FS_flag & 0x10)
|
||||
{
|
||||
FS_flag = 0;
|
||||
failsafe_count = 0;
|
||||
FAILSAFE_VALUES_off;
|
||||
}
|
||||
failsafe_count++;
|
||||
if(protocol==PROTO_FRSKY_R9)
|
||||
failsafe_count++; // R9 is 20ms, X is 9ms
|
||||
packet[offset] = FS_flag;
|
||||
#else
|
||||
packet[offset] = 0;
|
||||
#endif
|
||||
//
|
||||
packet[offset+1] = 0; //??
|
||||
//
|
||||
uint8_t chan_index = chan_start;
|
||||
uint16_t ch1,ch2;
|
||||
for(uint8_t i = offset+2; i < 12+offset+2 ; i+=3)
|
||||
{//12 bytes of channel data
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
if( (FS_flag & 0x10) && ((failsafe_chan & 0x07) == (chan_index & 0x07)) )
|
||||
ch1 = FrSkyX_scaleForPXX_FS(failsafe_chan);
|
||||
else
|
||||
#endif
|
||||
ch1 = FrSkyX_scaleForPXX(chan_index);
|
||||
chan_index++;
|
||||
//
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
if( (FS_flag & 0x10) && ((failsafe_chan & 0x07) == (chan_index & 0x07)) )
|
||||
ch2 = FrSkyX_scaleForPXX_FS(failsafe_chan);
|
||||
else
|
||||
#endif
|
||||
ch2 = FrSkyX_scaleForPXX(chan_index);
|
||||
chan_index++;
|
||||
//3 bytes per channel
|
||||
packet[i] = ch1;
|
||||
packet[i+1]=(((ch1>>8) & 0x0F)|(ch2 << 4));
|
||||
packet[i+2]=ch2>>4;
|
||||
}
|
||||
if(FrSkyFormat & 0x01) //In X8 mode send only 8ch every 9ms
|
||||
chan_start = 0 ;
|
||||
else
|
||||
chan_start^=0x08;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO) || defined(FRSKY_RX_CC2500_INO)
|
||||
enum {
|
||||
FRSKY_BIND = 0,
|
||||
FRSKY_BIND_DONE = 1000,
|
||||
@@ -70,11 +142,79 @@ void Frsky_init_hop(void)
|
||||
hopping_frequency[i]=i>46?0:val;
|
||||
}
|
||||
}
|
||||
|
||||
void FrSkyX2_init_hop(void)
|
||||
{
|
||||
uint16_t id=(rx_tx_addr[2]<<8) + rx_tx_addr[3];
|
||||
//Increment
|
||||
uint8_t inc = (id % 46) + 1;
|
||||
if( inc == 12 || inc ==35 ) inc++; //Exception list from dumps
|
||||
//Start offset
|
||||
uint8_t offset = id % 5;
|
||||
|
||||
debug("hop: ");
|
||||
uint8_t channel;
|
||||
for(uint8_t i=0; i<47; i++)
|
||||
{
|
||||
channel = 5 * (uint16_t(inc * i) % 47) + offset;
|
||||
//Exception list from dumps
|
||||
if(FrSkyFormat & 2 )// LBT or FCC
|
||||
{//LBT
|
||||
if( channel <=1 || channel == 43 || channel == 44 || channel == 87 || channel == 88 || channel == 129 || channel == 130 || channel == 173 || channel == 174)
|
||||
channel += 2;
|
||||
else if( channel == 216 || channel == 217 || channel == 218)
|
||||
channel += 3;
|
||||
}
|
||||
else //FCC
|
||||
if ( channel == 3 || channel == 4 || channel == 46 || channel == 47 || channel == 90 || channel == 91 || channel == 133 || channel == 134 || channel == 176 || channel == 177 || channel == 220 || channel == 221 )
|
||||
channel += 2;
|
||||
//Store
|
||||
hopping_frequency[i] = channel;
|
||||
debug(" %02X",channel);
|
||||
}
|
||||
debugln("");
|
||||
hopping_frequency[47] = 0; //Bind freq
|
||||
}
|
||||
|
||||
void Frsky_init_clone(void)
|
||||
{
|
||||
debugln("Clone mode");
|
||||
uint16_t temp = FRSKYD_CLONE_EEPROM_OFFSET;
|
||||
if(protocol==PROTO_FRSKYX)
|
||||
temp=FRSKYX_CLONE_EEPROM_OFFSET;
|
||||
else if(protocol==PROTO_FRSKYX2)
|
||||
temp=FRSKYX2_CLONE_EEPROM_OFFSET;
|
||||
FrSkyFormat=eeprom_read_byte((EE_ADDR)temp++);
|
||||
/* FRSKY_RX_D8 =0,
|
||||
FRSKY_RX_D16FCC =1,
|
||||
FRSKY_RX_D16LBT =2,
|
||||
FRSKY_RX_D16v2FCC =3,
|
||||
FRSKY_RX_D16v2LBT =4,*/
|
||||
if(protocol==PROTO_FRSKYX)
|
||||
FrSkyFormat >>= 1;
|
||||
else
|
||||
FrSkyFormat >>= 2;
|
||||
FrSkyFormat <<= 1; //FCC_16/LBT_16
|
||||
if(sub_protocol==XCLONE_8)
|
||||
FrSkyFormat++; //FCC_8/LBT_8
|
||||
rx_tx_addr[3] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
rx_tx_addr[2] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
rx_tx_addr[1] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
memset(hopping_frequency,0x00,50);
|
||||
if(protocol!=PROTO_FRSKYX2)
|
||||
{//D8 and D16v1
|
||||
for (uint8_t ch = 0; ch < 47; ch++)
|
||||
hopping_frequency[ch] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
}
|
||||
else
|
||||
FrSkyX2_init_hop();
|
||||
}
|
||||
|
||||
#endif
|
||||
/******************************/
|
||||
/** FrSky V, D and X routines **/
|
||||
/******************************/
|
||||
#if defined(FRSKYV_CC2500_INO) || defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO)
|
||||
#if defined(FRSKYV_CC2500_INO) || defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO)
|
||||
const PROGMEM uint8_t FRSKY_common_startreg_cc2500_conf[]= {
|
||||
CC2500_02_IOCFG0 ,
|
||||
CC2500_00_IOCFG2 ,
|
||||
@@ -142,16 +282,16 @@ void Frsky_init_hop(void)
|
||||
/*15_DEVIATN*/ 0x42 };
|
||||
#endif
|
||||
|
||||
#if defined(FRSKYX_CC2500_INO)
|
||||
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO)
|
||||
const PROGMEM uint8_t FRSKYX_cc2500_conf[]= {
|
||||
//FRSKYX
|
||||
/*02_IOCFG0*/ 0x06 ,
|
||||
/*00_IOCFG2*/ 0x06 ,
|
||||
/*17_MCSM1*/ 0x0c ,
|
||||
/*17_MCSM1*/ 0x0c , //X2->0x0E -> RX stays in RX and TX stays in TX???
|
||||
/*18_MCSM0*/ 0x18 ,
|
||||
/*06_PKTLEN*/ 0x1E ,
|
||||
/*07_PKTCTRL1*/ 0x04 ,
|
||||
/*08_PKTCTRL0*/ 0x01 ,
|
||||
/*08_PKTCTRL0*/ 0x01 , //X2->0x05 -> CRC enabled
|
||||
/*3E_PATABLE*/ 0xff ,
|
||||
/*0B_FSCTRL1*/ 0x0A ,
|
||||
/*0C_FSCTRL0*/ 0x00 ,
|
||||
@@ -159,7 +299,7 @@ void Frsky_init_hop(void)
|
||||
/*0E_FREQ1*/ 0x76 ,
|
||||
/*0F_FREQ0*/ 0x27 ,
|
||||
/*10_MDMCFG4*/ 0x7B ,
|
||||
/*11_MDMCFG3*/ 0x61 ,
|
||||
/*11_MDMCFG3*/ 0x61 , //X2->0x84 -> bitrate 70K->77K
|
||||
/*12_MDMCFG2*/ 0x13 ,
|
||||
/*13_MDMCFG1*/ 0x23 ,
|
||||
/*14_MDMCFG0*/ 0x7a ,
|
||||
@@ -171,7 +311,7 @@ void Frsky_init_hop(void)
|
||||
/*18_MCSM0*/ 0x18 ,
|
||||
/*06_PKTLEN*/ 0x23 ,
|
||||
/*07_PKTCTRL1*/ 0x04 ,
|
||||
/*08_PKTCTRL0*/ 0x01 ,
|
||||
/*08_PKTCTRL0*/ 0x01 , //X2->0x05 -> CRC enabled
|
||||
/*3E_PATABLE*/ 0xff ,
|
||||
/*0B_FSCTRL1*/ 0x08 ,
|
||||
/*0C_FSCTRL0*/ 0x00 ,
|
||||
@@ -184,6 +324,26 @@ void Frsky_init_hop(void)
|
||||
/*13_MDMCFG1*/ 0x23 ,
|
||||
/*14_MDMCFG0*/ 0x7a ,
|
||||
/*15_DEVIATN*/ 0x53 };
|
||||
const PROGMEM uint8_t FRSKYL_cc2500_conf[]= {
|
||||
/*02_IOCFG0*/ 0x02 ,
|
||||
/*00_IOCFG2*/ 0x02 ,
|
||||
/*17_MCSM1*/ 0x0C ,
|
||||
/*18_MCSM0*/ 0x18 ,
|
||||
/*06_PKTLEN*/ 0xFF ,
|
||||
/*07_PKTCTRL1*/ 0x00 ,
|
||||
/*08_PKTCTRL0*/ 0x02 ,
|
||||
/*3E_PATABLE*/ 0xFE ,
|
||||
/*0B_FSCTRL1*/ 0x0A ,
|
||||
/*0C_FSCTRL0*/ 0x00 ,
|
||||
/*0D_FREQ2*/ 0x5c ,
|
||||
/*0E_FREQ1*/ 0x76 ,
|
||||
/*0F_FREQ0*/ 0x27 ,
|
||||
/*10_MDMCFG4*/ 0x5C ,
|
||||
/*11_MDMCFG3*/ 0x3B ,
|
||||
/*12_MDMCFG2*/ 0x00 ,
|
||||
/*13_MDMCFG1*/ 0x03 ,
|
||||
/*14_MDMCFG0*/ 0x7A ,
|
||||
/*15_DEVIATN*/ 0x47 };
|
||||
#endif
|
||||
|
||||
const PROGMEM uint8_t FRSKY_common_end_cc2500_conf[][2]= {
|
||||
@@ -227,3 +387,160 @@ void Frsky_init_hop(void)
|
||||
CC2500_Strobe(CC2500_SIDLE); // Go to idle...
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYR9_SX1276_INO)
|
||||
uint8_t FrSkyX_TX_Seq, FrSkyX_TX_IN_Seq;
|
||||
uint8_t FrSkyX_RX_Seq ;
|
||||
|
||||
#ifdef SPORT_SEND
|
||||
struct t_FrSkyX_TX_Frame
|
||||
{
|
||||
uint8_t count;
|
||||
uint8_t payload[8];
|
||||
} ;
|
||||
// Store FrskyX telemetry
|
||||
struct t_FrSkyX_TX_Frame FrSkyX_TX_Frames[4] ;
|
||||
#endif
|
||||
|
||||
static void __attribute__((unused)) FrSkyX_seq_sport(uint8_t start, uint8_t end)
|
||||
{
|
||||
for (uint8_t i=start+1;i<=end;i++)
|
||||
packet[i]=0;
|
||||
packet[start] = FrSkyX_RX_Seq << 4; //TX=8 at startup
|
||||
#ifdef SPORT_SEND
|
||||
if (FrSkyX_TX_IN_Seq!=0xFF)
|
||||
{//RX has replied at least once
|
||||
if (FrSkyX_TX_IN_Seq & 0x08)
|
||||
{//Request init
|
||||
//debugln("Init");
|
||||
FrSkyX_TX_Seq = 0 ;
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
FrSkyX_TX_Frames[i].count=0; //Discard frames in current output buffer
|
||||
}
|
||||
else if (FrSkyX_TX_IN_Seq & 0x04)
|
||||
{//Retransmit the requested packet
|
||||
debugln("Retry:%d",FrSkyX_TX_IN_Seq&0x03);
|
||||
packet[start] |= FrSkyX_TX_IN_Seq&0x03;
|
||||
packet[start+1] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq&0x03].count;
|
||||
for (uint8_t i=start+2;i<start+2+FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq&0x03].count;i++)
|
||||
packet[i] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq&0x03].payload[i];
|
||||
}
|
||||
else if ( FrSkyX_TX_Seq != 0x08 )
|
||||
{
|
||||
if(FrSkyX_TX_Seq==FrSkyX_TX_IN_Seq)
|
||||
{//Send packet from the incoming radio buffer
|
||||
//debugln("Send:%d",FrSkyX_TX_Seq);
|
||||
packet[start] |= FrSkyX_TX_Seq;
|
||||
uint8_t nbr_bytes=0;
|
||||
for (uint8_t i=start+2;i<=end;i++)
|
||||
{
|
||||
if(SportHead==SportTail)
|
||||
break; //buffer empty
|
||||
packet[i]=SportData[SportHead];
|
||||
FrSkyX_TX_Frames[FrSkyX_TX_Seq].payload[i-start+2]=SportData[SportHead];
|
||||
SportHead=(SportHead+1) & (MAX_SPORT_BUFFER-1);
|
||||
nbr_bytes++;
|
||||
}
|
||||
packet[start+1]=nbr_bytes;
|
||||
FrSkyX_TX_Frames[FrSkyX_TX_Seq].count=nbr_bytes;
|
||||
if(nbr_bytes)
|
||||
{//Check the buffer status
|
||||
uint8_t used = SportTail;
|
||||
if ( SportHead > SportTail )
|
||||
used += MAX_SPORT_BUFFER - SportHead ;
|
||||
else
|
||||
used -= SportHead ;
|
||||
if ( used < (MAX_SPORT_BUFFER>>1) )
|
||||
{
|
||||
DATA_BUFFER_LOW_off;
|
||||
debugln("Ok buf:%d",used);
|
||||
}
|
||||
}
|
||||
FrSkyX_TX_Seq = ( FrSkyX_TX_Seq + 1 ) & 0x03 ; //Next iteration send next packet
|
||||
}
|
||||
else
|
||||
{//Not in sequence somehow, transmit what the receiver wants but why not asking for retransmit...
|
||||
//debugln("RX_Seq:%d,TX:%d",FrSkyX_TX_IN_Seq,FrSkyX_TX_Seq);
|
||||
packet[start] |= FrSkyX_TX_IN_Seq;
|
||||
packet[start+1] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].count;
|
||||
for (uint8_t i=start+2;i<start+2+FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].count;i++)
|
||||
packet[i] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].payload[i-start+2];
|
||||
}
|
||||
}
|
||||
else
|
||||
packet[start] |= 0x08 ; //FrSkyX_TX_Seq=8 at startup
|
||||
}
|
||||
if(packet[start+1])
|
||||
{//Debug
|
||||
debug("SP: ");
|
||||
for(uint8_t i=0;i<packet[start+1];i++)
|
||||
debug("%02X ",packet[start+2+i]);
|
||||
debugln("");
|
||||
}
|
||||
#else
|
||||
packet[start] |= FrSkyX_TX_Seq ;//TX=8 at startup
|
||||
if ( !(FrSkyX_TX_IN_Seq & 0xF8) )
|
||||
FrSkyX_TX_Seq = ( FrSkyX_TX_Seq + 1 ) & 0x03 ; // Next iteration send next packet
|
||||
#endif // SPORT_SEND
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FrSkyX_telem_init(void)
|
||||
{
|
||||
FrSkyX_TX_Seq = 0x08 ; // Request init
|
||||
#ifdef SPORT_SEND
|
||||
FrSkyX_TX_IN_Seq = 0xFF ; // No sequence received yet
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
FrSkyX_TX_Frames[i].count=0;// discard frames in current output buffer
|
||||
SportHead=SportTail=0; // empty data buffer
|
||||
#endif
|
||||
FrSkyX_RX_Seq = 0 ; // Seq 0 to start with
|
||||
#ifdef TELEMETRY
|
||||
telemetry_lost=1;
|
||||
telemetry_link=0; //Stop sending telemetry
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO)
|
||||
static void __attribute__((unused)) FrSkyX_set_start(uint8_t ch )
|
||||
{
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_WriteReg(CC2500_25_FSCAL1, calData[ch]);
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[ch]);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FrSkyX_init()
|
||||
{
|
||||
if(protocol==PROTO_FRSKYL)
|
||||
FRSKY_init_cc2500(FRSKYL_cc2500_conf);
|
||||
else
|
||||
FRSKY_init_cc2500((FrSkyFormat&2)?FRSKYXEU_cc2500_conf:FRSKYX_cc2500_conf); // LBT or FCC
|
||||
if(protocol==PROTO_FRSKYX2)
|
||||
{
|
||||
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Enable CRC
|
||||
if(!(FrSkyFormat&2))
|
||||
{ // FCC
|
||||
CC2500_WriteReg(CC2500_17_MCSM1, 0x0E); //0x0E -> RX stays in RX and TX stays in TX???
|
||||
CC2500_WriteReg(CC2500_11_MDMCFG3, 0x84); // bitrate 70K->77K
|
||||
}
|
||||
}
|
||||
//
|
||||
for(uint8_t c=0;c < 48;c++)
|
||||
{//calibrate hop channels
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR,hopping_frequency[c]);
|
||||
CC2500_Strobe(CC2500_SCAL);
|
||||
delayMicroseconds(900);//
|
||||
calData[c] = CC2500_ReadReg(CC2500_25_FSCAL1);
|
||||
}
|
||||
//#######END INIT########
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FrSkyX_initialize_data(uint8_t adr)
|
||||
{
|
||||
CC2500_WriteReg(CC2500_18_MCSM0, 0x8);
|
||||
CC2500_WriteReg(CC2500_09_ADDR, adr ? 0x03 : rx_tx_addr[3]);
|
||||
CC2500_WriteReg(CC2500_07_PKTCTRL1,0x05); // check address
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,7 @@ static void __attribute__((unused)) frsky2way_init(uint8_t bind)
|
||||
{
|
||||
FRSKY_init_cc2500(FRSKYD_cc2500_conf);
|
||||
|
||||
CC2500_WriteReg(CC2500_1B_AGCCTRL2, bind ? 0x43 : 0x03);
|
||||
CC2500_WriteReg(CC2500_09_ADDR, bind ? 0x03 : rx_tx_addr[3]);
|
||||
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05);
|
||||
CC2500_Strobe(CC2500_SIDLE); // Go to idle...
|
||||
@@ -53,7 +54,7 @@ static void __attribute__((unused)) frsky2way_build_bind_packet()
|
||||
packet[14] = 0x00;
|
||||
packet[15] = 0x00;
|
||||
packet[16] = 0x00;
|
||||
packet[17] = 0x01;
|
||||
packet[17] = rx_tx_addr[1];
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) frsky2way_data_frame()
|
||||
@@ -70,7 +71,7 @@ static void __attribute__((unused)) frsky2way_data_frame()
|
||||
packet[4] = 0x00;
|
||||
#endif
|
||||
|
||||
packet[5] = 0x01;
|
||||
packet[5] = rx_tx_addr[1];
|
||||
//
|
||||
packet[10] = 0;
|
||||
packet[11] = 0;
|
||||
@@ -95,7 +96,23 @@ static void __attribute__((unused)) frsky2way_data_frame()
|
||||
|
||||
uint16_t initFrSky_2way()
|
||||
{
|
||||
Frsky_init_hop();
|
||||
//FrskyD init hop
|
||||
if (sub_protocol==DCLONE)
|
||||
Frsky_init_clone();
|
||||
else
|
||||
{
|
||||
for(uint8_t i=0;i<50;i++)
|
||||
{
|
||||
uint8_t freq = (i * 0x1e) % 0xeb;
|
||||
if(i == 3 || i == 23 || i == 47)
|
||||
freq++;
|
||||
if(i > 47)
|
||||
freq=0;
|
||||
hopping_frequency[i]=freq;
|
||||
}
|
||||
rx_tx_addr[1]=1; // keep compatibility with already bound RXs
|
||||
}
|
||||
|
||||
packet_count=0;
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
@@ -164,7 +181,7 @@ uint16_t ReadFrSky_2way()
|
||||
if(packet_in[len-1] & 0x80)
|
||||
{//with valid crc
|
||||
packet_count=0;
|
||||
frsky_check_telemetry(packet_in,len); //check if valid telemetry packets and buffer them.
|
||||
frsky_process_telemetry(packet_in,len); //check if valid telemetry packets and buffer them.
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
262
Multiprotocol/FrSkyL_cc2500.ino
Normal file
262
Multiprotocol/FrSkyL_cc2500.ino
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#if defined(FRSKYL_CC2500_INO)
|
||||
|
||||
#include "iface_cc2500.h"
|
||||
|
||||
//#define FRSKYL_FORCE_ID
|
||||
#define FRSKYL_PACKET_LEN 256
|
||||
#define FRSKYL_PERIOD 18000
|
||||
|
||||
uint8_t FrSkyL_buffer[FRSKYL_PACKET_LEN];
|
||||
|
||||
static void __attribute__((unused)) FrSkyL_build_bind_packet()
|
||||
{
|
||||
//Header
|
||||
packet[0] = 0x4E; // Unknown but constant
|
||||
//Bind packet
|
||||
memset(&packet[1],0x00,3);
|
||||
//ID
|
||||
packet[4 ] = rx_tx_addr[3]; // ID
|
||||
packet[5 ] = rx_tx_addr[2]; // ID
|
||||
int idx = ((state -FRSKY_BIND) % 10) * 5;
|
||||
packet[6 ] = idx;
|
||||
packet[7 ] = hopping_frequency[idx++];
|
||||
packet[8 ] = hopping_frequency[idx++];
|
||||
packet[9 ] = hopping_frequency[idx++];
|
||||
packet[10] = hopping_frequency[idx++];
|
||||
packet[11] = hopping_frequency[idx++];
|
||||
packet[12] = rx_tx_addr[1]; // ID or hw ver?
|
||||
packet[13] = RX_num;
|
||||
packet[14] = 0x00; // Unknown but constant
|
||||
//CRC
|
||||
uint16_t lcrc = FrSkyX_crc(&packet[1], 14);
|
||||
packet[15] = lcrc >> 8;
|
||||
packet[16] = lcrc;
|
||||
//Debug
|
||||
/* debug("Bind:");
|
||||
for(uint8_t i=0;i<17;i++)
|
||||
debug(" %02X",packet[i]);
|
||||
debugln("");*/
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FrSkyL_build_packet()
|
||||
{
|
||||
static uint8_t chan_offset=0;
|
||||
uint16_t chan_0,chan_1;
|
||||
|
||||
//Header
|
||||
packet[0 ] = 0x4E; // Unknown but constant
|
||||
//ID
|
||||
packet[1 ] = rx_tx_addr[3]; // ID
|
||||
packet[2 ] = rx_tx_addr[2]; // ID
|
||||
packet[3 ] = rx_tx_addr[1]; // ID or hw ver?
|
||||
//skip_hop
|
||||
packet[4 ] = (FrSkyX_chanskip<<6)|hopping_frequency_no;
|
||||
packet[5 ] = FrSkyX_chanskip>>2;
|
||||
//Channels
|
||||
uint8_t startChan = chan_offset;
|
||||
for(uint8_t i = 0; i <9 ; i+=3)
|
||||
{//9 bytes of channel data
|
||||
chan_0 = FrSkyX_scaleForPXX(startChan,6);
|
||||
startChan++;
|
||||
//
|
||||
chan_1 = FrSkyX_scaleForPXX(startChan,6);
|
||||
startChan++;
|
||||
//
|
||||
packet[6+i] = lowByte(chan_0); //3 bytes*4
|
||||
packet[6+i+1]=(((chan_0>>8) & 0x0F)|(chan_1 << 4));
|
||||
packet[6+i+2]=chan_1>>4;
|
||||
}
|
||||
if(sub_protocol & 0x01 ) //6ch mode only??
|
||||
chan_offset = 0 ;
|
||||
else
|
||||
chan_offset^=0x06;
|
||||
//CRC
|
||||
uint16_t lcrc = FrSkyX_crc(&packet[1], 14, RX_num);
|
||||
packet[15] = lcrc >> 8;
|
||||
packet[16] = lcrc;
|
||||
//Debug
|
||||
/*debug("Norm:");
|
||||
for(uint8_t i=0;i<17;i++)
|
||||
debug(" %02X",packet[i]);
|
||||
debugln("");*/
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FrSkyL_encode_packet(bool type)
|
||||
{
|
||||
#define FRSKYL_BIT0 0xED
|
||||
#define FRSKYL_BIT1 0x712
|
||||
|
||||
uint32_t bits = 0;
|
||||
uint8_t bitsavailable = 0;
|
||||
uint8_t idx = 0,len=6;
|
||||
if(type)
|
||||
{//just replace packet content
|
||||
idx=66;
|
||||
len=17;
|
||||
}
|
||||
|
||||
//debugln("Encode:");
|
||||
for (uint8_t i = 0; i < len; i++)
|
||||
{
|
||||
uint8_t tmp=packet[i];
|
||||
//debug("%02X =",tmp);
|
||||
for(uint8_t j=0;j<8;j++)
|
||||
{
|
||||
bits <<= 11;
|
||||
if(tmp&0x01)
|
||||
bits |= FRSKYL_BIT1;
|
||||
else
|
||||
bits |= FRSKYL_BIT0;
|
||||
tmp >>=1;
|
||||
bitsavailable += 11;
|
||||
while (bitsavailable >= 8) {
|
||||
uint32_t bits_tmp=bits>>(bitsavailable-8);
|
||||
bitsavailable -= 8;
|
||||
FrSkyL_buffer[idx] = bits_tmp;
|
||||
//debug(" %02X",FrSkyL_buffer[idx]);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
//debugln("");
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t ReadFrSkyL()
|
||||
{
|
||||
static uint8_t written=0, send=0;
|
||||
switch(send)
|
||||
{
|
||||
case 1:
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_Strobe(CC2500_SFTX);
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, FrSkyL_buffer, 64);
|
||||
CC2500_Strobe(CC2500_STX);
|
||||
CC2500_Strobe(CC2500_SIDLE); // This cancels the current transmission???
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, FrSkyL_buffer, 64);
|
||||
CC2500_Strobe(CC2500_SFTX); // This just clears what we've written???
|
||||
CC2500_Strobe(CC2500_STX);
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, FrSkyL_buffer, 64);
|
||||
written=64;
|
||||
send++;
|
||||
return 2623;
|
||||
case 2:
|
||||
len=FRSKYL_PACKET_LEN-written;
|
||||
if(len>31)
|
||||
len=31;
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, FrSkyL_buffer+written, len);
|
||||
written+=len;
|
||||
if(len!=31) //everything has been sent
|
||||
{
|
||||
send=0;
|
||||
return 2936;
|
||||
}
|
||||
return 1984;
|
||||
}
|
||||
|
||||
switch(state)
|
||||
{
|
||||
default:
|
||||
//Bind
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(9000);
|
||||
#endif
|
||||
FrSkyX_set_start(47);
|
||||
CC2500_SetPower();
|
||||
CC2500_Strobe(CC2500_SFRX);
|
||||
//
|
||||
FrSkyL_build_bind_packet();
|
||||
FrSkyL_encode_packet(true);
|
||||
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
if(IS_BIND_DONE)
|
||||
state = FRSKY_BIND_DONE;
|
||||
else
|
||||
{
|
||||
state++;
|
||||
send=1;
|
||||
}
|
||||
return 537;
|
||||
case FRSKY_BIND_DONE:
|
||||
FrSkyX_initialize_data(0);
|
||||
hopping_frequency_no=0;
|
||||
BIND_DONE;
|
||||
state++; //FRSKY_DATA1
|
||||
break;
|
||||
|
||||
case FRSKY_DATA1:
|
||||
if ( prev_option != option )
|
||||
{
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); //Frequency offset hack
|
||||
prev_option = option ;
|
||||
}
|
||||
FrSkyX_set_start(hopping_frequency_no);
|
||||
FrSkyL_build_packet();
|
||||
FrSkyL_encode_packet(true);
|
||||
CC2500_SetPower();
|
||||
hopping_frequency_no = (hopping_frequency_no+FrSkyX_chanskip)%47;
|
||||
send=1;
|
||||
return 537;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint16_t initFrSkyL()
|
||||
{
|
||||
set_rx_tx_addr(MProtocol_id_master);
|
||||
rx_tx_addr[1]=0x02; // ID related, hw version?
|
||||
|
||||
#ifdef FRSKYL_FORCE_ID
|
||||
rx_tx_addr[3]=0x0E;
|
||||
rx_tx_addr[2]=0x1C;
|
||||
rx_tx_addr[1]=0x02;
|
||||
#endif
|
||||
FrSkyX2_init_hop();
|
||||
|
||||
while(!FrSkyX_chanskip)
|
||||
FrSkyX_chanskip=random(0xfefefefe)%47;
|
||||
|
||||
FrSkyX_init();
|
||||
|
||||
//Prepare frame
|
||||
memset(FrSkyL_buffer,0x00,FRSKYL_PACKET_LEN-3);
|
||||
memset(&FrSkyL_buffer[FRSKYL_PACKET_LEN-3],0x55,3);
|
||||
memset(packet,0xAA,6);
|
||||
FrSkyL_encode_packet(false);
|
||||
/*debugln("Frame:");
|
||||
for(uint16_t i=0;i<FRSKYL_PACKET_LEN;i++)
|
||||
{
|
||||
debug(" %02X",FrSkyL_buffer[i]);
|
||||
if(i%11==10)
|
||||
debugln("");
|
||||
}
|
||||
debugln("");*/
|
||||
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
state = FRSKY_BIND;
|
||||
FrSkyX_initialize_data(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
state = FRSKY_DATA1;
|
||||
FrSkyX_initialize_data(0);
|
||||
}
|
||||
return 10000;
|
||||
}
|
||||
#endif
|
||||
307
Multiprotocol/FrSkyR9_sx1276.ino
Normal file
307
Multiprotocol/FrSkyR9_sx1276.ino
Normal file
@@ -0,0 +1,307 @@
|
||||
#if defined(FRSKYR9_SX1276_INO)
|
||||
#include "iface_sx1276.h"
|
||||
|
||||
#define DISP_FREQ_TABLE
|
||||
|
||||
#define FLEX_FREQ 29
|
||||
#define FCC_FREQ 43
|
||||
#define EU_FREQ 19
|
||||
|
||||
enum {
|
||||
FRSKYR9_FREQ=0,
|
||||
FRSKYR9_DATA,
|
||||
FRSKYR9_RX1,
|
||||
FRSKYR9_RX2,
|
||||
};
|
||||
|
||||
void FrSkyR9_set_frequency()
|
||||
{
|
||||
uint8_t data[3];
|
||||
uint16_t num=0;
|
||||
hopping_frequency_no += FrSkyX_chanskip;
|
||||
switch(sub_protocol & 0xFD)
|
||||
{
|
||||
case R9_868:
|
||||
if(IS_BIND_DONE) // if bind is in progress use R9_915 instead
|
||||
{
|
||||
hopping_frequency_no %= FLEX_FREQ;
|
||||
num=hopping_frequency_no;
|
||||
if(hopping_frequency_no>=FLEX_FREQ-2)
|
||||
num+=FrSkyX_chanskip-FLEX_FREQ+2; // the last 2 values are FrSkyX_chanskip and FrSkyX_chanskip+1
|
||||
num <<= 5;
|
||||
num += 0xD700;
|
||||
break;
|
||||
}//else use R9_915
|
||||
case R9_915:
|
||||
hopping_frequency_no %= FLEX_FREQ;
|
||||
num=hopping_frequency_no;
|
||||
if(hopping_frequency_no>=FLEX_FREQ-2)
|
||||
num+=FrSkyX_chanskip-FLEX_FREQ+2; // the last 2 values are FrSkyX_chanskip and FrSkyX_chanskip+1
|
||||
num <<= 5;
|
||||
num += 0xE4C0;
|
||||
break;
|
||||
case R9_FCC:
|
||||
hopping_frequency_no %= FCC_FREQ;
|
||||
num=hopping_frequency_no;
|
||||
num <<= 5;
|
||||
num += 0xE200;
|
||||
break;
|
||||
case R9_EU:
|
||||
hopping_frequency_no %= EU_FREQ;
|
||||
num=hopping_frequency_no;
|
||||
num <<= 4;
|
||||
num += 0xD7D0;
|
||||
break;
|
||||
}
|
||||
data[0] = num>>8;
|
||||
data[1] = num&0xFF;
|
||||
data[2] = 0x00;
|
||||
|
||||
#ifdef DISP_FREQ_TABLE
|
||||
if(phase==0xFF)
|
||||
debugln("F%d=%02X%02X%02X=%lu", hopping_frequency_no, data[0], data[1], data[2], (uint32_t)((data[0]<<16)+(data[1]<<8)+data[2])*61);
|
||||
#endif
|
||||
SX1276_WriteRegisterMulti(SX1276_06_FRFMSB, data, 3);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FrSkyR9_build_packet()
|
||||
{
|
||||
//ID
|
||||
packet[0] = rx_tx_addr[1];
|
||||
packet[1] = rx_tx_addr[2];
|
||||
packet[2] = rx_tx_addr[3];
|
||||
|
||||
//Hopping
|
||||
packet[3] = hopping_frequency_no; // current channel index
|
||||
packet[4] = FrSkyX_chanskip; // step size and last 2 channels start index
|
||||
|
||||
//RX number
|
||||
packet[5] = RX_num; // receiver number from OpenTX
|
||||
|
||||
//Channels
|
||||
FrSkyX_channels(6); // Set packet[6]=failsafe, packet[7]=0?? and packet[8..19]=channels data
|
||||
|
||||
//Bind
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{// 915 0x01=CH1-8_TELEM_ON 0x41=CH1-8_TELEM_OFF 0xC1=CH9-16_TELEM_OFF 0x81=CH9-16_TELEM_ON
|
||||
packet[6] = 0x01; // bind indicator
|
||||
if(sub_protocol & 1)
|
||||
packet[6] |= 0x20; // 868
|
||||
if(binding_idx&0x01)
|
||||
packet[6] |= 0x40; // telem OFF
|
||||
if(binding_idx&0x02)
|
||||
packet[6] |= 0x80; // ch9-16
|
||||
}
|
||||
|
||||
//Sequence and send SPort
|
||||
FrSkyX_seq_sport(20,23); //20=RX|TXseq, 21=bytes count, 22&23=data
|
||||
|
||||
//CRC
|
||||
uint16_t crc = FrSkyX_crc(packet, 24);
|
||||
packet[24] = crc; // low byte
|
||||
packet[25] = crc >> 8; // high byte
|
||||
}
|
||||
|
||||
static uint8_t __attribute__((unused)) FrSkyR9_CRC8(uint8_t *p, uint8_t l)
|
||||
{
|
||||
uint8_t crc = 0xFF;
|
||||
for (uint8_t i = 0; i < l; i++)
|
||||
{
|
||||
crc = crc ^ p[i];
|
||||
for ( uint8_t j = 0; j < 8; j++ )
|
||||
if ( crc & 0x80 )
|
||||
{
|
||||
crc <<= 1;
|
||||
crc ^= 0x07;
|
||||
}
|
||||
else
|
||||
crc <<= 1;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FrSkyR9_build_EU_packet()
|
||||
{
|
||||
//ID
|
||||
packet[0] = rx_tx_addr[1];
|
||||
packet[1] = rx_tx_addr[2];
|
||||
packet[2] = rx_tx_addr[3];
|
||||
|
||||
//Hopping
|
||||
packet[3] = FrSkyX_chanskip; // step size and last 2 channels start index
|
||||
|
||||
//RX number
|
||||
packet[4] = RX_num; // receiver number from OpenTX
|
||||
|
||||
//Channels
|
||||
//TODO FrSkyX_channels(5,4); // Set packet[5]=failsafe and packet[6..11]=4 channels data
|
||||
|
||||
//Bind
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet[5] = 0x01; // bind indicator
|
||||
if((sub_protocol & 2) == 0)
|
||||
packet[5] |= 0x10; // 16CH
|
||||
// if(sub_protocol & 1)
|
||||
// packet[5] |= 0x20; // 868
|
||||
if(binding_idx&0x01)
|
||||
packet[5] |= 0x40; // telem OFF
|
||||
if(binding_idx&0x02)
|
||||
packet[5] |= 0x80; // ch9-16
|
||||
}
|
||||
|
||||
//Sequence and send SPort
|
||||
packet[12] = (FrSkyX_RX_Seq << 4)|0x08; //TX=8 at startup
|
||||
|
||||
//CRC
|
||||
packet[13] = FrSkyR9_CRC8(packet, 13);
|
||||
}
|
||||
|
||||
uint16_t initFrSkyR9()
|
||||
{
|
||||
//Check frequencies
|
||||
#ifdef DISP_FREQ_TABLE
|
||||
phase=0xFF;
|
||||
FrSkyX_chanskip=1;
|
||||
hopping_frequency_no=0xFF;
|
||||
for(uint8_t i=0;i<FCC_FREQ;i++)
|
||||
FrSkyR9_set_frequency();
|
||||
#endif
|
||||
|
||||
//Reset ID
|
||||
set_rx_tx_addr(MProtocol_id_master);
|
||||
|
||||
//FrSkyX_chanskip
|
||||
FrSkyX_chanskip = 1 + (random(0xfefefefe) % 24);
|
||||
debugln("chanskip=%d", FrSkyX_chanskip);
|
||||
|
||||
//Set FrSkyFormat
|
||||
if((sub_protocol & 0x02) == 0)
|
||||
FrSkyFormat=0; // 16 channels
|
||||
else
|
||||
FrSkyFormat=1; // 8 channels
|
||||
debugln("%dCH", FrSkyFormat&1 ? 8:16);
|
||||
|
||||
//EU packet length
|
||||
if( (sub_protocol & 0xFD) == R9_EU )
|
||||
packet_length=14;
|
||||
else
|
||||
packet_length=26;
|
||||
|
||||
//SX1276 Init
|
||||
SX1276_SetMode(true, false, SX1276_OPMODE_SLEEP);
|
||||
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
|
||||
|
||||
// uint8_t buffer[2];
|
||||
// buffer[0] = 0x00;
|
||||
// buffer[1] = 0x00;
|
||||
// SX1276_WriteRegisterMulti(SX1276_40_DIOMAPPING1, buffer, 2);
|
||||
|
||||
SX1276_SetDetectOptimize(true, SX1276_DETECT_OPTIMIZE_SF6);
|
||||
SX1276_ConfigModem1(SX1276_MODEM_CONFIG1_BW_500KHZ, SX1276_MODEM_CONFIG1_CODING_RATE_4_5, true);
|
||||
SX1276_ConfigModem2(6, false, false);
|
||||
SX1276_ConfigModem3(false, false);
|
||||
SX1276_SetPreambleLength(9);
|
||||
SX1276_SetDetectionThreshold(SX1276_MODEM_DETECTION_THRESHOLD_SF6);
|
||||
SX1276_SetLna(1, true);
|
||||
SX1276_SetHopPeriod(0); // 0 = disabled, we hop frequencies manually
|
||||
SX1276_SetPaDac(true);
|
||||
SX1276_SetTxRxMode(TX_EN); // Set RF switch to TX
|
||||
//Enable all IRQ flags
|
||||
SX1276_WriteReg(SX1276_11_IRQFLAGSMASK,0x00);
|
||||
FrSkyX_telem_init();
|
||||
|
||||
hopping_frequency_no=0;
|
||||
phase=FRSKYR9_FREQ;
|
||||
return 20000; // Start calling FrSkyR9_callback in 20 milliseconds
|
||||
}
|
||||
|
||||
uint16_t FrSkyR9_callback()
|
||||
{
|
||||
switch (phase)
|
||||
{
|
||||
case FRSKYR9_FREQ:
|
||||
//Force standby
|
||||
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
|
||||
//Set frequency
|
||||
FrSkyR9_set_frequency(); // Set current center frequency
|
||||
//Set power
|
||||
// max power: 15dBm (10.8 + 0.6 * MaxPower [dBm])
|
||||
// output_power: 2 dBm (17-(15-OutputPower) (if pa_boost_pin == true))
|
||||
SX1276_SetPaConfig(true, 7, 0); // Lowest power for the T18
|
||||
//Build packet
|
||||
if( packet_length == 26 )
|
||||
FrSkyR9_build_packet();
|
||||
else
|
||||
FrSkyR9_build_EU_packet();
|
||||
phase++;
|
||||
return 460; // Frequency settle time
|
||||
case FRSKYR9_DATA:
|
||||
//Set RF switch to TX
|
||||
SX1276_SetTxRxMode(TX_EN);
|
||||
//Send packet
|
||||
SX1276_WritePayloadToFifo(packet, packet_length);
|
||||
SX1276_SetMode(true, false, SX1276_OPMODE_TX);
|
||||
#if not defined TELEMETRY
|
||||
phase=FRSKYR9_FREQ;
|
||||
return 20000-460;
|
||||
#else
|
||||
phase++;
|
||||
return 11140; // Packet send time
|
||||
case FRSKYR9_RX1:
|
||||
//Force standby
|
||||
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
|
||||
//RX packet size is 13
|
||||
SX1276_WriteReg(SX1276_22_PAYLOAD_LENGTH, 13);
|
||||
//Reset pointer
|
||||
SX1276_WriteReg(SX1276_0D_FIFOADDRPTR, 0x00);
|
||||
//Set RF switch to RX
|
||||
SX1276_SetTxRxMode(RX_EN);
|
||||
//Clear all IRQ flags
|
||||
SX1276_WriteReg(SX1276_12_REGIRQFLAGS,0xFF);
|
||||
//Switch to RX
|
||||
SX1276_WriteReg(SX1276_01_OPMODE, 0x85);
|
||||
phase++;
|
||||
return 7400;
|
||||
case FRSKYR9_RX2:
|
||||
if( (SX1276_ReadReg(SX1276_12_REGIRQFLAGS)&0xF0) == (_BV(SX1276_REGIRQFLAGS_RXDONE) | _BV(SX1276_REGIRQFLAGS_VALIDHEADER)) )
|
||||
{
|
||||
if(SX1276_ReadReg(SX1276_13_REGRXNBBYTES)==13)
|
||||
{
|
||||
SX1276_ReadRegisterMulti(SX1276_00_FIFO,packet_in,13);
|
||||
if( packet_in[9]==rx_tx_addr[1] && packet_in[10]==rx_tx_addr[2] && FrSkyX_crc(packet_in, 11, rx_tx_addr[1]+(rx_tx_addr[2]<<8))==(packet_in[11]+(packet_in[12]<<8)) )
|
||||
{
|
||||
if(packet_in[0]&0x80)
|
||||
RX_RSSI=packet_in[0]<<1;
|
||||
else
|
||||
v_lipo1=(packet_in[0]<<1)+1;
|
||||
//TX_LQI=~(SX1276_ReadReg(SX1276_19_PACKETSNR)>>2)+1;
|
||||
TX_RSSI=SX1276_ReadReg(SX1276_1A_PACKETRSSI)-157;
|
||||
for(uint8_t i=0;i<9;i++)
|
||||
packet[4+i]=packet_in[i]; // Adjust buffer to match FrSkyX
|
||||
frsky_process_telemetry(packet,len); // Process telemetry packet
|
||||
pps_counter++;
|
||||
if(TX_LQI==0)
|
||||
TX_LQI++; // Recover telemetry right away
|
||||
}
|
||||
}
|
||||
}
|
||||
if (millis() - pps_timer >= 1000)
|
||||
{//1 packet every 20ms
|
||||
pps_timer = millis();
|
||||
debugln("%d pps", pps_counter);
|
||||
TX_LQI = pps_counter<<1; // Max=100%
|
||||
pps_counter = 0;
|
||||
}
|
||||
if(TX_LQI==0)
|
||||
FrSkyX_telem_init(); // Reset telemetry
|
||||
else
|
||||
telemetry_link=1; // Send telemetry out anyway
|
||||
phase=FRSKYR9_FREQ;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return 1000;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,4 @@
|
||||
/* **************************
|
||||
* By Midelic on RCGroups *
|
||||
**************************
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -19,60 +17,22 @@
|
||||
|
||||
#include "iface_cc2500.h"
|
||||
|
||||
uint8_t FrSkyX_chanskip;
|
||||
uint8_t FrSkyX_TX_Seq, FrSkyX_TX_IN_Seq;
|
||||
uint8_t FrSkyX_RX_Seq ;
|
||||
|
||||
#ifdef SPORT_SEND
|
||||
struct t_FrSkyX_TX_Frame
|
||||
{
|
||||
uint8_t count;
|
||||
uint8_t payload[8];
|
||||
} ;
|
||||
// Store FrskyX telemetry
|
||||
struct t_FrSkyX_TX_Frame FrSkyX_TX_Frames[4] ;
|
||||
#endif
|
||||
|
||||
#define FrSkyX_FAILSAFE_TIMEOUT 1032
|
||||
|
||||
static void __attribute__((unused)) FrSkyX_set_start(uint8_t ch )
|
||||
{
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_WriteReg(CC2500_25_FSCAL1, calData[ch]);
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[ch]);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FrSkyX_init()
|
||||
{
|
||||
FRSKY_init_cc2500((sub_protocol&2)?FRSKYXEU_cc2500_conf:FRSKYX_cc2500_conf); // LBT or FCC
|
||||
//
|
||||
for(uint8_t c=0;c < 48;c++)
|
||||
{//calibrate hop channels
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR,hopping_frequency[c]);
|
||||
CC2500_Strobe(CC2500_SCAL);
|
||||
delayMicroseconds(900);//
|
||||
calData[c] = CC2500_ReadReg(CC2500_25_FSCAL1);
|
||||
}
|
||||
//#######END INIT########
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FrSkyX_initialize_data(uint8_t adr)
|
||||
{
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack
|
||||
CC2500_WriteReg(CC2500_18_MCSM0, 0x8);
|
||||
CC2500_WriteReg(CC2500_09_ADDR, adr ? 0x03 : rx_tx_addr[3]);
|
||||
CC2500_WriteReg(CC2500_07_PKTCTRL1,0x05);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FrSkyX_build_bind_packet()
|
||||
{
|
||||
packet[0] = (sub_protocol & 2 ) ? 0x20 : 0x1D ; // LBT or FCC
|
||||
packet[1] = 0x03;
|
||||
packet[2] = 0x01;
|
||||
//
|
||||
packet[3] = rx_tx_addr[3];
|
||||
packet[4] = rx_tx_addr[2];
|
||||
uint8_t packet_size = 0x1D;
|
||||
if(protocol==PROTO_FRSKYX && (FrSkyFormat & 2 ))
|
||||
packet_size=0x20; // FrSkyX V1 LBT
|
||||
//Header
|
||||
packet[0] = packet_size; // Number of bytes in the packet (after this one)
|
||||
packet[1] = 0x03; // Bind packet
|
||||
packet[2] = 0x01; // Bind packet
|
||||
|
||||
//ID
|
||||
packet[3] = rx_tx_addr[3]; // ID
|
||||
packet[4] = rx_tx_addr[2]; // ID
|
||||
|
||||
if(protocol==PROTO_FRSKYX)
|
||||
{
|
||||
int idx = ((state -FRSKY_BIND) % 10) * 5;
|
||||
packet[5] = idx;
|
||||
packet[6] = hopping_frequency[idx++];
|
||||
@@ -80,208 +40,84 @@ static void __attribute__((unused)) FrSkyX_build_bind_packet()
|
||||
packet[8] = hopping_frequency[idx++];
|
||||
packet[9] = hopping_frequency[idx++];
|
||||
packet[10] = hopping_frequency[idx++];
|
||||
packet[11] = 0x02;
|
||||
packet[11] = rx_tx_addr[1]; // Unknown but constant ID?
|
||||
packet[12] = RX_num;
|
||||
//
|
||||
uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ;
|
||||
memset(&packet[13], 0, limit - 13);
|
||||
uint16_t lcrc = FrSkyX_crc(&packet[3], limit-3);
|
||||
//
|
||||
packet[limit++] = lcrc >> 8;
|
||||
packet[limit] = lcrc;
|
||||
//
|
||||
memset(&packet[13], 0, packet_size - 14);
|
||||
if(binding_idx&0x01)
|
||||
memcpy(&packet[13],(void *)"\x55\xAA\x5A\xA5",4); // Telem off
|
||||
if(binding_idx&0x02)
|
||||
memcpy(&packet[17],(void *)"\x55\xAA\x5A\xA5",4); // CH9-16
|
||||
}
|
||||
else
|
||||
{
|
||||
//packet 1D 03 01 0E 1C 02 00 00 32 0B 00 00 A8 26 28 01 A1 00 00 00 3E F6 87 C7 00 00 00 00 C9 C9
|
||||
packet[5] = rx_tx_addr[1]; // Unknown but constant ID?
|
||||
packet[6] = RX_num;
|
||||
//Bind flags
|
||||
packet[7]=0;
|
||||
if(binding_idx&0x01)
|
||||
packet[7] |= 0x40; // Telem off
|
||||
if(binding_idx&0x02)
|
||||
packet[7] |= 0x80; // CH9-16
|
||||
//Unknown bytes
|
||||
memcpy(&packet[8],"\x32\x0B\x00\x00\xA8\x26\x28\x01\xA1\x00\x00\x00\x3E\xF6\x87\xC7",16);
|
||||
packet[20]^= 0x0E ^ rx_tx_addr[3]; // Update the ID
|
||||
packet[21]^= 0x1C ^ rx_tx_addr[2]; // Update the ID
|
||||
//Xor
|
||||
for(uint8_t i=3; i<packet_size-1; i++)
|
||||
packet[i] ^= 0xA7;
|
||||
}
|
||||
//CRC
|
||||
uint16_t lcrc = FrSkyX_crc(&packet[3], packet_size-4);
|
||||
packet[packet_size-1] = lcrc >> 8;
|
||||
packet[packet_size] = lcrc;
|
||||
|
||||
/*//Debug
|
||||
debug("Bind:");
|
||||
for(uint8_t i=0;i<=packet_size;i++)
|
||||
debug(" %02X",packet[i]);
|
||||
debugln("");*/
|
||||
}
|
||||
|
||||
// 0-2047, 0 = 817, 1024 = 1500, 2047 = 2182
|
||||
//64=860,1024=1500,1984=2140//Taranis 125%
|
||||
static uint16_t __attribute__((unused)) FrSkyX_scaleForPXX( uint8_t i )
|
||||
{ //mapped 860,2140(125%) range to 64,1984(PXX values);
|
||||
uint16_t chan_val=convert_channel_frsky(i)-1226;
|
||||
if(i>7) chan_val|=2048; // upper channels offset
|
||||
return chan_val;
|
||||
}
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
static uint16_t __attribute__((unused)) FrSkyX_scaleForPXX_FS( uint8_t i )
|
||||
{ //mapped 1,2046(125%) range to 64,1984(PXX values);
|
||||
uint16_t chan_val=((Failsafe_data[i]*15)>>4)+64;
|
||||
if(Failsafe_data[i]==FAILSAFE_CHANNEL_NOPULSES)
|
||||
chan_val=FAILSAFE_CHANNEL_NOPULSES;
|
||||
else if(Failsafe_data[i]==FAILSAFE_CHANNEL_HOLD)
|
||||
chan_val=FAILSAFE_CHANNEL_HOLD;
|
||||
if(i>7) chan_val|=2048; // upper channels offset
|
||||
return chan_val;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define FrSkyX_FAILSAFE_TIME 1032
|
||||
static void __attribute__((unused)) FrSkyX_build_packet()
|
||||
{
|
||||
//0x1D 0xB3 0xFD 0x02 0x56 0x07 0x15 0x00 0x00 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x00 0x04 0x40 0x08 0x00 0x00 0x00 0x00 0x00 0x00 0x96 0x12
|
||||
//
|
||||
static uint8_t chan_offset=0;
|
||||
uint16_t chan_0 ;
|
||||
uint16_t chan_1 ;
|
||||
//
|
||||
// data frames sent every 9ms; failsafe every 9 seconds
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
static uint16_t failsafe_count=0;
|
||||
static uint8_t FS_flag=0,failsafe_chan=0;
|
||||
if (FS_flag == 0 && failsafe_count > FrSkyX_FAILSAFE_TIME && chan_offset == 0 && IS_FAILSAFE_VALUES_on)
|
||||
{
|
||||
FS_flag = 0x10;
|
||||
failsafe_chan = 0;
|
||||
} else if (FS_flag & 0x10 && failsafe_chan < (sub_protocol & 0x01 ? 8-1:16-1))
|
||||
{
|
||||
FS_flag = 0x10 | ((FS_flag + 2) & 0x0F); //10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
|
||||
failsafe_chan ++;
|
||||
} else if (FS_flag & 0x10)
|
||||
{
|
||||
FS_flag = 0;
|
||||
failsafe_count = 0;
|
||||
FAILSAFE_VALUES_off;
|
||||
}
|
||||
failsafe_count++;
|
||||
#endif
|
||||
|
||||
packet[0] = (sub_protocol & 0x02 ) ? 0x20 : 0x1D ; // LBT or FCC
|
||||
packet[1] = rx_tx_addr[3];
|
||||
packet[2] = rx_tx_addr[2];
|
||||
packet[3] = 0x02;
|
||||
//
|
||||
uint8_t packet_size = 0x1D;
|
||||
if(protocol==PROTO_FRSKYX && (FrSkyFormat & 2 ))
|
||||
packet_size=0x20; // FrSkyX V1 LBT
|
||||
//Header
|
||||
packet[0] = packet_size; // Number of bytes in the packet (after this one)
|
||||
packet[1] = rx_tx_addr[3]; // ID
|
||||
packet[2] = rx_tx_addr[2]; // ID
|
||||
packet[3] = rx_tx_addr[1]; // Unknown but constant ID?
|
||||
//
|
||||
packet[4] = (FrSkyX_chanskip<<6)|hopping_frequency_no;
|
||||
packet[5] = FrSkyX_chanskip>>2;
|
||||
packet[6] = RX_num;
|
||||
//packet[7] = FLAGS 00 - standard packet
|
||||
//10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
|
||||
//20 - range check packet
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
packet[7] = FS_flag;
|
||||
#else
|
||||
packet[7] = 0;
|
||||
#endif
|
||||
packet[8] = 0;
|
||||
//
|
||||
uint8_t startChan = chan_offset;
|
||||
for(uint8_t i = 0; i <12 ; i+=3)
|
||||
{//12 bytes of channel data
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
if( (FS_flag & 0x10) && ((failsafe_chan & 0x07) == (startChan & 0x07)) )
|
||||
chan_0 = FrSkyX_scaleForPXX_FS(failsafe_chan);
|
||||
else
|
||||
#endif
|
||||
chan_0 = FrSkyX_scaleForPXX(startChan);
|
||||
startChan++;
|
||||
//
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
if( (FS_flag & 0x10) && ((failsafe_chan & 0x07) == (startChan & 0x07)) )
|
||||
chan_1 = FrSkyX_scaleForPXX_FS(failsafe_chan);
|
||||
else
|
||||
#endif
|
||||
chan_1 = FrSkyX_scaleForPXX(startChan);
|
||||
startChan++;
|
||||
//
|
||||
packet[9+i] = lowByte(chan_0); //3 bytes*4
|
||||
packet[9+i+1]=(((chan_0>>8) & 0x0F)|(chan_1 << 4));
|
||||
packet[9+i+2]=chan_1>>4;
|
||||
}
|
||||
if(sub_protocol & 0x01 ) //In X8 mode send only 8ch every 9ms
|
||||
chan_offset = 0 ;
|
||||
else
|
||||
chan_offset^=0x08;
|
||||
|
||||
//sequence and send SPort
|
||||
uint8_t limit = (sub_protocol & 2 ) ? 31 : 28 ;
|
||||
for (uint8_t i=22;i<limit;i++)
|
||||
packet[i]=0;
|
||||
packet[21] = FrSkyX_RX_Seq << 4; //TX=8 at startup
|
||||
#ifdef SPORT_SEND
|
||||
if (FrSkyX_TX_IN_Seq!=0xFF)
|
||||
{//RX has replied at least once
|
||||
if (FrSkyX_TX_IN_Seq & 0x08)
|
||||
{//Request init
|
||||
//debugln("Init");
|
||||
FrSkyX_TX_Seq = 0 ;
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
FrSkyX_TX_Frames[i].count=0; //Discard frames in current output buffer
|
||||
}
|
||||
else if (FrSkyX_TX_IN_Seq & 0x04)
|
||||
{//Retransmit the requested packet
|
||||
debugln("Retry:%d",FrSkyX_TX_IN_Seq&0x03);
|
||||
packet[21] |= FrSkyX_TX_IN_Seq&0x03;
|
||||
packet[22] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq&0x03].count;
|
||||
for (uint8_t i=23;i<23+FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq&0x03].count;i++)
|
||||
packet[i] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq&0x03].payload[i];
|
||||
}
|
||||
else if ( FrSkyX_TX_Seq != 0x08 )
|
||||
{
|
||||
if(FrSkyX_TX_Seq==FrSkyX_TX_IN_Seq)
|
||||
{//Send packet from the incoming radio buffer
|
||||
//debugln("Send:%d",FrSkyX_TX_Seq);
|
||||
packet[21] |= FrSkyX_TX_Seq;
|
||||
uint8_t nbr_bytes=0;
|
||||
for (uint8_t i=23;i<limit;i++)
|
||||
{
|
||||
if(SportHead==SportTail)
|
||||
break; //buffer empty
|
||||
packet[i]=SportData[SportHead];
|
||||
FrSkyX_TX_Frames[FrSkyX_TX_Seq].payload[i-23]=SportData[SportHead];
|
||||
SportHead=(SportHead+1) & (MAX_SPORT_BUFFER-1);
|
||||
nbr_bytes++;
|
||||
}
|
||||
packet[22]=nbr_bytes;
|
||||
FrSkyX_TX_Frames[FrSkyX_TX_Seq].count=nbr_bytes;
|
||||
if(nbr_bytes)
|
||||
{//Check the buffer status
|
||||
uint8_t used = SportTail;
|
||||
if ( SportHead > SportTail )
|
||||
used += MAX_SPORT_BUFFER - SportHead ;
|
||||
else
|
||||
used -= SportHead ;
|
||||
if ( used < (MAX_SPORT_BUFFER>>1) )
|
||||
{
|
||||
DATA_BUFFER_LOW_off;
|
||||
debugln("Ok buf:%d",used);
|
||||
}
|
||||
}
|
||||
FrSkyX_TX_Seq = ( FrSkyX_TX_Seq + 1 ) & 0x03 ; //Next iteration send next packet
|
||||
}
|
||||
else
|
||||
{//Not in sequence somehow, transmit what the receiver wants but why not asking for retransmit...
|
||||
//debugln("RX_Seq:%d,TX:%d",FrSkyX_TX_IN_Seq,FrSkyX_TX_Seq);
|
||||
packet[21] |= FrSkyX_TX_IN_Seq;
|
||||
packet[22] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].count;
|
||||
for (uint8_t i=23;i<23+FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].count;i++)
|
||||
packet[i] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].payload[i-23];
|
||||
}
|
||||
}
|
||||
else
|
||||
packet[21] |= 0x08 ; //FrSkyX_TX_Seq=8 at startup
|
||||
}
|
||||
if(packet[22])
|
||||
{//Debug
|
||||
debug("SP: ");
|
||||
for(uint8_t i=0;i<packet[22];i++)
|
||||
debug("%02X ",packet[23+i]);
|
||||
debugln("");
|
||||
}
|
||||
#else
|
||||
packet[21] |= FrSkyX_TX_Seq ;//TX=8 at startup
|
||||
if ( !(FrSkyX_TX_IN_Seq & 0xF8) )
|
||||
FrSkyX_TX_Seq = ( FrSkyX_TX_Seq + 1 ) & 0x03 ; // Next iteration send next packet
|
||||
#endif // SPORT_SEND
|
||||
//Channels
|
||||
FrSkyX_channels(7); // Set packet[7]=failsafe, packet[8]=0?? and packet[9..20]=channels data
|
||||
|
||||
uint16_t lcrc = FrSkyX_crc(&packet[3], limit-3);
|
||||
packet[limit++]=lcrc>>8;//high byte
|
||||
packet[limit]=lcrc;//low byte
|
||||
//Sequence and send SPort
|
||||
FrSkyX_seq_sport(21,packet_size-2); //21=RX|TXseq, 22=bytes count, 23..packet_size-2=data
|
||||
|
||||
//CRC
|
||||
uint16_t lcrc = FrSkyX_crc(&packet[3], packet_size-4);
|
||||
packet[packet_size-1] = lcrc >> 8;
|
||||
packet[packet_size] = lcrc;
|
||||
|
||||
/*//Debug
|
||||
debug("Norm:");
|
||||
for(uint8_t i=0;i<=packet_size;i++)
|
||||
debug(" %02X",packet[i]);
|
||||
debugln("");*/
|
||||
}
|
||||
|
||||
uint16_t ReadFrSkyX()
|
||||
{
|
||||
static bool transmit=true;
|
||||
#ifdef DEBUG_SERIAL
|
||||
static uint16_t fr_time=0;
|
||||
#endif
|
||||
|
||||
switch(state)
|
||||
{
|
||||
default:
|
||||
@@ -303,98 +139,108 @@ uint16_t ReadFrSkyX()
|
||||
BIND_DONE;
|
||||
state++; //FRSKY_DATA1
|
||||
break;
|
||||
case FRSKY_DATA5:
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(9000);
|
||||
#endif
|
||||
#if defined TELEMETRY
|
||||
telemetry_link=1; //Send telemetry out anyway
|
||||
#endif
|
||||
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||
if (len && (len<=(0x0E + 3))) //Telemetry frame is 17
|
||||
{
|
||||
packet_count=0;
|
||||
CC2500_ReadData(packet_in, len);
|
||||
#if defined TELEMETRY
|
||||
frsky_check_telemetry(packet_in,len); //Check and parse telemetry packets
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_count++;
|
||||
//debugln("M %d",packet_count);
|
||||
// restart sequence on missed packet - might need count or timeout instead of one missed
|
||||
if(packet_count>100)
|
||||
{//~1sec
|
||||
FrSkyX_TX_Seq = 0x08 ; //Request init
|
||||
FrSkyX_TX_IN_Seq = 0xFF ; //No sequence received yet
|
||||
#ifdef SPORT_SEND
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
FrSkyX_TX_Frames[i].count=0; //Discard frames in current output buffer
|
||||
#endif
|
||||
packet_count=0;
|
||||
#if defined TELEMETRY
|
||||
telemetry_lost=1;
|
||||
telemetry_link=0; //Stop sending telemetry
|
||||
#endif
|
||||
}
|
||||
CC2500_Strobe(CC2500_SFRX); //Flush the RXFIFO
|
||||
}
|
||||
FrSkyX_build_packet();
|
||||
state = FRSKY_DATA1;
|
||||
#if not defined(FRSKYX_LBT)
|
||||
return 500;
|
||||
#endif // for LBT just continue to DATA1 right away
|
||||
|
||||
case FRSKY_DATA1:
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
if ( prev_option != option )
|
||||
{
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); //Frequency offset hack
|
||||
prev_option = option ;
|
||||
}
|
||||
FrSkyX_set_start(hopping_frequency_no);
|
||||
transmit=true;
|
||||
#ifdef FRSKYX_LBT
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
delayMicroseconds(90); //Wait for the freq to stabilize
|
||||
FrSkyX_build_packet();
|
||||
if(FrSkyFormat & 2)
|
||||
{// LBT
|
||||
CC2500_Strobe(CC2500_SRX); //Acquire RSSI
|
||||
state++;
|
||||
return 500;
|
||||
return 400; // LBT
|
||||
}
|
||||
case FRSKY_DATA2:
|
||||
uint8_t rssi;
|
||||
rssi = CC2500_ReadReg(CC2500_34_RSSI | CC2500_READ_BURST); // 0.5 db/count, RSSI value read from the RSSI status register is a 2's complement number
|
||||
if ((sub_protocol & 2) && rssi > 72 && rssi < 128) //LBT and RSSI between -36 and -8.5 dBm
|
||||
if(FrSkyFormat & 2)
|
||||
{
|
||||
transmit=false;
|
||||
uint16_t rssi=0;
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
rssi += CC2500_ReadReg(CC2500_34_RSSI | CC2500_READ_BURST); // 0.5 db/count, RSSI value read from the RSSI status register is a 2's complement number
|
||||
rssi>>=2;
|
||||
#if 0
|
||||
uint8_t rssi_level=convert_channel_8b(CH16)>>1; //CH16 0..127
|
||||
if ( rssi > rssi_level && rssi < 128) //test rssi level dynamically
|
||||
#else
|
||||
if ( rssi > 14 && rssi < 128) //if RSSI above -65dBm (12=-70) => ETSI requirement
|
||||
#endif
|
||||
{
|
||||
LBT_POWER_on; //Reduce to low power before transmitting
|
||||
debugln("Busy %d %d",hopping_frequency_no,rssi);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_Strobe(CC2500_SFRX);
|
||||
CC2500_Strobe(CC2500_SFTX); //Flush the TXFIFO
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
CC2500_SetPower();
|
||||
hopping_frequency_no = (hopping_frequency_no+FrSkyX_chanskip)%47;
|
||||
if(transmit)
|
||||
{
|
||||
#ifdef DEBUG_SERIAL
|
||||
uint16_t fr_cur=millis();
|
||||
fr_time=fr_cur-fr_time;
|
||||
if(fr_time!=9)
|
||||
debugln("Bad timing: %d",fr_time);
|
||||
fr_time=fr_cur;
|
||||
#endif
|
||||
CC2500_WriteData(packet, packet[0]+1);
|
||||
}
|
||||
state=FRSKY_DATA3;
|
||||
return 5200;
|
||||
if(FrSkyFormat & 2)
|
||||
return 4000; // LBT
|
||||
else
|
||||
return 5200; // FCC
|
||||
case FRSKY_DATA3:
|
||||
CC2500_SetTxRxMode(RX_EN);
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
state++;
|
||||
return 200;
|
||||
case FRSKY_DATA4:
|
||||
CC2500_Strobe(CC2500_SFRX); //Flush the RXFIFO
|
||||
CC2500_SetTxRxMode(RX_EN);
|
||||
CC2500_Strobe(CC2500_SRX);
|
||||
state++;
|
||||
return 3100;
|
||||
if(FrSkyFormat & 2)
|
||||
return 4200; // LBT
|
||||
else
|
||||
return 3400; // FCC
|
||||
case FRSKY_DATA4:
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(9000);
|
||||
#endif
|
||||
#if defined TELEMETRY
|
||||
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||
if (len && len <= 17) //Telemetry frame is 17 bytes
|
||||
{
|
||||
//debug("Telem:");
|
||||
CC2500_ReadData(packet_in, len); //Read what has been received so far
|
||||
if(len<17)
|
||||
{//not all bytes were received
|
||||
uint8_t last_len=CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||
if(last_len==17) //All bytes received
|
||||
{
|
||||
CC2500_ReadData(packet_in+len, last_len-len); //Finish to read
|
||||
len=17;
|
||||
}
|
||||
}
|
||||
if(len==17 && (protocol==PROTO_FRSKYX || (protocol==PROTO_FRSKYX2 && (packet_in[len-1] & 0x80))) )
|
||||
{//Telemetry received with valid crc for FRSKYX2
|
||||
//Debug
|
||||
//for(uint8_t i=0;i<len;i++)
|
||||
// debug(" %02X",packet_in[i]);
|
||||
if(frsky_process_telemetry(packet_in,len)) //Check and process telemetry packet
|
||||
{//good packet received
|
||||
pps_counter++;
|
||||
if(TX_LQI==0)
|
||||
TX_LQI++; //Recover telemetry right away
|
||||
}
|
||||
}
|
||||
//debugln("");
|
||||
}
|
||||
if (millis() - pps_timer >= 900)
|
||||
{//1 packet every 9ms
|
||||
pps_timer = millis();
|
||||
debugln("%d pps", pps_counter);
|
||||
TX_LQI = pps_counter; //Max=100%
|
||||
pps_counter = 0;
|
||||
}
|
||||
if(TX_LQI==0)
|
||||
FrSkyX_telem_init(); //Reset telemetry
|
||||
else
|
||||
telemetry_link=1; //Send telemetry out anyway
|
||||
#endif
|
||||
state = FRSKY_DATA1;
|
||||
return 400; // FCC & LBT
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -402,15 +248,30 @@ uint16_t ReadFrSkyX()
|
||||
uint16_t initFrSkyX()
|
||||
{
|
||||
set_rx_tx_addr(MProtocol_id_master);
|
||||
FrSkyFormat = sub_protocol;
|
||||
|
||||
if (sub_protocol==XCLONE_16||sub_protocol==XCLONE_8)
|
||||
Frsky_init_clone();
|
||||
else if(protocol==PROTO_FRSKYX)
|
||||
{
|
||||
Frsky_init_hop();
|
||||
rx_tx_addr[1]=0x02; // ID related, hw version?
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef FRSKYX2_FORCE_ID
|
||||
rx_tx_addr[3]=0x0E;
|
||||
rx_tx_addr[2]=0x1C;
|
||||
FrSkyX_chanskip=18;
|
||||
#endif
|
||||
rx_tx_addr[1]=0x02; // ID related, hw version?
|
||||
FrSkyX2_init_hop();
|
||||
}
|
||||
|
||||
packet_count=0;
|
||||
while(!FrSkyX_chanskip)
|
||||
FrSkyX_chanskip=random(0xfefefefe)%47;
|
||||
|
||||
//for test***************
|
||||
//rx_tx_addr[3]=0xB3;
|
||||
//rx_tx_addr[2]=0xFD;
|
||||
//************************
|
||||
FrSkyX_init();
|
||||
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
@@ -423,14 +284,7 @@ uint16_t initFrSkyX()
|
||||
state = FRSKY_DATA1;
|
||||
FrSkyX_initialize_data(0);
|
||||
}
|
||||
FrSkyX_TX_Seq = 0x08 ; // Request init
|
||||
FrSkyX_TX_IN_Seq = 0xFF ; // No sequence received yet
|
||||
#ifdef SPORT_SEND
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
FrSkyX_TX_Frames[i].count=0; // discard frames in current output buffer
|
||||
SportHead=SportTail=0; // empty data buffer
|
||||
#endif
|
||||
FrSkyX_RX_Seq = 0 ; // Seq 0 to start with
|
||||
FrSkyX_telem_init();
|
||||
return 10000;
|
||||
}
|
||||
#endif
|
||||
@@ -17,16 +17,19 @@
|
||||
|
||||
#include "iface_cc2500.h"
|
||||
|
||||
#define FRSKY_RX_D16FCC_LENGTH 32
|
||||
#define FRSKY_RX_D16LBT_LENGTH 35
|
||||
#define FRSKY_RX_D8_LENGTH 20
|
||||
#define FRSKY_RX_FORMATS 3
|
||||
#define FRSKY_RX_D16FCC_LENGTH 0x1D+1
|
||||
#define FRSKY_RX_D16LBT_LENGTH 0x20+1
|
||||
#define FRSKY_RX_D16v2_LENGTH 0x1D+1
|
||||
#define FRSKY_RX_D8_LENGTH 0x11+1
|
||||
#define FRSKY_RX_FORMATS 5
|
||||
|
||||
enum
|
||||
{
|
||||
FRSKY_RX_D16FCC = 0,
|
||||
FRSKY_RX_D16LBT,
|
||||
FRSKY_RX_D8
|
||||
FRSKY_RX_D8 =0,
|
||||
FRSKY_RX_D16FCC =1,
|
||||
FRSKY_RX_D16LBT =2,
|
||||
FRSKY_RX_D16v2FCC =3,
|
||||
FRSKY_RX_D16v2LBT =4,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -40,7 +43,7 @@ enum {
|
||||
const PROGMEM uint8_t frsky_rx_common_reg[][2] = {
|
||||
{CC2500_02_IOCFG0, 0x01},
|
||||
{CC2500_18_MCSM0, 0x18},
|
||||
{CC2500_07_PKTCTRL1, 0x04},
|
||||
{CC2500_07_PKTCTRL1, 0x05},
|
||||
{CC2500_3E_PATABLE, 0xFF},
|
||||
{CC2500_0C_FSCTRL0, 0},
|
||||
{CC2500_0D_FREQ2, 0x5C},
|
||||
@@ -62,7 +65,7 @@ const PROGMEM uint8_t frsky_rx_common_reg[][2] = {
|
||||
{CC2500_2D_TEST1, 0x31},
|
||||
{CC2500_2E_TEST0, 0x0B},
|
||||
{CC2500_03_FIFOTHR, 0x07},
|
||||
{CC2500_09_ADDR, 0x00},
|
||||
{CC2500_09_ADDR, 0x03},
|
||||
};
|
||||
|
||||
const PROGMEM uint8_t frsky_rx_d16fcc_reg[][2] = {
|
||||
@@ -116,27 +119,36 @@ static void __attribute__((unused)) frsky_rx_strobe_rx()
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) frsky_rx_initialise_cc2500() {
|
||||
const uint8_t frsky_rx_length[] = { FRSKY_RX_D16FCC_LENGTH, FRSKY_RX_D16LBT_LENGTH, FRSKY_RX_D8_LENGTH };
|
||||
const uint8_t frsky_rx_length[] = { FRSKY_RX_D8_LENGTH, FRSKY_RX_D16FCC_LENGTH, FRSKY_RX_D16LBT_LENGTH, FRSKY_RX_D16v2_LENGTH, FRSKY_RX_D16v2_LENGTH };
|
||||
packet_length = frsky_rx_length[frsky_rx_format];
|
||||
CC2500_Reset();
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
for (uint8_t i = 0; i < sizeof(frsky_rx_common_reg) / 2; i++)
|
||||
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_common_reg[i][0]), pgm_read_byte_near(&frsky_rx_common_reg[i][1]));
|
||||
|
||||
switch (frsky_rx_format) {
|
||||
switch (frsky_rx_format)
|
||||
{
|
||||
case FRSKY_RX_D16v2FCC:
|
||||
case FRSKY_RX_D16FCC:
|
||||
for (uint8_t i = 0; i < sizeof(frsky_rx_d16fcc_reg) / 2; i++)
|
||||
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_d16fcc_reg[i][0]), pgm_read_byte_near(&frsky_rx_d16fcc_reg[i][1]));
|
||||
if(frsky_rx_format==FRSKY_RX_D16v2FCC)
|
||||
{
|
||||
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Enable CRC
|
||||
CC2500_WriteReg(CC2500_17_MCSM1, 0x0E); // Go/Stay in RX mode
|
||||
CC2500_WriteReg(CC2500_11_MDMCFG3, 0x84); // bitrate 70K->77K
|
||||
}
|
||||
break;
|
||||
case FRSKY_RX_D16v2LBT:
|
||||
case FRSKY_RX_D16LBT:
|
||||
for (uint8_t i = 0; i < sizeof(frsky_rx_d16lbt_reg) / 2; i++)
|
||||
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_d16lbt_reg[i][0]), pgm_read_byte_near(&frsky_rx_d16lbt_reg[i][1]));
|
||||
if(frsky_rx_format==FRSKY_RX_D16v2LBT)
|
||||
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Enable CRC
|
||||
break;
|
||||
case FRSKY_RX_D8:
|
||||
for (uint8_t i = 0; i < sizeof(frsky_rx_d8_reg) / 2; i++)
|
||||
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_d8_reg[i][0]), pgm_read_byte_near(&frsky_rx_d8_reg[i][1]));
|
||||
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05); // always check address
|
||||
CC2500_WriteReg(CC2500_09_ADDR, 0x03); // bind address
|
||||
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
|
||||
break;
|
||||
}
|
||||
@@ -169,16 +181,71 @@ static void __attribute__((unused)) frsky_rx_calibrate()
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t __attribute__((unused)) frskyx_rx_check_crc()
|
||||
static uint8_t __attribute__((unused)) frskyx_rx_check_crc_id(bool bind,bool init)
|
||||
{
|
||||
// check D8 checksum
|
||||
/*debugln("RX");
|
||||
for(uint8_t i=0; i<packet_length;i++)
|
||||
debug(" %02X",packet[i]);
|
||||
debugln("");*/
|
||||
|
||||
if(bind && packet[0]!=packet_length-1 && packet[1] !=0x03 && packet[2] != 0x01)
|
||||
return false;
|
||||
uint8_t offset=bind?3:1;
|
||||
|
||||
// Check D8 checksum
|
||||
if (frsky_rx_format == FRSKY_RX_D8)
|
||||
return (packet[packet_length-1] & 0x80) == 0x80; // check CRC_OK flag in status byte 2
|
||||
// check D16 checksum
|
||||
uint8_t limit = packet_length - 4;
|
||||
uint16_t lcrc = FrSkyX_crc(&packet[3], limit - 3); // computed crc
|
||||
uint16_t rcrc = (packet[limit] << 8) | (packet[limit + 1] & 0xff); // received crc
|
||||
return lcrc == rcrc;
|
||||
{
|
||||
if((packet[packet_length+1] & 0x80) != 0x80) // Check CRC_OK flag in status byte 2
|
||||
return false; // Bad CRC
|
||||
if(init)
|
||||
{//Save TXID
|
||||
rx_tx_addr[3] = packet[3];
|
||||
rx_tx_addr[2] = packet[4];
|
||||
rx_tx_addr[1] = packet[17];
|
||||
}
|
||||
else
|
||||
if(rx_tx_addr[3] != packet[offset] || rx_tx_addr[2] != packet[offset+1] || rx_tx_addr[1] != packet[bind?17:5])
|
||||
return false; // Bad address
|
||||
return true; // Full match
|
||||
}
|
||||
|
||||
// Check D16v2 checksum
|
||||
if (frsky_rx_format == FRSKY_RX_D16v2LBT || frsky_rx_format == FRSKY_RX_D16v2FCC)
|
||||
if((packet[packet_length+1] & 0x80) != 0x80) // Check CRC_OK flag in status byte 2
|
||||
return false;
|
||||
//debugln("HW Checksum ok");
|
||||
|
||||
// Check D16 checksum
|
||||
uint16_t lcrc = FrSkyX_crc(&packet[3], packet_length - 5); // Compute crc
|
||||
uint16_t rcrc = (packet[packet_length-2] << 8) | (packet[packet_length-1] & 0xff); // Received crc
|
||||
if(lcrc != rcrc)
|
||||
return false; // Bad CRC
|
||||
//debugln("Checksum ok");
|
||||
|
||||
if (bind && (frsky_rx_format == FRSKY_RX_D16v2LBT || frsky_rx_format == FRSKY_RX_D16v2FCC))
|
||||
for(uint8_t i=3; i<packet_length-2; i++) //unXOR bind packet
|
||||
packet[i] ^= 0xA7;
|
||||
|
||||
uint8_t offset2=0;
|
||||
if (bind && (frsky_rx_format == FRSKY_RX_D16LBT || frsky_rx_format == FRSKY_RX_D16FCC))
|
||||
offset2=6;
|
||||
if(init)
|
||||
{//Save TXID
|
||||
rx_tx_addr[3] = packet[3];
|
||||
rx_tx_addr[2] = packet[4];
|
||||
rx_tx_addr[1] = packet[5+offset2];
|
||||
rx_tx_addr[0] = packet[6+offset2]; // RXnum
|
||||
}
|
||||
else
|
||||
if(rx_tx_addr[3] != packet[offset] || rx_tx_addr[2] != packet[offset+1] || rx_tx_addr[1] != packet[offset+2+offset2])
|
||||
return false; // Bad address
|
||||
//debugln("Address ok");
|
||||
|
||||
if(!bind && rx_tx_addr[0] != packet[6])
|
||||
return false; // Bad RX num
|
||||
|
||||
//debugln("Match");
|
||||
return true; // Full match
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) frsky_rx_build_telemetry_packet()
|
||||
@@ -189,8 +256,24 @@ static void __attribute__((unused)) frsky_rx_build_telemetry_packet()
|
||||
uint8_t idx = 0;
|
||||
uint8_t i;
|
||||
|
||||
if (frsky_rx_format == FRSKY_RX_D16FCC || frsky_rx_format == FRSKY_RX_D16LBT) {
|
||||
// decode D16 channels
|
||||
if (frsky_rx_format == FRSKY_RX_D8)
|
||||
{// decode D8 channels
|
||||
raw_channel[0] = ((packet[10] & 0x0F) << 8 | packet[6]);
|
||||
raw_channel[1] = ((packet[10] & 0xF0) << 4 | packet[7]);
|
||||
raw_channel[2] = ((packet[11] & 0x0F) << 8 | packet[8]);
|
||||
raw_channel[3] = ((packet[11] & 0xF0) << 4 | packet[9]);
|
||||
raw_channel[4] = ((packet[16] & 0x0F) << 8 | packet[12]);
|
||||
raw_channel[5] = ((packet[16] & 0xF0) << 4 | packet[13]);
|
||||
raw_channel[6] = ((packet[17] & 0x0F) << 8 | packet[14]);
|
||||
raw_channel[7] = ((packet[17] & 0xF0) << 4 | packet[15]);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (raw_channel[i] < 1290)
|
||||
raw_channel[i] = 1290;
|
||||
rx_rc_chan[i] = min(((raw_channel[i] - 1290) << 4) / 15, 2047);
|
||||
}
|
||||
}
|
||||
else
|
||||
{// decode D16 channels
|
||||
raw_channel[0] = ((packet[10] << 8) & 0xF00) | packet[9];
|
||||
raw_channel[1] = ((packet[11] << 4) & 0xFF0) | (packet[10] >> 4);
|
||||
raw_channel[2] = ((packet[13] << 8) & 0xF00) | packet[12];
|
||||
@@ -211,22 +294,6 @@ static void __attribute__((unused)) frsky_rx_build_telemetry_packet()
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// decode D8 channels
|
||||
raw_channel[0] = ((packet[10] & 0x0F) << 8 | packet[6]);
|
||||
raw_channel[1] = ((packet[10] & 0xF0) << 4 | packet[7]);
|
||||
raw_channel[2] = ((packet[11] & 0x0F) << 8 | packet[8]);
|
||||
raw_channel[3] = ((packet[11] & 0xF0) << 4 | packet[9]);
|
||||
raw_channel[4] = ((packet[16] & 0x0F) << 8 | packet[12]);
|
||||
raw_channel[5] = ((packet[16] & 0xF0) << 4 | packet[13]);
|
||||
raw_channel[6] = ((packet[17] & 0x0F) << 8 | packet[14]);
|
||||
raw_channel[7] = ((packet[17] & 0xF0) << 4 | packet[15]);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (raw_channel[i] < 1290)
|
||||
raw_channel[i] = 1290;
|
||||
rx_rc_chan[i] = min(((raw_channel[i] - 1290) << 4) / 15, 2047);
|
||||
}
|
||||
}
|
||||
|
||||
// buid telemetry packet
|
||||
packet_in[idx++] = RX_LQI;
|
||||
@@ -246,32 +313,40 @@ static void __attribute__((unused)) frsky_rx_build_telemetry_packet()
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t initFrSky_Rx()
|
||||
static void __attribute__((unused)) frsky_rx_data()
|
||||
{
|
||||
state = 0;
|
||||
frsky_rx_chanskip = 1;
|
||||
hopping_frequency_no = 0;
|
||||
rx_data_started = false;
|
||||
frsky_rx_finetune = 0;
|
||||
telemetry_link = 0;
|
||||
if (IS_BIND_IN_PROGRESS) {
|
||||
frsky_rx_format = FRSKY_RX_D8;
|
||||
frsky_rx_initialise_cc2500();
|
||||
phase = FRSKY_RX_TUNE_START;
|
||||
}
|
||||
else {
|
||||
uint16_t temp = FRSKY_RX_EEPROM_OFFSET;
|
||||
frsky_rx_format = eeprom_read_byte((EE_ADDR)temp++) % FRSKY_RX_FORMATS;
|
||||
rx_tx_addr[0] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
rx_tx_addr[1] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
rx_tx_addr[3] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
rx_tx_addr[2] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
rx_tx_addr[1] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
rx_tx_addr[0] = RX_num;
|
||||
frsky_rx_finetune = eeprom_read_byte((EE_ADDR)temp++);
|
||||
debug("format=%d, ", frsky_rx_format);
|
||||
debug("addr[3]=%02X, ", rx_tx_addr[3]);
|
||||
debug("addr[2]=%02X, ", rx_tx_addr[2]);
|
||||
debug("addr[1]=%02X, ", rx_tx_addr[1]);
|
||||
debug("rx_num=%02X, ", rx_tx_addr[0]);
|
||||
debugln("tune=%d", (int8_t)frsky_rx_finetune);
|
||||
if(frsky_rx_format != FRSKY_RX_D16v2LBT && frsky_rx_format != FRSKY_RX_D16v2FCC)
|
||||
{//D8 & D16v1
|
||||
for (uint8_t ch = 0; ch < 47; ch++)
|
||||
hopping_frequency[ch] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
}
|
||||
else
|
||||
{
|
||||
FrSkyFormat=frsky_rx_format == FRSKY_RX_D16v2FCC?0:2;
|
||||
FrSkyX2_init_hop();
|
||||
}
|
||||
debug("ch:");
|
||||
for (uint8_t ch = 0; ch < 47; ch++)
|
||||
debug(" %02X", hopping_frequency[ch]);
|
||||
debugln("");
|
||||
|
||||
frsky_rx_initialise_cc2500();
|
||||
frsky_rx_calibrate();
|
||||
CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // FS_AUTOCAL = manual
|
||||
CC2500_WriteReg(CC2500_09_ADDR, rx_tx_addr[0]); // set address
|
||||
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);
|
||||
@@ -280,18 +355,37 @@ uint16_t initFrSky_Rx()
|
||||
frsky_rx_set_channel(hopping_frequency_no);
|
||||
phase = FRSKY_RX_DATA;
|
||||
}
|
||||
|
||||
uint16_t initFrSky_Rx()
|
||||
{
|
||||
frsky_rx_chanskip = 1;
|
||||
hopping_frequency_no = 0;
|
||||
rx_data_started = false;
|
||||
frsky_rx_finetune = 0;
|
||||
telemetry_link = 0;
|
||||
packet_count = 0;
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
frsky_rx_format = FRSKY_RX_D8;
|
||||
frsky_rx_initialise_cc2500();
|
||||
phase = FRSKY_RX_TUNE_START;
|
||||
debugln("FRSKY_RX_TUNE_START");
|
||||
}
|
||||
else
|
||||
frsky_rx_data();
|
||||
return 1000;
|
||||
}
|
||||
|
||||
uint16_t FrSky_Rx_callback()
|
||||
{
|
||||
static uint32_t pps_timer=0;
|
||||
static uint8_t pps_counter=0;
|
||||
static int8_t read_retry = 0;
|
||||
static int8_t tune_low, tune_high;
|
||||
uint8_t len, ch;
|
||||
|
||||
if ((prev_option != option) && (phase >= FRSKY_RX_DATA)) {
|
||||
if(IS_BIND_DONE && phase != FRSKY_RX_DATA) return initFrSky_Rx(); // Abort bind
|
||||
|
||||
if ((prev_option != option) && (phase >= FRSKY_RX_DATA))
|
||||
{
|
||||
if (option == 0)
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
|
||||
else
|
||||
@@ -299,28 +393,31 @@ uint16_t FrSky_Rx_callback()
|
||||
prev_option = option;
|
||||
}
|
||||
|
||||
if (rx_disable_lna != IS_POWER_FLAG_on) {
|
||||
if (rx_disable_lna != IS_POWER_FLAG_on)
|
||||
{
|
||||
rx_disable_lna = IS_POWER_FLAG_on;
|
||||
CC2500_SetTxRxMode(rx_disable_lna ? TXRX_OFF : RX_EN);
|
||||
}
|
||||
|
||||
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||
|
||||
switch(phase) {
|
||||
switch(phase)
|
||||
{
|
||||
case FRSKY_RX_TUNE_START:
|
||||
if (len >= packet_length) {
|
||||
CC2500_ReadData(packet, packet_length);
|
||||
if(packet[1] == 0x03 && packet[2] == 0x01) {
|
||||
if(frskyx_rx_check_crc()) {
|
||||
if (len == packet_length + 2) //+2=RSSI+LQI+CRC
|
||||
{
|
||||
CC2500_ReadData(packet, len);
|
||||
if(frskyx_rx_check_crc_id(true,true))
|
||||
{
|
||||
frsky_rx_finetune = -127;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
|
||||
phase = FRSKY_RX_TUNE_LOW;
|
||||
debugln("FRSKY_RX_TUNE_LOW");
|
||||
frsky_rx_strobe_rx();
|
||||
state = 0;
|
||||
return 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
frsky_rx_format = (frsky_rx_format + 1) % FRSKY_RX_FORMATS; // switch to next format (D16FCC, D16LBT, D8)
|
||||
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);
|
||||
@@ -328,13 +425,15 @@ uint16_t FrSky_Rx_callback()
|
||||
return 18000;
|
||||
|
||||
case FRSKY_RX_TUNE_LOW:
|
||||
if (len >= packet_length) {
|
||||
CC2500_ReadData(packet, packet_length);
|
||||
if (frskyx_rx_check_crc()) {
|
||||
if (len == packet_length + 2) //+2=RSSI+LQI+CRC
|
||||
{
|
||||
CC2500_ReadData(packet, len);
|
||||
if(frskyx_rx_check_crc_id(true,false)) {
|
||||
tune_low = frsky_rx_finetune;
|
||||
frsky_rx_finetune = 127;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
|
||||
phase = FRSKY_RX_TUNE_HIGH;
|
||||
debugln("FRSKY_RX_TUNE_HIGH");
|
||||
frsky_rx_strobe_rx();
|
||||
return 1000;
|
||||
}
|
||||
@@ -345,16 +444,23 @@ uint16_t FrSky_Rx_callback()
|
||||
return 18000;
|
||||
|
||||
case FRSKY_RX_TUNE_HIGH:
|
||||
if (len >= packet_length) {
|
||||
CC2500_ReadData(packet, packet_length);
|
||||
if (frskyx_rx_check_crc()) {
|
||||
if (len == packet_length + 2) //+2=RSSI+LQI+CRC
|
||||
{
|
||||
CC2500_ReadData(packet, len);
|
||||
if(frskyx_rx_check_crc_id(true,false)) {
|
||||
tune_high = frsky_rx_finetune;
|
||||
frsky_rx_finetune = (tune_low + tune_high) / 2;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, (int8_t)frsky_rx_finetune);
|
||||
if(tune_low < tune_high)
|
||||
{
|
||||
phase = FRSKY_RX_BIND;
|
||||
debugln("FRSKY_RX_TUNE_HIGH");
|
||||
}
|
||||
else
|
||||
{
|
||||
phase = FRSKY_RX_TUNE_START;
|
||||
debugln("FRSKY_RX_TUNE_START");
|
||||
}
|
||||
frsky_rx_strobe_rx();
|
||||
return 1000;
|
||||
}
|
||||
@@ -365,62 +471,96 @@ uint16_t FrSky_Rx_callback()
|
||||
return 18000;
|
||||
|
||||
case FRSKY_RX_BIND:
|
||||
if(len >= packet_length) {
|
||||
CC2500_ReadData(packet, packet_length);
|
||||
if (frskyx_rx_check_crc()) {
|
||||
if (packet[5] <= 0x2D) {
|
||||
if (len == packet_length + 2) //+2=RSSI+LQI+CRC
|
||||
{
|
||||
CC2500_ReadData(packet, len);
|
||||
if(frskyx_rx_check_crc_id(true,false)) {
|
||||
if(frsky_rx_format != FRSKY_RX_D16v2LBT && frsky_rx_format != FRSKY_RX_D16v2FCC)
|
||||
{// D8 & D16v1
|
||||
if(packet[5] <= 0x2D)
|
||||
{
|
||||
for (ch = 0; ch < 5; ch++)
|
||||
hopping_frequency[packet[5]+ch] = packet[6+ch];
|
||||
state |= 1 << (packet[5] / 5);
|
||||
}
|
||||
}
|
||||
if (state == 0x3ff) {
|
||||
debugln("bind complete");
|
||||
frsky_rx_calibrate();
|
||||
rx_tx_addr[0] = packet[3]; // TXID
|
||||
rx_tx_addr[1] = packet[4]; // TXID
|
||||
rx_tx_addr[2] = packet[12]; // RX # (D16)
|
||||
CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // FS_AUTOCAL = manual
|
||||
CC2500_WriteReg(CC2500_09_ADDR, rx_tx_addr[0]); // set address
|
||||
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05); // check address
|
||||
phase = FRSKY_RX_DATA;
|
||||
frsky_rx_set_channel(hopping_frequency_no);
|
||||
else
|
||||
state = 0x3FF; //No hop table for D16v2
|
||||
if (state == 0x3FF)
|
||||
{
|
||||
debugln("Bind complete");
|
||||
BIND_DONE;
|
||||
// store format, finetune setting, txid, channel list
|
||||
uint16_t temp = FRSKY_RX_EEPROM_OFFSET;
|
||||
if(sub_protocol==FRSKY_CLONE)
|
||||
{
|
||||
if(frsky_rx_format==FRSKY_RX_D8)
|
||||
temp=FRSKYD_CLONE_EEPROM_OFFSET;
|
||||
else if(frsky_rx_format == FRSKY_RX_D16FCC || frsky_rx_format == FRSKY_RX_D16LBT)
|
||||
temp=FRSKYX_CLONE_EEPROM_OFFSET;
|
||||
else
|
||||
temp=FRSKYX2_CLONE_EEPROM_OFFSET;
|
||||
}
|
||||
eeprom_write_byte((EE_ADDR)temp++, frsky_rx_format);
|
||||
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[0]);
|
||||
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[1]);
|
||||
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[3]);
|
||||
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[2]);
|
||||
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[1]);
|
||||
if(sub_protocol==FRSKY_RX)
|
||||
eeprom_write_byte((EE_ADDR)temp++, frsky_rx_finetune);
|
||||
if(frsky_rx_format != FRSKY_RX_D16v2FCC && frsky_rx_format != FRSKY_RX_D16v2LBT)
|
||||
for (ch = 0; ch < 47; ch++)
|
||||
eeprom_write_byte((EE_ADDR)temp++, hopping_frequency[ch]);
|
||||
BIND_DONE;
|
||||
frsky_rx_data();
|
||||
debugln("FRSKY_RX_DATA");
|
||||
}
|
||||
}
|
||||
frsky_rx_strobe_rx();
|
||||
}
|
||||
return 1000;
|
||||
|
||||
case FRSKY_RX_DATA:
|
||||
if (len >= packet_length) {
|
||||
CC2500_ReadData(packet, packet_length);
|
||||
if (packet[1] == rx_tx_addr[0] && packet[2] == rx_tx_addr[1] && frskyx_rx_check_crc() && (frsky_rx_format == FRSKY_RX_D8 || packet[6] == rx_tx_addr[2])) {
|
||||
RX_RSSI = packet[packet_length-2];
|
||||
if (len == packet_length + 2) //+2=RSSI+LQI+CRC
|
||||
{
|
||||
CC2500_ReadData(packet, len);
|
||||
if(frskyx_rx_check_crc_id(false,false))
|
||||
{
|
||||
RX_RSSI = packet[len-2];
|
||||
if(RX_RSSI >= 128)
|
||||
RX_RSSI -= 128;
|
||||
else
|
||||
RX_RSSI += 128;
|
||||
bool chanskip_valid=true;
|
||||
// hop to next channel
|
||||
if (frsky_rx_format == FRSKY_RX_D16FCC || frsky_rx_format == FRSKY_RX_D16LBT)
|
||||
frsky_rx_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2);
|
||||
if (frsky_rx_format != FRSKY_RX_D8)
|
||||
{//D16v1 & D16v2
|
||||
if(rx_data_started)
|
||||
{
|
||||
if(frsky_rx_chanskip != (((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2)))
|
||||
{
|
||||
chanskip_valid=false; // chanskip value has changed which surely indicates a bad frame
|
||||
packet_count++;
|
||||
if(packet_count>5) // the TX must have changed chanskip...
|
||||
frsky_rx_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); // chanskip init
|
||||
}
|
||||
else
|
||||
packet_count=0;
|
||||
}
|
||||
else
|
||||
frsky_rx_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); // chanskip init
|
||||
}
|
||||
hopping_frequency_no = (hopping_frequency_no + frsky_rx_chanskip) % 47;
|
||||
frsky_rx_set_channel(hopping_frequency_no);
|
||||
if (telemetry_link == 0) { // send channels to TX
|
||||
if(chanskip_valid)
|
||||
{
|
||||
if (telemetry_link == 0)
|
||||
{ // send channels to TX
|
||||
frsky_rx_build_telemetry_packet();
|
||||
telemetry_link = 1;
|
||||
}
|
||||
pps_counter++;
|
||||
}
|
||||
rx_data_started = true;
|
||||
read_retry = 0;
|
||||
pps_counter++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,6 +569,11 @@ uint16_t FrSky_Rx_callback()
|
||||
pps_timer = millis();
|
||||
debugln("%d pps", pps_counter);
|
||||
RX_LQI = pps_counter;
|
||||
if(pps_counter==0) // no packets for 1 sec or more...
|
||||
{// restart the search
|
||||
rx_data_started=false;
|
||||
packet_count=0;
|
||||
}
|
||||
pps_counter = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*/
|
||||
// Last sync with main deviation/sfhss_cc2500.c dated 2016-03-23
|
||||
|
||||
#if defined(SFHSS_CC2500_INO)
|
||||
#if defined(FUTABA_CC2500_INO)
|
||||
|
||||
#include "iface_cc2500.h"
|
||||
|
||||
@@ -16,7 +16,7 @@ Multiprotocol is distributed in the hope that it will be useful,
|
||||
|
||||
#if defined(GD00X_NRF24L01_INO)
|
||||
|
||||
#include "iface_xn297l.h"
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
//#define FORCE_GD00X_ORIGINAL_ID
|
||||
|
||||
|
||||
@@ -29,10 +29,21 @@ enum {
|
||||
HOTT_START = 0x00,
|
||||
HOTT_CAL = 0x01,
|
||||
HOTT_DATA1 = 0x02,
|
||||
HOTT_RX1 = 0x03,
|
||||
HOTT_RX2 = 0x04,
|
||||
HOTT_DATA2 = 0x03,
|
||||
HOTT_RX1 = 0x04,
|
||||
HOTT_RX2 = 0x05,
|
||||
};
|
||||
|
||||
#ifdef HOTT_FW_TELEMETRY
|
||||
#define HOTT_SENSOR_TYPE 6
|
||||
#define HOTT_SENSOR_SEARCH_PERIOD 2000
|
||||
uint8_t HOTT_sensor_cur=0;
|
||||
uint8_t HOTT_sensor_pages=0;
|
||||
uint8_t HOTT_sensor_valid=false;
|
||||
uint8_t HOTT_sensor_ok[HOTT_SENSOR_TYPE];
|
||||
uint8_t HOTT_sensor_seq=0;
|
||||
#endif
|
||||
|
||||
#define HOTT_FREQ0_VAL 0x6E
|
||||
|
||||
// Some important initialization parameters, all others are either default,
|
||||
@@ -134,33 +145,34 @@ static void __attribute__((unused)) HOTT_init()
|
||||
|
||||
for(uint8_t i=0; i<HOTT_NUM_RF_CHANNELS; i++)
|
||||
hopping_frequency[i]=pgm_read_byte_near( &HOTT_hop[num_ch][i] );
|
||||
|
||||
#ifdef HOTT_FORCE_ID
|
||||
memcpy(rx_tx_addr,"\x7C\x94\x00\x0D\x50",5);
|
||||
memcpy(rx_tx_addr,"\x7C\x94\x00\x0D\x50",5); //TX1
|
||||
memcpy(rx_tx_addr,"\xEA\x4D\x00\x01\x50",5); //TX2
|
||||
#endif
|
||||
memset(&packet[30],0xFF,9);
|
||||
packet[39]=0x07; // unknown and constant
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet[28] = 0x80; // unknown 0x80 when bind starts then when RX replies start normal, 0x89/8A/8B/8C/8D/8E during normal packets
|
||||
packet[29] = 0x02; // unknown 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets
|
||||
memset(&packet[40],0xFA,5);
|
||||
memcpy(&packet[45],rx_tx_addr,5);
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[28] = 0x8C; // unknown 0x80 when bind starts then when RX replies start normal, 0x89/8A/8B/8C/8D/8E during normal packets, 0x0F->config menu
|
||||
packet[29] = 0x02; // unknown 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets, 0x01->config menu, 0x0A->no more RX telemetry
|
||||
memcpy(&packet[40],rx_tx_addr,5);
|
||||
|
||||
uint8_t addr=HOTT_EEPROM_OFFSET+RX_num*5;
|
||||
debug("RXID: ");
|
||||
for(uint8_t i=0;i<5;i++)
|
||||
{
|
||||
packet[45+i]=eeprom_read_byte((EE_ADDR)(addr+i));
|
||||
debug(" %02X",packet[45+i]);
|
||||
}
|
||||
debugln("");
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) HOTT_data_packet()
|
||||
static void __attribute__((unused)) HOTT_prep_data_packet()
|
||||
{
|
||||
|
||||
packet[2] = hopping_frequency_no;
|
||||
|
||||
packet[3] = 0x00; // used for failsafe but may also be used for additional channels
|
||||
@@ -210,31 +222,45 @@ static void __attribute__((unused)) HOTT_data_packet()
|
||||
packet[i] = val;
|
||||
packet[i+1] = val>>8;
|
||||
}
|
||||
|
||||
#ifdef HOTT_FW_TELEMETRY
|
||||
static uint8_t prev_SerialRX_val=0;
|
||||
if(HoTT_SerialRX && HoTT_SerialRX_val >= 0xD7 && HoTT_SerialRX_val <= 0xDF)
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
static uint8_t prev_SerialRX_val=0;
|
||||
if(HoTT_SerialRX)
|
||||
{//Text mode
|
||||
uint8_t sensor=HoTT_SerialRX_val&0xF0;
|
||||
if((sensor&0x80) && sensor!=0xF0 && (HoTT_SerialRX_val&0x0F) >= 0x07)
|
||||
{//Valid Text query
|
||||
if(sensor==0x80) HoTT_SerialRX_val&=0x0F; // RX only
|
||||
if(prev_SerialRX_val!=HoTT_SerialRX_val)
|
||||
{
|
||||
prev_SerialRX_val=HoTT_SerialRX_val;
|
||||
packet[28] = HoTT_SerialRX_val; // send the touch being pressed only once
|
||||
packet[28] = HoTT_SerialRX_val; // send the button being pressed only once
|
||||
}
|
||||
else
|
||||
packet[28] = 0xDF; // no touch pressed
|
||||
packet[29] = 0x01; // 0x01->config menu
|
||||
packet[28] = HoTT_SerialRX_val | 0x0F; // no button pressed
|
||||
packet[29] = 0x01; // 0x01->Text config menu
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[28] = 0x8C; // unknown 0x80 when bind starts then when RX replies start normal, 0x89/8A/8B/8C/8D/8E during normal packets, 0x0F->config menu
|
||||
packet[29] = 0x02; // unknown 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets, 0x01->config menu, 0x0A->no more RX telemetry
|
||||
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]);
|
||||
}
|
||||
}
|
||||
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_SetTxRxMode(TX_EN);
|
||||
CC2500_SetPower();
|
||||
CC2500_WriteReg(CC2500_06_PKTLEN, 0x32);
|
||||
CC2500_WriteData(packet, HOTT_TX_PACKET_LEN);
|
||||
CC2500_WriteReg(CC2500_06_PKTLEN, HOTT_TX_PACKET_LEN);
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, packet, HOTT_TX_PACKET_LEN);
|
||||
#if 0
|
||||
debug("RF:%02X P:",rf_ch_num);
|
||||
for(uint8_t i=0;i<HOTT_TX_PACKET_LEN;i++)
|
||||
@@ -248,10 +274,6 @@ static void __attribute__((unused)) HOTT_data_packet()
|
||||
|
||||
uint16_t ReadHOTT()
|
||||
{
|
||||
#ifdef HOTT_FW_TELEMETRY
|
||||
static uint8_t pps_counter=0;
|
||||
#endif
|
||||
|
||||
switch(phase)
|
||||
{
|
||||
case HOTT_START:
|
||||
@@ -268,38 +290,86 @@ uint16_t ReadHOTT()
|
||||
hopping_frequency_no = 0;
|
||||
rf_ch_num=hopping_frequency[hopping_frequency_no];
|
||||
counter = 0;
|
||||
CC2500_SetTxRxMode(RX_EN);
|
||||
phase = HOTT_DATA1;
|
||||
}
|
||||
return 2000;
|
||||
|
||||
/* Work cycle: 10ms */
|
||||
case HOTT_DATA1:
|
||||
//TX
|
||||
//Set RF freq, setup LBT and prep packet
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(HOTT_PACKET_PERIOD);
|
||||
#endif
|
||||
//Clear all
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_Strobe(CC2500_SNOP);
|
||||
CC2500_Strobe(CC2500_SFTX);
|
||||
CC2500_Strobe(CC2500_SFRX);
|
||||
CC2500_WriteReg(CC2500_04_SYNC1, 0xD3);
|
||||
CC2500_WriteReg(CC2500_05_SYNC0, 0x91);
|
||||
//Set RF freq
|
||||
HOTT_tune_freq();
|
||||
HOTT_tune_chan_fast();
|
||||
HOTT_data_packet();
|
||||
phase = HOTT_RX1;
|
||||
return 4500;
|
||||
//Setup LBT
|
||||
CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xFF);
|
||||
CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x0C);
|
||||
CC2500_Strobe(CC2500_SRX);
|
||||
//Prep packet
|
||||
HOTT_prep_data_packet();
|
||||
//Listen
|
||||
CC2500_WriteReg(CC2500_17_MCSM1, 0x10); //??
|
||||
CC2500_WriteReg(CC2500_18_MCSM0, 0x18); //??
|
||||
CC2500_Strobe(CC2500_SRX); //??
|
||||
phase++; //HOTT_DATA2
|
||||
return 1095;
|
||||
case HOTT_DATA2:
|
||||
//LBT
|
||||
if((CC2500_ReadReg(CC2500_38_PKTSTATUS | CC2500_READ_BURST)&0x10)==0)
|
||||
{ //Channel is busy
|
||||
LBT_POWER_on; // Reduce to low power before transmitting
|
||||
debugln("Busy %d",rf_ch_num);
|
||||
}
|
||||
CC2500_WriteReg(CC2500_17_MCSM1, 0x00); //??
|
||||
CC2500_WriteReg(CC2500_18_MCSM0, 0x08); //??
|
||||
CC2500_SetPower();
|
||||
//Send packet
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
CC2500_Strobe(CC2500_STX);
|
||||
phase++; //HOTT_RX1
|
||||
return 3880;
|
||||
case HOTT_RX1:
|
||||
//Clear all
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_Strobe(CC2500_SFTX);
|
||||
CC2500_Strobe(CC2500_SFRX);
|
||||
//RX
|
||||
if(packet[29] & 0xF8)
|
||||
{// binary telemetry
|
||||
CC2500_WriteReg(CC2500_04_SYNC1, 0x2C);
|
||||
CC2500_WriteReg(CC2500_05_SYNC0, 0x6E);
|
||||
}
|
||||
CC2500_SetTxRxMode(RX_EN);
|
||||
CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xC7);
|
||||
CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x09);
|
||||
CC2500_WriteReg(CC2500_06_PKTLEN, HOTT_RX_PACKET_LEN);
|
||||
CC2500_Strobe(CC2500_SRX);
|
||||
phase = HOTT_RX2;
|
||||
return 4500;
|
||||
phase++; //HOTT_RX2
|
||||
return 4025;
|
||||
case HOTT_RX2:
|
||||
//Telemetry
|
||||
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||
if (len==HOTT_RX_PACKET_LEN+2)
|
||||
{
|
||||
CC2500_ReadData(packet_in, len);
|
||||
if(memcmp(rx_tx_addr,packet_in,5)==0)
|
||||
{ // TX ID matches
|
||||
if((packet_in[HOTT_RX_PACKET_LEN+1]&0x80) && memcmp(rx_tx_addr,packet_in,5)==0)
|
||||
{ // CRC OK and TX ID matches
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
//GR-16: D4 20 F2 E6 F6 31 BD 01 00 90 00 FF 03 00 9E 1B 00 00 00 00 00 00
|
||||
//GR-12L: D4 20 F2 E6 F6 6E EE 01 00 B1 00 FF 03 00 0E 08 10 00 02 00 00 00
|
||||
//Vector: D4 20 F2 E6 F6 00 00 3A 01 A1 00 00 1A 24 35 1A 00 24 00 00 00 1A
|
||||
// -----TXID----- -----RXID----- ---------------Unknown-------------
|
||||
debug("B:");
|
||||
for(uint8_t i=0;i<HOTT_RX_PACKET_LEN;i++)
|
||||
debug(" %02X", packet_in[i]);
|
||||
@@ -317,16 +387,16 @@ uint16_t ReadHOTT()
|
||||
// [5..9] = RXID
|
||||
// [10] = 0x40 bind, 0x00 normal, 0x80 config menu
|
||||
// [11] = telmetry pages. For sensors 0x00 to 0x04, for config mennu 0x00 to 0x12.
|
||||
// Normal telem page 0 = 0x00, 0x33, 0x34, 0x46, 0x64, 0x33, 0x0A, 0x00, 0x00, 0x00
|
||||
// = 0x55, 0x32, 0x38, 0x55, 0x64, 0x32, 0xD0, 0x07, 0x00, 0x55
|
||||
// Page 0 [12] = [21] = ??
|
||||
// Page 0 [13] = RX_Voltage*10 in V
|
||||
// Normal telem page 0 = 0x55, 0x32, 0x38, 0x55, 0x64, 0x32, 0xD0, 0x07, 0x00, 0x55
|
||||
// Page 0 [12] = [21] = [15]
|
||||
// Page 0 [13] = RX_Voltage Cur*10 in V
|
||||
// Page 0 [14] = Temperature-20 in °C
|
||||
// Page 0 [15] = RX_RSSI
|
||||
// Page 0 [16] = RX_LQI ??
|
||||
// Page 0 [17] = RX_STR ??
|
||||
// Page 0 [18,19] = [19]*256+[18]=max lost packet time in ms, max value seems 2s=0x7D0
|
||||
// Page 0 [15] = RX_RSSI CC2500 formated (a<128:a/2-71dBm, a>=128:(a-256)/2-71dBm)
|
||||
// Page 0 [16] = RX_LQI in %
|
||||
// Page 0 [17] = RX_Voltage Min*10 in V
|
||||
// Page 0 [18,19] = [19]<<8+[18]=max lost packet time in ms, max value seems 2s=0x7D0
|
||||
// Page 0 [20] = 0x00 ??
|
||||
//
|
||||
// Config menu consists of the different telem pages put all together
|
||||
// Page X [12] = seems like all the telem pages with the same value are going together to make the full config menu text. Seen so far 'a', 'b', 'c', 'd'
|
||||
// Page X [13..21] = 9 ascii chars to be displayed, char is highlighted when ascii|0x80
|
||||
@@ -334,22 +404,78 @@ uint16_t ReadHOTT()
|
||||
// Menu commands are sent through TX packets:
|
||||
// packet[28]= 0xXF=>no key press, 0xXD=>down, 0xXB=>up, 0xX9=>enter, 0xXE=>right, 0xX7=>left with X=0 or D
|
||||
// packet[29]= 0xX1/0xX9 with X=0 or X counting 0,1,1,2,2,..,9,9
|
||||
TX_RSSI = packet_in[22];
|
||||
if(TX_RSSI >=128)
|
||||
TX_RSSI -= 128;
|
||||
else
|
||||
TX_RSSI += 128;
|
||||
// Reduce telemetry to 14 bytes
|
||||
packet_in[0]= TX_RSSI;
|
||||
packet_in[0]= packet_in[HOTT_RX_PACKET_LEN];
|
||||
packet_in[1]= TX_LQI;
|
||||
debug("T=");
|
||||
bool send_telem=true;
|
||||
if(packet[29]==1)
|
||||
{ //Text mode
|
||||
HOTT_sensor_pages = 0;
|
||||
HOTT_sensor_valid = false;
|
||||
packet_in[10] = 0x80; // Marking telem Text mode
|
||||
packet_in[12] = 0;
|
||||
for(uint8_t i=0; i<HOTT_SENSOR_TYPE;i++)
|
||||
packet_in[12] |= HOTT_sensor_ok[i]<<i; // Send detected sensors
|
||||
}
|
||||
else
|
||||
{ //Binary sensor
|
||||
HOTT_sensor_seq++; // Increment RX sequence counter
|
||||
HOTT_sensor_seq %= 5; // 5 pages in binary mode per sensor
|
||||
if(state==0 && HOTT_sensor_ok[0]==false && HOTT_sensor_ok[1]==false && HOTT_sensor_ok[2]==false && HOTT_sensor_ok[3]==false && HOTT_sensor_ok[4]==false && HOTT_sensor_ok[5]==false)
|
||||
HOTT_sensor_seq=0; // No sensors always ask page 0
|
||||
if(state)
|
||||
state--;
|
||||
if( packet_in[11]==1 ) // Page 1
|
||||
{
|
||||
if( packet_in[12] == (HOTT_sensor_cur+9)<<4 )
|
||||
{ //Requested sensor is sending: 0x90/A0/B0/C0/D0/E0
|
||||
HOTT_sensor_pages = 0; // Sensor first page received
|
||||
HOTT_sensor_valid = true; // Data from the expected sensor is being received
|
||||
HOTT_sensor_ok[(packet_in[12]>>4)-9]=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
HOTT_sensor_valid = false;
|
||||
HOTT_sensor_pages = 0x1E; // Switch to next sensor
|
||||
}
|
||||
}
|
||||
if(packet_in[11])
|
||||
{ //Page != 0
|
||||
if(HOTT_sensor_valid) // Valid
|
||||
{
|
||||
packet_in[10] = HOTT_sensor_cur+9; // Mark telem with sensor ID
|
||||
HOTT_sensor_pages |= 1<<packet_in[11]; // Page received
|
||||
}
|
||||
else
|
||||
send_telem=false; // Do not send
|
||||
}
|
||||
else
|
||||
packet_in[10]=0; // Mark telem with sensor 0=RX
|
||||
}
|
||||
debug("T%d=",send_telem);
|
||||
for(uint8_t i=10;i < HOTT_RX_PACKET_LEN; i++)
|
||||
{
|
||||
packet_in[i-8]=packet_in[i];
|
||||
debug(" %02X",packet_in[i]);
|
||||
}
|
||||
debugln("");
|
||||
if(send_telem)
|
||||
telemetry_link=2;
|
||||
if((HOTT_sensor_pages&0x1E) == 0x1E) // All 4 pages received from the sensor
|
||||
{ //Next sensor
|
||||
uint8_t loop=0;
|
||||
do
|
||||
{
|
||||
HOTT_sensor_cur++; // Switch to next sensor
|
||||
HOTT_sensor_cur %= HOTT_SENSOR_TYPE;
|
||||
loop++;
|
||||
}
|
||||
while(HOTT_sensor_ok[HOTT_sensor_cur]==false && loop<HOTT_SENSOR_TYPE+1 && state==0);
|
||||
HOTT_sensor_valid=false;
|
||||
HOTT_sensor_pages=0;
|
||||
HOTT_sensor_seq=0;
|
||||
debugln("Sensor:%02X",HOTT_sensor_cur+9);
|
||||
}
|
||||
}
|
||||
pps_counter++;
|
||||
#endif
|
||||
@@ -360,10 +486,18 @@ uint16_t ReadHOTT()
|
||||
if(packet_count>=100)
|
||||
{
|
||||
TX_LQI=pps_counter;
|
||||
if(pps_counter==0)
|
||||
{ // lost connection with RX, power cycle? research sensors again.
|
||||
HOTT_sensor_cur=3;
|
||||
HOTT_sensor_seq=0;
|
||||
HOTT_sensor_valid=false;
|
||||
for(uint8_t i=0; i<HOTT_SENSOR_TYPE;i++)
|
||||
HOTT_sensor_ok[i]=false; // no sensors detected
|
||||
state=HOTT_SENSOR_SEARCH_PERIOD;
|
||||
}
|
||||
pps_counter=packet_count=0;
|
||||
}
|
||||
#endif
|
||||
CC2500_Strobe(CC2500_SFRX); //Flush the RXFIFO
|
||||
phase=HOTT_DATA1;
|
||||
return 1000;
|
||||
}
|
||||
@@ -375,10 +509,17 @@ uint16_t initHOTT()
|
||||
num_ch=random(0xfefefefe)%16;
|
||||
HOTT_init();
|
||||
HOTT_rf_init();
|
||||
packet_count=0;
|
||||
#ifdef HOTT_FW_TELEMETRY
|
||||
HoTT_SerialRX_val=0;
|
||||
HoTT_SerialRX=false;
|
||||
HOTT_sensor_cur=3;
|
||||
HOTT_sensor_pages=0;
|
||||
HOTT_sensor_valid=false;
|
||||
HOTT_sensor_seq=0;
|
||||
for(uint8_t i=0; i<HOTT_SENSOR_TYPE;i++)
|
||||
HOTT_sensor_ok[i]=false; // no sensors detected
|
||||
packet_count=0;
|
||||
state=HOTT_SENSOR_SEARCH_PERIOD;
|
||||
#endif
|
||||
phase = HOTT_START;
|
||||
return 10000;
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
*/
|
||||
// Compatible with FZ-410 TX
|
||||
|
||||
#if defined(FLYZONE_A7105_INO)
|
||||
#if defined(HEIGHT_A7105_INO)
|
||||
|
||||
#include "iface_a7105.h"
|
||||
|
||||
//#define FLYZONE_FORCEID
|
||||
//#define HEIGHT_FORCEID
|
||||
|
||||
#define FLYZONE_BIND_COUNT 220 // 5 sec
|
||||
#define FLYZONE_BIND_CH 0x18 // TX, RX for bind end is 0x17
|
||||
#define HEIGHT_BIND_COUNT 220 // 5 sec
|
||||
#define HEIGHT_BIND_CH 0x18 // TX, RX for bind end is 0x17
|
||||
|
||||
static void __attribute__((unused)) flyzone_build_packet()
|
||||
static void __attribute__((unused)) HEIGHT_build_packet()
|
||||
{
|
||||
packet[0] = 0xA5;
|
||||
packet[1] = rx_tx_addr[2];
|
||||
@@ -32,12 +32,18 @@ static void __attribute__((unused)) flyzone_build_packet()
|
||||
packet[4] = convert_channel_8b(ELEVATOR); //00..80..FF
|
||||
packet[5] = convert_channel_8b(THROTTLE); //00..FF
|
||||
packet[6] = convert_channel_8b(RUDDER); //00..80..FF
|
||||
packet[7] = 0xFF;
|
||||
packet[7] = convert_channel_8b(CH5); //00..80..FF
|
||||
if(sub_protocol == HEIGHT_8CH)
|
||||
{
|
||||
packet[8] = convert_channel_8b(CH6); //00..80..FF
|
||||
packet[9] = convert_channel_8b(CH7); //00..80..FF
|
||||
packet[10] = convert_channel_8b(CH8); //00..80..FF
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t ReadFlyzone()
|
||||
uint16_t ReadHeight()
|
||||
{
|
||||
#ifndef FORCE_FLYZONE_TUNING
|
||||
#ifndef FORCE_HEIGHT_TUNING
|
||||
A7105_AdjustLOBaseFreq(1);
|
||||
#endif
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
@@ -45,7 +51,7 @@ uint16_t ReadFlyzone()
|
||||
packet[0] = 0x1B;
|
||||
packet[1] = rx_tx_addr[2];
|
||||
packet[2] = rx_tx_addr[3];
|
||||
A7105_WriteData(3, FLYZONE_BIND_CH);
|
||||
A7105_WriteData(3, HEIGHT_BIND_CH);
|
||||
if (bind_counter--==0)
|
||||
BIND_DONE;
|
||||
return 22700;
|
||||
@@ -58,8 +64,8 @@ uint16_t ReadFlyzone()
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(20*1500);
|
||||
#endif
|
||||
flyzone_build_packet();
|
||||
A7105_WriteData(8, hopping_frequency[0]);
|
||||
HEIGHT_build_packet();
|
||||
A7105_WriteData(sub_protocol?11:8, hopping_frequency[0]);
|
||||
A7105_SetPower();
|
||||
}
|
||||
else
|
||||
@@ -72,14 +78,14 @@ uint16_t ReadFlyzone()
|
||||
return 1500;
|
||||
}
|
||||
|
||||
uint16_t initFlyzone()
|
||||
uint16_t initHeight()
|
||||
{
|
||||
A7105_Init();
|
||||
|
||||
hopping_frequency[0]=((random(0xfefefefe) & 0x0F)+2)<<2;
|
||||
hopping_frequency[1]=hopping_frequency[0]+0x50;
|
||||
|
||||
#ifdef FLYZONE_FORCEID
|
||||
#ifdef HEIGHT_FORCEID
|
||||
rx_tx_addr[2]=0x35;
|
||||
rx_tx_addr[3]=0xD0;
|
||||
hopping_frequency[0]=0x18;
|
||||
@@ -87,7 +93,7 @@ uint16_t initFlyzone()
|
||||
#endif
|
||||
|
||||
phase=255;
|
||||
bind_counter = FLYZONE_BIND_COUNT;
|
||||
bind_counter = HEIGHT_BIND_COUNT;
|
||||
return 2400;
|
||||
}
|
||||
#endif
|
||||
@@ -146,6 +146,11 @@ static void __attribute__((unused)) HITEC_build_packet()
|
||||
break;
|
||||
case 0x7B:
|
||||
packet[5]=hopping_frequency[13]>>1; // if not there the Optima link is jerky...
|
||||
packet[14]=0x2A;
|
||||
packet[15]=0x46; // unknown but if 0x45 then 17=0x46, if 0x46 then 17=0x46 or 0x47, if 0x47 then 0x45 or 0x46
|
||||
packet[16]=0x2A;
|
||||
packet[17]=0x47;
|
||||
packet[18]=0x2A;
|
||||
break;
|
||||
}
|
||||
if(sub_protocol==MINIMA)
|
||||
@@ -302,8 +307,8 @@ uint16_t ReadHITEC()
|
||||
{ // bind packet: 0A,00,E5,F2,7X,05,06,07,08,09,00
|
||||
debug(",bind");
|
||||
boolean check=true;
|
||||
for(uint8_t i=5;i<=10;i++)
|
||||
if(packet_in[i]!=i%10) check=false;
|
||||
for(uint8_t i=5;i<10;i++)
|
||||
if(packet_in[i]!=i) check=false;
|
||||
if((packet_in[4]&0xF0)==0x70 && check)
|
||||
{
|
||||
bind_phase=packet_in[4]+1;
|
||||
|
||||
195
Multiprotocol/JJRC345_nrf24l01.ino
Normal file
195
Multiprotocol/JJRC345_nrf24l01.ino
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// compatible with JJRC345
|
||||
|
||||
#if defined(JJRC345_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
//#define JJRC345_FORCE_ID
|
||||
|
||||
#define JJRC345_PACKET_PERIOD 7450 // Timeout for callback in uSec
|
||||
#define JJRC345_INITIAL_WAIT 500
|
||||
#define JJRC345_PACKET_SIZE 16
|
||||
#define JJRC345_RF_BIND_CHANNEL 5
|
||||
#define SKYTMBLR_RF_BIND_CHANNEL 40
|
||||
#define JJRC345_BIND_COUNT 500
|
||||
#define JJRC345_NUM_CHANNELS 4
|
||||
|
||||
|
||||
enum JJRC345_FLAGS {
|
||||
// flags going to packet[8]
|
||||
JJRC345_FLAG_HEADLESS = 0x40,
|
||||
JJRC345_FLAG_RTH = 0x80,
|
||||
// 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)
|
||||
{
|
||||
uint8_t val=convert_channel_8b(num);
|
||||
// 7E..60..41..01, 80 center, 81..C1..E0..FE
|
||||
if(val<0x80)
|
||||
{
|
||||
val=0x80-val; // 80..01
|
||||
if(val>0x7E)
|
||||
val=0x7E; // 7E..01
|
||||
}
|
||||
else if(val>0xFE)
|
||||
val=0xFE; // 81..FE
|
||||
return val;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) JJRC345_send_packet()
|
||||
{
|
||||
packet[0] = 0x00;
|
||||
packet[2] = 0x00;
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
{ //00 05 00 0A 46 4A 41 47 00 00 40 46 A5 4A F1 18
|
||||
packet[1] = (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];
|
||||
packet[7] = hopping_frequency[3];
|
||||
packet[12] = 0xa5;
|
||||
}
|
||||
else
|
||||
{ //00 41 00 0A 00 80 80 80 00 00 40 46 00 49 F1 18
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
|
||||
hopping_frequency_no++;
|
||||
hopping_frequency_no %= JJRC345_NUM_CHANNELS;
|
||||
packet[1] = hopping_frequency[hopping_frequency_no]; // next packet will be sent on this channel
|
||||
|
||||
packet[4] = convert_channel_8b(THROTTLE); // throttle: 00..FF
|
||||
packet[5] = JJRC345_convert_channel(RUDDER); // rudder: 70..60..41..01, 80 center, 81..C1..E0..F0
|
||||
packet[6] = JJRC345_convert_channel(ELEVATOR); // elevator: 70..60..41..01, 80 center, 81..C1..E0..F0
|
||||
packet[7] = JJRC345_convert_channel(AILERON); // aileron: 70..60..41..01, 80 center, 81..C1..E0..F0
|
||||
|
||||
if(CH5_SW) //Flip
|
||||
{
|
||||
if(packet[6]>0xF0)
|
||||
packet[6]=0xFF;
|
||||
else if(packet[6]<0x80 && packet[6]>0x70)
|
||||
packet[6]=0x7F;
|
||||
if(packet[7]>0xF0)
|
||||
packet[7]=0xFF;
|
||||
else if(packet[7]<0x80 && packet[7]>0x70)
|
||||
packet[7]=0x7F;
|
||||
}
|
||||
|
||||
packet[12] = 0x02; // Rate: 00-01-02
|
||||
}
|
||||
|
||||
packet[3] = 0x00; // Checksum upper bits
|
||||
|
||||
packet[8] = 0x00 // Rudder trim, 00 when not used, 01..1F when trimmed left, 20..3F
|
||||
| GET_FLAG(CH6_SW ,JJRC345_FLAG_HEADLESS) // 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
|
||||
|
||||
// Checksum
|
||||
uint16_t sum=2;
|
||||
for (uint8_t i = 0; i < 13; i++)
|
||||
sum += packet[i];
|
||||
packet[13]=sum;
|
||||
packet[3]=((sum>>8)<<2)+2;
|
||||
|
||||
// TX ID
|
||||
packet[14] = rx_tx_addr[2];
|
||||
packet[15] = rx_tx_addr[3];
|
||||
|
||||
// Power on, TX mode
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
XN297_WritePayload(packet, JJRC345_PACKET_SIZE);
|
||||
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) JJRC345_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
XN297_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, sub_protocol == JJRC345 ? JJRC345_RF_BIND_CHANNEL:SKYTMBLR_RF_BIND_CHANNEL); // Bind channel
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1 Mbps
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
uint16_t JJRC345_callback()
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(JJRC345_PACKET_PERIOD);
|
||||
#endif
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
if (bind_counter)
|
||||
bind_counter--;
|
||||
else
|
||||
BIND_DONE;
|
||||
}
|
||||
JJRC345_send_packet();
|
||||
return JJRC345_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) JJRC345_initialize_txid()
|
||||
{
|
||||
calc_fh_channels(JJRC345_NUM_CHANNELS);
|
||||
|
||||
#ifdef JJRC345_FORCE_ID
|
||||
//TX 1
|
||||
rx_tx_addr[2]=0x1B;
|
||||
rx_tx_addr[3]=0x12;
|
||||
hopping_frequency[0] = 0x3f;
|
||||
hopping_frequency[1] = 0x49;
|
||||
hopping_frequency[2] = 0x47;
|
||||
hopping_frequency[3] = 0x47;
|
||||
//TX 2
|
||||
rx_tx_addr[2]=0xF1;
|
||||
rx_tx_addr[3]=0x18;
|
||||
hopping_frequency[0] = 0x46;
|
||||
hopping_frequency[1] = 0x4A;
|
||||
hopping_frequency[2] = 0x41;
|
||||
hopping_frequency[3] = 0x47;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t initJJRC345(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
bind_counter = JJRC345_BIND_COUNT;
|
||||
JJRC345_initialize_txid();
|
||||
JJRC345_init();
|
||||
return JJRC345_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -16,7 +16,7 @@ Multiprotocol is distributed in the hope that it will be useful,
|
||||
|
||||
#if defined(KF606_NRF24L01_INO)
|
||||
|
||||
#include "iface_xn297l.h"
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
//#define FORCE_KF606_ORIGINAL_ID
|
||||
|
||||
|
||||
202
Multiprotocol/Kyosho_a7105.ino
Normal file
202
Multiprotocol/Kyosho_a7105.ino
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(KYOSHO_A7105_INO)
|
||||
|
||||
#include "iface_a7105.h"
|
||||
|
||||
//#define KYOSHO_FORCE_ID_FHSS
|
||||
//#define KYOSHO_FORCE_ID_HYPE
|
||||
|
||||
//Kyosho constants & variables
|
||||
#define KYOSHO_BIND_COUNT 2500
|
||||
|
||||
static void __attribute__((unused)) kyosho_send_packet()
|
||||
{
|
||||
//ID
|
||||
packet[1] = rx_tx_addr[0];
|
||||
packet[2] = rx_tx_addr[1];
|
||||
packet[3] = rx_tx_addr[2];
|
||||
packet[4] = rx_tx_addr[3];
|
||||
//unknown may be RX ID on some other remotes
|
||||
memset(packet+5,0xFF,4);
|
||||
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet[ 0] = 0xBC; // bind indicator
|
||||
packet[ 9] &= 0x01;
|
||||
packet[ 9] ^= 0x01; // high/ low part of the RF table
|
||||
packet[10] = 0x00;
|
||||
//RF table
|
||||
for(uint8_t i=0; i<16;i++)
|
||||
packet[i+11]=hopping_frequency[i+(packet[9]<<4)];
|
||||
//unknwon
|
||||
packet[27] = 0x05;
|
||||
packet[28] = 0x00;
|
||||
memset(packet+29,0xFF,8);
|
||||
//frequency hop during bind
|
||||
if(packet[9])
|
||||
rf_ch_num=0x8C;
|
||||
else
|
||||
rf_ch_num=0x0D;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[ 0] = 0x58; // normal packet
|
||||
//14 channels: steering, throttle, ...
|
||||
for(uint8_t i = 0; i < 14; i++)
|
||||
{
|
||||
uint16_t temp=convert_channel_ppm(i);
|
||||
packet[9 + i*2]=temp&0xFF; // low byte of servo timing(1000-2000us)
|
||||
packet[10 + i*2]=(temp>>8)&0xFF; // high byte of servo timing(1000-2000us)
|
||||
}
|
||||
rf_ch_num=hopping_frequency[hopping_frequency_no];
|
||||
hopping_frequency_no++;
|
||||
packet[34] |= (hopping_frequency_no&0x0F)<<4;
|
||||
packet[36] |= (hopping_frequency_no&0xF0); // last byte is ending with F on the dumps so let's see
|
||||
hopping_frequency_no &= 0x1F;
|
||||
}
|
||||
#if 0
|
||||
debug("ch=%02X P=",rf_ch_num);
|
||||
for(uint8_t i=0; i<37; i++)
|
||||
debug("%02X ", packet[i]);
|
||||
debugln("");
|
||||
#endif
|
||||
A7105_WriteData(37, rf_ch_num);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) kyosho_hype_send_packet()
|
||||
{
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
if(packet_sent==0)
|
||||
{//build the packet and send it
|
||||
packet[0] = rx_tx_addr[1];
|
||||
packet[1] = rx_tx_addr[3];
|
||||
//RF table
|
||||
for(uint8_t i=0; i<15;i++)
|
||||
packet[i+2]=hopping_frequency[i];
|
||||
A7105_WriteData(17, 0x01);
|
||||
packet_sent++;
|
||||
packet_period=1421;
|
||||
#if 0
|
||||
debug("ch=01 P=");
|
||||
for(uint8_t i=0; i<17; i++)
|
||||
debug("%02X ", packet[i]);
|
||||
debugln("");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
A7105_Strobe(A7105_TX); //only send
|
||||
}
|
||||
else
|
||||
{
|
||||
//original TX is only refreshing the packet every 20ms and keep repeating the same packet in between (STROBE_TX)
|
||||
//build packet=6 channels with order AETR
|
||||
for(uint8_t i=0;i<6;i++)
|
||||
packet[i] = convert_channel_8b(CH_AETR[i]);
|
||||
//set RF channel
|
||||
rf_ch_num=hopping_frequency[hopping_frequency_no];
|
||||
hopping_frequency_no++;
|
||||
if(hopping_frequency_no>14)
|
||||
hopping_frequency_no = 0;
|
||||
//send it
|
||||
A7105_WriteData(6, rf_ch_num);
|
||||
packet_period=931; //packet period fluctuates a lot on the original TX from one packet to the other but stable if looking over a period of 40ms
|
||||
#if 0
|
||||
debug("ch=%02X P=",rf_ch_num);
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
debug("%02X ", packet[i]);
|
||||
debugln("");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t ReadKyosho()
|
||||
{
|
||||
#ifndef FORCE_KYOSHO_TUNING
|
||||
A7105_AdjustLOBaseFreq(1);
|
||||
#endif
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
bind_counter--;
|
||||
if (bind_counter==0)
|
||||
{
|
||||
BIND_DONE;
|
||||
if(sub_protocol==KYOSHO_HYPE)
|
||||
{
|
||||
A7105_WriteID(MProtocol_id);
|
||||
A7105_WriteReg(A7105_03_FIFOI,0x05);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(hopping_frequency_no==0)
|
||||
A7105_SetPower();
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
}
|
||||
if(sub_protocol==KYOSHO_FHSS)
|
||||
kyosho_send_packet();
|
||||
else//HYPE
|
||||
kyosho_hype_send_packet();
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
uint16_t initKyosho()
|
||||
{
|
||||
A7105_Init();
|
||||
|
||||
// compute channels from ID
|
||||
calc_fh_channels(sub_protocol==KYOSHO_FHSS?32:15);
|
||||
hopping_frequency_no=0;
|
||||
|
||||
#ifdef KYOSHO_FORCE_ID_FHSS
|
||||
if(sub_protocol==KYOSHO_FHSS)
|
||||
{
|
||||
memcpy(rx_tx_addr,"\x3A\x39\x37\x00",4);
|
||||
memcpy(hopping_frequency,"\x29\x4C\x67\x92\x31\x1C\x77\x18\x23\x6E\x81\x5C\x8F\x5A\x51\x94\x7A\x12\x45\x6C\x7F\x1E\x0D\x88\x63\x8C\x4F\x37\x26\x61\x2C\x8A",32);
|
||||
}
|
||||
#endif
|
||||
if(sub_protocol==KYOSHO_HYPE)
|
||||
{
|
||||
MProtocol_id &= 0x00FF00FF;
|
||||
rx_tx_addr[0] = 0xAF - (rx_tx_addr[1]&0x0F);
|
||||
rx_tx_addr[2] = 0xFF - rx_tx_addr[3];
|
||||
MProtocol_id |= (rx_tx_addr[0]<<24) + (rx_tx_addr[2]<<8);
|
||||
#ifdef KYOSHO_FORCE_ID_HYPE
|
||||
MProtocol_id=0xAF90738C;
|
||||
set_rx_tx_addr(MProtocol_id);
|
||||
memcpy(hopping_frequency,"\x27\x1B\x63\x75\x03\x39\x57\x69\x87\x0F\x7B\x3F\x33\x51\x6F",15);
|
||||
#endif
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
A7105_WriteID(0xAF00FF00);
|
||||
else
|
||||
{
|
||||
A7105_WriteID(MProtocol_id);
|
||||
A7105_WriteReg(A7105_03_FIFOI,0x05);
|
||||
}
|
||||
}
|
||||
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
bind_counter = KYOSHO_BIND_COUNT;
|
||||
|
||||
packet_sent=0;
|
||||
packet_period=3852; //FHSS
|
||||
return 2000;
|
||||
}
|
||||
#endif
|
||||
@@ -18,7 +18,7 @@
|
||||
#if defined(MJXQ_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
#include "iface_xn297l.h"
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
#define MJXQ_BIND_COUNT 150
|
||||
#define MJXQ_PACKET_PERIOD 4000 // Timeout for callback in uSec
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
1,Flysky,Flysky,V9x9,V6x6,V912,CX20
|
||||
2,Hubsan,H107,H301,H501
|
||||
3,FrskyD
|
||||
3,FrskyD,D8,Cloned
|
||||
4,Hisky,Hisky,HK310
|
||||
5,V2x2,V2x2,JXD506
|
||||
6,DSM,DSM2-22,DSM2-11,DSMX-22,DSMX-11,AUTO
|
||||
5,V2x2,V2x2,JXD506,MR101
|
||||
6,DSM,DSM2_1F,DSM2_2F,DSMX_1F,DSMX_2F,AUTO
|
||||
7,Devo,8CH,10CH,12CH,6CH,7CH
|
||||
8,YD717,YD717,SKYWLKR,SYMAX4,XINXUN,NIHUI
|
||||
9,KN,WLTOYS,FEILUN
|
||||
@@ -11,28 +11,28 @@
|
||||
11,SLT,SLT_V1,SLT_V2,Q100,Q200,MR100
|
||||
12,CX10,GREEN,BLUE,DM007,---,J3015_1,J3015_2,MK33041
|
||||
13,CG023,CG023,YD829
|
||||
14,Bayang,Bayang,H8S3D,X16_AH,IRDRONE,DHD_D4
|
||||
15,FrskyX,CH_16,CH_8,EU_16,EU_8
|
||||
16,ESky,4CH,7CH
|
||||
14,Bayang,Bayang,H8S3D,X16_AH,IRDRONE,DHD_D4,QX100
|
||||
15,FrskyX,CH_16,CH_8,EU_16,EU_8,Cloned,Clon_8
|
||||
16,ESky,Std,ET4
|
||||
17,MT99xx,MT,H7,YZ,LS,FY805
|
||||
18,MJXq,WLH08,X600,X800,H26D,E010,H26WH,PHOENIX
|
||||
19,Shenqi
|
||||
20,FY326,FY326,FY319
|
||||
21,SFHSS
|
||||
21,Futaba,SFHSS
|
||||
22,J6PRO
|
||||
23,FQ777
|
||||
24,ASSAN
|
||||
25,FrskyV
|
||||
26,HONTAI,HONTAI,JJRCX1,X5C1,FQ777_951
|
||||
27,OpnLrs
|
||||
28,AFHDS2A,PWM_IBUS,PPM_IBUS,PWM_SBUS,PPM_SBUS
|
||||
28,AFHDS2A,PWM_IBUS,PPM_IBUS,PWM_SBUS,PPM_SBUS,PWM_IB16,PPM_IB16
|
||||
29,Q2X2,Q222,Q242,Q282
|
||||
30,WK2x01,WK2801,WK2401,W6_5_1,W6_6_1,W6_HEL,W6_HEL_I
|
||||
31,Q303,Q303,CX35,CX10D,CX10WD
|
||||
32,GW008
|
||||
33,DM002
|
||||
34,CABELL,CAB_V3,C_TELEM,-,-,-,-,F_SAFE,UNBIND
|
||||
35,ESKY150
|
||||
35,ESKY150,4CH,7CH
|
||||
36,H8_3D,H8_3D,H20H,H20Mini,H30Mini
|
||||
37,CORONA,COR_V1,COR_V2,FD_V3
|
||||
38,CFlie
|
||||
@@ -43,17 +43,36 @@
|
||||
43,Traxxas,RX6519
|
||||
44,NCC1701
|
||||
45,E01X,E012,E015,E016H
|
||||
46,V911S
|
||||
47,GD00X,GD_V1,GD_V2
|
||||
48,V761
|
||||
46,V911S,V911S,E119
|
||||
47,GD00x,GD_V1,GD_V2
|
||||
48,V761,3CH,4CH
|
||||
49,KF606
|
||||
50,Redpine,Fast,Slow
|
||||
51,Potensic,A20
|
||||
52,ZSX,280
|
||||
53,Flyzone,FZ-410
|
||||
53,Height,5ch,8ch
|
||||
54,Scanner
|
||||
55,Frsky_RX
|
||||
55,Frsky_RX,RX,CloneTX
|
||||
56,AFHDS2A_RX
|
||||
57,HoTT
|
||||
57,HoTT,Sync,No_Sync
|
||||
58,FX816,P38
|
||||
63,XN_DUMP,250K,1M,2M
|
||||
59,Bayang_RX
|
||||
60,Pelikan,Pro,Lite
|
||||
61,Tiger
|
||||
62,XK,X450,X420
|
||||
63,XN_DUMP,250K,1M,2M,AUTO
|
||||
64,FrskyX2,CH_16,CH_8,EU_16,EU_8,Cloned
|
||||
65,FrSkyR9,915MHz,868MHz,915_8ch,868_8ch,FCC,--,FCC_8ch,--_8ch
|
||||
66,PROPEL,74-Z
|
||||
67,LR12,LR12,LR12_6ch
|
||||
68,Skyartec
|
||||
69,ESKYv2,150V2
|
||||
70,DSM_RX
|
||||
71,JJRC345,JJRC345,SkyTmblr
|
||||
72,Q90C
|
||||
73,Kyosho,FHSS,Hype
|
||||
74,RadioLink,Surface,Air
|
||||
75,---
|
||||
76,Realacc,R11
|
||||
77,OMP
|
||||
78,M-Link
|
||||
|
||||
@@ -21,6 +21,7 @@ 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";
|
||||
@@ -29,26 +30,31 @@ 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_FUTABA[] ="Futaba";
|
||||
const char STR_J6PRO[] ="J6 Pro";
|
||||
const char STR_JJRC345[] ="JJRC345";
|
||||
const char STR_FQ777[] ="FQ777";
|
||||
const char STR_ASSAN[] ="Assan";
|
||||
const char STR_FRSKYV[] ="FrSky V";
|
||||
const char STR_HONTAI[] ="Hontai";
|
||||
const char STR_AFHDS2A[] ="FSky 2A";
|
||||
const char STR_AFHDS2A[] ="FlSky2A";
|
||||
const char STR_Q2X2[] ="Q2x2";
|
||||
const char STR_WK2x01[] ="Walkera";
|
||||
const char STR_Q303[] ="Q303";
|
||||
const char STR_Q90C[] ="Q90C";
|
||||
const char STR_GW008[] ="GW008";
|
||||
const char STR_DM002[] ="DM002";
|
||||
const char STR_CABELL[] ="Cabell";
|
||||
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";
|
||||
@@ -60,27 +66,41 @@ 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_GD00X[] ="GD00x";
|
||||
const char STR_V761[] ="V761";
|
||||
const char STR_KF606[] ="KF606";
|
||||
const char STR_REDPINE[] ="Redpine";
|
||||
const char STR_POTENSIC[] ="Potensi";
|
||||
const char STR_ZSX[] ="ZSX";
|
||||
const char STR_FLYZONE[] ="FlyZone";
|
||||
const char STR_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_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20";
|
||||
const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501";
|
||||
const char STR_SUBTYPE_FRSKYX[] = "\x07""D16\0 ""D16 8ch""LBT(EU)""LBT 8ch";
|
||||
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";
|
||||
const char STR_SUBTYPE_DSM[] = "\x06""2 22ms""2 11ms""X 22ms""X 11ms";
|
||||
const char STR_SUBTYPE_V2X2[] = "\x06""Std\0 ""JXD506""MR101\0";
|
||||
const char STR_SUBTYPE_DSM[] = "\x04""2 1F""2 2F""X 1F""X 2F""Auto";
|
||||
const char STR_SUBTYPE_DEVO[] = "\x04""8ch\0""10ch""12ch""6ch\0""7ch\0";
|
||||
const char STR_SUBTYPE_YD717[] = "\x07""Std\0 ""SkyWlkr""Syma X4""XINXUN\0""NIHUI\0 ";
|
||||
const char STR_SUBTYPE_KN[] = "\x06""WLtoys""FeiLun";
|
||||
@@ -88,12 +108,12 @@ const char STR_SUBTYPE_SYMAX[] = "\x03""Std""X5C";
|
||||
const char STR_SUBTYPE_SLT[] = "\x06""V1_6ch""V2_8ch""Q100\0 ""Q200\0 ""MR100\0";
|
||||
const char STR_SUBTYPE_CX10[] = "\x07""Green\0 ""Blue\0 ""DM007\0 ""-\0 ""JC3015a""JC3015b""MK33041";
|
||||
const char STR_SUBTYPE_CG023[] = "\x05""Std\0 ""YD829";
|
||||
const char STR_SUBTYPE_BAYANG[] = "\x07""Std\0 ""H8S3D\0 ""X16 AH\0""IRDrone""DHD D4";
|
||||
const char STR_SUBTYPE_BAYANG[] = "\x07""Std\0 ""H8S3D\0 ""X16 AH\0""IRDrone""DHD D4\0""QX100\0 ";
|
||||
const char STR_SUBTYPE_MT99[] = "\x06""MT99\0 ""H7\0 ""YZ\0 ""LS\0 ""FY805";
|
||||
const char STR_SUBTYPE_MJXQ[] = "\x07""WLH08\0 ""X600\0 ""X800\0 ""H26D\0 ""E010\0 ""H26WH\0 ""Phoenix";
|
||||
const char STR_SUBTYPE_FY326[] = "\x05""Std\0 ""FY319";
|
||||
const char STR_SUBTYPE_HONTAI[] = "\x07""Std\0 ""JJRC X1""X5C1\0 ""FQ_951";
|
||||
const char STR_SUBTYPE_AFHDS2A[] = "\x08""PWM,IBUS""PPM,IBUS""PWM,SBUS""PPM,SBUS";
|
||||
const char STR_SUBTYPE_AFHDS2A[] = "\x08""PWM,IBUS""PPM,IBUS""PWM,SBUS""PPM,SBUS""PWM,IB16""PPM,IB16""PWM,SB16""PPM,SB16";
|
||||
const char STR_SUBTYPE_Q2X2[] = "\x04""Q222""Q242""Q282";
|
||||
const char STR_SUBTYPE_WK2x01[] = "\x06""WK2801""WK2401""W6_5_1""W6_6_1""W6_HeL""W6_HeI";
|
||||
const char STR_SUBTYPE_Q303[] = "\x06""Std\0 ""CX35\0 ""CX10D\0""CX10WD";
|
||||
@@ -108,10 +128,27 @@ const char STR_SUBTYPE_GD00X[] = "\x05""GD_V1""GD_V2";
|
||||
const char STR_SUBTYPE_REDPINE[] = "\x04""Fast""Slow";
|
||||
const char STR_SUBTYPE_POTENSIC[] = "\x03""A20";
|
||||
const char STR_SUBTYPE_ZSX[] = "\x07""280JJRC";
|
||||
const char STR_SUBTYPE_FLYZONE[] = "\x05""FZ410";
|
||||
const char STR_SUBTYPE_HEIGHT[] = "\x03""5ch""8ch";
|
||||
const char STR_SUBTYPE_FX816[] = "\x03""P38";
|
||||
const char STR_SUBTYPE_XN297DUMP[] = "\x07""250Kbps""1Mbps\0 ""2Mbps\0 ";
|
||||
const char STR_SUBTYPE_ESKY150[] = "\x03""4CH""7CH";
|
||||
const char STR_SUBTYPE_XN297DUMP[] = "\x07""250Kbps""1Mbps\0 ""2Mbps\0 ""Auto\0 ""NRF\0 ";
|
||||
const char STR_SUBTYPE_ESKY150[] = "\x03""4ch""7ch";
|
||||
const char STR_SUBTYPE_ESKY150V2[] = "\x05""150V2";
|
||||
const char STR_SUBTYPE_V911S[] = "\x05""V911S""E119\0";
|
||||
const char STR_SUBTYPE_XK[] = "\x04""X450""X420";
|
||||
const char STR_SUBTYPE_FRSKYR9[] = "\x07""915MHz\0""868MHz\0""915 8ch""868 8ch""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";
|
||||
const char STR_SUBTYPE_KYOSHO[] = "\x04""FHSS""Hype";
|
||||
const char STR_SUBTYPE_FUTABA[] = "\x05""SFHSS";
|
||||
const char STR_SUBTYPE_JJRC345[] = "\x08""JJRC345\0""SkyTmblr";
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -123,129 +160,22 @@ enum
|
||||
OPTION_TELEM,
|
||||
OPTION_SRVFREQ,
|
||||
OPTION_MAXTHR,
|
||||
OPTION_RFCHAN
|
||||
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(FLYSKY_A7105_INO)
|
||||
{PROTO_FLYSKY, STR_FLYSKY, 5, STR_SUBTYPE_FLYSKY, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(HUBSAN_A7105_INO)
|
||||
{PROTO_HUBSAN, STR_HUBSAN, 3, STR_SUBTYPE_HUBSAN, OPTION_VIDFREQ },
|
||||
#endif
|
||||
#if defined(FRSKYD_CC2500_INO)
|
||||
{PROTO_FRSKYD, STR_FRSKYD, 0, NO_SUBTYPE, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(HISKY_NRF24L01_INO)
|
||||
{PROTO_HISKY, STR_HISKY, 2, STR_SUBTYPE_HISKY, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(V2X2_NRF24L01_INO)
|
||||
{PROTO_V2X2, STR_V2X2, 2, STR_SUBTYPE_V2X2, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(DSM_CYRF6936_INO)
|
||||
{PROTO_DSM, STR_DSM, 4, STR_SUBTYPE_DSM, OPTION_MAXTHR },
|
||||
#endif
|
||||
#if defined(DEVO_CYRF6936_INO)
|
||||
{PROTO_DEVO, STR_DEVO, 5, STR_SUBTYPE_DEVO, OPTION_FIXEDID },
|
||||
#endif
|
||||
#if defined(YD717_NRF24L01_INO)
|
||||
{PROTO_YD717, STR_YD717, 5, STR_SUBTYPE_YD717, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(KN_NRF24L01_INO)
|
||||
{PROTO_KN, STR_KN, 2, STR_SUBTYPE_KN, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(SYMAX_NRF24L01_INO)
|
||||
{PROTO_SYMAX, STR_SYMAX, 2, STR_SUBTYPE_SYMAX, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(SLT_NRF24L01_INO)
|
||||
{PROTO_SLT, STR_SLT, 5, STR_SUBTYPE_SLT, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(CX10_NRF24L01_INO)
|
||||
{PROTO_CX10, STR_CX10, 7, STR_SUBTYPE_CX10, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(CG023_NRF24L01_INO)
|
||||
{PROTO_CG023, STR_CG023, 2, STR_SUBTYPE_CG023, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(BAYANG_NRF24L01_INO)
|
||||
{PROTO_BAYANG, STR_BAYANG, 5, STR_SUBTYPE_BAYANG, OPTION_TELEM },
|
||||
#endif
|
||||
#if defined(FRSKYX_CC2500_INO)
|
||||
{PROTO_FRSKYX, STR_FRSKYX, 4, STR_SUBTYPE_FRSKYX, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(ESKY_NRF24L01_INO)
|
||||
{PROTO_ESKY, STR_ESKY, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(MT99XX_NRF24L01_INO)
|
||||
{PROTO_MT99XX, STR_MT99XX, 5, STR_SUBTYPE_MT99, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(MJXQ_NRF24L01_INO)
|
||||
{PROTO_MJXQ, STR_MJXQ, 7, STR_SUBTYPE_MJXQ, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(SHENQI_NRF24L01_INO)
|
||||
{PROTO_SHENQI, STR_SHENQI, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(FY326_NRF24L01_INO)
|
||||
{PROTO_FY326, STR_FY326, 2, STR_SUBTYPE_FY326, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(SFHSS_CC2500_INO)
|
||||
{PROTO_SFHSS, STR_SFHSS, 0, NO_SUBTYPE, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(J6PRO_CYRF6936_INO)
|
||||
{PROTO_J6PRO, STR_J6PRO, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(FQ777_NRF24L01_INO)
|
||||
{PROTO_FQ777, STR_FQ777, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(ASSAN_NRF24L01_INO)
|
||||
{PROTO_ASSAN, STR_ASSAN, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(FRSKYV_CC2500_INO)
|
||||
{PROTO_FRSKYV, STR_FRSKYV, 0, NO_SUBTYPE, OPTION_RFTUNE },
|
||||
#if defined(BAYANG_NRF24L01_INO)
|
||||
{PROTO_BAYANG, STR_BAYANG, 6, STR_SUBTYPE_BAYANG, OPTION_TELEM },
|
||||
#endif
|
||||
#if defined(HONTAI_NRF24L01_INO)
|
||||
{PROTO_HONTAI, STR_HONTAI, 4, STR_SUBTYPE_HONTAI, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(AFHDS2A_A7105_INO)
|
||||
{PROTO_AFHDS2A, STR_AFHDS2A, 4, STR_SUBTYPE_AFHDS2A, OPTION_SRVFREQ },
|
||||
#endif
|
||||
#if defined(CX10_NRF24L01_INO)
|
||||
{PROTO_Q2X2, STR_Q2X2, 3, STR_SUBTYPE_Q2X2, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(WK2x01_CYRF6936_INO)
|
||||
{PROTO_WK2x01, STR_WK2x01, 6, STR_SUBTYPE_WK2x01, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(Q303_NRF24L01_INO)
|
||||
{PROTO_Q303, STR_Q303, 4, STR_SUBTYPE_Q303, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(GW008_NRF24L01_INO)
|
||||
{PROTO_GW008, STR_GW008, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(DM002_NRF24L01_INO)
|
||||
{PROTO_DM002, STR_DM002, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(CABELL_NRF24L01_INO)
|
||||
{PROTO_CABELL, STR_CABELL, 8, STR_SUBTYPE_CABELL, OPTION_OPTION },
|
||||
#endif
|
||||
#if defined(ESKY150_NRF24L01_INO)
|
||||
{PROTO_ESKY150, STR_ESKY150, 2, STR_SUBTYPE_ESKY150, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(H8_3D_NRF24L01_INO)
|
||||
{PROTO_H8_3D, STR_H8_3D, 4, STR_SUBTYPE_H83D, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(CORONA_CC2500_INO)
|
||||
{PROTO_CORONA, STR_CORONA, 3, STR_SUBTYPE_CORONA, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(CFLIE_NRF24L01_INO)
|
||||
{PROTO_CFLIE, STR_CFLIE, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(HITEC_CC2500_INO)
|
||||
{PROTO_HITEC, STR_HITEC, 3, STR_SUBTYPE_HITEC, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(WFLY_CYRF6936_INO)
|
||||
{PROTO_WFLY, STR_WFLY, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#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 },
|
||||
@@ -253,59 +183,224 @@ const mm_protocol_definition multi_protocols[] = {
|
||||
#if defined(BUGSMINI_NRF24L01_INO)
|
||||
{PROTO_BUGSMINI, STR_BUGSMINI, 2, STR_SUBTYPE_BUGS_MINI, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(TRAXXAS_CYRF6936_INO)
|
||||
{PROTO_TRAXXAS, STR_TRAXXAS, 1, STR_SUBTYPE_TRAXXAS, OPTION_NONE },
|
||||
#if defined(CABELL_NRF24L01_INO)
|
||||
{PROTO_CABELL, STR_CABELL, 8, STR_SUBTYPE_CABELL, OPTION_OPTION },
|
||||
#endif
|
||||
#if defined(NCC1701_NRF24L01_INO)
|
||||
{PROTO_NCC1701, STR_NCC1701, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#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(V911S_NRF24L01_INO)
|
||||
{PROTO_V911S, STR_V911S, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#if defined(ESKY_NRF24L01_INO)
|
||||
{PROTO_ESKY, STR_ESKY, 2, STR_SUBTYPE_ESKY, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(GD00X_NRF24L01_INO)
|
||||
{PROTO_GD00X, STR_GD00X, 2, STR_SUBTYPE_GD00X, OPTION_RFTUNE },
|
||||
#if defined(ESKY150_NRF24L01_INO)
|
||||
{PROTO_ESKY150, STR_ESKY150, 2, STR_SUBTYPE_ESKY150, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(V761_NRF24L01_INO)
|
||||
{PROTO_V761, STR_V761, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#if defined(ESKY150V2_CC2500_INO)
|
||||
{PROTO_ESKY150V2, STR_ESKY150V2, 1, STR_SUBTYPE_ESKY150V2, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(KF606_NRF24L01_INO)
|
||||
{PROTO_KF606, STR_KF606, 0, NO_SUBTYPE, OPTION_RFTUNE },
|
||||
#if defined(FLYSKY_A7105_INO)
|
||||
{PROTO_FLYSKY, STR_FLYSKY, 5, STR_SUBTYPE_FLYSKY, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(REDPINE_CC2500_INO)
|
||||
{PROTO_REDPINE, STR_REDPINE, 2, STR_SUBTYPE_REDPINE, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(POTENSIC_NRF24L01_INO)
|
||||
{PROTO_POTENSIC, STR_POTENSIC, 1, STR_SUBTYPE_POTENSIC, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(ZSX_NRF24L01_INO)
|
||||
{PROTO_ZSX, STR_ZSX, 1, STR_SUBTYPE_ZSX, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(FLYZONE_A7105_INO)
|
||||
{PROTO_FLYZONE, STR_FLYZONE, 1, STR_SUBTYPE_FLYZONE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(SCANNER_CC2500_INO)
|
||||
{PROTO_SCANNER, STR_SCANNER, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(FRSKY_RX_CC2500_INO)
|
||||
{PROTO_FRSKY_RX, STR_FRSKY_RX, 0, NO_SUBTYPE, OPTION_RFTUNE },
|
||||
#if defined(AFHDS2A_A7105_INO)
|
||||
{PROTO_AFHDS2A, STR_AFHDS2A, 8, STR_SUBTYPE_AFHDS2A, OPTION_SRVFREQ },
|
||||
#endif
|
||||
#if defined(AFHDS2A_RX_A7105_INO)
|
||||
{PROTO_AFHDS2A_RX, STR_AFHDS2A_RX,0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(HOTT_CC2500_INO)
|
||||
{PROTO_HOTT, STR_HOTT, 0, NO_SUBTYPE, OPTION_RFTUNE },
|
||||
#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(FUTABA_CC2500_INO)
|
||||
{PROTO_FUTABA, STR_FUTABA, 1, STR_SUBTYPE_FUTABA, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(FX816_NRF24L01_INO)
|
||||
{PROTO_FX816, STR_FX816, 1, STR_SUBTYPE_FX816, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(BAYANG_RX_NRF24L01_INO)
|
||||
{PROTO_BAYANG_RX, STR_BAYANG_RX, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#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(HEIGHT_A7105_INO)
|
||||
{PROTO_HEIGHT, STR_HEIGHT, 2, STR_SUBTYPE_HEIGHT, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(HISKY_NRF24L01_INO)
|
||||
{PROTO_HISKY, STR_HISKY, 2, STR_SUBTYPE_HISKY, OPTION_NONE },
|
||||
#endif
|
||||
#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, 2, STR_SUBTYPE_JJRC345, 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, 2, STR_SUBTYPE_KYOSHO, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(MJXQ_NRF24L01_INO)
|
||||
{PROTO_MJXQ, STR_MJXQ, 7, STR_SUBTYPE_MJXQ, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(MLINK_CYRF6936_INO)
|
||||
{PROTO_MLINK, STR_MLINK, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(MT99XX_NRF24L01_INO)
|
||||
{PROTO_MT99XX, STR_MT99XX, 5, STR_SUBTYPE_MT99, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(NCC1701_NRF24L01_INO)
|
||||
{PROTO_NCC1701, STR_NCC1701, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(OMP_CC2500_INO)
|
||||
{PROTO_OMP, STR_OMP, 0, NO_SUBTYPE, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(PELIKAN_A7105_INO)
|
||||
{PROTO_PELIKAN, STR_PELIKAN , 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(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, 3, STR_SUBTYPE_XN297DUMP, OPTION_RFCHAN },
|
||||
{PROTO_XN297DUMP, STR_XN297DUMP, 5, STR_SUBTYPE_XN297DUMP, OPTION_RFCHAN },
|
||||
#endif
|
||||
#if defined(YD717_NRF24L01_INO)
|
||||
{PROTO_YD717, STR_YD717, 5, STR_SUBTYPE_YD717, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(ZSX_NRF24L01_INO)
|
||||
{PROTO_ZSX, STR_ZSX, 1, STR_SUBTYPE_ZSX, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(TEST_CC2500_INO)
|
||||
{PROTO_TEST, STR_TEST, 0, NO_SUBTYPE, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(NANORF_NRF24L01_INO)
|
||||
{PROTO_NANORF, STR_NANORF, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
{0x00, nullptr, 0, nullptr, 0 }
|
||||
};
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
//******************
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 3
|
||||
#define VERSION_REVISION 0
|
||||
#define VERSION_PATCH_LEVEL 47
|
||||
#define VERSION_REVISION 1
|
||||
#define VERSION_PATCH_LEVEL 78
|
||||
|
||||
//******************
|
||||
// Protocols
|
||||
@@ -47,7 +47,7 @@ enum PROTOCOLS
|
||||
PROTO_MJXQ = 18, // =>NRF24L01
|
||||
PROTO_SHENQI = 19, // =>NRF24L01
|
||||
PROTO_FY326 = 20, // =>NRF24L01
|
||||
PROTO_SFHSS = 21, // =>CC2500
|
||||
PROTO_FUTABA = 21, // =>CC2500
|
||||
PROTO_J6PRO = 22, // =>CYRF6936
|
||||
PROTO_FQ777 = 23, // =>NRF24L01
|
||||
PROTO_ASSAN = 24, // =>NRF24L01
|
||||
@@ -79,14 +79,34 @@ enum PROTOCOLS
|
||||
PROTO_REDPINE = 50, // =>CC2500
|
||||
PROTO_POTENSIC = 51, // =>NRF24L01
|
||||
PROTO_ZSX = 52, // =>NRF24L01
|
||||
PROTO_FLYZONE = 53, // =>A7105
|
||||
PROTO_HEIGHT = 53, // =>A7105
|
||||
PROTO_SCANNER = 54, // =>CC2500
|
||||
PROTO_FRSKY_RX = 55, // =>CC2500
|
||||
PROTO_AFHDS2A_RX= 56, // =>A7105
|
||||
PROTO_HOTT = 57, // =>CC2500
|
||||
PROTO_FX816 = 58, // =>NRF24L01
|
||||
PROTO_BAYANG_RX = 59, // =>NRF24L01
|
||||
PROTO_PELIKAN = 60, // =>A7105
|
||||
PROTO_TIGER = 61, // =>NRF24L01
|
||||
PROTO_XK = 62, // =>NRF24L01
|
||||
PROTO_XN297DUMP = 63, // =>NRF24L01
|
||||
PROTO_FRSKYX2 = 64, // =>CC2500
|
||||
PROTO_FRSKY_R9 = 65, // =>SX1276
|
||||
PROTO_PROPEL = 66, // =>NRF24L01
|
||||
PROTO_FRSKYL = 67, // =>CC2500
|
||||
PROTO_SKYARTEC = 68, // =>CC2500
|
||||
PROTO_ESKY150V2 = 69, // =>CC2500+NRF24L01
|
||||
PROTO_DSM_RX = 70, // =>CYRF6936
|
||||
PROTO_JJRC345 = 71, // =>NRF24L01
|
||||
PROTO_Q90C = 72, // =>NRF24L01 or CC2500
|
||||
PROTO_KYOSHO = 73, // =>A7105
|
||||
PROTO_RLINK = 74, // =>CC2500
|
||||
PROTO_REALACC = 76, // =>NRF24L01
|
||||
PROTO_OMP = 77, // =>CC2500 & NRF24L01
|
||||
PROTO_MLINK = 78, // =>CYRF6936
|
||||
|
||||
PROTO_NANORF = 126, // =>NRF24L01
|
||||
PROTO_TEST = 127, // =>CC2500
|
||||
};
|
||||
|
||||
enum Flysky
|
||||
@@ -97,7 +117,7 @@ enum Flysky
|
||||
V912 = 3,
|
||||
CX20 = 4,
|
||||
};
|
||||
enum Flyzone
|
||||
enum Height
|
||||
{
|
||||
FZ410 = 0,
|
||||
};
|
||||
@@ -113,6 +133,8 @@ enum AFHDS2A
|
||||
PPM_IBUS = 1,
|
||||
PWM_SBUS = 2,
|
||||
PPM_SBUS = 3,
|
||||
PWM_IB16 = 4,
|
||||
PPM_IB16 = 5,
|
||||
};
|
||||
enum Hisky
|
||||
{
|
||||
@@ -183,6 +205,7 @@ enum BAYANG
|
||||
X16_AH = 2,
|
||||
IRDRONE = 3,
|
||||
DHD_D4 = 4,
|
||||
QX100 = 5,
|
||||
};
|
||||
enum MT99XX
|
||||
{
|
||||
@@ -202,12 +225,19 @@ enum MJXQ
|
||||
H26WH = 5,
|
||||
PHOENIX = 6,
|
||||
};
|
||||
enum FRSKYD
|
||||
{
|
||||
FRSKYD = 0,
|
||||
DCLONE = 1,
|
||||
};
|
||||
enum FRSKYX
|
||||
{
|
||||
CH_16 = 0,
|
||||
CH_8 = 1,
|
||||
EU_16 = 2,
|
||||
EU_8 = 3,
|
||||
XCLONE_16 = 4,
|
||||
XCLONE_8 = 5,
|
||||
};
|
||||
enum HONTAI
|
||||
{
|
||||
@@ -220,6 +250,7 @@ enum V2X2
|
||||
{
|
||||
V2X2 = 0,
|
||||
JXD506 = 1,
|
||||
V2X2_MR101 = 2,
|
||||
};
|
||||
enum FY326
|
||||
{
|
||||
@@ -298,6 +329,87 @@ enum ESKY150
|
||||
ESKY150_4CH = 0,
|
||||
ESKY150_7CH = 1,
|
||||
};
|
||||
enum V911S
|
||||
{
|
||||
V911S_STD = 0,
|
||||
V911S_E119 = 1,
|
||||
};
|
||||
enum XK
|
||||
{
|
||||
X450 = 0,
|
||||
X420 = 1,
|
||||
};
|
||||
enum XN297DUMP
|
||||
{
|
||||
XN297DUMP_250K = 0,
|
||||
XN297DUMP_1M = 1,
|
||||
XN297DUMP_2M = 2,
|
||||
XN297DUMP_AUTO = 3,
|
||||
};
|
||||
enum FRSKY_R9
|
||||
{
|
||||
R9_915 = 0,
|
||||
R9_868 = 1,
|
||||
R9_915_8CH = 2,
|
||||
R9_868_8CH = 3,
|
||||
R9_FCC = 4,
|
||||
R9_EU = 5,
|
||||
R9_FCC_8CH = 6,
|
||||
R9_EU_8CH = 7,
|
||||
};
|
||||
enum ESKY
|
||||
{
|
||||
ESKY_STD = 0,
|
||||
ESKY_ET4 = 1,
|
||||
};
|
||||
|
||||
enum FRSKY_RX
|
||||
{
|
||||
FRSKY_RX = 0,
|
||||
FRSKY_CLONE = 1,
|
||||
};
|
||||
|
||||
enum FRSKYL
|
||||
{
|
||||
LR12 = 0,
|
||||
LR12_6CH = 1,
|
||||
};
|
||||
|
||||
enum HOTT
|
||||
{
|
||||
HOTT_SYNC = 0,
|
||||
HOTT_NO_SYNC= 1,
|
||||
};
|
||||
|
||||
enum PELIKAN
|
||||
{
|
||||
PELIKAN_PRO = 0,
|
||||
PELIKAN_LITE= 1,
|
||||
};
|
||||
|
||||
enum V761
|
||||
{
|
||||
V761_3CH = 0,
|
||||
V761_4CH = 1,
|
||||
};
|
||||
|
||||
enum HEIGHT
|
||||
{
|
||||
HEIGHT_5CH = 0,
|
||||
HEIGHT_8CH = 1,
|
||||
};
|
||||
|
||||
enum KYOSHO
|
||||
{
|
||||
KYOSHO_FHSS = 0,
|
||||
KYOSHO_HYPE = 1,
|
||||
};
|
||||
|
||||
enum JJRC345
|
||||
{
|
||||
JJRC345 = 0,
|
||||
SKYTMBLR = 1,
|
||||
};
|
||||
|
||||
#define NONE 0
|
||||
#define P_HIGH 1
|
||||
@@ -341,8 +453,8 @@ enum MultiPacketTypes
|
||||
//***************
|
||||
//*** Tests ***
|
||||
//***************
|
||||
#define IS_FAILSAFE_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_SFHSS || protocol==PROTO_WK2x01 || protocol== PROTO_HOTT || protocol==PROTO_FRSKYX )
|
||||
#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 )
|
||||
#define IS_FAILSAFE_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_FUTABA || protocol==PROTO_WK2x01 || protocol== PROTO_HOTT || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKY_R9)
|
||||
#define IS_CHMAP_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_FUTABA || protocol==PROTO_WK2x01 || protocol== PROTO_DSM || protocol==PROTO_SLT || protocol==PROTO_FLYSKY || (protocol==PROTO_KYOSHO && sub_protocol==KYOSHO_HYPE) || protocol==PROTO_ESKY || protocol==PROTO_J6PRO || protocol==PROTO_PELIKAN || protocol==PROTO_SKYARTEC || protocol==PROTO_ESKY150V2 || protocol==PROTO_DSM_RX)
|
||||
|
||||
//***************
|
||||
//*** Flags ***
|
||||
@@ -432,6 +544,11 @@ enum MultiPacketTypes
|
||||
#define DISABLE_TELEM_on protocol_flags3 |= _BV(3)
|
||||
#define IS_DISABLE_TELEM_on ( ( protocol_flags3 & _BV(3) ) !=0 )
|
||||
#define IS_DISABLE_TELEM_off ( ( protocol_flags3 & _BV(3) ) ==0 )
|
||||
//LBT power
|
||||
#define LBT_POWER_off protocol_flags3 &= ~_BV(7)
|
||||
#define LBT_POWER_on protocol_flags3 |= _BV(7)
|
||||
#define IS_LBT_POWER_on ( ( protocol_flags3 & _BV(7) ) !=0 )
|
||||
#define IS_LBT_POWER_off ( ( protocol_flags3 & _BV(7) ) ==0 )
|
||||
|
||||
|
||||
// Failsafe
|
||||
@@ -500,17 +617,17 @@ enum {
|
||||
};
|
||||
|
||||
// A7105 power
|
||||
// Power amp is ~+16dBm so:
|
||||
// The numbers do not take into account any outside amplifier
|
||||
enum A7105_POWER
|
||||
{
|
||||
A7105_POWER_0 = 0x00<<3 | 0x00, // TXPOWER_100uW = -23dBm == PAC=0 TBG=0
|
||||
A7105_POWER_1 = 0x00<<3 | 0x01, // TXPOWER_300uW = -20dBm == PAC=0 TBG=1
|
||||
A7105_POWER_2 = 0x00<<3 | 0x02, // TXPOWER_1mW = -16dBm == PAC=0 TBG=2
|
||||
A7105_POWER_3 = 0x00<<3 | 0x04, // TXPOWER_3mW = -11dBm == PAC=0 TBG=4
|
||||
A7105_POWER_4 = 0x01<<3 | 0x05, // TXPOWER_10mW = -6dBm == PAC=1 TBG=5
|
||||
A7105_POWER_5 = 0x02<<3 | 0x07, // TXPOWER_30mW = 0dBm == PAC=2 TBG=7
|
||||
A7105_POWER_6 = 0x03<<3 | 0x07, // TXPOWER_100mW = 1dBm == PAC=3 TBG=7
|
||||
A7105_POWER_7 = 0x03<<3 | 0x07 // TXPOWER_150mW = 1dBm == PAC=3 TBG=7
|
||||
A7105_POWER_0 = 0x00<<3 | 0x00, // -23dBm == PAC=0 TBG=0
|
||||
A7105_POWER_1 = 0x00<<3 | 0x01, // -20dBm == PAC=0 TBG=1
|
||||
A7105_POWER_2 = 0x00<<3 | 0x02, // -16dBm == PAC=0 TBG=2
|
||||
A7105_POWER_3 = 0x00<<3 | 0x04, // -11dBm == PAC=0 TBG=4
|
||||
A7105_POWER_4 = 0x01<<3 | 0x05, // -6dBm == PAC=1 TBG=5
|
||||
A7105_POWER_5 = 0x02<<3 | 0x07, // 0dBm == PAC=2 TBG=7
|
||||
A7105_POWER_6 = 0x03<<3 | 0x07, // +1dBm == PAC=3 TBG=7
|
||||
A7105_POWER_7 = 0x03<<3 | 0x07 // +1dBm == PAC=3 TBG=7
|
||||
};
|
||||
#define A7105_HIGH_POWER A7105_POWER_7
|
||||
#define A7105_LOW_POWER A7105_POWER_3
|
||||
@@ -518,14 +635,13 @@ enum A7105_POWER
|
||||
#define A7105_BIND_POWER A7105_POWER_0
|
||||
|
||||
// NRF Power
|
||||
// Power setting is 0..3 for nRF24L01
|
||||
// Claimed power amp for nRF24L01 from eBay is 20dBm.
|
||||
// The numbers do not take into account any outside amplifier
|
||||
enum NRF_POWER
|
||||
{ // Raw w 20dBm PA
|
||||
NRF_POWER_0 = 0x00, // 0 : -18dBm (16uW) 2dBm (1.6mW)
|
||||
NRF_POWER_1 = 0x01, // 1 : -12dBm (60uW) 8dBm (6mW)
|
||||
NRF_POWER_2 = 0x02, // 2 : -6dBm (250uW) 14dBm (25mW)
|
||||
NRF_POWER_3 = 0x03 // 3 : 0dBm (1mW) 20dBm (100mW)
|
||||
{
|
||||
NRF_POWER_0 = 0x00, // -18dBm
|
||||
NRF_POWER_1 = 0x01, // -12dBm
|
||||
NRF_POWER_2 = 0x02, // -6dBm
|
||||
NRF_POWER_3 = 0x03 // 0dBm
|
||||
};
|
||||
#define NRF_HIGH_POWER NRF_POWER_3
|
||||
#define NRF_LOW_POWER NRF_POWER_1
|
||||
@@ -556,11 +672,13 @@ enum CC2500_POWER
|
||||
CC2500_POWER_17 = 0xFF // +1dbm
|
||||
};
|
||||
#define CC2500_HIGH_POWER CC2500_POWER_17
|
||||
#define CC2500_LBT_POWER CC2500_POWER_14
|
||||
#define CC2500_LOW_POWER CC2500_POWER_13
|
||||
#define CC2500_RANGE_POWER CC2500_POWER_1
|
||||
#define CC2500_BIND_POWER CC2500_POWER_1
|
||||
|
||||
// CYRF power
|
||||
// The numbers do not take into account any outside amplifier
|
||||
enum CYRF_POWER
|
||||
{
|
||||
CYRF_POWER_0 = 0x00, // -35dbm
|
||||
@@ -609,7 +727,20 @@ enum {
|
||||
#define AFHDS2A_EEPROM_OFFSET2 250 // RX ID, 4 bytes per model id, end is 250+192=442
|
||||
#define HOTT_EEPROM_OFFSET 442 // RX ID, 5 bytes per model id, end is 320+442=762
|
||||
#define BAYANG_RX_EEPROM_OFFSET 762 // (5) TX ID + (4) channels, 9 bytes, end is 771
|
||||
//#define CONFIG_EEPROM_OFFSET 771 // Current configuration of the multimodule
|
||||
#define FRSKYD_CLONE_EEPROM_OFFSET 771 // (1) format + (3) TX ID + (47) channels, 51 bytes, end is 822
|
||||
#define FRSKYX_CLONE_EEPROM_OFFSET 822 // (1) format + (3) TX ID + (47) channels, 51 bytes, end is 873
|
||||
#define FRSKYX2_CLONE_EEPROM_OFFSET 873 // (1) format + (3) TX ID, 4 bytes, end is 877
|
||||
#define DSM_RX_EEPROM_OFFSET 877 // (4) TX ID + format, 5 bytes, end is 882
|
||||
//#define CONFIG_EEPROM_OFFSET 882 // Current configuration of the multimodule
|
||||
|
||||
/* 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 ***
|
||||
@@ -648,7 +779,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
MJXQ 18
|
||||
SHENQI 19
|
||||
FY326 20
|
||||
SFHSS 21
|
||||
Futaba 21
|
||||
J6PRO 22
|
||||
FQ777 23
|
||||
ASSAN 24
|
||||
@@ -680,13 +811,31 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
REDPINE 50
|
||||
POTENSIC 51
|
||||
ZSX 52
|
||||
FLYZONE 53
|
||||
HEIGHT 53
|
||||
SCANNER 54
|
||||
FRSKY_RX 55
|
||||
AFHDS2A_RX 56
|
||||
HOTT 57
|
||||
FX816 58
|
||||
BAYANG_RX 59
|
||||
PELIKAN 60
|
||||
TIGER 61
|
||||
XK 62
|
||||
XN297DUMP 63
|
||||
FRSKYX2 64
|
||||
FRSKY_R9 65
|
||||
PROPEL 66
|
||||
FRSKYL 67
|
||||
SKYARTEC 68
|
||||
ESKY150V2 69
|
||||
DSM_RX 70
|
||||
JJRC345 71
|
||||
Q90C 72
|
||||
KYOSHO 73
|
||||
RLINK 74
|
||||
REALACC 76
|
||||
OMP 77
|
||||
MLINK 78
|
||||
BindBit=> 0x80 1=Bind/0=No
|
||||
AutoBindBit=> 0x40 1=Yes /0=No
|
||||
RangeCheck=> 0x20 1=Yes /0=No
|
||||
@@ -759,11 +908,21 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
E010 4
|
||||
H26WH 5
|
||||
PHOENIX 6
|
||||
sub_protocol==FRSKYD
|
||||
FRSKYD 0
|
||||
DCLONE 1
|
||||
sub_protocol==FRSKYX
|
||||
CH_16 0
|
||||
CH_8 1
|
||||
EU_16 2
|
||||
EU_8 3
|
||||
XCLONE 4
|
||||
sub_protocol==FRSKYX2
|
||||
CH_16 0
|
||||
CH_8 1
|
||||
EU_16 2
|
||||
EU_8 3
|
||||
XCLONE 4
|
||||
sub_protocol==HONTAI
|
||||
HONTAI 0
|
||||
JJRCX1 1
|
||||
@@ -774,9 +933,12 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
PPM_IBUS 1
|
||||
PWM_SBUS 2
|
||||
PPM_SBUS 3
|
||||
PWM_IB16 4
|
||||
PPM_IB16 5
|
||||
sub_protocol==V2X2
|
||||
V2X2 0
|
||||
JXD506 1
|
||||
V2X2_MR101 2
|
||||
sub_protocol==FY326
|
||||
FY326 0
|
||||
FY319 1
|
||||
@@ -831,6 +993,45 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
sub_protocol==ESKY150
|
||||
ESKY150_4CH 0
|
||||
ESKY150_7CH 1
|
||||
sub_protocol==V911S
|
||||
V911S_STD 0
|
||||
V911S_E119 1
|
||||
sub_protocol==XK
|
||||
X450 0
|
||||
X420 1
|
||||
sub_protocol==FRSKY_R9
|
||||
R9_915 0
|
||||
R9_868 1
|
||||
R9_915_8CH 2
|
||||
R9_868_8CH 3
|
||||
R9_FCC 4
|
||||
R9_EU 5
|
||||
R9_FCC_8CH 6
|
||||
R9_EU_8CH 7
|
||||
sub_protocol==ESKY
|
||||
ESKY_STD 0
|
||||
ESKY_ET4 1
|
||||
sub_protocol==FRSKY_RX
|
||||
FRSKY_RX 0
|
||||
FRSKY_CLONE 1
|
||||
sub_protocol==FRSKYL
|
||||
LR12 0
|
||||
LR12_6CH 1
|
||||
sub_protocol==HOTT
|
||||
HOTT_SYNC 0
|
||||
HOTT_NO_SYNC 1
|
||||
sub_protocol==PELIKAN
|
||||
PELIKAN_PRO 0
|
||||
PELIKAN_LITE 1
|
||||
sub_protocol==V761
|
||||
V761_3CH 0
|
||||
V761_4CH 1
|
||||
sub_protocol==HEIGHT
|
||||
HEIGHT_5CH 0
|
||||
HEIGHT_8CH 1
|
||||
sub_protocol==JJRC345
|
||||
JJRC345 0
|
||||
SKYTMBLR 1
|
||||
|
||||
Power value => 0x80 0=High/1=Low
|
||||
Stream[3] = option_protocol;
|
||||
@@ -853,6 +1054,11 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
Disable_Telemetry => 0x02 0=enable, 1=disable
|
||||
Disable_CH_Mapping => 0x01 0=enable, 1=disable
|
||||
Stream[27.. 35] = between 0 and 9 bytes for additional protocol data
|
||||
Protocol specific use:
|
||||
FrSkyX and FrSkyX2: Stream[27] during bind Telem on=0x00,off=0x01 | CH1-8=0x00,CH9-16=0x02
|
||||
FrSkyX and FrSkyX2: Stream[27..34] during normal operation unstuffed SPort data to be sent
|
||||
HoTT: Stream[27] 1 byte for telemetry type
|
||||
DSM: Stream[27..33] Forward Programming
|
||||
*/
|
||||
/*
|
||||
Multimodule Status
|
||||
@@ -933,8 +1139,10 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
OPTION_SRVFREQ 6
|
||||
OPTION_MAXTHR 7
|
||||
OPTION_RFCHAN 8
|
||||
OPTION_RFPOWER 9
|
||||
[19&0x0F] Number of sub protocols
|
||||
[20..27] Sub protocol name [8], not null terminated if sub prototcol len == 8
|
||||
If the current protocol is invalid [12..27] are all 0x00.
|
||||
|
||||
more information can be added by specifing a longer length of the type, the TX will just ignore these bytes
|
||||
|
||||
|
||||
@@ -75,7 +75,11 @@ uint32_t blink=0,last_signal=0;
|
||||
//
|
||||
uint16_t counter;
|
||||
uint8_t channel;
|
||||
#ifdef ESKY150V2_CC2500_INO
|
||||
uint8_t packet[150];
|
||||
#else
|
||||
uint8_t packet[50];
|
||||
#endif
|
||||
|
||||
#define NUM_CHN 16
|
||||
// Servo data
|
||||
@@ -97,8 +101,8 @@ uint16_t packet_period;
|
||||
uint8_t packet_count;
|
||||
uint8_t packet_sent;
|
||||
uint8_t packet_length;
|
||||
#ifdef HOTT_CC2500_INO
|
||||
uint8_t hopping_frequency[75];
|
||||
#if defined(HOTT_CC2500_INO) || defined(ESKY150V2_CC2500_INO) || defined(MLINK_CYRF6936_INO)
|
||||
uint8_t hopping_frequency[78];
|
||||
#else
|
||||
uint8_t hopping_frequency[50];
|
||||
#endif
|
||||
@@ -115,11 +119,13 @@ uint16_t state;
|
||||
uint8_t len;
|
||||
uint8_t armed, arm_flags, arm_channel_previous;
|
||||
uint8_t num_ch;
|
||||
uint32_t pps_timer;
|
||||
uint16_t pps_counter;
|
||||
|
||||
#ifdef CC2500_INSTALLED
|
||||
#ifdef SCANNER_CC2500_INO
|
||||
uint8_t calData[255];
|
||||
#elif defined(HOTT_CC2500_INO)
|
||||
#elif defined(HOTT_CC2500_INO) || defined(ESKY150V2_CC2500_INO)
|
||||
uint8_t calData[75];
|
||||
#else
|
||||
uint8_t calData[50];
|
||||
@@ -179,7 +185,7 @@ volatile uint8_t rx_idx=0, rx_len=0;
|
||||
|
||||
|
||||
// Telemetry
|
||||
#define TELEMETRY_BUFFER_SIZE 30
|
||||
#define TELEMETRY_BUFFER_SIZE 32
|
||||
uint8_t packet_in[TELEMETRY_BUFFER_SIZE];//telemetry receiving packets
|
||||
#if defined(TELEMETRY)
|
||||
#ifdef MULTI_SYNC
|
||||
@@ -227,7 +233,7 @@ uint8_t packet_in[TELEMETRY_BUFFER_SIZE];//telemetry receiving packets
|
||||
#endif
|
||||
|
||||
//RX protocols
|
||||
#if defined(AFHDS2A_RX_A7105_INO) || defined(FRSKY_RX_CC2500_INO) || defined(BAYANG_RX_NRF24L01_INO)
|
||||
#if defined(AFHDS2A_RX_A7105_INO) || defined(FRSKY_RX_CC2500_INO) || defined(BAYANG_RX_NRF24L01_INO) || defined(DSM_RX_CYRF6936_INO)
|
||||
bool rx_data_started;
|
||||
bool rx_data_received;
|
||||
bool rx_disable_lna;
|
||||
@@ -250,6 +256,10 @@ uint8_t packet_in[TELEMETRY_BUFFER_SIZE];//telemetry receiving packets
|
||||
uint8_t HoTT_SerialRX_val=0;
|
||||
bool HoTT_SerialRX=false;
|
||||
#endif
|
||||
#ifdef DSM_FWD_PGM
|
||||
uint8_t DSM_SerialRX_val[7];
|
||||
bool DSM_SerialRX=false;
|
||||
#endif
|
||||
#endif // TELEMETRY
|
||||
|
||||
// Callback
|
||||
@@ -305,6 +315,7 @@ void setup()
|
||||
#elif defined STM32_BOARD
|
||||
//STM32
|
||||
afio_cfg_debug_ports(AFIO_DEBUG_NONE);
|
||||
pinMode(LED_pin,OUTPUT);
|
||||
pinMode(LED2_pin,OUTPUT);
|
||||
pinMode(A7105_CSN_pin,OUTPUT);
|
||||
pinMode(CC25_CSN_pin,OUTPUT);
|
||||
@@ -331,11 +342,76 @@ void setup()
|
||||
pinMode(S2_pin,INPUT_PULLUP);
|
||||
pinMode(S3_pin,INPUT_PULLUP);
|
||||
pinMode(S4_pin,INPUT_PULLUP);
|
||||
//Random pins
|
||||
pinMode(PB0, INPUT_ANALOG); // set up pin for analog input
|
||||
|
||||
#ifdef MULTI_5IN1_INTERNAL
|
||||
//pinMode(SX1276_RST_pin,OUTPUT); // already done by LED2_pin
|
||||
pinMode(SX1276_TXEN_pin,OUTPUT); // PB0
|
||||
pinMode(SX1276_DIO0_pin,INPUT_PULLUP);
|
||||
#else
|
||||
//Random pin
|
||||
pinMode(RND_pin, INPUT_ANALOG); // set up PB0 pin for analog input
|
||||
#endif
|
||||
|
||||
#if defined ENABLE_DIRECT_INPUTS
|
||||
#if defined (DI1_PIN)
|
||||
pinMode(DI1_PIN,INPUT_PULLUP);
|
||||
#endif
|
||||
#if defined (DI2_PIN)
|
||||
pinMode(DI2_PIN,INPUT_PULLUP);
|
||||
#endif
|
||||
#if defined (DI3_PIN)
|
||||
pinMode(DI3_PIN,INPUT_PULLUP);
|
||||
#endif
|
||||
#if defined (DI4_PIN)
|
||||
pinMode(DI4_PIN,INPUT_PULLUP);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//Timers
|
||||
init_HWTimer(); //0.5us
|
||||
|
||||
//Read module flash size
|
||||
#ifndef DISABLE_FLASH_SIZE_CHECK
|
||||
unsigned short *flashSize = (unsigned short *) (0x1FFFF7E0);// Address register
|
||||
debugln("Module Flash size: %dKB",(int)(*flashSize & 0xffff));
|
||||
if((int)(*flashSize & 0xffff) < MCU_EXPECTED_FLASH_SIZE) // Not supported by this project
|
||||
while (true) { //SOS
|
||||
for(uint8_t i=0; i<3;i++)
|
||||
{
|
||||
LED_on;
|
||||
delay(100);
|
||||
LED_off;
|
||||
delay(100);
|
||||
}
|
||||
for(uint8_t i=0; i<3;i++)
|
||||
{
|
||||
LED_on;
|
||||
delay(500);
|
||||
LED_off;
|
||||
delay(100);
|
||||
}
|
||||
for(uint8_t i=0; i<3;i++)
|
||||
{
|
||||
LED_on;
|
||||
delay(100);
|
||||
LED_off;
|
||||
delay(100);
|
||||
}
|
||||
LED_off;
|
||||
delay(1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Initialize the EEPROM
|
||||
uint16_t eepromStatus = EEPROM.init();
|
||||
debugln("EEPROM initialized: %d",eepromStatus);
|
||||
|
||||
// If there was no valid EEPROM page the EEPROM is corrupt or uninitialized and should be formatted
|
||||
if( eepromStatus == EEPROM_NO_VALID_PAGE )
|
||||
{
|
||||
EEPROM.format();
|
||||
debugln("No valid EEPROM page, EEPROM formatted");
|
||||
}
|
||||
#else
|
||||
//ATMEGA328p
|
||||
// all inputs
|
||||
@@ -390,6 +466,10 @@ void setup()
|
||||
#ifdef NRF_CSN_pin
|
||||
NRF_CSN_on;
|
||||
#endif
|
||||
#ifdef SPI_CSN_pin
|
||||
SPI_CSN_on;
|
||||
#endif
|
||||
|
||||
// Set SPI lines
|
||||
#ifdef STM32_BOARD
|
||||
initSPI2();
|
||||
@@ -453,7 +533,12 @@ void setup()
|
||||
#ifdef STM32_BOARD
|
||||
uint32_t seed=0;
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
seed=(seed<<8) | (analogRead(PB0)& 0xFF);
|
||||
#ifdef RND_pin
|
||||
seed=(seed<<8) | (analogRead(RND_pin)& 0xFF);
|
||||
#else
|
||||
//TODO find something to randomize...
|
||||
seed=(seed<<8);
|
||||
#endif
|
||||
randomSeed(seed);
|
||||
#else
|
||||
//Init the seed with a random value created from watchdog timer for all protocols requiring random values
|
||||
@@ -488,19 +573,24 @@ void setup()
|
||||
option = FORCE_FRSKYD_TUNING; // Use config-defined tuning value for FrSkyD
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_FRSKYL_TUNING) && defined(FRSKYL_CC2500_INO)
|
||||
if(protocol==PROTO_FRSKYL)
|
||||
option = FORCE_FRSKYL_TUNING; // Use config-defined tuning value for FrSkyL
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_FRSKYV_TUNING) && defined(FRSKYV_CC2500_INO)
|
||||
if(protocol==PROTO_FRSKYV)
|
||||
option = FORCE_FRSKYV_TUNING; // Use config-defined tuning value for FrSkyV
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_FRSKYX_TUNING) && defined(FRSKYX_CC2500_INO)
|
||||
if(protocol==PROTO_FRSKYX)
|
||||
if(protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2)
|
||||
option = FORCE_FRSKYX_TUNING; // Use config-defined tuning value for FrSkyX
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_SFHSS_TUNING) && defined(SFHSS_CC2500_INO)
|
||||
if (protocol==PROTO_SFHSS)
|
||||
option = FORCE_SFHSS_TUNING; // Use config-defined tuning value for SFHSS
|
||||
#if defined(FORCE_FUTABA_TUNING) && defined(FUTABA_CC2500_INO)
|
||||
if (protocol==PROTO_FUTABA)
|
||||
option = FORCE_FUTABA_TUNING; // Use config-defined tuning value for SFHSS
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_CORONA_TUNING) && defined(CORONA_CC2500_INO)
|
||||
@@ -508,11 +598,21 @@ void setup()
|
||||
option = FORCE_CORONA_TUNING; // Use config-defined tuning value for CORONA
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_SKYARTEC_TUNING) && defined(SKYARTEC_CC2500_INO)
|
||||
if (protocol==PROTO_SKYARTEC)
|
||||
option = FORCE_SKYARTEC_TUNING; // Use config-defined tuning value for SKYARTEC
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_REDPINE_TUNING) && defined(REDPINE_CC2500_INO)
|
||||
if (protocol==PROTO_REDPINE)
|
||||
option = FORCE_REDPINE_TUNING; // Use config-defined tuning value for REDPINE
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_RADIOLINK_TUNING) && defined(RADIOLINK_CC2500_INO)
|
||||
if (protocol==PROTO_RADIOLINK)
|
||||
option = FORCE_RADIOLINK_TUNING; // Use config-defined tuning value for RADIOLINK
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_HITEC_TUNING) && defined(HITEC_CC2500_INO)
|
||||
if (protocol==PROTO_HITEC)
|
||||
option = FORCE_HITEC_TUNING; // Use config-defined tuning value for HITEC
|
||||
@@ -567,8 +667,8 @@ void setup()
|
||||
#endif
|
||||
#endif //ENABLE_SERIAL
|
||||
}
|
||||
LED2_on;
|
||||
debugln("Init complete");
|
||||
LED2_on;
|
||||
}
|
||||
|
||||
// Main
|
||||
@@ -667,7 +767,28 @@ bool Update_All()
|
||||
{
|
||||
uint32_t chan_or=chan_order;
|
||||
uint8_t ch;
|
||||
for(uint8_t i=0;i<PPM_chan_max;i++)
|
||||
uint8_t channelsCount = PPM_chan_max;
|
||||
|
||||
#ifdef ENABLE_DIRECT_INPUTS
|
||||
#ifdef DI_CH1_read
|
||||
PPM_data[channelsCount] = DI_CH1_read;
|
||||
channelsCount++;
|
||||
#endif
|
||||
#ifdef DI_CH2_read
|
||||
PPM_data[channelsCount] = DI_CH2_read;
|
||||
channelsCount++;
|
||||
#endif
|
||||
#ifdef DI_CH3_read
|
||||
PPM_data[channelsCount] = DI_CH3_read;
|
||||
channelsCount++;
|
||||
#endif
|
||||
#ifdef DI_CH4_read
|
||||
PPM_data[channelsCount] = DI_CH4_read;
|
||||
channelsCount++;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
for(uint8_t i=0;i<channelsCount;i++)
|
||||
{ // update servo data without interrupts to prevent bad read
|
||||
uint16_t val;
|
||||
cli(); // disable global int
|
||||
@@ -700,7 +821,7 @@ bool Update_All()
|
||||
update_led_status();
|
||||
#if defined(TELEMETRY)
|
||||
#if ( !( defined(MULTI_TELEMETRY) || defined(MULTI_STATUS) ) )
|
||||
if((protocol == PROTO_BAYANG_RX) || (protocol == PROTO_AFHDS2A_RX) || (protocol == PROTO_FRSKY_RX) || (protocol == PROTO_SCANNER) || (protocol==PROTO_FRSKYD) || (protocol==PROTO_BAYANG) || (protocol==PROTO_NCC1701) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_FRSKYX) || (protocol==PROTO_DSM) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_HOTT))
|
||||
if((protocol == PROTO_BAYANG_RX) || (protocol == PROTO_AFHDS2A_RX) || (protocol == PROTO_FRSKY_RX) || (protocol == PROTO_SCANNER) || (protocol==PROTO_FRSKYD) || (protocol==PROTO_BAYANG) || (protocol==PROTO_NCC1701) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_FRSKYX) || (protocol==PROTO_FRSKYX2) || (protocol==PROTO_DSM) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_HOTT) || (protocol==PROTO_PROPEL) || (protocol==PROTO_OMP) || (protocol==PROTO_DEVO) || (protocol==PROTO_DSM_RX) || (protocol==PROTO_FRSKY_R9) || (protocol==PROTO_RLINK))
|
||||
#endif
|
||||
if(IS_DISABLE_TELEM_off)
|
||||
TelemetryUpdate();
|
||||
@@ -716,8 +837,8 @@ bool Update_All()
|
||||
{ // Autobind is on and BIND_CH went down
|
||||
BIND_CH_PREV_off;
|
||||
//Request protocol to terminate bind
|
||||
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYV_CC2500_INO) || defined(AFHDS2A_A7105_INO)
|
||||
if(protocol==PROTO_FRSKYD || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYV || protocol==PROTO_AFHDS2A )
|
||||
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYL_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYV_CC2500_INO) || defined(AFHDS2A_A7105_INO) || defined(FRSKYR9_SX1276_INO)
|
||||
if(protocol==PROTO_FRSKYD || protocol==PROTO_FRSKYL || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKYV || protocol==PROTO_AFHDS2A || protocol==PROTO_FRSKY_R9)
|
||||
BIND_DONE;
|
||||
else
|
||||
#endif
|
||||
@@ -975,6 +1096,8 @@ static void protocol_init()
|
||||
#endif
|
||||
tx_pause();
|
||||
init_frskyd_link_telemetry();
|
||||
pps_timer=millis();
|
||||
pps_counter=0;
|
||||
#ifdef BASH_SERIAL
|
||||
TIMSK0 = 0 ; // Stop all timer 0 interrupts
|
||||
#ifdef INVERT_SERIAL
|
||||
@@ -997,6 +1120,7 @@ static void protocol_init()
|
||||
rx_rc_chan[ch] = 1024;
|
||||
#endif
|
||||
#endif
|
||||
binding_idx=0;
|
||||
|
||||
//Set global ID and rx_tx_addr
|
||||
MProtocol_id = RX_num + MProtocol_id_master;
|
||||
@@ -1044,11 +1168,11 @@ static void protocol_init()
|
||||
remote_callback = ReadBUGS;
|
||||
break;
|
||||
#endif
|
||||
#if defined(FLYZONE_A7105_INO)
|
||||
case PROTO_FLYZONE:
|
||||
#if defined(HEIGHT_A7105_INO)
|
||||
case PROTO_HEIGHT:
|
||||
PE1_off; //antenna RF1
|
||||
next_callback = initFlyzone();
|
||||
remote_callback = ReadFlyzone;
|
||||
next_callback = initHeight();
|
||||
remote_callback = ReadHeight;
|
||||
break;
|
||||
#endif
|
||||
#if defined(AFHDS2A_RX_A7105_INO)
|
||||
@@ -1058,6 +1182,20 @@ static void protocol_init()
|
||||
remote_callback = AFHDS2A_Rx_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(PELIKAN_A7105_INO)
|
||||
case PROTO_PELIKAN:
|
||||
PE1_off; //antenna RF1
|
||||
next_callback = initPelikan();
|
||||
remote_callback = ReadPelikan;
|
||||
break;
|
||||
#endif
|
||||
#if defined(KYOSHO_A7105_INO)
|
||||
case PROTO_KYOSHO:
|
||||
PE1_off; //antenna RF1
|
||||
next_callback = initKyosho();
|
||||
remote_callback = ReadKyosho;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CC2500_INSTALLED
|
||||
#if defined(FRSKYD_CC2500_INO)
|
||||
@@ -1068,6 +1206,14 @@ static void protocol_init()
|
||||
remote_callback = ReadFrSky_2way;
|
||||
break;
|
||||
#endif
|
||||
#if defined(FRSKYL_CC2500_INO)
|
||||
case PROTO_FRSKYL:
|
||||
PE1_off; //antenna RF2
|
||||
PE2_on;
|
||||
next_callback = initFrSkyL();
|
||||
remote_callback = ReadFrSkyL;
|
||||
break;
|
||||
#endif
|
||||
#if defined(FRSKYV_CC2500_INO)
|
||||
case PROTO_FRSKYV:
|
||||
PE1_off; //antenna RF2
|
||||
@@ -1078,14 +1224,19 @@ static void protocol_init()
|
||||
#endif
|
||||
#if defined(FRSKYX_CC2500_INO)
|
||||
case PROTO_FRSKYX:
|
||||
case PROTO_FRSKYX2:
|
||||
#ifdef EU_MODULE
|
||||
if(sub_protocol<2)
|
||||
break;
|
||||
#endif
|
||||
PE1_off; //antenna RF2
|
||||
PE2_on;
|
||||
next_callback = initFrSkyX();
|
||||
remote_callback = ReadFrSkyX;
|
||||
break;
|
||||
#endif
|
||||
#if defined(SFHSS_CC2500_INO)
|
||||
case PROTO_SFHSS:
|
||||
#if defined(FUTABA_CC2500_INO)
|
||||
case PROTO_FUTABA:
|
||||
PE1_off; //antenna RF2
|
||||
PE2_on;
|
||||
next_callback = initSFHSS();
|
||||
@@ -1100,6 +1251,14 @@ static void protocol_init()
|
||||
remote_callback = ReadCORONA;
|
||||
break;
|
||||
#endif
|
||||
#if defined(SKYARTEC_CC2500_INO)
|
||||
case PROTO_SKYARTEC:
|
||||
PE1_off; //antenna RF2
|
||||
PE2_on;
|
||||
next_callback = initSKYARTEC();
|
||||
remote_callback = ReadSKYARTEC;
|
||||
break;
|
||||
#endif
|
||||
#if defined(REDPINE_CC2500_INO)
|
||||
case PROTO_REDPINE:
|
||||
PE1_off; //antenna RF2
|
||||
@@ -1140,6 +1299,22 @@ static void protocol_init()
|
||||
remote_callback = FrSky_Rx_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(ESKY150V2_CC2500_INO)
|
||||
case PROTO_ESKY150V2:
|
||||
PE1_off;
|
||||
PE2_on; //antenna RF2
|
||||
next_callback = initESKY150V2();
|
||||
remote_callback = ESKY150V2_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(RLINK_CC2500_INO)
|
||||
case PROTO_RLINK:
|
||||
PE1_off;
|
||||
PE2_on; //antenna RF2
|
||||
next_callback = initRLINK();
|
||||
remote_callback = RLINK_callback;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CYRF6936_INSTALLED
|
||||
#if defined(DSM_CYRF6936_INO)
|
||||
@@ -1149,6 +1324,13 @@ static void protocol_init()
|
||||
remote_callback = ReadDsm;
|
||||
break;
|
||||
#endif
|
||||
#if defined(DSM_RX_CYRF6936_INO)
|
||||
case PROTO_DSM_RX:
|
||||
PE2_on; //antenna RF4
|
||||
next_callback = initDSM_Rx();
|
||||
remote_callback = DSM_Rx_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(WFLY_CYRF6936_INO)
|
||||
case PROTO_WFLY:
|
||||
PE2_on; //antenna RF4
|
||||
@@ -1156,6 +1338,13 @@ static void protocol_init()
|
||||
remote_callback = ReadWFLY;
|
||||
break;
|
||||
#endif
|
||||
#if defined(MLINK_CYRF6936_INO)
|
||||
case PROTO_MLINK:
|
||||
PE2_on; //antenna RF4
|
||||
next_callback = initMLINK();
|
||||
remote_callback = ReadMLINK;
|
||||
break;
|
||||
#endif
|
||||
#if defined(DEVO_CYRF6936_INO)
|
||||
case PROTO_DEVO:
|
||||
#ifdef ENABLE_PPM
|
||||
@@ -1428,12 +1617,74 @@ static void protocol_init()
|
||||
remote_callback = Bayang_Rx_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(TIGER_NRF24L01_INO)
|
||||
case PROTO_TIGER:
|
||||
next_callback=initTIGER();
|
||||
remote_callback = TIGER_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(XK_NRF24L01_INO)
|
||||
case PROTO_XK:
|
||||
next_callback=initXK();
|
||||
remote_callback = XK_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(PROPEL_NRF24L01_INO)
|
||||
case PROTO_PROPEL:
|
||||
next_callback=initPROPEL();
|
||||
remote_callback = PROPEL_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(XN297DUMP_NRF24L01_INO)
|
||||
case PROTO_XN297DUMP:
|
||||
next_callback=initXN297Dump();
|
||||
remote_callback = XN297Dump_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(JJRC345_NRF24L01_INO)
|
||||
case PROTO_JJRC345:
|
||||
next_callback=initJJRC345();
|
||||
remote_callback = JJRC345_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(Q90C_NRF24L01_INO)
|
||||
case PROTO_Q90C:
|
||||
next_callback=initQ90C();
|
||||
remote_callback = Q90C_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(REALACC_NRF24L01_INO)
|
||||
case PROTO_REALACC:
|
||||
next_callback=initREALACC();
|
||||
remote_callback = REALACC_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(OMP_CC2500_INO)
|
||||
case PROTO_OMP:
|
||||
next_callback=initOMP();
|
||||
remote_callback = OMP_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(TEST_CC2500_INO)
|
||||
case PROTO_TEST:
|
||||
next_callback=initTEST();
|
||||
remote_callback = TEST_callback;
|
||||
break;
|
||||
#endif
|
||||
#if defined(NANORF_NRF24L01_INO)
|
||||
case PROTO_NANORF:
|
||||
next_callback=initNANORF();
|
||||
remote_callback = NANORF_callback;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SX1276_INSTALLED
|
||||
#if defined(FRSKYR9_SX1276_INO)
|
||||
case PROTO_FRSKY_R9:
|
||||
next_callback = initFrSkyR9();
|
||||
remote_callback = FrSkyR9_callback;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
debugln("Protocol selected: %d, sub proto %d, rxnum %d, option %d", protocol, sub_protocol, RX_num, option);
|
||||
@@ -1537,19 +1788,24 @@ void update_serial_data()
|
||||
option=FORCE_FRSKYD_TUNING; // Use config-defined tuning value for FrSkyD
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_FRSKYL_TUNING) && defined(FRSKYL_CC2500_INO)
|
||||
if(protocol==PROTO_FRSKYL)
|
||||
option=FORCE_FRSKYL_TUNING; // Use config-defined tuning value for FrSkyL
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_FRSKYV_TUNING) && defined(FRSKYV_CC2500_INO)
|
||||
if(protocol==PROTO_FRSKYV)
|
||||
option=FORCE_FRSKYV_TUNING; // Use config-defined tuning value for FrSkyV
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_FRSKYX_TUNING) && defined(FRSKYX_CC2500_INO)
|
||||
if(protocol==PROTO_FRSKYX)
|
||||
if(protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2)
|
||||
option=FORCE_FRSKYX_TUNING; // Use config-defined tuning value for FrSkyX
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_SFHSS_TUNING) && defined(SFHSS_CC2500_INO)
|
||||
if (protocol==PROTO_SFHSS)
|
||||
option=FORCE_SFHSS_TUNING; // Use config-defined tuning value for SFHSS
|
||||
#if defined(FORCE_FUTABA_TUNING) && defined(FUTABA_CC2500_INO)
|
||||
if (protocol==PROTO_FUTABA)
|
||||
option=FORCE_FUTABA_TUNING; // Use config-defined tuning value for SFHSS
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_CORONA_TUNING) && defined(CORONA_CC2500_INO)
|
||||
@@ -1557,11 +1813,21 @@ void update_serial_data()
|
||||
option=FORCE_CORONA_TUNING; // Use config-defined tuning value for CORONA
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_SKYARTEC_TUNING) && defined(SKYARTEC_CC2500_INO)
|
||||
if (protocol==PROTO_SKYARTEC)
|
||||
option=FORCE_SKYARTEC_TUNING; // Use config-defined tuning value for SKYARTEC
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_REDPINE_TUNING) && defined(REDPINE_CC2500_INO)
|
||||
if (protocol==PROTO_REDPINE)
|
||||
option=FORCE_REDPINE_TUNING; // Use config-defined tuning value for REDPINE
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_RADIOLINK_TUNING) && defined(RADIOLINK_CC2500_INO)
|
||||
if (protocol==PROTO_RADIOLINK)
|
||||
option = FORCE_RADIOLINK_TUNING; // Use config-defined tuning value for RADIOLINK
|
||||
else
|
||||
#endif
|
||||
#if defined(FORCE_HITEC_TUNING) && defined(HITEC_CC2500_INO)
|
||||
if (protocol==PROTO_HITEC)
|
||||
option=FORCE_HITEC_TUNING; // Use config-defined tuning value for HITEC
|
||||
@@ -1649,8 +1915,8 @@ void update_serial_data()
|
||||
else
|
||||
if( ((rx_ok_buff[1]&0x80)==0) && ((cur_protocol[1]&0x80)!=0) ) // Bind flag has been reset
|
||||
{ // Request protocol to end bind
|
||||
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYV_CC2500_INO) || defined(AFHDS2A_A7105_INO)
|
||||
if(protocol==PROTO_FRSKYD || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYV || protocol==PROTO_AFHDS2A )
|
||||
#if defined(FRSKYD_CC2500_INO) || defined(FRSKYL_CC2500_INO) || defined(FRSKYX_CC2500_INO) || defined(FRSKYV_CC2500_INO) || defined(AFHDS2A_A7105_INO) || defined(FRSKYR9_SX1276_INO) || defined(DSM_RX_CYRF6936_INO)
|
||||
if(protocol==PROTO_FRSKYD || protocol==PROTO_FRSKYL || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKYV || protocol==PROTO_AFHDS2A || protocol==PROTO_FRSKY_R9 || protocol==PROTO_DSM_RX)
|
||||
BIND_DONE;
|
||||
else
|
||||
#endif
|
||||
@@ -1709,19 +1975,32 @@ void update_serial_data()
|
||||
#endif
|
||||
if(rx_len>27)
|
||||
{ // Data available for the current protocol
|
||||
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYR9_SX1276_INO)
|
||||
if((protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKY_R9) && rx_len==28)
|
||||
{//Protocol waiting for 1 byte during bind
|
||||
binding_idx=rx_ok_buff[27];
|
||||
}
|
||||
#endif
|
||||
#ifdef SPORT_SEND
|
||||
if(protocol==PROTO_FRSKYX && rx_len==35)
|
||||
if((protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 || protocol==PROTO_FRSKY_R9) && rx_len==27+8)
|
||||
{//Protocol waiting for 8 bytes
|
||||
#define BYTE_STUFF 0x7D
|
||||
#define STUFF_MASK 0x20
|
||||
//debug("SPort_in: ");
|
||||
boolean sport_valid=false;
|
||||
for(uint8_t i=28;i<28+7;i++)
|
||||
if(rx_ok_buff[i]!=0) sport_valid=true; //Check that the payload is not full of 0
|
||||
if((rx_ok_buff[27]&0x1F) > 0x1B) //Check 1st byte validity
|
||||
sport_valid=false;
|
||||
if(sport_valid)
|
||||
{
|
||||
SportData[SportTail]=0x7E;
|
||||
SportTail = (SportTail+1) & (MAX_SPORT_BUFFER-1);
|
||||
SportData[SportTail]=rx_ok_buff[27]&0x1F;
|
||||
SportTail = (SportTail+1) & (MAX_SPORT_BUFFER-1);
|
||||
for(uint8_t i=28;i<28+7;i++)
|
||||
{
|
||||
if(rx_ok_buff[i]==BYTE_STUFF)
|
||||
if( (rx_ok_buff[i]==BYTE_STUFF) || (rx_ok_buff[i]==0x7E) )
|
||||
{//stuff
|
||||
SportData[SportTail]=BYTE_STUFF;
|
||||
SportTail = (SportTail+1) & (MAX_SPORT_BUFFER-1);
|
||||
@@ -1744,14 +2023,22 @@ void update_serial_data()
|
||||
debugln("Low buf=%d,h=%d,t=%d",used,SportHead,SportTail);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //SPORT_SEND
|
||||
#ifdef HOTT_FW_TELEMETRY
|
||||
if(protocol==PROTO_HOTT && rx_len==28)
|
||||
if(protocol==PROTO_HOTT && rx_len==27+1)
|
||||
{//Protocol waiting for 1 byte
|
||||
HoTT_SerialRX_val=rx_ok_buff[27];
|
||||
HoTT_SerialRX=true;
|
||||
}
|
||||
#endif
|
||||
#ifdef DSM_FWD_PGM
|
||||
if(protocol==PROTO_DSM && rx_len==27+7)
|
||||
{//Protocol waiting for 7 bytes
|
||||
memcpy(DSM_SerialRX_val, (const void *)&rx_ok_buff[27],7);
|
||||
DSM_SerialRX=true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
RX_DONOTUPDATE_off;
|
||||
@@ -1791,6 +2078,9 @@ void modules_reset()
|
||||
#ifdef NRF24L01_INSTALLED
|
||||
NRF24L01_Reset();
|
||||
#endif
|
||||
#ifdef SX1276_INSTALLED
|
||||
SX1276_Reset();
|
||||
#endif
|
||||
|
||||
//Wait for every component to reset
|
||||
delayMilliseconds(100);
|
||||
@@ -1993,14 +2283,14 @@ void pollBoot()
|
||||
#if defined(TELEMETRY)
|
||||
void PPM_Telemetry_serial_init()
|
||||
{
|
||||
if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_BAYANG)|| (protocol==PROTO_NCC1701) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI)
|
||||
if( (protocol==PROTO_FRSKYD) || (protocol==PROTO_HUBSAN) || (protocol==PROTO_AFHDS2A) || (protocol==PROTO_BAYANG)|| (protocol==PROTO_NCC1701) || (protocol==PROTO_CABELL) || (protocol==PROTO_HITEC) || (protocol==PROTO_BUGS) || (protocol==PROTO_BUGSMINI) || (protocol==PROTO_PROPEL) || (protocol==PROTO_OMP) || (protocol==PROTO_RLINK)
|
||||
#ifdef TELEMETRY_FRSKYX_TO_FRSKYD
|
||||
|| (protocol==PROTO_FRSKYX)
|
||||
|| (protocol==PROTO_FRSKYX) || (protocol==PROTO_FRSKYX2)
|
||||
#endif
|
||||
)
|
||||
initTXSerial( SPEED_9600 ) ;
|
||||
#ifndef TELEMETRY_FRSKYX_TO_FRSKYD
|
||||
if(protocol==PROTO_FRSKYX)
|
||||
if(protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2)
|
||||
initTXSerial( SPEED_57600 ) ;
|
||||
#endif
|
||||
if(protocol==PROTO_DSM)
|
||||
@@ -2059,6 +2349,51 @@ static uint32_t random_id(uint16_t address, uint8_t create_new)
|
||||
#endif
|
||||
}
|
||||
|
||||
// Generate frequency hopping sequence in the range [02..77]
|
||||
static void __attribute__((unused)) calc_fh_channels(uint8_t num_ch)
|
||||
{
|
||||
uint8_t idx = 0;
|
||||
uint32_t rnd = MProtocol_id;
|
||||
uint8_t max=(num_ch/3)+2;
|
||||
|
||||
while (idx < num_ch)
|
||||
{
|
||||
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 a distance of 5 between consecutive channels
|
||||
if (idx !=0)
|
||||
{
|
||||
if(hopping_frequency[idx-1]>next_ch)
|
||||
{
|
||||
if(hopping_frequency[idx-1]-next_ch<5)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
if(next_ch-hopping_frequency[idx-1]<5)
|
||||
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 < max) || (next_ch >= 27 && next_ch <= 50 && count_27_50 < max) || (next_ch >= 51 && count_51_74 < max) )
|
||||
hopping_frequency[idx++] = next_ch;//find hopping frequency
|
||||
}
|
||||
}
|
||||
|
||||
/**************************/
|
||||
/**************************/
|
||||
/** Interrupt routines **/
|
||||
@@ -2211,7 +2546,7 @@ static uint32_t random_id(uint16_t address, uint8_t create_new)
|
||||
ISR(TIMER1_COMPB_vect)
|
||||
#endif
|
||||
{ // Timer1 compare B interrupt
|
||||
if(rx_idx>=26 && rx_idx<RXBUFFER_SIZE)
|
||||
if(rx_idx>=26 && rx_idx<=RXBUFFER_SIZE)
|
||||
{
|
||||
// A full frame has been received
|
||||
if(!IS_RX_DONOTUPDATE_on)
|
||||
@@ -2230,7 +2565,7 @@ static uint32_t random_id(uint16_t address, uint8_t create_new)
|
||||
}
|
||||
#ifdef DEBUG_SERIAL
|
||||
else
|
||||
debugln("RX frame too short");
|
||||
debugln("RX frame size incorrect");
|
||||
#endif
|
||||
discard_frame=true;
|
||||
#ifdef STM32_BOARD
|
||||
|
||||
@@ -172,6 +172,10 @@ void NRF24L01_SetPower()
|
||||
if(prev_power != power)
|
||||
{
|
||||
rf_setup = (rf_setup & 0xF9) | (power << 1);
|
||||
if(power==3)
|
||||
rf_setup |=0x01; // Si24r01 full power, unused bit for NRF
|
||||
else
|
||||
rf_setup &=0xFE;
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
|
||||
prev_power=power;
|
||||
}
|
||||
@@ -505,7 +509,7 @@ boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
|
||||
//process address
|
||||
for (uint8_t i = 0; i < xn297_addr_len; ++i)
|
||||
{
|
||||
uint8_t b_in=xn297_tx_addr[xn297_addr_len-i-1];
|
||||
uint8_t b_in=xn297_rx_addr[xn297_addr_len-i-1];
|
||||
if(xn297_scramble_enabled)
|
||||
b_in ^= xn297_scramble[i];
|
||||
crc = crc16_update(crc, b_in, 8);
|
||||
@@ -525,10 +529,13 @@ boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
|
||||
}
|
||||
|
||||
uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
{ //!!! Don't forget do a +2 and if using CRC add +4 on any of the used NRF24L01_11_RX_PW_Px !!!
|
||||
uint8_t buffer[32];
|
||||
uint8_t pcf_size; // pcf payload size
|
||||
NRF24L01_ReadPayload(buffer, len+2); // pcf + payload
|
||||
if (xn297_crc)
|
||||
NRF24L01_ReadPayload(buffer, len+4); // Read pcf + payload + CRC
|
||||
else
|
||||
NRF24L01_ReadPayload(buffer, len+2); // Read pcf + payload
|
||||
pcf_size = buffer[0];
|
||||
if(xn297_scramble_enabled)
|
||||
pcf_size ^= xn297_scramble[xn297_addr_len];
|
||||
@@ -540,7 +547,35 @@ uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
|
||||
msg[i] ^= bit_reverse((xn297_scramble[xn297_addr_len+i+1] << 2) |
|
||||
(xn297_scramble[xn297_addr_len+i+2] >> 6));
|
||||
}
|
||||
return pcf_size;
|
||||
|
||||
if (!xn297_crc)
|
||||
return pcf_size; // No CRC so OK by default...
|
||||
|
||||
// Calculate CRC
|
||||
uint16_t crc = 0xb5d2;
|
||||
//process address
|
||||
for (uint8_t i = 0; i < xn297_addr_len; ++i)
|
||||
{
|
||||
uint8_t b_in=xn297_rx_addr[xn297_addr_len-i-1];
|
||||
if(xn297_scramble_enabled)
|
||||
b_in ^= xn297_scramble[i];
|
||||
crc = crc16_update(crc, b_in, 8);
|
||||
}
|
||||
//process payload
|
||||
for (uint8_t i = 0; i < len+1; ++i)
|
||||
crc = crc16_update(crc, buffer[i], 8);
|
||||
crc = crc16_update(crc, buffer[len+1] & 0xc0, 2);
|
||||
//xorout
|
||||
if (xn297_scramble_enabled)
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
|
||||
#ifdef XN297DUMP_NRF24L01_INO
|
||||
else
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
|
||||
#endif
|
||||
uint16_t crcxored=(buffer[len+1]<<10)|(buffer[len+2]<<2)|(buffer[len+3]>>6) ;
|
||||
if( crc == crcxored)
|
||||
return pcf_size; // CRC OK
|
||||
return 0; // CRC NOK
|
||||
}
|
||||
|
||||
// End of XN297 emulation
|
||||
|
||||
464
Multiprotocol/NRF250K_EMU.ino
Normal file
464
Multiprotocol/NRF250K_EMU.ino
Normal file
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifdef NRF24L01_INSTALLED
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
static void __attribute__((unused)) XN297L_Init()
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
debugln("Using NRF");
|
||||
PE1_on; //NRF24L01 antenna RF3 by default
|
||||
PE2_off; //NRF24L01 antenna RF3 by default
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
|
||||
NRF24L01_SetPower();
|
||||
return;
|
||||
}
|
||||
//CC2500
|
||||
#ifdef CC2500_INSTALLED
|
||||
debugln("Using CC2500");
|
||||
PE1_off; // antenna RF2
|
||||
PE2_on;
|
||||
CC2500_Reset();
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
|
||||
// Address Config = No address check
|
||||
// Base Frequency = 2400
|
||||
// CRC Autoflush = false
|
||||
// CRC Enable = false
|
||||
// Channel Spacing = 333.251953
|
||||
// Data Format = Normal mode
|
||||
// Data Rate = 249.939
|
||||
// Deviation = 126.953125
|
||||
// Device Address = 0
|
||||
// Manchester Enable = false
|
||||
// Modulated = true
|
||||
// Modulation Format = GFSK
|
||||
// Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word
|
||||
// RX Filter BW = 203.125000
|
||||
// Sync Word Qualifier Mode = No preamble/sync
|
||||
// TX Power = 0
|
||||
// Whitening = false
|
||||
// Fast Frequency Hopping - no PLL auto calibration
|
||||
|
||||
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x01); // Packet Automation Control
|
||||
CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0A); // Frequency Synthesizer Control
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option); // Frequency offset hack
|
||||
CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // Frequency Control Word, High Byte
|
||||
CC2500_WriteReg(CC2500_0E_FREQ1, 0x4E); // Frequency Control Word, Middle Byte
|
||||
CC2500_WriteReg(CC2500_0F_FREQ0, 0xC3); // Frequency Control Word, Low Byte
|
||||
CC2500_WriteReg(CC2500_10_MDMCFG4, 0x8D); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_12_MDMCFG2, 0x10); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_14_MDMCFG0, 0xA4); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_15_DEVIATN, 0x62); // Modem Deviation Setting
|
||||
CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // Main Radio Control State Machine Configuration
|
||||
CC2500_WriteReg(CC2500_19_FOCCFG, 0x1D); // Frequency Offset Compensation Configuration
|
||||
CC2500_WriteReg(CC2500_1A_BSCFG, 0x1C); // Bit Synchronization Configuration
|
||||
CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xC7); // AGC Control
|
||||
CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x00); // AGC Control
|
||||
CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0xB0); // AGC Control
|
||||
CC2500_WriteReg(CC2500_21_FREND1, 0xB6); // Front End RX Configuration
|
||||
CC2500_WriteReg(CC2500_23_FSCAL3, 0xEA); // Frequency Synthesizer Calibration
|
||||
CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // Frequency Synthesizer Calibration
|
||||
CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // Frequency Synthesizer Calibration
|
||||
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
CC2500_SetPower();
|
||||
xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t* addr, uint8_t len)
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
XN297_SetTXAddr(addr,len);
|
||||
return;
|
||||
}
|
||||
//CC2500
|
||||
#ifdef CC2500_INSTALLED
|
||||
if (len > 5) len = 5;
|
||||
if (len < 3) len = 3;
|
||||
xn297_addr_len = len;
|
||||
memcpy(xn297_tx_addr, addr, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
XN297_WritePayload(msg, len);
|
||||
return;
|
||||
}
|
||||
//CC2500
|
||||
#ifdef CC2500_INSTALLED
|
||||
uint8_t buf[32];
|
||||
uint8_t last = 0;
|
||||
uint8_t i;
|
||||
static const uint16_t initial = 0xb5d2;
|
||||
|
||||
// address
|
||||
for (i = 0; i < xn297_addr_len; ++i)
|
||||
{
|
||||
buf[last] = xn297_tx_addr[xn297_addr_len - i - 1];
|
||||
if(xn297_scramble_enabled)
|
||||
buf[last] ^= xn297_scramble[i];
|
||||
last++;
|
||||
}
|
||||
|
||||
// payload
|
||||
for (i = 0; i < len; ++i) {
|
||||
// bit-reverse bytes in packet
|
||||
buf[last] = bit_reverse(msg[i]);
|
||||
if(xn297_scramble_enabled)
|
||||
buf[last] ^= xn297_scramble[xn297_addr_len+i];
|
||||
last++;
|
||||
}
|
||||
|
||||
// crc
|
||||
uint16_t crc = initial;
|
||||
for (uint8_t i = 0; i < last; ++i)
|
||||
crc = crc16_update(crc, buf[i], 8);
|
||||
if(xn297_scramble_enabled)
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
|
||||
else
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]);
|
||||
buf[last++] = crc >> 8;
|
||||
buf[last++] = crc & 0xff;
|
||||
|
||||
// stop TX/RX
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
// flush tx FIFO
|
||||
CC2500_Strobe(CC2500_SFTX);
|
||||
// packet length
|
||||
CC2500_WriteReg(CC2500_3F_TXFIFO, last + 3);
|
||||
// xn297L preamble
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (uint8_t*)"\x71\x0f\x55", 3);
|
||||
// xn297 packet
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last);
|
||||
// transmit
|
||||
CC2500_Strobe(CC2500_STX);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
XN297_WriteEnhancedPayload(msg, len, noack);
|
||||
return;
|
||||
}
|
||||
//CC2500
|
||||
#ifdef CC2500_INSTALLED
|
||||
uint8_t buf[32];
|
||||
uint8_t scramble_index=0;
|
||||
uint8_t last = 0;
|
||||
static uint8_t pid=0;
|
||||
|
||||
// address
|
||||
for (uint8_t i = 0; i < xn297_addr_len; ++i)
|
||||
{
|
||||
buf[last] = xn297_tx_addr[xn297_addr_len-i-1];
|
||||
if(xn297_scramble_enabled)
|
||||
buf[last] ^= xn297_scramble[scramble_index++];
|
||||
last++;
|
||||
}
|
||||
|
||||
// pcf
|
||||
buf[last] = (len << 1) | (pid>>1);
|
||||
if(xn297_scramble_enabled)
|
||||
buf[last] ^= xn297_scramble[scramble_index++];
|
||||
last++;
|
||||
buf[last] = (pid << 7) | (noack << 6);
|
||||
|
||||
// payload
|
||||
buf[last]|= bit_reverse(msg[0]) >> 2; // first 6 bit of payload
|
||||
if(xn297_scramble_enabled)
|
||||
buf[last] ^= xn297_scramble[scramble_index++];
|
||||
|
||||
for (uint8_t i = 0; i < len-1; ++i)
|
||||
{
|
||||
last++;
|
||||
buf[last] = (bit_reverse(msg[i]) << 6) | (bit_reverse(msg[i+1]) >> 2);
|
||||
if(xn297_scramble_enabled)
|
||||
buf[last] ^= xn297_scramble[scramble_index++];
|
||||
}
|
||||
|
||||
last++;
|
||||
buf[last] = bit_reverse(msg[len-1]) << 6; // last 2 bit of payload
|
||||
if(xn297_scramble_enabled)
|
||||
buf[last] ^= xn297_scramble[scramble_index++] & 0xc0;
|
||||
|
||||
// crc
|
||||
//if (xn297_crc)
|
||||
{
|
||||
uint16_t 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);
|
||||
if (xn297_scramble_enabled)
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
|
||||
//else
|
||||
// crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
|
||||
|
||||
buf[last++] |= (crc >> 8) >> 2;
|
||||
buf[last++] = ((crc >> 8) << 6) | ((crc & 0xff) >> 2);
|
||||
buf[last++] = (crc & 0xff) << 6;
|
||||
}
|
||||
|
||||
pid++;
|
||||
pid &= 3;
|
||||
|
||||
// stop TX/RX
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
// flush tx FIFO
|
||||
CC2500_Strobe(CC2500_SFTX);
|
||||
// packet length
|
||||
CC2500_WriteReg(CC2500_3F_TXFIFO, last + 3);
|
||||
// xn297L preamble
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (uint8_t*)"\x71\x0F\x55", 3);
|
||||
// xn297 packet
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last);
|
||||
// transmit
|
||||
CC2500_Strobe(CC2500_STX);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_HoppingCalib(uint8_t num_freq)
|
||||
{ //calibrate hopping frequencies
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
return; //NRF
|
||||
#ifdef CC2500_INSTALLED
|
||||
for (uint8_t i = 0; i < num_freq; i++)
|
||||
{
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[i]*3);
|
||||
CC2500_Strobe(CC2500_SCAL);
|
||||
delayMicroseconds(900);
|
||||
calData[i]=CC2500_ReadReg(CC2500_25_FSCAL1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_Hopping(uint8_t index)
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[index]);
|
||||
return;
|
||||
}
|
||||
#ifdef CC2500_INSTALLED
|
||||
// spacing is 333.25 kHz, must multiply xn297 channel by 3
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[index] * 3);
|
||||
// set PLL calibration
|
||||
CC2500_WriteReg(CC2500_25_FSCAL1, calData[index]);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_RFChannel(uint8_t number)
|
||||
{ //change channel
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, number);
|
||||
return;
|
||||
}
|
||||
#ifdef CC2500_INSTALLED
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, number*3);
|
||||
CC2500_Strobe(CC2500_SCAL);
|
||||
delayMicroseconds(900);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_SetPower()
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
NRF24L01_SetPower();
|
||||
return;
|
||||
}
|
||||
#ifdef CC2500_INSTALLED
|
||||
CC2500_SetPower();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_SetFreqOffset()
|
||||
{ // Frequency offset
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0 && prev_option==0)
|
||||
#endif
|
||||
return; //NRF
|
||||
#ifdef CC2500_INSTALLED
|
||||
if (prev_option != option)
|
||||
{
|
||||
if(prev_option==0 || option==0)
|
||||
CHANGE_PROTOCOL_FLAG_on;
|
||||
prev_option = option;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) NRF250K_SetTXAddr(uint8_t* addr, uint8_t len)
|
||||
{
|
||||
if (len > 5) len = 5;
|
||||
if (len < 3) len = 3;
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr, len);
|
||||
return;
|
||||
}
|
||||
//CC2500
|
||||
#ifdef CC2500_INSTALLED
|
||||
xn297_addr_len = len;
|
||||
memcpy(xn297_tx_addr, addr, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) NRF250K_WritePayload(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_MAX_RT));
|
||||
NRF24L01_WritePayload(msg, len);
|
||||
return;
|
||||
}
|
||||
//CC2500
|
||||
#ifdef CC2500_INSTALLED
|
||||
#if defined(ESKY150V2_CC2500_INO)
|
||||
uint8_t buf[158];
|
||||
#else
|
||||
uint8_t buf[35];
|
||||
#endif
|
||||
uint8_t last = 0;
|
||||
uint8_t i;
|
||||
|
||||
//nrf preamble
|
||||
if(xn297_tx_addr[xn297_addr_len - 1] & 0x80)
|
||||
buf[0]=0xAA;
|
||||
else
|
||||
buf[0]=0x55;
|
||||
last++;
|
||||
// address
|
||||
for (i = 0; i < xn297_addr_len; ++i)
|
||||
buf[last++] = xn297_tx_addr[xn297_addr_len - i - 1];
|
||||
// payload
|
||||
for (i = 0; i < len; ++i)
|
||||
buf[last++] = msg[i];
|
||||
|
||||
// crc
|
||||
uint16_t crc = 0xffff;
|
||||
for (uint8_t i = 1; i < last; ++i)
|
||||
crc = crc16_update(crc, buf[i], 8);
|
||||
buf[last++] = crc >> 8;
|
||||
buf[last++] = crc & 0xff;
|
||||
buf[last++] = 0;
|
||||
|
||||
//for(uint8_t i=0;i<last;i++)
|
||||
// debug("%02X ",buf[i]);
|
||||
//debugln("");
|
||||
// stop TX/RX
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
// flush tx FIFO
|
||||
CC2500_Strobe(CC2500_SFTX);
|
||||
// packet length
|
||||
CC2500_WriteReg(CC2500_3F_TXFIFO, last);
|
||||
// transmit nrf packet
|
||||
uint8_t *buff=buf;
|
||||
uint8_t status;
|
||||
if(last>63)
|
||||
{
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, 63);
|
||||
CC2500_Strobe(CC2500_STX);
|
||||
last-=63;
|
||||
buff+=63;
|
||||
while(last)
|
||||
{//Loop until all the data is sent
|
||||
do
|
||||
{// Wait for the FIFO to become available
|
||||
status=CC2500_ReadReg(CC2500_3A_TXBYTES | CC2500_READ_BURST);
|
||||
}
|
||||
while((status&0x7F)>31 && (status&0x80)==0);
|
||||
if(last>31)
|
||||
{//Send 31 bytes
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, 31);
|
||||
last-=31;
|
||||
buff+=31;
|
||||
}
|
||||
else
|
||||
{//Send last bytes
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, last);
|
||||
last=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{//Send packet
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, last);
|
||||
CC2500_Strobe(CC2500_STX);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static boolean __attribute__((unused)) NRF250K_IsPacketSent()
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{ //NRF
|
||||
return NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS);
|
||||
}
|
||||
return true; // don't know on the CC2500 how to detect if the packet has been transmitted...
|
||||
}
|
||||
|
||||
#endif
|
||||
73
Multiprotocol/NanoRF_nrf24l01.ino
Normal file
73
Multiprotocol/NanoRF_nrf24l01.ino
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(NANORF_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#define NANORF_PACKET_PERIOD 40000
|
||||
#define NANORF_INITIAL_WAIT 500
|
||||
#define NANORF_RF_CHANNEL 40
|
||||
#define NANORF_PAYLOADSIZE 7
|
||||
|
||||
static void __attribute__((unused)) NANORF_send_packet()
|
||||
{
|
||||
packet[0] = convert_channel_8b(AILERON);
|
||||
packet[1] = convert_channel_8b(ELEVATOR);
|
||||
packet[2] = convert_channel_8b(THROTTLE);
|
||||
packet[3] = convert_channel_8b(RUDDER);
|
||||
packet[4] = convert_channel_8b(CH5);
|
||||
packet[5] = convert_channel_8b(CH6);
|
||||
packet[6] = 0;
|
||||
for (uint8_t i=0; i < NANORF_PAYLOADSIZE-1; i++)
|
||||
packet[6] += packet[i];
|
||||
packet[6] += 0x55;
|
||||
|
||||
// clear packet status bits and TX FIFO
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WritePayload(packet, NANORF_PAYLOADSIZE);
|
||||
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) NANORF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR , (uint8_t *)"Nano1",5);
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable all data pipes (even though not used?)
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // 4mS retransmit t/o, 15 tries (retries w/o AA?)
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, NANORF_RF_CHANNEL);
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M);
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP)); //
|
||||
}
|
||||
|
||||
uint16_t NANORF_callback()
|
||||
{
|
||||
NANORF_send_packet();
|
||||
return NANORF_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initNANORF()
|
||||
{
|
||||
BIND_DONE;
|
||||
NANORF_init();
|
||||
return NANORF_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
300
Multiprotocol/OMP_cc2500.ino
Normal file
300
Multiprotocol/OMP_cc2500.ino
Normal file
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(OMP_CC2500_INO)
|
||||
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
//#define FORCE_OMP_ORIGINAL_ID
|
||||
//#define OMP_TELEM_DEBUG
|
||||
|
||||
#define OMP_INITIAL_WAIT 500
|
||||
#define OMP_PACKET_PERIOD 5000
|
||||
#define OMP_RF_BIND_CHANNEL 35
|
||||
#define OMP_RF_NUM_CHANNELS 8
|
||||
#define OMP_PAYLOAD_SIZE 16
|
||||
#define OMP_BIND_COUNT 600 //3sec
|
||||
|
||||
static void __attribute__((unused)) OMP_send_packet()
|
||||
{
|
||||
#ifdef OMP_HUB_TELEMETRY
|
||||
if(option==0) option=1; // Select the CC2500 by default
|
||||
PE1_off; PE2_on; // CC2500 antenna RF2
|
||||
#endif
|
||||
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
memcpy(packet,"BND",3);
|
||||
memcpy(&packet[3],rx_tx_addr,5);
|
||||
memcpy(&packet[8],hopping_frequency,8);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(packet,0x00,OMP_PAYLOAD_SIZE);
|
||||
|
||||
#ifdef OMP_HUB_TELEMETRY
|
||||
//RX telem request every 7*5=35ms
|
||||
packet_sent++;
|
||||
packet_sent %= OMP_RF_NUM_CHANNELS-1; // Change telem RX channels every time
|
||||
if(packet_sent==0)
|
||||
{
|
||||
packet[0] |= 0x40; // |0x40 to request RX telemetry
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
|
||||
}
|
||||
#endif
|
||||
|
||||
//hopping frequency
|
||||
packet[0 ] |= hopping_frequency_no;
|
||||
XN297L_Hopping(hopping_frequency_no);
|
||||
hopping_frequency_no++;
|
||||
hopping_frequency_no &= OMP_RF_NUM_CHANNELS-1; // 8 RF channels
|
||||
|
||||
//flags
|
||||
packet[1 ] = 0x08 //unknown
|
||||
| GET_FLAG(CH5_SW, 0x20); // HOLD
|
||||
|
||||
packet[2 ] = 0x40; //unknown
|
||||
|
||||
if(Channel_data[CH6] > CHANNEL_MAX_COMMAND)
|
||||
packet[2 ] |= 0x20; // IDLE2
|
||||
else if(Channel_data[CH6] > CHANNEL_MIN_COMMAND)
|
||||
packet[1 ] |= 0x40; // IDLE1
|
||||
|
||||
if(Channel_data[CH7] > CHANNEL_MAX_COMMAND)
|
||||
packet[2 ] |= 0x08; // 3D
|
||||
else if(Channel_data[CH7] > CHANNEL_MIN_COMMAND)
|
||||
packet[2 ] |= 0x04; // ATTITUDE
|
||||
|
||||
//trims??
|
||||
//packet[3..6]
|
||||
|
||||
//channels TAER packed 11bits
|
||||
uint16_t channel=convert_channel_16b_limit(THROTTLE,0,2047);
|
||||
packet[7 ] = channel;
|
||||
packet[8 ] = channel>>8;
|
||||
channel=convert_channel_16b_limit(AILERON,2047,0);
|
||||
packet[8 ] |= channel<<3;
|
||||
packet[9 ] = channel>>5;
|
||||
channel=convert_channel_16b_limit(ELEVATOR,0,2047);
|
||||
packet[9] |= channel<<6;
|
||||
packet[10] = channel>>2;
|
||||
packet[11] = channel>>10;
|
||||
channel=convert_channel_16b_limit(RUDDER,2047,0);
|
||||
packet[11] |= channel<<1;
|
||||
packet[12] = channel>>7;
|
||||
|
||||
//unknown
|
||||
//packet[13..15]
|
||||
packet[15] = 0x04;
|
||||
}
|
||||
|
||||
XN297L_SetPower(); // Set tx_power
|
||||
XN297L_SetFreqOffset(); // Set frequency offset
|
||||
XN297L_WriteEnhancedPayload(packet, OMP_PAYLOAD_SIZE, packet_sent!=0);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) OMP_init()
|
||||
{
|
||||
//Config CC2500
|
||||
#ifdef OMP_HUB_TELEMETRY
|
||||
if(option==0)
|
||||
option=1; // Select the CC2500
|
||||
#endif
|
||||
XN297L_Init();
|
||||
XN297L_SetTXAddr((uint8_t*)"FLPBD", 5);
|
||||
XN297L_HoppingCalib(OMP_RF_NUM_CHANNELS); // Calibrate all channels
|
||||
XN297L_RFChannel(OMP_RF_BIND_CHANNEL); // Set bind channel
|
||||
|
||||
#ifdef OMP_HUB_TELEMETRY
|
||||
//Config NRF
|
||||
option=0; // Select the NRF
|
||||
XN297L_Init();
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC));
|
||||
XN297_SetRXAddr(rx_tx_addr, 5); // Set the RX address
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF); // Turn it off for now
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, OMP_PAYLOAD_SIZE + 4); // packet length +4 bytes of PCF+CRC
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) OMP_initialize_txid()
|
||||
{
|
||||
calc_fh_channels(OMP_RF_NUM_CHANNELS);
|
||||
#ifdef FORCE_OMP_ORIGINAL_ID
|
||||
rx_tx_addr[0]=0x4E;
|
||||
rx_tx_addr[1]=0x72;
|
||||
rx_tx_addr[2]=0x8E;
|
||||
rx_tx_addr[3]=0x70;
|
||||
rx_tx_addr[4]=0x62;
|
||||
for(uint8_t i=0; i<OMP_RF_NUM_CHANNELS;i++)
|
||||
hopping_frequency[i]=(i+3)*5;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef OMP_HUB_TELEMETRY
|
||||
static void __attribute__((unused)) OMP_Send_Telemetry(uint8_t v)
|
||||
{
|
||||
v_lipo1=v;
|
||||
telemetry_counter++; //LQI
|
||||
telemetry_link=1;
|
||||
if(telemetry_lost)
|
||||
{
|
||||
telemetry_lost = 0;
|
||||
packet_count = 100;
|
||||
telemetry_counter = 100;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
enum {
|
||||
OMP_BIND = 0x00,
|
||||
OMP_PREPDATA = 0x01,
|
||||
OMP_DATA = 0x02,
|
||||
OMP_RX = 0x03,
|
||||
};
|
||||
|
||||
#define OMP_WRITE_TIME 850
|
||||
|
||||
uint16_t OMP_callback()
|
||||
{
|
||||
switch(phase)
|
||||
{
|
||||
case OMP_BIND:
|
||||
if(--bind_counter==0)
|
||||
phase++; // OMP_PREPDATA
|
||||
OMP_send_packet();
|
||||
return OMP_PACKET_PERIOD;
|
||||
case OMP_PREPDATA:
|
||||
BIND_DONE;
|
||||
XN297L_SetTXAddr(rx_tx_addr, 5);
|
||||
phase++; // OMP_DATA
|
||||
case OMP_DATA:
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(OMP_PACKET_PERIOD);
|
||||
#endif
|
||||
OMP_send_packet();
|
||||
#ifdef OMP_HUB_TELEMETRY
|
||||
if(packet_sent == 0)
|
||||
{
|
||||
phase++; // OMP_RX
|
||||
return OMP_WRITE_TIME;
|
||||
}
|
||||
else if(packet_sent == 1)
|
||||
{
|
||||
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{ // a packet has been received
|
||||
if(XN297_ReadEnhancedPayload(packet_in, OMP_PAYLOAD_SIZE) == OMP_PAYLOAD_SIZE)
|
||||
{ // packet with good CRC and length
|
||||
#ifdef OMP_TELEM_DEBUG
|
||||
debug("OK :");
|
||||
for(uint8_t i=0;i<OMP_PAYLOAD_SIZE;i++)
|
||||
debug(" %02X",packet_in[i]);
|
||||
#endif
|
||||
// packet_in = 01 00 98 2C 03 19 19 F0 49 02 00 00 00 00 00 00
|
||||
// all bytes are fixed and unknown except 2 and 3 which represent the battery voltage: packet_in[3]*256+packet_in[2]=lipo voltage*100 in V
|
||||
uint16_t v=((packet_in[3]<<8)+packet_in[2]-400)/50;
|
||||
if(v>255) v=255;
|
||||
v_lipo2=v;
|
||||
OMP_Send_Telemetry(v);
|
||||
}
|
||||
else
|
||||
{ // As soon as the motor spins the telem packets are becoming really bad and the CRC throws most of them in error as it should but...
|
||||
#ifdef OMP_TELEM_DEBUG
|
||||
debug("NOK:");
|
||||
for(uint8_t i=0;i<OMP_PAYLOAD_SIZE;i++)
|
||||
debug(" %02X",packet_in[i]);
|
||||
#endif
|
||||
if(packet_in[0]==0x01 && packet_in[1]==0x00)
|
||||
{// the start of the packet looks ok...
|
||||
uint16_t v=((packet_in[3]<<8)+packet_in[2]-400)/50;
|
||||
if(v<260 && v>180)
|
||||
{ //voltage is less than 13V and more than 9V (3V/element)
|
||||
if(v>255) v=255;
|
||||
uint16_t v1=v-v_lipo2;
|
||||
if(v1&0x8000) v1=-v1;
|
||||
if(v1<20) // the batt voltage is within 1V from a good reading...
|
||||
{
|
||||
OMP_Send_Telemetry(v); // ok to send
|
||||
#ifdef OMP_TELEM_DEBUG
|
||||
debug(" OK");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
telemetry_counter++; //LQI
|
||||
}
|
||||
#ifdef OMP_TELEM_DEBUG
|
||||
debugln("");
|
||||
#endif
|
||||
}
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
packet_count++;
|
||||
if(packet_count>=100)
|
||||
{//LQI calculation
|
||||
packet_count=0;
|
||||
TX_LQI=telemetry_counter;
|
||||
RX_RSSI=telemetry_counter;
|
||||
if(telemetry_counter==0)
|
||||
telemetry_lost = 1;
|
||||
telemetry_counter = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return OMP_PACKET_PERIOD;
|
||||
#ifdef OMP_HUB_TELEMETRY
|
||||
case OMP_RX:
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, (1 << NRF24L01_07_RX_DR) //reset the flag(s)
|
||||
| (1 << NRF24L01_07_TX_DS)
|
||||
| (1 << NRF24L01_07_MAX_RT));
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_PWR_UP) | (1 << NRF24L01_00_PRIM_RX) ); // Start RX
|
||||
{
|
||||
uint16_t start=(uint16_t)micros();
|
||||
while ((uint16_t)((uint16_t)micros()-(uint16_t)start) < 500)
|
||||
{
|
||||
if(CC2500_ReadReg(CC2500_35_MARCSTATE | CC2500_READ_BURST) != 0x13)
|
||||
break;
|
||||
}
|
||||
}
|
||||
NRF_CE_on;
|
||||
PE1_on;PE2_off; // NRF24L01 antenna RF3
|
||||
phase = OMP_DATA;
|
||||
return OMP_PACKET_PERIOD-OMP_WRITE_TIME;
|
||||
#endif
|
||||
}
|
||||
return OMP_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initOMP()
|
||||
{
|
||||
OMP_initialize_txid();
|
||||
OMP_init();
|
||||
hopping_frequency_no = 0;
|
||||
packet_sent = 0;
|
||||
#ifdef OMP_HUB_TELEMETRY
|
||||
packet_count = 0;
|
||||
telemetry_lost = 1;
|
||||
#endif
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
bind_counter = OMP_BIND_COUNT;
|
||||
phase = OMP_BIND;
|
||||
}
|
||||
else
|
||||
phase = OMP_PREPDATA;
|
||||
return OMP_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
293
Multiprotocol/Pelikan_a7105.ino
Normal file
293
Multiprotocol/Pelikan_a7105.ino
Normal file
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Compatible with CADET PRO V4 TX
|
||||
|
||||
#if defined(PELIKAN_A7105_INO)
|
||||
|
||||
#include "iface_a7105.h"
|
||||
|
||||
//#define PELIKAN_FORCE_ID
|
||||
//#define PELIKAN_LITE_FORCE_ID
|
||||
#define PELIKAN_LITE_FORCE_HOP
|
||||
|
||||
#define PELIKAN_BIND_COUNT 400
|
||||
#define PELIKAN_BIND_RF 0x3C
|
||||
#define PELIKAN_NUM_RF_CHAN 0x1D
|
||||
#define PELIKAN_PACKET_PERIOD 7980
|
||||
#define PELIKAN_LITE_PACKET_PERIOD 18000
|
||||
|
||||
static void __attribute__((unused)) pelikan_build_packet()
|
||||
{
|
||||
static boolean upper=false;
|
||||
packet[0] = 0x15;
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet[1] = 0x04; //version??
|
||||
packet[2] = rx_tx_addr[0];
|
||||
packet[3] = rx_tx_addr[1];
|
||||
packet[4] = rx_tx_addr[2];
|
||||
packet[5] = rx_tx_addr[3];
|
||||
if(sub_protocol==PELIKAN_PRO)
|
||||
packet[6] = 0x05; //sub version??
|
||||
else //PELIKAN_LITE
|
||||
packet[6] = 0x03; //sub version??
|
||||
packet[7] = 0x00; //??
|
||||
packet[8] = 0x55; //??
|
||||
packet_length = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
//ID
|
||||
packet[1] = rx_tx_addr[0];
|
||||
packet[7] = rx_tx_addr[1];
|
||||
packet[12] = rx_tx_addr[2];
|
||||
packet[13] = rx_tx_addr[3];
|
||||
//Channels
|
||||
uint8_t offset=upper?4:0;
|
||||
uint16_t channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871);
|
||||
uint8_t top=(channel>>2) & 0xC0;
|
||||
packet[2] = channel;
|
||||
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871);
|
||||
top|=(channel>>4) & 0x30;
|
||||
packet[3] = channel;
|
||||
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871);
|
||||
top|=(channel>>6) & 0x0C;
|
||||
packet[4] = channel;
|
||||
channel=convert_channel_16b_nolimit(CH_AETR[offset], 153, 871);
|
||||
top|=(channel>>8) & 0x03;
|
||||
packet[5] = channel;
|
||||
packet[6] = top;
|
||||
//Check
|
||||
crc8=0x15;
|
||||
for(uint8_t i=1;i<8;i++)
|
||||
crc8+=packet[i];
|
||||
packet[8]=crc8;
|
||||
//Low/Up channel flag
|
||||
packet[9]=upper?0xAA:0x00;
|
||||
upper=!upper;
|
||||
//Hopping counters
|
||||
if(sub_protocol==PELIKAN_LITE || ++packet_count>4)
|
||||
{
|
||||
packet_count=0;
|
||||
if(++hopping_frequency_no>=PELIKAN_NUM_RF_CHAN)
|
||||
hopping_frequency_no=0;
|
||||
}
|
||||
packet[10]=hopping_frequency_no;
|
||||
packet[11]=packet_count;
|
||||
|
||||
packet_length = 15;
|
||||
}
|
||||
|
||||
//Check
|
||||
crc8=0x15;
|
||||
for(uint8_t i=1; i<packet_length-1 ;i++)
|
||||
crc8+=packet[i];
|
||||
packet[packet_length-1]=crc8;
|
||||
|
||||
//Send
|
||||
#ifdef DEBUG_SERIAL
|
||||
if(packet[9]==0x00)
|
||||
{
|
||||
debug("C: %02X P(%d):",IS_BIND_IN_PROGRESS?PELIKAN_BIND_RF:hopping_frequency[hopping_frequency_no],packet_length);
|
||||
for(uint8_t i=0;i<packet_length;i++)
|
||||
debug(" %02X",packet[i]);
|
||||
debugln("");
|
||||
}
|
||||
#endif
|
||||
A7105_WriteData(packet_length, IS_BIND_IN_PROGRESS?PELIKAN_BIND_RF:hopping_frequency[hopping_frequency_no]);
|
||||
A7105_SetPower();
|
||||
}
|
||||
|
||||
uint16_t ReadPelikan()
|
||||
{
|
||||
if(phase==0)
|
||||
{
|
||||
#ifndef FORCE_PELIKAN_TUNING
|
||||
A7105_AdjustLOBaseFreq(1);
|
||||
#endif
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
bind_counter--;
|
||||
if (bind_counter==0)
|
||||
{
|
||||
BIND_DONE;
|
||||
A7105_Strobe(A7105_STANDBY);
|
||||
if(sub_protocol==PELIKAN_PRO)
|
||||
A7105_WriteReg(A7105_03_FIFOI,0x28);
|
||||
else//PELIKAN_LITE
|
||||
A7105_WriteID(MProtocol_id);
|
||||
}
|
||||
}
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(sub_protocol==PELIKAN_PRO?PELIKAN_PACKET_PERIOD:PELIKAN_LITE_PACKET_PERIOD);
|
||||
#endif
|
||||
pelikan_build_packet();
|
||||
if(sub_protocol==PELIKAN_PRO || IS_BIND_IN_PROGRESS)
|
||||
return PELIKAN_PACKET_PERIOD;
|
||||
//PELIKAN_LITE
|
||||
phase++;
|
||||
return 942;
|
||||
}
|
||||
//PELIKAN_LITE
|
||||
A7105_Strobe(A7105_TX);
|
||||
phase++;
|
||||
if(phase==1)
|
||||
return 942;
|
||||
phase=0;
|
||||
return PELIKAN_LITE_PACKET_PERIOD-942-942;
|
||||
}
|
||||
|
||||
static uint8_t pelikan_firstCh(uint8_t u, uint8_t l)
|
||||
{
|
||||
int16_t i;
|
||||
i = u * 10 + l - 23;
|
||||
do
|
||||
{
|
||||
if (i > 24)
|
||||
i -= 24;
|
||||
if (i <= 0)
|
||||
return 10;
|
||||
else if ((i > 0) && (i < 13))
|
||||
return 10 + 12 + (i * 4);
|
||||
else if ((i > 12) && (i < 24))
|
||||
return 10 - 2 + ((i - 12) * 4);
|
||||
}
|
||||
while (i > 24);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t pelikan_adjust_value(uint8_t value, uint8_t addition, uint8_t limit)
|
||||
{
|
||||
uint8_t i;
|
||||
do
|
||||
{
|
||||
i = 0;
|
||||
if (value > limit) {
|
||||
value -= 62;
|
||||
i++;
|
||||
}
|
||||
if (value == 24) {
|
||||
value += addition;
|
||||
i++;
|
||||
}
|
||||
if (value == 48) {
|
||||
value += addition;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
while (i > 0);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static uint8_t pelikan_add(uint8_t pfrq,uint8_t a, uint8_t limit)
|
||||
{
|
||||
uint8_t nfrq;
|
||||
nfrq = pfrq + a;
|
||||
|
||||
nfrq = pelikan_adjust_value(nfrq, a, limit);
|
||||
|
||||
return nfrq;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) pelikan_init_hop()
|
||||
{
|
||||
#define PELIKAN_HOP_LIMIT 70
|
||||
rx_tx_addr[0] = 0;
|
||||
rx_tx_addr[1]+= RX_num;
|
||||
uint8_t high = (rx_tx_addr[1]>>4) % 3; // 0..2
|
||||
uint8_t low = rx_tx_addr[1] & 0x0F;
|
||||
if(high==2)
|
||||
low %= 0x04; // 0..3
|
||||
else if(high)
|
||||
low %= 0x0E; // 0..D
|
||||
else
|
||||
low %= 0x0F; // 0..E
|
||||
rx_tx_addr[1] = (high<<4) + low;
|
||||
uint8_t addition = (20 * high)+ (2 * low) + 8;
|
||||
|
||||
uint8_t first_channel = pelikan_firstCh(high, low);
|
||||
first_channel = pelikan_adjust_value(first_channel, addition, PELIKAN_HOP_LIMIT);
|
||||
hopping_frequency[0] = first_channel;
|
||||
debug("%02X", first_channel);
|
||||
for (uint8_t i = 1; i < PELIKAN_NUM_RF_CHAN; i++)
|
||||
{
|
||||
hopping_frequency[i] = pelikan_add(hopping_frequency[i-1], addition, PELIKAN_HOP_LIMIT);
|
||||
debug(" %02X", hopping_frequency[i]);
|
||||
}
|
||||
debugln("");
|
||||
}
|
||||
|
||||
#ifdef PELIKAN_FORCE_ID
|
||||
const uint8_t PROGMEM pelikan_hopp[][PELIKAN_NUM_RF_CHAN] = {
|
||||
{ 0x5A,0x46,0x32,0x6E,0x6C,0x58,0x44,0x42,0x40,0x6A,0x56,0x54,0x52,0x3E,0x68,0x66,0x64,0x50,0x3C,0x3A,0x38,0x62,0x4E,0x4C,0x5E,0x4A,0x36,0x5C,0x34 }
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef PELIKAN_LITE_FORCE_HOP
|
||||
const uint8_t PROGMEM pelikan_lite_hopp[][PELIKAN_NUM_RF_CHAN] = {
|
||||
{ 0x46,0x2A,0x3E,0x5A,0x5C,0x24,0x4E,0x32,0x54,0x26,0x2C,0x34,0x56,0x1E,0x3A,0x3C,0x50,0x4A,0x2E,0x42,0x20,0x52,0x28,0x22,0x44,0x58,0x36,0x38,0x4C }
|
||||
};
|
||||
#endif
|
||||
|
||||
uint16_t initPelikan()
|
||||
{
|
||||
A7105_Init();
|
||||
if(IS_BIND_IN_PROGRESS || sub_protocol==PELIKAN_LITE)
|
||||
A7105_WriteReg(A7105_03_FIFOI,0x10);
|
||||
|
||||
pelikan_init_hop();
|
||||
|
||||
//ID from dump
|
||||
#if defined(PELIKAN_FORCE_ID)
|
||||
if(sub_protocol==PELIKAN_PRO)
|
||||
{
|
||||
rx_tx_addr[0]=0x0D; // hopping freq
|
||||
rx_tx_addr[1]=0xF4; // hopping freq
|
||||
rx_tx_addr[2]=0x50; // ID
|
||||
rx_tx_addr[3]=0x18; // ID
|
||||
// Fill frequency table
|
||||
for(uint8_t i=0;i<PELIKAN_NUM_RF_CHAN;i++)
|
||||
hopping_frequency[i]=pgm_read_byte_near(&pelikan_hopp[0][i]);
|
||||
}
|
||||
#endif
|
||||
#if defined(PELIKAN_LITE_FORCE_ID) || defined(PELIKAN_LITE_FORCE_HOP)
|
||||
if(sub_protocol==PELIKAN_LITE)
|
||||
{
|
||||
#if defined(PELIKAN_LITE_FORCE_ID)
|
||||
// ID
|
||||
rx_tx_addr[2]=0x60;
|
||||
rx_tx_addr[3]=0x18;
|
||||
#endif
|
||||
#if defined(PELIKAN_LITE_FORCE_HOP)
|
||||
// Hop frequency table
|
||||
rx_tx_addr[0]=0x04; // hopping freq
|
||||
rx_tx_addr[1]=0x63; // hopping freq
|
||||
for(uint8_t i=0;i<PELIKAN_NUM_RF_CHAN;i++)
|
||||
hopping_frequency[i]=pgm_read_byte_near(&pelikan_lite_hopp[0][i]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
MProtocol_id=((uint32_t)rx_tx_addr[0]<<24)|((uint32_t)rx_tx_addr[1]<<16)|((uint32_t)rx_tx_addr[2]<<8)|(rx_tx_addr[3]);
|
||||
if(sub_protocol==PELIKAN_LITE && IS_BIND_DONE)
|
||||
A7105_WriteID(MProtocol_id);
|
||||
|
||||
hopping_frequency_no=PELIKAN_NUM_RF_CHAN;
|
||||
packet_count=5;
|
||||
phase=0;
|
||||
return 2400;
|
||||
}
|
||||
#endif
|
||||
@@ -223,6 +223,8 @@
|
||||
#define S3_pin PA6
|
||||
#define S4_pin PA7
|
||||
//
|
||||
#define RND_pin PB0
|
||||
//
|
||||
#define PE1_pin PB4 //PE1
|
||||
#define PE2_pin PB5 //PE2
|
||||
//CS pins
|
||||
@@ -313,6 +315,20 @@
|
||||
#define DEBUG_PIN_toggle
|
||||
#endif
|
||||
|
||||
#ifdef MULTI_5IN1_INTERNAL
|
||||
#undef RND_pin
|
||||
#define SX1276_RST_pin PA2 //LED2 on other modules
|
||||
#define SX1276_TXEN_pin PB0 //Random gen on other modules
|
||||
#define SX1276_DIO0_pin PC13 //Unused on other modules
|
||||
|
||||
#define SX1276_RST_on digitalWrite(SX1276_RST_pin,HIGH)
|
||||
#define SX1276_RST_off digitalWrite(SX1276_RST_pin,LOW)
|
||||
#define SX1276_TXEN_on digitalWrite(SX1276_TXEN_pin,HIGH)
|
||||
#define SX1276_RXEN_on digitalWrite(SX1276_TXEN_pin,LOW)
|
||||
#define IS_DIO0_on ( digitalRead(SX1276_DIO0_pin)==HIGH )
|
||||
#define IS_DIO0_off ( digitalRead(SX1276_DIO0_pin)==LOW )
|
||||
#endif
|
||||
|
||||
#define cli() noInterrupts()
|
||||
#define sei() interrupts()
|
||||
#define delayMilliseconds(x) delay(x)
|
||||
|
||||
331
Multiprotocol/Propel_nrf24l01.ino
Normal file
331
Multiprotocol/Propel_nrf24l01.ino
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Compatible with PROPEL 74-Z Speeder Bike.
|
||||
|
||||
#if defined(PROPEL_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
//#define PROPEL_FORCE_ID
|
||||
|
||||
#define PROPEL_INITIAL_WAIT 500
|
||||
#define PROPEL_PACKET_PERIOD 10000
|
||||
#define PROPEL_BIND_RF_CHANNEL 0x23
|
||||
#define PROPEL_PAYLOAD_SIZE 16
|
||||
#define PROPEL_SEARCH_PERIOD 50 //*10ms
|
||||
#define PROPEL_BIND_PERIOD 1500
|
||||
#define PROPEL_PACKET_SIZE 14
|
||||
#define PROPEL_RF_NUM_CHANNELS 4
|
||||
#define PROPEL_ADDRESS_LENGTH 5
|
||||
#define PROPEL_DEFAULT_PERIOD 20
|
||||
|
||||
enum {
|
||||
PROPEL_BIND1 = 0,
|
||||
PROPEL_BIND2,
|
||||
PROPEL_BIND3,
|
||||
PROPEL_DATA1,
|
||||
};
|
||||
|
||||
static uint16_t __attribute__((unused)) PROPEL_checksum()
|
||||
{
|
||||
typedef union {
|
||||
struct {
|
||||
uint8_t h:1;
|
||||
uint8_t g:1;
|
||||
uint8_t f:1;
|
||||
uint8_t e:1;
|
||||
uint8_t d:1;
|
||||
uint8_t c:1;
|
||||
uint8_t b:1;
|
||||
uint8_t a:1;
|
||||
} bits;
|
||||
uint8_t byte:8;
|
||||
} byte_bits_t;
|
||||
|
||||
uint8_t sum = packet[0];
|
||||
for (uint8_t i = 1; i < PROPEL_PACKET_SIZE - 2; i++)
|
||||
sum += packet[i];
|
||||
|
||||
byte_bits_t in = { .byte = sum };
|
||||
byte_bits_t out = { .byte = sum };
|
||||
out.byte ^= 0x0a;
|
||||
out.bits.d = !(in.bits.d ^ in.bits.h);
|
||||
out.bits.c = (!in.bits.c && !in.bits.d && in.bits.g)
|
||||
|| (in.bits.c && !in.bits.d && !in.bits.g)
|
||||
|| (!in.bits.c && in.bits.g && !in.bits.h)
|
||||
|| (in.bits.c && !in.bits.g && !in.bits.h)
|
||||
|| (in.bits.c && in.bits.d && in.bits.g && in.bits.h)
|
||||
|| (!in.bits.c && in.bits.d && !in.bits.g && in.bits.h);
|
||||
out.bits.b = (!in.bits.b && !in.bits.c && !in.bits.d)
|
||||
|| (in.bits.b && in.bits.c && in.bits.g)
|
||||
|| (!in.bits.b && !in.bits.c && !in.bits.g)
|
||||
|| (!in.bits.b && !in.bits.d && !in.bits.g)
|
||||
|| (!in.bits.b && !in.bits.c && !in.bits.h)
|
||||
|| (!in.bits.b && !in.bits.g && !in.bits.h)
|
||||
|| (in.bits.b && in.bits.c && in.bits.d && in.bits.h)
|
||||
|| (in.bits.b && in.bits.d && in.bits.g && in.bits.h);
|
||||
out.bits.a = (in.bits.a && !in.bits.b)
|
||||
|| (in.bits.a && !in.bits.c && !in.bits.d)
|
||||
|| (in.bits.a && !in.bits.c && !in.bits.g)
|
||||
|| (in.bits.a && !in.bits.d && !in.bits.g)
|
||||
|| (in.bits.a && !in.bits.c && !in.bits.h)
|
||||
|| (in.bits.a && !in.bits.g && !in.bits.h)
|
||||
|| (!in.bits.a && in.bits.b && in.bits.c && in.bits.g)
|
||||
|| (!in.bits.a && in.bits.b && in.bits.c && in.bits.d && in.bits.h)
|
||||
|| (!in.bits.a && in.bits.b && in.bits.d && in.bits.g && in.bits.h);
|
||||
|
||||
return (sum << 8) | (out.byte & 0xff);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) PROPEL_bind_packet(bool valid_rx_id)
|
||||
{
|
||||
memset(packet, 0, PROPEL_PACKET_SIZE);
|
||||
|
||||
packet[0] = 0xD0;
|
||||
memcpy(&packet[1], rx_tx_addr, 4); // only 4 bytes sent of 5-byte address
|
||||
if (valid_rx_id) memcpy(&packet[5], rx_id, 4);
|
||||
packet[9] = rf_ch_num; // hopping table to be used when switching to normal mode
|
||||
packet[11] = 0x05; // unknown, 0x01 on TX2??
|
||||
|
||||
uint16_t check = PROPEL_checksum();
|
||||
packet[12] = check >> 8;
|
||||
packet[13] = check & 0xff;
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, (_BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT)));
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WritePayload(packet, PROPEL_PACKET_SIZE);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) PROPEL_data_packet()
|
||||
{
|
||||
memset(packet, 0, PROPEL_PACKET_SIZE);
|
||||
|
||||
packet[0] = 0xC0;
|
||||
packet[1] = convert_channel_16b_limit(THROTTLE, 0x2f, 0xcf);
|
||||
packet[2] = convert_channel_16b_limit(RUDDER , 0xcf, 0x2f);
|
||||
packet[3] = convert_channel_16b_limit(ELEVATOR, 0x2f, 0xcf);
|
||||
packet[4] = convert_channel_16b_limit(AILERON , 0xcf, 0x2f);
|
||||
packet[5] = 0x40; //might be trims but unsused
|
||||
packet[6] = 0x40; //might be trims but unsused
|
||||
packet[7] = 0x40; //might be trims but unsused
|
||||
packet[8] = 0x40; //might be trims but unsused
|
||||
if (bind_phase)
|
||||
{//need to send a couple of default packets after bind
|
||||
bind_phase--;
|
||||
packet[10] = 0x80; // LEDs
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[9] = 0x02 // Always fast speed, slow=0x00, medium=0x01, fast=0x02, 0x03=flight training mode
|
||||
| GET_FLAG( CH14_SW, 0x03) // Flight training mode
|
||||
| GET_FLAG( CH10_SW, 0x04) // Calibrate
|
||||
| GET_FLAG( CH12_SW, 0x08) // Take off
|
||||
| GET_FLAG( CH8_SW, 0x10) // Fire
|
||||
| GET_FLAG( CH11_SW, 0x20) // Altitude hold=0x20
|
||||
| GET_FLAG( CH6_SW, 0x40) // Roll CW
|
||||
| GET_FLAG( CH7_SW, 0x80); // Roll CCW
|
||||
packet[10] = GET_FLAG( CH13_SW, 0x20) // Land
|
||||
| GET_FLAG( CH9_SW, 0x40) // Weapon system activted=0x40
|
||||
| GET_FLAG(!CH5_SW, 0x80); // LEDs
|
||||
}
|
||||
packet[11] = 5; // unknown, 0x01 on TX2??
|
||||
|
||||
uint16_t check = PROPEL_checksum();
|
||||
packet[12] = check >> 8;
|
||||
packet[13] = check & 0xff;
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]);
|
||||
hopping_frequency_no &= 0x03;
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, (_BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT)));
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WritePayload(packet, PROPEL_PACKET_SIZE);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) PROPEL_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x7f);
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x3f); // AA on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3f); // Enable all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte address
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x36); // retransmit 1ms, 6 times
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x07); // ?? match protocol capture
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x99\x77\x55\x33\x11", PROPEL_ADDRESS_LENGTH); //Bind address
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x99\x77\x55\x33\x11", PROPEL_ADDRESS_LENGTH); //Bind address
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, PROPEL_BIND_RF_CHANNEL);
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // Enable dynamic payload length
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Enable all features
|
||||
// Beken 2425 register bank 1 initialized here in stock tx capture
|
||||
// Hopefully won't matter for nRF compatibility
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
}
|
||||
|
||||
const uint8_t PROGMEM PROPEL_hopping []= { 0x47,0x36,0x27,0x44,0x33,0x0D,0x3C,0x2E,0x1B,0x39,0x2A,0x18 };
|
||||
static void __attribute__((unused)) PROPEL_initialize_txid()
|
||||
{
|
||||
//address last byte
|
||||
rx_tx_addr[4]=0x11;
|
||||
|
||||
//random hopping channel table
|
||||
rf_ch_num=random(0xfefefefe)&0x03;
|
||||
for(uint8_t i=0; i<3; i++)
|
||||
hopping_frequency[i]=pgm_read_byte_near( &PROPEL_hopping[i + 3*rf_ch_num] );
|
||||
hopping_frequency[3]=0x23;
|
||||
|
||||
#ifdef PROPEL_FORCE_ID
|
||||
if(RX_num&1)
|
||||
memcpy(rx_tx_addr, (uint8_t *)"\x73\xd3\x31\x30\x11", PROPEL_ADDRESS_LENGTH); //TX1: 73 d3 31 30 11
|
||||
else
|
||||
memcpy(rx_tx_addr, (uint8_t *)"\x94\xc5\x31\x30\x11", PROPEL_ADDRESS_LENGTH); //TX2: 94 c5 31 30 11
|
||||
rf_ch_num = 0x03; //TX1
|
||||
memcpy(hopping_frequency,(uint8_t *)"\x39\x2A\x18\x23",PROPEL_RF_NUM_CHANNELS); //TX1: 57,42,24,35
|
||||
rf_ch_num = 0x00; //TX2
|
||||
memcpy(hopping_frequency,(uint8_t *)"\x47\x36\x27\x23",PROPEL_RF_NUM_CHANNELS); //TX2: 71,54,39,35
|
||||
rf_ch_num = 0x01; // Manual search
|
||||
memcpy(hopping_frequency,(uint8_t *)"\x44\x33\x0D\x23",PROPEL_RF_NUM_CHANNELS); //Manual: 68,51,13,35
|
||||
rf_ch_num = 0x02; // Manual search
|
||||
memcpy(hopping_frequency,(uint8_t *)"\x3C\x2E\x1B\x23",PROPEL_RF_NUM_CHANNELS); //Manual: 60,46,27,35
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t PROPEL_callback()
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
switch (phase)
|
||||
{
|
||||
case PROPEL_BIND1:
|
||||
PROPEL_bind_packet(false); //rx_id unknown
|
||||
phase++; //BIND2
|
||||
return PROPEL_BIND_PERIOD;
|
||||
|
||||
case PROPEL_BIND2:
|
||||
status=NRF24L01_ReadReg(NRF24L01_07_STATUS);
|
||||
if (status & _BV(NRF24L01_07_MAX_RT))
|
||||
{// Max retry (6) reached
|
||||
phase = PROPEL_BIND1;
|
||||
return PROPEL_BIND_PERIOD;
|
||||
}
|
||||
if (!(_BV(NRF24L01_07_RX_DR) & status))
|
||||
return PROPEL_BIND_PERIOD; // nothing received
|
||||
// received frame, got rx_id, save it
|
||||
NRF24L01_ReadPayload(packet_in, PROPEL_PACKET_SIZE);
|
||||
memcpy(rx_id, &packet_in[1], 4);
|
||||
PROPEL_bind_packet(true); //send bind packet with rx_id
|
||||
phase++; //BIND3
|
||||
break;
|
||||
|
||||
case PROPEL_BIND3:
|
||||
if (_BV(NRF24L01_07_RX_DR) & NRF24L01_ReadReg(NRF24L01_07_STATUS))
|
||||
{
|
||||
NRF24L01_ReadPayload(packet_in, PROPEL_PACKET_SIZE);
|
||||
if (packet_in[0] == 0xa3 && memcmp(&packet_in[1],rx_id,4)==0)
|
||||
{//confirmation from the model
|
||||
phase++; //PROPEL_DATA1
|
||||
bind_phase=PROPEL_DEFAULT_PERIOD;
|
||||
packet_count=0;
|
||||
BIND_DONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, PROPEL_ADDRESS_LENGTH);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, PROPEL_ADDRESS_LENGTH);
|
||||
PROPEL_bind_packet(true); //send bind packet with rx_id
|
||||
break;
|
||||
|
||||
case PROPEL_DATA1:
|
||||
#ifdef PROPEL_HUB_TELEMETRY
|
||||
if (_BV(NRF24L01_07_RX_DR) & NRF24L01_ReadReg(NRF24L01_07_STATUS))
|
||||
{// data received from the model
|
||||
NRF24L01_ReadPayload(packet_in, PROPEL_PACKET_SIZE);
|
||||
if (packet_in[0] == 0xa3 && memcmp(&packet_in[1],rx_id,3)==0)
|
||||
{
|
||||
telemetry_counter++; //LQI
|
||||
v_lipo1=packet[5]; //number of life left?
|
||||
v_lipo2=packet[4]; //bit mask: 0x80=flying, 0x08=taking off, 0x04=landing, 0x00=landed/crashed
|
||||
if(telemetry_lost==0)
|
||||
telemetry_link=1;
|
||||
}
|
||||
}
|
||||
packet_count++;
|
||||
if(packet_count>=100)
|
||||
{//LQI calculation
|
||||
packet_count=0;
|
||||
TX_LQI=telemetry_counter;
|
||||
RX_RSSI=telemetry_counter;
|
||||
telemetry_counter = 0;
|
||||
telemetry_lost=0;
|
||||
}
|
||||
#endif
|
||||
PROPEL_data_packet();
|
||||
break;
|
||||
}
|
||||
return PROPEL_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initPROPEL()
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
PROPEL_initialize_txid();
|
||||
PROPEL_init();
|
||||
hopping_frequency_no = 0;
|
||||
phase=PROPEL_BIND1;
|
||||
return PROPEL_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
// equations for checksum check byte from truth table
|
||||
// (1) z = a && !b
|
||||
// || a && !c && !d
|
||||
// || a && !c && !g
|
||||
// || a && !d && !g
|
||||
// || a && !c && !h
|
||||
// || a && !g && !h
|
||||
// || !a && b && c && g
|
||||
// || !a && b && c && d && h
|
||||
// || !a && b && d && g && h;
|
||||
//
|
||||
// (2) y = !b && !c && !d
|
||||
// || b && c && g
|
||||
// || !b && !c && !g
|
||||
// || !b && !d && !g
|
||||
// || !b && !c && !h
|
||||
// || !b && !g && !h
|
||||
// || b && c && d && h
|
||||
// || b && d && g && h;
|
||||
//
|
||||
// (3) x = !c && !d && g
|
||||
// || c && !d && !g
|
||||
// || !c && g && !h
|
||||
// || c && !g && !h
|
||||
// || c && d && g && h
|
||||
// || !c && d && !g && h;
|
||||
//
|
||||
// (4) w = d && h
|
||||
// || !d && !h;
|
||||
//
|
||||
// (5) v = !e;
|
||||
//
|
||||
// (6) u = f;
|
||||
//
|
||||
// (7) t = !g;
|
||||
//
|
||||
// (8) s = h;
|
||||
176
Multiprotocol/Q90C_nrf24l01.ino
Normal file
176
Multiprotocol/Q90C_nrf24l01.ino
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Compatible with Q90C quad.
|
||||
|
||||
#if defined(Q90C_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
//#define FORCE_Q90C_ORIGINAL_ID
|
||||
|
||||
#define Q90C_BIND_COUNT 250
|
||||
#define Q90C_PACKET_PERIOD 7336 // 6200 on saimat's TX...
|
||||
#define Q90C_INITIAL_WAIT 500
|
||||
#define Q90C_PACKET_SIZE 12
|
||||
#define Q90C_RF_BIND_CHANNEL 0x33
|
||||
#define Q90C_RF_NUM_CHANNELS 3
|
||||
#define Q90C_ADDRESS_LENGTH 5
|
||||
|
||||
bool Q90C_VTX;
|
||||
|
||||
int16_t Q90C_channel(uint8_t num, int16_t in_min,int16_t in_max, int16_t out_min,int16_t out_max)
|
||||
{
|
||||
int32_t val=Channel_data[num];
|
||||
if(val<in_min) val=in_min;
|
||||
else if(val>in_max) val=in_max;
|
||||
val=(val-in_min)*(out_max-out_min)/(in_max-in_min)+out_min;
|
||||
return (uint16_t)val;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) Q90C_send_packet()
|
||||
{
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
memcpy(packet, rx_tx_addr, 4);
|
||||
memcpy(&packet[4], hopping_frequency, 3);
|
||||
//packet[7] = 0x1e; // 2e on Saimat 1???
|
||||
packet[10] = 0x4B;
|
||||
packet[11] = 0x4E;
|
||||
}
|
||||
else
|
||||
{
|
||||
XN297L_Hopping(hopping_frequency_no++); // RF Freq
|
||||
hopping_frequency_no %= Q90C_RF_NUM_CHANNELS;
|
||||
packet[0]= convert_channel_8b(THROTTLE); // 0..255
|
||||
// A,E,R have weird scaling, 0x00-0xff range (unsigned) but center isn't 7f or 80
|
||||
// rudder ff-7a-00
|
||||
if (Channel_data[RUDDER] <= CHANNEL_MID)
|
||||
packet[1] = Q90C_channel(RUDDER, CHANNEL_MIN_100, CHANNEL_MID, 0xff, 0x7a );
|
||||
else
|
||||
packet[1] = Q90C_channel(RUDDER, CHANNEL_MID, CHANNEL_MAX_100, 0x7a, 0x00 );
|
||||
// elevator 00-88-ff
|
||||
if (Channel_data[ELEVATOR] <= CHANNEL_MID)
|
||||
packet[2] = Q90C_channel(ELEVATOR, CHANNEL_MIN_100, CHANNEL_MID, 0x00, 0x88);
|
||||
else
|
||||
packet[2] = Q90C_channel(ELEVATOR, CHANNEL_MID, CHANNEL_MAX_100, 0x88, 0xff);
|
||||
// aileron ff-88-00
|
||||
if (Channel_data[AILERON] <= CHANNEL_MID)
|
||||
packet[3] = Q90C_channel(AILERON, CHANNEL_MIN_100, CHANNEL_MID, 0xff, 0x88);
|
||||
else
|
||||
packet[3] = Q90C_channel(AILERON, CHANNEL_MID, CHANNEL_MAX_100, 0x88, 0x00);
|
||||
// required to "arm" (low throttle + aileron to the right)
|
||||
if (packet[0] < 5 && packet[3] < 25) {
|
||||
packet[1] = 0x7a;
|
||||
packet[2] = 0x88;
|
||||
}
|
||||
packet[4] = 0x1e; // T trim 00-1e-3c
|
||||
packet[5] = 0x1e; // R trim 3c-1e-00
|
||||
packet[6] = 0x1e; // E trim 00-1e-3c
|
||||
//packet[7] = 0x1e; // A trim 00-1e-3c
|
||||
packet[8] |= 0x02; // Rudder rate 0=min,1,2=max
|
||||
if(state!=Channel_data[CH5])
|
||||
{
|
||||
state=Channel_data[CH5];
|
||||
if(state<CHANNEL_MIN_COMMAND)
|
||||
packet[8] ^= 0x04; // Angle
|
||||
else if(state>CHANNEL_MAX_COMMAND)
|
||||
packet[8] ^= 0x10; // Acro
|
||||
else
|
||||
packet[8] ^= 0x08; // Horizon
|
||||
}
|
||||
if(!Q90C_VTX && CH6_SW)
|
||||
packet[8] ^= 0x20; // VTX+
|
||||
Q90C_VTX=CH6_SW;
|
||||
|
||||
debugln("8=%02X",packet[8]);
|
||||
packet[10] = packet_count++;
|
||||
}
|
||||
packet[7] = 0x1e; // bind 1e or 2e, normal: A trim 00-1e-3c
|
||||
|
||||
// checksum
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
uint8_t sum=0;
|
||||
for (uint8_t i = 0; i < Q90C_PACKET_SIZE - 1; i++)
|
||||
sum += packet[i];
|
||||
packet[11] = sum ^ crc8;
|
||||
}
|
||||
|
||||
XN297L_SetFreqOffset(); // Set frequency offset
|
||||
XN297L_SetPower(); // Set tx_power
|
||||
XN297L_WriteEnhancedPayload(packet, Q90C_PACKET_SIZE, 0);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) Q90C_initialize_txid()
|
||||
{
|
||||
calc_fh_channels(Q90C_RF_NUM_CHANNELS);
|
||||
rx_tx_addr[4]=0x4B;
|
||||
#ifdef FORCE_Q90C_ORIGINAL_ID
|
||||
//24 03 01 82 18 26 37 1E 00 00 4B 4E
|
||||
memcpy(rx_tx_addr, (uint8_t*)"\x24\x03\x01\x82\x4B", Q90C_ADDRESS_LENGTH); //Goebish
|
||||
memcpy(hopping_frequency, (uint8_t*)"\x18\x26\x37", Q90C_RF_NUM_CHANNELS);
|
||||
//4C 0A 02 01 17 24 36 2E 00 00 4B 4E
|
||||
memcpy(rx_tx_addr, (uint8_t*)"\x4C\x0A\x02\x01\x4B", Q90C_ADDRESS_LENGTH); //Saimat 1
|
||||
memcpy(hopping_frequency, (uint8_t*)"\x17\x24\x36", Q90C_RF_NUM_CHANNELS);
|
||||
//34 13 02 01 18 26 37 1E 00 00 4B 4E
|
||||
memcpy(rx_tx_addr, (uint8_t*)"\x34\x13\x02\x01\x4B", Q90C_ADDRESS_LENGTH); //Saimat 2
|
||||
memcpy(hopping_frequency, (uint8_t*)"\x18\x26\x37", Q90C_RF_NUM_CHANNELS);
|
||||
#endif
|
||||
crc8=rx_tx_addr[0]^rx_tx_addr[1]^rx_tx_addr[2]^rx_tx_addr[3];
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) Q90C_init()
|
||||
{
|
||||
XN297L_Init();
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
XN297L_SetTXAddr((uint8_t*)"\x4F\x43\x54\x81\x81", Q90C_ADDRESS_LENGTH);
|
||||
else
|
||||
XN297L_SetTXAddr(rx_tx_addr, Q90C_ADDRESS_LENGTH);
|
||||
XN297L_HoppingCalib(Q90C_RF_NUM_CHANNELS); // Calibrate all channels
|
||||
XN297L_RFChannel(Q90C_RF_BIND_CHANNEL); // Set bind channel
|
||||
}
|
||||
|
||||
uint16_t Q90C_callback()
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(Q90C_PACKET_PERIOD);
|
||||
#endif
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
if(--bind_counter==0)
|
||||
{
|
||||
BIND_DONE;
|
||||
XN297L_SetTXAddr(rx_tx_addr, Q90C_ADDRESS_LENGTH);
|
||||
}
|
||||
Q90C_send_packet();
|
||||
return Q90C_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initQ90C()
|
||||
{
|
||||
Q90C_initialize_txid();
|
||||
Q90C_init();
|
||||
hopping_frequency_no = 0;
|
||||
packet_count = 0;
|
||||
bind_counter=Q90C_BIND_COUNT;
|
||||
|
||||
//features
|
||||
state=Channel_data[CH5];
|
||||
Q90C_VTX=CH6_SW;
|
||||
packet[8] = 0x00;
|
||||
packet[9] = 0x00;
|
||||
return Q90C_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
157
Multiprotocol/REALACC_nrf24l01.ino
Normal file
157
Multiprotocol/REALACC_nrf24l01.ino
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Compatible with Realacc R11
|
||||
|
||||
#if defined(REALACC_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#define FORCE_REALACC_ORIGINAL_ID
|
||||
|
||||
#define REALACC_INITIAL_WAIT 500
|
||||
#define REALACC_PACKET_PERIOD 2268
|
||||
#define REALACC_BIND_RF_CHANNEL 80
|
||||
#define REALACC_BIND_PAYLOAD_SIZE 10
|
||||
#define REALACC_PAYLOAD_SIZE 13
|
||||
#define REALACC_BIND_COUNT 50
|
||||
#define REALACC_RF_NUM_CHANNELS 5
|
||||
|
||||
static void __attribute__((unused)) REALACC_send_packet()
|
||||
{
|
||||
packet[ 0]= 0xDC;
|
||||
packet[ 1]= convert_channel_8b(AILERON); // 00..80..FF
|
||||
packet[ 2]= convert_channel_8b(ELEVATOR); // 00..80..FF
|
||||
packet[ 3]= convert_channel_8b(THROTTLE); // 00..FF
|
||||
packet[ 4]= convert_channel_8b(RUDDER); // 00..80..FF
|
||||
packet[ 5]= 0x20; // Trim
|
||||
packet[ 6]= 0x20; // Trim
|
||||
packet[ 7]= 0x20; // Trim
|
||||
packet[ 8]= 0x20; // Trim
|
||||
packet[ 9]= num_ch; // Change at each power up
|
||||
packet[10]= 0x04 // Flag1
|
||||
| 0x02 // Rate1=0, Rate2=1, Rate3=2
|
||||
| GET_FLAG(CH8_SW, 0x20); // Headless
|
||||
packet[11]= 0x00 // Flag2
|
||||
| GET_FLAG(CH7_SW, 0x01) // Calib
|
||||
| GET_FLAG(CH9_SW, 0x20) // Return
|
||||
| GET_FLAG(CH10_SW,0x80); // Unknown
|
||||
packet[12]= 0x00 // Flag3
|
||||
| GET_FLAG(CH5_SW, 0x01) // Flip
|
||||
| GET_FLAG(CH6_SW, 0x80); // Light
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency_no);
|
||||
hopping_frequency_no++;
|
||||
hopping_frequency_no %= REALACC_RF_NUM_CHANNELS;
|
||||
XN297_WriteEnhancedPayload(packet, REALACC_PAYLOAD_SIZE,0);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) REALACC_send_bind_packet()
|
||||
{
|
||||
packet[0] = 0xB1;
|
||||
memcpy(&packet[1],rx_tx_addr,4);
|
||||
memcpy(&packet[5],hopping_frequency,5);
|
||||
|
||||
XN297_WriteEnhancedPayload(packet, REALACC_BIND_PAYLOAD_SIZE,1);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) REALACC_initialize_txid()
|
||||
{
|
||||
calc_fh_channels(REALACC_RF_NUM_CHANNELS);
|
||||
num_ch=random(0xfefefefe); // 00..FF
|
||||
|
||||
#ifdef FORCE_REALACC_ORIGINAL_ID
|
||||
//Dump
|
||||
rx_tx_addr[0]=0x99;
|
||||
rx_tx_addr[1]=0x06;
|
||||
rx_tx_addr[2]=0x00;
|
||||
rx_tx_addr[3]=0x00;
|
||||
hopping_frequency[0]=0x55;
|
||||
hopping_frequency[1]=0x59;
|
||||
hopping_frequency[2]=0x5A;
|
||||
hopping_frequency[3]=0x5A;
|
||||
hopping_frequency[4]=0x62;
|
||||
num_ch=0xC5; // Value in dumps: C5 A2 77 F0 84 58
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) REALACC_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
XN297_SetTXAddr((uint8_t*)"MAIN", 4);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, REALACC_BIND_RF_CHANNEL); // Set bind channel
|
||||
}
|
||||
|
||||
uint16_t REALACC_callback()
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(REALACC_PACKET_PERIOD);
|
||||
#endif
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_SetPower();
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
REALACC_send_bind_packet();
|
||||
if(--bind_counter==0)
|
||||
{
|
||||
BIND_DONE;
|
||||
XN297_SetTXAddr(rx_tx_addr, 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
REALACC_send_packet();
|
||||
return REALACC_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initREALACC()
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
REALACC_initialize_txid();
|
||||
REALACC_init();
|
||||
bind_counter=REALACC_BIND_COUNT;
|
||||
hopping_frequency_no=0;
|
||||
return REALACC_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// XN297 speed 1Mb, scrambled, enhanced
|
||||
// Bind
|
||||
// Address = 4D 41 49 4E = 'MAIN'
|
||||
// Channel = 80 (most likely from dump)
|
||||
// P(10) = B1 99 06 00 00 55 59 5A 5A 62
|
||||
// B1 indicates bind packet
|
||||
// 99 06 00 00 = ID = address of normal packets
|
||||
// 55 59 5A 5A 62 = 85, 89, 90, 90, 98 = RF channels to be used (kind of match previous dumps)// Normal
|
||||
// Normal
|
||||
// Address = 99 06 00 00
|
||||
// Channels = 84, 89, 90, 90, 98 (guess from bind)
|
||||
// P(13)= DC 80 80 32 80 20 20 20 20 58 04 00 00
|
||||
// DC = normal packet
|
||||
// 80 80 32 80 : AETR 00..80..FF
|
||||
// 20 20 20 20 : Trims
|
||||
// 58 : changing every time the TX restart
|
||||
// 04 : |0x20=headless, |0x01=rate2, |0x02=rate3
|
||||
// 00 : |0x01=calib, |0x20=return, |0x80=unknown
|
||||
// 00 : |0x80=light, |0x01=flip
|
||||
307
Multiprotocol/RadioLink_cc2500.ino
Normal file
307
Multiprotocol/RadioLink_cc2500.ino
Normal file
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Radiolink surface protocol. TXs: RC4GS,RC6GS. Compatible RXs:R7FG(Std),R6FG,R6F,R8EF,R8FM,R8F,R4FGM
|
||||
|
||||
#if defined(RLINK_CC2500_INO)
|
||||
|
||||
#include "iface_cc2500.h"
|
||||
|
||||
//#define RLINK_FORCE_ID
|
||||
|
||||
#define RLINK_TX_PACKET_LEN 33
|
||||
#define RLINK_RX_PACKET_LEN 15
|
||||
#define RLINK_TX_ID_LEN 4
|
||||
#define RLINK_HOP 16
|
||||
|
||||
enum {
|
||||
RLINK_DATA = 0x00,
|
||||
RLINK_RX1 = 0x01,
|
||||
RLINK_RX2 = 0x02,
|
||||
};
|
||||
|
||||
uint32_t RLINK_rand1;
|
||||
uint32_t RLINK_rand2;
|
||||
|
||||
static uint32_t __attribute__((unused)) RLINK_prng_next(uint32_t r)
|
||||
{
|
||||
return 0xA5E2A705 * r + 0x754DB79B;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) RLINK_init_random(uint32_t id)
|
||||
{
|
||||
uint32_t result = id;
|
||||
|
||||
RLINK_rand2 = result;
|
||||
for (uint8_t i=0; i<31; i++)
|
||||
result = RLINK_prng_next(result);
|
||||
RLINK_rand1 = result;
|
||||
}
|
||||
|
||||
static uint8_t __attribute__((unused)) RLINK_next_random_swap()
|
||||
{
|
||||
uint8_t result = (RLINK_rand2 >> 16) + RLINK_rand2 + (RLINK_rand1 >> 16) + RLINK_rand1;
|
||||
|
||||
RLINK_rand2 = RLINK_prng_next(RLINK_rand2);
|
||||
RLINK_rand1 = RLINK_prng_next(RLINK_rand1);
|
||||
|
||||
return result & 0x0F;
|
||||
}
|
||||
|
||||
static uint32_t __attribute__((unused)) RLINK_compute_start_id(uint32_t id)
|
||||
{
|
||||
return id * 0xF65EF9F9u + 0x2EDDF6CAu;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) RLINK_shuffle_freqs(uint32_t seed)
|
||||
{
|
||||
RLINK_init_random(seed);
|
||||
|
||||
for(uint8_t i=0; i<RLINK_HOP; i++)
|
||||
{
|
||||
uint8_t r = RLINK_next_random_swap();
|
||||
uint8_t tmp = hopping_frequency[r];
|
||||
hopping_frequency[r] = hopping_frequency[i];
|
||||
hopping_frequency[i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) RLINK_hop()
|
||||
{
|
||||
uint8_t inc=3*(rx_tx_addr[0]&3);
|
||||
|
||||
// init hop table
|
||||
for(uint8_t i=0; i<RLINK_HOP; i++)
|
||||
hopping_frequency[i] = (12*i) + inc;
|
||||
|
||||
// shuffle
|
||||
RLINK_shuffle_freqs(RLINK_compute_start_id(rx_tx_addr[0] + (rx_tx_addr[1] << 8)));
|
||||
RLINK_shuffle_freqs(RLINK_compute_start_id(rx_tx_addr[2] + (rx_tx_addr[3] << 8)));
|
||||
|
||||
// replace one of the channel randomely
|
||||
rf_ch_num=random(0xfefefefe)%0x11; // 0x00..0x10
|
||||
if(inc==9) inc=6; // frequency exception
|
||||
hopping_frequency[rf_ch_num]=12*16+inc;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) RLINK_init()
|
||||
{
|
||||
#ifdef RLINK_FORCE_ID
|
||||
//surface RC6GS
|
||||
memcpy(rx_tx_addr,"\x3A\x99\x22\x3A",RLINK_TX_ID_LEN);
|
||||
//air T8FB
|
||||
//memcpy(rx_tx_addr,"\xFC\x11\x0D\x20",RLINK_TX_ID_LEN);
|
||||
#endif
|
||||
// channels order depend on ID
|
||||
RLINK_hop();
|
||||
|
||||
#if 0
|
||||
debug("ID:");
|
||||
for(uint8_t i=0;i<RLINK_TX_ID_LEN;i++)
|
||||
debug(" 0x%02X",rx_tx_addr[i]);
|
||||
debugln("");
|
||||
debug("Hop(%d):", rf_ch_num);
|
||||
for(uint8_t i=0;i<RLINK_HOP;i++)
|
||||
debug(" 0x%02X",hopping_frequency[i]);
|
||||
debugln("");
|
||||
#endif
|
||||
}
|
||||
|
||||
const PROGMEM uint8_t RLINK_init_values[] = {
|
||||
/* 00 */ 0x5B, 0x06, 0x5C, 0x07, 0xAB, 0xCD, 0x40, 0x04,
|
||||
/* 08 */ 0x45, 0x00, 0x00, 0x06, 0x00, 0x5C, 0x62, 0x76,
|
||||
/* 10 */ 0x7A, 0x7F, 0x13, 0x23, 0xF8, 0x44, 0x07, 0x30,
|
||||
/* 18 */ 0x18, 0x16, 0x6C, 0x43, 0x40, 0x91, 0x87, 0x6B,
|
||||
/* 20 */ 0xF8, 0x56, 0x10, 0xA9, 0x0A, 0x00, 0x11
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) RLINK_rf_init()
|
||||
{
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
|
||||
for (uint8_t i = 0; i < 39; ++i)
|
||||
CC2500_WriteReg(i, pgm_read_byte_near(&RLINK_init_values[i]));
|
||||
|
||||
prev_option = option;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) RLINK_tune_freq()
|
||||
{
|
||||
if ( prev_option != option )
|
||||
{
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
prev_option = option ;
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) RLINK_send_packet()
|
||||
{
|
||||
static uint32_t pseudo=0;
|
||||
uint32_t bits = 0;
|
||||
uint8_t bitsavailable = 0;
|
||||
uint8_t idx = 6;
|
||||
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
|
||||
// packet length
|
||||
packet[0] = RLINK_TX_PACKET_LEN;
|
||||
// header
|
||||
if(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
|
||||
|
||||
// ID
|
||||
memcpy(&packet[2],rx_tx_addr,RLINK_TX_ID_LEN);
|
||||
|
||||
// pack 16 channels on 11 bits values between 170 and 1876, 1023 middle. The last 8 channels are failsafe values associated to the first 8 values.
|
||||
for (uint8_t i = 0; i < 16; i++)
|
||||
{
|
||||
uint32_t val = convert_channel_16b_nolimit(i,170,1876); // allow extended limits
|
||||
if (val & 0x8000)
|
||||
val = 0;
|
||||
else if (val > 2047)
|
||||
val=2047;
|
||||
|
||||
bits |= val << bitsavailable;
|
||||
bitsavailable += 11;
|
||||
while (bitsavailable >= 8) {
|
||||
packet[idx++] = bits & 0xff;
|
||||
bits >>= 8;
|
||||
bitsavailable -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
// hop
|
||||
pseudo=((pseudo * 0xAA) + 0x03) % 0x7673; // calc next pseudo random value
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[pseudo & 0x0F]);
|
||||
packet[28]= pseudo;
|
||||
packet[29]= pseudo >> 8;
|
||||
packet[30]= 0x00; // unknown
|
||||
packet[31]= 0x00; // unknown
|
||||
packet[32]= rf_ch_num; // index of value changed in the RF table
|
||||
|
||||
// check
|
||||
uint8_t sum=0;
|
||||
for(uint8_t i=1;i<33;i++)
|
||||
sum+=packet[i];
|
||||
packet[33]=sum;
|
||||
|
||||
// send packet
|
||||
CC2500_WriteData(packet, RLINK_TX_PACKET_LEN+1);
|
||||
|
||||
// packets type
|
||||
packet_count++;
|
||||
if(packet_count>5) packet_count=0;
|
||||
|
||||
//debugln("C= 0x%02X",hopping_frequency[pseudo & 0x0F]);
|
||||
//debug("P=");
|
||||
//for(uint8_t i=1;i<RLINK_TX_PACKET_LEN+1;i++)
|
||||
// debug(" 0x%02X",packet[i]);
|
||||
//debugln("");
|
||||
}
|
||||
|
||||
#define RLINK_TIMING_PROTO 20000-100 // -100 for compatibility with R8EF
|
||||
#define RLINK_TIMING_RFSEND 10500
|
||||
#define RLINK_TIMING_CHECK 2000
|
||||
uint16_t RLINK_callback()
|
||||
{
|
||||
switch(phase)
|
||||
{
|
||||
case RLINK_DATA:
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(RLINK_TIMING_PROTO);
|
||||
#endif
|
||||
CC2500_SetPower();
|
||||
RLINK_tune_freq();
|
||||
RLINK_send_packet();
|
||||
#if not defined RLINK_HUB_TELEMETRY
|
||||
return RLINK_TIMING_PROTO;
|
||||
#else
|
||||
if(!(packet[1]&0x02))
|
||||
return RLINK_TIMING_PROTO; //Normal packet
|
||||
//Telemetry packet
|
||||
phase++; // RX1
|
||||
return RLINK_TIMING_RFSEND;
|
||||
case RLINK_RX1:
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_Strobe(CC2500_SFRX);
|
||||
CC2500_SetTxRxMode(RX_EN);
|
||||
CC2500_Strobe(CC2500_SRX);
|
||||
phase++; // RX2
|
||||
return RLINK_TIMING_PROTO-RLINK_TIMING_RFSEND-RLINK_TIMING_CHECK;
|
||||
case RLINK_RX2:
|
||||
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||
if (len == RLINK_RX_PACKET_LEN + 1 + 2) //Telemetry frame is 15 bytes + 1 byte for length + 2 bytes for RSSI&LQI&CRC
|
||||
{
|
||||
//debug("Telem:");
|
||||
CC2500_ReadData(packet_in, len);
|
||||
if(packet_in[0]==RLINK_RX_PACKET_LEN && (packet_in[len-1] & 0x80) && memcmp(&packet[2],rx_tx_addr,RLINK_TX_ID_LEN)==0 && packet_in[6]==packet[1])
|
||||
{//Correct telemetry received: length, CRC, ID and type
|
||||
//Debug
|
||||
//for(uint8_t i=0;i<len;i++)
|
||||
// debug(" %02X",packet_in[i]);
|
||||
TX_RSSI = packet_in[len-2];
|
||||
if(TX_RSSI >=128)
|
||||
TX_RSSI -= 128;
|
||||
else
|
||||
TX_RSSI += 128;
|
||||
RX_RSSI=packet_in[7]; //Should be packet_in[7]-256 but since it's an uint8_t...
|
||||
v_lipo1=packet_in[8]<<1; //RX Batt
|
||||
v_lipo2=packet_in[9]; //Batt
|
||||
telemetry_link=1; //Send telemetry out
|
||||
pps_counter++;
|
||||
packet_count=0;
|
||||
}
|
||||
//debugln("");
|
||||
}
|
||||
if (millis() - pps_timer >= 2000)
|
||||
{//1 telemetry packet every 100ms
|
||||
pps_timer = millis();
|
||||
if(pps_counter<20)
|
||||
pps_counter*=5;
|
||||
else
|
||||
pps_counter=100;
|
||||
debugln("%d pps", pps_counter);
|
||||
TX_LQI = pps_counter; //0..100%
|
||||
pps_counter = 0;
|
||||
}
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
phase=RLINK_DATA; // DATA
|
||||
return RLINK_TIMING_CHECK;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t initRLINK()
|
||||
{
|
||||
BIND_DONE; // Not a TX bind protocol
|
||||
RLINK_init();
|
||||
RLINK_rf_init();
|
||||
packet_count = 0;
|
||||
phase = RLINK_DATA;
|
||||
return 10000;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -17,10 +17,10 @@
|
||||
|
||||
#include "iface_cc2500.h"
|
||||
|
||||
#define REDPINE_LOOPTIME_FAST 25 //2.5ms
|
||||
#define REDPINE_LOOPTIME_SLOW 6 //6ms
|
||||
#define REDPINE_LOOPTIME_FAST 20 //2.0ms
|
||||
#define REDPINE_LOOPTIME_SLOW 20 //20ms
|
||||
|
||||
#define REDPINE_BIND 1000
|
||||
#define REDPINE_BIND 2000
|
||||
#define REDPINE_PACKET_SIZE 11
|
||||
#define REDPINE_FEC false // from cc2500 datasheet: The convolutional coder is a rate 1/2 code with a constraint length of m=4
|
||||
#define REDPINE_NUM_HOPS 50
|
||||
@@ -105,10 +105,9 @@ static uint16_t ReadREDPINE()
|
||||
}
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
if(bind_counter == REDPINE_BIND)
|
||||
if (state == REDPINE_BIND) {
|
||||
REDPINE_init(0);
|
||||
if(bind_counter == REDPINE_BIND/2)
|
||||
REDPINE_init(1);
|
||||
}
|
||||
REDPINE_set_channel(49);
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
CC2500_SetPower();
|
||||
@@ -121,7 +120,7 @@ static uint16_t ReadREDPINE()
|
||||
BIND_DONE;
|
||||
REDPINE_init(sub_protocol);
|
||||
}
|
||||
return 9000;
|
||||
return 4000;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -149,23 +148,19 @@ static const uint8_t REDPINE_init_data[][3] = {
|
||||
{CC2500_07_PKTCTRL1, 0x04, 0x04},
|
||||
{CC2500_08_PKTCTRL0, 0x05, 0x05},
|
||||
{CC2500_09_ADDR, 0x00, 0x00},
|
||||
{CC2500_0B_FSCTRL1, 0x0A, 0x0A},
|
||||
{CC2500_0B_FSCTRL1, 0x0A, 0x06},
|
||||
{CC2500_0C_FSCTRL0, 0x00, 0x00},
|
||||
{CC2500_0D_FREQ2, 0x5D, 0x5c},
|
||||
{CC2500_0E_FREQ1, 0x93, 0x76},
|
||||
{CC2500_0F_FREQ0, 0xB1, 0x27},
|
||||
{CC2500_10_MDMCFG4, 0x2D, 0x7B},
|
||||
{CC2500_11_MDMCFG3, 0x3B, 0x61},
|
||||
{CC2500_12_MDMCFG2, 0x73, 0x13},
|
||||
#ifdef REDPINE_FEC
|
||||
{CC2500_13_MDMCFG1, 0xA3, 0xA3},
|
||||
#else
|
||||
{CC2500_13_MDMCFG1, 0x23, 0x23},
|
||||
#endif
|
||||
{CC2500_14_MDMCFG0, 0x56, 0x7a}, // Chan space
|
||||
{CC2500_15_DEVIATN, 0x00, 0x51},
|
||||
{CC2500_0D_FREQ2, 0x5D, 0x5D},
|
||||
{CC2500_0E_FREQ1, 0x93, 0x93},
|
||||
{CC2500_0F_FREQ0, 0xB1, 0xB1},
|
||||
{CC2500_10_MDMCFG4, 0x2D, 0x78},
|
||||
{CC2500_11_MDMCFG3, 0x3B, 0x93},
|
||||
{CC2500_12_MDMCFG2, 0x73, 0x03},
|
||||
{CC2500_13_MDMCFG1, 0x23, 0x22},
|
||||
{CC2500_14_MDMCFG0, 0x56, 0xF8}, // Chan space
|
||||
{CC2500_15_DEVIATN, 0x00, 0x44},
|
||||
{CC2500_17_MCSM1, 0x0c, 0x0c},
|
||||
{CC2500_18_MCSM0, 0x08, 0x08}, //??? 0x18, 0x18},
|
||||
{CC2500_18_MCSM0, 0x18, 0x18},
|
||||
{CC2500_19_FOCCFG, 0x1D, 0x16},
|
||||
{CC2500_1A_BSCFG, 0x1C, 0x6c},
|
||||
{CC2500_1B_AGCCTRL2, 0xC7, 0x43},
|
||||
@@ -190,8 +185,9 @@ static void REDPINE_init(uint8_t format)
|
||||
|
||||
CC2500_WriteReg(CC2500_06_PKTLEN, REDPINE_PACKET_SIZE);
|
||||
|
||||
for (uint8_t i=0; i < ((sizeof REDPINE_init_data) / (sizeof REDPINE_init_data[0])); i++)
|
||||
for (uint8_t i=0; i < ((sizeof(REDPINE_init_data)) / (sizeof(REDPINE_init_data[0]))); i++) {
|
||||
CC2500_WriteReg(REDPINE_init_data[i][0], REDPINE_init_data[i][format+1]);
|
||||
}
|
||||
|
||||
prev_option = option;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
@@ -215,7 +211,6 @@ static uint16_t initREDPINE()
|
||||
uint32_t idx = 0;
|
||||
uint32_t rnd = MProtocol_id;
|
||||
#define REDPINE_MAX_RF_CHANNEL 255
|
||||
hopping_frequency[idx++] = 1;
|
||||
while (idx < REDPINE_NUM_HOPS-1)
|
||||
{
|
||||
uint32_t i;
|
||||
@@ -226,8 +221,9 @@ static uint16_t initREDPINE()
|
||||
for (i = 0; i < idx; i++)
|
||||
{
|
||||
uint8_t ch = hopping_frequency[i];
|
||||
if ((ch <= next_ch + 1) && (ch >= next_ch - 1) && (ch > 1))
|
||||
if ((ch <= next_ch + 1) && (ch >= next_ch - 1) && (ch >= 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != idx)
|
||||
continue;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#if defined(SLT_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
//#define SLT_Q200_FORCE_ID
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#define SLT_PAYLOADSIZE_V2 11
|
||||
#define SLT_NFREQCHANNELS 15
|
||||
#define SLT_TXID_SIZE 4
|
||||
#define SLT_BIND_CHANNEL 0x50
|
||||
|
||||
enum{
|
||||
// flags going to packet[6] (Q200)
|
||||
@@ -48,30 +49,13 @@ enum {
|
||||
SLT_DATA2,
|
||||
SLT_DATA3,
|
||||
SLT_BIND1,
|
||||
SLT_BIND2
|
||||
SLT_BIND2,
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) SLT_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO)); // 2-bytes CRC, radio off
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x02); // 4-byte RX/TX address
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // Disable auto retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 4); // bytes of data payload for pipe 1
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 256kbps
|
||||
NRF24L01_SetPower();
|
||||
if(sub_protocol==SLT_V1)
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\xC3\xC3\xAA\x55", SLT_TXID_SIZE);
|
||||
else // V2
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, SLT_TXID_SIZE);
|
||||
NRF24L01_FlushTx();
|
||||
// Turn radio power on
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF250K_Init();
|
||||
NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_set_freq(void)
|
||||
@@ -109,21 +93,25 @@ static void __attribute__((unused)) SLT_set_freq(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Bind channel
|
||||
hopping_frequency[SLT_NFREQCHANNELS]=SLT_BIND_CHANNEL;
|
||||
|
||||
//Calib all channels
|
||||
NRF250K_HoppingCalib(SLT_NFREQCHANNELS+1);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_wait_radio()
|
||||
{
|
||||
if (packet_sent)
|
||||
while (!(NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)));
|
||||
while (!NRF250K_IsPacketSent());
|
||||
packet_sent = 0;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_send_packet(uint8_t len)
|
||||
{
|
||||
SLT_wait_radio();
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_MAX_RT));
|
||||
NRF24L01_WritePayload(packet, len);
|
||||
NRF250K_WritePayload(packet, len);
|
||||
packet_sent = 1;
|
||||
}
|
||||
|
||||
@@ -132,7 +120,8 @@ static void __attribute__((unused)) SLT_build_packet()
|
||||
static uint8_t calib_counter=0;
|
||||
|
||||
// Set radio channel - once per packet batch
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
|
||||
NRF250K_SetFreqOffset(); // Set frequency offset
|
||||
NRF250K_Hopping(hopping_frequency_no);
|
||||
if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
|
||||
hopping_frequency_no = 0;
|
||||
|
||||
@@ -183,23 +172,16 @@ static void __attribute__((unused)) SLT_build_packet()
|
||||
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
|
||||
NRF24L01_SetPower();
|
||||
NRF250K_SetPower();
|
||||
BIND_DONE;
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x50);
|
||||
NRF250K_SetTXAddr((uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
|
||||
memcpy((void*)packet,(void*)rx_tx_addr,SLT_TXID_SIZE);
|
||||
if(phase==SLT_BIND2)
|
||||
SLT_send_packet(SLT_TXID_SIZE);
|
||||
else // SLT_BIND1
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V2);
|
||||
|
||||
SLT_wait_radio(); //Wait until the packet's sent before changing TX address!
|
||||
|
||||
NRF24L01_SetPower(); //Change power back to normal level
|
||||
if(phase==SLT_BIND2) // after V1 bind and V2 second bind packet
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, SLT_TXID_SIZE);
|
||||
}
|
||||
|
||||
#define SLT_TIMING_BUILD 1000
|
||||
@@ -217,6 +199,8 @@ uint16_t SLT_callback()
|
||||
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:
|
||||
@@ -253,7 +237,6 @@ uint16_t SLT_callback()
|
||||
}
|
||||
else
|
||||
{// Continue to send normal packets
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
phase = SLT_BUILD;
|
||||
if(sub_protocol==SLT_V1)
|
||||
return 20000-SLT_TIMING_BUILD;
|
||||
@@ -289,8 +272,8 @@ uint16_t initSLT()
|
||||
/* rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x0B;rx_tx_addr[3]=0x57;*/
|
||||
#endif
|
||||
}
|
||||
SLT_set_freq();
|
||||
SLT_init();
|
||||
SLT_set_freq();
|
||||
phase = SLT_BUILD;
|
||||
return 50000;
|
||||
}
|
||||
|
||||
246
Multiprotocol/SX1276_SPI.ino
Normal file
246
Multiprotocol/SX1276_SPI.ino
Normal file
@@ -0,0 +1,246 @@
|
||||
#ifdef SX1276_INSTALLED
|
||||
#include "iface_sx1276.h"
|
||||
|
||||
bool SX1276_Mode_LoRa=false;
|
||||
|
||||
void SX1276_WriteReg(uint8_t address, uint8_t data)
|
||||
{
|
||||
SPI_CSN_off;
|
||||
SPI_Write(address | 0x80); // MSB 1 = write
|
||||
NOP();
|
||||
SPI_Write(data);
|
||||
SPI_CSN_on;
|
||||
}
|
||||
|
||||
uint8_t SX1276_ReadReg(uint8_t address)
|
||||
{
|
||||
SPI_CSN_off;
|
||||
SPI_Write(address & 0x7F);
|
||||
uint8_t result = SPI_Read();
|
||||
SPI_CSN_on;
|
||||
return result;
|
||||
}
|
||||
|
||||
void SX1276_WriteRegisterMulti(uint8_t address, const uint8_t* data, uint8_t length)
|
||||
{
|
||||
SPI_CSN_off;
|
||||
SPI_Write(address | 0x80); // MSB 1 = write
|
||||
|
||||
for(uint8_t i = 0; i < length; i++)
|
||||
SPI_Write(data[i]);
|
||||
|
||||
SPI_CSN_on;
|
||||
}
|
||||
|
||||
void SX1276_ReadRegisterMulti(uint8_t address, uint8_t* data, uint8_t length)
|
||||
{
|
||||
SPI_CSN_off;
|
||||
SPI_Write(address & 0x7F);
|
||||
|
||||
for(uint8_t i = 0; i < length; i++)
|
||||
data[i]=SPI_Read();
|
||||
|
||||
SPI_CSN_on;
|
||||
}
|
||||
|
||||
uint8_t SX1276_Reset()
|
||||
{
|
||||
//TODO when pin is not wired
|
||||
#ifdef SX1276_RST_pin
|
||||
SX1276_RST_off;
|
||||
delayMicroseconds(200);
|
||||
SX1276_RST_on;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SX1276_DetectChip() //to be called after reset, verfies the chip has been detected
|
||||
{
|
||||
#define SX1276_Detect_MaxAttempts 5
|
||||
uint8_t i = 0;
|
||||
bool chipFound = false;
|
||||
while ((i < SX1276_Detect_MaxAttempts) && !chipFound)
|
||||
{
|
||||
uint8_t ChipVersion = SX1276_ReadReg(SX1276_42_VERSION);
|
||||
if (ChipVersion == 0x12)
|
||||
{
|
||||
debugln("SX1276 reg version=%d", ChipVersion);
|
||||
chipFound = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("SX1276 not found! attempts: %d", i);
|
||||
debug(" of ");
|
||||
debugln("%d SX1276 reg version=%d", SX1276_Detect_MaxAttempts, ChipVersion);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (!chipFound)
|
||||
{
|
||||
debugln("SX1276 not detected!!!");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
debugln("Found SX1276 Device!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void SX1276_SetTxRxMode(uint8_t mode)
|
||||
{
|
||||
#ifdef SX1276_TXEN_pin
|
||||
if(mode == TX_EN)
|
||||
SX1276_TXEN_on;
|
||||
else
|
||||
SX1276_RXEN_on;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SX1276_SetFrequency(uint32_t frequency)
|
||||
{
|
||||
uint32_t f = frequency / 61;
|
||||
uint8_t data[3];
|
||||
data[0] = f >> 16;
|
||||
data[1] = f >> 8;
|
||||
data[2] = f;
|
||||
|
||||
SX1276_WriteRegisterMulti(SX1276_06_FRFMSB, data, 3);
|
||||
}
|
||||
|
||||
void SX1276_SetMode(bool lora, bool low_freq_mode, uint8_t mode)
|
||||
{
|
||||
uint8_t data = 0x00;
|
||||
|
||||
SX1276_Mode_LoRa=lora;
|
||||
|
||||
if(lora)
|
||||
{
|
||||
data = data | (1 << 7);
|
||||
data = data & ~(1 << 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = data & ~(1 << 7);
|
||||
data = data | (1 << 6);
|
||||
}
|
||||
|
||||
if(low_freq_mode)
|
||||
data = data | (1 << 3);
|
||||
|
||||
data = data | mode;
|
||||
|
||||
SX1276_WriteReg(SX1276_01_OPMODE, data);
|
||||
}
|
||||
|
||||
void SX1276_SetDetectOptimize(bool auto_if, uint8_t detect_optimize)
|
||||
{
|
||||
uint8_t data = SX1276_ReadReg(SX1276_31_DETECTOPTIMIZE);
|
||||
data = (data & 0b01111000) | detect_optimize;
|
||||
data = data | (auto_if << 7);
|
||||
|
||||
SX1276_WriteReg(SX1276_31_DETECTOPTIMIZE, data);
|
||||
}
|
||||
|
||||
void SX1276_ConfigModem1(uint8_t bandwidth, uint8_t coding_rate, bool implicit_header_mode)
|
||||
{
|
||||
uint8_t data = 0x00;
|
||||
data = data | (bandwidth << 4);
|
||||
data = data | (coding_rate << 1);
|
||||
data = data | implicit_header_mode;
|
||||
|
||||
SX1276_WriteReg(SX1276_1D_MODEMCONFIG1, data);
|
||||
|
||||
if (bandwidth == SX1276_MODEM_CONFIG1_BW_500KHZ) //datasheet errata reconmendation http://caxapa.ru/thumbs/972894/SX1276_77_8_ErrataNote_1.1_STD.pdf
|
||||
{
|
||||
SX1276_WriteReg(SX1276_36_LORA_REGHIGHBWOPTIMIZE1, 0x02);
|
||||
SX1276_WriteReg(SX1276_3A_LORA_REGHIGHBWOPTIMIZE2, 0x64);
|
||||
}
|
||||
else
|
||||
SX1276_WriteReg(SX1276_36_LORA_REGHIGHBWOPTIMIZE1, 0x03);
|
||||
}
|
||||
|
||||
void SX1276_ConfigModem2(uint8_t spreading_factor, bool tx_continuous_mode, bool rx_payload_crc_on)
|
||||
{
|
||||
uint8_t data = SX1276_ReadReg(SX1276_1E_MODEMCONFIG2);
|
||||
data = data & 0b11; // preserve the last 2 bits
|
||||
data = data | (spreading_factor << 4);
|
||||
data = data | (tx_continuous_mode << 3);
|
||||
data = data | (rx_payload_crc_on << 2);
|
||||
|
||||
SX1276_WriteReg(SX1276_1E_MODEMCONFIG2, data);
|
||||
}
|
||||
|
||||
void SX1276_ConfigModem3(bool low_data_rate_optimize, bool agc_auto_on)
|
||||
{
|
||||
uint8_t data = SX1276_ReadReg(SX1276_26_MODEMCONFIG3);
|
||||
data = data & 0b11; // preserve the last 2 bits
|
||||
data = data | (low_data_rate_optimize << 3);
|
||||
data = data | (agc_auto_on << 2);
|
||||
|
||||
SX1276_WriteReg(SX1276_26_MODEMCONFIG3, data);
|
||||
}
|
||||
|
||||
void SX1276_SetPreambleLength(uint16_t length)
|
||||
{
|
||||
uint8_t data[2];
|
||||
data[0] = (length >> 8) & 0xFF; // high byte
|
||||
data[1] = length & 0xFF; // low byte
|
||||
|
||||
SX1276_WriteRegisterMulti(SX1276_20_PREAMBLEMSB, data, 2);
|
||||
}
|
||||
|
||||
void SX1276_SetDetectionThreshold(uint8_t threshold)
|
||||
{
|
||||
SX1276_WriteReg(SX1276_37_DETECTIONTHRESHOLD, threshold);
|
||||
}
|
||||
|
||||
void SX1276_SetLna(uint8_t gain, bool high_freq_lna_boost)
|
||||
{
|
||||
uint8_t data = SX1276_ReadReg(SX1276_0C_LNA);
|
||||
data = data & 0b100; // preserve the third bit
|
||||
data = data | (gain << 5);
|
||||
|
||||
if(high_freq_lna_boost)
|
||||
data = data | 0b11;
|
||||
|
||||
SX1276_WriteReg(SX1276_0C_LNA, data);
|
||||
}
|
||||
|
||||
void SX1276_SetHopPeriod(uint8_t freq_hop_period)
|
||||
{
|
||||
SX1276_WriteReg(SX1276_24_HOPPERIOD, freq_hop_period);
|
||||
}
|
||||
|
||||
void SX1276_SetPaDac(bool on)
|
||||
{
|
||||
uint8_t data = SX1276_ReadReg(SX1276_4D_PADAC);
|
||||
data = data & 0b11111000; // preserve the upper 5 bits
|
||||
|
||||
if(on)
|
||||
data = data | 0x07;
|
||||
else
|
||||
data = data | 0x04;
|
||||
|
||||
SX1276_WriteReg(SX1276_4D_PADAC, data);
|
||||
}
|
||||
|
||||
void SX1276_SetPaConfig(bool pa_boost_pin, uint8_t max_power, uint8_t output_power)
|
||||
{
|
||||
uint8_t data = 0x00;
|
||||
data = data | (pa_boost_pin << 7);
|
||||
data = data | (max_power << 4);
|
||||
data = data | output_power;
|
||||
|
||||
SX1276_WriteReg(SX1276_09_PACONFIG, data);
|
||||
}
|
||||
|
||||
void SX1276_WritePayloadToFifo(uint8_t* payload, uint8_t length)
|
||||
{
|
||||
SX1276_WriteReg(SX1276_22_PAYLOAD_LENGTH, length);
|
||||
SX1276_WriteReg(SX1276_0E_FIFOTXBASEADDR, 0x00);
|
||||
SX1276_WriteReg(SX1276_0D_FIFOADDRPTR, 0x00);
|
||||
SX1276_WriteRegisterMulti(SX1276_00_FIFO, payload, length);
|
||||
}
|
||||
|
||||
#endif
|
||||
179
Multiprotocol/Skyartec_cc2500.ino
Normal file
179
Multiprotocol/Skyartec_cc2500.ino
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(SKYARTEC_CC2500_INO)
|
||||
|
||||
#include "iface_cc2500.h"
|
||||
|
||||
//#define SKYARTEC_FORCE_ID
|
||||
|
||||
#define SKYARTEC_COARSE 0x00
|
||||
#define SKYARTEC_TX_ADDR rx_tx_addr[1]
|
||||
#define SKYARTEC_TX_CHANNEL rx_tx_addr[0]
|
||||
|
||||
enum {
|
||||
SKYARTEC_PKT1 = 0,
|
||||
SKYARTEC_SLEEP1,
|
||||
SKYARTEC_PKT2,
|
||||
SKYARTEC_SLEEP2,
|
||||
SKYARTEC_PKT3,
|
||||
SKYARTEC_SLEEP3,
|
||||
SKYARTEC_PKT4,
|
||||
SKYARTEC_SLEEP4,
|
||||
SKYARTEC_PKT5,
|
||||
SKYARTEC_SLEEP5,
|
||||
SKYARTEC_PKT6,
|
||||
SKYARTEC_LAST,
|
||||
};
|
||||
|
||||
const PROGMEM uint8_t SKYARTEC_init_values[] = {
|
||||
/* 04 */ 0x13, 0x18, 0xFF, 0x05,
|
||||
/* 08 */ 0x05, 0x43, 0xCD, 0x09, 0x00, 0x5D, 0x93, 0xB1 + SKYARTEC_COARSE,
|
||||
/* 10 */ 0x2D, 0x20, 0x73, 0x22, 0xF8, 0x50, 0x07, 0x30,
|
||||
/* 18 */ 0x18, 0x1D, 0x1C, 0xC7, 0x00, 0xB2, 0x87, 0x6B,
|
||||
/* 20 */ 0xF8, 0xB6, 0x10, 0xEA, 0x0A, 0x00, 0x11, 0x41,
|
||||
/* 28 */ 0x00, 0x59, 0x7F, 0x3F, 0x88, 0x31, 0x0B
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) SKYARTEC_rf_init()
|
||||
{
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
|
||||
for (uint8_t i = 4; i <= 0x2E; ++i)
|
||||
CC2500_WriteReg(i, pgm_read_byte_near(&SKYARTEC_init_values[i-4]));
|
||||
|
||||
prev_option = option;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
CC2500_SetPower();
|
||||
CC2500_Strobe(CC2500_SFTX);
|
||||
CC2500_Strobe(CC2500_SFRX);
|
||||
CC2500_Strobe(CC2500_SXOFF);
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SKYARTEC_send_data_packet()
|
||||
{
|
||||
//13 c5 01 0259 0168 0000 0259 030c 021a 0489 f3 7e 0a
|
||||
//header
|
||||
packet[0] = 0x13; //Length
|
||||
packet[1] = SKYARTEC_TX_ADDR; //Tx Addr?
|
||||
packet[2] = 0x01; //???
|
||||
//channels
|
||||
for(uint8_t i = 0; i < 7; i++)
|
||||
{
|
||||
uint16_t value = convert_channel_16b_limit(CH_AETR[i],0x000,0x500);
|
||||
packet[3+2*i] = value >> 8;
|
||||
packet[4+2*i] = value & 0xff;
|
||||
}
|
||||
//checks
|
||||
uint8_t xor1 = 0;
|
||||
for(uint8_t i = 3; i <= 14; i++)
|
||||
xor1 ^= packet[i];
|
||||
packet[18] = xor1;
|
||||
xor1 ^= packet[15];
|
||||
xor1 ^= packet[16];
|
||||
packet[17] = xor1;
|
||||
packet[19] = packet[3] + packet[5] + packet[7] + packet[9] + packet[11] + packet[13];
|
||||
|
||||
CC2500_WriteReg(CC2500_04_SYNC1, rx_tx_addr[3]);
|
||||
CC2500_WriteReg(CC2500_05_SYNC0, rx_tx_addr[2]);
|
||||
CC2500_WriteReg(CC2500_09_ADDR, SKYARTEC_TX_ADDR);
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, SKYARTEC_TX_CHANNEL);
|
||||
CC2500_WriteData(packet, 20);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SKYARTEC_send_bind_packet()
|
||||
{
|
||||
//0b 7d 01 01 b2 c5 4a 2f 00 00 c5 d6
|
||||
packet[0] = 0x0b; //Length
|
||||
packet[1] = 0x7d;
|
||||
packet[2] = 0x01;
|
||||
packet[3] = 0x01;
|
||||
packet[4] = rx_tx_addr[0];
|
||||
packet[5] = rx_tx_addr[1];
|
||||
packet[6] = rx_tx_addr[2];
|
||||
packet[7] = rx_tx_addr[3];
|
||||
packet[8] = 0x00;
|
||||
packet[9] = 0x00;
|
||||
packet[10] = SKYARTEC_TX_ADDR;
|
||||
uint8_t xor1 = 0;
|
||||
for(uint8_t i = 3; i < 11; i++)
|
||||
xor1 ^= packet[i];
|
||||
packet[11] = xor1;
|
||||
CC2500_WriteReg(CC2500_04_SYNC1, 0x7d);
|
||||
CC2500_WriteReg(CC2500_05_SYNC0, 0x7d);
|
||||
CC2500_WriteReg(CC2500_09_ADDR, 0x7d);
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, 0x7d);
|
||||
CC2500_WriteData(packet, 12);
|
||||
}
|
||||
|
||||
uint16_t ReadSKYARTEC()
|
||||
{
|
||||
if (phase & 0x01)
|
||||
{
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
if (phase == SKYARTEC_LAST)
|
||||
{
|
||||
CC2500_SetPower();
|
||||
// Tune frequency if it has been changed
|
||||
if ( prev_option != option )
|
||||
{
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
prev_option = option ;
|
||||
}
|
||||
phase = SKYARTEC_PKT1;
|
||||
}
|
||||
else
|
||||
phase++;
|
||||
return 3000;
|
||||
}
|
||||
if (phase == SKYARTEC_PKT1 && bind_counter)
|
||||
{
|
||||
SKYARTEC_send_bind_packet();
|
||||
bind_counter--;
|
||||
if(bind_counter == 0)
|
||||
BIND_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(6000);
|
||||
#endif
|
||||
SKYARTEC_send_data_packet();
|
||||
}
|
||||
phase++;
|
||||
return 3000;
|
||||
}
|
||||
|
||||
uint16_t initSKYARTEC()
|
||||
{
|
||||
SKYARTEC_rf_init();
|
||||
|
||||
#ifdef SKYARTEC_FORCE_ID
|
||||
memset(rx_tx_addr,0x00,4);
|
||||
#endif
|
||||
if(rx_tx_addr[0]==0) rx_tx_addr[0]=0xB2;
|
||||
if(rx_tx_addr[1]==0) rx_tx_addr[1]=0xC5;
|
||||
if(rx_tx_addr[2]==0) rx_tx_addr[2]=0x4A;
|
||||
if(rx_tx_addr[3]==0) rx_tx_addr[3]=0x2F;
|
||||
|
||||
bind_counter = 250;
|
||||
phase = SKYARTEC_PKT1;
|
||||
return 10000;
|
||||
}
|
||||
|
||||
#endif
|
||||
63
Multiprotocol/TEST_cc2500.ino
Normal file
63
Multiprotocol/TEST_cc2500.ino
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(TEST_CC2500_INO)
|
||||
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
#define TEST_INITIAL_WAIT 500
|
||||
#define TEST_PACKET_PERIOD 10000
|
||||
#define TEST_PAYLOAD_SIZE 10
|
||||
#define TEST_RF_NUM_CHANNELS 3
|
||||
|
||||
uint16_t TEST_callback()
|
||||
{
|
||||
option=1;
|
||||
if(phase)
|
||||
XN297L_WritePayload(packet, TEST_PAYLOAD_SIZE);
|
||||
else
|
||||
{
|
||||
if(Channel_data[CH5]<CHANNEL_MIN_COMMAND)
|
||||
hopping_frequency_no=0;
|
||||
else if(Channel_data[CH5]>CHANNEL_MAX_COMMAND)
|
||||
hopping_frequency_no=2;
|
||||
else
|
||||
hopping_frequency_no=1;
|
||||
XN297L_Hopping(hopping_frequency_no);
|
||||
CC2500_WriteReg(CC2500_3E_PATABLE,convert_channel_8b(CH6));
|
||||
debugln("CH:%d, PWR:%d",hopping_frequency_no,convert_channel_8b(CH6));
|
||||
}
|
||||
phase ^= 1;
|
||||
return TEST_PACKET_PERIOD>>1;
|
||||
}
|
||||
|
||||
uint16_t initTEST()
|
||||
{
|
||||
option=1;
|
||||
|
||||
hopping_frequency[0]=0;
|
||||
hopping_frequency[1]=40;
|
||||
hopping_frequency[2]=80;
|
||||
XN297L_Init();
|
||||
XN297L_HoppingCalib(TEST_RF_NUM_CHANNELS); // Calibrate all channels
|
||||
XN297L_SetTXAddr((uint8_t*)"RADIO", 5);
|
||||
hopping_frequency_no = 0;
|
||||
phase=0;
|
||||
for(uint8_t i=0; i<TEST_PAYLOAD_SIZE; i++)
|
||||
packet[i]= i;
|
||||
return TEST_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -33,7 +33,6 @@ uint8_t RetrySequence ;
|
||||
#if defined SPORT_TELEMETRY
|
||||
#define FRSKY_SPORT_PACKET_SIZE 8
|
||||
#define FX_BUFFERS 4
|
||||
uint8_t RxBt = 0;
|
||||
uint8_t Sport_Data = 0;
|
||||
uint8_t pktx1[FRSKY_SPORT_PACKET_SIZE*FX_BUFFERS];
|
||||
|
||||
@@ -120,12 +119,15 @@ static void telemetry_set_input_sync(uint16_t refreshRate)
|
||||
|
||||
static void multi_send_status()
|
||||
{
|
||||
#ifdef MULTI_TELEMETRY
|
||||
#ifdef MULTI_NAMES
|
||||
if(multi_protocols_index != 0xFF)
|
||||
multi_send_header(MULTI_TELEMETRY_STATUS, 24);
|
||||
else
|
||||
#else
|
||||
multi_send_header(MULTI_TELEMETRY_STATUS, 5);
|
||||
#endif
|
||||
#else
|
||||
multi_send_header(MULTI_TELEMETRY_STATUS, 5);
|
||||
#endif
|
||||
multi_send_header(MULTI_TELEMETRY_STATUS, 6);
|
||||
|
||||
// Build flags
|
||||
uint8_t flags=0;
|
||||
@@ -137,12 +139,21 @@ static void multi_send_status()
|
||||
{
|
||||
flags |= 0x04;
|
||||
#ifdef MULTI_NAMES
|
||||
if((sub_protocol&0x07) && multi_protocols_index != 0xFF)
|
||||
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)
|
||||
flags &= ~0x04; //Invalid protocol
|
||||
#endif
|
||||
if (IS_WAIT_BIND_on)
|
||||
flags |= 0x10;
|
||||
@@ -166,21 +177,30 @@ 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
|
||||
|
||||
#ifdef MULTI_NAMES
|
||||
if(multi_protocols_index != 0xFF)
|
||||
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[multi_protocols_index+1].protocol); // next protocol number
|
||||
else
|
||||
Serial_write(protocol); // end of list
|
||||
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(protocol); // begining of list
|
||||
Serial_write(multi_protocols[multi_protocols_index].protocol); // begining of list
|
||||
// Protocol
|
||||
for(uint8_t i=0;i<7;i++)
|
||||
Serial_write(multi_protocols[multi_protocols_index].ProtoString[i]); // protocol name
|
||||
@@ -197,9 +217,9 @@ static void multi_send_status()
|
||||
}
|
||||
for(;j<8;j++)
|
||||
Serial_write(0x00);
|
||||
}
|
||||
// Channels function
|
||||
//TODO
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -246,7 +266,7 @@ static void multi_send_status()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (FRSKY_RX_TELEMETRY) || defined (AFHDS2A_RX_TELEMETRY) || defined (BAYANG_RX_TELEMETRY)
|
||||
#if defined (FRSKY_RX_TELEMETRY) || defined (AFHDS2A_RX_TELEMETRY) || defined (BAYANG_RX_TELEMETRY) || defined (DSM_RX_CYRF6936_INO)
|
||||
void receiver_channels_frame()
|
||||
{
|
||||
uint16_t len = packet_in[3] * 11; // 11 bit per channel
|
||||
@@ -327,26 +347,28 @@ void frskySendStuffed()
|
||||
Serial_write(START_STOP);
|
||||
}
|
||||
|
||||
void frsky_check_telemetry(uint8_t *packet_in,uint8_t len)
|
||||
bool frsky_process_telemetry(uint8_t *buffer,uint8_t len)
|
||||
{
|
||||
if(packet_in[1] != rx_tx_addr[3] || packet_in[2] != rx_tx_addr[2] || len != packet_in[0] + 3 )
|
||||
return; // Bad address or length...
|
||||
|
||||
telemetry_link|=1; // Telemetry data is available
|
||||
if(protocol!=PROTO_FRSKY_R9)
|
||||
{
|
||||
if(buffer[1] != rx_tx_addr[3] || buffer[2] != rx_tx_addr[2] || len != buffer[0] + 3 )
|
||||
return false; // Bad address or length...
|
||||
// RSSI and LQI are the 2 last bytes
|
||||
TX_RSSI = packet_in[len-2];
|
||||
TX_RSSI = buffer[len-2];
|
||||
if(TX_RSSI >=128)
|
||||
TX_RSSI -= 128;
|
||||
else
|
||||
TX_RSSI += 128;
|
||||
TX_LQI = packet_in[len-1]&0x7F;
|
||||
}
|
||||
telemetry_link|=1; // Telemetry data is available
|
||||
|
||||
#if defined FRSKYD_CC2500_INO
|
||||
if (protocol==PROTO_FRSKYD)
|
||||
{
|
||||
TX_LQI = buffer[len-1]&0x7F;
|
||||
//Save current buffer
|
||||
for (uint8_t i=3;i<len-2;i++)
|
||||
telemetry_in_buffer[i]=packet_in[i]; // Buffer telemetry values to be sent
|
||||
telemetry_in_buffer[i]=buffer[i]; // Buffer telemetry values to be sent
|
||||
|
||||
//Check incoming telemetry sequence
|
||||
if(telemetry_in_buffer[6]>0 && telemetry_in_buffer[6]<=10)
|
||||
@@ -371,8 +393,8 @@ void frsky_check_telemetry(uint8_t *packet_in,uint8_t len)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined SPORT_TELEMETRY && defined FRSKYX_CC2500_INO
|
||||
if (protocol==PROTO_FRSKYX)
|
||||
#if defined SPORT_TELEMETRY && (defined FRSKYX_CC2500_INO || defined FRSKYR9_SX1276_INO)
|
||||
if (protocol==PROTO_FRSKYX||protocol==PROTO_FRSKYX2)
|
||||
{
|
||||
/*Telemetry frames(RF) SPORT info
|
||||
15 bytes payload
|
||||
@@ -392,29 +414,30 @@ void frsky_check_telemetry(uint8_t *packet_in,uint8_t len)
|
||||
[12] STRM6 D1 D1 D0 D0
|
||||
[13] CHKSUM1 --|2 CRC bytes sent by RX (calculated on RX side crc16/table)
|
||||
[14] CHKSUM2 --|*/
|
||||
telemetry_lost=0;
|
||||
//len=17 -> len-7=10 -> 3..12
|
||||
uint16_t lcrc = FrSkyX_crc(&buffer[3], len-7 ) ;
|
||||
if ( ( (lcrc >> 8) != buffer[len-4]) || ( (lcrc & 0x00FF ) != buffer[len-3]) )
|
||||
return false; // Bad CRC
|
||||
|
||||
uint16_t lcrc = FrSkyX_crc(&packet_in[3], len-7 ) ;
|
||||
if ( ( (lcrc >> 8) != packet_in[len-4]) || ( (lcrc & 0x00FF ) != packet_in[len-3]) )
|
||||
return; // Bad CRC
|
||||
|
||||
if(packet_in[4] & 0x80)
|
||||
RX_RSSI=packet_in[4] & 0x7F ;
|
||||
if(buffer[4] & 0x80)
|
||||
RX_RSSI=buffer[4] & 0x7F ;
|
||||
else
|
||||
RxBt = (packet_in[4]<<1) + 1 ;
|
||||
v_lipo1 = (buffer[4]<<1) + 1 ;
|
||||
#if defined(TELEMETRY_FRSKYX_TO_FRSKYD) && defined(ENABLE_PPM)
|
||||
if(mode_select != MODE_SERIAL)
|
||||
{//PPM
|
||||
v_lipo1=RxBt;
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
if (protocol==PROTO_FRSKYX||protocol==PROTO_FRSKYX2||protocol==PROTO_FRSKY_R9)
|
||||
{
|
||||
telemetry_lost=0;
|
||||
|
||||
//Save outgoing telemetry sequence
|
||||
FrSkyX_TX_IN_Seq=packet_in[5] >> 4;
|
||||
FrSkyX_TX_IN_Seq=buffer[5] >> 4;
|
||||
|
||||
//Check incoming telemetry sequence
|
||||
uint8_t packet_seq=packet_in[5] & 0x03;
|
||||
if ( packet_in[5] & 0x08 )
|
||||
uint8_t packet_seq=buffer[5] & 0x03;
|
||||
if ( buffer[5] & 0x08 )
|
||||
{//Request init
|
||||
FrSkyX_RX_Seq = 0x08 ;
|
||||
FrSkyX_RX_NextFrame = 0x00 ;
|
||||
@@ -427,17 +450,17 @@ void frsky_check_telemetry(uint8_t *packet_in,uint8_t len)
|
||||
{//In sequence
|
||||
struct t_FrSkyX_RX_Frame *p ;
|
||||
uint8_t count ;
|
||||
// packet_in[4] RSSI
|
||||
// packet_in[5] sequence control
|
||||
// packet_in[6] payload count
|
||||
// packet_in[7-12] payload
|
||||
// buffer[4] RSSI
|
||||
// buffer[5] sequence control
|
||||
// buffer[6] payload count
|
||||
// buffer[7-12] payload
|
||||
p = &FrSkyX_RX_Frames[packet_seq] ;
|
||||
count = packet_in[6]; // Payload length
|
||||
count = buffer[6]; // Payload length
|
||||
if ( count <= 6 )
|
||||
{//Store payload
|
||||
p->count = count ;
|
||||
for ( uint8_t i = 0 ; i < count ; i++ )
|
||||
p->payload[i] = packet_in[i+7] ;
|
||||
p->payload[i] = buffer[i+7] ;
|
||||
}
|
||||
else
|
||||
p->count = 0 ; // Discard
|
||||
@@ -456,19 +479,19 @@ void frsky_check_telemetry(uint8_t *packet_in,uint8_t len)
|
||||
{//Not in sequence
|
||||
struct t_FrSkyX_RX_Frame *q ;
|
||||
uint8_t count ;
|
||||
// packet_in[4] RSSI
|
||||
// packet_in[5] sequence control
|
||||
// packet_in[6] payload count
|
||||
// packet_in[7-12] payload
|
||||
// buffer[4] RSSI
|
||||
// buffer[5] sequence control
|
||||
// buffer[6] payload count
|
||||
// buffer[7-12] payload
|
||||
if ( packet_seq == ( ( FrSkyX_RX_Seq +1 ) & 3 ) )
|
||||
{//Received next sequence -> save it
|
||||
q = &FrSkyX_RX_Frames[packet_seq] ;
|
||||
count = packet_in[6]; // Payload length
|
||||
count = buffer[6]; // Payload length
|
||||
if ( count <= 6 )
|
||||
{//Store payload
|
||||
q->count = count ;
|
||||
for ( uint8_t i = 0 ; i < count ; i++ )
|
||||
q->payload[i] = packet_in[i+7] ;
|
||||
q->payload[i] = buffer[i+7] ;
|
||||
}
|
||||
else
|
||||
q->count = 0 ;
|
||||
@@ -480,6 +503,7 @@ void frsky_check_telemetry(uint8_t *packet_in,uint8_t len)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void init_frskyd_link_telemetry()
|
||||
@@ -507,7 +531,7 @@ void frsky_link_frame()
|
||||
telemetry_link |= 2 ; // Send hub if available
|
||||
}
|
||||
else
|
||||
{//PROTO_HUBSAN, PROTO_AFHDS2A, PROTO_BAYANG, PROTO_NCC1701, PROTO_CABELL, PROTO_HITEC, PROTO_BUGS, PROTO_BUGSMINI, PROTO_FRSKYX
|
||||
{//PROTO_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
|
||||
frame[1] = v_lipo1;
|
||||
frame[2] = v_lipo2;
|
||||
frame[3] = RX_RSSI;
|
||||
@@ -719,7 +743,7 @@ void sportSendFrame()
|
||||
case 4: //BATT
|
||||
frame[2] = 0x04;
|
||||
frame[3] = 0xf1;
|
||||
frame[4] = RxBt;//a1;
|
||||
frame[4] = v_lipo1; //a1;
|
||||
break;
|
||||
default:
|
||||
if(Sport_Data)
|
||||
@@ -849,7 +873,7 @@ void TelemetryUpdate()
|
||||
#endif
|
||||
#endif
|
||||
#if defined SPORT_TELEMETRY
|
||||
if (protocol==PROTO_FRSKYX && telemetry_link
|
||||
if ((protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2||protocol==PROTO_FRSKY_R9) && telemetry_link
|
||||
#ifdef TELEMETRY_FRSKYX_TO_FRSKYD
|
||||
&& mode_select==MODE_SERIAL
|
||||
#endif
|
||||
@@ -918,8 +942,8 @@ void TelemetryUpdate()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (FRSKY_RX_TELEMETRY) || defined(AFHDS2A_RX_TELEMETRY) || defined (BAYANG_RX_TELEMETRY)
|
||||
if ((telemetry_link & 1) && (protocol == PROTO_FRSKY_RX || protocol == PROTO_AFHDS2A_RX || protocol == PROTO_BAYANG_RX))
|
||||
#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;
|
||||
@@ -928,7 +952,7 @@ void TelemetryUpdate()
|
||||
#endif
|
||||
|
||||
if( telemetry_link & 1 )
|
||||
{ // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs + BugsMini + NCC1701
|
||||
{ // FrSkyD + Hubsan + AFHDS2A + Bayang + Cabell + Hitec + Bugs + BugsMini + NCC1701 + PROPEL + RLINK + OMP
|
||||
// FrSkyX telemetry if in PPM
|
||||
frsky_link_frame();
|
||||
return;
|
||||
|
||||
182
Multiprotocol/Tiger_nrf24l01.ino
Normal file
182
Multiprotocol/Tiger_nrf24l01.ino
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Compatible with Tiger Drone 1400782.
|
||||
|
||||
#if defined(TIGER_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#define TIGER_FORCE_ID
|
||||
|
||||
#define TIGER_INITIAL_WAIT 500
|
||||
#define TIGER_PACKET_PERIOD 3940
|
||||
#define TIGER_RF_NUM_CHANNELS 4
|
||||
#define TIGER_BIND_RF_NUM_CHANNELS 8
|
||||
#define TIGER_PAYLOAD_SIZE 16
|
||||
#define TIGER_BIND_COUNT 761 //3sec
|
||||
|
||||
|
||||
static uint8_t __attribute__((unused)) TIGER_convert_channel(uint8_t num)
|
||||
{
|
||||
uint8_t val=convert_channel_8b(num);
|
||||
// 7F..01=left, 00=center, 80..FF=right
|
||||
if(val==0x80)
|
||||
val=0; // 0
|
||||
else
|
||||
if(val>0x80)
|
||||
val--; // 80..FE
|
||||
else
|
||||
{
|
||||
val=0x80-val; // 80..01
|
||||
if(val==0x80)
|
||||
val--; // 7F..01
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) TIGER_send_packet()
|
||||
{
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
//Channels
|
||||
packet[0]=convert_channel_8b(THROTTLE); // 00..FF
|
||||
packet[1]=TIGER_convert_channel(RUDDER); // 7F..01=left, 00=center, 80..FF=right
|
||||
packet[2]=TIGER_convert_channel(ELEVATOR); // 7F..01=down, 00=center, 80..FF=up
|
||||
packet[3]=TIGER_convert_channel(AILERON); // 7F..01=left, 00=center, 80..FF=right
|
||||
//Flags
|
||||
packet[14]= GET_FLAG(CH5_SW, 0x04) //FLIP
|
||||
| GET_FLAG(CH6_SW, 0x10); //LIGHT
|
||||
}
|
||||
//Check
|
||||
crc8=0;
|
||||
for(uint8_t i=0;i<TIGER_PAYLOAD_SIZE-1;i++)
|
||||
crc8+=packet[i];
|
||||
packet[TIGER_PAYLOAD_SIZE-1]=crc8;
|
||||
|
||||
//Hopping frequency
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no>>1]);
|
||||
hopping_frequency_no++;
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
if(hopping_frequency_no>=2*TIGER_BIND_RF_NUM_CHANNELS)
|
||||
hopping_frequency_no=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(hopping_frequency_no>=2*(TIGER_BIND_RF_NUM_CHANNELS+TIGER_RF_NUM_CHANNELS))
|
||||
hopping_frequency_no=2*TIGER_BIND_RF_NUM_CHANNELS;
|
||||
}
|
||||
|
||||
//Clear packet status bits and TX FIFO
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
//Send packet
|
||||
XN297_WritePayload(packet, TIGER_PAYLOAD_SIZE);
|
||||
//Set tx_power
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) TIGER_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
XN297_SetTXAddr((uint8_t *)"\x68\x94\xA6\xD5\xC3", 5);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // No retransmits
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
|
||||
NRF24L01_Activate(0x73);
|
||||
// Power on, TX mode, 2byte CRC
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) TIGER_initialize_txid()
|
||||
{
|
||||
#ifdef TIGER_FORCE_ID
|
||||
rx_tx_addr[0]=0x64;
|
||||
rx_tx_addr[1]=0x39;
|
||||
rx_tx_addr[2]=0x12;
|
||||
rx_tx_addr[3]=0x00;
|
||||
rx_tx_addr[4]=0x00;
|
||||
memcpy(hopping_frequency,"\x0E\x39\x1C\x07\x24\x3E\x2B\x47",TIGER_BIND_RF_NUM_CHANNELS);
|
||||
memcpy(&hopping_frequency[TIGER_BIND_RF_NUM_CHANNELS],"\x36\x41\x37\x4E",TIGER_RF_NUM_CHANNELS);
|
||||
#endif
|
||||
//prepare bind packet
|
||||
memset(&packet[0], 0x00, 4);
|
||||
memset(&packet[4], 0x40, 10);
|
||||
memcpy(&packet[7], rx_tx_addr, 5);
|
||||
packet[14]=0xC0;
|
||||
}
|
||||
|
||||
uint16_t TIGER_callback()
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(TIGER_PACKET_PERIOD);
|
||||
#endif
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
if(--bind_counter==0)
|
||||
{
|
||||
BIND_DONE;
|
||||
XN297_SetTXAddr((uint8_t *)"\x49\xA6\x83\xEB\x4B", 5);
|
||||
}
|
||||
TIGER_send_packet();
|
||||
return TIGER_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initTIGER()
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
TIGER_initialize_txid();
|
||||
TIGER_init();
|
||||
hopping_frequency_no = 0;
|
||||
bind_counter=TIGER_BIND_COUNT;
|
||||
return TIGER_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*Bind
|
||||
- RF setup: 1Mbps, scrambled, CRC
|
||||
- TX addr: 0x68 0x94 0xA6 0xD5 0xC3
|
||||
- 8 RF channels: 0x0E 0x39 0x1C 0x07 0x24 0x3E 0x2B 0x47
|
||||
- 2 packets per RF channel, 3940µs between packets
|
||||
- payload 16 bytes: 0x00 0x00 0x00 0x00 0x40 0x40 0x40 0x64 0x39 0x12 0x00 0x00 0x40 0x40 0xC0 0xAF
|
||||
- payload[15]=sum of payload[0..14]
|
||||
- the only difference with normal packets is the payload[14]=0xC0
|
||||
- ??? payload[7..11] TX ID ???
|
||||
|
||||
Normal
|
||||
- RF setup: 1Mbps
|
||||
- TX addr: 0x49 0xA6 0x83 0xEB 0x4B
|
||||
- 4 RF channels: 0x36 0x41 0x37 0x4E
|
||||
- 2 packets per RF channel, 3940µs between packets
|
||||
- payload 16 bytes: 0x00 0x00 0x00 0x00 0x40 0x40 0x40 0x64 0x39 0x12 0x00 0x00 0x40 0x40 0x00 0xEF
|
||||
- payload[15]=sum of payload[0..14]
|
||||
- throttle is on payload[0] 00..FF
|
||||
- rudder is on payload[1] 00=center, 80..FF=right, 01..7F=left
|
||||
- elevator is on payload[2] 00=center, 80..FF=up, 01..7F=down
|
||||
- aileron is on payload[3] 00=center, 80..FF=right, 01..7F=left
|
||||
- trims payload[4..6]
|
||||
- ??? payload[7..11] TX ID ???
|
||||
- ??? payload[12..13] ???
|
||||
- flip is on payload[14] and flag 0x04
|
||||
- light is on payload[14] and flag 0x10
|
||||
*/
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#define V2X2_MR101_FORCE_ID
|
||||
|
||||
#define V2X2_BIND_COUNT 1000
|
||||
// Timeout for callback in uSec, 4ms=4000us for V202
|
||||
@@ -51,14 +51,6 @@ enum {
|
||||
|
||||
//
|
||||
|
||||
enum {
|
||||
V202_INIT2 = 0,
|
||||
V202_INIT2_NO_BIND,//1
|
||||
V202_BIND1,//2
|
||||
V202_BIND2,//3
|
||||
V202_DATA//4
|
||||
};
|
||||
|
||||
// This is frequency hopping table for V202 protocol
|
||||
// The table is the first 4 rows of 32 frequency hopping
|
||||
// patterns, all other rows are derived from the first 4.
|
||||
@@ -87,39 +79,29 @@ static void __attribute__((unused)) v202_init()
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3F); // Enable all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0xFF); // 4ms retransmit t/o, 15 tries
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x08); // Channel 8
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
// NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0xFF); // 4ms retransmit t/o, 15 tries
|
||||
// NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x08); // Channel 8
|
||||
NRF24L01_SetBitrate(sub_protocol==V2X2_MR101?NRF24L01_BR_250K:NRF24L01_BR_1M);
|
||||
NRF24L01_SetPower();
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
// NRF24L01_WriteReg(NRF24L01_08_OBSERVE_TX, 0x00); // no write bits in this field
|
||||
// NRF24L01_WriteReg(NRF24L01_00_CD, 0x00); // same
|
||||
NRF24L01_WriteReg(NRF24L01_0C_RX_ADDR_P2, 0xC3); // LSB byte of pipe 2 receive address
|
||||
NRF24L01_WriteReg(NRF24L01_0D_RX_ADDR_P3, 0xC4);
|
||||
NRF24L01_WriteReg(NRF24L01_0E_RX_ADDR_P4, 0xC5);
|
||||
NRF24L01_WriteReg(NRF24L01_0F_RX_ADDR_P5, 0xC6);
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, V2X2_PAYLOADSIZE); // bytes of data payload for pipe 1
|
||||
NRF24L01_WriteReg(NRF24L01_12_RX_PW_P1, V2X2_PAYLOADSIZE);
|
||||
NRF24L01_WriteReg(NRF24L01_13_RX_PW_P2, V2X2_PAYLOADSIZE);
|
||||
NRF24L01_WriteReg(NRF24L01_14_RX_PW_P3, V2X2_PAYLOADSIZE);
|
||||
NRF24L01_WriteReg(NRF24L01_15_RX_PW_P4, V2X2_PAYLOADSIZE);
|
||||
NRF24L01_WriteReg(NRF24L01_16_RX_PW_P5, V2X2_PAYLOADSIZE);
|
||||
NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here
|
||||
// NRF24L01_WriteReg(NRF24L01_0C_RX_ADDR_P2, 0xC3); // LSB byte of pipe 2 receive address
|
||||
// NRF24L01_WriteReg(NRF24L01_0D_RX_ADDR_P3, 0xC4);
|
||||
// NRF24L01_WriteReg(NRF24L01_0E_RX_ADDR_P4, 0xC5);
|
||||
// NRF24L01_WriteReg(NRF24L01_0F_RX_ADDR_P5, 0xC6);
|
||||
// NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, V2X2_PAYLOADSIZE); // bytes of data payload for pipe 1
|
||||
// NRF24L01_WriteReg(NRF24L01_12_RX_PW_P1, V2X2_PAYLOADSIZE);
|
||||
// NRF24L01_WriteReg(NRF24L01_13_RX_PW_P2, V2X2_PAYLOADSIZE);
|
||||
// NRF24L01_WriteReg(NRF24L01_14_RX_PW_P3, V2X2_PAYLOADSIZE);
|
||||
// NRF24L01_WriteReg(NRF24L01_15_RX_PW_P4, V2X2_PAYLOADSIZE);
|
||||
// NRF24L01_WriteReg(NRF24L01_16_RX_PW_P5, V2X2_PAYLOADSIZE);
|
||||
// NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x66\x88\x68\x68\x68", 5);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, (uint8_t *)"\x88\x66\x86\x86\x86", 5);
|
||||
// NRF24L01_WriteRegisterMulti(NRF24L01_0B_RX_ADDR_P1, (uint8_t *)"\x88\x66\x86\x86\x86", 5);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x66\x88\x68\x68\x68", 5);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) V202_init2()
|
||||
{
|
||||
NRF24L01_FlushTx();
|
||||
packet_sent = 0;
|
||||
hopping_frequency_no = 0;
|
||||
|
||||
// Turn radio power on
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
//Done by TX_EN??? => NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) V2X2_set_tx_id(void)
|
||||
@@ -135,20 +117,27 @@ static void __attribute__((unused)) V2X2_set_tx_id(void)
|
||||
// Strange avoidance of channels divisible by 16
|
||||
hopping_frequency[i] = (val & 0x0f) ? val : val - 3;
|
||||
}
|
||||
#ifdef V2X2_MR101_FORCE_ID
|
||||
if(sub_protocol==V2X2_MR101)
|
||||
{
|
||||
rx_tx_addr[1]=0x83;
|
||||
rx_tx_addr[2]=0x03;
|
||||
rx_tx_addr[3]=0xAE;
|
||||
memcpy(hopping_frequency,"\x05\x12\x08\x0C\x04\x0E\x10",7);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) V2X2_add_pkt_checksum()
|
||||
static void __attribute__((unused)) V2X2_send_packet()
|
||||
{
|
||||
uint8_t sum = 0;
|
||||
for (uint8_t i = 0; i < 15; ++i)
|
||||
sum += packet[i];
|
||||
packet[15] = sum;
|
||||
}
|
||||
uint8_t rf_ch = hopping_frequency[hopping_frequency_no >> 1];
|
||||
hopping_frequency_no = (hopping_frequency_no + 1) & 0x1F;
|
||||
if(sub_protocol==V2X2_MR101 && hopping_frequency_no>13)
|
||||
hopping_frequency_no=0;
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch);
|
||||
|
||||
static void __attribute__((unused)) V2X2_send_packet(uint8_t bind)
|
||||
{
|
||||
uint8_t flags2=0;
|
||||
if (bind)
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
flags = V2X2_FLAG_BIND;
|
||||
packet[0] = 0;
|
||||
@@ -174,6 +163,9 @@ static void __attribute__((unused)) V2X2_send_packet(uint8_t bind)
|
||||
flags=0;
|
||||
// Channel 5
|
||||
if (CH5_SW) flags = V2X2_FLAG_FLIP;
|
||||
|
||||
if(sub_protocol!=V2X2_MR101)
|
||||
{//V2X2 & JXD506
|
||||
// Channel 6
|
||||
if (CH6_SW) flags |= V2X2_FLAG_LIGHT;
|
||||
// Channel 7
|
||||
@@ -192,7 +184,7 @@ static void __attribute__((unused)) V2X2_send_packet(uint8_t bind)
|
||||
flags2 |= V2X2_FLAG_EMERGENCY;
|
||||
}
|
||||
else
|
||||
{
|
||||
{//V2X2
|
||||
// Channel 10
|
||||
if (CH10_SW)
|
||||
flags2 |= V2X2_FLAG_MAG_CAL_X;
|
||||
@@ -201,6 +193,7 @@ static void __attribute__((unused)) V2X2_send_packet(uint8_t bind)
|
||||
flags2 |= V2X2_FLAG_MAG_CAL_Y;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TX id
|
||||
packet[7] = rx_tx_addr[1];
|
||||
packet[8] = rx_tx_addr[2];
|
||||
@@ -223,16 +216,26 @@ static void __attribute__((unused)) V2X2_send_packet(uint8_t bind)
|
||||
packet[12] = 0x40;
|
||||
packet[13] = 0x40;
|
||||
}
|
||||
packet[14] = flags;
|
||||
V2X2_add_pkt_checksum();
|
||||
else if(sub_protocol==V2X2_MR101)
|
||||
{
|
||||
|
||||
if (CH10_SW) packet[11] = 0x04; // Motors start/stop
|
||||
if (CH11_SW) packet[11] |= 0x40; // Auto Land=-100% Takeoff=+100%
|
||||
if (CH7_SW) flags |= 0x02; // Picture
|
||||
if (CH8_SW) flags |= 0x01; // Video
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
flags = 0x80;
|
||||
flags |= (hopping_frequency_no & 0x01)<<6;
|
||||
}
|
||||
packet[14] = flags;
|
||||
uint8_t sum = packet[0];
|
||||
for (uint8_t i = 1; i < 15; ++i)
|
||||
sum += packet[i];
|
||||
packet[15] = sum;
|
||||
|
||||
packet_sent = 0;
|
||||
uint8_t rf_ch = hopping_frequency[hopping_frequency_no >> 1];
|
||||
hopping_frequency_no = (hopping_frequency_no + 1) & 0x1F;
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WritePayload(packet, V2X2_PAYLOADSIZE);
|
||||
packet_sent = 1;
|
||||
//packet_sent = 1;
|
||||
|
||||
if (! hopping_frequency_no)
|
||||
NRF24L01_SetPower();
|
||||
@@ -240,35 +243,26 @@ static void __attribute__((unused)) V2X2_send_packet(uint8_t bind)
|
||||
|
||||
uint16_t ReadV2x2()
|
||||
{
|
||||
switch (phase) {
|
||||
case V202_INIT2:
|
||||
V202_init2();
|
||||
phase = V202_BIND2;
|
||||
return 150;
|
||||
break;
|
||||
case V202_INIT2_NO_BIND:
|
||||
V202_init2();
|
||||
phase = V202_DATA;
|
||||
return 150;
|
||||
break;
|
||||
case V202_BIND2:
|
||||
if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED)
|
||||
return V2X2_PACKET_CHKTIME;
|
||||
V2X2_send_packet(1);
|
||||
if (--bind_counter == 0)
|
||||
{
|
||||
phase = V202_DATA;
|
||||
BIND_DONE;
|
||||
}
|
||||
break;
|
||||
case V202_DATA:
|
||||
if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED)
|
||||
return V2X2_PACKET_CHKTIME;
|
||||
//if (packet_sent && NRF24L01_packet_ack() != PKT_ACKED)
|
||||
// return V2X2_PACKET_CHKTIME;
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(V2X2_PACKET_PERIOD);
|
||||
#endif
|
||||
V2X2_send_packet(0);
|
||||
break;
|
||||
V2X2_send_packet();
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
if (--bind_counter == 0)
|
||||
{
|
||||
BIND_DONE;
|
||||
if(sub_protocol==V2X2_MR101)
|
||||
{
|
||||
#ifdef V2X2_MR101_FORCE_ID
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\xC9\x59\xD2\x65\x34", 5);
|
||||
memcpy(hopping_frequency,"\x03\x05\x15\x0D\x06\x14\x0B",7);
|
||||
#endif
|
||||
}
|
||||
hopping_frequency_no = 0;
|
||||
}
|
||||
}
|
||||
// Packet every 4ms
|
||||
return V2X2_PACKET_PERIOD;
|
||||
@@ -276,15 +270,13 @@ uint16_t ReadV2x2()
|
||||
|
||||
uint16_t initV2x2()
|
||||
{
|
||||
v202_init();
|
||||
//
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
if(sub_protocol==V2X2_MR101)
|
||||
BIND_IN_PROGRESS;
|
||||
//packet_sent = 0;
|
||||
hopping_frequency_no = 0;
|
||||
bind_counter = V2X2_BIND_COUNT;
|
||||
phase = V202_INIT2;
|
||||
}
|
||||
else
|
||||
phase = V202_INIT2_NO_BIND;
|
||||
|
||||
v202_init();
|
||||
V2X2_set_tx_id();
|
||||
return 50000;
|
||||
}
|
||||
|
||||
@@ -17,12 +17,12 @@ Multiprotocol is distributed in the hope that it will be useful,
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
//#define V761_FORCE_ID
|
||||
|
||||
#define V761_PACKET_PERIOD 7060 // Timeout for callback in uSec
|
||||
#define V761_INITIAL_WAIT 500
|
||||
#define V761_PACKET_SIZE 8
|
||||
#define V761_BIND_COUNT 200
|
||||
|
||||
//Fx chan management
|
||||
#define V761_BIND_FREQ 0x28
|
||||
#define V761_RF_NUM_CHANNELS 3
|
||||
|
||||
@@ -53,6 +53,8 @@ static void __attribute__((unused)) V761_set_checksum()
|
||||
|
||||
static void __attribute__((unused)) V761_send_packet()
|
||||
{
|
||||
static bool calib=false, prev_ch6=false;
|
||||
|
||||
if(phase != V761_DATA)
|
||||
{
|
||||
packet[0] = rx_tx_addr[0];
|
||||
@@ -66,14 +68,23 @@ static void __attribute__((unused)) V761_send_packet()
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[0] = convert_channel_8b(THROTTLE); // throttle
|
||||
packet[1] = convert_channel_8b(RUDDER)>>1; // rudder
|
||||
packet[2] = convert_channel_8b(ELEVATOR)>>1; // elevator
|
||||
packet[3] = convert_channel_8b(AILERON)>>1; // aileron
|
||||
packet[5] = (packet_count++ / 3)<<6;
|
||||
packet[4] = (packet[5] == 0x40) ? 0x1a : 0x20;
|
||||
packet[0] = convert_channel_8b(THROTTLE); // Throttle
|
||||
packet[2] = convert_channel_8b(ELEVATOR)>>1; // Elevator
|
||||
|
||||
if(sub_protocol==V761_3CH)
|
||||
{
|
||||
packet[1] = convert_channel_8b(RUDDER)>>1; // Rudder
|
||||
packet[3] = convert_channel_8b(AILERON)>>1; // Aileron
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[1] = convert_channel_8b(AILERON)>>1; // Aileron
|
||||
packet[3] = convert_channel_8b(RUDDER)>>1; // Rudder
|
||||
}
|
||||
|
||||
packet[5] = (packet_count++ / 3)<<6;
|
||||
packet[4] = (packet[5] == 0x40) ? 0x1a : 0x20; // ?
|
||||
|
||||
// Channel 5 - Gyro mode is packet 5
|
||||
if(CH5_SW) // Mode Expert Gyro off
|
||||
flags = 0x0c;
|
||||
else
|
||||
@@ -81,8 +92,20 @@ static void __attribute__((unused)) V761_send_packet()
|
||||
flags = 0x08; // Beginer mode (Gyro on, yaw and pitch rate limited)
|
||||
else
|
||||
flags = 0x0a; // Mid Mode ( Gyro on no rate limits)
|
||||
|
||||
if(!prev_ch6 && CH6_SW) // -100% -> 100% launch gyro calib
|
||||
calib=!calib;
|
||||
prev_ch6 = CH6_SW;
|
||||
if(calib)
|
||||
flags |= 0x01; // Gyro calibration
|
||||
|
||||
packet[5] |= flags;
|
||||
packet[6] = 0x80; // unknown
|
||||
|
||||
packet[6] = GET_FLAG(CH7_SW, 0x20) // Flip
|
||||
|GET_FLAG(CH8_SW, 0x08) // RTH activation
|
||||
|GET_FLAG(CH9_SW, 0x10); // RTH on/off
|
||||
if(sub_protocol==V761_3CH)
|
||||
packet[6] |= 0x80; // unknown, set on original V761-1 dump but not on eachine dumps, keeping for compatibility
|
||||
|
||||
//packet counter
|
||||
if(packet_count >= 12)
|
||||
@@ -120,22 +143,40 @@ static void __attribute__((unused)) V761_init()
|
||||
|
||||
static void __attribute__((unused)) V761_initialize_txid()
|
||||
{
|
||||
// TODO: try arbitrary rx_tx_addr & frequencies (except hopping_frequency[0])
|
||||
switch(RX_num%3)
|
||||
#ifdef V761_FORCE_ID
|
||||
switch(RX_num%5)
|
||||
{
|
||||
case 1: //Dump from air on Protonus TX
|
||||
memcpy(rx_tx_addr,(uint8_t *)"\xE8\xE4\x45\x09",4);
|
||||
memcpy(hopping_frequency,(uint8_t *)"\x0D\x21\x44",3);
|
||||
memcpy(hopping_frequency,(uint8_t *)"\x0D\x21",2);
|
||||
break;
|
||||
case 2: //Dump from air on mshagg2 TX
|
||||
memcpy(rx_tx_addr,(uint8_t *)"\xAE\xD1\x45\x09",4);
|
||||
memcpy(hopping_frequency,(uint8_t *)"\x13\x1D\x4A",3);
|
||||
memcpy(hopping_frequency,(uint8_t *)"\x13\x1D",2);
|
||||
break;
|
||||
case 3: //Dump from air on MikeHRC Eachine TX
|
||||
memcpy(rx_tx_addr,(uint8_t *)"\x08\x03\x00\xA0",4);
|
||||
memcpy(hopping_frequency,(uint8_t *)"\x0D\x21",2);
|
||||
break;
|
||||
case 4: //Dump from air on Crashanium Eachine TX
|
||||
memcpy(rx_tx_addr,(uint8_t *)"\x58\x08\x00\xA0",4);
|
||||
memcpy(hopping_frequency,(uint8_t *)"\x0D\x31",2);
|
||||
break;
|
||||
default: //Dump from SPI
|
||||
memcpy(rx_tx_addr,(uint8_t *)"\x6f\x2c\xb1\x93",4);
|
||||
memcpy(hopping_frequency,(uint8_t *)"\x14\x1e\x4b",3);
|
||||
memcpy(hopping_frequency,(uint8_t *)"\x14\x1e",2);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
//Tested with Eachine RX
|
||||
rx_tx_addr[0]+=RX_num;
|
||||
hopping_frequency[0]=(rx_tx_addr[0]&0x0F)+0x05;
|
||||
hopping_frequency[1]=hopping_frequency[0]+0x05+(RX_num%0x2D);
|
||||
#endif
|
||||
|
||||
hopping_frequency[2]=hopping_frequency[0]+0x37;
|
||||
|
||||
debugln("ID: %02X %02X %02X %02X , HOP: %02X %02X %02X",rx_tx_addr[0],rx_tx_addr[1],rx_tx_addr[2],rx_tx_addr[3],hopping_frequency[0],hopping_frequency[1],hopping_frequency[2]);
|
||||
}
|
||||
|
||||
uint16_t V761_callback()
|
||||
@@ -185,10 +226,18 @@ uint16_t V761_callback()
|
||||
|
||||
uint16_t initV761(void)
|
||||
{
|
||||
BIND_IN_PROGRESS;
|
||||
bind_counter = V761_BIND_COUNT;
|
||||
V761_initialize_txid();
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
bind_counter = V761_BIND_COUNT;
|
||||
phase = V761_BIND1;
|
||||
}
|
||||
else
|
||||
{
|
||||
XN297_SetTXAddr(rx_tx_addr, 4);
|
||||
phase = V761_DATA;
|
||||
}
|
||||
|
||||
V761_init();
|
||||
hopping_frequency_no = 0;
|
||||
packet_count = 0;
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// compatible with V911S
|
||||
|
||||
#if defined(V911S_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
//#define V911S_ORIGINAL_ID
|
||||
|
||||
#define V911S_PACKET_PERIOD 5000
|
||||
#define V911S_BIND_PACKET_PERIOD 3300
|
||||
#define V911S_INITIAL_WAIT 500
|
||||
#define V911S_PACKET_SIZE 16
|
||||
#define V911S_RF_BIND_CHANNEL 35
|
||||
#define V911S_NUM_RF_CHANNELS 8
|
||||
#define V911S_BIND_COUNT 200
|
||||
|
||||
// flags going to packet[1]
|
||||
#define V911S_FLAG_EXPERT 0x04
|
||||
// flags going to packet[2]
|
||||
#define V911S_FLAG_CALIB 0x01
|
||||
|
||||
static void __attribute__((unused)) V911S_send_packet(uint8_t bind)
|
||||
{
|
||||
if(bind)
|
||||
{
|
||||
packet[0] = 0x42;
|
||||
packet[1] = 0x4E;
|
||||
packet[2] = 0x44;
|
||||
for(uint8_t i=0;i<5;i++)
|
||||
packet[i+3] = rx_tx_addr[i];
|
||||
for(uint8_t i=0;i<8;i++)
|
||||
packet[i+8] = hopping_frequency[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t channel=hopping_frequency_no;
|
||||
if(rf_ch_num&1)
|
||||
{
|
||||
if((hopping_frequency_no&1)==0)
|
||||
channel+=8;
|
||||
channel>>=1;
|
||||
}
|
||||
if(rf_ch_num&2)
|
||||
channel=7-channel;
|
||||
packet[ 0]=(rf_ch_num<<3)|channel;
|
||||
packet[ 1]=V911S_FLAG_EXPERT; // short press on left button
|
||||
packet[ 2]=GET_FLAG(CH5_SW,V911S_FLAG_CALIB); // long press on right button
|
||||
memset(packet+3, 0x00, V911S_PACKET_SIZE - 3);
|
||||
//packet[3..6]=trims TAER signed
|
||||
uint16_t ch=convert_channel_16b_limit(THROTTLE ,0,0x7FF);
|
||||
packet[ 7] = ch;
|
||||
packet[ 8] = ch>>8;
|
||||
ch=convert_channel_16b_limit(AILERON ,0x7FF,0);
|
||||
packet[ 8]|= ch<<3;
|
||||
packet[ 9] = ch>>5;
|
||||
ch=convert_channel_16b_limit(ELEVATOR,0,0x7FF);
|
||||
packet[10] = ch;
|
||||
packet[11] = ch>>8;
|
||||
ch=convert_channel_16b_limit(RUDDER ,0x7FF,0);
|
||||
packet[11]|= ch<<3;
|
||||
packet[12] = ch>>5;
|
||||
}
|
||||
|
||||
// Power on, TX mode, 2byte CRC
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
if (!bind)
|
||||
{
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[channel]);
|
||||
hopping_frequency_no++;
|
||||
hopping_frequency_no&=7; // 8 RF channels
|
||||
}
|
||||
// clear packet status bits and TX FIFO
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
XN297_WritePayload(packet, V911S_PACKET_SIZE);
|
||||
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) V911S_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
XN297_SetTXAddr((uint8_t *)"\x4B\x4E\x42\x4E\x44", 5); // Bind address
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, V911S_RF_BIND_CHANNEL); // Bind channel
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) V911S_initialize_txid()
|
||||
{
|
||||
//channels
|
||||
uint8_t offset=rx_tx_addr[3]%5; // 0-4
|
||||
for(uint8_t i=0;i<V911S_NUM_RF_CHANNELS;i++)
|
||||
hopping_frequency[i]=0x10+i*5+offset;
|
||||
if(!offset) hopping_frequency[0]++;
|
||||
|
||||
// channels order
|
||||
rf_ch_num=random(0xfefefefe)&0x03; // 0-3
|
||||
}
|
||||
|
||||
uint16_t V911S_callback()
|
||||
{
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(V911S_PACKET_PERIOD);
|
||||
#endif
|
||||
V911S_send_packet(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bind_counter == 0)
|
||||
{
|
||||
BIND_DONE;
|
||||
XN297_SetTXAddr(rx_tx_addr, 5);
|
||||
packet_period=V911S_PACKET_PERIOD;
|
||||
}
|
||||
else
|
||||
{
|
||||
V911S_send_packet(1);
|
||||
bind_counter--;
|
||||
if(bind_counter==100) // same as original TX...
|
||||
packet_period=V911S_BIND_PACKET_PERIOD*3;
|
||||
}
|
||||
}
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
uint16_t initV911S(void)
|
||||
{
|
||||
V911S_initialize_txid();
|
||||
#ifdef V911S_ORIGINAL_ID
|
||||
rx_tx_addr[0]=0xA5;
|
||||
rx_tx_addr[1]=0xFF;
|
||||
rx_tx_addr[2]=0x70;
|
||||
rx_tx_addr[3]=0x8D;
|
||||
rx_tx_addr[4]=0x76;
|
||||
for(uint8_t i=0;i<V911S_NUM_RF_CHANNELS;i++)
|
||||
hopping_frequency[i]=0x10+i*5;
|
||||
hopping_frequency[0]++;
|
||||
rf_ch_num=0;
|
||||
#endif
|
||||
|
||||
V911S_init();
|
||||
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
bind_counter = V911S_BIND_COUNT;
|
||||
packet_period= V911S_BIND_PACKET_PERIOD;
|
||||
}
|
||||
else
|
||||
{
|
||||
XN297_SetTXAddr(rx_tx_addr, 5);
|
||||
packet_period= V911S_PACKET_PERIOD;
|
||||
}
|
||||
hopping_frequency_no=0;
|
||||
return V911S_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -14,9 +14,9 @@
|
||||
*/
|
||||
// compatible with V911S
|
||||
|
||||
#if defined(V911S_XN297L_INO)
|
||||
#if defined(V911S_NRF24L01_INO)
|
||||
|
||||
#include "iface_xn297l.h"
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
//#define V911S_ORIGINAL_ID
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
// flags going to packet[1]
|
||||
#define V911S_FLAG_EXPERT 0x04
|
||||
#define E119_FLAG_EXPERT 0x08
|
||||
#define E119_FLAG_CALIB 0x40
|
||||
// flags going to packet[2]
|
||||
#define V911S_FLAG_CALIB 0x01
|
||||
|
||||
@@ -56,10 +58,21 @@ static void __attribute__((unused)) V911S_send_packet(uint8_t bind)
|
||||
}
|
||||
if(rf_ch_num&2)
|
||||
channel=7-channel;
|
||||
XN297L_Hopping(channel);
|
||||
hopping_frequency_no++;
|
||||
hopping_frequency_no&=7; // 8 RF channels
|
||||
|
||||
packet[ 0]=(rf_ch_num<<3)|channel;
|
||||
memset(packet+1, 0x00, V911S_PACKET_SIZE - 1);
|
||||
if(sub_protocol==V911S_STD)
|
||||
{
|
||||
packet[ 1]=V911S_FLAG_EXPERT; // short press on left button
|
||||
packet[ 2]=GET_FLAG(CH5_SW,V911S_FLAG_CALIB); // long press on right button
|
||||
memset(packet+3, 0x00, V911S_PACKET_SIZE - 3);
|
||||
}
|
||||
else
|
||||
packet[ 1]=E119_FLAG_EXPERT // short press on left button
|
||||
|GET_FLAG(CH5_SW,E119_FLAG_CALIB); // short press on right button
|
||||
|
||||
//packet[3..6]=trims TAER signed
|
||||
uint16_t ch=convert_channel_16b_limit(THROTTLE ,0,0x7FF);
|
||||
packet[ 7] = ch;
|
||||
@@ -68,21 +81,30 @@ static void __attribute__((unused)) V911S_send_packet(uint8_t bind)
|
||||
packet[ 8]|= ch<<3;
|
||||
packet[ 9] = ch>>5;
|
||||
ch=convert_channel_16b_limit(ELEVATOR,0,0x7FF);
|
||||
if(sub_protocol==V911S_STD)
|
||||
{
|
||||
packet[10] = ch;
|
||||
packet[11] = ch>>8;
|
||||
ch=convert_channel_16b_limit(RUDDER ,0x7FF,0);
|
||||
packet[11]|= ch<<3;
|
||||
packet[12] = ch>>5;
|
||||
}
|
||||
|
||||
if (!bind)
|
||||
else
|
||||
{
|
||||
XN297L_Hopping(channel);
|
||||
hopping_frequency_no++;
|
||||
hopping_frequency_no&=7; // 8 RF channels
|
||||
ch=0x7FF-ch;
|
||||
packet[ 9]|= ch<<6;
|
||||
packet[10] = ch>>2;
|
||||
packet[11] = ch>>10;
|
||||
ch=convert_channel_16b_limit(RUDDER ,0x7FF,0);
|
||||
packet[11]|= ch<<1;
|
||||
packet[12] = ch>>7;
|
||||
}
|
||||
}
|
||||
|
||||
if(sub_protocol==V911S_STD)
|
||||
XN297L_WritePayload(packet, V911S_PACKET_SIZE);
|
||||
else
|
||||
XN297L_WriteEnhancedPayload(packet, V911S_PACKET_SIZE, bind?0:1);
|
||||
|
||||
XN297L_SetPower(); // Set tx_power
|
||||
XN297L_SetFreqOffset(); // Set frequency offset
|
||||
@@ -91,7 +113,10 @@ static void __attribute__((unused)) V911S_send_packet(uint8_t bind)
|
||||
static void __attribute__((unused)) V911S_init()
|
||||
{
|
||||
XN297L_Init();
|
||||
XN297L_SetTXAddr((uint8_t *)"KNBND",5); // Bind address
|
||||
if(sub_protocol==V911S_STD)
|
||||
XN297L_SetTXAddr((uint8_t *)"KNBND",5); // V911S Bind address
|
||||
else
|
||||
XN297L_SetTXAddr((uint8_t *)"XPBND",5); // E119 Bind address
|
||||
XN297L_HoppingCalib(V911S_NUM_RF_CHANNELS); // Calibrate all channels
|
||||
XN297L_RFChannel(V911S_RF_BIND_CHANNEL); // Set bind channel
|
||||
}
|
||||
@@ -140,6 +165,8 @@ uint16_t initV911S(void)
|
||||
{
|
||||
V911S_initialize_txid();
|
||||
#ifdef V911S_ORIGINAL_ID
|
||||
if(sub_protocol==V911S_STD)
|
||||
{//V911S
|
||||
rx_tx_addr[0]=0xA5;
|
||||
rx_tx_addr[1]=0xFF;
|
||||
rx_tx_addr[2]=0x70;
|
||||
@@ -149,6 +176,19 @@ uint16_t initV911S(void)
|
||||
hopping_frequency[i]=0x10+i*5;
|
||||
hopping_frequency[0]++;
|
||||
rf_ch_num=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//E119
|
||||
rx_tx_addr[0]=0x30;
|
||||
rx_tx_addr[1]=0xFF;
|
||||
rx_tx_addr[2]=0xD1;
|
||||
rx_tx_addr[3]=0x2C;
|
||||
rx_tx_addr[4]=0x2A;
|
||||
for(uint8_t i=0;i<V911S_NUM_RF_CHANNELS;i++)
|
||||
hopping_frequency[i]=0x0E + i*5;
|
||||
rf_ch_num=0;
|
||||
}
|
||||
#endif
|
||||
|
||||
V911S_init();
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
#endif
|
||||
#if not defined (ORANGE_TX) && not defined (STM32_BOARD)
|
||||
//Atmega328p
|
||||
#if not defined(ARDUINO_AVR_PRO) && not defined(ARDUINO_MULTI_NO_BOOT) && not defined(ARDUINO_MULTI_FLASH_FROM_TX) && not defined(ARDUINO_AVR_MINI) && not defined(ARDUINO_AVR_NANO)
|
||||
#if not defined(ARDUINO_AVR_PRO) && not defined(ARDUINO_MULTI_NO_BOOT) && not defined(ARDUINO_MULTI_FLASH_FROM_TX) && not defined(ARDUINO_AVR_MINI) && not defined(ARDUINO_AVR_NANO) && not defined(ARDUINO_AVR_DUEMILANOVE)
|
||||
#error You must select one of these boards: "Multi 4-in-1", "Arduino Pro or Pro Mini" or "Arduino Mini"
|
||||
#endif
|
||||
#if F_CPU != 16000000L || not defined(__AVR_ATmega328P__)
|
||||
#if F_CPU != 16000000L || not (defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__))
|
||||
#error You must select the processor type "ATmega328(5V, 16MHz)"
|
||||
#endif
|
||||
#endif
|
||||
@@ -79,6 +79,11 @@
|
||||
#error "The FrSkyD forced frequency tuning value is outside of the range -127..127."
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FORCE_FRSKYL_TUNING
|
||||
#if ( FORCE_FRSKYL_TUNING < -127 ) || ( FORCE_FRSKYL_TUNING > 127 )
|
||||
#error "The FrSkyL forced frequency tuning value is outside of the range -127..127."
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FORCE_FRSKYV_TUNING
|
||||
#if ( FORCE_FRSKYV_TUNING < -127 ) || ( FORCE_FRSKYV_TUNING > 127 )
|
||||
#error "The FrSkyV forced frequency tuning value is outside of the range -127..127."
|
||||
@@ -94,19 +99,29 @@
|
||||
#error "The HITEC forced frequency tuning value is outside of the range -127..127."
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FORCE_HOTT_TUNING
|
||||
#if ( FORCE_HOTT_TUNING < -127 ) || ( FORCE_HOTT_TUNING > 127 )
|
||||
#error "The HOTT forced frequency tuning value is outside of the range -127..127."
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FORCE_REDPINE_TUNING
|
||||
#if ( FORCE_REDPINE_TUNING < -127 ) || ( FORCE_REDPINE_TUNING > 127 )
|
||||
#error "The REDPINE forced frequency tuning value is outside of the range -127..127."
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FORCE_SFHSS_TUNING
|
||||
#if ( FORCE_SFHSS_TUNING < -127 ) || ( FORCE_SFHSS_TUNING > 127 )
|
||||
#error "The SFHSS forced frequency tuning value is outside of the range -127..127."
|
||||
#ifdef FORCE_RADIOLINK_TUNING
|
||||
#if ( FORCE_RADIOLINK_TUNING < -127 ) || ( FORCE_RADIOLINK_TUNING > 127 )
|
||||
#error "The RADIOLINK forced frequency tuning value is outside of the range -127..127."
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FORCE_HOTT_TUNING
|
||||
#if ( FORCE_HOTT_TUNING < -127 ) || ( FORCE_HOTT_TUNING > 127 )
|
||||
#error "The HOTT forced frequency tuning value is outside of the range -127..127."
|
||||
#ifdef FORCE_FUTABA_TUNING
|
||||
#if ( FORCE_FUTABA_TUNING < -127 ) || ( FORCE_FUTABA_TUNING > 127 )
|
||||
#error "The Futaba forced frequency tuning value is outside of the range -127..127."
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FORCE_SKYARTEC_TUNING
|
||||
#if ( FORCE_SKYARTEC_TUNING < -127 ) || ( FORCE_SKYARTEC_TUNING > 127 )
|
||||
#error "The SKYARTEC forced frequency tuning value is outside of the range -127..127."
|
||||
#endif
|
||||
#endif
|
||||
//A7105
|
||||
@@ -125,9 +140,14 @@
|
||||
#error "The Flysky forced frequency tuning value is outside of the range -300..300."
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FORCE_FLYZONE_TUNING
|
||||
#if ( FORCE_FLYZONE_TUNING < -300 ) || ( FORCE_FLYZONE_TUNING > 300 )
|
||||
#error "The Flyzone forced frequency tuning value is outside of the range -300..300."
|
||||
#ifdef FORCE_HEIGHT_TUNING
|
||||
#if ( FORCE_HEIGHT_TUNING < -300 ) || ( FORCE_HEIGHT_TUNING > 300 )
|
||||
#error "The Height forced frequency tuning value is outside of the range -300..300."
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FORCE_PELIKAN_TUNING
|
||||
#if ( FORCE_PELIKAN_TUNING < -300 ) || ( FORCE_PELIKAN_TUNING > 300 )
|
||||
#error "The Pelikan forced frequency tuning value is outside of the range -300..300."
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FORCE_HUBSAN_TUNING
|
||||
@@ -135,6 +155,11 @@
|
||||
#error "The Hubsan forced frequency tuning value is outside of the range -300..300."
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FORCE_KYOSHO_TUNING
|
||||
#if ( FORCE_KYOSHO_TUNING < -300 ) || ( FORCE_KYOSHO_TUNING > 300 )
|
||||
#error "The Kyosho forced frequency tuning value is outside of the range -300..300."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef USE_A7105_CH15_TUNING
|
||||
#ifndef FORCE_BUGS_TUNING
|
||||
@@ -143,8 +168,14 @@
|
||||
#ifndef FORCE_FLYSKY_TUNING
|
||||
#define FORCE_FLYSKY_TUNING 0
|
||||
#endif
|
||||
#ifndef FORCE_FLYZONE_TUNING
|
||||
#define FORCE_FLYZONE_TUNING 0
|
||||
#ifndef FORCE_HEIGHT_TUNING
|
||||
#define FORCE_HEIGHT_TUNING 0
|
||||
#endif
|
||||
#ifndef FORCE_PELIKAN_TUNING
|
||||
#define FORCE_PELIKAN_TUNING 0
|
||||
#endif
|
||||
#ifndef FORCE_KYOSHO_TUNING
|
||||
#define FORCE_KYOSHO_TUNING 0
|
||||
#endif
|
||||
#ifndef FORCE_HUBSAN_TUNING
|
||||
#define FORCE_HUBSAN_TUNING 0
|
||||
@@ -167,79 +198,119 @@
|
||||
#undef CC25_CSN_pin
|
||||
#undef NRF24L01_INSTALLED // Disable NRF for OrangeTX module
|
||||
#undef NRF_CSN_pin
|
||||
#undef SX1276_INSTALLED // Disable SX1276 for OrangeTX module
|
||||
#define TELEMETRY // Enable telemetry
|
||||
#define INVERT_TELEMETRY // Enable invert telemetry
|
||||
#define DSM_TELEMETRY // Enable DSM telemetry
|
||||
#endif
|
||||
|
||||
//Change/Force RF chip configuration if MULTI_5IN1_INTERNAL
|
||||
#ifdef MULTI_5IN1_INTERNAL
|
||||
#if not defined(STM32_BOARD)
|
||||
#error "Error MULTI_5IN1_INTERNAL is only for STM32 boards."
|
||||
#endif
|
||||
#define A7105_INSTALLED
|
||||
#define CYRF6936_INSTALLED
|
||||
#define CC2500_INSTALLED
|
||||
#define NRF24L01_INSTALLED
|
||||
#define SX1276_INSTALLED
|
||||
#undef ENABLE_PPM
|
||||
#endif
|
||||
|
||||
//Make sure protocols are selected correctly
|
||||
#ifndef A7105_INSTALLED
|
||||
#undef FLYSKY_A7105_INO
|
||||
#undef HUBSAN_A7105_INO
|
||||
#undef AFHDS2A_A7105_INO
|
||||
#undef BUGS_A7105_INO
|
||||
#undef FLYZONE_A7105_INO
|
||||
#undef AFHDS2A_RX_A7105_INO
|
||||
#undef BUGS_A7105_INO
|
||||
#undef FLYSKY_A7105_INO
|
||||
#undef HEIGHT_A7105_INO
|
||||
#undef HUBSAN_A7105_INO
|
||||
#undef KYOSHO_A7105_INO
|
||||
#undef PELIKAN_A7105_INO
|
||||
#endif
|
||||
#ifndef CYRF6936_INSTALLED
|
||||
#undef DEVO_CYRF6936_INO
|
||||
#undef DSM_CYRF6936_INO
|
||||
#undef HOTT_CC2500_INO
|
||||
#undef DSM_RX_CYRF6936_INO
|
||||
#undef J6PRO_CYRF6936_INO
|
||||
#undef MLINK_CYRF6936_INO
|
||||
#undef TRAXXAS_CYRF6936_INO
|
||||
#undef WFLY_CYRF6936_INO
|
||||
#undef WK2x01_CYRF6936_INO
|
||||
#undef TRAXXAS_CYRF6936_INO
|
||||
#endif
|
||||
#ifndef CC2500_INSTALLED
|
||||
#undef CORONA_CC2500_INO
|
||||
#undef ESKY150V2_CC2500_INO
|
||||
#undef FRSKYD_CC2500_INO
|
||||
#undef FRSKYL_CC2500_INO
|
||||
#undef FRSKYV_CC2500_INO
|
||||
#undef FRSKYX_CC2500_INO
|
||||
#undef SFHSS_CC2500_INO
|
||||
#undef CORONA_CC2500_INO
|
||||
#undef REDPINE_CC2500_INO
|
||||
#undef HITEC_CC2500_INO
|
||||
#undef XN297L_CC2500_EMU
|
||||
#undef SCANNER_CC2500_INO
|
||||
#undef FRSKY_RX_CC2500_INO
|
||||
#undef HITEC_CC2500_INO
|
||||
#undef HOTT_CC2500_INO
|
||||
#undef OMP_CC2500_INO
|
||||
#undef REDPINE_CC2500_INO
|
||||
#undef RLINK_CC2500_INO
|
||||
#undef SCANNER_CC2500_INO
|
||||
#undef FUTABA_CC2500_INO
|
||||
#undef SKYARTEC_CC2500_INO
|
||||
#endif
|
||||
#ifndef NRF24L01_INSTALLED
|
||||
#undef ASSAN_NRF24L01_INO
|
||||
#undef BAYANG_NRF24L01_INO
|
||||
#undef BAYANG_RX_NRF24L01_INO
|
||||
#undef BUGSMINI_NRF24L01_INO
|
||||
#undef CABELL_NRF24L01_INO
|
||||
#undef CFLIE_NRF24L01_INO
|
||||
#undef CG023_NRF24L01_INO
|
||||
#undef CX10_NRF24L01_INO
|
||||
#undef DM002_NRF24L01_INO
|
||||
#undef E01X_NRF24L01_INO
|
||||
#undef ESKY_NRF24L01_INO
|
||||
#undef HISKY_NRF24L01_INO
|
||||
#undef KF606_NRF24L01_INO
|
||||
#undef KN_NRF24L01_INO
|
||||
#undef SLT_NRF24L01_INO
|
||||
#undef SYMAX_NRF24L01_INO
|
||||
#undef V2X2_NRF24L01_INO
|
||||
#undef YD717_NRF24L01_INO
|
||||
#undef MT99XX_NRF24L01_INO
|
||||
#undef MJXQ_NRF24L01_INO
|
||||
#undef SHENQI_NRF24L01_INO
|
||||
#undef ESKY150_NRF24L01_INO
|
||||
#undef ESKY150V2_CC2500_INO // Use both CC2500 and NRF code
|
||||
#undef FQ777_NRF24L01_INO
|
||||
#undef FX816_NRF24L01_INO
|
||||
#undef FY326_NRF24L01_INO
|
||||
#undef FQ777_NRF24L01_INO
|
||||
#undef ASSAN_NRF24L01_INO
|
||||
#undef HONTAI_NRF24L01_INO
|
||||
#undef Q303_NRF24L01_INO
|
||||
#undef GW008_NRF24L01_INO
|
||||
#undef GD00X_NRF24L01_INO
|
||||
#undef DM002_NRF24L01_INO
|
||||
#undef CABELL_NRF24L01_INO
|
||||
#undef ESKY150_NRF24L01_INO
|
||||
#undef GW008_NRF24L01_INO
|
||||
#undef H8_3D_NRF24L01_INO
|
||||
#undef CFLIE_NRF24L01_INO
|
||||
#undef BUGSMINI_NRF24L01_INO
|
||||
#undef HISKY_NRF24L01_INO
|
||||
#undef HONTAI_NRF24L01_INO
|
||||
#undef JJRC345_NRF24L01_INO
|
||||
#undef KF606_NRF24L01_INO
|
||||
#undef KN_NRF24L01_INO
|
||||
#undef MJXQ_NRF24L01_INO
|
||||
#undef MT99XX_NRF24L01_INO
|
||||
#undef NCC1701_NRF24L01_INO
|
||||
#undef E01X_NRF24L01_INO
|
||||
#undef OMP_CC2500_INO
|
||||
#undef POTENSIC_NRF24L01_INO
|
||||
#undef PROPEL_NRF24L01_INO
|
||||
#undef Q303_NRF24L01_INO
|
||||
#undef Q90C_NRF24L01_INO
|
||||
#undef REALACC_NRF24L01_INO
|
||||
#undef SHENQI_NRF24L01_INO
|
||||
#undef SLT_NRF24L01_INO
|
||||
#undef SYMAX_NRF24L01_INO
|
||||
#undef TIGER_NRF24L01_INO
|
||||
#undef V2X2_NRF24L01_INO
|
||||
#undef V761_NRF24L01_INO
|
||||
#undef V911S_NRF24L01_INO
|
||||
#undef XN297L_CC2500_EMU
|
||||
#undef POTENSIC_NRF24L01_INO
|
||||
#undef XK_NRF24L01_INO
|
||||
#undef YD717_NRF24L01_INO
|
||||
#undef ZSX_NRF24L01_INO
|
||||
#undef BAYANG_RX_NRF24L01_INO
|
||||
#endif
|
||||
#if not defined(STM32_BOARD)
|
||||
#undef SX1276_INSTALLED
|
||||
#endif
|
||||
#ifndef SX1276_INSTALLED
|
||||
#undef FRSKYR9_SX1276_INO
|
||||
#endif
|
||||
|
||||
//OpenTX 2.3.x issue
|
||||
#if defined (FRSKYD_CC2500_INO) || defined(FRSKYV_CC2500_INO) || defined(FRSKYX_CC2500_INO)
|
||||
#define FRSKYX_CC2500_INO
|
||||
#define FRSKY_RX_CC2500_INO
|
||||
#endif
|
||||
|
||||
//Make sure telemetry is selected correctly
|
||||
@@ -269,6 +340,12 @@
|
||||
#undef HOTT_FW_TELEMETRY
|
||||
#undef BAYANG_RX_TELEMETRY
|
||||
#undef BAYANG_RX_NRF24L01_INO
|
||||
#undef DEVO_HUB_TELEMETRY
|
||||
#undef PROPEL_HUB_TELEMETRY
|
||||
#undef OMP_HUB_TELEMETRY
|
||||
#undef RLINK_HUB_TELEMETRY
|
||||
#undef DSM_RX_CYRF6936_INO
|
||||
#undef DSM_FWD_PGM
|
||||
#else
|
||||
#if defined(MULTI_TELEMETRY) && defined(MULTI_STATUS)
|
||||
#error You should choose either MULTI_TELEMETRY or MULTI_STATUS but not both.
|
||||
@@ -292,6 +369,15 @@
|
||||
#if not defined(BAYANG_NRF24L01_INO)
|
||||
#undef BAYANG_HUB_TELEMETRY
|
||||
#endif
|
||||
#if not defined(DEVO_CYRF6936_INO)
|
||||
#undef DEVO_HUB_TELEMETRY
|
||||
#endif
|
||||
#if not defined(OMP_CC2500_INO)
|
||||
#undef OMP_HUB_TELEMETRY
|
||||
#endif
|
||||
#if not defined(PROPEL_NRF24L01_INO)
|
||||
#undef PROPEL_HUB_TELEMETRY
|
||||
#endif
|
||||
#if not defined(NCC1701_NRF24L01_INO)
|
||||
#undef NCC1701_HUB_TELEMETRY
|
||||
#endif
|
||||
@@ -301,6 +387,9 @@
|
||||
#if not defined(CABELL_NRF24L01_INO)
|
||||
#undef CABELL_HUB_TELEMETRY
|
||||
#endif
|
||||
#if not defined(RLINK_CC2500_INO)
|
||||
#undef RLINK_HUB_TELEMETRY
|
||||
#endif
|
||||
#if not defined(HUBSAN_A7105_INO)
|
||||
#undef HUBSAN_HUB_TELEMETRY
|
||||
#endif
|
||||
@@ -315,7 +404,7 @@
|
||||
#if not defined(FRSKYD_CC2500_INO)
|
||||
#undef HUB_TELEMETRY
|
||||
#endif
|
||||
#if not defined(FRSKYX_CC2500_INO)
|
||||
#if not defined(FRSKYX_CC2500_INO) && not defined(FRSKYR9_SX1276_INO)
|
||||
#undef SPORT_TELEMETRY
|
||||
#undef SPORT_SEND
|
||||
#endif
|
||||
@@ -328,7 +417,7 @@
|
||||
#if not defined(HOTT_CC2500_INO)
|
||||
#undef HOTT_FW_TELEMETRY
|
||||
#endif
|
||||
#if not defined(HOTT_FW_TELEMETRY) && not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BUGS_HUB_TELEMETRY) && not defined(NCC1701_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS) && not defined(HITEC_HUB_TELEMETRY) && not defined(HITEC_FW_TELEMETRY) && not defined(SCANNER_TELEMETRY) && not defined(FRSKY_RX_TELEMETRY) && not defined(AFHDS2A_RX_TELEMETRY) && not defined(BAYANG_RX_TELEMETRY)
|
||||
#if not defined(HOTT_FW_TELEMETRY) && not defined(DSM_TELEMETRY) && not defined(SPORT_TELEMETRY) && not defined(HUB_TELEMETRY) && not defined(HUBSAN_HUB_TELEMETRY) && not defined(BUGS_HUB_TELEMETRY) && not defined(NCC1701_HUB_TELEMETRY) && not defined(BAYANG_HUB_TELEMETRY) && not defined(CABELL_HUB_TELEMETRY) && not defined(RLINK_HUB_TELEMETRY) && not defined(AFHDS2A_HUB_TELEMETRY) && not defined(AFHDS2A_FW_TELEMETRY) && not defined(MULTI_TELEMETRY) && not defined(MULTI_STATUS) && not defined(HITEC_HUB_TELEMETRY) && not defined(HITEC_FW_TELEMETRY) && not defined(SCANNER_TELEMETRY) && not defined(FRSKY_RX_TELEMETRY) && not defined(AFHDS2A_RX_TELEMETRY) && not defined(BAYANG_RX_TELEMETRY) && not defined(DEVO_HUB_TELEMETRY) && not defined(PROPEL_HUB_TELEMETRY) && not defined(OMP_HUB_TELEMETRY)
|
||||
#undef TELEMETRY
|
||||
#undef INVERT_TELEMETRY
|
||||
#undef MULTI_TELEMETRY
|
||||
@@ -347,9 +436,7 @@
|
||||
#if not defined(MULTI_TELEMETRY)
|
||||
#undef MULTI_SYNC
|
||||
#undef MULTI_NAMES
|
||||
#endif
|
||||
|
||||
#if defined(MULTI_TELEMETRY)
|
||||
#else
|
||||
#define MULTI_NAMES
|
||||
#endif
|
||||
|
||||
@@ -404,3 +491,18 @@
|
||||
#if defined (STM32_BOARD) && defined (DEBUG_SERIAL) && defined (NRF24L01_INSTALLED)
|
||||
#define XN297DUMP_NRF24L01_INO
|
||||
#endif
|
||||
|
||||
//Check if Direct inputs defined correctly
|
||||
#if defined (ENABLE_DIRECT_INPUTS)
|
||||
#if not defined (STM32_BOARD) || not defined (ENABLE_PPM) || defined (ENABLE_SERIAL)
|
||||
#error You can enable dirct inputs only in PPM mode and only for STM32 board.
|
||||
#endif
|
||||
|
||||
#if not defined (DI1_PIN) && not defined (DI2_PIN) && not defined (DI3_PIN) && not defined (DI4_PIN)
|
||||
#error You must define at least 1 direct input pin or undefine ENABLE_DIRECT_INPUTS in config.
|
||||
#endif
|
||||
|
||||
#if not defined (DI_CH1_read) && not defined (DI_CH2_read) && not defined (DI_CH3_read) && not defined (DI_CH4_read)
|
||||
#error You must define at least 1 direct input chanell read macros or undefine ENABLE_DIRECT_INPUTS in config.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
227
Multiprotocol/XK_nrf24l01.ino
Normal file
227
Multiprotocol/XK_nrf24l01.ino
Normal file
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Compatible with X450 and X420/X520 plane.
|
||||
|
||||
#if defined(XK_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
//#define FORCE_XK_ORIGINAL_ID
|
||||
|
||||
#define XK_INITIAL_WAIT 500
|
||||
#define XK_PACKET_PERIOD 4000
|
||||
#define XK_RF_BIND_NUM_CHANNELS 8
|
||||
#define XK_RF_NUM_CHANNELS 4
|
||||
#define XK_PAYLOAD_SIZE 16
|
||||
#define XK_BIND_COUNT 750 //3sec
|
||||
|
||||
static uint16_t __attribute__((unused)) XK_convert_channel(uint8_t num)
|
||||
{
|
||||
uint16_t val;
|
||||
if(num==RUDDER)
|
||||
{// introduce deadband on rudder to prevent twitching
|
||||
//debug("RUD:%d",val);
|
||||
val=convert_channel_8b_limit_deadband(RUDDER,0x00,0x80, 0xFF, 40)<<2;
|
||||
//debugln(",%d",val);
|
||||
}
|
||||
else
|
||||
val=convert_channel_10b(num);
|
||||
|
||||
// 1FF..01=left, 00=center, 200..3FF=right
|
||||
if(val==0x200)
|
||||
val=0; // 0
|
||||
else
|
||||
if(val>0x200)
|
||||
val--; // 200..3FE
|
||||
else
|
||||
{
|
||||
val=0x200-val; // 200..01
|
||||
if(val==0x200)
|
||||
val--; // 1FF..01
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XK_send_packet()
|
||||
{
|
||||
memset(packet,0x00,7);
|
||||
memset(&packet[10],0x00,5);
|
||||
|
||||
packet[12]=0x40;
|
||||
packet[13]=0x40;
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
packet[14] = 0xC0;
|
||||
else
|
||||
{
|
||||
uint16_t val=convert_channel_10b(THROTTLE);
|
||||
packet[0] = val>>2; // 0..255
|
||||
packet[12] |= val & 2;
|
||||
val=XK_convert_channel(RUDDER);
|
||||
packet[1] = val>>2;
|
||||
packet[12] |= (val & 2)<<2;
|
||||
val=XK_convert_channel(ELEVATOR);
|
||||
packet[2] = val>>2;
|
||||
packet[13] |= val & 2;
|
||||
val=XK_convert_channel(AILERON);
|
||||
packet[3] = val>>2;
|
||||
packet[13] |= (val & 2)<<2;
|
||||
|
||||
memset(&packet[4],0x40,3); // Trims
|
||||
|
||||
if(Channel_data[CH5] > CHANNEL_MAX_COMMAND)
|
||||
packet[10] = 0x10; // V-Mode
|
||||
else
|
||||
if(Channel_data[CH5] > CHANNEL_MIN_COMMAND)
|
||||
packet[10] = 0x04; // 6G-Mode
|
||||
//0x00 default M-Mode
|
||||
|
||||
packet[10] |= GET_FLAG(CH7_SW,0x80); // Emergency stop momentary switch
|
||||
|
||||
packet[11] = GET_FLAG(CH8_SW,0x03) // 3D/6G momentary switch
|
||||
|GET_FLAG(CH6_SW,0x40); // Take off momentary switch
|
||||
packet[14] = GET_FLAG(CH9_SW,0x01) // Photo momentary switch
|
||||
|GET_FLAG(CH10_SW,0x2); // Video momentary switch
|
||||
//debugln("P1:%02X,P12:%02X",packet[1],packet[12]);
|
||||
}
|
||||
|
||||
crc=packet[0];
|
||||
for(uint8_t i=1; i<XK_PAYLOAD_SIZE-1;i++)
|
||||
crc+=packet[i];
|
||||
packet[15]=crc;
|
||||
|
||||
// debug("C: %02X, P:",hopping_frequency[(IS_BIND_IN_PROGRESS?0:XK_RF_BIND_NUM_CHANNELS)+(hopping_frequency_no>>1)]);
|
||||
XN297L_Hopping((IS_BIND_IN_PROGRESS?0:XK_RF_BIND_NUM_CHANNELS)+(hopping_frequency_no>>1));
|
||||
hopping_frequency_no++;
|
||||
if(hopping_frequency_no >= (IS_BIND_IN_PROGRESS?XK_RF_BIND_NUM_CHANNELS*2:XK_RF_NUM_CHANNELS*2))
|
||||
hopping_frequency_no=0;
|
||||
|
||||
XN297L_WritePayload(packet, XK_PAYLOAD_SIZE);
|
||||
// for(uint8_t i=0; i<XK_PAYLOAD_SIZE; i++)
|
||||
// debug(" %02X",packet[i]);
|
||||
// debugln("");
|
||||
|
||||
XN297L_SetPower(); // Set tx_power
|
||||
XN297L_SetFreqOffset(); // Set frequency offset
|
||||
}
|
||||
|
||||
const uint8_t PROGMEM XK_bind_hop[XK_RF_BIND_NUM_CHANNELS]= { 0x07, 0x24, 0x3E, 0x2B, 0x47, 0x0E, 0x39, 0x1C }; // Bind
|
||||
|
||||
const uint8_t PROGMEM XK_tx_addr[]= { 0xB3, 0x67, 0xE9, 0x98, 0x3A, 0xEC, 0xA6, 0x59, 0xB2, 0x94, 0x2B, 0xA5, 0x37, 0xC5, 0x4A, 0xD3,
|
||||
0x49, 0xA6, 0x83, 0xEB, 0x4B, 0xC9, 0x59, 0xD2, 0x65, 0x34, 0x6A, 0xD3, 0x2C, 0x96, 0x2A, 0xA9,
|
||||
0x32, 0xB2, 0xB4, 0x49, 0xD3, 0x37, 0xE9 };
|
||||
|
||||
const uint8_t PROGMEM XK_hop[]= { 0x47, 0x3A, 0x4C, 0x39, 0x4D, 0x34, 0x4A, 0x3F, 0x45, 0x3E, 0x4B, 0x3D, 0x3B, 0x48, 0x40, 0x49,
|
||||
0x46, 0x3C, 0x43, 0x38, 0x35, 0x42, 0x33, 0x44, 0x4E, 0x37, 0x44, 0x35, 0x37, 0x4E, 0x36, 0x41 };
|
||||
|
||||
static void __attribute__((unused)) XK_initialize_txid()
|
||||
{
|
||||
//bind hop
|
||||
for(uint8_t i=0; i<XK_RF_BIND_NUM_CHANNELS; i++)
|
||||
hopping_frequency[i]=pgm_read_byte_near( &XK_bind_hop[i] );
|
||||
|
||||
//GID
|
||||
packet[7]=rx_tx_addr[1];
|
||||
packet[8]=rx_tx_addr[2];
|
||||
packet[9]=rx_tx_addr[3];
|
||||
uint8_t sum=packet[7]+packet[8]+packet[9];
|
||||
// debugln("GID=%02X %02X %02X, sum=%d", packet[7],packet[8],packet[9],sum);
|
||||
|
||||
//Normal hop
|
||||
uint8_t start=(sum&0x07)<<2;
|
||||
// debug("start=%d, hop=",start);
|
||||
for(uint8_t i=0; i<XK_RF_NUM_CHANNELS; i++)
|
||||
{
|
||||
hopping_frequency[ i + XK_RF_BIND_NUM_CHANNELS ]=pgm_read_byte_near( &XK_hop[ start + i ] );
|
||||
// debug("%02X ", hopping_frequency[ i + XK_RF_BIND_NUM_CHANNELS ]);
|
||||
}
|
||||
// debugln("");
|
||||
//Normal packet address
|
||||
start=(sum&0x1F)+((sum>>5)&0x03);
|
||||
// debug("start=%d, addr=",start);
|
||||
for(uint8_t i=0; i<5; i++)
|
||||
{
|
||||
rx_tx_addr[i]=pgm_read_byte_near( &XK_tx_addr[ start + i ] );
|
||||
// debug("%02X ", rx_tx_addr[ i ]);
|
||||
}
|
||||
// debugln("");
|
||||
|
||||
#ifdef FORCE_XK_ORIGINAL_ID
|
||||
switch(RX_num%2)
|
||||
{
|
||||
default:
|
||||
//TX1 X8 X450
|
||||
//GID
|
||||
packet[7]=0x04;
|
||||
packet[8]=0x15;
|
||||
packet[9]=0x22;
|
||||
//Normal hop
|
||||
memcpy(&hopping_frequency[XK_RF_BIND_NUM_CHANNELS],(uint8_t*)"\x3B\x48\x40\x49", XK_RF_NUM_CHANNELS); // freq and order verified
|
||||
//Normal packet address
|
||||
memcpy(rx_tx_addr,(uint8_t*)"\x2C\x96\x2A\xA9\x32",5);
|
||||
break;
|
||||
case 1:
|
||||
//TX2 X4 X420
|
||||
//GID
|
||||
packet[7]=0x13;
|
||||
packet[8]=0x24;
|
||||
packet[9]=0x18;
|
||||
//Normal hop
|
||||
memcpy(&hopping_frequency[XK_RF_BIND_NUM_CHANNELS],(uint8_t*)"\x36\x41\x37\x4E", XK_RF_NUM_CHANNELS); // freq ok and order from xn297dump auto
|
||||
//Normal packet address
|
||||
memcpy(rx_tx_addr,(uint8_t*)"\xA6\x83\xEB\x4B\xC9",5);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XK_init()
|
||||
{
|
||||
XN297L_Init();
|
||||
XN297L_SetTXAddr((uint8_t*)"\x68\x94\xA6\xD5\xC3", 5); // Bind address
|
||||
XN297L_HoppingCalib(XK_RF_BIND_NUM_CHANNELS+XK_RF_NUM_CHANNELS); // Calibrate all channels
|
||||
}
|
||||
|
||||
uint16_t XK_callback()
|
||||
{
|
||||
if(sub_protocol==X420)
|
||||
option=0; // Forcing the use of NRF24L01@1Mbps
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(XK_PACKET_PERIOD);
|
||||
#endif
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
if(--bind_counter==0)
|
||||
{
|
||||
BIND_DONE;
|
||||
XN297L_SetTXAddr(rx_tx_addr, 5); // Normal packets address
|
||||
}
|
||||
XK_send_packet();
|
||||
return XK_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initXK()
|
||||
{
|
||||
if(sub_protocol==X420)
|
||||
option=prev_option=0; // Forcing the use of NRF24L01@1Mbps
|
||||
BIND_IN_PROGRESS; // Autobind protocol
|
||||
XK_initialize_txid();
|
||||
XK_init();
|
||||
if(sub_protocol==X420)
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // X420/X520 runs @1Mbps
|
||||
hopping_frequency_no = 0;
|
||||
bind_counter=XK_BIND_COUNT;
|
||||
return XK_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
// Parameters which can be modified
|
||||
#define XN297DUMP_PERIOD_SCAN 50000 // 25000
|
||||
#define XN297DUMP_MAX_RF_CHANNEL 84 // Default 84
|
||||
#define XN297DUMP_MAX_RF_CHANNEL 127 // Default 84
|
||||
|
||||
// Do not touch from there
|
||||
#define XN297DUMP_INITIAL_WAIT 500
|
||||
@@ -33,6 +33,10 @@
|
||||
uint8_t address_length;
|
||||
uint16_t timeH=0;
|
||||
boolean scramble;
|
||||
boolean enhanced;
|
||||
boolean ack;
|
||||
uint8_t pid;
|
||||
uint8_t bitrate;
|
||||
|
||||
static void __attribute__((unused)) XN297Dump_init()
|
||||
{
|
||||
@@ -48,14 +52,14 @@ static void __attribute__((unused)) XN297Dump_init()
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\x55\x0F\x71", 3); // set up RX address to xn297 preamble
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, XN297DUMP_MAX_PACKET_LEN); // Enable rx pipe 0
|
||||
|
||||
debug("XN297 dump, address length=%d, speed=",address_length);
|
||||
switch(sub_protocol)
|
||||
debug("XN297 dump, address length=%d, bitrate=",address_length);
|
||||
switch(bitrate)
|
||||
{
|
||||
case 0:
|
||||
case XN297DUMP_250K:
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K);
|
||||
debugln("250K");
|
||||
break;
|
||||
case 2:
|
||||
case XN297DUMP_2M:
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_2M);
|
||||
debugln("2M");
|
||||
break;
|
||||
@@ -76,9 +80,14 @@ static boolean __attribute__((unused)) XN297Dump_process_packet(void)
|
||||
{
|
||||
uint16_t crcxored;
|
||||
uint8_t packet_sc[XN297DUMP_MAX_PACKET_LEN], packet_un[XN297DUMP_MAX_PACKET_LEN];
|
||||
enhanced=false;
|
||||
// init crc
|
||||
crc = 0xb5d2;
|
||||
|
||||
/*debug("P: 71 0F 55 ");
|
||||
for(uint8_t i=0; i<XN297DUMP_MAX_PACKET_LEN; i++)
|
||||
debug("%02X ",packet[i]);
|
||||
debugln("");*/
|
||||
//Try normal payload
|
||||
// address
|
||||
for (uint8_t i = 0; i < address_length; i++)
|
||||
@@ -142,17 +151,17 @@ static boolean __attribute__((unused)) XN297Dump_process_packet(void)
|
||||
}
|
||||
if(packet_length!=0)
|
||||
{ // Found a valid CRC for the enhanced payload mode
|
||||
debug("Enhanced ");
|
||||
enhanced=true;
|
||||
//check selected address length
|
||||
if((packet_un[address_length]>>1)!=packet_length-address_length)
|
||||
{
|
||||
for(uint8_t i=3;i<=5;i++)
|
||||
if((packet_un[i]>>1)==packet_length-i)
|
||||
address_length=i;
|
||||
debug("Wrong address length selected using %d ", address_length )
|
||||
debugln("Detected wrong address length, using %d intead", address_length );
|
||||
}
|
||||
debug("pid=%d ",((packet_un[address_length]&0x01)<<1)|(packet_un[address_length+1]>>7));
|
||||
debug("ack=%d ",(packet_un[address_length+1]>>6)&0x01);
|
||||
pid=((packet_un[address_length]&0x01)<<1)|(packet_un[address_length+1]>>7);
|
||||
ack=(packet_un[address_length+1]>>6)&0x01;
|
||||
// address
|
||||
for (uint8_t i = 0; i < address_length; i++)
|
||||
packet[address_length-1-i]=packet_un[i];
|
||||
@@ -175,12 +184,14 @@ static void __attribute__((unused)) XN297Dump_overflow()
|
||||
}
|
||||
static uint16_t XN297Dump_callback()
|
||||
{
|
||||
static uint32_t time=0;
|
||||
static uint32_t time=0,*time_rf;
|
||||
|
||||
//!!!Blocking mode protocol!!!
|
||||
TX_MAIN_PAUSE_off;
|
||||
tx_resume();
|
||||
while(1)
|
||||
{
|
||||
if(sub_protocol<XN297DUMP_AUTO)
|
||||
{
|
||||
if(option==0xFF && bind_counter>XN297DUMP_PERIOD_SCAN)
|
||||
{ // Scan frequencies
|
||||
@@ -192,7 +203,7 @@ static uint16_t XN297Dump_callback()
|
||||
if(hopping_frequency_no>XN297DUMP_MAX_RF_CHANNEL)
|
||||
hopping_frequency_no=0; // Invalid channel 0 by default
|
||||
rf_ch_num=hopping_frequency_no;
|
||||
debugln("Channel=%d,0x%02X",hopping_frequency_no,hopping_frequency_no)
|
||||
debugln("Channel=%d,0x%02X",hopping_frequency_no,hopping_frequency_no);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency_no);
|
||||
// switch to RX mode
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
@@ -219,17 +230,23 @@ static uint16_t XN297Dump_callback()
|
||||
XN297Dump_overflow();
|
||||
timeL=0;
|
||||
}
|
||||
if(phase==0)
|
||||
if((phase&0x01)==0)
|
||||
{
|
||||
phase=1;
|
||||
time=0;
|
||||
}
|
||||
else
|
||||
time=(timeH<<16)+timeL-time;
|
||||
debug("RX: %5luus C=%d ", time>>1 , hopping_frequency_no);
|
||||
time=(timeH<<16)+timeL;
|
||||
if(XN297Dump_process_packet())
|
||||
{ // valid crc found
|
||||
debug("RX: %5luus C=%d ", time>>1 , hopping_frequency_no);
|
||||
time=(timeH<<16)+timeL;
|
||||
if(enhanced)
|
||||
{
|
||||
debug("Enhanced ");
|
||||
debug("pid=%d ",pid);
|
||||
if(ack) debug("ack ");
|
||||
}
|
||||
debug("S=%c A=",scramble?'Y':'N');
|
||||
for(uint8_t i=0; i<address_length; i++)
|
||||
{
|
||||
@@ -244,7 +261,7 @@ static uint16_t XN297Dump_callback()
|
||||
}
|
||||
else
|
||||
{
|
||||
debugln("Bad CRC");
|
||||
debugln("RX: %5luus C=%d Bad CRC", time>>1 , hopping_frequency_no);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,11 +277,431 @@ static uint16_t XN297Dump_callback()
|
||||
| (1 << NRF24L01_00_PRIM_RX));
|
||||
XN297Dump_overflow();
|
||||
}
|
||||
}
|
||||
else if(sub_protocol==XN297DUMP_AUTO)
|
||||
{
|
||||
switch(phase)
|
||||
{
|
||||
case 0:
|
||||
debugln("------------------------");
|
||||
debugln("Detecting XN297 packets.");
|
||||
XN297Dump_init();
|
||||
debug("Trying RF channel: 0");
|
||||
hopping_frequency_no=0;
|
||||
bitrate=0;
|
||||
phase++;
|
||||
break;
|
||||
case 1:
|
||||
if(bind_counter>XN297DUMP_PERIOD_SCAN)
|
||||
{ // Scan frequencies
|
||||
hopping_frequency_no++;
|
||||
bind_counter=0;
|
||||
if(hopping_frequency_no>XN297DUMP_MAX_RF_CHANNEL)
|
||||
{
|
||||
hopping_frequency_no=0;
|
||||
bitrate++;
|
||||
bitrate%=3;
|
||||
debugln("");
|
||||
XN297Dump_init();
|
||||
debug("Trying RF channel: 0");
|
||||
}
|
||||
if(hopping_frequency_no)
|
||||
debug(",%d",hopping_frequency_no);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency_no);
|
||||
// switch to RX mode
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC) // switch to RX mode and disable CRC
|
||||
| (1 << NRF24L01_00_CRCO)
|
||||
| (1 << NRF24L01_00_PWR_UP)
|
||||
| (1 << NRF24L01_00_PRIM_RX));
|
||||
}
|
||||
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{ // RX fifo data ready
|
||||
if(NRF24L01_ReadReg(NRF24L01_09_CD))
|
||||
{
|
||||
NRF24L01_ReadPayload(packet,XN297DUMP_MAX_PACKET_LEN);
|
||||
if(XN297Dump_process_packet())
|
||||
{ // valid crc found
|
||||
debug("\r\n\r\nPacket detected: bitrate=");
|
||||
switch(bitrate)
|
||||
{
|
||||
case XN297DUMP_250K:
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K);
|
||||
debug("250K");
|
||||
break;
|
||||
case XN297DUMP_2M:
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_2M);
|
||||
debug("2M");
|
||||
break;
|
||||
default:
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M);
|
||||
debug("1M");
|
||||
break;
|
||||
|
||||
}
|
||||
debug(" C=%d ", hopping_frequency_no);
|
||||
if(enhanced)
|
||||
{
|
||||
debug("Enhanced ");
|
||||
debug("pid=%d ",pid);
|
||||
if(ack) debug("ack ");
|
||||
}
|
||||
debug("S=%c A=",scramble?'Y':'N');
|
||||
for(uint8_t i=0; i<address_length; i++)
|
||||
{
|
||||
debug(" %02X",packet[i]);
|
||||
rx_tx_addr[i]=packet[i];
|
||||
}
|
||||
debug(" P(%d)=",packet_length-address_length);
|
||||
for(uint8_t i=address_length; i<packet_length; i++)
|
||||
{
|
||||
debug(" %02X",packet[i]);
|
||||
}
|
||||
packet_length=packet_length-address_length;
|
||||
debugln("\r\n--------------------------------");
|
||||
phase=2;
|
||||
debugln("Identifying all RF channels in use.");
|
||||
bind_counter=0;
|
||||
hopping_frequency_no=0;
|
||||
rf_ch_num=0;
|
||||
packet_count=0;
|
||||
debug("Trying RF channel: 0");
|
||||
NRF24L01_Initialize();
|
||||
XN297_SetScrambledMode(scramble?XN297_SCRAMBLED:XN297_UNSCRAMBLED);
|
||||
XN297_SetTXAddr(rx_tx_addr,address_length);
|
||||
XN297_SetRXAddr(rx_tx_addr,address_length);
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, packet_length + 2 + (enhanced?2:0) ); // 2 extra bytes for xn297 crc
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH,0);
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if(bind_counter>XN297DUMP_PERIOD_SCAN)
|
||||
{ // Scan frequencies
|
||||
hopping_frequency_no++;
|
||||
bind_counter=0;
|
||||
if(packet_count && packet_count<=5)
|
||||
debug("\r\nTrying RF channel: ");
|
||||
packet_count=0;
|
||||
if(hopping_frequency_no>XN297DUMP_MAX_RF_CHANNEL)
|
||||
{
|
||||
debug("\r\n\r\n%d RF channels identified:",rf_ch_num);
|
||||
for(uint8_t i=0;i<rf_ch_num;i++)
|
||||
debug(" %d",hopping_frequency[i]);
|
||||
time_rf=(uint32_t*)malloc(rf_ch_num*sizeof(time));
|
||||
if(time_rf==NULL)
|
||||
{
|
||||
debugln("\r\nCan't allocate memory for next phase!!!");
|
||||
phase=0;
|
||||
break;
|
||||
}
|
||||
debugln("\r\n--------------------------------");
|
||||
debugln("Identifying RF channels order.");
|
||||
hopping_frequency_no=1;
|
||||
phase=3;
|
||||
packet_count=0;
|
||||
bind_counter=0;
|
||||
debugln("Time between CH:%d and CH:%d",hopping_frequency[0],hopping_frequency[hopping_frequency_no]);
|
||||
time_rf[hopping_frequency_no]=0xFFFFFFFF;
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency[0]);
|
||||
uint16_t timeL=TCNT1;
|
||||
if(TIMER2_BASE->SR & TIMER_SR_UIF)
|
||||
{//timer just rolled over...
|
||||
XN297Dump_overflow();
|
||||
timeL=0;
|
||||
}
|
||||
time=(timeH<<16)+timeL;
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC) // switch to RX mode and disable CRC
|
||||
| (1 << NRF24L01_00_CRCO)
|
||||
| (1 << NRF24L01_00_PWR_UP)
|
||||
| (1 << NRF24L01_00_PRIM_RX));
|
||||
XN297Dump_overflow();
|
||||
break;
|
||||
}
|
||||
debug(",%d",hopping_frequency_no);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency_no);
|
||||
// switch to RX mode
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_FlushRx();
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
|
||||
}
|
||||
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{ // RX fifo data ready
|
||||
if(NRF24L01_ReadReg(NRF24L01_09_CD))
|
||||
{
|
||||
boolean res;
|
||||
if(enhanced)
|
||||
res=XN297_ReadEnhancedPayload(packet, packet_length);
|
||||
else
|
||||
res=XN297_ReadPayload(packet, packet_length);
|
||||
if(res)
|
||||
{ // valid crc found
|
||||
XN297Dump_overflow();
|
||||
uint16_t timeL=TCNT1;
|
||||
if(TIMER2_BASE->SR & TIMER_SR_UIF)
|
||||
{//timer just rolled over...
|
||||
XN297Dump_overflow();
|
||||
timeL=0;
|
||||
}
|
||||
if(packet_count==0)
|
||||
{//save channel
|
||||
hopping_frequency[rf_ch_num]=hopping_frequency_no;
|
||||
rf_ch_num++;
|
||||
time=0;
|
||||
}
|
||||
else
|
||||
time=(timeH<<16)+timeL-time;
|
||||
debug("\r\nRX on channel: %d, Time: %5luus P:",hopping_frequency_no, time>>1);
|
||||
time=(timeH<<16)+timeL;
|
||||
for(uint8_t i=0;i<packet_length;i++)
|
||||
debug(" %02X",packet[i]);
|
||||
packet_count++;
|
||||
if(packet_count>5)
|
||||
{//change channel
|
||||
bind_counter=XN297DUMP_PERIOD_SCAN+1;
|
||||
debug("\r\nTrying RF channel: ");
|
||||
}
|
||||
}
|
||||
}
|
||||
// restart RX mode
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_FlushRx();
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
|
||||
}
|
||||
XN297Dump_overflow();
|
||||
break;
|
||||
case 3:
|
||||
if(bind_counter>XN297DUMP_PERIOD_SCAN)
|
||||
{ // Scan frequencies
|
||||
hopping_frequency_no++;
|
||||
bind_counter=0;
|
||||
if(hopping_frequency_no>=rf_ch_num)
|
||||
{
|
||||
uint8_t next=0;
|
||||
debugln("\r\n\r\nChannel order:");
|
||||
debugln("%d: 0us",hopping_frequency[0]);
|
||||
uint8_t i=1;
|
||||
do
|
||||
{
|
||||
time=time_rf[i];
|
||||
if(time!=0xFFFFFFFF)
|
||||
{
|
||||
next=i;
|
||||
for(uint8_t j=2;j<rf_ch_num;j++)
|
||||
if(time>time_rf[j])
|
||||
{
|
||||
next=j;
|
||||
time=time_rf[j];
|
||||
}
|
||||
time_rf[next]=-1;
|
||||
debugln("%d: %5luus",hopping_frequency[next],time);
|
||||
i=0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
while(i<rf_ch_num);
|
||||
free(time_rf);
|
||||
debugln("\r\n--------------------------------");
|
||||
debugln("Identifying Sticks and features.");
|
||||
phase=4;
|
||||
hopping_frequency_no=0;
|
||||
break;
|
||||
}
|
||||
debugln("Time between CH:%d and CH:%d",hopping_frequency[0],hopping_frequency[hopping_frequency_no]);
|
||||
time_rf[hopping_frequency_no]=-1;
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency[0]);
|
||||
uint16_t timeL=TCNT1;
|
||||
if(TIMER2_BASE->SR & TIMER_SR_UIF)
|
||||
{//timer just rolled over...
|
||||
XN297Dump_overflow();
|
||||
timeL=0;
|
||||
}
|
||||
time=(timeH<<16)+timeL;
|
||||
// switch to RX mode
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_FlushRx();
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
|
||||
}
|
||||
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{ // RX fifo data ready
|
||||
if(NRF24L01_ReadReg(NRF24L01_09_CD))
|
||||
{
|
||||
boolean res;
|
||||
if(enhanced)
|
||||
res=XN297_ReadEnhancedPayload(packet, packet_length);
|
||||
else
|
||||
res=XN297_ReadPayload(packet, packet_length);
|
||||
if(res)
|
||||
{ // valid crc found
|
||||
XN297Dump_overflow();
|
||||
uint16_t timeL=TCNT1;
|
||||
if(TIMER2_BASE->SR & TIMER_SR_UIF)
|
||||
{//timer just rolled over...
|
||||
XN297Dump_overflow();
|
||||
timeL=0;
|
||||
}
|
||||
if(packet_count&1)
|
||||
{
|
||||
time=(timeH<<16)+timeL-time;
|
||||
if(time_rf[hopping_frequency_no] > (time>>1))
|
||||
time_rf[hopping_frequency_no]=time>>1;
|
||||
debugln("Time: %5luus", time>>1);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
time=(timeH<<16)+timeL;
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH,hopping_frequency[hopping_frequency_no]);
|
||||
}
|
||||
packet_count++;
|
||||
if(packet_count>6)
|
||||
{
|
||||
bind_counter=XN297DUMP_PERIOD_SCAN+1;
|
||||
packet_count=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// restart RX mode
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_FlushRx();
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
|
||||
}
|
||||
XN297Dump_overflow();
|
||||
break;
|
||||
case 4:
|
||||
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{ // RX fifo data ready
|
||||
if(NRF24L01_ReadReg(NRF24L01_09_CD))
|
||||
{
|
||||
boolean res;
|
||||
if(enhanced)
|
||||
res=XN297_ReadEnhancedPayload(packet, packet_length);
|
||||
else
|
||||
res=XN297_ReadPayload(packet, packet_length);
|
||||
if(res)
|
||||
{ // valid crc found
|
||||
if(memcmp(packet_in,packet,packet_length))
|
||||
{
|
||||
debug("P:");
|
||||
for(uint8_t i=0;i<packet_length;i++)
|
||||
debug(" %02X",packet[i]);
|
||||
debugln("");
|
||||
memcpy(packet_in,packet,packet_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
// restart RX mode
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_FlushRx();
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(phase==0)
|
||||
{
|
||||
address_length=5;
|
||||
memcpy(rx_tx_addr, (uint8_t *)"\xC9\x59\xD2\x65\x34", 5);
|
||||
bitrate=XN297DUMP_250K;
|
||||
packet_length=16;
|
||||
hopping_frequency_no=0x03;
|
||||
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, address_length-2); // RX/TX address length
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, address_length); // set up RX address
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, packet_length); // Enable rx pipe 0
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency_no);
|
||||
|
||||
debug("NRF dump, len=%d, rf=%d, address length=%d, bitrate=",packet_length,hopping_frequency_no,address_length);
|
||||
switch(bitrate)
|
||||
{
|
||||
case XN297DUMP_250K:
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K);
|
||||
debugln("250K");
|
||||
break;
|
||||
case XN297DUMP_2M:
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_2M);
|
||||
debugln("2M");
|
||||
break;
|
||||
default:
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M);
|
||||
debugln("1M");
|
||||
break;
|
||||
|
||||
}
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
|
||||
NRF24L01_Activate(0x73);
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
|
||||
phase++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{ // RX fifo data ready
|
||||
if(NRF24L01_ReadReg(NRF24L01_09_CD))
|
||||
{
|
||||
NRF24L01_ReadPayload(packet, packet_length);
|
||||
if(memcmp(packet_in,packet,packet_length))
|
||||
{
|
||||
debug("P:");
|
||||
for(uint8_t i=0;i<packet_length;i++)
|
||||
debug(" %02X",packet[i]);
|
||||
debugln("");
|
||||
memcpy(packet_in,packet,packet_length);
|
||||
}
|
||||
}
|
||||
// restart RX mode
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) | _BV(NRF24L01_00_PRIM_RX));
|
||||
}
|
||||
}
|
||||
}
|
||||
bind_counter++;
|
||||
if(IS_RX_FLAG_on) // Let the radio update the protocol
|
||||
{
|
||||
if(Update_All()) return 10000; // New protocol selected
|
||||
if(prev_option!=option)
|
||||
if(prev_option!=option && sub_protocol<XN297DUMP_AUTO)
|
||||
{ // option has changed
|
||||
hopping_frequency_no=option;
|
||||
prev_option=option;
|
||||
@@ -278,6 +715,10 @@ static uint16_t XN297Dump_callback()
|
||||
uint16_t initXN297Dump(void)
|
||||
{
|
||||
BIND_DONE;
|
||||
if(sub_protocol<XN297DUMP_AUTO)
|
||||
bitrate=sub_protocol;
|
||||
else
|
||||
bitrate=0;
|
||||
address_length=RX_num;
|
||||
if(address_length<3||address_length>5)
|
||||
address_length=5; //default
|
||||
@@ -285,7 +726,7 @@ uint16_t initXN297Dump(void)
|
||||
bind_counter=0;
|
||||
rf_ch_num=0xFF;
|
||||
prev_option=option^0x55;
|
||||
phase=0; // init timer
|
||||
phase=0; // init
|
||||
return XN297DUMP_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,223 +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/>.
|
||||
*/
|
||||
#include "iface_xn297l.h"
|
||||
|
||||
#if defined (XN297L_CC2500_EMU)
|
||||
static void __attribute__((unused)) XN297L_Init()
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t* addr, uint8_t len)
|
||||
{
|
||||
if (len > 5) len = 5;
|
||||
if (len < 3) len = 3;
|
||||
xn297_addr_len = len;
|
||||
memcpy(xn297_tx_addr, addr, len);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
uint8_t buf[32];
|
||||
uint8_t last = 0;
|
||||
uint8_t i;
|
||||
static const uint16_t initial = 0xb5d2;
|
||||
|
||||
// address
|
||||
for (i = 0; i < xn297_addr_len; ++i)
|
||||
{
|
||||
buf[last] = xn297_tx_addr[xn297_addr_len - i - 1];
|
||||
if(xn297_scramble_enabled)
|
||||
buf[last] ^= xn297_scramble[i];
|
||||
last++;
|
||||
}
|
||||
|
||||
// payload
|
||||
for (i = 0; i < len; ++i) {
|
||||
// bit-reverse bytes in packet
|
||||
buf[last] = bit_reverse(msg[i]);
|
||||
if(xn297_scramble_enabled)
|
||||
buf[last] ^= xn297_scramble[xn297_addr_len+i];
|
||||
last++;
|
||||
}
|
||||
|
||||
// crc
|
||||
uint16_t crc = initial;
|
||||
for (uint8_t i = 0; i < last; ++i)
|
||||
crc = crc16_update(crc, buf[i], 8);
|
||||
if(xn297_scramble_enabled)
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
|
||||
else
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]);
|
||||
buf[last++] = crc >> 8;
|
||||
buf[last++] = crc & 0xff;
|
||||
|
||||
// stop TX/RX
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
// flush tx FIFO
|
||||
CC2500_Strobe(CC2500_SFTX);
|
||||
// packet length
|
||||
CC2500_WriteReg(CC2500_3F_TXFIFO, last + 3);
|
||||
// xn297L preamble
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (uint8_t*)"\x71\x0f\x55", 3);
|
||||
// xn297 packet
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last);
|
||||
// transmit
|
||||
CC2500_Strobe(CC2500_STX);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_HoppingCalib(uint8_t num_freq)
|
||||
{ //calibrate hopping frequencies
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_Hopping(uint8_t index)
|
||||
{
|
||||
// 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]);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_RFChannel(uint8_t number)
|
||||
{ //change channel
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, number*3);
|
||||
CC2500_Strobe(CC2500_SCAL);
|
||||
delayMicroseconds(900);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_SetPower()
|
||||
{
|
||||
CC2500_SetPower();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_SetFreqOffset()
|
||||
{ // Frequency offset
|
||||
if (prev_option != option)
|
||||
{
|
||||
prev_option = option;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined (NRF24L01_INSTALLED)
|
||||
|
||||
static void __attribute__((unused)) XN297L_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_250K); // 250Kbps
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t* addr, uint8_t len)
|
||||
{
|
||||
XN297_SetTXAddr(addr,len);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_HoppingCalib(__attribute__((unused)) uint8_t num_freq)
|
||||
{ //calibrate hopping frequencies
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_Hopping(uint8_t index)
|
||||
{
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[index]);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_RFChannel(uint8_t number)
|
||||
{ //change channel
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, number);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_SetPower()
|
||||
{
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_SetFreqOffset()
|
||||
{ // Frequency offset
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -16,7 +16,7 @@ Multiprotocol is distributed in the hope that it will be useful,
|
||||
|
||||
#if defined(ZSX_NRF24L01_INO)
|
||||
|
||||
#include "iface_xn297l.h"
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
//#define FORCE_ZSX_ORIGINAL_ID
|
||||
|
||||
|
||||
@@ -69,17 +69,20 @@
|
||||
/****************/
|
||||
/*** RF CHIPS ***/
|
||||
/****************/
|
||||
//There are 4 RF components supported. If one of them is not installed you must comment it using "//".
|
||||
//There are 5 RF components supported. If one of them is not installed you must comment it using "//".
|
||||
//If a chip is not installed all associated protocols are automatically disabled.
|
||||
//4-in-1 modules have all RF chips installed
|
||||
//4-in-1 modules have the A7105, CYRF6936, CC2500 and NRF24L01 RF chips installed
|
||||
//5-in-1 modules have all RF chips installed
|
||||
//!!!If a RF chip is present it MUST be marked as installed!!! or weird things will happen you have been warned.
|
||||
#define A7105_INSTALLED
|
||||
#define CYRF6936_INSTALLED
|
||||
#define CC2500_INSTALLED
|
||||
#define NRF24L01_INSTALLED
|
||||
//#define SX1276_INSTALLED // only supported on STM32 modules
|
||||
|
||||
//If available use the CC2500 to emulate the XN297L @250Kbps instead of the NRF24L01. Comment to disable.
|
||||
#define XN297L_CC2500_EMU
|
||||
//Uncomment (remove //) if you have an internal 5-in-1 Multi module.
|
||||
//All components are considered to be installed and specifics to that module are automatically configured
|
||||
//#define MULTI_5IN1_INTERNAL
|
||||
|
||||
/** OrangeRX TX **/
|
||||
//If you compile for the OrangeRX TX module you need to select the correct board type.
|
||||
@@ -87,19 +90,22 @@
|
||||
//#define ORANGE_TX_BLUE
|
||||
|
||||
/** CC2500 Fine Frequency Tuning **/
|
||||
//For optimal performance the CC2500 RF module used by the CORONA, FrSkyD, FrSkyV, FrSkyX, Hitec, HoTT, SFHSS and Redpine protocols needs to be tuned for each protocol.
|
||||
//For optimal performance the CC2500 RF module used by the CORONA, FrSkyD, FrSkyV, FrSkyX, Hitec, HoTT, Futaba/SFHSS and Redpine protocols needs to be tuned for each protocol.
|
||||
//Initial tuning should be done via the radio menu with a genuine CORONA/FrSky/Hitec/HoTT/Futaba/Redpine receiver.
|
||||
//Once a good tuning value is found it can be set here and will override the radio's 'option' setting for all existing and new models which use that protocol.
|
||||
//For more information: https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/tree/master/docs/Frequency_Tuning.md
|
||||
//Uncomment the lines below (remove the "//") and set an appropriate value (replace the "0") to enable. Valid range is -127 to +127.
|
||||
//#define FORCE_CORONA_TUNING 0
|
||||
//#define FORCE_FRSKYD_TUNING 0
|
||||
//#define FORCE_FRSKYL_TUNING 0
|
||||
//#define FORCE_FRSKYV_TUNING 0
|
||||
//#define FORCE_FRSKYX_TUNING 0
|
||||
//#define FORCE_SFHSS_TUNING 0
|
||||
//#define FORCE_HITEC_TUNING 0
|
||||
//#define FORCE_HOTT_TUNING 0
|
||||
//#define FORCE_RADIOLINK_TUNING 0
|
||||
//#define FORCE_REDPINE_TUNING 0
|
||||
//#define FORCE_FUTABA_TUNING 0
|
||||
//#define FORCE_SKYARTEC_TUNING 0
|
||||
|
||||
/** A7105 Fine Frequency Tuning **/
|
||||
//This is required in rare cases where some A7105 modules and/or RXs have an inaccurate crystal oscillator.
|
||||
@@ -112,8 +118,10 @@
|
||||
//#define FORCE_AFHDS2A_TUNING 0
|
||||
//#define FORCE_BUGS_TUNING 0
|
||||
//#define FORCE_FLYSKY_TUNING 0
|
||||
//#define FORCE_FLYZONE_TUNING 0
|
||||
//#define FORCE_HEIGHT_TUNING 0
|
||||
//#define FORCE_HUBSAN_TUNING 0
|
||||
//#define FORCE_KYOSHO_TUNING 0
|
||||
//#define FORCE_PELIKAN_TUNING 0
|
||||
|
||||
/** CYRF6936 Fine Frequency Tuning **/
|
||||
//This is required in rare cases where some CYRF6936 modules and/or RXs have an inaccurate crystal oscillator.
|
||||
@@ -140,6 +148,7 @@
|
||||
//If you have 2 Multi modules which you want to share the same ID so you can use either to control the same RC model
|
||||
// then you can force the ID to a certain known value using the lines below.
|
||||
//Default is commented, you should uncoment only for test purpose or if you know exactly what you are doing!!!
|
||||
//The 8 numbers below can be anything between 0...9 and A..F
|
||||
//#define FORCE_GLOBAL_ID 0x12345678
|
||||
|
||||
//Protocols using the CYRF6936 (DSM, Devo, Walkera...) are using the CYRF ID instead which should prevent duplicated IDs.
|
||||
@@ -161,12 +170,15 @@
|
||||
#define AFHDS2A_RX_A7105_INO
|
||||
#define BUGS_A7105_INO
|
||||
#define FLYSKY_A7105_INO
|
||||
#define FLYZONE_A7105_INO
|
||||
#define HEIGHT_A7105_INO
|
||||
#define HUBSAN_A7105_INO
|
||||
#define KYOSHO_A7105_INO
|
||||
#define PELIKAN_A7105_INO
|
||||
|
||||
//The protocols below need a CYRF6936 to be installed
|
||||
#define DEVO_CYRF6936_INO
|
||||
#define DSM_CYRF6936_INO
|
||||
#define DSM_RX_CYRF6936_INO
|
||||
#define J6PRO_CYRF6936_INO
|
||||
#define TRAXXAS_CYRF6936_INO
|
||||
#define WFLY_CYRF6936_INO
|
||||
@@ -174,15 +186,20 @@
|
||||
|
||||
//The protocols below need a CC2500 to be installed
|
||||
#define CORONA_CC2500_INO
|
||||
#define ESKY150V2_CC2500_INO //Need both CC2500 and NRF
|
||||
#define FRSKYL_CC2500_INO
|
||||
#define FRSKYD_CC2500_INO
|
||||
#define FRSKYV_CC2500_INO
|
||||
#define FRSKYX_CC2500_INO
|
||||
#define FRSKY_RX_CC2500_INO
|
||||
#define HITEC_CC2500_INO
|
||||
#define HOTT_CC2500_INO
|
||||
#define OMP_CC2500_INO //Need both CC2500 and NRF
|
||||
#define SCANNER_CC2500_INO
|
||||
#define SFHSS_CC2500_INO
|
||||
#define FUTABA_CC2500_INO
|
||||
#define SKYARTEC_CC2500_INO
|
||||
#define REDPINE_CC2500_INO
|
||||
#define RLINK_CC2500_INO
|
||||
|
||||
//The protocols below need a NRF24L01 to be installed
|
||||
#define ASSAN_NRF24L01_INO
|
||||
@@ -205,33 +222,35 @@
|
||||
#define HISKY_NRF24L01_INO
|
||||
#define HONTAI_NRF24L01_INO
|
||||
#define H8_3D_NRF24L01_INO
|
||||
#define JJRC345_NRF24L01_INO
|
||||
#define KF606_NRF24L01_INO
|
||||
#define KN_NRF24L01_INO
|
||||
#define MJXQ_NRF24L01_INO
|
||||
#define MT99XX_NRF24L01_INO
|
||||
#define NCC1701_NRF24L01_INO
|
||||
#define POTENSIC_NRF24L01_INO
|
||||
#define PROPEL_NRF24L01_INO
|
||||
#define Q303_NRF24L01_INO
|
||||
#define Q90C_NRF24L01_INO
|
||||
#define REALACC_NRF24L01_INO
|
||||
#define SHENQI_NRF24L01_INO
|
||||
#define SLT_NRF24L01_INO
|
||||
#define SYMAX_NRF24L01_INO
|
||||
#define TIGER_NRF24L01_INO
|
||||
#define V2X2_NRF24L01_INO
|
||||
#define V761_NRF24L01_INO
|
||||
#define V911S_NRF24L01_INO
|
||||
#define XK_NRF24L01_INO
|
||||
#define YD717_NRF24L01_INO
|
||||
#define ZSX_NRF24L01_INO
|
||||
|
||||
//The protocols below need a SX1276 to be installed
|
||||
#define FRSKYR9_SX1276_INO
|
||||
|
||||
/***************************/
|
||||
/*** PROTOCOLS SETTINGS ***/
|
||||
/***************************/
|
||||
|
||||
//FrSkyX specific setting
|
||||
//-----------------------
|
||||
//EU LBT setting: if commented the TX will not check if a channel is busy before transmitting.
|
||||
//!!! Work in progress !!! it's currently known to cause telemerty issues. Enable only if you know what you are doing.
|
||||
//#define FRSKYX_LBT
|
||||
|
||||
//DSM specific settings
|
||||
//---------------------
|
||||
//The DSM protocol is using by default the Spektrum throw of 1100..1900us @100% and 1000..2000us @125%.
|
||||
@@ -240,19 +259,21 @@
|
||||
//Some models (X-Vert, Blade 230S...) require a special value to instant stop the motor(s).
|
||||
// You can disable this feature by adding "//" on the line below. You have to specify which channel (14 by default) will be used to kill the throttle channel.
|
||||
// If the channel 14 is above -50% the throttle is untouched but if it is between -50% and -100%, the throttle output will be forced between -100% and -150%.
|
||||
// For example, a value of -80% applied on channel 15 will instantly kill the motors on the X-Vert.
|
||||
// For example, a value of -80% applied on channel 14 will instantly kill the motors on the X-Vert.
|
||||
#define DSM_THROTTLE_KILL_CH 14
|
||||
|
||||
//Enable DSM Forward Programming
|
||||
#define DSM_FWD_PGM
|
||||
|
||||
//AFHDS2A specific settings
|
||||
//-------------------------
|
||||
//When enabled (remove the "//"), the below setting makes LQI (Link Quality Indicator) available on one of the RX ouput channel (5-14).
|
||||
//#define AFHDS2A_LQI_CH 14
|
||||
|
||||
|
||||
/**************************/
|
||||
/*** FAILSAFE SETTINGS ***/
|
||||
/**************************/
|
||||
//The following protocols are supporting failsafe: FrSkyX, Devo, WK2x01, SFHSS, HISKY/HK310 and AFHDS2A
|
||||
//The following protocols are supporting failsafe: FrSkyX, Devo, WK2x01, Futaba/SFHSS, HISKY/HK310 and AFHDS2A
|
||||
//In Serial mode failsafe is configured on the radio itself.
|
||||
//In PPM mode and only after the module is up and fully operational, press the bind button for at least 5sec to send the current stick positions as failsafe to the RX.
|
||||
//If you want to disable failsafe globally comment the line below using "//".
|
||||
@@ -294,9 +315,13 @@
|
||||
#define HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define BAYANG_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define BUGS_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define DEVO_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define HUBSAN_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define NCC1701_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define OMP_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define PROPEL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define CABELL_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define RLINK_HUB_TELEMETRY // Use FrSkyD Hub format to send telemetry to TX
|
||||
#define HITEC_HUB_TELEMETRY // Use FrSkyD Hub format to send basic telemetry to the radios which can decode it like er9x, erskyTX and OpenTX
|
||||
#define HITEC_FW_TELEMETRY // Forward received telemetry packets to be decoded by erskyTX and OpenTX
|
||||
#define SCANNER_TELEMETRY // Forward spectrum scanner data to TX
|
||||
@@ -381,7 +406,7 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
/* 5 */ {PROTO_AFHDS2A, PWM_IBUS , 3 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 3
|
||||
/* 6 */ {PROTO_AFHDS2A, PWM_IBUS , 2 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 4
|
||||
/* 7 */ {PROTO_AFHDS2A, PWM_IBUS , 3 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 5
|
||||
/* 8 */ {PROTO_SFHSS, H107 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
|
||||
/* 8 */ {PROTO_FUTABA, NONE , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // option=fine freq tuning
|
||||
/* 9 */ {PROTO_FRSKYV, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 , 0x00000000 }, // option=fine freq tuning
|
||||
/* 10 */ {PROTO_FRSKYD, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 , 0x00000000 }, // option=fine freq tuning
|
||||
/* 11 */ {PROTO_FRSKYX, CH_16 , 0 , P_HIGH , NO_AUTOBIND , 40 , 0x00000000 }, // option=fine freq tuning
|
||||
@@ -491,6 +516,8 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
PPM_IBUS
|
||||
PWM_SBUS
|
||||
PPM_SBUS
|
||||
PWM_IB16
|
||||
PPM_IB16
|
||||
PROTO_AFHDS2A_RX
|
||||
NONE
|
||||
PROTO_ASSAN
|
||||
@@ -501,6 +528,7 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
X16_AH
|
||||
IRDRONE
|
||||
DHD_D4
|
||||
QX100
|
||||
PROTO_BAYANG_RX
|
||||
NONE
|
||||
PROTO_BUGS
|
||||
@@ -538,27 +566,46 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
DSM2_11
|
||||
DSMX_22
|
||||
DSMX_11
|
||||
PROTO_DSM_RX
|
||||
NONE
|
||||
PROTO_E01X
|
||||
E012
|
||||
E015
|
||||
E016H
|
||||
PROTO_ESKY
|
||||
NONE
|
||||
ESKY_STD
|
||||
ESKY_ET4
|
||||
PROTO_ESKY150
|
||||
ESKY150_4CH
|
||||
ESKY150_7CH
|
||||
PROTO_ESKY150V2
|
||||
NONE
|
||||
PROTO_FLYSKY
|
||||
Flysky
|
||||
V9X9
|
||||
V6X6
|
||||
V912
|
||||
CX20
|
||||
PROTO_FLYZONE
|
||||
FZ410
|
||||
PROTO_FQ777
|
||||
NONE
|
||||
PROTO_FRSKY_RX
|
||||
FRSKY_RX
|
||||
FRSKY_CLONE
|
||||
PROTO_FRSKYD
|
||||
NONE
|
||||
FRSKYD
|
||||
DCLONE
|
||||
PROTO_FRSKYL
|
||||
LR12
|
||||
LR12_6CH
|
||||
PROTO_FRSKYR9
|
||||
R9_915
|
||||
R9_868
|
||||
R9_915_8CH
|
||||
R9_868_8CH
|
||||
R9_FCC
|
||||
R9_EU
|
||||
R9_FCC_8CH
|
||||
R9_EU_8CH
|
||||
PROTO_FRSKYV
|
||||
NONE
|
||||
PROTO_FRSKYX
|
||||
@@ -566,8 +613,17 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
CH_8
|
||||
EU_16
|
||||
EU_8
|
||||
XCLONE_16
|
||||
XCLONE_8
|
||||
PROTO_FRSKYX2
|
||||
CH_16
|
||||
CH_8
|
||||
EU_16
|
||||
EU_8
|
||||
XCLONE
|
||||
PROTO_FRSKY_RX
|
||||
NONE
|
||||
FRSKY_RX
|
||||
FRSKY_CLONE
|
||||
PROTO_FX816
|
||||
NONE
|
||||
PROTO_FY326
|
||||
@@ -583,6 +639,9 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
H20H
|
||||
H20MINI
|
||||
H30MINI
|
||||
PROTO_HEIGHT
|
||||
HEIGHT_5CH
|
||||
HEIGHT_8CH
|
||||
PROTO_HISKY
|
||||
Hisky
|
||||
HK310
|
||||
@@ -596,18 +655,25 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
X5C1
|
||||
FQ777_951
|
||||
PROTO_HOTT
|
||||
NONE
|
||||
HOTT_SYNC
|
||||
HOTT_NO_SYNC
|
||||
PROTO_HUBSAN
|
||||
H107
|
||||
H301
|
||||
H501
|
||||
PROTO_J6PRO
|
||||
NONE
|
||||
PROTO_JJRC345
|
||||
JJRC345
|
||||
SKYTMBLR
|
||||
PROTO_KF606
|
||||
NONE
|
||||
PROTO_KN
|
||||
WLTOYS
|
||||
FEILUN
|
||||
PROTO_KYOSHO
|
||||
KYOSHO_FHSS
|
||||
KYOSHO_HYPE
|
||||
PROTO_MJXQ
|
||||
WLH08
|
||||
X600
|
||||
@@ -624,8 +690,15 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
FY805
|
||||
PROTO_NCC1701
|
||||
NONE
|
||||
PROTO_OMP
|
||||
NONE
|
||||
PROTO_PELIKAN
|
||||
PELIKAN_PRO
|
||||
PELIKAN_LITE
|
||||
PROTO_POTENSIC
|
||||
NONE
|
||||
PROTO_PROPEL
|
||||
NONE
|
||||
PROTO_Q2X2
|
||||
Q222
|
||||
Q242
|
||||
@@ -635,15 +708,23 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
CX35
|
||||
CX10D
|
||||
CX10WD
|
||||
PROTO_Q90C
|
||||
NONE
|
||||
PROTO_REALACC
|
||||
NONE
|
||||
PROTO_REDPINE
|
||||
RED_FAST
|
||||
RED_SLOW
|
||||
PROTO_RLINK
|
||||
NONE
|
||||
PROTO_SCANNER
|
||||
NONE
|
||||
PROTO_SFHSS
|
||||
PROTO_FUTABA
|
||||
NONE
|
||||
PROTO_SHENQI
|
||||
NONE
|
||||
PROTO_SKYARTEC
|
||||
NONE
|
||||
PROTO_SLT
|
||||
SLT_V1
|
||||
SLT_V2
|
||||
@@ -653,15 +734,20 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
PROTO_SYMAX
|
||||
SYMAX
|
||||
SYMAX5C
|
||||
PROTO_TIGER
|
||||
NONE
|
||||
PROTO_TRAXXAS
|
||||
RX6519
|
||||
PROTO_V2X2
|
||||
V2X2
|
||||
JXD506
|
||||
V2X2_MR101
|
||||
PROTO_V761
|
||||
NONE
|
||||
V761_3CH
|
||||
V761_4CH
|
||||
PROTO_V911S
|
||||
NONE
|
||||
V911S_STD
|
||||
V911S_E119
|
||||
PROTO_WFLY
|
||||
NONE
|
||||
PROTO_WK2x01
|
||||
@@ -671,6 +757,9 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
W6_6_1
|
||||
W6_HEL
|
||||
W6_HEL_I
|
||||
PROTO_XK
|
||||
X450
|
||||
X420
|
||||
PROTO_YD717
|
||||
YD717
|
||||
SKYWLKR
|
||||
@@ -680,3 +769,29 @@ const PPM_Parameters PPM_prot[14*NBR_BANKS]= {
|
||||
PROTO_ZSX
|
||||
NONE
|
||||
*/
|
||||
|
||||
/**********************************/
|
||||
/*** DIRECT INPUTS SETTINGS ***/
|
||||
/**********************************/
|
||||
//In this section you can configure the direct inputs.
|
||||
//It enables switches wired directly to the board
|
||||
//Direct inputs works only in ppm mode and only for stm_32 boards
|
||||
//Uncomment following lines to enable derect inputs or define your own configuration in _MyConfig.h
|
||||
/*
|
||||
#define ENABLE_DIRECT_INPUTS
|
||||
|
||||
#define DI1_PIN PC13
|
||||
#define IS_DI1_on (digitalRead(DI1_PIN)==LOW)
|
||||
|
||||
#define DI2_PIN PC14
|
||||
#define IS_DI2_on (digitalRead(DI2_PIN)==LOW)
|
||||
|
||||
#define DI3_PIN PC15
|
||||
#define IS_DI3_on (digitalRead(DI3_PIN)==LOW)
|
||||
|
||||
//Define up to 4 direct input channels
|
||||
//CHANNEL1 - 2pos switch
|
||||
#define DI_CH1_read IS_DI1_on ? PPM_MAX_100*2 : PPM_MIN_100*2
|
||||
//CHANNEL2 - 3pos switch
|
||||
#define DI_CH2_read IS_DI2_on ? PPM_MAX_100*2 : (IS_DI2_on ? PPM_MAX_100 + PPM_MIN_100 : PPM_MIN_100*2)
|
||||
*/
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
/* 5 */ {PROTO_AFHDS2A, PWM_IBUS , 3 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 3
|
||||
/* 6 */ {PROTO_AFHDS2A, PWM_IBUS , 2 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 4
|
||||
/* 7 */ {PROTO_AFHDS2A, PWM_IBUS , 3 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 }, // RX number 5
|
||||
/* 8 */ {PROTO_SFHSS, H107 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
|
||||
/* 8 */ {PROTO_HUBSAN, H107 , 0 , P_HIGH , NO_AUTOBIND , 0 , 0x00000000 },
|
||||
/* 9 */ {PROTO_FRSKYV, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 , 0x00000000 }, // option=fine freq tuning
|
||||
/* 10 */ {PROTO_FRSKYD, NONE , 0 , P_HIGH , NO_AUTOBIND , 40 , 0x00000000 }, // option=fine freq tuning
|
||||
/* 11 */ {PROTO_FRSKYX, CH_16 , 0 , P_HIGH , NO_AUTOBIND , 40 , 0x00000000 }, // option=fine freq tuning
|
||||
|
||||
34
Multiprotocol/iface_nrf250k.h
Normal file
34
Multiprotocol/iface_nrf250k.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef _IFACE_NRF250K_H_
|
||||
|
||||
#define _IFACE_NRF250K_H_
|
||||
|
||||
#if defined (CC2500_INSTALLED)
|
||||
#include "iface_cc2500.h"
|
||||
#endif
|
||||
#if defined (NRF24L01_INSTALLED)
|
||||
#include "iface_nrf24l01.h"
|
||||
#endif
|
||||
|
||||
//XN297L
|
||||
static void __attribute__((unused)) XN297L_Init();
|
||||
static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t*, uint8_t);
|
||||
static void __attribute__((unused)) XN297L_WritePayload(uint8_t*, uint8_t);
|
||||
static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t*, uint8_t, uint8_t);
|
||||
static void __attribute__((unused)) XN297L_HoppingCalib(__attribute__((unused)) uint8_t);
|
||||
static void __attribute__((unused)) XN297L_Hopping(uint8_t);
|
||||
static void __attribute__((unused)) XN297L_RFChannel(uint8_t);
|
||||
static void __attribute__((unused)) XN297L_SetPower();
|
||||
static void __attribute__((unused)) XN297L_SetFreqOffset();
|
||||
|
||||
//NRF250K
|
||||
#define NRF250K_Init() XN297L_Init()
|
||||
#define NRF250K_HoppingCalib(X) XN297L_HoppingCalib(X)
|
||||
#define NRF250K_Hopping(X) XN297L_Hopping(X)
|
||||
#define NRF250K_RFChannel(X) XN297L_RFChannel(X)
|
||||
#define NRF250K_SetPower() XN297L_SetPower()
|
||||
#define NRF250K_SetFreqOffset() XN297L_SetFreqOffset()
|
||||
static void __attribute__((unused)) NRF250K_SetTXAddr(uint8_t*, uint8_t);
|
||||
static void __attribute__((unused)) NRF250K_WritePayload(uint8_t*, uint8_t);
|
||||
static boolean __attribute__((unused)) NRF250K_IsPacketSent();
|
||||
|
||||
#endif
|
||||
112
Multiprotocol/iface_sx1276.h
Normal file
112
Multiprotocol/iface_sx1276.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _IFACE_SX1276_H_
|
||||
#define _IFACE_SX1276_H_
|
||||
|
||||
enum
|
||||
{
|
||||
SX1276_00_FIFO = 0x00,
|
||||
SX1276_01_OPMODE = 0x01,
|
||||
SX1276_06_FRFMSB = 0x06,
|
||||
SX1276_09_PACONFIG = 0x09,
|
||||
SX1276_0B_OCP = 0x0B,
|
||||
SX1276_0C_LNA = 0x0C,
|
||||
SX1276_0D_FIFOADDRPTR = 0x0D,
|
||||
SX1276_0E_FIFOTXBASEADDR = 0x0E,
|
||||
SX1276_11_IRQFLAGSMASK = 0x11,
|
||||
SX1276_12_REGIRQFLAGS = 0x12,
|
||||
SX1276_13_REGRXNBBYTES = 0x13,
|
||||
SX1276_19_PACKETSNR = 0x19,
|
||||
SX1276_1A_PACKETRSSI = 0x1A,
|
||||
SX1276_1D_MODEMCONFIG1 = 0x1D,
|
||||
SX1276_1E_MODEMCONFIG2 = 0x1E,
|
||||
SX1276_20_PREAMBLEMSB = 0x20,
|
||||
SX1276_22_PAYLOAD_LENGTH = 0x22,
|
||||
SX1276_24_HOPPERIOD = 0x24,
|
||||
SX1276_26_MODEMCONFIG3 = 0x26,
|
||||
SX1276_31_DETECTOPTIMIZE = 0x31,
|
||||
SX1276_37_DETECTIONTHRESHOLD = 0x37,
|
||||
SX1276_40_DIOMAPPING1 = 0x40,
|
||||
SX1276_42_VERSION = 0x42,
|
||||
SX1276_4D_PADAC = 0x4D
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SX1276_REGIRQFLAGS_CADDETECTED = 0,
|
||||
SX1276_REGIRQFLAGS_FHSSCHANGECHANNEL = 1,
|
||||
SX1276_REGIRQFLAGS_CADDONE = 2,
|
||||
SX1276_REGIRQFLAGS_TXDONE = 3,
|
||||
SX1276_REGIRQFLAGS_VALIDHEADER = 4,
|
||||
SX1276_REGIRQFLAGS_PAYLOADCRCERROR = 5,
|
||||
SX1276_REGIRQFLAGS_RXDONE = 6,
|
||||
SX1276_REGIRQFLAGS_RXTIMEOUT = 7,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SX1276_36_LORA_REGHIGHBWOPTIMIZE1 = 0x36,
|
||||
SX1276_3A_LORA_REGHIGHBWOPTIMIZE2 = 0x3A
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SX1276_OPMODE_SLEEP = 0,
|
||||
SX1276_OPMODE_STDBY,
|
||||
SX1276_OPMODE_FSTX,
|
||||
SX1276_OPMODE_TX,
|
||||
SX1276_OPMODE_FSRX,
|
||||
SX1276_OPMODE_RXCONTINUOUS,
|
||||
SX1276_OPMODE_RXSINGLE,
|
||||
SX1276_OPMODE_CAD
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SX1276_DETECT_OPTIMIZE_SF7_TO_SF12 = 0x03,
|
||||
SX1276_DETECT_OPTIMIZE_SF6 = 0x05
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SX1276_MODEM_CONFIG1_BW_7_8KHZ = 0,
|
||||
SX1276_MODEM_CONFIG1_BW_10_4KHZ,
|
||||
SX1276_MODEM_CONFIG1_BW_15_6KHZ,
|
||||
SX1276_MODEM_CONFIG1_BW_20_8KHZ,
|
||||
SX1276_MODEM_CONFIG1_BW_31_25KHZ,
|
||||
SX1276_MODEM_CONFIG1_BW_41_7KHZ,
|
||||
SX1276_MODEM_CONFIG1_BW_62_5KHZ,
|
||||
SX1276_MODEM_CONFIG1_BW_125KHZ,
|
||||
SX1276_MODEM_CONFIG1_BW_250KHZ,
|
||||
SX1276_MODEM_CONFIG1_BW_500KHZ
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SX1276_MODEM_CONFIG1_CODING_RATE_4_5 = 1,
|
||||
SX1276_MODEM_CONFIG1_CODING_RATE_4_6,
|
||||
SX1276_MODEM_CONFIG1_CODING_RATE_4_7,
|
||||
SX1276_MODEM_CONFIG1_CODING_RATE_4_8
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SX1276_MODEM_DETECTION_THRESHOLD_SF7_TO_SF12 = 0x0A,
|
||||
SX1276_MODEM_DETECTION_THRESHOLD_SF6 = 0x0C,
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,20 +0,0 @@
|
||||
#ifndef _IFACE_XN297L_H_
|
||||
|
||||
#define _IFACE_XN297L_H_
|
||||
|
||||
#if defined (XN297L_CC2500_EMU)
|
||||
#include "iface_cc2500.h"
|
||||
#elif defined (NRF24L01_INSTALLED)
|
||||
#include "iface_nrf24l01.h"
|
||||
#endif
|
||||
|
||||
static void __attribute__((unused)) XN297L_Init();
|
||||
static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t*, uint8_t);
|
||||
static void __attribute__((unused)) XN297L_WritePayload(uint8_t*, uint8_t);
|
||||
static void __attribute__((unused)) XN297L_HoppingCalib(__attribute__((unused)) uint8_t);
|
||||
static void __attribute__((unused)) XN297L_Hopping(uint8_t);
|
||||
static void __attribute__((unused)) XN297L_RFChannel(uint8_t);
|
||||
static void __attribute__((unused)) XN297L_SetPower();
|
||||
static void __attribute__((unused)) XN297L_SetFreqOffset();
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,10 +19,11 @@ If you like this project and want to support further development please consider
|
||||
|
||||
## Development status
|
||||
|
||||
Current Multiprotocol code check status: [](https://travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module)
|
||||
Multiprotocol downloads: <img src=https://img.shields.io/github/downloads/pascallanger/DIY-Multiprotocol-TX-Module/total.svg>
|
||||
|
||||
Current Multiprotocol boards check status: [](https://travis-ci.org/pascallanger/DIY-Multiprotocol-TX-Module-Boards)
|
||||
Current Multiprotocol code check status: [](https://travis-ci.com/pascallanger/DIY-Multiprotocol-TX-Module)
|
||||
|
||||
Current Multiprotocol boards check status: [](https://travis-ci.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards)
|
||||
|
||||
## Quicklinks
|
||||
* [Download latest releases of the firmware](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/releases) and [instructions to upload .hex files](docs/Advanced_Manually_Setting_ATmega328_Fuses.md)
|
||||
|
||||
27
buildroot/bin/build_release_avr_noboot
Normal file
27
buildroot/bin/build_release_avr_noboot
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
exitcode=0;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-avr-usbasp-aetr-A7105-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
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;
|
||||
|
||||
exit $exitcode;
|
||||
28
buildroot/bin/build_release_avr_optiboot
Normal file
28
buildroot/bin/build_release_avr_optiboot
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
exitcode=0;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-avr-txflash-aetr-A7105-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
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;
|
||||
|
||||
exit $exitcode;
|
||||
27
buildroot/bin/build_release_orx
Normal file
27
buildroot/bin/build_release_orx
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
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;
|
||||
|
||||
printf "\n\e[33;1mPackaging ancilliary files for v$MULTI_VERSION\e[0m\n";
|
||||
cp Multiprotocol/Multi.txt ./binaries/Multi.txt;
|
||||
mkdir -p SCRIPTS/TOOLS;
|
||||
cp Lua_scripts/*.lua SCRIPTS/TOOLS/;
|
||||
cp Lua_scripts/*.txt SCRIPTS/TOOLS/;
|
||||
zip -q ./binaries/MultiLuaScripts.zip SCRIPTS/TOOLS/*;
|
||||
|
||||
printf "\n";
|
||||
|
||||
exit $exitcode;
|
||||
12
buildroot/bin/build_release_stm32f1_native_debug
Normal file
12
buildroot/bin/build_release_stm32f1_native_debug
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
exitcode=0;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-stm-xn297dump-usbdebug-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_add XN297DUMP_NRF24L01_INO;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-xn297dump-usbdebug-v$MULTI_VERSION.bin;
|
||||
|
||||
exit $exitcode;
|
||||
71
buildroot/bin/build_release_stm32f1_no_debug
Normal file
71
buildroot/bin/build_release_stm32f1_no_debug
Normal file
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
exitcode=0;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-stm-serial-aetr-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_disable ENABLE_PPM;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-serial-aetr-v$MULTI_VERSION.bin;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-stm-serial-taer-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace AETR TAER;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-serial-taer-v$MULTI_VERSION.bin;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-stm-serial-reta-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace TAER RETA;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-serial-reta-v$MULTI_VERSION.bin;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-stm-cc2500-aetr-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace RETA AETR;
|
||||
opt_disable A7105_INSTALLED;
|
||||
opt_disable CYRF6936_INSTALLED;
|
||||
opt_disable NRF24L01_INSTALLED;
|
||||
opt_disable INVERT_TELEMETRY;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-cc2500-aetr-v$MULTI_VERSION.bin;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-stm-cc2500-taer-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace AETR TAER;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-cc2500-taer-v$MULTI_VERSION.bin;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-stm-cc2500-reta-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace TAER RETA;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-cc2500-reta-v$MULTI_VERSION.bin;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-stm-ppm-aetr-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_enable A7105_INSTALLED;
|
||||
opt_enable CYRF6936_INSTALLED;
|
||||
opt_enable NRF24L01_INSTALLED;
|
||||
opt_enable ENABLE_PPM;
|
||||
opt_disable ENABLE_SERIAL;
|
||||
opt_replace RETA AETR;
|
||||
opt_disable MULTI_STATUS;
|
||||
opt_disable MULTI_TELEMETRY;
|
||||
opt_set NBR_BANKS 5;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-ppm-aetr-v$MULTI_VERSION.bin;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-stm-ppm-taer-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace AETR TAER;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-ppm-taer-v$MULTI_VERSION.bin;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-stm-ppm-reta-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace TAER RETA;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-ppm-reta-v$MULTI_VERSION.bin;
|
||||
|
||||
exit $exitcode;
|
||||
12
buildroot/bin/build_release_stm32f1_serial_debug
Normal file
12
buildroot/bin/build_release_stm32f1_serial_debug
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
exitcode=0;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-stm-xn297dump-ftdidebug-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_add XN297DUMP_NRF24L01_INO;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-xn297dump-ftdidebug-v$MULTI_VERSION.bin;
|
||||
|
||||
exit $exitcode;
|
||||
24
buildroot/bin/build_release_stm32f1_t18int
Normal file
24
buildroot/bin/build_release_stm32f1_t18int
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
exitcode=0;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-t18int-aetr-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_disable ENABLE_PPM;
|
||||
opt_disable INVERT_TELEMETRY;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-t18int-aetr-v$MULTI_VERSION.bin;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-t18int-taer-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace AETR TAER;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-t18int-taer-v$MULTI_VERSION.bin;
|
||||
|
||||
printf "\n\e[33;1mBuilding multi-t18int-reta-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace TAER RETA;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-t18int-reta-v$MULTI_VERSION.bin;
|
||||
|
||||
exit $exitcode;
|
||||
@@ -6,9 +6,10 @@ To get the XN297L dump feature working on your module you must know:
|
||||
|
||||
Procedure to use the XN297L dump feature:
|
||||
1. Start the Multi module in serial debug mode with the Arduion IDE Serial Monitor open<br> <img src="images/Serial_Monitor_2.png" />
|
||||
1. Select the protocol 63 or "Custom 63" to enable the XN297L Dump protocol
|
||||
1. Select the protocol XN297DP, 63 or "Custom 63" to enable the XN297L Dump protocol
|
||||
1. This protocol parameters are:
|
||||
* sub_protocol or type or the second number after "Custom 63" is used to set the transmission speed: 0=250Kbps, 1=1Mbps and 2=2Mbps. Any other value will default to 1Mbps.
|
||||
* sub_protocol or type or the second number after "Custom 63" is used to set the transmission speed: 0=250Kbps, 1=1Mbps, 2=2Mbps and 3=Auto.
|
||||
* Auto is the recommended mode since it gives many information like channels, timing, order as well as finding bytes meaning
|
||||
* RX_num or Receiver number sets the address length 3, 4 or 5 bytes. Any other value will default to an address length of 5 bytes.
|
||||
* option sets the RF channel number used to receive packets between 0..84 . A value of -1 will automatically scan all channels one by one. Any other value will default to the RF channel 0.
|
||||
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
# Flashing from the Transmitter
|
||||
|
||||
For radios running erskyTx and OpenTX, there is an option to flash a precompiled firmware file to the multiprotocol module using the transmitter's Bootloader mode.
|
||||
For radios running erskyTx and OpenTX, there is an option to flash a precompiled firmware file to the multiprotocol module:
|
||||
- OpenTX: using the SD card browser
|
||||
- erskyTX : using the transmitter's Bootloader mode.
|
||||
|
||||
## Tools required
|
||||
* A compatible transmitter running an erskyTx bootloader v2.9 or newer. This is true for both OpenTX and erskyTx.
|
||||
What you need:
|
||||
* A precompiled multiprotocol firmware file (.hex for Atmega328p or .bin for STM32)
|
||||
* A **Flash from TX** bootloader installed on an Atmega328p or STM32 multiprotocol module
|
||||
* A means to get the firmware file onto the transmitter's SD card
|
||||
|
||||
## Radio bootloader and apps
|
||||
## OpenTX 2.3.3 or newer
|
||||
1. Copy the firmware file to the radio's SD card - it doesn't matter where you put it
|
||||
1. Switch the radio on normally and use the radio menu to locate the file on the SD card
|
||||
1. Highlight the file and press the ENTER button
|
||||
1. Choose Flash internal module or Flash external module as appropriate
|
||||
|
||||
## erskyTX
|
||||
|
||||
### How to check the bootloader version
|
||||
1. Push both horizontals trims inwards (close to each others) while powering on the radio
|
||||
@@ -35,9 +42,7 @@ For radios running erskyTx and OpenTX, there is an option to flash a precompiled
|
||||
1. Long press it and select `Flash bootloader`
|
||||
1. Check by rebooting the radio in bootloader mode that everything is [ok](###-How-to-check-the-bootloader-version)
|
||||
|
||||
**Note**: For OpenTX radio, this bootloader is an upgraded version of the existing bootloader shipped with OpenTX. It's providing you the exact same level of default features while adding more through apps. You can go back and forth between the 2 bootloaders without an issue.
|
||||
|
||||
## Multimodule upgrade procedure
|
||||
### Multimodule upgrade procedure
|
||||
1. Either:
|
||||
1. Connect the transmitter using a USB cable and power it on, or
|
||||
1. Remove the SD card from the transmitter and mount it using a suitable reader
|
||||
|
||||
@@ -23,7 +23,8 @@ Original FrSky, Futaba, Corona Hitec and HoTT receivers have been frequency-tune
|
||||
The procedure can be performed in serial or PPM mode, but is easier with in serial mode where the effect of the change can be seen in real-time.
|
||||
|
||||
### Preparation
|
||||
The radio needs to be bound with the receiver.
|
||||
The radio needs to be bound with the receiver in order to fine tune. If the receiver does not bind, use *coarse* tuning (varying the **Freq** value in steps of +/- 40) until the receiver binds.
|
||||
|
||||
1. Configure the radio with the appropriate protocol
|
||||
1. Set the **Freq** value to 0
|
||||
1. Put the receiver into **Binding** mode
|
||||
@@ -48,16 +49,16 @@ Connection is lost at -73 and +35; the median is -19:
|
||||
`(-73 + 35) / 2 = -19`
|
||||
|
||||
### Finally
|
||||
Once the **Freq** value is known it should be applied to all other models which use this protocol and, if they were previously bound, the receivers must be re-bound.
|
||||
|
||||
For convenience this can be applied once for all per protocol using the FORCE commands described below in `_Config.h` (or `_MyConfig.h`) configuration file.
|
||||
Usually all RXs using the same protocol&sub_protocol can use the same **Freq** value but it can't harm to do all of them.
|
||||
If you change the Freq value it is best to rebind the receiver(s).
|
||||
|
||||
#### Forced tuning values
|
||||
Once known-good tuning values have been determined, they can be stored in the configuration file to be automatically applied to all models which use the given protocol.
|
||||
|
||||
For convenience the freq value can be applied once for all per protocol using the FORCE commands described below in `_Config.h` (or `_MyConfig.h`) configuration file.
|
||||
These settings can also be used to force different tuning values for different multiprotocol modules, removing the need to alter the tuning option on the transmitter when swapping between modules. (Assuming that the modules also share a common hardware ID.)
|
||||
|
||||
**Note:** If a forced tuning value is set in the configuration, it cannot be overriden by the protocol's **Freq** option on the radio for any model.
|
||||
Once known-good tuning values have been determined, they can be stored in the configuration file to be automatically applied to all models which use the given protocol.
|
||||
|
||||
**Note:** If a forced tuning value is set in the configuration, the protocol's **Freq** option on the radio GUI will be ignored whatever the value is set to.
|
||||
|
||||
```
|
||||
/*******************************/
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
- **_Slower blink(on=1s,off=1s)_**: PPM has been selected but no valid signal is being seen on the PPM pin.
|
||||
- **_Fast double blink(on=0.1s,off=0.1s,on=0.1s,off=0.5s)_**: serial debugging is enabled and is waiting for a serial connection
|
||||
- **_On_**: Module is in normal operation mode (transmitting control signals).
|
||||
- **_SOS_**: Module's CPU does not match the minimum requirement of a full 128KB available/good flash. The module won't boot further. This has been introduced after finding out that some module's manufacturers are using wrong components which are causing unexpected behaviors with bad consequences...
|
||||
|
||||
## Protocol selection
|
||||
|
||||
|
||||
BIN
docs/images/warning.png
Normal file
BIN
docs/images/warning.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 104 KiB |
Reference in New Issue
Block a user