mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-11-25 13:29:40 +00:00
Compare commits
406 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03d0adbd74 | ||
|
|
905ee4b1ed | ||
|
|
dbc33951a4 | ||
|
|
732e66cab2 | ||
|
|
0dab92552a | ||
|
|
047952537a | ||
|
|
d4bf1fb36e | ||
|
|
ff817cd098 | ||
|
|
04ea44ed4b | ||
|
|
e23c8e2216 | ||
|
|
afb4802a2c | ||
|
|
3a5d341514 | ||
|
|
b6bcab1604 | ||
|
|
0a998d2dc5 | ||
|
|
7927bc601e | ||
|
|
f8cc913898 | ||
|
|
a5428bc180 | ||
|
|
c0285f81f0 | ||
|
|
600049898a | ||
|
|
0e1db8f06b | ||
|
|
ec83f1e5a3 | ||
|
|
f8f7769d9c | ||
|
|
4dacac29c6 | ||
|
|
593f3b87f1 | ||
|
|
bb70116df0 | ||
|
|
d7c24d62ed | ||
|
|
07df1a8959 | ||
|
|
ca9e2870ab | ||
|
|
99ca6fa36c | ||
|
|
3d82560f71 | ||
|
|
44d362aeb4 | ||
|
|
3d4ed5ad11 | ||
|
|
ca3c2bbdc8 | ||
|
|
90c226c748 | ||
|
|
b757283f41 | ||
|
|
b3132c7bf1 | ||
|
|
9ba56f040a | ||
|
|
ac71b4d981 | ||
|
|
6bb2c06cf6 | ||
|
|
2ad3c727fd | ||
|
|
d36af55b84 | ||
|
|
f19bb05c7a | ||
|
|
08ea8818fb | ||
|
|
59c541d013 | ||
|
|
37e2b5f41c | ||
|
|
614a330cf2 | ||
|
|
9106548859 | ||
|
|
2f07e79e50 | ||
|
|
2233f6f862 | ||
|
|
ae842f0bdc | ||
|
|
4b36656246 | ||
|
|
ea282489f9 | ||
|
|
6f2d9430d0 | ||
|
|
bccd9dc0d9 | ||
|
|
af919fb940 | ||
|
|
7dab0de3c5 | ||
|
|
2c0525421a | ||
|
|
0844ec2efd | ||
|
|
49c3af12f9 | ||
|
|
96d335f458 | ||
|
|
eae412fe41 | ||
|
|
0270420531 | ||
|
|
93bb117961 | ||
|
|
29d1fb00b1 | ||
|
|
5a49d99c4f | ||
|
|
d66bf1a5b3 | ||
|
|
b41dccef67 | ||
|
|
addf2c5143 | ||
|
|
ff829f1f7b | ||
|
|
7ee72976c4 | ||
|
|
dc18e8e5b2 | ||
|
|
97de2aaf3d | ||
|
|
3b8b2ef376 | ||
|
|
d496f62719 | ||
|
|
fc978f95ef | ||
|
|
596e8c9b55 | ||
|
|
0cf58c2990 | ||
|
|
6ba1c8b118 | ||
|
|
b949ac0fed | ||
|
|
510f892d2f | ||
|
|
17750e774a | ||
|
|
be1591c489 | ||
|
|
3b22705166 | ||
|
|
c05c0a5693 | ||
|
|
d6fc6a3517 | ||
|
|
7bfaee8b4f | ||
|
|
89c00e8f17 | ||
|
|
447a58966f | ||
|
|
74162aa972 | ||
|
|
78a1e61f7a | ||
|
|
a917227ddc | ||
|
|
c866d07743 | ||
|
|
43d969f962 | ||
|
|
3973b42f81 | ||
|
|
6046ad81db | ||
|
|
63a9874aea | ||
|
|
89420fe2d4 | ||
|
|
9769354989 | ||
|
|
580b996215 | ||
|
|
8f5fb5083f | ||
|
|
821076ce95 | ||
|
|
0bfe1f8e63 | ||
|
|
9c35f6f73c | ||
|
|
983debe6ce | ||
|
|
66704b5a13 | ||
|
|
f11da0c1de | ||
|
|
7676398aab | ||
|
|
9c6c55fa00 | ||
|
|
5b9ca3ba06 | ||
|
|
23141b6087 | ||
|
|
6d4b4bd2c0 | ||
|
|
5cec22a757 | ||
|
|
153ba2e090 | ||
|
|
21e8bed52b | ||
|
|
ecfc5b0313 | ||
|
|
2bcebbda45 | ||
|
|
52e8d87ab1 | ||
|
|
b613345da4 | ||
|
|
f2665ca786 | ||
|
|
e3189d3aed | ||
|
|
c829e1c86f | ||
|
|
8499a508f5 | ||
|
|
50dec0e55d | ||
|
|
6f419adb7f | ||
|
|
502e8beafb | ||
|
|
5aae065dc0 | ||
|
|
152dbed3fa | ||
|
|
b516bb8d20 | ||
|
|
30e3e84066 | ||
|
|
8338104266 | ||
|
|
00c6aa52b9 | ||
|
|
e5689d2f1b | ||
|
|
b51dedcea1 | ||
|
|
49f004e53f | ||
|
|
062fc05eac | ||
|
|
6d080d5d5f | ||
|
|
0955340a93 | ||
|
|
9b2318cc7e | ||
|
|
2098cdc5e0 | ||
|
|
d19b5187c5 | ||
|
|
2a78b1d6b7 | ||
|
|
84ae6366eb | ||
|
|
e5b235ac83 | ||
|
|
0195384592 | ||
|
|
0937f832fc | ||
|
|
c77b4af2a0 | ||
|
|
b943bae8dd | ||
|
|
4955978eb6 | ||
|
|
df409fddf5 | ||
|
|
0330c596e4 | ||
|
|
8c6c58f12f | ||
|
|
4bc08d22b8 | ||
|
|
96fb3b20b7 | ||
|
|
47f713c6c8 | ||
|
|
443c7a6b99 | ||
|
|
e79ca9b7d7 | ||
|
|
b94f774f80 | ||
|
|
5614e8bef6 | ||
|
|
4ce3a5d298 | ||
|
|
f6de3de78c | ||
|
|
8099018132 | ||
|
|
360dde2e1b | ||
|
|
cc7b7638d3 | ||
|
|
321e4aee34 | ||
|
|
f18847df57 | ||
|
|
a2559a65d3 | ||
|
|
5ac41fdd15 | ||
|
|
6d38dd2d7a | ||
|
|
667058269c | ||
|
|
ad6f934892 | ||
|
|
714220c349 | ||
|
|
4887fca873 | ||
|
|
cfe80edcb6 | ||
|
|
484588ff6b | ||
|
|
1bb059c2a2 | ||
|
|
ef5d9cb6b3 | ||
|
|
37a06c050d | ||
|
|
5f0ed395ba | ||
|
|
ae27c8b671 | ||
|
|
088bfb9c2f | ||
|
|
b01462e36b | ||
|
|
abd36dc6a4 | ||
|
|
ebb8a33c1a | ||
|
|
2b0f663482 | ||
|
|
956e632392 | ||
|
|
90b6bb8f7d | ||
|
|
6153e84abf | ||
|
|
16357f29e9 | ||
|
|
0b8a5a7539 | ||
|
|
6874e3a6a7 | ||
|
|
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 |
195
.github/workflows/main.yml
vendored
Normal file
195
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
# Workflow for testing MULTI-Module firmware builds
|
||||
|
||||
name: CI
|
||||
|
||||
on:
|
||||
# Trigger the workflow on pushes, except those that are tagged (avoids double-testing releases)
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
tags-ignore:
|
||||
- '**'
|
||||
paths:
|
||||
- '.github/workflows/**'
|
||||
- 'buildroot/bin/**'
|
||||
- 'Multiprotocol/**'
|
||||
|
||||
# Trigger the workflow on pull requests to the master branch
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '.github/workflows/**'
|
||||
- 'buildroot/bin/**'
|
||||
- 'Multiprotocol/**'
|
||||
|
||||
# Triggers the workflow on release creation
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
|
||||
# Allows the workflow to be triggered manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Configure the board matrix
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
board: [
|
||||
"multi4in1:avr:multiatmega328p:bootloader=none",
|
||||
"multi4in1:avr:multiatmega328p:bootloader=optiboot",
|
||||
"multi4in1:avr:multixmega32d4",
|
||||
"multi4in1:STM32F1:multi5in1t18int",
|
||||
"multi4in1:STM32F1:multistm32f103cb:debug_option=none",
|
||||
"multi4in1:STM32F1:multistm32f103cb:debug_option=native",
|
||||
"multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi",
|
||||
"multi4in1:STM32F1:multistm32f103c8:debug_option=none"
|
||||
]
|
||||
|
||||
# Set the environment variables
|
||||
env:
|
||||
BOARD: ${{ matrix.board }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Arduino CLI
|
||||
uses: arduino/setup-arduino-cli@v1.1.1
|
||||
|
||||
- name: Prepare build environment
|
||||
run: |
|
||||
echo "Github Ref: $GITHUB_REF"
|
||||
echo "Event name: ${{ github.event_name }}"
|
||||
echo "Event action: ${{ github.event.action }}"
|
||||
echo "Tag name: ${{ github.event.release.tag_name }}"
|
||||
|
||||
arduino-cli config init --additional-urls https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/master/package_multi_4in1_board_index.json
|
||||
arduino-cli core update-index
|
||||
|
||||
if [[ "$BOARD" =~ "multi4in1:avr:" ]]; then
|
||||
arduino-cli core install arduino:avr;
|
||||
arduino-cli core install multi4in1:avr
|
||||
fi
|
||||
|
||||
if [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
|
||||
arduino-cli core install multi4in1:STM32F1
|
||||
fi
|
||||
|
||||
chmod +x ${GITHUB_WORKSPACE}/buildroot/bin/*
|
||||
echo "${GITHUB_WORKSPACE}/buildroot/bin" >> $GITHUB_PATH
|
||||
|
||||
mkdir ./build
|
||||
mkdir ./binaries
|
||||
|
||||
- name: Configure MULTI-Module firmware options
|
||||
run: |
|
||||
# Load the build functions
|
||||
source ./buildroot/bin/buildFunctions;
|
||||
|
||||
# Get the version
|
||||
getMultiVersion
|
||||
echo "MULTI_VERSION=$(echo $MULTI_VERSION)" >> $GITHUB_ENV
|
||||
|
||||
# Get all the protocols for this board
|
||||
getAllProtocols
|
||||
echo "A7105_PROTOCOLS=$(echo $A7105_PROTOCOLS)" >> $GITHUB_ENV
|
||||
echo "CC2500_PROTOCOLS=$(echo $CC2500_PROTOCOLS)" >> $GITHUB_ENV
|
||||
echo "CYRF6936_PROTOCOLS=$(echo $CYRF6936_PROTOCOLS)" >> $GITHUB_ENV
|
||||
echo "NRF24L01_PROTOCOLS=$(echo $NRF24L01_PROTOCOLS)" >> $GITHUB_ENV
|
||||
echo "SX1276_PROTOCOLS=$(echo $SX1276_PROTOCOLS)" >> $GITHUB_ENV
|
||||
echo "CCNRF_INO_PROTOCOLS=$(echo $CCNRF_INO_PROTOCOLS)" >> $GITHUB_ENV
|
||||
echo "ALL_PROTOCOLS=$(echo $ALL_PROTOCOLS)" >> $GITHUB_ENV
|
||||
|
||||
# Get all the RF modules for this board
|
||||
getAllRFModules
|
||||
echo "ALL_RFMODULES=$(echo $ALL_RFMODULES)" >> $GITHUB_ENV
|
||||
|
||||
# Disable CHECK_FOR_BOOTLOADER when not needed
|
||||
if [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=none" ]]; then
|
||||
opt_disable CHECK_FOR_BOOTLOADER;
|
||||
fi
|
||||
|
||||
# Trim the build down for the Atmega328p board
|
||||
if [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:" ]]; then
|
||||
opt_disable $ALL_PROTOCOLS
|
||||
opt_enable FRSKYX_CC2500_INO AFHDS2A_A7105_INO MJXQ_NRF24L01_INO DSM_CYRF6936_INO;
|
||||
fi
|
||||
|
||||
# Trim the enabled protocols down for the STM32F103CB board with debugging or the STM32F103C8 board in general
|
||||
if [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=ftdi" ]] || [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=native" ]] || [[ "$BOARD" =~ "multi4in1:STM32F1:multistm32f103c8" ]]; then
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable FRSKYX_CC2500_INO AFHDS2A_A7105_INO MJXQ_NRF24L01_INO DSM_CYRF6936_INO;
|
||||
fi
|
||||
|
||||
- name: Save default firmware configuration
|
||||
run: |
|
||||
cat Multiprotocol/_Config.h
|
||||
cp Multiprotocol/_Config.h ./_Config.h.bak
|
||||
|
||||
- name: Build default configuration
|
||||
run: |
|
||||
# Skip the default build for boards where it's too large now
|
||||
if [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103cb:debug_option=none" ]] || [[ "$BOARD" == "multi4in1:STM32F1:multi5in1t18int" ]]; then
|
||||
printf "Not testing default build for $BOARD.";
|
||||
else
|
||||
source ./buildroot/bin/buildFunctions;
|
||||
buildMulti
|
||||
fi
|
||||
|
||||
- name: Build serial only
|
||||
run: |
|
||||
source ./buildroot/bin/buildFunctions;
|
||||
cp ./_Config.h.bak Multiprotocol/_Config.h
|
||||
opt_disable ENABLE_PPM;
|
||||
buildMulti;
|
||||
|
||||
- name: Build PPM only
|
||||
run: |
|
||||
source ./buildroot/bin/buildFunctions;
|
||||
cp ./_Config.h.bak Multiprotocol/_Config.h
|
||||
opt_disable ENABLE_SERIAL;
|
||||
buildMulti;
|
||||
|
||||
- name: Build each RF module individually
|
||||
run: |
|
||||
source ./buildroot/bin/buildFunctions;
|
||||
cp ./_Config.h.bak Multiprotocol/_Config.h;
|
||||
buildEachRFModule;
|
||||
|
||||
- name: Build each protocol individually
|
||||
run: |
|
||||
source ./buildroot/bin/buildFunctions;
|
||||
cp ./_Config.h.bak Multiprotocol/_Config.h;
|
||||
buildEachProtocol;
|
||||
|
||||
- name: Build release files
|
||||
run: |
|
||||
source ./buildroot/bin/buildFunctions;
|
||||
cp ./_Config.h.bak Multiprotocol/_Config.h;
|
||||
buildReleaseFiles;
|
||||
ls -al ./binaries;
|
||||
|
||||
NUM_FILES=$(ls -l ./binaries | grep ^- | wc -l);
|
||||
if [ $NUM_FILES -gt 0 ]; then
|
||||
echo "HAVE_FILES=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "HAVE_FILES=false" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Deploy files to release
|
||||
if: github.event_name == 'release' && github.event.action == 'created' && env.HAVE_FILES == 'true'
|
||||
uses: AButler/upload-release-assets@v2.0
|
||||
with:
|
||||
files: './binaries/*'
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: 'Upload Artifacts'
|
||||
if: env.HAVE_FILES == 'true'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: multi-test-build
|
||||
path: ./binaries/
|
||||
362
.travis.yml
362
.travis.yml
@@ -1,362 +0,0 @@
|
||||
dist: bionic
|
||||
sudo: true
|
||||
language: c
|
||||
|
||||
env:
|
||||
global:
|
||||
- IDE_VERSION=1.8.9
|
||||
matrix:
|
||||
- BOARD="multi4in1:avr:multiatmega328p:bootloader=none"
|
||||
- BOARD="multi4in1:avr:multiatmega328p:bootloader=optiboot"
|
||||
- BOARD="multi4in1:avr:multixmega32d4"
|
||||
- BOARD="multi4in1:STM32F1:multistm32f103c:debug_option=none"
|
||||
- BOARD="multi4in1:STM32F1:multistm32f103c:debug_option=native"
|
||||
- BOARD="multi4in1:STM32F1:multistm32f103c:debug_option=ftdi"
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
before_install:
|
||||
# Fetch the tag information for the current branch
|
||||
- git fetch origin --tags
|
||||
|
||||
# Publish the buildroot script folder
|
||||
- chmod +x ${TRAVIS_BUILD_DIR}/buildroot/bin/*
|
||||
- export PATH=${TRAVIS_BUILD_DIR}/buildroot/bin/:${PATH}
|
||||
|
||||
# Arduino IDE adds a lot of noise caused by network traffic; firewall it
|
||||
- sudo iptables -P INPUT DROP
|
||||
- sudo iptables -P FORWARD DROP
|
||||
- sudo iptables -P OUTPUT ACCEPT
|
||||
- sudo iptables -A INPUT -i lo -j ACCEPT
|
||||
- sudo iptables -A OUTPUT -o lo -j ACCEPT
|
||||
- sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
# Helper functions for the builds
|
||||
- buildMulti() { start_fold config_diff; travis_time_start; git diff Multiprotocol/_Config.h; end_fold config_diff; exitcode=0; BUILDCMD="arduino --verify --board $BOARD Multiprotocol/Multiprotocol.ino --pref build.path=./build/"; echo $BUILDCMD; $BUILDCMD; if [ $? -ne 0 ]; then exitcode=1; fi; echo; return $exitcode; }
|
||||
- buildProtocol() { exitcode=0; opt_disable $ALL_PROTOCOLS; opt_enable $1; buildMulti; if [ $? -ne 0 ]; then exitcode=1; fi; return $exitcode; }
|
||||
- buildEachProtocol() { exitcodesum=0; for PROTOCOL in $ALL_PROTOCOLS ; do printf "\e[33;1mBuilding $PROTOCOL\e[0m"; buildProtocol $PROTOCOL; if [ $? -ne 0 ]; then exitcodesum=$((exitcodesum + 1)); fi; done; return $exitcodesum; }
|
||||
- buildRFModule() { exitcode=0; opt_disable $ALL_RFMODULES; opt_enable $1; buildMulti; if [ $? -ne 0 ]; then exitcode=1; fi; return $exitcode; }
|
||||
- buildEachRFModule() { exitcodesum=0; for RFMODULE in $ALL_RFMODULES; do printf "\e[33;1mBuilding $RFMODULE\e[0m"; buildRFModule $RFMODULE; if [ $? -ne 0 ]; then exitcodesum=$((exitcodesum + 1)); fi; done; return $exitcodesum; }
|
||||
- buildDefault() { exitcode=0; printf "\n\e[33;1mBuilding default configuration\e[0m\n"; buildMulti; if [ $? -ne 0 ]; then exitcode=1; fi; return $exitcode; }
|
||||
- buildSerialOnly() { exitcode=0; printf "\n\e[33;1mBuilding serial mode only\e[0m\n"; opt_disable ENABLE_PPM; opt_enable ENABLE_SERIAL; buildMulti; if [ $? -ne 0 ]; then exitcode=1; fi; return $exitcode; }
|
||||
- buildPPMOnly() { exitcode=0; printf "\n\e[33;1mBuilding PPM mode only\e[0m\n"; opt_enable ENABLE_PPM; opt_disable ENABLE_SERIAL; buildMulti; if [ $? -ne 0 ]; then exitcode=1; fi; return $exitcode; }
|
||||
|
||||
# Function to build the release files - dependent on board type
|
||||
- if [[ "$BOARD" == "multi4in1:avr:multixmega32d4" ]]; then
|
||||
buildReleaseFiles(){
|
||||
exitcode=0;
|
||||
printf "\n\e[33;1mBuilding multi-orangerx-aetr-green-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_enable $ALL_PROTOCOLS;
|
||||
opt_disable ORANGE_TX_BLUE;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-orangerx-aetr-green-inv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-orangerx-aetr-blue-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_enable ORANGE_TX_BLUE;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-orangerx-aetr-blue-inv-v$MULTI_VERSION.bin;
|
||||
cp Multiprotocol/Multi.txt ./binaries/Multi.txt;
|
||||
return $exitcode; };
|
||||
elif [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=none" ]]; then
|
||||
buildReleaseFiles(){
|
||||
printf "\n\e[33;1mBuilding multi-avr-usbasp-aetr-A7105-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
exitcode=0;
|
||||
opt_disable CHECK_FOR_BOOTLOADER;
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable $A7105_PROTOCOLS;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-usbasp-aetr-A7105-inv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-avr-usbasp-aetr-CC2500-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable $CC2500_PROTOCOLS;
|
||||
buildMulti;
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-usbasp-aetr-CC2500-inv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-avr-usbasp-aetr-CYRF6936-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable $CYRF6936_PROTOCOLS;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-usbasp-aetr-CYRF6936-inv-v$MULTI_VERSION.bin;
|
||||
return $exitcode; };
|
||||
elif [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=optiboot" ]]; then
|
||||
buildReleaseFiles(){
|
||||
printf "\n\e[33;1mBuilding multi-avr-txflash-aetr-A7105-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
exitcode=0;
|
||||
opt_enable CHECK_FOR_BOOTLOADER;
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable $A7105_PROTOCOLS;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-txflash-aetr-A7105-inv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-avr-txflash-aetr-CC2500-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable $CC2500_PROTOCOLS;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-txflash-aetr-CC2500-inv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-avr-txflash-aetr-CYRF6936-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable $CYRF6936_PROTOCOLS;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-avr-txflash-aetr-CYRF6936-inv-v$MULTI_VERSION.bin;
|
||||
return $exitcode; };
|
||||
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c:debug_option=none" ]]; then
|
||||
buildReleaseFiles(){
|
||||
printf "\n\e[33;1mBuilding multi-stm-erskytx-aetr-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
exitcode=0;
|
||||
opt_enable CHECK_FOR_BOOTLOADER;
|
||||
opt_enable $ALL_PROTOCOLS;
|
||||
opt_enable MULTI_STATUS;
|
||||
opt_disable MULTI_TELEMETRY;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-aetr-inv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-erskytx-taer-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace AETR TAER;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-taer-inv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-erskytx-reta-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace TAER RETA;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-reta-inv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-erskytx-aetr-noinv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace RETA AETR;
|
||||
opt_disable INVERT_TELEMETRY;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-aetr-noinv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-erskytx-taer-noinv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace AETR TAER;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-taer-noinv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-erskytx-reta-noinv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace TAER RETA;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-reta-noinv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-opentx-aetr-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace RETA AETR;
|
||||
opt_disable MULTI_STATUS;
|
||||
opt_enable MULTI_TELEMETRY;
|
||||
opt_enable INVERT_TELEMETRY;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-aetr-inv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-opentx-taer-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace AETR TAER;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-taer-inv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-opentx-reta-inv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace TAER RETA;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-reta-inv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-opentx-aetr-noinv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace RETA AETR;
|
||||
opt_disable INVERT_TELEMETRY;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-aetr-noinv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-opentx-taer-noinv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace AETR TAER;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-taer-noinv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-opentx-reta-noinv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace TAER RETA;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-reta-noinv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-ppm-aetr-noinv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace RETA AETR;
|
||||
opt_disable MULTI_STATUS;
|
||||
opt_disable MULTI_TELEMETRY;
|
||||
opt_set NBR_BANKS 5;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-ppm-aetr-noinv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-ppm-taer-noinv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace AETR TAER;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-ppm-taer-noinv-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-ppm-reta-noinv-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_replace TAER RETA;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-ppm-reta-noinv-v$MULTI_VERSION.bin;
|
||||
return $exitcode; };
|
||||
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c:debug_option=native" ]]; then
|
||||
buildReleaseFiles(){
|
||||
printf "\n\e[33;1mBuilding multi-stm-erskytx-xn297dump-inv-usbdebug-v$MULTI_VERSION.bin\e[0m";
|
||||
exitcode=0;
|
||||
opt_enable CHECK_FOR_BOOTLOADER;
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_add XN297DUMP_NRF24L01_INO;
|
||||
opt_enable MULTI_STATUS;
|
||||
opt_disable MULTI_TELEMETRY;
|
||||
opt_enable INVERT_TELEMETRY;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-xn297dump-inv-usbdebug-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-opentx-xn297dump-inv-usbdebug-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_disable MULTI_STATUS;
|
||||
opt_enable MULTI_TELEMETRY;
|
||||
opt_enable INVERT_TELEMETRY;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-xn297dump-inv-usbdebug-v$MULTI_VERSION.bin;
|
||||
return $exitcode; };
|
||||
elif [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c:debug_option=ftdi" ]]; then
|
||||
buildReleaseFiles(){
|
||||
printf "\n\e[33;1mBuilding multi-stm-erskytx-xn297dump-inv-ftdidebug-v$MULTI_VERSION.bin\e[0m";
|
||||
exitcode=0;
|
||||
opt_enable CHECK_FOR_BOOTLOADER;
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_add XN297DUMP_NRF24L01_INO;
|
||||
opt_enable MULTI_STATUS;
|
||||
opt_disable MULTI_TELEMETRY;
|
||||
opt_enable INVERT_TELEMETRY;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-erskytx-xn297dump-inv-ftdidebug-v$MULTI_VERSION.bin;
|
||||
printf "\n\e[33;1mBuilding multi-stm-opentx-xn297dump-inv-ftdidebug-v$MULTI_VERSION.bin\e[0m";
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_disable MULTI_STATUS;
|
||||
opt_enable MULTI_TELEMETRY;
|
||||
opt_enable INVERT_TELEMETRY;
|
||||
buildMulti;
|
||||
exitcode=$((exitcode+$?));
|
||||
mv build/Multiprotocol.ino.bin ./binaries/multi-stm-opentx-xn297dump-inv-ftdidebug-v$MULTI_VERSION.bin;
|
||||
return $exitcode; };
|
||||
else
|
||||
buildReleaseFiles() { echo "No release files for this board."; };
|
||||
fi
|
||||
|
||||
install:
|
||||
# Install Arduino IDE
|
||||
- wget http://downloads.arduino.cc/arduino-$IDE_VERSION-linux64.tar.xz
|
||||
- tar xf arduino-$IDE_VERSION-linux64.tar.xz
|
||||
- mv arduino-$IDE_VERSION $HOME/arduino-ide
|
||||
- export PATH=$PATH:$HOME/arduino-ide
|
||||
|
||||
# Set the Multi boards package URL
|
||||
- arduino --pref "boardsmanager.additional.urls=https://raw.githubusercontent.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/master/package_multi_4in1_board_index.json" --save-prefs
|
||||
|
||||
# Install the STM32 board if needed
|
||||
- if [[ "$BOARD" =~ "multi4in1:STM32F1:" ]]; then
|
||||
arduino --install-boards multi4in1:STM32F1;
|
||||
fi
|
||||
|
||||
# Install the AVR board if needed
|
||||
- if [[ "$BOARD" =~ "multi4in1:avr:" ]]; then
|
||||
arduino --install-boards multi4in1:avr;
|
||||
fi
|
||||
|
||||
before_script:
|
||||
# Change current working directory to the build dir
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
|
||||
# Create somwhere to put the exported binaries
|
||||
- mkdir ./binaries
|
||||
|
||||
# Log the initial Multi config
|
||||
- cat Multiprotocol/_Config.h
|
||||
|
||||
# Back up the configuration
|
||||
- cp Multiprotocol/_Config.h ./_Config.h.bak
|
||||
|
||||
# Get the firmware version number from the source
|
||||
- MAJOR_VERSION=$(grep "VERSION_MAJOR" "Multiprotocol/Multiprotocol.h" | awk -v N=3 '{gsub(/\r/,""); print $N}')
|
||||
- MINOR_VERSION=$(grep "VERSION_MINOR" "Multiprotocol/Multiprotocol.h" | awk -v N=3 '{gsub(/\r/,""); print $N}')
|
||||
- REVISION_VERSION=$(grep "VERSION_REVISION" "Multiprotocol//Multiprotocol.h" | awk -v N=3 '{gsub(/\r/,""); print $N}')
|
||||
- PATCH_VERSION=$(grep "VERSION_PATCH" "Multiprotocol//Multiprotocol.h" | awk -v N=3 '{gsub(/\r/,""); print $N}')
|
||||
- MULTI_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$REVISION_VERSION.$PATCH_VERSION
|
||||
|
||||
# Derive the Multi protocols from the Multi source
|
||||
- A7105_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_A7105_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
|
||||
- CC2500_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_CC2500_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
|
||||
- CYRF6936_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_CYRF6936_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
|
||||
- NRF24L01_PROTOCOLS=$(sed -n 's/[\/\/]*[[:blank:]]*#define[[:blank:]]*\([[:alnum:]_]*_NRF24L01_INO\)\(.*\)/\1/p' Multiprotocol/_Config.h)
|
||||
- if [[ "$BOARD" =~ "multi4in1:avr:multixmega32d4" ]]; then
|
||||
ALL_PROTOCOLS=$(echo $CYRF6936_PROTOCOLS);
|
||||
else
|
||||
ALL_PROTOCOLS=$(echo $A7105_PROTOCOLS $CC2500_PROTOCOLS $CYRF6936_PROTOCOLS $NRF24L01_PROTOCOLS);
|
||||
fi
|
||||
- echo $ALL_PROTOCOLS
|
||||
|
||||
# Declare all the installed modules
|
||||
- ALL_RFMODULES=$(echo A7105_INSTALLED CYRF6936_INSTALLED CC2500_INSTALLED NRF24L01_INSTALLED);
|
||||
|
||||
# Disable CHECK_FOR_BOOTLOADER when not needed
|
||||
- if [[ "$BOARD" == "multi4in1:avr:multiatmega328p:bootloader=none" ]]; then
|
||||
opt_disable CHECK_FOR_BOOTLOADER;
|
||||
fi
|
||||
|
||||
# Trim the enabled protocols down for the STM32 board with debugging
|
||||
- if [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c:debug_option=ftdi" ]] || [[ "$BOARD" == "multi4in1:STM32F1:multistm32f103c:debug_option=native" ]]; then
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable FRSKYX_CC2500_INO AFHDS2A_A7105_INO MJXQ_NRF24L01_INO DSM_CYRF6936_INO;
|
||||
fi
|
||||
|
||||
# Trim the enabled protocols down for the Atmega328p board
|
||||
- if [[ "$BOARD" =~ "multi4in1:avr:multiatmega328p:" ]]; then
|
||||
opt_disable $ALL_PROTOCOLS;
|
||||
opt_enable FRSKYX_CC2500_INO AFHDS2A_A7105_INO MJXQ_NRF24L01_INO DSM_CYRF6936_INO;
|
||||
fi
|
||||
|
||||
# Useful Travis functions
|
||||
- export -f travis_fold
|
||||
- export -f travis_nanoseconds
|
||||
- export -f travis_time_start
|
||||
- export -f travis_time_finish
|
||||
- start_fold() { echo -e "travis_fold:start:$1"; }
|
||||
- end_fold() { echo -e "\ntravis_fold:end:$1\r"; }
|
||||
|
||||
script:
|
||||
# Build with default configuration - all protocols are enabled for STM32; a subset of protocols for Atmega or STM32 debugging
|
||||
- buildDefault
|
||||
|
||||
# Serial only
|
||||
- buildSerialOnly
|
||||
|
||||
# PPM only
|
||||
- buildPPMOnly
|
||||
|
||||
# Re-enable PPM and serial
|
||||
- opt_enable ENABLE_SERIAL
|
||||
- opt_enable ENABLE_PPM
|
||||
|
||||
# Build for each RF module individually
|
||||
- buildEachRFModule
|
||||
|
||||
# Restore the default configuration
|
||||
- cp ./_Config.h.bak Multiprotocol/_Config.h
|
||||
|
||||
# Build each protocol individually
|
||||
- buildEachProtocol
|
||||
|
||||
# Restore the default configuration
|
||||
- cp ./_Config.h.bak Multiprotocol/_Config.h
|
||||
|
||||
# Builds the files for a release - always built, but only copied to Github if the test is tagged as a release
|
||||
- buildReleaseFiles
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: KGXaoqvd8rbZ3AZtL9Rrn1JYiocGsPaihRUyR8gM8vTfvH9WYAE1+h6SzROQOuJSwr89MvTo3SBOTlM/0PDBnEGLec9Irt7cwO0xf9xM2vPuUG8DYcUzmJJzME9dkn/7qHof1JGgRpp1duUAN1triE9NxhKxL1hbs+tUUbDPAejxwoFNfnta/T4PfD6xmkZNJbneIfYFuFgyLpwwFhuUy9JP7s1AFOiT+fCHxPaZrPn5GsXqAi95Cb7Q3w1iVSt3BmrGxL2j3CeNpWzFY1RrMdc8ay+ppOhSPEIl2vyM7VeLRRBL3EVeFWkiS4ywevqw70wOivTczluv3OeuIJAe5o2UU+w5+59c7+i44Nih23PDAZBhAG5JkLUYUN0XUJpXJ5ZlZsb8IS8sI1txlZa5tNVoXO9+soGEY4rKSpZaPptuENm792CzzAjcaUI9pOFJ/0CBoSCbu5MpM/plkJCMd8fY27EE8cNYvolMuRATNlXs7h9mURGR69pmcR1jFShH+A7Kyp1S1sH19sGCEU16rt2aAtf2FadFg/gKACC2y9rB3wBb4Qnapu2AwNRlTYNuU1+G+kb2FXRwMl04q+38S+cIBHH9NHfdftp9MRPf8Ekatojs92be/Ux21S+hcA7sx/DV22Dl45V6l4mXzR7U4x1nQcdn1SGuy5I4lL6IYCk=
|
||||
skip_cleanup: true
|
||||
file_glob: true
|
||||
file: binaries/*
|
||||
on:
|
||||
tags: true
|
||||
@@ -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
|
||||
|
||||
@@ -170,6 +170,24 @@
|
||||
],
|
||||
"toolsDependencies": []
|
||||
},
|
||||
{
|
||||
"name": "MULTI-Module AVR Boards",
|
||||
"architecture": "avr",
|
||||
"version": "1.1.1",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_avr_board_v1.1.1.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_avr_board_v1.1.1.tar.gz",
|
||||
"checksum": "SHA-256:02158258b4dbaca61bedbb6933336200d13b02ad0db981e2dda253682c482e99",
|
||||
"size": "324512",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)"},
|
||||
{"name": "Multi 4-in-1 (OrangeRX)"}
|
||||
],
|
||||
"toolsDependencies": []
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 STM32 Board",
|
||||
"architecture": "STM32F1",
|
||||
@@ -527,6 +545,95 @@
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi X-in-1 STM32 Boards",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.1.8",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.1.8.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.1.8.tar.gz",
|
||||
"checksum": "SHA-256:e9ed8055ebf72abf37e60e1b8d1c6ee5472132ea7c0a3c4a63fbb8442613e4c2",
|
||||
"size": "7481800",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (STM32F103C)"},
|
||||
{"name": "Multi 5-in-1 (Jumper T18 Internal)"}
|
||||
],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi X-in-1 STM32 Boards",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.2.0",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.2.0.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.2.0.tar.gz",
|
||||
"checksum": "SHA-256:754f08ca2a553701cc9112b645c079b6041107f1bf863648305e560c136a6ac5",
|
||||
"size": "7496214",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (STM32F103C)"},
|
||||
{"name": "Multi 5-in-1 (Jumper T18 Internal)"}
|
||||
],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi X-in-1 STM32 Boards",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.2.1",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.2.1.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.2.1.tar.gz",
|
||||
"checksum": "SHA-256:c66d34afadc5b21e9e28c4d477fa03a6d55db0b74b59ff2dcb07b4d6ef06da1a",
|
||||
"size": "7496448",
|
||||
"boards": [
|
||||
{"name": "Multi 4-in-1 (STM32F103C)"},
|
||||
{"name": "Multi 5-in-1 (Jumper T18 Internal)"}
|
||||
],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "MULTI-Module STM32 Boards",
|
||||
"architecture": "STM32F1",
|
||||
"version": "1.2.2",
|
||||
"category": "Contributed",
|
||||
"help": {
|
||||
"online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module"
|
||||
},
|
||||
"url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module-Boards/raw/master/archives/package_multi_4in1_stm32_board_v1.2.2.tar.gz",
|
||||
"archiveFileName": "package_multi_4in1_stm32_board_v1.2.2.tar.gz",
|
||||
"checksum": "SHA-256:0fe4a8899438bbc31dc37714acca13968e43d75a47e59143343d83b634d2e47d",
|
||||
"size": "7485662",
|
||||
"boards": [
|
||||
{"name": "Multi X-in-1 STM32F103CB (128KB)"},
|
||||
{"name": "Multi X-in-1 STM32F103C8 (64KB)"},
|
||||
{"name": "Multi 5-in-1 (Jumper T18 Internal)"}
|
||||
],
|
||||
"toolsDependencies": [{
|
||||
"packager": "arduino",
|
||||
"name": "arm-none-eabi-gcc",
|
||||
"version": "4.8.3-2014q1"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "Multi 4-in-1 OrangeRX Board - DEPRECATED, USE MULTI 4-IN-1 AVR BOARDS PACKAGE INSTEAD",
|
||||
"architecture": "orangerx",
|
||||
|
||||
601
Lua_scripts/DSM FwdPrg.lua
Normal file
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 }
|
||||
192
Lua_scripts/MultiChan.txt
Normal file
192
Lua_scripts/MultiChan.txt
Normal file
@@ -0,0 +1,192 @@
|
||||
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
|
||||
59,1,BayangRX,CPPM,1,AnAux1,AnAux2,Flip,RTH,Pict,Video
|
||||
41,0,Bugs,3-6-8,0,Arm,Angle,Flip,Pict,Video,LED
|
||||
42,0,BugsMini,Mini,0,Arm,Angle,Flip,Pict,Video,LED
|
||||
42,1,BugsMini,3H,0,Arm,Angle,Flip,Pict,Video,LED,AltHol
|
||||
34,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
|
||||
70,1,DSM_RX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||
45,0,E01X,E012,1,n-a,Flip,n-a,HLess,RTH
|
||||
45,1,E01X,E015,1,Arm,Flip,LED,HLess,RTH
|
||||
45,2,E01X,E016H,1,Stop,Flip,n-a,HLess,RTH
|
||||
16,0,ESKY,Std,0,Gyro,Pitch
|
||||
16,1,ESKY,ET4,0,Gyro,Pitch
|
||||
35,0,ESKY150,4CH,0
|
||||
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
|
||||
56,1,Flysky2A_RX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
53,0,Height,5ch,0,Gear
|
||||
53,1,Height,8ch,0,Gear,Gyro,Flap,Light
|
||||
25,0,FrSkyV,V8,0,CH5,CH6,CH7,CH8
|
||||
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
|
||||
55,2,FrSkyRX,EraseTX,0
|
||||
55,3,FrSkyRX,CPPM,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
58,0,FX816,P38,1
|
||||
20,0,FY326,FY326,1,Flip,RTH,HLess,Expert,Calib
|
||||
20,1,FY326,FY319,1,Flip,RTH,HLess,Expert,Calib
|
||||
23,0,FY326,FY326,1,Flip,RTH,HLess,Expert
|
||||
47,0,GD00x,V1,1,Trim,LED,Rate
|
||||
47,1,GD00x,V2,1,Trim,LED,Rate
|
||||
32,0,GW008,FY326,1,Flip
|
||||
36,0,H8_3D,Std,1,Flip,Light,Pict,Video,RTH,FlMode,Cal1
|
||||
36,1,H8_3D,H20H,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||
36,2,H8_3D,H20,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||
36,3,H8_3D,H30,1,Flip,Light,Pict,Video,Opt1,Opt2,Cal1,Cal2,Gimbal
|
||||
4,0,Hisky,Std,0,Gear,Pitch,Gyro,CH8
|
||||
4,1,Hisky,HK310,0,Aux
|
||||
39,0,Hitec,Opt_Fw,0,CH5,CH6,CH7,CH8,CH9
|
||||
39,1,Hitec,Opt_Hub,0,CH5,CH6,CH7,CH8,CH9
|
||||
39,2,Hitec,Minima,0,CH5,CH6,CH7,CH8,CH9
|
||||
26,0,Hontai,Std,1,Flip,LED,Pict,Video,HLess,RTH,Calib
|
||||
26,1,Hontai,JJRCX1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||
26,2,Hontai,X5C1,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||
26,3,Hontai,FQ777_951,1,Flip,Arm,Pict,Video,HLess,RTH,Calib
|
||||
57,0,HoTT,Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
57,1,HoTT,No_Sync,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
2,0,Hubsan,H107,1,Flip,Light,Pict,Video,HLess
|
||||
2,1,Hubsan,H301,0,RTH,Light,Stab,Video
|
||||
2,2,Hubsan,H501,0,RTH,Light,Pict,Video,HLess,GPS_H,ALT_H,Flip,FModes
|
||||
22,0,J6Pro,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12
|
||||
71,0,JJRC345,JJRC345,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
|
||||
71,1,JJRC345,SkyTmblr,1,Flip,HLess,RTH,LED,UNK1,UNK2,UNK3
|
||||
49,0,KF606,Std,1,Trim
|
||||
9,0,KN,WLToys,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
|
||||
9,1,KN,Feilun,0,DRate,THold,IdleUp,Gyro,Ttrim,Atrim,Etrim
|
||||
73,0,Kyosho,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14
|
||||
18,0,MJXQ,WHL08,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,1,MJXQ,X600,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,2,MJXQ,X800,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,3,MJXQ,H26D,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,4,MJXQ,E010,1,Flip,LED,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,5,MJXQ,H26WH,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
18,6,MJXQ,Phoenix,1,Flip,Arm,Pict,Video,HLess,RTH,AuFlip,Pan,Tilt,Rate
|
||||
17,0,MT99XX,Std,1,Flip,LED,Pict,Video,HLess
|
||||
17,1,MT99XX,H7,1,Flip,LED,Pict,Video,HLess
|
||||
17,2,MT99XX,YZ,1,Flip,LED,Pict,Video,HLess
|
||||
17,3,MT99XX,LS,1,Flip,Invert,Pict,Video,HLess
|
||||
17,4,MT99XX,FY805,1,Flip,n-a,n-a,n-a,HLess
|
||||
17,5,MT99XX,A180,0,3D_6G
|
||||
17,6,MT99XX,Dragon,0,Mode,RTH
|
||||
44,0,NCC1701,Std,1,Warp
|
||||
77,0,OMP,M2,0,THold,IdleUp,6G_3D
|
||||
60,0,Pelikan,PRO_V4,0,CH5,CH6,CH7,CH8
|
||||
60,1,Pelikan,LITE_V4,0,CH5,CH6,CH7,CH8
|
||||
51,0,Potensic,A20,1,TakLan,Emerg,Mode,HLess
|
||||
66,0,Propel,74-Z,1,LEDs,RollCW,RolCCW,Fire,Weapon,Calib,AltHol,TakeOf,Land,Train
|
||||
29,0,Q2x2,Q222,1,Flip,LED,Mod2,Mod1,HLess,RTH,XCal,YCal
|
||||
29,1,Q2x2,Q242,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
|
||||
29,2,Q2x2,Q282,1,Flip,LED,Pict,Video,HLess,RTH,XCal,YCal
|
||||
31,0,Q303,Q303,1,AltHol,Flip,Pict,Video,HLess,RTH,Gimbal
|
||||
31,1,Q303,C35,1,Arm,VTX,Pict,Video,n-a,RTH,Gimbal
|
||||
31,2,Q303,CX10D,1,Arm,Flip
|
||||
31,3,Q303,CX10WD,1,Arm,Flip
|
||||
72,0,Q90C,Std,0,FMode,VTX+
|
||||
74,0,RadioLink,Surface,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
|
||||
74,1,RadioLink,Air,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
|
||||
74,2,RadioLink,DumboRC,0,CH5,CH6,CH7,CH8,FS_CH1,FS_CH2,FS_CH3,FS_CH4,FS_CH5,FS_CH6,FS_CH7,FS_CH8
|
||||
76,0,Realacc,R11,1,Flip,Light,Calib,HLess,RTH,UNK
|
||||
50,0,Redpine,Fast,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
||||
50,1,Redpine,Slow,0,sCH5,sCH6,sCH7,sCH8,sCH9,sCH10,sCH11,sCH12,sCH13,sCH14,sCH15,sCH16
|
||||
21,0,Futaba,SFHSS,0,CH5,CH6,CH7,CH8
|
||||
19,0,Shenqi,Cycle,1
|
||||
68,0,Skyartec,Std,0,CH5,CH6,CH7
|
||||
11,0,SLT,V1,0,Gear,Pitch
|
||||
11,1,SLT,V2,0,CH5,CH6,CH7,CH8
|
||||
11,2,SLT,Q100,0,Rates,n-a,CH7,CH8,Mode,Flip,n-a,n-a,Calib
|
||||
11,3,SLT,Q200,0,Rates,n-a,CH7,CH8,Mode,VidOn,VidOff,Calib
|
||||
11,4,SLT,MR100,0,Rates,n-a,CH7,CH8,Mode,Flip,Video,Pict
|
||||
10,0,Symax,Std,1,Flip,Rates,Pict,Video,HLess
|
||||
10,1,Symax,X5C,1,Flip,Rates,Pict,Video,HLess
|
||||
61,0,Tiger,Std,1,Flip,Light
|
||||
43,0,Traxxas,6519,0
|
||||
5,0,V2x2,Std,1,Flip,Light,Pict,Video,HLess,CalX,CalY
|
||||
5,1,V2x2,JXD506,1,Flip,Light,Pict,Video,HLess,StaSto,Emerg,Cam_UD
|
||||
48,0,V761,3CH,0,Gyro,Calib,Flip,RtnAct,Rtn
|
||||
48,1,V761,4CH,0,Gyro,Calib,Flip,RtnAct,Rtn
|
||||
46,0,V911s,V911s,1,Calib
|
||||
46,1,V911s,E119,1,Calib
|
||||
22,0,WFLY,WFR0xS,0,CH5,CH6,CH7,CH8,CH9
|
||||
30,0,WK2x01,WK2801,0,CH5,CH6,CH7,CH8
|
||||
30,1,WK2x01,WK2401,0
|
||||
30,2,WK2x01,W6_5_1,0,Gear,Dis,Gyro
|
||||
30,3,WK2x01,W6_6_1,0,Gear,Col,Gyro
|
||||
30,4,WK2x01,W6HEL,0,Gear,Col,Gyro
|
||||
30,5,WK2x01,W6HEL_I,0,Gear,Col,Gyro
|
||||
62,0,XK,X450,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
|
||||
62,1,XK,X420,1,FMode,TakeOf,Emerg,3D_6G,Pict,Video
|
||||
8,0,YD717,Std,1,Flip,Light,Pict,Video,HLess
|
||||
8,1,YD717,SkyWlkr,1,Flip,Light,Pict,Video,HLess
|
||||
8,2,YD717,Simax4,1,Flip,Light,Pict,Video,HLess
|
||||
8,3,YD717,XinXun,1,Flip,Light,Pict,Video,HLess
|
||||
8,4,YD717,NiHui,1,Flip,Light,Pict,Video,HLess
|
||||
52,0,ZSX,280,1,Light
|
||||
78,0,M-Link,Std,0,CH5,CH6,CH7,CH8,CH9,CH10,CH11,CH12,CH13,CH14,CH15,CH16
|
||||
79,0,WFLY2,RF20x,0,CH5,CH6,CH7,CH8,CH9,CH10
|
||||
80,0,E016Hv2,E016Hv2,1,TakLan,EmStop,Flip,Calib,HLess,RTH
|
||||
81,0,E010r5,E010r5,1,Flip,LED,CALIB,HLess,RTH,GLIDE
|
||||
82,0,LOLI,Std,0,CH5,CH6,CH7,CH8,1SwSePpPw,2SwSePw,3SwSe,4SwSe,5SwSeSb,6SwSe,7SwSePw,8SwSe
|
||||
83,0,E129,E129,1,TakLan,EmStop,TrimA,TrimE,TrimR
|
||||
84,0,JOYSWAY,Std,0
|
||||
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 }
|
||||
221
Lua_scripts/MultiLOLI.lua
Normal file
221
Lua_scripts/MultiLOLI.lua
Normal file
@@ -0,0 +1,221 @@
|
||||
|
||||
local toolName = "TNS|Multi LOLI RX config|TNE"
|
||||
|
||||
---- #########################################################################
|
||||
---- # #
|
||||
---- # Copyright (C) OpenTX #
|
||||
-----# #
|
||||
---- # License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html #
|
||||
---- # #
|
||||
---- # This program is free software; you can redistribute it and/or modify #
|
||||
---- # it under the terms of the GNU General Public License version 2 as #
|
||||
---- # published by the Free Software Foundation. #
|
||||
---- # #
|
||||
---- # This program is distributed in the hope that it will be useful #
|
||||
---- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
---- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
---- # GNU General Public License for more details. #
|
||||
---- # #
|
||||
---- #########################################################################
|
||||
|
||||
local loli_nok = false
|
||||
local channels={ { 768, "PWM", 100, 102, "PPM", 50, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH1
|
||||
{ 768, "PWM", 100, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH2
|
||||
{ -768, "Servo", 0, -2048, "Switch", -100 }, -- CH3
|
||||
{ -768, "Servo", 0, -2048, "Switch", -100 }, -- CH4
|
||||
{ 102, "SBUS", 50, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH5
|
||||
{ -768, "Servo", 0, -2048, "Switch", -100 }, -- CH6
|
||||
{ 768, "PWM", 100, -768, "Servo", 0, -2048, "Switch", -100 }, -- CH7
|
||||
{ -768, "Servo", 0, -2048, "Switch", -100 } } -- CH8
|
||||
|
||||
local sel = 1
|
||||
local edit = false
|
||||
|
||||
local blink = 0
|
||||
local BLINK_SPEED = 15
|
||||
|
||||
local function drawScreenTitle(title)
|
||||
if LCD_W == 480 then
|
||||
lcd.drawFilledRectangle(0, 0, LCD_W, 30, TITLE_BGCOLOR)
|
||||
lcd.drawText(1, 5, title, MENU_TITLE_COLOR)
|
||||
else
|
||||
lcd.drawScreenTitle(title, 0, 0)
|
||||
end
|
||||
end
|
||||
|
||||
local function LOLI_Draw_LCD(event)
|
||||
local line = 0
|
||||
|
||||
lcd.clear()
|
||||
|
||||
--Display settings
|
||||
local lcd_opt = 0
|
||||
if LCD_W == 480 then
|
||||
drawScreenTitle("Multi - LOLI RX configuration tool")
|
||||
x_pos = 152
|
||||
x_inc = 90
|
||||
y_pos = 40
|
||||
y_inc = 20
|
||||
else
|
||||
x_pos = 5
|
||||
x_inc = 30
|
||||
y_pos = 1
|
||||
y_inc = 8
|
||||
lcd_opt = SMLSIZE
|
||||
end
|
||||
|
||||
--Multi Module detection
|
||||
if loli_nok then
|
||||
if LCD_W == 480 then
|
||||
lcd.drawText(10,50,"The LOLI protocol is not selected...", lcd_opt)
|
||||
else
|
||||
--Draw on LCD_W=128
|
||||
lcd.drawText(2,17,"LOLI protocol not selected...",SMLSIZE)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
--Display current config
|
||||
if LCD_W == 480 then
|
||||
line = line + 1
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line -2, "Channel", lcd_opt)
|
||||
lcd.drawText(x_pos+x_inc, y_pos+y_inc*line -2, "Function", lcd_opt)
|
||||
lcd.drawRectangle(x_pos-4, y_pos+y_inc*line -4 , 2*x_inc +2, 188)
|
||||
lcd.drawLine(x_pos-4, y_pos+y_inc*line +18, x_pos-4 +2*x_inc +1, y_pos+y_inc*line +18, SOLID, 0)
|
||||
lcd.drawLine(x_pos+x_inc -5, y_pos+y_inc*line -4, x_pos+x_inc -5, y_pos+y_inc*line -5 +188, SOLID, 0)
|
||||
line = line + 1
|
||||
end
|
||||
|
||||
local out
|
||||
for i = 1, 8 do
|
||||
out = getValue("ch"..(i+8))
|
||||
lcd.drawText(x_pos, y_pos+y_inc*line, "CH"..i, lcd_opt)
|
||||
for j = 1, #channels[i], 3 do
|
||||
if out > channels[i][j] then
|
||||
if sel == i then
|
||||
invert = INVERS
|
||||
if edit == true then
|
||||
blink = blink + 1
|
||||
if blink > BLINK_SPEED then
|
||||
invert = 0
|
||||
if blink > BLINK_SPEED * 2 then
|
||||
blink = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
invert = 0
|
||||
end
|
||||
lcd.drawText(x_pos+x_inc, y_pos+y_inc*line, channels[i][j+1], lcd_opt + invert)
|
||||
break
|
||||
end
|
||||
end
|
||||
line = line + 1
|
||||
end
|
||||
end
|
||||
|
||||
local function LOLI_Change_Value(dir)
|
||||
local pos = 0
|
||||
local out
|
||||
--look for the current position
|
||||
out = getValue("ch"..(sel+8))
|
||||
for j = 1, #channels[sel], 3 do
|
||||
if out > channels[sel][j] then
|
||||
pos = j
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
--decrement or increment
|
||||
if dir < 0 and pos > 1 then
|
||||
pos = pos - 3
|
||||
elseif dir > 0 and pos + 3 < #channels[sel] then
|
||||
pos = pos + 3
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
--delete all mixers for the selected channel
|
||||
local num_mix = model.getMixesCount(sel-1 +8)
|
||||
for i = 1, num_mix do
|
||||
model.deleteMix(sel-1 +8, 0);
|
||||
end
|
||||
|
||||
--create new mixer
|
||||
local source_max = getFieldInfo("cyc1")
|
||||
|
||||
local val = { name = channels[sel][pos+1],
|
||||
source = source_max.id - 1, -- MAX=100 on TX16S
|
||||
weight = channels[sel][pos+2],
|
||||
offset = 0,
|
||||
switch = 0,
|
||||
multiplex = 0,
|
||||
curveType = 0,
|
||||
curveValue = 0,
|
||||
flightModes = 0,
|
||||
carryTrim = false,
|
||||
mixWarn = 0,
|
||||
delayUp = 0,
|
||||
delayDown = 0,
|
||||
speedUp = 0,
|
||||
speedDown = 0 }
|
||||
model.insertMix(sel-1 +8, 0, val)
|
||||
end
|
||||
|
||||
local function LOLI_Menu(event)
|
||||
if event == EVT_VIRTUAL_NEXT then
|
||||
if edit == false then
|
||||
-- not changing a value
|
||||
if sel < 8 then
|
||||
sel = sel + 1
|
||||
end
|
||||
else
|
||||
-- need to inc the value
|
||||
LOLI_Change_Value(1)
|
||||
end
|
||||
elseif event == EVT_VIRTUAL_PREV then
|
||||
if edit == false then
|
||||
-- not changing a value
|
||||
if sel > 1 then
|
||||
sel = sel - 1
|
||||
end
|
||||
else
|
||||
-- need to dec the value
|
||||
LOLI_Change_Value(-1)
|
||||
end
|
||||
elseif event == EVT_VIRTUAL_ENTER then
|
||||
if edit == false then
|
||||
edit = true
|
||||
blink = BLINK_SPEED
|
||||
else
|
||||
edit = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Init
|
||||
local function LOLI_Init()
|
||||
local module_conf = model.getModule(0)
|
||||
if module_conf["Type"] ~= 6 or module_conf["protocol"] ~= 82 then
|
||||
module_conf = model.getModule(1)
|
||||
if module_conf["Type"] ~= 6 or module_conf["protocol"] ~= 82 then
|
||||
loli_nok = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Main
|
||||
local function LOLI_Run(event)
|
||||
if event == nil then
|
||||
error("Cannot be run as a model script!")
|
||||
return 2
|
||||
elseif event == EVT_VIRTUAL_EXIT then
|
||||
return 2
|
||||
else
|
||||
LOLI_Menu(event)
|
||||
LOLI_Draw_LCD(event)
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
return { init=LOLI_Init, run=LOLI_Run }
|
||||
56
Lua_scripts/README.md
Normal file
56
Lua_scripts/README.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# Multiprotocol TX Module OpenTX LUA scripts
|
||||
<img align="right" width=300 src="../docs/images/multi.png" />
|
||||
|
||||
If you like this project and want to support further development please consider making a [donation](../docs/Donations.md).
|
||||
|
||||
<table cellspacing=0>
|
||||
<tr>
|
||||
<td align=center width=200><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=VF2K9T23DRY56&lc=US&item_name=DIY%20Multiprotocol¤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
|
||||
|
||||
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)
|
||||
|
||||
## MultiLOLI
|
||||
|
||||
Script to set the channels function (switch, servo, pwm, ppm, sbus) on a [LOLI RX](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/blob/master/Protocols_Details.md#loli---82)
|
||||
|
||||
[](https://www.youtube.com/watch?v=e698pQxfv-A)
|
||||
|
||||
## Graupner HoTT
|
||||
|
||||
Enable text configuration of the HoTT RX and sensors: Vario, GPS, ESC, GAM and EAM.
|
||||
|
||||
Need OpenTX 2.3.9 or above. Located on the radio SD card under \SCRIPTS\TOOLS.
|
||||
|
||||
Notes:
|
||||
- Menu/MDL/Model is used to cycle through the detected sensors.
|
||||
- It's normal to lose the telemetry feed while using the text mode configuration. Telemetry will resume properly if the script is exited by doing a short press on the exit button.
|
||||
|
||||
[](https://www.youtube.com/watch?v=81wd8NlF3Qw)
|
||||
|
||||
## DSM Forward Programming
|
||||
|
||||
This is a work in progress. It's only available for color screens (Horus, TX16S, T16, T18...).
|
||||
|
||||
If some text appears as Unknown_xxx, please report xxx and what the exact text display should be.
|
||||
|
||||
Need OpenTX 2.3.10 nightly or above. Located on the radio SD card under \SCRIPTS\TOOLS.
|
||||
|
||||
[](https://www.youtube.com/watch?v=sjIaDw5j9nE)
|
||||
|
||||
## DSM PID Flight log gain parameters for Blade micros
|
||||
|
||||
Lua telemetry script from [feathering on RCGroups](https://www.rcgroups.com/forums/showpost.php?p=46033341&postcount=20728) to facilitate setting the Gain Parameters on the Blade 150S FBL. It doesn't use Forward Programming but instead it just reads telemetry data from the Multi-module and displays it on a telemetry display.
|
||||
|
||||
It is very similar to the Telemetry Based Text Generator functionality on Spektrum transmitters where one doesn't need to rely on the angle of the swashplate to determine selection/value.
|
||||
127
Lua_scripts/pidDsm.lua
Normal file
127
Lua_scripts/pidDsm.lua
Normal file
@@ -0,0 +1,127 @@
|
||||
--
|
||||
-- This telemetry script displays the Flight Log Gain
|
||||
-- Parameters streamed from the Blade 150S Spektrum AR6335A
|
||||
-- Flybarless Controller.
|
||||
|
||||
-- The script facilitates the setting of the FBL's
|
||||
-- Gain Parameters including PID for both
|
||||
-- cyclic and tail. It is similar to the Telemetry Based
|
||||
-- Text Generator available on Spektrum transmitters.
|
||||
|
||||
-- Supporting similar Blade micros such as the Fusion 180
|
||||
-- would possibly require minor modifications to this script.
|
||||
|
||||
-- This script reads telemetry data from the Spektrum
|
||||
-- receiver and thus functionality relies on data being
|
||||
-- captured by the OpenTX transmitter. A DSM
|
||||
-- telemetry-ready module is required. Please see the
|
||||
-- MULTI-Module project at https://www.multi-module.org/.
|
||||
|
||||
-- The only supported display is the Taranis'. It may work
|
||||
-- with higher res screens.
|
||||
--
|
||||
|
||||
|
||||
-- Sensor names
|
||||
local PSensor = "FdeA"
|
||||
local ISensor = "FdeB"
|
||||
local DSensor = "FdeL"
|
||||
local RSensor = "FdeR"
|
||||
local ActiveParamSensor = "Hold"
|
||||
|
||||
local tags = {"P", "I", "D"}
|
||||
|
||||
|
||||
local function getPage(iParam)
|
||||
-- get page from 0-based index
|
||||
-- {0,1,2,3}: cyclic (1), {4,5,6,7}: tail (2)
|
||||
local res = (math.floor(iParam/4)==0) and 1 or 2
|
||||
return res
|
||||
end
|
||||
|
||||
function round(v)
|
||||
-- round float
|
||||
local factor = 100
|
||||
return math.floor(v * factor + 0.5) / factor
|
||||
end
|
||||
|
||||
|
||||
local function readValue(sensor)
|
||||
-- read from sensor, round and return
|
||||
local v = getValue(sensor)
|
||||
v = round(v)
|
||||
return v
|
||||
end
|
||||
|
||||
local function readActiveParamValue(sensor)
|
||||
-- read and return a validated active parameter value
|
||||
local v = getValue(sensor)
|
||||
if (v<1 or v>8) then
|
||||
return nil
|
||||
end
|
||||
return v
|
||||
end
|
||||
|
||||
local function readParameters()
|
||||
-- read and return parameters
|
||||
local p = readValue(PSensor)
|
||||
local i = readValue(ISensor)
|
||||
local d = readValue(DSensor)
|
||||
local r = readValue(RSensor)
|
||||
local a = readActiveParamValue(ActiveParamSensor)
|
||||
return {p,i,d,r,a}
|
||||
end
|
||||
|
||||
local function drawParameters()
|
||||
-- draw labels and params on screen
|
||||
local params = readParameters()
|
||||
local activeParam = params[5]
|
||||
|
||||
-- if active gain does not validate then assume
|
||||
-- Gain Adjustment Mode is disabled
|
||||
if not activeParam then
|
||||
lcd.clear()
|
||||
lcd.drawText(20,30,"Please enter Gain Adjustment Mode")
|
||||
return
|
||||
end
|
||||
|
||||
local activePage = getPage(activeParam-1)
|
||||
for iParam=0,7 do
|
||||
-- highlight selected parameter
|
||||
local attr = (activeParam==iParam+1) and 2 or 0
|
||||
-- circular index (per page)
|
||||
local perPageIndx = iParam % 4 + 1
|
||||
-- check if displaying cyclic params.
|
||||
local isCyclicPage = (getPage(iParam)==1)
|
||||
-- set y draw coord
|
||||
local y = perPageIndx*10+2
|
||||
|
||||
-- labels
|
||||
local x = isCyclicPage and 6 or 120
|
||||
-- labels are P,I,D for both pages except for last param
|
||||
local val = iParam==3 and "Response" or
|
||||
(iParam==7 and "Filtering" or tags[perPageIndx])
|
||||
lcd.drawText (x, y, val, attr)
|
||||
|
||||
-- gains
|
||||
-- set all params for non-active page to '--' rather than 'last value'
|
||||
val = (getPage(iParam)==activePage) and params[perPageIndx] or '--'
|
||||
x = isCyclicPage and 70 or 180
|
||||
lcd.drawText (x, y, val, attr)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function run_func(event)
|
||||
-- TODO: calling clear() on every function call redrawing all labels is not ideal
|
||||
lcd.clear()
|
||||
lcd.drawText (8, 2, "Cyclic (0...200)")
|
||||
lcd.drawText (114, 2, "Tail (0...200)")
|
||||
drawParameters()
|
||||
end
|
||||
|
||||
local function init_func() end
|
||||
local function bg_func() end
|
||||
|
||||
|
||||
return { run=run_func, background=bg_func, init=init_func }
|
||||
@@ -27,13 +27,16 @@ void A7105_WriteData(uint8_t len, uint8_t channel)
|
||||
for (i = 0; i < len; i++)
|
||||
SPI_Write(packet[i]);
|
||||
A7105_CSN_on;
|
||||
if(protocol!=PROTO_FLYSKY)
|
||||
if(protocol!=PROTO_WFLY2)
|
||||
{
|
||||
A7105_Strobe(A7105_STANDBY); //Force standby mode, ie cancel any TX or RX...
|
||||
A7105_SetTxRxMode(TX_EN); //Switch to PA
|
||||
if(!(protocol==PROTO_FLYSKY || protocol==PROTO_KYOSHO))
|
||||
{
|
||||
A7105_Strobe(A7105_STANDBY); //Force standby mode, ie cancel any TX or RX...
|
||||
A7105_SetTxRxMode(TX_EN); //Switch to PA
|
||||
}
|
||||
A7105_WriteReg(A7105_0F_PLL_I, channel);
|
||||
A7105_Strobe(A7105_TX);
|
||||
}
|
||||
A7105_WriteReg(A7105_0F_PLL_I, channel);
|
||||
A7105_Strobe(A7105_TX);
|
||||
}
|
||||
|
||||
void A7105_ReadData(uint8_t len)
|
||||
@@ -107,7 +110,7 @@ void A7105_WriteID(uint32_t ida)
|
||||
{
|
||||
A7105_CSN_off;
|
||||
SPI_Write(A7105_06_ID_DATA); //ex id=0x5475c52a ;txid3txid2txid1txid0
|
||||
SPI_Write((ida>>24)&0xff); //53
|
||||
SPI_Write((ida>>24)&0xff); //54
|
||||
SPI_Write((ida>>16)&0xff); //75
|
||||
SPI_Write((ida>>8)&0xff); //c5
|
||||
SPI_Write((ida>>0)&0xff); //2a
|
||||
@@ -192,9 +195,9 @@ void A7105_AdjustLOBaseFreq(uint8_t cmd)
|
||||
offset=(int16_t)FORCE_FLYSKY_TUNING;
|
||||
#endif
|
||||
break;
|
||||
case PROTO_FLYZONE:
|
||||
#ifdef FORCE_FLYZONE_TUNING
|
||||
offset=(int16_t)FORCE_FLYZONE_TUNING;
|
||||
case PROTO_HEIGHT:
|
||||
#ifdef FORCE_HEIGHT_TUNING
|
||||
offset=(int16_t)FORCE_HEIGHT_TUNING;
|
||||
#endif
|
||||
break;
|
||||
case PROTO_PELIKAN:
|
||||
@@ -202,6 +205,21 @@ void A7105_AdjustLOBaseFreq(uint8_t cmd)
|
||||
offset=(int16_t)FORCE_PELIKAN_TUNING;
|
||||
#endif
|
||||
break;
|
||||
case PROTO_KYOSHO:
|
||||
#ifdef FORCE_KYOSHO_TUNING
|
||||
offset=(int16_t)FORCE_KYOSHO_TUNING;
|
||||
#endif
|
||||
break;
|
||||
case PROTO_JOYSWAY:
|
||||
#ifdef FORCE_JOYSWAY_TUNING
|
||||
offset=(int16_t)FORCE_JOYSWAY_TUNING;
|
||||
#endif
|
||||
break;
|
||||
case PROTO_WFLY2:
|
||||
#ifdef FORCE_WFLY2_TUNING
|
||||
offset=(int16_t)FORCE_WFLY2_TUNING;
|
||||
#endif
|
||||
break;
|
||||
case PROTO_AFHDS2A:
|
||||
case PROTO_AFHDS2A_RX:
|
||||
#ifdef FORCE_AFHDS2A_TUNING
|
||||
@@ -211,7 +229,7 @@ void A7105_AdjustLOBaseFreq(uint8_t cmd)
|
||||
}
|
||||
}
|
||||
if(offset==1024) // Use channel 15 as an input
|
||||
offset=convert_channel_16b_nolimit(CH15,-300,300);
|
||||
offset=convert_channel_16b_nolimit(CH15,-300,300,false);
|
||||
|
||||
if(old_offset==offset) // offset is the same as before...
|
||||
return;
|
||||
@@ -282,8 +300,8 @@ const uint8_t PROGMEM FLYSKY_A7105_regs[] = {
|
||||
0x01, 0x0f // 30 - 31
|
||||
};
|
||||
#endif
|
||||
#ifdef FLYZONE_A7105_INO
|
||||
const uint8_t PROGMEM FLYZONE_A7105_regs[] = {
|
||||
#ifdef HEIGHT_A7105_INO
|
||||
const uint8_t PROGMEM HEIGHT_A7105_regs[] = {
|
||||
0xff, 0x42, 0x00, 0x07, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x01, 0x50, // 00 - 0f
|
||||
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0xc3, 0x1f, // 10 - 1f
|
||||
0x12, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3a, 0x00, 0x3f, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f
|
||||
@@ -306,6 +324,36 @@ const uint8_t PROGMEM PELIKAN_A7105_regs[] = {
|
||||
0x01, 0x0f // 30 - 31
|
||||
};
|
||||
#endif
|
||||
#ifdef KYOSHO_A7105_INO
|
||||
const uint8_t PROGMEM KYOSHO_A7105_regs[] = {
|
||||
0xff, 0x42, 0xff, 0x25, 0x00, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x05, 0x00, 0x50, // 00 - 0f
|
||||
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x40, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0x03, 0x1f, // 10 - 1f
|
||||
0x1e, 0x00, 0x00, 0xff, 0x00, 0x00, 0x23, 0x70, 0x1F, 0x47, 0x80, 0x57, 0x01, 0x45, 0x19, 0x00, // 20 - 2f
|
||||
0x01, 0x0f // 30 - 31
|
||||
};
|
||||
const uint8_t PROGMEM KYOSHO_HYPE_A7105_regs[] = {
|
||||
0xff, 0x42, 0x00, 0x10, 0xC0, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0x05, 0x01, 0x04, // 00 - 0f
|
||||
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x00, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x96, 0xc2, 0x1f, // 10 - 1f
|
||||
0x12, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3a, 0x00, 0x17, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f
|
||||
0x01, 0x0f // 30 - 31
|
||||
};
|
||||
#endif
|
||||
#ifdef WFLY2_A7105_INO //A7106 values
|
||||
const uint8_t PROGMEM WFLY2_A7105_regs[] = {
|
||||
0xff, 0x62, 0xff, 0x1F, 0x40, 0xff, 0xff ,0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x05, 0x00, 0x64, // 00 - 0f Changes: 0B:19->33, 0C:01,33
|
||||
0x9e, 0x4b, 0x00, 0x02, 0x16, 0x2b, 0x12, 0x40, 0x62, 0x80, 0x80, 0x00, 0x0a, 0x32, 0x03, 0x0f, // 10 - 1f 1C:4A->0A
|
||||
0x12, 0x00, 0x00, 0xff, 0x00, 0x00, 0x23, 0x70, 0x15, 0x47, 0x80, 0x03, 0x01, 0x45, 0x18, 0x00, // 20 - 2f 2B:77->03, 2E:19->18
|
||||
0x01, 0x0f // 30 - 31
|
||||
};
|
||||
#endif
|
||||
#ifdef JOYSWAY_A7105_INO
|
||||
const uint8_t PROGMEM JOYSWAY_A7105_regs[] = {
|
||||
0xff, 0x62, 0xff, 0x0F, 0x00, 0xff, 0xff ,0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0xF5, 0x00, 0x15, // 00 - 0f
|
||||
0x9E, 0x4B, 0x00, 0x03, 0x56, 0x2B, 0x12, 0x4A, 0x02, 0x80, 0x80, 0x00, 0x0E, 0x91, 0x03, 0x0F, // 10 - 1f
|
||||
0x16, 0x2A, 0x00, 0xff, 0xff, 0xff, 0x3A, 0x06, 0x1F, 0x47, 0x80, 0x01, 0x05, 0x45, 0x18, 0x00, // 20 - 2f
|
||||
0x01, 0x0f // 30 - 31
|
||||
};
|
||||
#endif
|
||||
|
||||
#define ID_NORMAL 0x55201041
|
||||
#define ID_PLUS 0xAA201041
|
||||
@@ -314,10 +362,24 @@ void A7105_Init(void)
|
||||
uint8_t *A7105_Regs=0;
|
||||
uint8_t vco_calibration0, vco_calibration1;
|
||||
|
||||
#ifdef FLYZONE_A7105_INO
|
||||
if(protocol==PROTO_FLYZONE)
|
||||
#ifdef JOYSWAY_A7105_INO
|
||||
if(protocol==PROTO_JOYSWAY)
|
||||
{
|
||||
A7105_Regs=(uint8_t*)FLYZONE_A7105_regs;
|
||||
A7105_Regs=(uint8_t*)JOYSWAY_A7105_regs;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef WFLY2_A7105_INO
|
||||
if(protocol==PROTO_WFLY2)
|
||||
{
|
||||
A7105_Regs=(uint8_t*)WFLY2_A7105_regs;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef HEIGHT_A7105_INO
|
||||
if(protocol==PROTO_HEIGHT)
|
||||
{
|
||||
A7105_Regs=(uint8_t*)HEIGHT_A7105_regs;
|
||||
A7105_WriteID(0x25A53C45);
|
||||
}
|
||||
else
|
||||
@@ -348,13 +410,20 @@ void A7105_Init(void)
|
||||
#ifdef FLYSKY_A7105_INO
|
||||
if(protocol==PROTO_FLYSKY)
|
||||
A7105_Regs=(uint8_t*)FLYSKY_A7105_regs;
|
||||
else
|
||||
#endif
|
||||
#if defined(AFHDS2A_A7105_INO) || defined(AFHDS2A_RX_A7105_INO)
|
||||
if(protocol==PROTO_AFHDS2A || protocol==PROTO_AFHDS2A_RX)
|
||||
A7105_Regs=(uint8_t*)AFHDS2A_A7105_regs;
|
||||
#endif
|
||||
#ifdef KYOSHO_A7105_INO
|
||||
if(protocol==PROTO_KYOSHO)
|
||||
{
|
||||
#if defined(AFHDS2A_A7105_INO) || defined(AFHDS2A_RX_A7105_INO)
|
||||
A7105_Regs=(uint8_t*)AFHDS2A_A7105_regs;
|
||||
#endif
|
||||
if(sub_protocol==KYOSHO_FHSS)
|
||||
A7105_Regs=(uint8_t*)KYOSHO_A7105_regs;
|
||||
else
|
||||
A7105_Regs=(uint8_t*)KYOSHO_HYPE_A7105_regs;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 0x32; i++)
|
||||
@@ -368,59 +437,81 @@ void A7105_Init(void)
|
||||
if(i==0x20) val=0x1E;
|
||||
}
|
||||
#endif
|
||||
if( val != 0xFF)
|
||||
#ifdef HEIGHT_A7105_INO
|
||||
if(protocol==PROTO_HEIGHT && sub_protocol==HEIGHT_8CH)
|
||||
if(i==0x03) val=0x0A;
|
||||
#endif
|
||||
if( val != 0xff)
|
||||
A7105_WriteReg(i, val);
|
||||
}
|
||||
A7105_Strobe(A7105_STANDBY);
|
||||
|
||||
//IF Filter Bank Calibration
|
||||
A7105_WriteReg(A7105_02_CALC,1);
|
||||
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
|
||||
// A7105_ReadReg(A7105_22_IF_CALIB_I);
|
||||
// A7105_ReadReg(A7105_24_VCO_CURCAL);
|
||||
|
||||
if(protocol!=PROTO_HUBSAN)
|
||||
{
|
||||
//VCO Current Calibration
|
||||
A7105_WriteReg(A7105_24_VCO_CURCAL,0x13); //Recommended calibration from A7105 Datasheet
|
||||
//VCO Bank Calibration
|
||||
A7105_WriteReg(A7105_26_VCO_SBCAL_II,0x3b); //Recommended calibration from A7105 Datasheet
|
||||
if(protocol==PROTO_KYOSHO && sub_protocol==KYOSHO_FHSS)
|
||||
{//strange calibration...
|
||||
//IF Filter Bank Calibration
|
||||
A7105_WriteReg(A7105_02_CALC,0x0F);
|
||||
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
|
||||
// A7105_ReadReg(A7105_22_IF_CALIB_I);
|
||||
// A7105_ReadReg(A7105_24_VCO_CURCAL);
|
||||
// A7105_ReadReg(25_VCO_SBCAL_I);
|
||||
// A7105_ReadReg(1A_RX_GAIN_II);
|
||||
// A7105_ReadReg(1B_RX_GAIN_III);
|
||||
}
|
||||
|
||||
//VCO Bank Calibrate channel 0
|
||||
A7105_WriteReg(A7105_0F_CHANNEL, 0);
|
||||
A7105_WriteReg(A7105_02_CALC,2);
|
||||
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
|
||||
vco_calibration0 = A7105_ReadReg(A7105_25_VCO_SBCAL_I);
|
||||
|
||||
//VCO Bank Calibrate channel A0
|
||||
A7105_WriteReg(A7105_0F_CHANNEL, 0xa0);
|
||||
A7105_WriteReg(A7105_02_CALC, 2);
|
||||
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
|
||||
vco_calibration1 = A7105_ReadReg(A7105_25_VCO_SBCAL_I);
|
||||
|
||||
if(protocol==PROTO_BUGS)
|
||||
A7105_SetVCOBand(vco_calibration0 & 0x07, vco_calibration1 & 0x07); // Set calibration band value to best match
|
||||
else
|
||||
{
|
||||
//IF Filter Bank Calibration
|
||||
A7105_WriteReg(A7105_02_CALC,1);
|
||||
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
|
||||
// A7105_ReadReg(A7105_22_IF_CALIB_I);
|
||||
// A7105_ReadReg(A7105_24_VCO_CURCAL);
|
||||
|
||||
if(protocol!=PROTO_HUBSAN)
|
||||
{
|
||||
switch(protocol)
|
||||
{
|
||||
case PROTO_FLYSKY:
|
||||
vco_calibration1=0x08;
|
||||
break;
|
||||
case PROTO_FLYZONE:
|
||||
vco_calibration1=0x02;
|
||||
break;
|
||||
case PROTO_PELIKAN:
|
||||
vco_calibration1=0x0C;
|
||||
break;
|
||||
default:
|
||||
vco_calibration1=0x0A;
|
||||
break;
|
||||
}
|
||||
A7105_WriteReg(A7105_25_VCO_SBCAL_I,vco_calibration1); //Reset VCO Band calibration
|
||||
//VCO Current Calibration
|
||||
A7105_WriteReg(A7105_24_VCO_CURCAL,0x13); //Recommended calibration from A7105 Datasheet
|
||||
//VCO Bank Calibration
|
||||
A7105_WriteReg(A7105_26_VCO_SBCAL_II,0x3b); //Recommended calibration from A7105 Datasheet
|
||||
}
|
||||
|
||||
//VCO Bank Calibrate channel 0
|
||||
A7105_WriteReg(A7105_0F_CHANNEL, 0);
|
||||
A7105_WriteReg(A7105_02_CALC,2);
|
||||
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
|
||||
vco_calibration0 = A7105_ReadReg(A7105_25_VCO_SBCAL_I);
|
||||
|
||||
//VCO Bank Calibrate channel A0
|
||||
A7105_WriteReg(A7105_0F_CHANNEL, 0xa0);
|
||||
A7105_WriteReg(A7105_02_CALC, 2);
|
||||
while(A7105_ReadReg(A7105_02_CALC)); // Wait for calibration to end
|
||||
vco_calibration1 = A7105_ReadReg(A7105_25_VCO_SBCAL_I);
|
||||
|
||||
if(protocol==PROTO_BUGS || protocol==PROTO_WFLY2)
|
||||
A7105_SetVCOBand(vco_calibration0 & 0x07, vco_calibration1 & 0x07); // Set calibration band value to best match
|
||||
else
|
||||
if(protocol!=PROTO_HUBSAN)
|
||||
{
|
||||
switch(protocol)
|
||||
{
|
||||
case PROTO_FLYSKY:
|
||||
vco_calibration1=0x08;
|
||||
break;
|
||||
case PROTO_HEIGHT:
|
||||
vco_calibration1=0x02;
|
||||
break;
|
||||
case PROTO_PELIKAN:
|
||||
case PROTO_KYOSHO: //sub_protocol Hype
|
||||
vco_calibration1=0x0C;
|
||||
break;
|
||||
case PROTO_JOYSWAY:
|
||||
vco_calibration1=0x09;
|
||||
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();
|
||||
|
||||
|
||||
@@ -24,10 +24,11 @@
|
||||
enum {
|
||||
AFHDS2A_RX_BIND1,
|
||||
AFHDS2A_RX_BIND2,
|
||||
AFHDS2A_RX_BIND3,
|
||||
AFHDS2A_RX_DATA
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) AFHDS2A_Rx_build_telemetry_packet()
|
||||
static void __attribute__((unused)) AFHDS2A_RX_build_telemetry_packet()
|
||||
{
|
||||
uint32_t bits = 0;
|
||||
uint8_t bitsavailable = 0;
|
||||
@@ -39,7 +40,7 @@ static void __attribute__((unused)) AFHDS2A_Rx_build_telemetry_packet()
|
||||
packet_in[idx++] = 14; // number of channels in packet
|
||||
// pack channels
|
||||
for (uint8_t i = 0; i < 14; i++) {
|
||||
uint32_t val = packet[9+i*2] | (packet[10+i*2] << 8);
|
||||
uint32_t val = packet[9+i*2] | (((packet[10+i*2])&0x0F) << 8);
|
||||
if (val < 860)
|
||||
val = 860;
|
||||
// convert ppm (860-2140) to Multi (0-2047)
|
||||
@@ -55,13 +56,13 @@ static void __attribute__((unused)) AFHDS2A_Rx_build_telemetry_packet()
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t __attribute__((unused)) AFHDS2A_Rx_data_ready()
|
||||
static uint8_t __attribute__((unused)) AFHDS2A_RX_data_ready()
|
||||
{
|
||||
// check if FECF+CRCF Ok
|
||||
return !(A7105_ReadReg(A7105_00_MODE) & (1 << 5 | 1 << 6 | 1 << 0));
|
||||
}
|
||||
|
||||
uint16_t initAFHDS2A_Rx()
|
||||
void AFHDS2A_RX_init()
|
||||
{
|
||||
uint8_t i;
|
||||
A7105_Init();
|
||||
@@ -83,15 +84,12 @@ uint16_t initAFHDS2A_Rx()
|
||||
hopping_frequency[i] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
phase = AFHDS2A_RX_DATA;
|
||||
}
|
||||
return 1000;
|
||||
}
|
||||
|
||||
#define AFHDS2A_RX_WAIT_WRITE 0x80
|
||||
|
||||
uint16_t AFHDS2A_Rx_callback()
|
||||
uint16_t AFHDS2A_RX_callback()
|
||||
{
|
||||
static uint32_t pps_timer = 0;
|
||||
static uint16_t pps_counter = 0;
|
||||
static int8_t read_retry;
|
||||
int16_t temp;
|
||||
uint8_t i;
|
||||
@@ -106,22 +104,33 @@ uint16_t AFHDS2A_Rx_callback()
|
||||
|
||||
switch(phase) {
|
||||
case AFHDS2A_RX_BIND1:
|
||||
if (AFHDS2A_Rx_data_ready()) {
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
AFHDS2A_RX_init(); // Abort bind
|
||||
break;
|
||||
}
|
||||
debugln("bind p=%d", phase+1);
|
||||
if (AFHDS2A_RX_data_ready()) {
|
||||
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
|
||||
if ((packet[0] == 0xbb && packet[9] == 0x01) || (packet[0] == 0xbc && packet[9] <= 0x02)) {
|
||||
memcpy(rx_id, &packet[1], 4); // TX id actually
|
||||
memcpy(hopping_frequency, &packet[11], AFHDS2A_RX_NUMFREQ);
|
||||
phase = AFHDS2A_RX_BIND2;
|
||||
debugln("phase bind2");
|
||||
}
|
||||
}
|
||||
A7105_WriteReg(A7105_0F_PLL_I, (packet_count++ & 1) ? 0x0D : 0x8C); // bind channels
|
||||
A7105_SetTxRxMode(RX_EN);
|
||||
A7105_Strobe(A7105_RX);
|
||||
return 10000;
|
||||
|
||||
case AFHDS2A_RX_BIND2:
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
AFHDS2A_RX_init(); // Abort bind
|
||||
break;
|
||||
}
|
||||
// got 2nd bind packet from tx ?
|
||||
if (AFHDS2A_Rx_data_ready()) {
|
||||
if (AFHDS2A_RX_data_ready()) {
|
||||
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
|
||||
if ((packet[0] == 0xBC && packet[9] == 0x02 && packet[10] == 0x00) &&
|
||||
(memcmp(rx_id, &packet[1], 4) == 0) &&
|
||||
@@ -132,42 +141,58 @@ uint16_t AFHDS2A_Rx_callback()
|
||||
eeprom_write_byte((EE_ADDR)temp++, rx_id[i]);
|
||||
for (i = 0; i < AFHDS2A_RX_NUMFREQ; i++)
|
||||
eeprom_write_byte((EE_ADDR)temp++, hopping_frequency[i]);
|
||||
BIND_DONE;
|
||||
phase = AFHDS2A_RX_DATA;
|
||||
return 3850;
|
||||
phase = AFHDS2A_RX_BIND3;
|
||||
debugln("phase bind3");
|
||||
packet_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
case AFHDS2A_RX_BIND3:
|
||||
debugln("bind p=%d", phase+1);
|
||||
// transmit response packet
|
||||
packet[0] = 0xBC;
|
||||
memcpy(&packet[1], rx_id, 4);
|
||||
memcpy(&packet[5], rx_tx_addr, 4);
|
||||
packet[9] = 0x01;
|
||||
//packet[9] = 0x01;
|
||||
packet[10] = 0x00;
|
||||
memset(&packet[11], 0xFF, 26);
|
||||
A7105_SetTxRxMode(TX_EN);
|
||||
rx_disable_lna = !IS_POWER_FLAG_on;
|
||||
A7105_WriteData(AFHDS2A_RX_RXPACKET_SIZE, packet_count++ & 1 ? 0x0D : 0x8C);
|
||||
if(phase == AFHDS2A_RX_BIND3 && packet_count > 20)
|
||||
{
|
||||
debugln("done");
|
||||
BIND_DONE;
|
||||
AFHDS2A_RX_init(); // Restart protocol
|
||||
break;
|
||||
}
|
||||
phase |= AFHDS2A_RX_WAIT_WRITE;
|
||||
return 1700;
|
||||
|
||||
case AFHDS2A_RX_BIND2 | AFHDS2A_RX_WAIT_WRITE:
|
||||
//Wait for TX completion
|
||||
pps_timer = micros();
|
||||
while (micros() - pps_timer < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
|
||||
while ((uint32_t)(micros() - pps_timer) < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
|
||||
if (!(A7105_ReadReg(A7105_00_MODE) & 0x01))
|
||||
break;
|
||||
A7105_Strobe(A7105_RX);
|
||||
case AFHDS2A_RX_BIND3 | AFHDS2A_RX_WAIT_WRITE:
|
||||
phase &= ~AFHDS2A_RX_WAIT_WRITE;
|
||||
return 10000;
|
||||
|
||||
case AFHDS2A_RX_DATA:
|
||||
if (AFHDS2A_Rx_data_ready()) {
|
||||
if (AFHDS2A_RX_data_ready()) {
|
||||
A7105_ReadData(AFHDS2A_RX_TXPACKET_SIZE);
|
||||
if (memcmp(&packet[1], rx_id, 4) == 0 && memcmp(&packet[5], rx_tx_addr, 4) == 0) {
|
||||
if (packet[0] == 0x58 && packet[37] == 0x00 && telemetry_link == 0) { // standard packet, send channels to TX
|
||||
if (packet[0] == 0x58 && packet[37] == 0x00 && (telemetry_link&0x7F) == 0) { // standard packet, send channels to TX
|
||||
int rssi = min(A7105_ReadReg(A7105_1D_RSSI_THOLD),160);
|
||||
RX_RSSI = map16b(rssi, 160, 8, 0, 128);
|
||||
AFHDS2A_Rx_build_telemetry_packet();
|
||||
AFHDS2A_RX_build_telemetry_packet();
|
||||
telemetry_link = 1;
|
||||
#ifdef SEND_CPPM
|
||||
if(sub_protocol>0)
|
||||
telemetry_link |= 0x80; // Disable telemetry output
|
||||
#endif
|
||||
}
|
||||
rx_data_started = true;
|
||||
read_retry = 10; // hop to next channel
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
#define AFHDS2A_RXPACKET_SIZE 37
|
||||
#define AFHDS2A_NUMFREQ 16
|
||||
|
||||
#if not defined TELEMETRY
|
||||
uint8_t RX_LQI=0;
|
||||
#endif
|
||||
|
||||
enum{
|
||||
AFHDS2A_PACKET_STICKS,
|
||||
AFHDS2A_PACKET_SETTINGS,
|
||||
@@ -65,7 +69,6 @@ static void AFHDS2A_calc_channels()
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(AFHDS2A_FW_TELEMETRY) || defined(AFHDS2A_HUB_TELEMETRY)
|
||||
// telemetry sensors ID
|
||||
enum{
|
||||
AFHDS2A_SENSOR_RX_VOLTAGE = 0x00,
|
||||
@@ -76,10 +79,9 @@ enum{
|
||||
AFHDS2A_SENSOR_A3_VOLTAGE = 0x03,
|
||||
};
|
||||
|
||||
#if defined(AFHDS2A_FW_TELEMETRY) || defined(AFHDS2A_HUB_TELEMETRY)
|
||||
static void AFHDS2A_update_telemetry()
|
||||
{
|
||||
if(packet[0]==0xAA && packet[9]==0xFD)
|
||||
return; // ignore packets which contain the RX configuration: FD FF 32 00 01 00 FF FF FF 05 DC 05 DE FA FF FF FF FF FF FF FF FF FF FF FF FF FF FF
|
||||
// Read TX RSSI
|
||||
int16_t temp=256-(A7105_ReadReg(A7105_1D_RSSI_THOLD)*8)/5; // value from A7105 is between 8 for maximum signal strength to 160 or less
|
||||
if(temp<0) temp=0;
|
||||
@@ -183,37 +185,64 @@ static void AFHDS2A_build_packet(uint8_t type)
|
||||
{
|
||||
case AFHDS2A_PACKET_STICKS:
|
||||
packet[0] = 0x58;
|
||||
for(uint8_t ch=0; ch<14; ch++)
|
||||
//16 channels + RX_LQI on channel 17
|
||||
for(uint8_t ch=0; ch<num_ch; ch++)
|
||||
{
|
||||
uint16_t channelMicros = convert_channel_ppm(CH_AETR[ch]);
|
||||
packet[9 + ch*2] = channelMicros&0xFF;
|
||||
packet[10 + ch*2] = (channelMicros>>8)&0xFF;
|
||||
if(ch == 16 // CH17=RX_LQI
|
||||
#ifdef AFHDS2A_LQI_CH
|
||||
|| ch == (AFHDS2A_LQI_CH-1) // override channel with LQI
|
||||
#endif
|
||||
)
|
||||
val = 2000 - 10*RX_LQI;
|
||||
else
|
||||
val = convert_channel_ppm(CH_AETR[ch]);
|
||||
if(ch<14)
|
||||
{
|
||||
packet[9 + ch*2] = val;
|
||||
packet[10 + ch*2] = (val>>8)&0x0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[10 + (ch-14)*6] |= (val)<<4;
|
||||
packet[12 + (ch-14)*6] |= (val)&0xF0;
|
||||
packet[14 + (ch-14)*6] |= (val>>4)&0xF0;
|
||||
}
|
||||
}
|
||||
#ifdef AFHDS2A_LQI_CH
|
||||
// override channel with LQI
|
||||
val = 2000 - 10*RX_LQI;
|
||||
packet[9+((AFHDS2A_LQI_CH-1)*2)] = val & 0xff;
|
||||
packet[10+((AFHDS2A_LQI_CH-1)*2)] = (val >> 8) & 0xff;
|
||||
#endif
|
||||
break;
|
||||
case AFHDS2A_PACKET_FAILSAFE:
|
||||
packet[0] = 0x56;
|
||||
for(uint8_t ch=0; ch<14; ch++)
|
||||
for(uint8_t ch=0; ch<num_ch; ch++)
|
||||
{
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
uint16_t failsafeMicros = Failsafe_data[CH_AETR[ch]];
|
||||
if( failsafeMicros!=FAILSAFE_CHANNEL_HOLD && failsafeMicros!=FAILSAFE_CHANNEL_NOPULSES)
|
||||
if(ch<16)
|
||||
val = Failsafe_data[CH_AETR[ch]];
|
||||
else
|
||||
val = FAILSAFE_CHANNEL_NOPULSES;
|
||||
if(val!=FAILSAFE_CHANNEL_HOLD && val!=FAILSAFE_CHANNEL_NOPULSES)
|
||||
{ // Failsafe values
|
||||
failsafeMicros = (((failsafeMicros<<2)+failsafeMicros)>>3)+860;
|
||||
packet[9 + ch*2] = failsafeMicros & 0xff;
|
||||
packet[10+ ch*2] = ( failsafeMicros >> 8) & 0xff;
|
||||
val = (((val<<2)+val)>>3)+860;
|
||||
if(ch<14)
|
||||
{
|
||||
packet[9 + ch*2] = val;
|
||||
packet[10 + ch*2] = (val>>8)&0x0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[10 + (ch-14)*6] &= 0x0F;
|
||||
packet[10 + (ch-14)*6] |= (val)<<4;
|
||||
packet[12 + (ch-14)*6] &= 0x0F;
|
||||
packet[12 + (ch-14)*6] |= (val)&0xF0;
|
||||
packet[14 + (ch-14)*6] &= 0x0F;
|
||||
packet[14 + (ch-14)*6] |= (val>>4)&0xF0;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{ // no values
|
||||
packet[9 + ch*2] = 0xff;
|
||||
packet[10+ ch*2] = 0xff;
|
||||
}
|
||||
if(ch<14)
|
||||
{ // no values
|
||||
packet[9 + ch*2] = 0xff;
|
||||
packet[10+ ch*2] = 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AFHDS2A_PACKET_SETTINGS:
|
||||
@@ -224,17 +253,14 @@ static void AFHDS2A_build_packet(uint8_t type)
|
||||
if(val<50 || val>400) val=50; // default is 50Hz
|
||||
packet[11]= val;
|
||||
packet[12]= val >> 8;
|
||||
if(sub_protocol == PPM_IBUS || sub_protocol == PPM_SBUS)
|
||||
packet[13] = 0x01; // PPM output enabled
|
||||
else
|
||||
packet[13] = 0x00;
|
||||
packet[13] = sub_protocol & 0x01; // 1 -> PPM output enabled
|
||||
packet[14]= 0x00;
|
||||
for(uint8_t i=15; i<37; i++)
|
||||
packet[i] = 0xff;
|
||||
packet[18] = 0x05; // ?
|
||||
packet[19] = 0xdc; // ?
|
||||
packet[20] = 0x05; // ?
|
||||
if(sub_protocol == PWM_SBUS || sub_protocol == PPM_SBUS)
|
||||
if(sub_protocol&2)
|
||||
packet[21] = 0xdd; // SBUS output enabled
|
||||
else
|
||||
packet[21] = 0xde; // IBUS
|
||||
@@ -244,11 +270,18 @@ static void AFHDS2A_build_packet(uint8_t type)
|
||||
}
|
||||
|
||||
#define AFHDS2A_WAIT_WRITE 0x80
|
||||
uint16_t ReadAFHDS2A()
|
||||
|
||||
#ifdef STM32_BOARD
|
||||
#define AFHDS2A_WRITE_TIME 1550
|
||||
#else
|
||||
#define AFHDS2A_WRITE_TIME 1700
|
||||
#endif
|
||||
|
||||
uint16_t AFHDS2A_callback()
|
||||
{
|
||||
static uint8_t packet_type;
|
||||
static uint16_t packet_counter;
|
||||
uint8_t data_rx;
|
||||
uint8_t data_rx=0;
|
||||
uint16_t start;
|
||||
#ifndef FORCE_AFHDS2A_TUNING
|
||||
A7105_AdjustLOBaseFreq(1);
|
||||
@@ -260,12 +293,12 @@ uint16_t ReadAFHDS2A()
|
||||
case AFHDS2A_BIND3:
|
||||
AFHDS2A_build_bind_packet();
|
||||
A7105_WriteData(AFHDS2A_TXPACKET_SIZE, packet_count%2 ? 0x0d : 0x8c);
|
||||
if(!(A7105_ReadReg(A7105_00_MODE) & (1<<5 | 1<<6)))
|
||||
{ // FECF+CRCF Ok
|
||||
if(!(A7105_ReadReg(A7105_00_MODE) & (1<<5))) // removed FECF check due to issues with fs-x6b -> & (1<<5 | 1<<6)
|
||||
{ // CRCF Ok
|
||||
A7105_ReadData(AFHDS2A_RXPACKET_SIZE);
|
||||
if(packet[0] == 0xbc && packet[9] == 0x01)
|
||||
{
|
||||
uint8_t addr;
|
||||
uint16_t addr;
|
||||
if(RX_num<16)
|
||||
addr=AFHDS2A_EEPROM_OFFSET+RX_num*4;
|
||||
else
|
||||
@@ -277,23 +310,23 @@ uint16_t ReadAFHDS2A()
|
||||
}
|
||||
phase = AFHDS2A_BIND4;
|
||||
packet_count++;
|
||||
return 3850;
|
||||
break;
|
||||
}
|
||||
}
|
||||
packet_count++;
|
||||
if(IS_BIND_DONE)
|
||||
{ // exit bind if asked to do so from the GUI
|
||||
phase = AFHDS2A_BIND4;
|
||||
return 3850;
|
||||
break;
|
||||
}
|
||||
phase |= AFHDS2A_WAIT_WRITE;
|
||||
return 1700;
|
||||
return AFHDS2A_WRITE_TIME;
|
||||
case AFHDS2A_BIND1|AFHDS2A_WAIT_WRITE:
|
||||
case AFHDS2A_BIND2|AFHDS2A_WAIT_WRITE:
|
||||
case AFHDS2A_BIND3|AFHDS2A_WAIT_WRITE:
|
||||
//Wait for TX completion
|
||||
start=micros();
|
||||
while ((uint16_t)micros()-start < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
|
||||
while ((uint16_t)((uint16_t)micros()-start) < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
|
||||
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
|
||||
break;
|
||||
A7105_SetPower();
|
||||
@@ -303,7 +336,7 @@ uint16_t ReadAFHDS2A()
|
||||
phase++;
|
||||
if(phase > AFHDS2A_BIND3)
|
||||
phase = AFHDS2A_BIND1;
|
||||
return 2150;
|
||||
return 3850-AFHDS2A_WRITE_TIME;
|
||||
case AFHDS2A_BIND4:
|
||||
AFHDS2A_build_bind_packet();
|
||||
A7105_WriteData(AFHDS2A_TXPACKET_SIZE, packet_count%2 ? 0x0d : 0x8c);
|
||||
@@ -315,7 +348,7 @@ uint16_t ReadAFHDS2A()
|
||||
phase = AFHDS2A_DATA_INIT;
|
||||
BIND_DONE;
|
||||
}
|
||||
return 3850;
|
||||
break;
|
||||
case AFHDS2A_DATA_INIT:
|
||||
packet_counter=0;
|
||||
packet_type = AFHDS2A_PACKET_STICKS;
|
||||
@@ -325,10 +358,7 @@ uint16_t ReadAFHDS2A()
|
||||
telemetry_set_input_sync(3850);
|
||||
#endif
|
||||
AFHDS2A_build_packet(packet_type);
|
||||
if((A7105_ReadReg(A7105_00_MODE) & 0x01)) // Check if something has been received...
|
||||
data_rx=0;
|
||||
else
|
||||
data_rx=1; // Yes
|
||||
data_rx=A7105_ReadReg(A7105_00_MODE); // Check if something has been received...
|
||||
A7105_WriteData(AFHDS2A_TXPACKET_SIZE, hopping_frequency[hopping_frequency_no++]);
|
||||
if(hopping_frequency_no >= AFHDS2A_NUMFREQ)
|
||||
hopping_frequency_no = 0;
|
||||
@@ -344,32 +374,27 @@ uint16_t ReadAFHDS2A()
|
||||
}
|
||||
else
|
||||
#endif
|
||||
packet_type = AFHDS2A_PACKET_STICKS; // todo : check for settings changes
|
||||
packet_type = AFHDS2A_PACKET_STICKS; // todo : check for settings changes
|
||||
}
|
||||
if(!(A7105_ReadReg(A7105_00_MODE) & (1<<5 | 1<<6)) && data_rx==1)
|
||||
{ // RX+FECF+CRCF Ok
|
||||
if(!(A7105_ReadReg(A7105_00_MODE) & (1<<5)) && !(data_rx & 1)) // removed FECF check due to issues with fs-x6b -> & (1<<5 | 1<<6)
|
||||
{ // RX+CRCF Ok
|
||||
A7105_ReadData(AFHDS2A_RXPACKET_SIZE);
|
||||
if(packet[0] == 0xAA && packet[9] == 0xFC)
|
||||
packet_type=AFHDS2A_PACKET_SETTINGS; // RX is asking for settings
|
||||
packet_type=AFHDS2A_PACKET_SETTINGS; // RX is asking for settings
|
||||
else
|
||||
if(packet[0] == 0xAA || packet[0] == 0xAC)
|
||||
{
|
||||
if((packet[0] == 0xAA && packet[9]!=0xFD) || packet[0] == 0xAC)
|
||||
{// Normal telemetry packet, ignore packets which contain the RX configuration: AA FD FF 32 00 01 00 FF FF FF 05 DC 05 DE FA FF FF FF FF FF FF FF FF FF FF FF FF FF FF
|
||||
if(!memcmp(&packet[1], rx_tx_addr, 4))
|
||||
{ // TX address validated
|
||||
#ifdef AFHDS2A_LQI_CH
|
||||
if(packet[0]==0xAA && packet[9]!=0xFD)
|
||||
{// Normal telemetry packet
|
||||
for(uint8_t sensor=0; sensor<7; sensor++)
|
||||
{//read LQI value for RX output
|
||||
uint8_t index = 9+(4*sensor);
|
||||
if(packet[index]==AFHDS2A_SENSOR_RX_ERR_RATE && packet[index+2]<=100)
|
||||
{
|
||||
RX_LQI=packet[index+2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(uint8_t sensor=0; sensor<7; sensor++)
|
||||
{//read LQI value for RX output
|
||||
uint8_t index = 9+(4*sensor);
|
||||
if(packet[index]==AFHDS2A_SENSOR_RX_ERR_RATE && packet[index+2]<=100)
|
||||
{
|
||||
RX_LQI=packet[index+2];
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if defined(AFHDS2A_FW_TELEMETRY) || defined(AFHDS2A_HUB_TELEMETRY)
|
||||
AFHDS2A_update_telemetry();
|
||||
#endif
|
||||
@@ -378,23 +403,23 @@ uint16_t ReadAFHDS2A()
|
||||
}
|
||||
packet_counter++;
|
||||
phase |= AFHDS2A_WAIT_WRITE;
|
||||
return 1700;
|
||||
return AFHDS2A_WRITE_TIME;
|
||||
case AFHDS2A_DATA|AFHDS2A_WAIT_WRITE:
|
||||
//Wait for TX completion
|
||||
start=micros();
|
||||
while ((uint16_t)micros()-start < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
|
||||
while ((uint16_t)((uint16_t)micros()-start) < 700) // Wait max 700µs, using serial+telemetry exit in about 120µs
|
||||
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
|
||||
break;
|
||||
A7105_SetPower();
|
||||
A7105_SetTxRxMode(RX_EN);
|
||||
A7105_Strobe(A7105_RX);
|
||||
phase &= ~AFHDS2A_WAIT_WRITE;
|
||||
return 2150;
|
||||
return 3850-AFHDS2A_WRITE_TIME;
|
||||
}
|
||||
return 3850; // never reached, please the compiler
|
||||
return 3850;
|
||||
}
|
||||
|
||||
uint16_t initAFHDS2A()
|
||||
void AFHDS2A_init()
|
||||
{
|
||||
A7105_Init();
|
||||
|
||||
@@ -407,7 +432,7 @@ uint16_t initAFHDS2A()
|
||||
{
|
||||
phase = AFHDS2A_DATA_INIT;
|
||||
//Read RX ID from EEPROM based on RX_num, RX_num must be uniq for each RX
|
||||
uint8_t addr;
|
||||
uint16_t addr;
|
||||
if(RX_num<16)
|
||||
addr=AFHDS2A_EEPROM_OFFSET+RX_num*4;
|
||||
else
|
||||
@@ -416,6 +441,9 @@ uint16_t initAFHDS2A()
|
||||
rx_id[i]=eeprom_read_byte((EE_ADDR)(addr+i));
|
||||
}
|
||||
hopping_frequency_no = 0;
|
||||
return 50000;
|
||||
if(sub_protocol&0x04)
|
||||
num_ch=17;
|
||||
else
|
||||
num_ch=14;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -33,19 +33,14 @@ enum {
|
||||
ASSAN_DATA5
|
||||
};
|
||||
|
||||
void ASSAN_init()
|
||||
void ASSAN_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
//Specifics to ASSAN
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x02); // 4 bytes rx/tx address
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x80\x80\x80\xB8", ASSAN_ADDRESS_LENGTH); // Bind address
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x80\x80\x80\xB8", ASSAN_ADDRESS_LENGTH); // Bind address
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x80\x80\x80\xB8", ASSAN_ADDRESS_LENGTH); // Bind address
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, ASSAN_PACKET_SIZE);
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
void ASSAN_send_packet()
|
||||
@@ -169,17 +164,16 @@ static void __attribute__((unused)) ASSAN_initialize_txid()
|
||||
hopping_frequency[1]=freq2;
|
||||
}
|
||||
|
||||
uint16_t initASSAN()
|
||||
void ASSAN_init()
|
||||
{
|
||||
ASSAN_initialize_txid();
|
||||
ASSAN_init();
|
||||
ASSAN_RF_init();
|
||||
hopping_frequency_no = 0;
|
||||
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
phase=ASSAN_BIND0;
|
||||
else
|
||||
phase=ASSAN_DATA0;
|
||||
return 1000;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -115,7 +115,7 @@ void delayMilliseconds(unsigned long ms)
|
||||
uint16_t lms = ms ;
|
||||
|
||||
while (lms > 0) {
|
||||
if (((uint16_t)micros() - start) >= 1000) {
|
||||
if ((uint16_t)((uint16_t)micros() - start) >= 1000) {
|
||||
lms--;
|
||||
start += 1000;
|
||||
}
|
||||
|
||||
@@ -57,22 +57,11 @@ enum {
|
||||
#define BUGSMINI_FLAG_ANGLE 0x02 // angle/acro mode (set is angle mode)
|
||||
#define BUGSMINI_FLAG_ALTHOLD 0x04 // angle/altitude hold mode (set is altitude mode)
|
||||
|
||||
static void __attribute__((unused)) BUGSMINI_init()
|
||||
static void __attribute__((unused)) BUGSMINI_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, BUGSMINI_RX_PAYLOAD_SIZE); // bytes of data payload for rx pipe 1
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, 0x07);
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M);
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x00); // Set feature bits on
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) BUGSMINI_check_arming()
|
||||
@@ -95,7 +84,7 @@ static void __attribute__((unused)) BUGSMINI_check_arming()
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) BUGSMINI_send_packet(uint8_t bind)
|
||||
static void __attribute__((unused)) BUGSMINI_send_packet()
|
||||
{
|
||||
BUGSMINI_check_arming(); // sets globals arm_flags and armed
|
||||
|
||||
@@ -107,7 +96,7 @@ static void __attribute__((unused)) BUGSMINI_send_packet(uint8_t bind)
|
||||
packet[1] = BUGSMINI_txid[0];
|
||||
packet[2] = BUGSMINI_txid[1];
|
||||
packet[3] = BUGSMINI_txid[2];
|
||||
if(bind)
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet[4] = 0x00;
|
||||
packet[5] = 0x7d;
|
||||
@@ -159,7 +148,7 @@ static void __attribute__((unused)) BUGSMINI_send_packet(uint8_t bind)
|
||||
hopping_frequency_no++;
|
||||
if(hopping_frequency_no >= BUGSMINI_NUM_RF_CHANNELS)
|
||||
hopping_frequency_no = 0;
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? hopping_frequency[hopping_frequency_no+BUGSMINI_NUM_RF_CHANNELS] : hopping_frequency[hopping_frequency_no]);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? hopping_frequency[hopping_frequency_no+BUGSMINI_NUM_RF_CHANNELS] : hopping_frequency[hopping_frequency_no]);
|
||||
}
|
||||
|
||||
// Power on, TX mode, 2byte CRC
|
||||
@@ -286,7 +275,7 @@ uint16_t BUGSMINI_callback()
|
||||
}
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
BUGSMINI_send_packet(1);
|
||||
BUGSMINI_send_packet();
|
||||
phase = BUGSMINI_BIND2;
|
||||
return BUGSMINI_WRITE_WAIT;
|
||||
case BUGSMINI_BIND2:
|
||||
@@ -309,7 +298,7 @@ uint16_t BUGSMINI_callback()
|
||||
}
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
BUGSMINI_send_packet(0);
|
||||
BUGSMINI_send_packet();
|
||||
phase = BUGSMINI_DATA2;
|
||||
return BUGSMINI_WRITE_WAIT;
|
||||
case BUGSMINI_DATA2:
|
||||
@@ -357,11 +346,11 @@ static void __attribute__((unused)) BUGSMINI_initialize_txid()
|
||||
BUGSMINI_txhash = pgm_read_byte_near( &BUGSMINI_tx_hash[rx_tx_addr[3]%BUGSMINI_NUM_TX_RF_MAPS] );
|
||||
}
|
||||
|
||||
uint16_t initBUGSMINI()
|
||||
void BUGSMINI_init()
|
||||
{
|
||||
BUGSMINI_initialize_txid();
|
||||
memset(packet, (uint8_t)0, BUGSMINI_TX_PAYLOAD_SIZE);
|
||||
BUGSMINI_init();
|
||||
BUGSMINI_RF_init();
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
XN297_SetTXAddr((const uint8_t*)"mjxRC", 5);
|
||||
@@ -378,7 +367,6 @@ uint16_t initBUGSMINI()
|
||||
armed = 0;
|
||||
arm_flags = BUGSMINI_FLAG_DISARM; // initial value from captures
|
||||
arm_channel_previous = BUGSMINI_CH_SW_ARM;
|
||||
return BUGSMINI_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,18 +33,8 @@ static void __attribute__((unused)) Bayang_Rx_init_nrf24l01()
|
||||
NRF24L01_Initialize();
|
||||
XN297_SetTXAddr(bind_address, BAYANG_RX_ADDRESS_LENGTH);
|
||||
XN297_SetRXAddr(bind_address, BAYANG_RX_ADDRESS_LENGTH);
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, BAYANG_RX_PACKET_SIZE + 2); // 2 extra bytes for xn297 crc
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, BAYANG_RX_RF_BIND_CHANNEL);
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
|
||||
NRF24L01_Activate(0x73);
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
@@ -98,7 +88,7 @@ static void __attribute__((unused)) Bayang_Rx_build_telemetry_packet()
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t initBayang_Rx()
|
||||
void BAYANG_RX_init()
|
||||
{
|
||||
uint8_t i;
|
||||
Bayang_Rx_init_nrf24l01();
|
||||
@@ -119,18 +109,20 @@ uint16_t initBayang_Rx()
|
||||
XN297_SetRXAddr(rx_tx_addr, BAYANG_RX_ADDRESS_LENGTH);
|
||||
phase = BAYANG_RX_DATA;
|
||||
}
|
||||
return 1000;
|
||||
}
|
||||
|
||||
uint16_t Bayang_Rx_callback()
|
||||
uint16_t BAYANG_RX_callback()
|
||||
{
|
||||
uint8_t i;
|
||||
static int8_t read_retry;
|
||||
static uint16_t pps_counter;
|
||||
static uint32_t pps_timer = 0;
|
||||
|
||||
switch (phase) {
|
||||
case BAYANG_RX_BIND:
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
BAYANG_RX_init(); // Abort bind
|
||||
break;
|
||||
}
|
||||
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) {
|
||||
// data received from TX
|
||||
if (XN297_ReadPayload(packet, BAYANG_RX_PACKET_SIZE) && ( packet[0] == 0xA4 || packet[0] == 0xA2 ) && Bayang_Rx_check_validity()) {
|
||||
@@ -156,9 +148,13 @@ uint16_t Bayang_Rx_callback()
|
||||
case BAYANG_RX_DATA:
|
||||
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR)) {
|
||||
if (XN297_ReadPayload(packet, BAYANG_RX_PACKET_SIZE) && packet[0] == 0xA5 && Bayang_Rx_check_validity()) {
|
||||
if (telemetry_link == 0) {
|
||||
if ((telemetry_link & 0x7F) == 0) {
|
||||
Bayang_Rx_build_telemetry_packet();
|
||||
telemetry_link = 1;
|
||||
#ifdef SEND_CPPM
|
||||
if(sub_protocol>0)
|
||||
telemetry_link |= 0x80; // Disable telemetry output
|
||||
#endif
|
||||
}
|
||||
rx_data_started = true;
|
||||
rx_data_received = true;
|
||||
|
||||
@@ -67,12 +67,16 @@ static void __attribute__((unused)) BAYANG_send_packet()
|
||||
else
|
||||
#endif
|
||||
packet[0]= 0xA4;
|
||||
if(sub_protocol==QX100)
|
||||
packet[0] = 0x53;
|
||||
|
||||
for(i=0;i<5;i++)
|
||||
packet[i+1]=rx_tx_addr[i];
|
||||
for(i=0;i<4;i++)
|
||||
packet[i+6]=hopping_frequency[i];
|
||||
switch (sub_protocol)
|
||||
{
|
||||
case QX100:
|
||||
case X16_AH:
|
||||
packet[10] = 0x00;
|
||||
packet[11] = 0x00;
|
||||
@@ -139,19 +143,19 @@ static void __attribute__((unused)) BAYANG_send_packet()
|
||||
if(CH13_SW)
|
||||
packet[3] |= BAYANG_FLAG_EMG_STOP;
|
||||
//Aileron
|
||||
val = convert_channel_10b(AILERON);
|
||||
val = convert_channel_10b(AILERON, false);
|
||||
packet[4] = (val>>8) + (dyntrim ? ((val>>2) & 0xFC) : 0x7C);
|
||||
packet[5] = val & 0xFF;
|
||||
//Elevator
|
||||
val = convert_channel_10b(ELEVATOR);
|
||||
val = convert_channel_10b(ELEVATOR, false);
|
||||
packet[6] = (val>>8) + (dyntrim ? ((val>>2) & 0xFC) : 0x7C);
|
||||
packet[7] = val & 0xFF;
|
||||
//Throttle
|
||||
val = convert_channel_10b(THROTTLE);
|
||||
val = convert_channel_10b(THROTTLE, false);
|
||||
packet[8] = (val>>8) + 0x7C;
|
||||
packet[9] = val & 0xFF;
|
||||
//Rudder
|
||||
val = convert_channel_10b(RUDDER);
|
||||
val = convert_channel_10b(RUDDER, false);
|
||||
packet[10] = (val>>8) + (dyntrim ? ((val>>2) & 0xFC) : 0x7C);
|
||||
packet[11] = val & 0xFF;
|
||||
}
|
||||
@@ -161,6 +165,7 @@ static void __attribute__((unused)) BAYANG_send_packet()
|
||||
packet[12] = rx_tx_addr[2]; // txid[2]
|
||||
packet[13] = 0x34;
|
||||
break;
|
||||
case QX100:
|
||||
case X16_AH:
|
||||
packet[12] = 0;
|
||||
packet[13] = 0;
|
||||
@@ -213,47 +218,40 @@ static void __attribute__((unused)) BAYANG_check_rx(void)
|
||||
for (uint8_t i=1; i < BAYANG_PACKET_SIZE-1; i++)
|
||||
check += packet[i];
|
||||
// decode data , check sum is ok as well, since there is no crc
|
||||
if (packet[0] == 0x85 && packet[14] == check)
|
||||
if (packet[0] == 0x85 && packet[14] == check && telemetry_link == 0)
|
||||
{
|
||||
// uncompensated battery volts*100/2
|
||||
v_lipo1 = (packet[3]<<7) + (packet[4]>>2);
|
||||
v_lipo1 = (packet[3]<<7) + (packet[4]>>1);
|
||||
// compensated battery volts*100/2
|
||||
v_lipo2 = (packet[5]<<7) + (packet[6]>>2);
|
||||
v_lipo2 = (packet[5]<<7) + (packet[6]>>1);
|
||||
// reception in packets / sec
|
||||
RX_LQI = packet[7];
|
||||
RX_RSSI = RX_LQI;
|
||||
//Flags
|
||||
//uint8_t flags = packet[3] >> 3;
|
||||
// battery low: flags & 1
|
||||
telemetry_link=1;
|
||||
#if defined HUB_TELEMETRY
|
||||
// Multiplexed P, I, D values in packet[8] and packet[9].
|
||||
// The two most significant bits specify which term is sent.
|
||||
// Remaining 14 bits represent the value: 0 .. 16383
|
||||
frsky_send_user_frame(0x24+(packet[8]>>6), packet[9], packet[8] & 0x3F ); //0x24 = ACCEL_X_ID, so ACCEL_X_ID=P, ACCEL_Y_ID=I, ACCEL_Z_ID=D
|
||||
#endif
|
||||
telemetry_counter++;
|
||||
if(telemetry_lost==0)
|
||||
telemetry_link=1;
|
||||
if(telemetry_lost)
|
||||
telemetry_link=0; // Don't send anything yet
|
||||
}
|
||||
}
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void __attribute__((unused)) BAYANG_init()
|
||||
static void __attribute__((unused)) BAYANG_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
XN297_SetTXAddr((uint8_t *)"\x00\x00\x00\x00\x00", BAYANG_ADDRESS_LENGTH);
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, BAYANG_PACKET_SIZE);
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // No retransmits
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
|
||||
NRF24L01_Activate(0x73);
|
||||
|
||||
switch (sub_protocol)
|
||||
{
|
||||
@@ -351,15 +349,14 @@ static void __attribute__((unused)) BAYANG_initialize_txid()
|
||||
hopping_frequency_no=0;
|
||||
}
|
||||
|
||||
uint16_t initBAYANG(void)
|
||||
void BAYANG_init(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
phase=BAYANG_BIND;
|
||||
bind_counter = BAYANG_BIND_COUNT;
|
||||
BAYANG_initialize_txid();
|
||||
BAYANG_init();
|
||||
BAYANG_RF_init();
|
||||
packet_count=0;
|
||||
return BAYANG_INITIAL_WAIT+BAYANG_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -315,7 +315,7 @@ static void __attribute__((unused)) BUGS_increment_counts()
|
||||
// FIFO config is one less than desired value
|
||||
#define BUGS_FIFO_SIZE_RX 15
|
||||
#define BUGS_FIFO_SIZE_TX 21
|
||||
uint16_t ReadBUGS(void)
|
||||
uint16_t BUGS_callback(void)
|
||||
{
|
||||
uint8_t mode, base_adr;
|
||||
uint16_t rxid;
|
||||
@@ -340,7 +340,7 @@ uint16_t ReadBUGS(void)
|
||||
case BUGS_BIND_2:
|
||||
//Wait for TX completion
|
||||
start=micros();
|
||||
while ((uint16_t)micros()-start < 500) // Wait max 500µs, using serial+telemetry exit in about 60µs
|
||||
while ((uint16_t)((uint16_t)micros()-start) < 500) // Wait max 500µs, using serial+telemetry exit in about 60µs
|
||||
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
|
||||
break;
|
||||
A7105_SetTxRxMode(RX_EN);
|
||||
@@ -399,7 +399,7 @@ uint16_t ReadBUGS(void)
|
||||
case BUGS_DATA_2:
|
||||
//Wait for TX completion
|
||||
start=micros();
|
||||
while ((uint16_t)micros()-start < 500) // Wait max 500µs, using serial+telemetry exit in about 60µs
|
||||
while ((uint16_t)((uint16_t)micros()-start) < 500) // Wait max 500µs, using serial+telemetry exit in about 60µs
|
||||
if(!(A7105_ReadReg(A7105_00_MODE) & 0x01))
|
||||
break;
|
||||
A7105_SetTxRxMode(RX_EN);
|
||||
@@ -437,7 +437,7 @@ uint16_t ReadBUGS(void)
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
uint16_t initBUGS(void)
|
||||
void BUGS_init(void)
|
||||
{
|
||||
uint16_t rxid=0;
|
||||
uint8_t base_adr=BUGS_EEPROM_OFFSET+(RX_num&0x0F)*2;
|
||||
@@ -459,8 +459,6 @@ uint16_t initBUGS(void)
|
||||
armed = 0;
|
||||
arm_flags = BUGS_FLAG_DISARM; // initial value from captures
|
||||
arm_channel_previous = BUGS_CH_SW_ARM;
|
||||
|
||||
return 10000;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -255,7 +255,7 @@ static void __attribute__((unused)) CABELL_send_packet(uint8_t bindMode)
|
||||
*p |= (packet_count++)<<7; // This causes the 8th bit of the first byte to toggle with each xmit so consecutive payloads are not identical.
|
||||
// This is a work around for a reported bug in clone NRF24L01 chips that mis-took this case for a re-transmit of the same packet.
|
||||
|
||||
CABELL_SetPower();
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_WritePayload((uint8_t*)&TxPacket, packetSize);
|
||||
|
||||
#if defined CABELL_HUB_TELEMETRY
|
||||
@@ -356,48 +356,18 @@ static void __attribute__((unused)) CABELL_setAddress()
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
static void __attribute__((unused)) CABELL_init()
|
||||
static void __attribute__((unused)) CABELL_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
CABELL_SetPower();
|
||||
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // slower data rate gives better range/reliability
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment on all data pipes
|
||||
NRF24L01_SetTxRxMode(TX_EN); //Power up and 16 bit CRC
|
||||
|
||||
CABELL_setAddress();
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01);
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 0x20); // 32 byte packet length
|
||||
NRF24L01_WriteReg(NRF24L01_12_RX_PW_P1, 0x20); // 32 byte packet length
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x5F); // no retransmits
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3F); // Enable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x04); // Enable dynamic Payload Length
|
||||
NRF24L01_Activate(0x73);
|
||||
prev_power = NRF_POWER_0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
static void CABELL_SetPower() // This over-ride the standard Set Power to allow an flag in option to indicate max power setting
|
||||
// Note that on many modules max power may actually be worse than the normal high power setting
|
||||
// test and only use max if it helps the range
|
||||
{
|
||||
if(IS_BIND_DONE && !IS_RANGE_FLAG_on && ((option & CABELL_OPTION_MASK_MAX_POWER_OVERRIDE) != 0))
|
||||
{ // If we are not in range or bind mode and power setting override is in effect, then set max power, else standard power logic
|
||||
if(prev_power != NRF_POWER_3) // prev_power is global variable for NRF24L01; NRF_POWER_3 is max power
|
||||
{
|
||||
uint8_t rf_setup = NRF24L01_ReadReg(NRF24L01_06_RF_SETUP);
|
||||
rf_setup = (rf_setup & 0xF9) | (NRF_POWER_3 << 1);
|
||||
NRF24L01_WriteReg(NRF24L01_06_RF_SETUP, rf_setup);
|
||||
prev_power=NRF_POWER_3;
|
||||
}
|
||||
}
|
||||
else
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_SetTxRxMode(TX_EN); // Clear data ready, data sent, retransmit and enable CRC 16bits, ready for TX
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
@@ -414,7 +384,7 @@ uint16_t CABELL_callback()
|
||||
else if (bind_counter == 0)
|
||||
{
|
||||
BIND_DONE;
|
||||
CABELL_init(); // non-bind address
|
||||
CABELL_RF_init(); // non-bind address
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -425,17 +395,15 @@ uint16_t CABELL_callback()
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
uint16_t initCABELL(void)
|
||||
void CABELL_init(void)
|
||||
{
|
||||
if (IS_BIND_DONE)
|
||||
bind_counter = 0;
|
||||
else
|
||||
bind_counter = CABELL_BIND_COUNT;
|
||||
CABELL_init();
|
||||
CABELL_RF_init();
|
||||
|
||||
packet_period = CABELL_PACKET_PERIOD;
|
||||
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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)
|
||||
@@ -158,4 +163,174 @@ void CC2500_SetPower()
|
||||
prev_power=power;
|
||||
}
|
||||
}
|
||||
|
||||
void __attribute__((unused)) CC2500_SetFreqOffset()
|
||||
{
|
||||
if(prev_option != option)
|
||||
{
|
||||
prev_option = option;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
}
|
||||
}
|
||||
|
||||
void __attribute__((unused)) CC2500_250K_Init()
|
||||
{
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
|
||||
// Address Config = No address check
|
||||
// Base Frequency = 2400
|
||||
// CRC Autoflush = false
|
||||
// CRC Enable = false
|
||||
// Channel Spacing = 333.251953
|
||||
// Data Format = Normal mode
|
||||
// Data Rate = 249.939
|
||||
// Deviation = 126.953125
|
||||
// Device Address = 0
|
||||
// Manchester Enable = false
|
||||
// Modulated = true
|
||||
// Modulation Format = GFSK
|
||||
// Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word
|
||||
// RX Filter BW = 203.125000
|
||||
// Sync Word Qualifier Mode = No preamble/sync
|
||||
// TX Power = 0
|
||||
// Whitening = false
|
||||
// Fast Frequency Hopping - no PLL auto calibration
|
||||
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x01); // Packet Automation Control
|
||||
CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0A); // Frequency Synthesizer Control
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option); // Frequency offset hack
|
||||
CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // Frequency Control Word, High Byte
|
||||
CC2500_WriteReg(CC2500_0E_FREQ1, 0x4E); // Frequency Control Word, Middle Byte
|
||||
CC2500_WriteReg(CC2500_0F_FREQ0, 0xC3); // Frequency Control Word, Low Byte
|
||||
CC2500_WriteReg(CC2500_10_MDMCFG4, 0x8D); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_12_MDMCFG2, 0x10); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_14_MDMCFG0, 0xA4); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_15_DEVIATN, 0x62); // Modem Deviation Setting
|
||||
CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // Main Radio Control State Machine Configuration
|
||||
CC2500_WriteReg(CC2500_19_FOCCFG, 0x1D); // Frequency Offset Compensation Configuration
|
||||
CC2500_WriteReg(CC2500_1A_BSCFG, 0x1C); // Bit Synchronization Configuration
|
||||
CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xC7); // AGC Control
|
||||
CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x00); // AGC Control
|
||||
CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0xB0); // AGC Control
|
||||
CC2500_WriteReg(CC2500_21_FREND1, 0xB6); // Front End RX Configuration
|
||||
CC2500_WriteReg(CC2500_23_FSCAL3, 0xEA); // Frequency Synthesizer Calibration
|
||||
CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // Frequency Synthesizer Calibration
|
||||
CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // Frequency Synthesizer Calibration
|
||||
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
CC2500_SetPower();
|
||||
}
|
||||
void __attribute__((unused)) CC2500_250K_HoppingCalib(uint8_t num_freq)
|
||||
{
|
||||
for (uint8_t i = 0; i < num_freq; i++)
|
||||
{
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
// spacing is 333.25 kHz, must multiply channel by 3
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[i]*3);
|
||||
// calibrate
|
||||
CC2500_Strobe(CC2500_SCAL);
|
||||
delayMicroseconds(900);
|
||||
calData[i]=CC2500_ReadReg(CC2500_25_FSCAL1);
|
||||
}
|
||||
}
|
||||
void __attribute__((unused)) CC2500_250K_Hopping(uint8_t index)
|
||||
{
|
||||
// spacing is 333.25 kHz, must multiply channel by 3
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[index] * 3);
|
||||
// set PLL calibration
|
||||
CC2500_WriteReg(CC2500_25_FSCAL1, calData[index]);
|
||||
}
|
||||
void __attribute__((unused)) CC2500_250K_RFChannel(uint8_t number)
|
||||
{
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
// spacing is 333.25 kHz, must multiply channel by 3
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, number*3);
|
||||
// calibrate
|
||||
CC2500_Strobe(CC2500_SCAL);
|
||||
delayMicroseconds(900);
|
||||
}
|
||||
|
||||
//NRF emulation layer with CRC16 enabled
|
||||
uint8_t cc2500_nrf_tx_addr[5], cc2500_nrf_addr_len;
|
||||
void __attribute__((unused)) CC2500_250K_NRF_SetTXAddr(uint8_t* addr, uint8_t len)
|
||||
{
|
||||
cc2500_nrf_addr_len = len;
|
||||
memcpy(cc2500_nrf_tx_addr, addr, len);
|
||||
}
|
||||
void __attribute__((unused)) CC2500_250K_NRF_WritePayload(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
#if defined(ESKY150V2_CC2500_INO)
|
||||
uint8_t buf[158];
|
||||
#else
|
||||
uint8_t buf[35];
|
||||
#endif
|
||||
uint8_t last = 0;
|
||||
uint8_t i;
|
||||
|
||||
//nrf preamble
|
||||
if(cc2500_nrf_tx_addr[cc2500_nrf_addr_len - 1] & 0x80)
|
||||
buf[0]=0xAA;
|
||||
else
|
||||
buf[0]=0x55;
|
||||
last++;
|
||||
// address
|
||||
for (i = 0; i < cc2500_nrf_addr_len; ++i)
|
||||
buf[last++] = cc2500_nrf_tx_addr[cc2500_nrf_addr_len - i - 1];
|
||||
// payload
|
||||
for (i = 0; i < len; ++i)
|
||||
buf[last++] = msg[i];
|
||||
|
||||
// crc
|
||||
crc = 0xffff;
|
||||
for (uint8_t i = 1; i < last; ++i)
|
||||
crc16_update( buf[i], 8);
|
||||
buf[last++] = crc >> 8;
|
||||
buf[last++] = crc & 0xff;
|
||||
buf[last++] = 0;
|
||||
|
||||
//for(uint8_t i=0;i<last;i++)
|
||||
// debug("%02X ",buf[i]);
|
||||
//debugln("");
|
||||
// stop TX/RX
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
// flush tx FIFO
|
||||
CC2500_Strobe(CC2500_SFTX);
|
||||
// packet length
|
||||
CC2500_WriteReg(CC2500_3F_TXFIFO, last);
|
||||
// transmit nrf packet
|
||||
uint8_t *buff=buf;
|
||||
uint8_t status;
|
||||
if(last>63)
|
||||
{
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, 63);
|
||||
CC2500_Strobe(CC2500_STX);
|
||||
last-=63;
|
||||
buff+=63;
|
||||
while(last)
|
||||
{//Loop until all the data is sent
|
||||
do
|
||||
{// Wait for the FIFO to become available
|
||||
status=CC2500_ReadReg(CC2500_3A_TXBYTES | CC2500_READ_BURST);
|
||||
}
|
||||
while((status&0x7F)>31 && (status&0x80)==0);
|
||||
if(last>31)
|
||||
{//Send 31 bytes
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, 31);
|
||||
last-=31;
|
||||
buff+=31;
|
||||
}
|
||||
else
|
||||
{//Send last bytes
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, last);
|
||||
last=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{//Send packet
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buff, last);
|
||||
CC2500_Strobe(CC2500_STX);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -644,37 +644,24 @@ static uint8_t crtp_log_setup_state_machine()
|
||||
return state_machine_completed;
|
||||
}
|
||||
|
||||
static int cflie_init()
|
||||
static void CFLIE_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
|
||||
// CRC, radio on
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x01); // Auto Acknowledgement for data pipe 0
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, TX_ADDR_SIZE-2); // 5-byte RX/TX address
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x13); // 3 retransmits, 500us delay
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch_num); // Defined in initialize_rx_tx_addr
|
||||
NRF24L01_SetBitrate(data_rate); // Defined in initialize_rx_tx_addr
|
||||
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, TX_ADDR_SIZE);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, TX_ADDR_SIZE);
|
||||
|
||||
// this sequence necessary for module from stock tx
|
||||
NRF24L01_ReadReg(NRF24L01_1D_FEATURE);
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_ReadReg(NRF24L01_1D_FEATURE);
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x01); // Enable Dynamic Payload Length on pipe 0
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x06); // Enable Dynamic Payload Length, enable Payload with ACK
|
||||
|
||||
// 50ms delay in callback
|
||||
return 50000;
|
||||
NRF24L01_SetTxRxMode(TX_EN); // Clear data ready, data sent, retransmit and enable CRC 16bits, ready for TX
|
||||
}
|
||||
|
||||
// TODO: Fix telemetry
|
||||
@@ -749,7 +736,7 @@ static int cflie_init()
|
||||
// }
|
||||
// }
|
||||
|
||||
static uint16_t cflie_callback()
|
||||
static uint16_t CFLIE_callback()
|
||||
{
|
||||
switch (phase) {
|
||||
case CFLIE_INIT_SEARCH:
|
||||
@@ -799,7 +786,7 @@ static uint16_t cflie_callback()
|
||||
}
|
||||
|
||||
// Generate address to use from TX id and manufacturer id (STM32 unique id)
|
||||
static uint8_t initialize_rx_tx_addr()
|
||||
static uint8_t CFLIE_initialize_rx_tx_addr()
|
||||
{
|
||||
rx_tx_addr[0] =
|
||||
rx_tx_addr[1] =
|
||||
@@ -844,19 +831,15 @@ static uint8_t initialize_rx_tx_addr()
|
||||
return CFLIE_INIT_SEARCH;
|
||||
}
|
||||
|
||||
uint16_t initCFlie(void)
|
||||
void CFLIE_init(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
|
||||
phase = initialize_rx_tx_addr();
|
||||
phase = CFLIE_initialize_rx_tx_addr();
|
||||
crtp_log_setup_state = CFLIE_CRTP_LOG_SETUP_STATE_INIT;
|
||||
packet_count=0;
|
||||
|
||||
int delay = cflie_init();
|
||||
|
||||
// debugln("CFlie init!");
|
||||
|
||||
return delay;
|
||||
CFLIE_RF_init();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -49,7 +49,7 @@ enum YD829_FLAGS {
|
||||
YD829_FLAG_STILL = 0x80,
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) CG023_send_packet(uint8_t bind)
|
||||
static void __attribute__((unused)) CG023_send_packet()
|
||||
{
|
||||
// throttle : 0x00 - 0xFF
|
||||
throttle=convert_channel_8b(THROTTLE);
|
||||
@@ -62,7 +62,7 @@ static void __attribute__((unused)) CG023_send_packet(uint8_t bind)
|
||||
// aileron : 0x43 - 0x7F - 0xBB
|
||||
aileron = convert_channel_16b_limit(AILERON, 0x43, 0xBB);
|
||||
|
||||
if (bind)
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
packet[0]= 0xaa;
|
||||
else
|
||||
packet[0]= 0x55;
|
||||
@@ -106,7 +106,7 @@ static void __attribute__((unused)) CG023_send_packet(uint8_t bind)
|
||||
// Power on, TX mode, 2byte CRC
|
||||
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
if (bind)
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, CG023_RF_BIND_CHANNEL);
|
||||
else
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency_no);
|
||||
@@ -119,41 +119,25 @@ static void __attribute__((unused)) CG023_send_packet(uint8_t bind)
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) CG023_init()
|
||||
static void __attribute__((unused)) CG023_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
XN297_SetTXAddr((uint8_t *)"\x26\xA8\x67\x35\xCC", 5);
|
||||
NRF24L01_Initialize();
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
XN297_SetTXAddr((uint8_t *)"\x26\xA8\x67\x35\xCC", 5);
|
||||
}
|
||||
|
||||
uint16_t CG023_callback()
|
||||
{
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
CG023_send_packet(0);
|
||||
}
|
||||
else
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
if(bind_counter)
|
||||
{
|
||||
bind_counter--;
|
||||
if (bind_counter == 0)
|
||||
BIND_DONE;
|
||||
else
|
||||
{
|
||||
CG023_send_packet(1);
|
||||
bind_counter--;
|
||||
}
|
||||
}
|
||||
CG023_send_packet();
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
@@ -165,17 +149,16 @@ static void __attribute__((unused)) CG023_initialize_txid()
|
||||
hopping_frequency_no = rx_tx_addr[0] - 0x7D; // rf channel for data packets
|
||||
}
|
||||
|
||||
uint16_t initCG023(void)
|
||||
void CG023_init(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
bind_counter = CG023_BIND_COUNT;
|
||||
CG023_initialize_txid();
|
||||
CG023_init();
|
||||
CG023_RF_init();
|
||||
if(sub_protocol==CG023)
|
||||
packet_period=CG023_PACKET_PERIOD;
|
||||
else // YD829
|
||||
packet_period=YD829_PACKET_PERIOD;
|
||||
return CG023_INITIAL_WAIT+YD829_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,17 +19,17 @@
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#define CX10_BIND_COUNT 4360 // 6 seconds
|
||||
#define CX10_BIND_COUNT 4360 // 6 seconds
|
||||
#define CX10_PACKET_SIZE 15
|
||||
#define CX10A_PACKET_SIZE 19 // CX10 blue board packets have 19-byte payload
|
||||
#define CX10A_PACKET_SIZE 19 // CX10 blue board packets have 19-byte payload
|
||||
#define Q2X2_PACKET_SIZE 21
|
||||
#define CX10_PACKET_PERIOD 1316 // Timeout for callback in uSec
|
||||
#define CX10_PACKET_PERIOD 1316 // Timeout for callback in uSec
|
||||
#define CX10A_PACKET_PERIOD 6000
|
||||
|
||||
#define CX10_INITIAL_WAIT 500
|
||||
|
||||
// flags
|
||||
#define CX10_FLAG_FLIP 0x10 // goes to rudder channel
|
||||
#define CX10_FLAG_FLIP 0x10 // goes to rudder channel
|
||||
#define CX10_FLAG_MODE_MASK 0x03
|
||||
#define CX10_FLAG_HEADLESS 0x04
|
||||
// flags2
|
||||
@@ -169,21 +169,14 @@ static void __attribute__((unused)) CX10_Write_Packet(uint8_t bind)
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) CX10_init()
|
||||
static void __attribute__((unused)) CX10_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
XN297_SetTXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc",5);
|
||||
XN297_SetRXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc",5);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, packet_length); // rx pipe 0 (used only for blue board)
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, CX10_RF_BIND_CHANNEL);
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, CX10_RF_BIND_CHANNEL);
|
||||
}
|
||||
|
||||
uint16_t CX10_callback()
|
||||
@@ -220,7 +213,8 @@ uint16_t CX10_callback()
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
CX10_Write_Packet(1);
|
||||
delayMicroseconds(400);
|
||||
// wait for packet to be sent
|
||||
while( (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)) == 0); //delayMicroseconds(400);
|
||||
// switch to RX mode
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_FlushRx();
|
||||
@@ -260,9 +254,13 @@ static void __attribute__((unused)) CX10_initialize_txid()
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t initCX10(void)
|
||||
void CX10_init(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
|
||||
if(protocol == PROTO_Q2X2)
|
||||
sub_protocol|=0x08; // Increase the number of sub_protocols for CX-10
|
||||
|
||||
if(sub_protocol==CX10_BLUE)
|
||||
{
|
||||
packet_length = CX10A_PACKET_SIZE;
|
||||
@@ -285,8 +283,7 @@ uint16_t initCX10(void)
|
||||
bind_counter = CX10_BIND_COUNT;
|
||||
}
|
||||
CX10_initialize_txid();
|
||||
CX10_init();
|
||||
return CX10_INITIAL_WAIT+packet_period;
|
||||
CX10_RF_init();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -98,14 +98,14 @@ void CYRF_SetTxRxMode(uint8_t mode)
|
||||
{
|
||||
if(mode==TXRX_OFF)
|
||||
{
|
||||
if(protocol!=PROTO_WFLY)
|
||||
if( protocol!=PROTO_WFLY && protocol!=PROTO_MLINK )
|
||||
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24); // 4=IDLE, 8=TX, C=RX
|
||||
CYRF_WriteRegister(CYRF_0E_GPIO_CTRL,0x00); // XOUT=0 PACTL=0
|
||||
}
|
||||
else
|
||||
{
|
||||
//Set the post tx/rx state
|
||||
if(protocol!=PROTO_WFLY)
|
||||
if( protocol!=PROTO_WFLY && protocol!=PROTO_MLINK )
|
||||
CYRF_WriteRegister(CYRF_0F_XACT_CFG, mode == TX_EN ? 0x28 : 0x2C); // 4=IDLE, 8=TX, C=RX
|
||||
if(mode == TX_EN)
|
||||
#ifdef ORANGE_TX_BLUE
|
||||
@@ -168,10 +168,10 @@ void CYRF_SetPower(uint8_t val)
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void CYRF_ConfigCRCSeed(uint16_t crc)
|
||||
void CYRF_ConfigCRCSeed(uint16_t crc_seed)
|
||||
{
|
||||
CYRF_WriteRegister(CYRF_15_CRC_SEED_LSB,crc & 0xff);
|
||||
CYRF_WriteRegister(CYRF_16_CRC_SEED_MSB,crc >> 8);
|
||||
CYRF_WriteRegister(CYRF_15_CRC_SEED_LSB,crc_seed & 0xff);
|
||||
CYRF_WriteRegister(CYRF_16_CRC_SEED_MSB,crc_seed >> 8);
|
||||
}
|
||||
/*
|
||||
* these are the recommended sop codes from Cyrpress
|
||||
@@ -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];
|
||||
@@ -320,4 +321,69 @@ static void __attribute__((unused)) CYRF_PROGMEM_ConfigSOPCode(const uint8_t *da
|
||||
code[i]=pgm_read_byte_near(&data[i]);
|
||||
CYRF_ConfigSOPCode(code);
|
||||
}
|
||||
|
||||
//CYRF GFSK 1Mb functions
|
||||
const uint8_t PROGMEM CYRF_GFSK1M_init_vals[][2] = {
|
||||
{CYRF_02_TX_CTRL, 0x00}, // transmit err & complete interrupts disabled
|
||||
{CYRF_05_RX_CTRL, 0x00}, // receive err & complete interrupts disabled
|
||||
{CYRF_28_CLK_EN, 0x02}, // Force Receive Clock Enable, MUST be set
|
||||
{CYRF_32_AUTO_CAL_TIME, 0x3c}, // must be set to 3C
|
||||
{CYRF_35_AUTOCAL_OFFSET, 0x14}, // must be set to 14
|
||||
{CYRF_06_RX_CFG, 0x48}, // LNA manual control, Rx Fast Turn Mode Enable
|
||||
{CYRF_1B_TX_OFFSET_LSB, 0x00}, // Tx frequency offset LSB
|
||||
{CYRF_1C_TX_OFFSET_MSB, 0x00}, // Tx frequency offset MSB
|
||||
{CYRF_0F_XACT_CFG, 0x24}, // Force End State, transaction end state = idle
|
||||
{CYRF_03_TX_CFG, 0x00}, // GFSK mode
|
||||
{CYRF_12_DATA64_THOLD, 0x0a}, // 64 Chip Data PN Code Correlator Threshold = 10
|
||||
{CYRF_0F_XACT_CFG, 0x04}, // Transaction End State = idle
|
||||
{CYRF_39_ANALOG_CTRL, 0x01}, // synth setting time for all channels is the same as for slow channels
|
||||
{CYRF_0F_XACT_CFG, 0x24}, //Force IDLE
|
||||
{CYRF_29_RX_ABORT, 0x00}, //Clear RX abort
|
||||
{CYRF_12_DATA64_THOLD, 0x0a}, //set pn correlation threshold
|
||||
{CYRF_10_FRAMING_CFG, 0x4a}, //set sop len and threshold
|
||||
{CYRF_29_RX_ABORT, 0x0f}, //Clear RX abort?
|
||||
{CYRF_03_TX_CFG, 0x00}, // GFSK mode
|
||||
{CYRF_10_FRAMING_CFG, 0x4a}, // 0b11000000 //set sop len and threshold
|
||||
{CYRF_1F_TX_OVERRIDE, 0x04}, //disable tx CRC
|
||||
{CYRF_1E_RX_OVERRIDE, 0x14}, //disable rx crc
|
||||
{CYRF_14_EOP_CTRL, 0x00}, //set EOP sync == 0
|
||||
};
|
||||
static void __attribute__((unused)) CYRF_GFSK1M_Init(uint8_t payload_length, uint8_t preamble_len)
|
||||
{
|
||||
for(uint8_t i = 0; i < sizeof(CYRF_GFSK1M_init_vals) / 2; i++)
|
||||
CYRF_WriteRegister(pgm_read_byte_near(&CYRF_GFSK1M_init_vals[i][0]), pgm_read_byte_near(&CYRF_GFSK1M_init_vals[i][1]));
|
||||
|
||||
|
||||
CYRF_WriteRegister(CYRF_01_TX_LENGTH, payload_length);
|
||||
|
||||
CYRF_WritePreamble(0xAAAA00 | preamble_len);
|
||||
|
||||
CYRF_SetPower(0x00);
|
||||
|
||||
CYRF_SetTxRxMode(TX_EN);
|
||||
}
|
||||
static void __attribute__((unused)) CYRF_GFSK1M_SendPayload(uint8_t *buffer, uint8_t len)
|
||||
{
|
||||
uint8_t send=len>16 ? 16 : len;
|
||||
CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x40);
|
||||
CYRF_WriteRegisterMulti(CYRF_20_TX_BUFFER, buffer, send); // Fill the buffer with 16 bytes max
|
||||
CYRF_WriteRegister(CYRF_02_TX_CTRL, 0x80); // Start send
|
||||
buffer += send;
|
||||
len -= send;
|
||||
|
||||
while(len>8)
|
||||
{
|
||||
while((CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS)&0x10) == 0); // Wait that half of the buffer is empty
|
||||
CYRF_WriteRegisterMulti(CYRF_20_TX_BUFFER, buffer, 8); // Add 8 bytes to the buffer
|
||||
buffer+=8;
|
||||
len-=8;
|
||||
}
|
||||
|
||||
if(len)
|
||||
{
|
||||
while((CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS)&0x10) == 0); // Wait that half of the buffer is empty
|
||||
CYRF_WriteRegisterMulti(CYRF_20_TX_BUFFER, buffer, len); // Add the remaining bytes to the buffer
|
||||
}
|
||||
}
|
||||
#define CYRF_GFSK1M_SetPower() CYRF_SetPower(0x00)
|
||||
#endif
|
||||
@@ -32,9 +32,15 @@ uint16_t convert_channel_ppm(uint8_t num)
|
||||
}
|
||||
|
||||
// Channel value 100% is converted to 10bit values 0<->1023
|
||||
uint16_t convert_channel_10b(uint8_t num)
|
||||
uint16_t convert_channel_10b(uint8_t num, bool failsafe)
|
||||
{
|
||||
uint16_t val=Channel_data[num];
|
||||
uint16_t val;
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
if(failsafe)
|
||||
val=Failsafe_data[num]; // 0<->2047
|
||||
else
|
||||
#endif
|
||||
val=Channel_data[num];
|
||||
val=((val<<2)+val)>>3;
|
||||
if(val<=128) return 0;
|
||||
if(val>=1152) return 1023;
|
||||
@@ -91,9 +97,15 @@ int16_t convert_channel_16b_limit(uint8_t num,int16_t min,int16_t max)
|
||||
}
|
||||
|
||||
// Channel value -125%<->125% is scaled to 16bit value with no limit
|
||||
int16_t convert_channel_16b_nolimit(uint8_t num, int16_t min, int16_t max)
|
||||
int16_t convert_channel_16b_nolimit(uint8_t num, int16_t min, int16_t max, bool failsafe)
|
||||
{
|
||||
int32_t val=Channel_data[num]; // 0<->2047
|
||||
int32_t val;
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
if(failsafe)
|
||||
val=Failsafe_data[num]; // 0<->2047
|
||||
else
|
||||
#endif
|
||||
val=Channel_data[num]; // 0<->2047
|
||||
val=(val-CHANNEL_MIN_100)*(max-min)/(CHANNEL_MAX_100-CHANNEL_MIN_100)+min;
|
||||
return (uint16_t)val;
|
||||
}
|
||||
@@ -151,14 +163,14 @@ static uint16_t __attribute__((unused)) FrSkyX_scaleForPXX( uint8_t i, uint8_t
|
||||
}
|
||||
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
static uint16_t __attribute__((unused)) FrSkyX_scaleForPXX_FS( uint8_t i )
|
||||
static uint16_t __attribute__((unused)) FrSkyX_scaleForPXX_FS( uint8_t i, uint8_t num_chan=8)
|
||||
{ //mapped 1,2046(125%) range to 64,1984(PXX values);
|
||||
uint16_t chan_val=((Failsafe_data[i]*15)>>4)+64;
|
||||
if(Failsafe_data[i]==FAILSAFE_CHANNEL_NOPULSES)
|
||||
chan_val=FAILSAFE_CHANNEL_NOPULSES;
|
||||
else if(Failsafe_data[i]==FAILSAFE_CHANNEL_HOLD)
|
||||
chan_val=FAILSAFE_CHANNEL_HOLD;
|
||||
if(i>7) chan_val|=2048; // upper channels offset
|
||||
if(i>=num_chan) chan_val|=2048; // upper channels offset
|
||||
return chan_val;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -61,7 +61,6 @@ static void __attribute__((unused)) CORONA_rf_init()
|
||||
CC2500_WriteReg(CC2500_15_DEVIATN, 0x50);
|
||||
}
|
||||
|
||||
prev_option = option;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
|
||||
//not sure what they are doing to the PATABLE since basically only the first byte is used and it's only 8 bytes long. So I think they end up filling the PATABLE fully with 0xFF
|
||||
@@ -72,7 +71,7 @@ static void __attribute__((unused)) CORONA_rf_init()
|
||||
}
|
||||
|
||||
// Generate id and hopping freq
|
||||
static void __attribute__((unused)) CORONA_init()
|
||||
static void __attribute__((unused)) CORONA_TXID_init()
|
||||
{
|
||||
#ifdef CORONA_FORCE_ID
|
||||
// Example of ID and channels taken from dumps
|
||||
@@ -256,17 +255,13 @@ static uint16_t __attribute__((unused)) CORONA_build_packet()
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
uint16_t ReadCORONA()
|
||||
uint16_t CORONA_callback()
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(22000);
|
||||
#endif
|
||||
// Tune frequency if it has been changed
|
||||
if ( prev_option != option )
|
||||
{
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
prev_option = option ;
|
||||
}
|
||||
CC2500_SetFreqOffset();
|
||||
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
@@ -281,7 +276,7 @@ uint16_t ReadCORONA()
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
uint16_t initCORONA()
|
||||
void CORONA_init()
|
||||
{
|
||||
switch(sub_protocol)
|
||||
{
|
||||
@@ -298,9 +293,8 @@ uint16_t initCORONA()
|
||||
state=400; // Used by V2 to send RF channels + ID for 2.65s at startup
|
||||
hopping_frequency_no=0;
|
||||
fdv3_id_send = 0;
|
||||
CORONA_init();
|
||||
CORONA_TXID_init();
|
||||
CORONA_rf_init();
|
||||
return 10000;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -37,10 +37,10 @@ enum DM002_FLAGS {
|
||||
DM002_FLAG_CAMERA2 = 0x80,
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) DM002_send_packet(uint8_t bind)
|
||||
static void __attribute__((unused)) DM002_send_packet()
|
||||
{
|
||||
memcpy(packet+5,(uint8_t *)"\x00\x7F\x7F\x7F\x00\x00\x00",7);
|
||||
if(bind)
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet[0] = 0xAA;
|
||||
packet[1] = rx_tx_addr[0];
|
||||
@@ -83,10 +83,7 @@ static void __attribute__((unused)) DM002_send_packet(uint8_t bind)
|
||||
// Power on, TX mode, 2byte CRC
|
||||
// Why CRC0? xn297 does not interpret it - either 16-bit CRC or nothing
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
if (bind)
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, DM002_RF_BIND_CHANNEL);
|
||||
else
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? DM002_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no]);
|
||||
// clear packet status bits and TX FIFO
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
@@ -95,43 +92,28 @@ static void __attribute__((unused)) DM002_send_packet(uint8_t bind)
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DM002_init()
|
||||
static void __attribute__((unused)) DM002_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
XN297_SetTXAddr((uint8_t *)"\x26\xA8\x67\x35\xCC", 5);
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
XN297_SetTXAddr((uint8_t *)"\x26\xA8\x67\x35\xCC", 5);
|
||||
}
|
||||
|
||||
uint16_t DM002_callback()
|
||||
{
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(DM002_PACKET_PERIOD);
|
||||
#endif
|
||||
DM002_send_packet(0);
|
||||
}
|
||||
else
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(DM002_PACKET_PERIOD);
|
||||
#endif
|
||||
if (bind_counter)
|
||||
{
|
||||
bind_counter--;
|
||||
if (bind_counter == 0)
|
||||
{
|
||||
BIND_DONE;
|
||||
XN297_SetTXAddr(rx_tx_addr, 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
DM002_send_packet(1);
|
||||
bind_counter--;
|
||||
}
|
||||
}
|
||||
DM002_send_packet();
|
||||
return DM002_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
@@ -155,13 +137,12 @@ static void __attribute__((unused)) DM002_initialize_txid()
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t initDM002(void)
|
||||
void DM002_init(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
bind_counter = DM002_BIND_COUNT;
|
||||
DM002_initialize_txid();
|
||||
DM002_init();
|
||||
return DM002_INITIAL_WAIT;
|
||||
DM002_RF_init();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
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
|
||||
508
Multiprotocol/DSM_Rx_cyrf6936.ino
Normal file
508
Multiprotocol/DSM_Rx_cyrf6936.ino
Normal file
@@ -0,0 +1,508 @@
|
||||
/*
|
||||
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_RF_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;
|
||||
#ifdef SEND_CPPM
|
||||
if(sub_protocol>0)
|
||||
telemetry_link |= 0x80; // Disable telemetry output
|
||||
#endif
|
||||
}
|
||||
|
||||
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];
|
||||
debugln(", num_ch=%d, type=%02X",num_ch, DSM_rx_type);
|
||||
switch(DSM_rx_type)
|
||||
{
|
||||
case 0x01:
|
||||
if(num_ch>7) DSM_rx_type = 0x02; // Can't be 0x01 with this number of channels
|
||||
break;
|
||||
case 0xA2:
|
||||
if(num_ch>7) DSM_rx_type = 0xB2; // Can't be 0xA2 with this number of channels
|
||||
break;
|
||||
case 0x02:
|
||||
case 0x12:
|
||||
case 0xB2:
|
||||
break;
|
||||
default: // Unknown type, default to DSMX 11ms
|
||||
DSM_rx_type = 0xB2;
|
||||
break;
|
||||
}
|
||||
eeprom_write_byte((EE_ADDR)temp, DSM_rx_type);
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
|
||||
CYRF_SetTxRxMode(TX_EN); // Force end state TX
|
||||
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;
|
||||
}
|
||||
|
||||
void DSM_RX_init()
|
||||
{
|
||||
DSM_RX_RF_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;
|
||||
}
|
||||
}
|
||||
|
||||
#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, 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;
|
||||
@@ -187,23 +82,26 @@ static void __attribute__((unused)) DSM_build_bind_packet()
|
||||
sum += packet[i];
|
||||
packet[8] = sum >> 8;
|
||||
packet[9] = sum & 0xff;
|
||||
packet[10] = 0x01; //???
|
||||
packet[11] = num_ch;
|
||||
packet[10] = 0x01; // ???
|
||||
if(sub_protocol==DSM_AUTO)
|
||||
packet[11] = 12;
|
||||
else
|
||||
packet[11] = num_ch;
|
||||
|
||||
if (sub_protocol==DSM2_22)
|
||||
packet[12]=num_ch<8?0x01:0x02; // DSM2/1024 1 or 2 packets depending on the number of channels
|
||||
if(sub_protocol==DSM2_11)
|
||||
if (sub_protocol==DSM2_1F)
|
||||
packet[12]=num_ch<8?0x01:0x02; // DSM2/1024 1 or 2 packets depending on the number of channels
|
||||
else if(sub_protocol==DSM2_2F)
|
||||
packet[12]=0x12; // DSM2/2048 2 packets
|
||||
if(sub_protocol==DSMX_22)
|
||||
else if(sub_protocol==DSMX_1F)
|
||||
#if defined DSM_TELEMETRY
|
||||
packet[12] = 0xb2; // DSMX/2048 2 packets
|
||||
#else
|
||||
packet[12] = num_ch<8? 0xa2 : 0xb2; // DSMX/2048 1 or 2 packets depending on the number of channels
|
||||
#endif
|
||||
if(sub_protocol==DSMX_11 || sub_protocol==DSM_AUTO) // Force DSMX/1024 in mode Auto
|
||||
packet[12]=0xb2; // DSMX/1024 2 packets
|
||||
else // DSMX_2F && DSM_AUTO
|
||||
packet[12]=0xb2; // DSMX/2048 2 packets
|
||||
|
||||
packet[13] = 0x00; //???
|
||||
packet[13] = 0x00; //???
|
||||
for(i = 8; i < 14; i++)
|
||||
sum += packet[i];
|
||||
packet[14] = sum >> 8;
|
||||
@@ -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]);
|
||||
}
|
||||
@@ -249,25 +141,28 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
|
||||
if(prev_option!=option)
|
||||
DSM_update_channels();
|
||||
|
||||
if (sub_protocol==DSMX_11 || sub_protocol==DSMX_22 )
|
||||
{
|
||||
if (sub_protocol==DSMX_2F || sub_protocol==DSMX_1F )
|
||||
{//DSMX
|
||||
packet[0] = cyrfmfg_id[2];
|
||||
packet[1] = cyrfmfg_id[3];
|
||||
}
|
||||
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
|
||||
if(sub_protocol==DSM2_1F)
|
||||
bits=10; // Only DSM2_1F is using a resolution of 1024
|
||||
}
|
||||
|
||||
#ifdef DSM_THROTTLE_KILL_CH
|
||||
uint16_t kill_ch=Channel_data[DSM_THROTTLE_KILL_CH-1];
|
||||
#endif
|
||||
for (uint8_t i = 0; i < 7; i++)
|
||||
{
|
||||
uint8_t idx = ch_map[(upper?7:0) + i];//1,5,2,3,0,4
|
||||
uint16_t value = 0xffff;;
|
||||
uint8_t idx = ch_map[(upper?7:0) + i]; // 1,5,2,3,0,4
|
||||
uint16_t value = 0xffff;
|
||||
if((option&0x40) == 0 && num_ch < 8 && upper)
|
||||
idx=0xff; // in 22ms do not transmit upper channels if <8, is it the right method???
|
||||
if (idx != 0xff)
|
||||
{
|
||||
/* Spektrum own remotes transmit normal values during bind and actually use this (e.g. Nano CP X) to
|
||||
@@ -275,7 +170,7 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
|
||||
#ifdef DSM_THROTTLE_KILL_CH
|
||||
if(idx==CH1 && kill_ch<=604)
|
||||
{//Activate throttle kill only if channel is throttle and DSM_THROTTLE_KILL_CH below -50%
|
||||
if(kill_ch<CHANNEL_MIN_100) // restrict val to 0...400
|
||||
if(kill_ch<CHANNEL_MIN_100) // restrict val to 0...400
|
||||
kill_ch=0;
|
||||
else
|
||||
kill_ch-=CHANNEL_MIN_100;
|
||||
@@ -284,12 +179,12 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
|
||||
else
|
||||
#endif
|
||||
#ifdef DSM_MAX_THROW
|
||||
value=Channel_data[CH_TAER[idx]]; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX
|
||||
value=Channel_data[CH_TAER[idx]]; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX
|
||||
#else
|
||||
if(option & 0x80)
|
||||
value=Channel_data[CH_TAER[idx]]; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX
|
||||
value=Channel_data[CH_TAER[idx]]; // -100%..+100% => 1024..1976us and -125%..+125% => 904..2096us based on Redcon 6 channel DSM2 RX
|
||||
else
|
||||
value=convert_channel_16b_nolimit(CH_TAER[idx],0x150,0x6B0); // -100%..+100% => 1100..1900us and -125%..+125% => 1000..2000us based on Redcon 6 channel DSM2 RX
|
||||
value=convert_channel_16b_nolimit(CH_TAER[idx],0x156,0x6AA,false); // -100%..+100% => 1100..1900us and -125%..+125% => 1000..2000us based on a DX8 G2 dump
|
||||
#endif
|
||||
if(bits==10) value>>=1;
|
||||
value |= (upper && i==0 ? 0x8000 : 0) | (idx << bits);
|
||||
@@ -297,71 +192,28 @@ static void __attribute__((unused)) DSM_build_data_packet(uint8_t upper)
|
||||
packet[i*2+2] = (value >> 8) & 0xff;
|
||||
packet[i*2+3] = (value >> 0) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DSM_set_sop_data_crc()
|
||||
{
|
||||
//The crc for channel '1' is NOT(mfgid[0] << 8 + mfgid[1])
|
||||
//The crc for channel '2' is (mfgid[0] << 8 + mfgid[1])
|
||||
uint16_t crc = (cyrfmfg_id[0] << 8) + cyrfmfg_id[1];
|
||||
if(phase==DSM_CH1_CHECK_A||phase==DSM_CH1_CHECK_B)
|
||||
CYRF_ConfigCRCSeed(crc); //CH2
|
||||
else
|
||||
CYRF_ConfigCRCSeed(~crc); //CH1
|
||||
|
||||
uint8_t pn_row = DSM_get_pn_row(hopping_frequency[hopping_frequency_no]);
|
||||
uint8_t code[16];
|
||||
DSM_read_code(code,pn_row,sop_col,8); // pn_row between 0 and 4, sop_col between 1 and 7
|
||||
CYRF_ConfigSOPCode(code);
|
||||
DSM_read_code(code,pn_row,7 - sop_col,8); // 7-sop_col between 0 and 6
|
||||
DSM_read_code(code+8,pn_row,7 - sop_col + 1,8); // 7-sop_col+1 between 1 and 7
|
||||
CYRF_ConfigDataCode(code, 16);
|
||||
|
||||
CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]);
|
||||
hopping_frequency_no++;
|
||||
if(sub_protocol == DSMX_11 || sub_protocol == DSMX_22)
|
||||
hopping_frequency_no %=23;
|
||||
else
|
||||
hopping_frequency_no %=2;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DSM_calc_dsmx_channel()
|
||||
{
|
||||
uint8_t idx = 0;
|
||||
uint32_t id = ~(((uint32_t)cyrfmfg_id[0] << 24) | ((uint32_t)cyrfmfg_id[1] << 16) | ((uint32_t)cyrfmfg_id[2] << 8) | (cyrfmfg_id[3] << 0));
|
||||
uint32_t id_tmp = id;
|
||||
while(idx < 23)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t count_3_27 = 0, count_28_51 = 0, count_52_76 = 0;
|
||||
id_tmp = id_tmp * 0x0019660D + 0x3C6EF35F; // Randomization
|
||||
uint8_t next_ch = ((id_tmp >> 8) % 0x49) + 3; // Use least-significant byte and must be larger than 3
|
||||
if ( (next_ch ^ cyrfmfg_id[3]) & 0x01 )
|
||||
continue;
|
||||
for (i = 0; i < idx; i++)
|
||||
{
|
||||
if(hopping_frequency[i] == next_ch)
|
||||
break;
|
||||
if(hopping_frequency[i] <= 27)
|
||||
count_3_27++;
|
||||
else
|
||||
if (hopping_frequency[i] <= 51)
|
||||
count_28_51++;
|
||||
else
|
||||
count_52_76++;
|
||||
#ifdef DSM_FWD_PGM
|
||||
if(upper==0 && DSM_SerialRX && (DSM_SerialRX_val[0]&0xF8)==0x70 )
|
||||
{ // Send forward programming data if available
|
||||
for(uint8_t i=0; i<(DSM_SerialRX_val[0]&0x07);i++)
|
||||
{
|
||||
packet[i*2+4]=0x70+i;
|
||||
packet[i*2+5]=DSM_SerialRX_val[i+1];
|
||||
}
|
||||
DSM_SerialRX=false;
|
||||
#ifdef DSM_DEBUG_FWD_PGM
|
||||
debug("FWD=");
|
||||
for(uint8_t i=4; i<16;i++)
|
||||
debug(" %02X",packet[i]);
|
||||
debugln("");
|
||||
#endif
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
static uint8_t __attribute__((unused)) DSM_Check_RX_packet()
|
||||
{
|
||||
uint8_t result=1; // assume good packet
|
||||
uint8_t result=1; // assume good packet
|
||||
|
||||
uint16_t sum = 384 - 0x10;
|
||||
for(uint8_t i = 1; i < 9; i++)
|
||||
@@ -369,14 +221,14 @@ static uint8_t __attribute__((unused)) DSM_Check_RX_packet()
|
||||
sum += packet_in[i];
|
||||
if(i<5)
|
||||
if(packet_in[i] != (0xff ^ cyrfmfg_id[i-1]))
|
||||
result=0; // bad packet
|
||||
result=0; // bad packet
|
||||
}
|
||||
if( packet_in[9] != (sum>>8) && packet_in[10] != (uint8_t)sum )
|
||||
result=0;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t ReadDsm()
|
||||
uint16_t DSM_callback()
|
||||
{
|
||||
#define DSM_CH1_CH2_DELAY 4010 // Time between write of channel 1 and channel 2
|
||||
#ifdef STM32_BOARD
|
||||
@@ -390,46 +242,62 @@ uint16_t ReadDsm()
|
||||
uint8_t len;
|
||||
#endif
|
||||
uint8_t start;
|
||||
|
||||
#ifdef DSM_GR300
|
||||
uint16_t timing=5000+(convert_channel_8b(CH13)*100);
|
||||
debugln("T=%u",timing);
|
||||
#endif
|
||||
|
||||
switch(phase)
|
||||
{
|
||||
case DSM_BIND_WRITE:
|
||||
if(bind_counter--==0)
|
||||
#if defined DSM_TELEMETRY
|
||||
phase=DSM_BIND_CHECK; //Check RX answer
|
||||
phase=DSM_BIND_CHECK; //Check RX answer
|
||||
#else
|
||||
phase=DSM_CHANSEL; //Switch to normal mode
|
||||
phase=DSM_CHANSEL; //Switch to normal mode
|
||||
#endif
|
||||
CYRF_WriteDataPacket(packet);
|
||||
return 10000;
|
||||
#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_SetTxRxMode(RX_EN); //Receive mode
|
||||
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //Prepare to receive
|
||||
bind_counter=2*DSM_BIND_COUNT; //Timeout of 4.2s if no packet received
|
||||
phase++; // change from BIND_CHECK to BIND_READ
|
||||
CYRF_ConfigDataCode((const uint8_t *)"\x98\x88\x1B\xE4\x30\x79\x03\x84", 16);
|
||||
CYRF_SetTxRxMode(RX_EN); //Receive mode
|
||||
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x87); //Prepare to receive
|
||||
bind_counter=2*DSM_BIND_COUNT; //Timeout of 4.2s if no packet received
|
||||
phase++; // change from BIND_CHECK to BIND_READ
|
||||
return 2000;
|
||||
case DSM_BIND_READ:
|
||||
//Read data from RX
|
||||
rx_phase = CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
|
||||
if((rx_phase & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
|
||||
if((rx_phase & 0x03) == 0x02) // RXC=1, RXE=0 then 2nd check is required (debouncing)
|
||||
rx_phase |= CYRF_ReadRegister(CYRF_07_RX_IRQ_STATUS);
|
||||
if((rx_phase & 0x07) == 0x02)
|
||||
{ // data received with no errors
|
||||
CYRF_WriteRegister(CYRF_07_RX_IRQ_STATUS, 0x80); // need to set RXOW before data read
|
||||
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
|
||||
{
|
||||
packet_in[0]=0x80;
|
||||
telemetry_link=1; // send received data on serial
|
||||
phase++;
|
||||
return 2000;
|
||||
CYRF_ReadDataPacketLen(packet_in+1, 10);
|
||||
if(DSM_Check_RX_packet())
|
||||
{
|
||||
debug("Bind");
|
||||
for(uint8_t i=0;i<10;i++)
|
||||
debug(" %02X",packet_in[i+1]);
|
||||
debugln("");
|
||||
packet_in[0]=0x80;
|
||||
packet_in[6]&=0x0F; // It looks like there is a flag 0x40 being added by some receivers
|
||||
if(packet_in[6]>12) packet_in[6]=12;
|
||||
else if(packet_in[6]<3) packet_in[6]=6;
|
||||
telemetry_link=1; // Send received data on serial
|
||||
phase++;
|
||||
return 2000;
|
||||
}
|
||||
}
|
||||
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)
|
||||
@@ -441,7 +309,7 @@ uint16_t ReadDsm()
|
||||
}
|
||||
if( --bind_counter == 0 )
|
||||
{ // Exit if no answer has been received for some time
|
||||
phase++; // DSM_CHANSEL
|
||||
phase++; // DSM_CHANSEL
|
||||
return 7000 ;
|
||||
}
|
||||
return 7000;
|
||||
@@ -452,18 +320,24 @@ 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_2F||sub_protocol==DSMX_1F);
|
||||
return 10000;
|
||||
case DSM_CH1_WRITE_A:
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(11000); // Always request 11ms spacing even if we don't use half of it in 22ms mode
|
||||
#endif
|
||||
CYRF_SetPower(0x28); //Keep transmit power in sync
|
||||
case DSM_CH1_WRITE_B:
|
||||
DSM_build_data_packet(phase == DSM_CH1_WRITE_B); // build lower or upper channels
|
||||
case DSM_CH2_WRITE_A:
|
||||
case DSM_CH2_WRITE_B:
|
||||
DSM_build_data_packet(phase == DSM_CH1_WRITE_B||phase == DSM_CH2_WRITE_B); // build lower or upper channels
|
||||
CYRF_ReadRegister(CYRF_04_TX_IRQ_STATUS); // clear IRQ flags
|
||||
CYRF_WriteDataPacket(packet);
|
||||
#if 0
|
||||
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,16 +361,18 @@ 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_2F || sub_protocol==DSMX_1F);
|
||||
phase++; // change from CH1_CHECK to CH2_WRITE
|
||||
return DSM_CH1_CH2_DELAY - DSM_WRITE_DELAY;
|
||||
}
|
||||
if (phase == DSM_CH2_CHECK_A)
|
||||
CYRF_SetPower(0x28); //Keep transmit power in sync
|
||||
#if defined DSM_TELEMETRY
|
||||
phase++; // change from CH2_CHECK to CH2_READ
|
||||
CYRF_SetTxRxMode(RX_EN); //Receive mode
|
||||
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,16 +387,29 @@ uint16_t ReadDsm()
|
||||
if(len>TELEMETRY_BUFFER_SIZE-2)
|
||||
len=TELEMETRY_BUFFER_SIZE-2;
|
||||
CYRF_ReadDataPacketLen(packet_in+1, len);
|
||||
#ifdef DSM_DEBUG_FWD_PGM
|
||||
//debug(" %02X", packet_in[1]);
|
||||
if(packet_in[1]==9)
|
||||
{
|
||||
for(uint8_t i=0;i<len;i++)
|
||||
debug(" %02X", packet_in[i+1]);
|
||||
debugln("");
|
||||
}
|
||||
#endif
|
||||
packet_in[0]=CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;// store RSSI of the received telemetry signal
|
||||
telemetry_link=1;
|
||||
}
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Abort RX operation
|
||||
if (phase == DSM_CH2_READ_A && (sub_protocol==DSM2_22 || sub_protocol==DSMX_22) && num_ch < 8) // 22ms mode
|
||||
if (phase == DSM_CH2_READ_A && (sub_protocol==DSM2_1F || sub_protocol==DSMX_1F) && num_ch < 8) // 22ms mode
|
||||
{
|
||||
CYRF_SetTxRxMode(RX_EN); // Force end state read
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Clear abort RX operation
|
||||
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,30 +418,38 @@ 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_2F||sub_protocol==DSMX_1F);
|
||||
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_2F||sub_protocol==DSMX_1F);
|
||||
if (phase == DSM_CH2_CHECK_A)
|
||||
{
|
||||
if(num_ch > 7 || sub_protocol==DSM2_11 || sub_protocol==DSMX_11)
|
||||
if(num_ch > 7 || sub_protocol==DSM2_2F || sub_protocol==DSMX_2F)
|
||||
phase = DSM_CH1_WRITE_B; //11ms mode or upper to transmit change from CH2_CHECK_A to CH1_WRITE_A
|
||||
else
|
||||
{ //Normal mode 22ms
|
||||
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
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t initDsm()
|
||||
void DSM_init()
|
||||
{
|
||||
CYRF_GetMfgData(cyrfmfg_id);
|
||||
//Model match
|
||||
@@ -565,8 +462,10 @@ 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)
|
||||
if (sub_protocol == DSMX_2F || sub_protocol == DSMX_1F)
|
||||
DSM_calc_dsmx_channel();
|
||||
else
|
||||
{
|
||||
@@ -597,7 +496,6 @@ uint16_t initDsm()
|
||||
}
|
||||
else
|
||||
phase = DSM_CHANSEL;//
|
||||
return 10000;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -146,7 +146,7 @@ static void __attribute__((unused)) DEVO_build_data_pkt()
|
||||
uint8_t sign = 0x0b;
|
||||
for (uint8_t i = 0; i < 4; i++)
|
||||
{
|
||||
int16_t value=convert_channel_16b_nolimit(CH_EATR[ch_idx * 4 + i],-1600,1600);//range -1600..+1600
|
||||
int16_t value=convert_channel_16b_nolimit(CH_EATR[ch_idx * 4 + i],-1600,1600,false);//range -1600..+1600
|
||||
if(value < 0)
|
||||
{
|
||||
value = -value;
|
||||
@@ -162,6 +162,151 @@ static void __attribute__((unused)) DEVO_build_data_pkt()
|
||||
DEVO_add_pkt_suffix();
|
||||
}
|
||||
|
||||
#if defined DEVO_HUB_TELEMETRY
|
||||
static uint32_t __attribute__((unused)) DEVO_text_to_int(uint8_t *ptr, uint8_t len)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
for(uint8_t i = 0; i < len; i++)
|
||||
value = value * 10 + (ptr[i] - '0');
|
||||
return value;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DEVO_float_to_ints(uint8_t *ptr, uint16_t *value, uint16_t *decimal)
|
||||
{
|
||||
bool seen_decimal = false;
|
||||
*value = 0;
|
||||
*decimal = 0;
|
||||
for(uint8_t i = 0; i < 7; i++)
|
||||
{
|
||||
if(ptr[i] == '.')
|
||||
{
|
||||
seen_decimal = true;
|
||||
continue;
|
||||
}
|
||||
if(ptr[i] < '0' || ptr[i] > '9')
|
||||
{
|
||||
if(*value != 0 || seen_decimal)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(seen_decimal)
|
||||
*decimal = *decimal * 10 + (ptr[i] - '0');
|
||||
else
|
||||
*value = *value * 10 + (ptr[i] - '0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) DEVO_parse_telemetry_packet()
|
||||
{ // Telemetry packets every 2.4ms
|
||||
DEVO_scramble_pkt(); //This will unscramble the packet
|
||||
|
||||
debugln("RX");
|
||||
if ((((uint32_t)packet[15] << 16) | ((uint32_t)packet[14] << 8) | packet[13]) != (MProtocol_id & 0x00ffffff))
|
||||
return; // ID does not match
|
||||
|
||||
if((telemetry_link & 3) != 0)
|
||||
{
|
||||
debugln("S%d",telemetry_link);
|
||||
return; // Previous telemetry not sent yet...
|
||||
}
|
||||
|
||||
//Debug telem RX
|
||||
//for(uint8_t i=0;i<12;i++)
|
||||
// debug("%02X ",packet[i]);
|
||||
//debugln("");
|
||||
|
||||
#if defined HUB_TELEMETRY
|
||||
//Telemetry https://github.com/DeviationTX/deviation/blob/5efb6a28bea697af9a61b5a0ed2528cc8d203f90/src/protocol/devo_cyrf6936.c#L232
|
||||
uint16_t val, dec;
|
||||
switch(packet[0])
|
||||
{
|
||||
case 0x30: // Volt and RPM packet
|
||||
//RSSI and voltage
|
||||
TX_RSSI = CYRF_ReadRegister(CYRF_13_RSSI) & 0x1F;
|
||||
TX_RSSI = (TX_RSSI << 1) + TX_RSSI;
|
||||
RX_RSSI = TX_RSSI;
|
||||
telemetry_link |= 1;
|
||||
v_lipo1 = packet[1] << 1;
|
||||
v_lipo2 = packet[3] << 1;
|
||||
//packet[5] = 127; // 12.7V
|
||||
if(packet[5] != 0)
|
||||
{
|
||||
val = (packet[5]*11)/21; // OpenTX strange transformation??
|
||||
dec = val;
|
||||
val /= 10;
|
||||
dec -= val*10;
|
||||
frsky_send_user_frame(0x3A, val, 0x00); // volt3
|
||||
frsky_send_user_frame(0x3B, dec, 0x00); // volt3
|
||||
}
|
||||
val = packet[7] * 120; // change to RPM
|
||||
frsky_send_user_frame(0x03, val, val>>8); // RPM
|
||||
break;
|
||||
case 0x31: // Temperature packet
|
||||
//memcpy(&packet[1],"\x29\x2A\x2B\x00\x00\x00\x00\x00\x00\x00\x00\x00",12); // 21°, 22°, 23°
|
||||
for(uint8_t i=0; i<2;i++)
|
||||
if(packet[i+1]!=0xff)
|
||||
{
|
||||
val = packet[i+1];
|
||||
val -= 20;
|
||||
frsky_send_user_frame(0x02 + i*3, val, val>>8); // temp 1 & 2
|
||||
}
|
||||
break;
|
||||
// GPS Data
|
||||
case 0x32: // Longitude
|
||||
//memcpy(&packet[1],"\x30\x33\x30\x32\x30\x2e\x38\x32\x37\x30\x45\xfb",12); // 030°20.8270E
|
||||
val = DEVO_text_to_int(&packet[1], 3)*100 + DEVO_text_to_int(&packet[4], 2); // dddmm
|
||||
frsky_send_user_frame(0x12 , val, val>>8);
|
||||
val = DEVO_text_to_int(&packet[7], 4); // .mmmm
|
||||
frsky_send_user_frame(0x12+8, val, val>>8);
|
||||
frsky_send_user_frame(0x1A+8, packet[11], 0x00); // 'E'/'W'
|
||||
break;
|
||||
case 0x33: // Latitude
|
||||
//memcpy(&packet[1],"\x35\x39\x35\x34\x2e\x37\x37\x37\x36\x4e\x07\x00",12); // 59°54.776N
|
||||
val = DEVO_text_to_int(&packet[1], 2)*100 + DEVO_text_to_int(&packet[3], 2); // ddmm
|
||||
frsky_send_user_frame(0x13 , val, val>>8);
|
||||
val = DEVO_text_to_int(&packet[6], 4); // .mmmm
|
||||
frsky_send_user_frame(0x13+8, val, val>>8);
|
||||
frsky_send_user_frame(0x1B+8, packet[10], 0x00); // 'N'/'S'
|
||||
break;
|
||||
case 0x34: // Altitude
|
||||
//memcpy(&packet[1],"\x31\x32\x2e\x38\x00\x00\x00\x4d\x4d\x4e\x45\xfb",12); // 12.8 MMNE
|
||||
DEVO_float_to_ints(&packet[1], &val, &dec);
|
||||
frsky_send_user_frame(0x10, val, val>>8);
|
||||
frsky_send_user_frame(0x21, dec, dec>>8);
|
||||
break;
|
||||
case 0x35: // Speed
|
||||
//memcpy(&packet[1],"\x00\x00\x00\x00\x00\x00\x30\x2e\x30\x30\x00\x00",12); // 0.0
|
||||
DEVO_float_to_ints(&packet[1], &val, &dec);
|
||||
frsky_send_user_frame(0x11 , val, val>>8);
|
||||
frsky_send_user_frame(0x11+8, dec, dec>>8);
|
||||
break;
|
||||
case 0x36: // Time
|
||||
//memcpy(&packet[1],"\x31\x38\x32\x35\x35\x32\x31\x35\x31\x30\x31\x32",12); // 2012-10-15 18:25:52 (UTC)
|
||||
if(packet[1]!=0)
|
||||
{
|
||||
frsky_send_user_frame(0x15, DEVO_text_to_int(&packet[9], 2), DEVO_text_to_int(&packet[7], 2)); // month, day
|
||||
frsky_send_user_frame(0x16, DEVO_text_to_int(&packet[11], 2)+24, 0x00); // year
|
||||
frsky_send_user_frame(0x17, DEVO_text_to_int(&packet[1], 2), DEVO_text_to_int(&packet[3], 2)); // hour, min
|
||||
frsky_send_user_frame(0x18, DEVO_text_to_int(&packet[5], 2), 0x00); // second
|
||||
}
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if(packet[0] == 0x30)
|
||||
{
|
||||
TX_RSSI = CYRF_ReadRegister(CYRF_13_RSSI) & 0x1F;
|
||||
TX_RSSI = (TX_RSSI << 1) + TX_RSSI;
|
||||
RX_RSSI = TX_RSSI;
|
||||
telemetry_link |= 1;
|
||||
v_lipo1 = packet[1] << 1;
|
||||
v_lipo2 = packet[3] << 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void __attribute__((unused)) DEVO_cyrf_set_bound_sop_code()
|
||||
{
|
||||
/* crc == 0 isn't allowed, so use 1 if the math results in 0 */
|
||||
@@ -267,9 +412,85 @@ static void __attribute__((unused)) DEVO_BuildPacket()
|
||||
packet_count = 0;
|
||||
}
|
||||
|
||||
uint16_t devo_callback()
|
||||
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,10 +519,26 @@ uint16_t devo_callback()
|
||||
CYRF_ConfigRFChannel(*hopping_frequency_ptr);
|
||||
}
|
||||
return 1200;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint16_t DevoInit()
|
||||
void DEVO_init()
|
||||
{
|
||||
#ifdef ENABLE_PPM
|
||||
if(mode_select) //PPM mode
|
||||
{
|
||||
if(IS_BIND_BUTTON_FLAG_on)
|
||||
{
|
||||
eeprom_write_byte((EE_ADDR)(MODELMODE_EEPROM_OFFSET+RX_num),0x00); // reset to autobind mode for the current model
|
||||
option=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
option=eeprom_read_byte((EE_ADDR)(MODELMODE_EEPROM_OFFSET+RX_num)); // load previous mode: autobind or fixed id
|
||||
if(option!=1) option=0; // if not fixed id mode then it should be autobind
|
||||
}
|
||||
}
|
||||
#endif //ENABLE_PPM
|
||||
switch(sub_protocol)
|
||||
{
|
||||
case 1:
|
||||
@@ -349,7 +586,6 @@ uint16_t DevoInit()
|
||||
bind_counter = 0;
|
||||
DEVO_cyrf_set_bound_sop_code();
|
||||
}
|
||||
return 2400;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
151
Multiprotocol/E010R5_cyrf6936.ino
Normal file
151
Multiprotocol/E010R5_cyrf6936.ino
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(E010R5_CYRF6936_INO)
|
||||
|
||||
#include "iface_rf2500.h"
|
||||
|
||||
#define E010R5_FORCE_ID
|
||||
|
||||
#define E010R5_PAYLOAD_SIZE 14
|
||||
|
||||
|
||||
static void __attribute__((unused)) E010R5_build_data_packet()
|
||||
{
|
||||
packet[ 0] = 0x0D; // Packet length
|
||||
packet[ 1] = convert_channel_8b(THROTTLE);
|
||||
packet[ 2] = convert_channel_s8b(RUDDER);
|
||||
packet[ 3] = convert_channel_s8b(ELEVATOR);
|
||||
packet[ 4] = convert_channel_s8b(AILERON);
|
||||
packet[ 5] = 0x20; // Trim Rudder
|
||||
packet[ 6] = 0x20; // Trim Elevator
|
||||
packet[ 7] = 0x20; // Trim Aileron
|
||||
packet[ 8] = 0x01 // Flags: high=0x01, low=0x00
|
||||
| GET_FLAG(CH5_SW, 0x04) // flip=0x04
|
||||
| GET_FLAG(CH6_SW, 0x08) // led=0x08
|
||||
| GET_FLAG(CH8_SW, 0x10) // headless=0x10
|
||||
| GET_FLAG(CH9_SW, 0x20); // one key return=0x20
|
||||
packet[ 9] = IS_BIND_IN_PROGRESS ? 0x80 : 0x00 // Flags: bind=0x80
|
||||
| GET_FLAG(CH7_SW, 0x20) // calib=0x20
|
||||
| GET_FLAG(CH10_SW, 0x01); // strange effect=0x01=long press on right button
|
||||
packet[10] = rx_tx_addr[0];
|
||||
packet[11] = rx_tx_addr[1];
|
||||
packet[12] = rx_tx_addr[2];
|
||||
packet[13] = 0x9D; // Check
|
||||
for(uint8_t i=0;i<13;i++)
|
||||
packet[13] += packet[i];
|
||||
|
||||
RF2500_BuildPayload(packet);
|
||||
}
|
||||
|
||||
uint16_t E010R5_callback()
|
||||
{
|
||||
//Bind
|
||||
if(bind_counter)
|
||||
if(--bind_counter==0)
|
||||
BIND_DONE;
|
||||
|
||||
//Send packet
|
||||
RF2500_SendPayload();
|
||||
|
||||
//Timing and hopping
|
||||
packet_count++;
|
||||
switch(packet_count)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 5:
|
||||
return 1183;
|
||||
default:
|
||||
hopping_frequency_no++;
|
||||
hopping_frequency_no &= 3;
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
rf_ch_num = 0x30 + (hopping_frequency_no<<3);
|
||||
else
|
||||
rf_ch_num = hopping_frequency[hopping_frequency_no];
|
||||
RF2500_RFChannel(rf_ch_num);
|
||||
RF2500_SetPower();
|
||||
packet_count = 0;
|
||||
case 3:
|
||||
E010R5_build_data_packet();
|
||||
return 3400;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void E010R5_init()
|
||||
{
|
||||
BIND_IN_PROGRESS; // Autobind protocol
|
||||
bind_counter = 2600;
|
||||
|
||||
//RF2500 emu init
|
||||
RF2500_Init(E010R5_PAYLOAD_SIZE, false); // 14 bytes, not scrambled
|
||||
RF2500_SetTXAddr((uint8_t*)"\x0E\x54\x96\xEE"); // Same address for bind and normal packets
|
||||
|
||||
rx_tx_addr[0]=0x00;
|
||||
hopping_frequency[0]=0x35; //53
|
||||
#ifdef E010R5_FORCE_ID
|
||||
switch(rx_tx_addr[3]%5)
|
||||
{
|
||||
case 0:
|
||||
//TX1
|
||||
//hopping_frequency[0]=0x35; //53
|
||||
hopping_frequency[1]=0x30; //48
|
||||
rx_tx_addr[1]=0x45;
|
||||
rx_tx_addr[2]=0x46;
|
||||
break;
|
||||
case 1:
|
||||
//TX2
|
||||
//hopping_frequency[0]=0x35; //53
|
||||
hopping_frequency[1]=0x3C; //60
|
||||
rx_tx_addr[1]=0x1B;
|
||||
rx_tx_addr[2]=0x9E;
|
||||
break;
|
||||
case 2:
|
||||
//TX4
|
||||
hopping_frequency[0]=0x30; //48
|
||||
hopping_frequency[1]=0x38; //56
|
||||
rx_tx_addr[1]=0x2E;
|
||||
rx_tx_addr[2]=0xAE;
|
||||
break;
|
||||
case 3:
|
||||
//TX5
|
||||
//hopping_frequency[0]=0x35; //53
|
||||
hopping_frequency[1]=0x41; //65
|
||||
rx_tx_addr[0]=0x0D;
|
||||
rx_tx_addr[1]=0xB9;
|
||||
rx_tx_addr[2]=0xFC;
|
||||
break;
|
||||
default:
|
||||
//TX3
|
||||
hopping_frequency[0]=0x30; //48
|
||||
hopping_frequency[1]=0x38; //56
|
||||
rx_tx_addr[1]=0x17;
|
||||
rx_tx_addr[2]=0x0D;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
// This is the same as the E010 v1...
|
||||
hopping_frequency[2]=hopping_frequency[0]+0x10;
|
||||
hopping_frequency[3]=hopping_frequency[1]+0x10;
|
||||
|
||||
E010R5_build_data_packet();
|
||||
RF2500_RFChannel(hopping_frequency[0]);
|
||||
hopping_frequency_no=0;
|
||||
packet_count=0;
|
||||
}
|
||||
|
||||
#endif
|
||||
157
Multiprotocol/E016HV2_cc2500.ino
Normal file
157
Multiprotocol/E016HV2_cc2500.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/>.
|
||||
*/
|
||||
|
||||
#if defined(E016HV2_CC2500_INO)
|
||||
|
||||
#include "iface_cc2500.h"
|
||||
|
||||
//#define FORCE_E016HV2_ORIGINAL_ID
|
||||
|
||||
#define E016HV2_INITIAL_WAIT 500
|
||||
#define E016HV2_PACKET_PERIOD 10000
|
||||
#define E016HV2_RF_BIND_CHANNEL 5
|
||||
#define E016HV2_PAYLOAD_SIZE 11
|
||||
#define E016HV2_BIND_COUNT 300 //3sec
|
||||
|
||||
static void __attribute__((unused)) E016HV2_send_packet()
|
||||
{
|
||||
//payload length (after this byte)
|
||||
packet[0 ] = 0x0A;
|
||||
|
||||
//bind indicator
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet[1 ] = 0x02;
|
||||
if(bind_counter)
|
||||
bind_counter--;
|
||||
else
|
||||
{
|
||||
BIND_DONE;
|
||||
CC2500_250K_RFChannel(rf_ch_num); // Set main channel
|
||||
}
|
||||
}
|
||||
else
|
||||
packet[1 ] = 0x20;
|
||||
|
||||
//ID
|
||||
packet[2 ] = rx_tx_addr[2];
|
||||
packet[3 ] = rx_tx_addr[3];
|
||||
|
||||
//channels TREA
|
||||
uint8_t channel;
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
channel=0x64; // Throttle must be centered during bind
|
||||
else
|
||||
channel=convert_channel_8b_limit_deadband(THROTTLE,0x00,0x64,0xC8, 20);
|
||||
packet[4 ] = channel;
|
||||
channel=convert_channel_16b_limit(RUDDER,0x00,0xC8);
|
||||
packet[5 ] = channel;
|
||||
channel=convert_channel_16b_limit(ELEVATOR,0x00,0xC8);
|
||||
packet[6 ] = channel;
|
||||
channel=convert_channel_16b_limit(AILERON,0x00,0xC8);
|
||||
packet[7 ] = channel;
|
||||
|
||||
//flags
|
||||
if(CH8_SW && !phase) //toggle calib flag
|
||||
flags ^= 0x40;
|
||||
phase=CH8_SW;
|
||||
|
||||
packet[8 ] = GET_FLAG(CH7_SW, 0x01) // 0x01=Flip
|
||||
| GET_FLAG(CH9_SW, 0x02) // 0x02=Headless
|
||||
| GET_FLAG(CH10_SW, 0x04) // 0x04=One Key Return
|
||||
| flags; // 0x40=Calib
|
||||
|
||||
packet[9 ] = 0x02; // Speed control 0x00:low, 0x01:medium, 0x02:high
|
||||
|
||||
packet[10] = GET_FLAG(CH5_SW, 0x01) // 0x01=TakeOff/Land (momentary switch)
|
||||
| GET_FLAG(CH6_SW, 0x04); // 0x04=Emergeny Stop (momentary switch)
|
||||
|
||||
CC2500_SetPower(); // Set tx_power
|
||||
CC2500_SetFreqOffset(); // Set frequency offset
|
||||
|
||||
//Build real packet and send it
|
||||
static uint8_t pid=0;
|
||||
crc=0;
|
||||
|
||||
// stop TX/RX
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
// flush tx FIFO
|
||||
CC2500_Strobe(CC2500_SFTX);
|
||||
// packet length
|
||||
CC2500_WriteReg(CC2500_3F_TXFIFO, 6 + 4 + 1 + 11 + 2); // preamble + address + packet_control + payload + crc
|
||||
|
||||
// preamble+address
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, (uint8_t*)"\xAA\xAA\xAA\xAA\xAA\xAA\xE7\xE7\xE7\xE7", 10);
|
||||
|
||||
// packet control
|
||||
CC2500_WriteReg(CC2500_3F_TXFIFO, 0x50+(pid<<2));
|
||||
pid++;
|
||||
|
||||
// payload
|
||||
//debug("P:")
|
||||
for (uint8_t i = 0; i < E016HV2_PAYLOAD_SIZE; ++i)
|
||||
{
|
||||
uint8_t byte = (bit_reverse(packet[i])<<1) | (packet[i+1]&0x01);
|
||||
//debug(" %02X",byte)
|
||||
CC2500_WriteReg(CC2500_3F_TXFIFO,byte);
|
||||
crc16_update(byte, 8);
|
||||
}
|
||||
|
||||
// crc
|
||||
CC2500_WriteReg(CC2500_3F_TXFIFO,crc >> 8);
|
||||
CC2500_WriteReg(CC2500_3F_TXFIFO,crc);
|
||||
//debugln(" %04X",crc)
|
||||
|
||||
// transmit
|
||||
CC2500_Strobe(CC2500_STX);
|
||||
}
|
||||
|
||||
uint16_t E016HV2_callback()
|
||||
{
|
||||
E016HV2_send_packet();
|
||||
return E016HV2_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
void E016HV2_init()
|
||||
{
|
||||
//Config CC2500
|
||||
CC2500_250K_Init();
|
||||
CC2500_250K_RFChannel(E016HV2_RF_BIND_CHANNEL); // Set bind channel
|
||||
|
||||
#ifdef FORCE_E016HV2_ORIGINAL_ID
|
||||
rx_tx_addr[2]=0x27;
|
||||
rx_tx_addr[3]=0x1B;
|
||||
//rf_ch_num = 44;
|
||||
#endif
|
||||
//General ID
|
||||
//3F1B -> 68,2C1B -> 49,2B1B -> 48,2A1B -> 47,291B -> 46,281B -> 45,271B -> 44,261B -> 43,251B -> 42
|
||||
//241B -> no bind,231B -> no bind,221B -> 71,211B -> 70,201B -> 69,1F1B -> 68,1E1B -> 67,1D1B -> 66,1C1B -> 65,1B1B -> 64,1A1B -> 63,191B -> 62,181B -> 61,171B -> 60,161B -> 59
|
||||
//0C1B -> 49,051B -> 42,041B -> no bind,031B -> no bind,021B -> 71,011B -> 70,001B -> no bind
|
||||
if(rx_tx_addr[2]<3) rx_tx_addr[2]+=3; // rx_tx_addr[2]=0 is invalid
|
||||
if(rx_tx_addr[3]==0) rx_tx_addr[3]+=64; // rx_tx_addr[3]=0 is invalid
|
||||
rf_ch_num = (rx_tx_addr[2] + rx_tx_addr[3]) % 32 + 42;
|
||||
if(rf_ch_num>71) // channels 72 and 73 are invalid
|
||||
{
|
||||
rx_tx_addr[2]-=2;
|
||||
rf_ch_num-=2;
|
||||
}
|
||||
|
||||
phase=CH8_SW;
|
||||
flags=0;
|
||||
bind_counter = E016HV2_BIND_COUNT;
|
||||
BIND_IN_PROGRESS; // Autobind protocol
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -95,14 +95,14 @@ static void __attribute__((unused)) E015_check_arming()
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) E01X_send_packet(uint8_t bind)
|
||||
static void __attribute__((unused)) E01X_send_packet()
|
||||
{
|
||||
uint8_t can_flip = 0, calibrate = 1;
|
||||
if(sub_protocol==E012)
|
||||
{
|
||||
packet_length=E012_PACKET_SIZE;
|
||||
packet[0] = rx_tx_addr[1];
|
||||
if(bind)
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet[1] = 0xaa;
|
||||
memcpy(&packet[2], hopping_frequency, E012_NUM_RF_CHANNELS);
|
||||
@@ -134,7 +134,7 @@ static void __attribute__((unused)) E01X_send_packet(uint8_t bind)
|
||||
}
|
||||
else if(sub_protocol==E015)
|
||||
{ // E015
|
||||
if(bind)
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet[0] = 0x18;
|
||||
packet[1] = 0x04;
|
||||
@@ -173,7 +173,7 @@ static void __attribute__((unused)) E01X_send_packet(uint8_t bind)
|
||||
else
|
||||
{ // E016H
|
||||
packet_length=E016H_PACKET_SIZE;
|
||||
if(bind)
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
rf_ch_num=E016H_BIND_CHANNEL;
|
||||
memcpy(packet, &rx_tx_addr[1], 4);
|
||||
@@ -244,34 +244,26 @@ static void __attribute__((unused)) E01X_send_packet(uint8_t bind)
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) E01X_init()
|
||||
static void __attribute__((unused)) E01X_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
if(sub_protocol==E012)
|
||||
HS6200_SetTXAddr((uint8_t *)"\x55\x42\x9C\x8F\xC9", E01X_ADDRESS_LENGTH);
|
||||
else if(sub_protocol==E015)
|
||||
HS6200_SetTXAddr((uint8_t *)"\x62\x54\x79\x38\x53", E01X_ADDRESS_LENGTH);
|
||||
else //E016H
|
||||
XN297_SetTXAddr((uint8_t *)"\x5a\x53\x46\x30\x31", 5); // bind address
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1 Mbps
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01); // Set feature bits on
|
||||
NRF24L01_Activate(0x73);
|
||||
}
|
||||
|
||||
uint16_t E01X_callback()
|
||||
{
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
if(bind_counter)
|
||||
{
|
||||
bind_counter--;
|
||||
if (bind_counter == 0)
|
||||
{
|
||||
if(sub_protocol==E016H)
|
||||
@@ -280,19 +272,8 @@ uint16_t E01X_callback()
|
||||
HS6200_SetTXAddr(rx_tx_addr, E01X_ADDRESS_LENGTH);
|
||||
BIND_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
E01X_send_packet(1);
|
||||
bind_counter--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
E01X_send_packet(0);
|
||||
}
|
||||
E01X_send_packet();
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
@@ -322,7 +303,7 @@ static void __attribute__((unused)) E016H_initialize_txid()
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t initE01X()
|
||||
void E01X_init()
|
||||
{
|
||||
BIND_IN_PROGRESS;
|
||||
if(sub_protocol==E012)
|
||||
@@ -343,10 +324,9 @@ uint16_t initE01X()
|
||||
E016H_initialize_txid();
|
||||
packet_period=E016H_PACKET_PERIOD;
|
||||
}
|
||||
E01X_init();
|
||||
E01X_RF_init();
|
||||
bind_counter = E01X_BIND_COUNT;
|
||||
hopping_frequency_no = 0;
|
||||
return E01X_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
148
Multiprotocol/E129_cyrf6936.ino
Normal file
148
Multiprotocol/E129_cyrf6936.ino
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(E129_CYRF6936_INO)
|
||||
|
||||
#include "iface_rf2500.h"
|
||||
|
||||
//#define E129_FORCE_ID
|
||||
|
||||
#define E129_BIND_CH 0x2D //45
|
||||
#define E129_PAYLOAD_SIZE 16
|
||||
|
||||
static void __attribute__((unused)) E129_build_data_packet()
|
||||
{
|
||||
//Build the packet
|
||||
memset(packet,0,E129_PAYLOAD_SIZE);
|
||||
packet[ 0] = 0x0F; // Packet length
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet[ 1] = 0xA4;
|
||||
packet[ 2] = bit_reverse(rx_tx_addr[2]);
|
||||
packet[ 3] = bit_reverse(rx_tx_addr[3]);
|
||||
packet[ 4] = bit_reverse(rx_tx_addr[0]);
|
||||
packet[ 5] = bit_reverse(rx_tx_addr[1]);
|
||||
for(uint8_t i=0; i<4; i++)
|
||||
packet[6+i]=hopping_frequency[i]-2;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[ 1] = 0xA6;
|
||||
packet[ 2] = 0xF7; // High rate 0xF7, low rate 0xF4
|
||||
//packet[ 3] = 0x00; // Mode: short press=0x20->0x00->0x20->..., long press=0x10->0x30->0x10->...
|
||||
packet[ 4] = GET_FLAG(CH5_SW, 0x20) // Take off/Land 0x20
|
||||
| GET_FLAG(CH6_SW, 0x04); // Emergency stop 0x04
|
||||
|
||||
uint16_t val = convert_channel_10b(AILERON,false);
|
||||
uint8_t trim = convert_channel_8b(CH7) & 0xFC;
|
||||
packet[ 5] = trim | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8
|
||||
packet[ 6] = val; // channel (0x000...0x200...0x3FF)
|
||||
val = convert_channel_10b(ELEVATOR,false);
|
||||
trim = convert_channel_8b(CH8) & 0xFC;
|
||||
packet[ 7] = trim | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8
|
||||
packet[ 8] = val; // channel (0x000...0x200...0x3FF)
|
||||
if(packet_count>200)
|
||||
val = convert_channel_10b(THROTTLE,false);
|
||||
else
|
||||
{//Allow bind to complete with throttle not centered
|
||||
packet_count++;
|
||||
val=0x200;
|
||||
}
|
||||
packet[ 9] = (0x1F<<2) | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8
|
||||
packet[10] = val; // channel (0x000...0x200...0x3FF)
|
||||
val = convert_channel_10b(RUDDER,false);
|
||||
trim = convert_channel_8b(CH9) & 0xFC;
|
||||
packet[11] = trim | (val >>8); // Trim (0x00..0x1F..0x3E) << 2 | channel >> 8
|
||||
packet[12] = val; // channel (0x000...0x200...0x3FF)
|
||||
}
|
||||
packet[14] = 0x00; // Check
|
||||
for(uint8_t i=0;i<14;i++)
|
||||
packet[14] += packet[i];
|
||||
|
||||
RF2500_BuildPayload(packet);
|
||||
}
|
||||
|
||||
uint16_t E129_callback()
|
||||
{
|
||||
//Set RF channel
|
||||
if(phase==0)
|
||||
RF2500_RFChannel(IS_BIND_IN_PROGRESS ? E129_BIND_CH : hopping_frequency[hopping_frequency_no]);
|
||||
|
||||
//Send packet
|
||||
RF2500_SendPayload();
|
||||
|
||||
//Send twice on same channel
|
||||
if(phase==0)
|
||||
{
|
||||
phase++;
|
||||
return 1260;
|
||||
}
|
||||
|
||||
//Bind
|
||||
if(bind_counter)
|
||||
if(--bind_counter==0)
|
||||
{
|
||||
BIND_DONE;
|
||||
RF2500_SetTXAddr(rx_tx_addr); // 4 bytes of address
|
||||
}
|
||||
|
||||
//Build packet
|
||||
E129_build_data_packet();
|
||||
|
||||
//Set power
|
||||
RF2500_SetPower();
|
||||
|
||||
//Hopp
|
||||
hopping_frequency_no++;
|
||||
hopping_frequency_no &= 3;
|
||||
|
||||
phase=0;
|
||||
return 5200-1260;
|
||||
}
|
||||
|
||||
void E129_init()
|
||||
{
|
||||
BIND_IN_PROGRESS; // Autobind protocol
|
||||
bind_counter = 384; // ~2sec
|
||||
|
||||
//RF2500 emu init
|
||||
RF2500_Init(E129_PAYLOAD_SIZE, true); // 16 bytes, Scrambled
|
||||
|
||||
//Freq hopping
|
||||
calc_fh_channels(4);
|
||||
for(uint8_t i=0; i<4; i++)
|
||||
if(hopping_frequency[i]==E129_BIND_CH)
|
||||
hopping_frequency[i]++;
|
||||
|
||||
#ifdef E129_FORCE_ID
|
||||
rx_tx_addr[0]=0xC1;
|
||||
rx_tx_addr[1]=0x22;
|
||||
rx_tx_addr[2]=0x05;
|
||||
rx_tx_addr[3]=0xA3;
|
||||
hopping_frequency[0]=0x3C; //60
|
||||
hopping_frequency[1]=0x49; //73
|
||||
hopping_frequency[2]=0x4B; //75
|
||||
hopping_frequency[3]=0x41; //65
|
||||
#endif
|
||||
|
||||
RF2500_SetTXAddr((uint8_t*)"\xE2\x32\xE0\xC8"); // 4 bytes of bind address
|
||||
|
||||
E129_build_data_packet();
|
||||
hopping_frequency_no=0;
|
||||
packet_count=0;
|
||||
phase=0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -23,7 +23,7 @@
|
||||
#define ESKY150_BINDING_PACKET_PERIOD 2000
|
||||
#define ESKY150_SENDING_PACKET_PERIOD 4800
|
||||
|
||||
static void __attribute__((unused)) ESKY150_init()
|
||||
static void __attribute__((unused)) ESKY150_RF_init()
|
||||
{
|
||||
//Original TX always sets for channelx 0x22 and 0x4a
|
||||
// Use channels 2..79
|
||||
@@ -31,25 +31,16 @@ static void __attribute__((unused)) ESKY150_init()
|
||||
hopping_frequency[1] = hopping_frequency[0] + 40;
|
||||
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO)));
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x02); // 4-byte RX/TX address
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0); // Disable retransmit
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_2M);
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, ESKY150_PAYLOADSIZE); // bytes of data payload for pipe 0
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, ESKY150_TX_ADDRESS_SIZE);
|
||||
|
||||
NRF24L01_Activate(0x73);
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 1); // Dynamic payload for data pipe 0
|
||||
// Enable: Dynamic Payload Length, Payload with ACK , W_TX_PAYLOAD_NOACK
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, _BV(NRF2401_1D_EN_DPL) | _BV(NRF2401_1D_EN_ACK_PAY) | _BV(NRF2401_1D_EN_DYN_ACK));
|
||||
NRF24L01_Activate(0x73);
|
||||
NRF24L01_FlushTx();
|
||||
// Turn radio power on
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
NRF24L01_SetTxRxMode(TX_EN); // Clear data ready, data sent, retransmit and enable CRC 16bits, ready for TX
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) ESKY150_bind_init()
|
||||
@@ -171,16 +162,15 @@ uint16_t ESKY150_callback()
|
||||
return ESKY150_SENDING_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initESKY150(void)
|
||||
void ESKY150_init(void)
|
||||
{
|
||||
ESKY150_init();
|
||||
ESKY150_RF_init();
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
bind_counter=3000;
|
||||
ESKY150_bind_init();
|
||||
}
|
||||
hopping_frequency_no=0;
|
||||
return 10000;
|
||||
}
|
||||
|
||||
#endif
|
||||
138
Multiprotocol/ESky150v2_cc2500.ino
Normal file
138
Multiprotocol/ESky150v2_cc2500.ino
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
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_cc2500.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
|
||||
CC2500_SetFreqOffset(); // Set frequency offset
|
||||
CC2500_250K_HoppingCalib(ESKY150V2_NFREQCHANNELS+1);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) ESKY150V2_send_packet()
|
||||
{
|
||||
CC2500_SetFreqOffset(); // Set frequency offset
|
||||
CC2500_250K_Hopping(hopping_frequency_no);
|
||||
if (++hopping_frequency_no >= ESKY150V2_NFREQCHANNELS)
|
||||
hopping_frequency_no = 0;
|
||||
CC2500_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;
|
||||
}
|
||||
CC2500_250K_NRF_WritePayload(packet, ESKY150V2_PAYLOADSIZE);
|
||||
}
|
||||
|
||||
uint16_t ESKY150V2_callback()
|
||||
{
|
||||
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...
|
||||
CC2500_SetPower(); //Set power level
|
||||
BIND_IN_PROGRESS;
|
||||
CC2500_250K_NRF_WritePayload(packet, ESKY150V2_BINDPAYLOADSIZE);
|
||||
if (--bind_counter == 0)
|
||||
{
|
||||
BIND_DONE;
|
||||
// Change TX address from bind to normal mode
|
||||
CC2500_250K_NRF_SetTXAddr(rx_tx_addr, ESKY150V2_TXID_SIZE);
|
||||
memset(packet,0x00,ESKY150V2_PAYLOADSIZE);
|
||||
}
|
||||
return 30000; //ESKY150V2_BINDING_PACKET_PERIOD;
|
||||
}
|
||||
return ESKY150V2_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
void ESKY150V2_init()
|
||||
{
|
||||
CC2500_250K_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)
|
||||
{
|
||||
CC2500_250K_NRF_SetTXAddr((uint8_t *)"\x73\x73\x74\x63", ESKY150V2_TXID_SIZE); //Bind address
|
||||
CC2500_250K_Hopping(ESKY150V2_NFREQCHANNELS); //Bind channel
|
||||
memcpy(packet,"\x73\x73\x74\x63", ESKY150V2_TXID_SIZE);
|
||||
memcpy(&packet[ESKY150V2_TXID_SIZE],rx_tx_addr, ESKY150V2_TXID_SIZE);
|
||||
packet[8]=0x41; //Unknown
|
||||
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
|
||||
CC2500_250K_NRF_SetTXAddr(rx_tx_addr, ESKY150V2_TXID_SIZE);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -35,14 +35,10 @@ static void __attribute__((unused)) ESKY_set_data_address()
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 4);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) ESKY_init()
|
||||
static void __attribute__((unused)) ESKY_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
|
||||
// 2-bytes CRC, radio off
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // 3-byte RX/TX address for bind packets
|
||||
@@ -51,11 +47,7 @@ static void __attribute__((unused)) ESKY_init()
|
||||
}
|
||||
else
|
||||
ESKY_set_data_address();
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0); // No auto retransmission
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 50); // Channel 50 for bind packets
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, ESKY_PAYLOAD_SIZE); // bytes of data payload for pipe 0
|
||||
NRF24L01_WriteReg(NRF24L01_12_RX_PW_P1, ESKY_PAYLOAD_SIZE);
|
||||
NRF24L01_WriteReg(NRF24L01_13_RX_PW_P2, ESKY_PAYLOAD_SIZE);
|
||||
@@ -65,7 +57,7 @@ static void __attribute__((unused)) ESKY_init()
|
||||
NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) ESKY_init2()
|
||||
static void __attribute__((unused)) ESKY_TXID_init()
|
||||
{
|
||||
NRF24L01_FlushTx();
|
||||
if(sub_protocol==ESKY_STD)
|
||||
@@ -187,7 +179,7 @@ uint16_t ESKY_callback()
|
||||
return ESKY_STD_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initESKY(void)
|
||||
void ESKY_init(void)
|
||||
{
|
||||
bind_counter = ESKY_BIND_COUNT;
|
||||
rx_tx_addr[2] = rx_tx_addr[3]; // Model match
|
||||
@@ -200,10 +192,9 @@ uint16_t initESKY(void)
|
||||
}
|
||||
#endif
|
||||
rx_tx_addr[3] = 0xBB;
|
||||
ESKY_init();
|
||||
ESKY_init2();
|
||||
ESKY_RF_init();
|
||||
ESKY_TXID_init();
|
||||
packet_count=0;
|
||||
return 50000;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -52,24 +52,18 @@ static void __attribute__((unused)) ssv_pack_dpl(uint8_t addr[], uint8_t pid, ui
|
||||
header[0] = (addr[4] >> 7);
|
||||
|
||||
// calculate the crc
|
||||
union
|
||||
{
|
||||
uint8_t bytes[2];
|
||||
uint16_t val;
|
||||
} crc;
|
||||
|
||||
crc.val=0x3c18;
|
||||
crc=0x3c18;
|
||||
for (i = 0; i < 7; ++i)
|
||||
crc.val=crc16_update(crc.val,header[i],8);
|
||||
crc16_update(header[i],8);
|
||||
for (i = 0; i < *len; ++i)
|
||||
crc.val=crc16_update(crc.val,payload[i],8);
|
||||
crc16_update(payload[i],8);
|
||||
|
||||
// encode payload and crc
|
||||
// xor with this:
|
||||
for (i = 0; i < *len; ++i)
|
||||
payload[i] ^= ssv_xor[i];
|
||||
crc.bytes[1] ^= ssv_xor[i++];
|
||||
crc.bytes[0] ^= ssv_xor[i++];
|
||||
crc ^= ssv_xor[i++]<<8;
|
||||
crc ^= ssv_xor[i++];
|
||||
|
||||
// pack the pcf, payload, and crc into packed_payload
|
||||
packed_payload[0] = pcf >> 1;
|
||||
@@ -78,20 +72,20 @@ static void __attribute__((unused)) ssv_pack_dpl(uint8_t addr[], uint8_t pid, ui
|
||||
for (i = 0; i < *len - 1; ++i)
|
||||
packed_payload[i+2] = (payload[i] << 7) | (payload[i+1] >> 1);
|
||||
|
||||
packed_payload[i+2] = (payload[i] << 7) | (crc.val >> 9);
|
||||
packed_payload[i+2] = (payload[i] << 7) | (crc >> 9);
|
||||
++i;
|
||||
packed_payload[i+2] = (crc.val >> 1 & 0x80 ) | (crc.val >> 1 & 0x7F);
|
||||
packed_payload[i+2] = (crc >> 1 & 0x80 ) | (crc >> 1 & 0x7F);
|
||||
++i;
|
||||
packed_payload[i+2] = (crc.val << 7);
|
||||
packed_payload[i+2] = (crc << 7);
|
||||
|
||||
*len += 4;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FQ777_send_packet(uint8_t bind)
|
||||
static void __attribute__((unused)) FQ777_send_packet()
|
||||
{
|
||||
uint8_t packet_len = FQ777_PACKET_SIZE;
|
||||
uint8_t packet_ori[8];
|
||||
if (bind)
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
// 4,5,6 = address fields
|
||||
// last field is checksum of address fields
|
||||
@@ -144,7 +138,7 @@ static void __attribute__((unused)) FQ777_send_packet(uint8_t bind)
|
||||
packet_count++;
|
||||
}
|
||||
|
||||
ssv_pack_dpl( (0 == bind) ? rx_tx_addr : FQ777_bind_addr, hopping_frequency_no, &packet_len, packet_ori, packet);
|
||||
ssv_pack_dpl( IS_BIND_IN_PROGRESS ? FQ777_bind_addr : rx_tx_addr, hopping_frequency_no, &packet_len, packet_ori, packet);
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG,_BV(NRF24L01_00_PWR_UP));
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no++]);
|
||||
@@ -156,30 +150,21 @@ static void __attribute__((unused)) FQ777_send_packet(uint8_t bind)
|
||||
NRF24L01_WritePayload(packet, packet_len);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FQ777_init()
|
||||
static void __attribute__((unused)) FQ777_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, FQ777_bind_addr, 5);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x00);
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K);
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
|
||||
NRF24L01_Activate(0x73);
|
||||
}
|
||||
|
||||
uint16_t FQ777_callback()
|
||||
{
|
||||
if(bind_counter!=0)
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(FQ777_PACKET_PERIOD);
|
||||
#endif
|
||||
if(bind_counter)
|
||||
{
|
||||
FQ777_send_packet(1);
|
||||
bind_counter--;
|
||||
if (bind_counter == 0)
|
||||
{
|
||||
@@ -187,17 +172,11 @@ uint16_t FQ777_callback()
|
||||
BIND_DONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(FQ777_PACKET_PERIOD);
|
||||
#endif
|
||||
FQ777_send_packet(0);
|
||||
}
|
||||
FQ777_send_packet();
|
||||
return FQ777_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initFQ777(void)
|
||||
void FQ777_init(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
bind_counter = FQ777_BIND_COUNT;
|
||||
@@ -210,8 +189,7 @@ uint16_t initFQ777(void)
|
||||
rx_tx_addr[2] = 0x00;
|
||||
rx_tx_addr[3] = 0xe7;
|
||||
rx_tx_addr[4] = 0x67;
|
||||
FQ777_init();
|
||||
return FQ777_INITIAL_WAIT;
|
||||
FQ777_RF_init();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -58,23 +58,11 @@ static void __attribute__((unused)) FX816_send_packet()
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FX816_init()
|
||||
static void __attribute__((unused)) FX816_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
XN297_SetTXAddr((uint8_t *)"\xcc\xcc\xcc\xcc\xcc", 5);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // No retransmits
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
|
||||
NRF24L01_Activate(0x73);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FX816_initialize_txid()
|
||||
@@ -93,21 +81,20 @@ uint16_t FX816_callback()
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(FX816_PACKET_PERIOD);
|
||||
#endif
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
if(bind_counter)
|
||||
if(--bind_counter==0)
|
||||
BIND_DONE;
|
||||
FX816_send_packet();
|
||||
return FX816_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initFX816()
|
||||
void FX816_init()
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
FX816_initialize_txid();
|
||||
FX816_init();
|
||||
FX816_RF_init();
|
||||
hopping_frequency_no = 0;
|
||||
bind_counter=FX816_BIND_COUNT;
|
||||
return FX816_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -88,34 +88,25 @@ static void __attribute__((unused)) FY326_send_packet(uint8_t bind)
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FY326_init()
|
||||
static void __attribute__((unused)) FY326_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
if(sub_protocol==FY319)
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // Five-byte rx/tx address
|
||||
else
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x01); // Three-byte rx/tx address
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x15\x59\x23\xc6\x29", 5);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x15\x59\x23\xc6\x29", 5);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, FY326_PACKET_SIZE);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, FY326_RF_BIND_CHANNEL);
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K);
|
||||
NRF24L01_SetPower();
|
||||
|
||||
NRF24L01_Activate(0x73);
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f);
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07);
|
||||
NRF24L01_Activate(0x73);
|
||||
|
||||
//Switch to RX
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
}
|
||||
|
||||
@@ -209,20 +200,19 @@ static void __attribute__((unused)) FY326_initialize_txid()
|
||||
hopping_frequency[i]=rx_tx_addr[0] & ~0x80;
|
||||
}
|
||||
|
||||
uint16_t initFY326(void)
|
||||
void FY326_init(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
rxid = 0xAA;
|
||||
bind_counter = FY326_BIND_COUNT;
|
||||
FY326_initialize_txid();
|
||||
FY326_init();
|
||||
FY326_RF_init();
|
||||
if(sub_protocol==FY319)
|
||||
{
|
||||
phase=FY319_BIND1;
|
||||
}
|
||||
else
|
||||
phase=FY326_BIND1;
|
||||
return FY326_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
108
Multiprotocol/Fake_nrf24l01.ino
Normal file
108
Multiprotocol/Fake_nrf24l01.ino
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(FAKE_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
static void __attribute__((unused)) FAKE_send_packet()
|
||||
{
|
||||
for(uint8_t i=0;i<5;i++)
|
||||
packet[i]=i;
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, (_BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_MAX_RT)));
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WritePayload(packet, 5);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FAKE_init()
|
||||
{
|
||||
// BIND_IN_PROGRESS;
|
||||
|
||||
//CC2500
|
||||
option=1;
|
||||
XN297L_Init();
|
||||
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x01); // Packet Automation Control
|
||||
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x00); // Packet Automation Control
|
||||
CC2500_WriteReg(CC2500_12_MDMCFG2, 0x12); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_13_MDMCFG1, 0x13); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_04_SYNC1, 0x11);
|
||||
CC2500_WriteReg(CC2500_05_SYNC0, 0x33);
|
||||
CC2500_WriteReg(CC2500_09_ADDR, 0x99);
|
||||
CC2500_WriteReg(CC2500_06_PKTLEN, 10);
|
||||
|
||||
CC2500_SetTxRxMode(RX_EN);
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_Strobe(CC2500_SRX);
|
||||
//CC2500_SetTxRxMode(TX_EN);
|
||||
XN297L_RFChannel(0);
|
||||
|
||||
//NRF
|
||||
/* option=0;
|
||||
PE1_on; //NRF24L01 antenna RF3 by default
|
||||
PE2_off; //NRF24L01 antenna RF3 by default
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x7f);
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00);//0x3f); // AA on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3f); // Enable all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte address
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x36); // retransmit 1ms, 6 times
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x99\x33\x11\xAA\xAA", 5); //Bind address
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x99\x33\x11\xAA\xAA", 5); //Bind address
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0);
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // Enable dynamic payload length
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Enable all features
|
||||
*/
|
||||
/*NRF24L01_FlushTx();
|
||||
NRF24L01_SetTxRxMode(TX_EN);*/
|
||||
}
|
||||
|
||||
uint16_t FAKE_callback()
|
||||
{
|
||||
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||
if(len) debug("L=%d, ",len);
|
||||
if(len && len < sizeof(packet_in))
|
||||
{
|
||||
CC2500_ReadData(packet_in, len);
|
||||
debug("P:");
|
||||
for(uint8_t i=0;i<len;i++)
|
||||
debug(" %02X", packet_in[i]);
|
||||
}
|
||||
if(len) debugln("");
|
||||
CC2500_Strobe(CC2500_SFRX);
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_Strobe(CC2500_SRX);
|
||||
|
||||
option=0;
|
||||
//FAKE_send_packet();
|
||||
|
||||
PE1_off; //antenna RF2
|
||||
PE2_on;
|
||||
/*packet[0]=0x99;
|
||||
for(uint8_t i=1;i<5;i++)
|
||||
packet[i]=i;
|
||||
CC2500_WriteData(packet, 5);*/
|
||||
return 10000;
|
||||
}
|
||||
|
||||
uint16_t initFAKE()
|
||||
{
|
||||
FAKE_init();
|
||||
return 5000;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -12,7 +12,7 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Last sync with hexfet new_protocols/flysky_a7105.c dated 2015-09-28
|
||||
// Last sync with hexfet new_protocols/FLYSKY_a7105.c dated 2015-09-28
|
||||
|
||||
#if defined(FLYSKY_A7105_INO)
|
||||
|
||||
@@ -53,7 +53,7 @@ enum {
|
||||
const uint8_t PROGMEM V912_X17_SEQ[10] = { 0x14, 0x31, 0x40, 0x49, 0x49, // sometime first byte is 0x15 ?
|
||||
0x49, 0x49, 0x49, 0x49, 0x49, };
|
||||
|
||||
static void __attribute__((unused)) flysky_apply_extension_flags()
|
||||
static void __attribute__((unused)) FLYSKY_apply_extension_flags()
|
||||
{
|
||||
switch(sub_protocol)
|
||||
{
|
||||
@@ -129,7 +129,7 @@ static void __attribute__((unused)) flysky_apply_extension_flags()
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) flysky_build_packet(uint8_t init)
|
||||
static void __attribute__((unused)) FLYSKY_send_packet()
|
||||
{
|
||||
uint8_t i;
|
||||
//servodata timing range for flysky.
|
||||
@@ -137,7 +137,7 @@ static void __attribute__((unused)) flysky_build_packet(uint8_t init)
|
||||
//+100% =~ 0x07ca//=1994us(max)
|
||||
//Center = 0x5d9//=1497us(center)
|
||||
//channel order AIL;ELE;THR;RUD;CH5;CH6;CH7;CH8
|
||||
packet[0] = init ? 0xaa : 0x55;
|
||||
packet[0] = IS_BIND_IN_PROGRESS ? 0xaa : 0x55;
|
||||
packet[1] = rx_tx_addr[3];
|
||||
packet[2] = rx_tx_addr[2];
|
||||
packet[3] = rx_tx_addr[1];
|
||||
@@ -150,36 +150,32 @@ static void __attribute__((unused)) flysky_build_packet(uint8_t init)
|
||||
packet[5 + i*2]=temp&0xFF; //low byte of servo timing(1000-2000us)
|
||||
packet[6 + i*2]=(temp>>8)&0xFF; //high byte of servo timing(1000-2000us)
|
||||
}
|
||||
flysky_apply_extension_flags();
|
||||
FLYSKY_apply_extension_flags();
|
||||
|
||||
A7105_SetPower();
|
||||
A7105_WriteData(21, IS_BIND_IN_PROGRESS ? 0x01:hopping_frequency[hopping_frequency_no & 0x0F]);
|
||||
hopping_frequency_no++;
|
||||
}
|
||||
|
||||
uint16_t ReadFlySky()
|
||||
uint16_t FLYSKY_callback()
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
#ifndef FORCE_FLYSKY_TUNING
|
||||
A7105_AdjustLOBaseFreq(1);
|
||||
#endif
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
if(bind_counter)
|
||||
{
|
||||
flysky_build_packet(1);
|
||||
A7105_WriteData(21, 1);
|
||||
bind_counter--;
|
||||
if (bind_counter==0)
|
||||
BIND_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
flysky_build_packet(0);
|
||||
A7105_WriteData(21, hopping_frequency[hopping_frequency_no & 0x0F]);
|
||||
A7105_SetPower();
|
||||
}
|
||||
hopping_frequency_no++;
|
||||
FLYSKY_send_packet();
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
const uint8_t PROGMEM tx_channels[8][4] = {
|
||||
const uint8_t PROGMEM FLYSKY_tx_channels[8][4] = {
|
||||
{ 0x12, 0x34, 0x56, 0x78},
|
||||
{ 0x18, 0x27, 0x36, 0x45},
|
||||
{ 0x41, 0x82, 0x36, 0x57},
|
||||
@@ -190,7 +186,7 @@ const uint8_t PROGMEM tx_channels[8][4] = {
|
||||
{ 0x71, 0x86, 0x43, 0x52}
|
||||
};
|
||||
|
||||
uint16_t initFlySky()
|
||||
void FLYSKY_init()
|
||||
{
|
||||
uint8_t chanrow;
|
||||
uint8_t chanoffset;
|
||||
@@ -208,7 +204,7 @@ uint16_t initFlySky()
|
||||
chanoffset=rx_tx_addr[3]/16;
|
||||
for(uint8_t i=0;i<16;i++)
|
||||
{
|
||||
temp=pgm_read_byte_near(&tx_channels[chanrow>>1][i>>2]);
|
||||
temp=pgm_read_byte_near(&FLYSKY_tx_channels[chanrow>>1][i>>2]);
|
||||
if(i&0x02)
|
||||
temp&=0x0F;
|
||||
else
|
||||
@@ -242,6 +238,5 @@ uint16_t initFlySky()
|
||||
bind_counter = FLYSKY_BIND_COUNT;
|
||||
else
|
||||
bind_counter = 0;
|
||||
return 2400;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
/** FrSky D and X routines **/
|
||||
/******************************/
|
||||
|
||||
#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[]={
|
||||
@@ -29,7 +34,7 @@ static uint16_t __attribute__((unused)) FrSkyX_CRCTable(uint8_t val)
|
||||
val /= 16 ;
|
||||
return word ^ (0x1081 * val) ;
|
||||
}
|
||||
uint16_t FrSkyX_crc(uint8_t *data, uint8_t len, uint8_t init=0)
|
||||
uint16_t FrSkyX_crc(uint8_t *data, uint8_t len, uint16_t init=0)
|
||||
{
|
||||
uint16_t crc = init;
|
||||
for(uint8_t i=0; i < len; i++)
|
||||
@@ -38,6 +43,73 @@ uint16_t FrSkyX_crc(uint8_t *data, uint8_t len, uint8_t init=0)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYR9_SX1276_INO)
|
||||
static void __attribute__((unused)) FrSkyX_channels(uint8_t offset)
|
||||
{
|
||||
static uint8_t chan_start=0;
|
||||
|
||||
//packet[7] = FLAGS 00 - standard packet
|
||||
//10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
|
||||
//20 - range check packet
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
#define FRSKYX_FAILSAFE_TIMEOUT 1032
|
||||
static uint16_t failsafe_count=0;
|
||||
static uint8_t FS_flag=0,failsafe_chan=0;
|
||||
if (FS_flag == 0 && failsafe_count > FRSKYX_FAILSAFE_TIMEOUT && chan_start == 0 && IS_FAILSAFE_VALUES_on)
|
||||
{
|
||||
FS_flag = 0x10;
|
||||
failsafe_chan = 0;
|
||||
} else if (FS_flag & 0x10 && failsafe_chan < (FrSkyFormat & 0x01 ? 8-1:16-1))
|
||||
{
|
||||
FS_flag = 0x10 | ((FS_flag + 2) & 0x0F); //10, 12, 14, 16, 18, 1A, 1C, 1E - failsafe packet
|
||||
failsafe_chan ++;
|
||||
} else if (FS_flag & 0x10)
|
||||
{
|
||||
FS_flag = 0;
|
||||
failsafe_count = 0;
|
||||
FAILSAFE_VALUES_off;
|
||||
}
|
||||
failsafe_count++;
|
||||
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 {
|
||||
@@ -50,8 +122,6 @@ enum {
|
||||
FRSKY_DATA5,
|
||||
};
|
||||
|
||||
uint8_t FrSkyFormat=0;
|
||||
|
||||
void Frsky_init_hop(void)
|
||||
{
|
||||
uint8_t val;
|
||||
@@ -115,11 +185,18 @@ void Frsky_init_clone(void)
|
||||
else if(protocol==PROTO_FRSKYX2)
|
||||
temp=FRSKYX2_CLONE_EEPROM_OFFSET;
|
||||
FrSkyFormat=eeprom_read_byte((EE_ADDR)temp++);
|
||||
/* FRSKY_RX_D8 =0,
|
||||
FRSKY_RX_D16FCC =1,
|
||||
FRSKY_RX_D16LBT =2,
|
||||
FRSKY_RX_D16v2FCC =3,
|
||||
FRSKY_RX_D16v2LBT =4,*/
|
||||
if(protocol==PROTO_FRSKYX)
|
||||
FrSkyFormat >>= 1;
|
||||
else
|
||||
FrSkyFormat >>= 2;
|
||||
FrSkyFormat <<= 1; //FCC_16/LBT_16
|
||||
if(sub_protocol==XCLONE_8)
|
||||
FrSkyFormat++; //FCC_8/LBT_8
|
||||
rx_tx_addr[3] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
rx_tx_addr[2] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
rx_tx_addr[1] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
@@ -210,7 +287,7 @@ void Frsky_init_clone(void)
|
||||
//FRSKYX
|
||||
/*02_IOCFG0*/ 0x06 ,
|
||||
/*00_IOCFG2*/ 0x06 ,
|
||||
/*17_MCSM1*/ 0x0c , //X2->0x0E -> Go/Stay in RX mode
|
||||
/*17_MCSM1*/ 0x0c , //X2->0x0E -> RX stays in RX and TX stays in TX???
|
||||
/*18_MCSM0*/ 0x18 ,
|
||||
/*06_PKTLEN*/ 0x1E ,
|
||||
/*07_PKTCTRL1*/ 0x04 ,
|
||||
@@ -298,7 +375,6 @@ void Frsky_init_clone(void)
|
||||
val=option;
|
||||
CC2500_WriteReg(reg,val);
|
||||
}
|
||||
prev_option = option ; // Save option to monitor FSCTRL0 change
|
||||
for(uint8_t i=0;i<17;i++)
|
||||
{
|
||||
uint8_t reg=pgm_read_byte_near(&FRSKY_common_end_cc2500_conf[i][0]);
|
||||
@@ -311,23 +387,120 @@ void Frsky_init_clone(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO)
|
||||
uint8_t FrSkyX_chanskip;
|
||||
uint8_t FrSkyX_TX_Seq, FrSkyX_TX_IN_Seq;
|
||||
uint8_t FrSkyX_RX_Seq ;
|
||||
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYR9_SX1276_INO)
|
||||
uint8_t FrSkyX_TX_Seq, FrSkyX_TX_IN_Seq;
|
||||
uint8_t FrSkyX_RX_Seq ;
|
||||
|
||||
#ifdef SPORT_SEND
|
||||
struct t_FrSkyX_TX_Frame
|
||||
#ifdef SPORT_SEND
|
||||
struct t_FrSkyX_TX_Frame
|
||||
{
|
||||
uint8_t count;
|
||||
uint8_t payload[8];
|
||||
} ;
|
||||
// Store FrskyX telemetry
|
||||
struct t_FrSkyX_TX_Frame FrSkyX_TX_Frames[4] ;
|
||||
#endif
|
||||
|
||||
static void __attribute__((unused)) FrSkyX_seq_sport(uint8_t start, uint8_t end)
|
||||
{
|
||||
uint8_t count;
|
||||
uint8_t payload[8];
|
||||
} ;
|
||||
// Store FrskyX telemetry
|
||||
struct t_FrSkyX_TX_Frame FrSkyX_TX_Frames[4] ;
|
||||
for (uint8_t i=start+1;i<=end;i++)
|
||||
packet[i]=0;
|
||||
packet[start] = FrSkyX_RX_Seq << 4;
|
||||
#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
|
||||
|
||||
#define FRSKYX_FAILSAFE_TIMEOUT 1032
|
||||
|
||||
#if defined(FRSKYX_CC2500_INO) || defined(FRSKYL_CC2500_INO)
|
||||
static void __attribute__((unused)) FrSkyX_set_start(uint8_t ch )
|
||||
{
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
@@ -335,7 +508,7 @@ static void __attribute__((unused)) FrSkyX_set_start(uint8_t ch )
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[ch]);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) FrSkyX_init()
|
||||
static void __attribute__((unused)) FrSkyX_RF_init()
|
||||
{
|
||||
if(protocol==PROTO_FRSKYL)
|
||||
FRSKY_init_cc2500(FRSKYL_cc2500_conf);
|
||||
@@ -346,7 +519,7 @@ static void __attribute__((unused)) FrSkyX_init()
|
||||
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Enable CRC
|
||||
if(!(FrSkyFormat&2))
|
||||
{ // FCC
|
||||
CC2500_WriteReg(CC2500_17_MCSM1, 0x0E); // Go/Stay in RX mode
|
||||
CC2500_WriteReg(CC2500_17_MCSM1, 0x0E); //0x0E -> RX stays in RX and TX stays in TX???
|
||||
CC2500_WriteReg(CC2500_11_MDMCFG3, 0x84); // bitrate 70K->77K
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
|
||||
#include "iface_cc2500.h"
|
||||
|
||||
static void __attribute__((unused)) frsky2way_init(uint8_t bind)
|
||||
static void __attribute__((unused)) FRSKYD_RF_init()
|
||||
{
|
||||
FRSKY_init_cc2500(FRSKYD_cc2500_conf);
|
||||
|
||||
CC2500_WriteReg(CC2500_1B_AGCCTRL2, bind ? 0x43 : 0x03);
|
||||
CC2500_WriteReg(CC2500_09_ADDR, bind ? 0x03 : rx_tx_addr[3]);
|
||||
CC2500_WriteReg(CC2500_1B_AGCCTRL2, IS_BIND_IN_PROGRESS ? 0x43 : 0x03);
|
||||
CC2500_WriteReg(CC2500_09_ADDR, IS_BIND_IN_PROGRESS ? 0x03 : rx_tx_addr[3]);
|
||||
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05);
|
||||
CC2500_Strobe(CC2500_SIDLE); // Go to idle...
|
||||
//
|
||||
@@ -32,7 +32,7 @@ static void __attribute__((unused)) frsky2way_init(uint8_t bind)
|
||||
//#######END INIT########
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) frsky2way_build_bind_packet()
|
||||
static void __attribute__((unused)) FRSKYD_build_bind_packet()
|
||||
{
|
||||
//11 03 01 d7 2d 00 00 1e 3c 5b 78 00 00 00 00 00 00 01
|
||||
//11 03 01 19 3e 00 02 8e 2f bb 5c 00 00 00 00 00 00 01
|
||||
@@ -54,10 +54,10 @@ 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()
|
||||
static void __attribute__((unused)) FRSKYD_data_frame()
|
||||
{//pachet[4] is telemetry user frame counter(hub)
|
||||
//11 d7 2d 22 00 01 c9 c9 ca ca 88 88 ca ca c9 ca 88 88
|
||||
//11 57 12 00 00 01 f2 f2 f2 f2 06 06 ca ca ca ca 18 18
|
||||
@@ -71,7 +71,7 @@ static void __attribute__((unused)) frsky2way_data_frame()
|
||||
packet[4] = 0x00;
|
||||
#endif
|
||||
|
||||
packet[5] = 0x01;
|
||||
packet[5] = rx_tx_addr[1];
|
||||
//
|
||||
packet[10] = 0;
|
||||
packet[11] = 0;
|
||||
@@ -94,12 +94,13 @@ static void __attribute__((unused)) frsky2way_data_frame()
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t initFrSky_2way()
|
||||
void FRSKYD_init(void)
|
||||
{
|
||||
//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;
|
||||
@@ -109,25 +110,26 @@ uint16_t initFrSky_2way()
|
||||
freq=0;
|
||||
hopping_frequency[i]=freq;
|
||||
}
|
||||
rx_tx_addr[1]=1; // keep compatibility with already bound RXs
|
||||
}
|
||||
|
||||
packet_count=0;
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
frsky2way_init(1);
|
||||
FRSKYD_RF_init();
|
||||
state = FRSKY_BIND;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = FRSKY_BIND_DONE;
|
||||
}
|
||||
return 10000;
|
||||
}
|
||||
|
||||
uint16_t ReadFrSky_2way()
|
||||
uint16_t FRSKYD_callback(void)
|
||||
{
|
||||
if (state < FRSKY_BIND_DONE)
|
||||
{
|
||||
frsky2way_build_bind_packet();
|
||||
FRSKYD_build_bind_packet();
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, 0x00);
|
||||
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
|
||||
@@ -141,10 +143,10 @@ uint16_t ReadFrSky_2way()
|
||||
}
|
||||
if (state == FRSKY_BIND_DONE)
|
||||
{
|
||||
state = FRSKY_DATA2;
|
||||
frsky2way_init(0);
|
||||
counter = 0;
|
||||
BIND_DONE;
|
||||
FRSKYD_RF_init();
|
||||
counter = 0;
|
||||
state = FRSKY_DATA2;
|
||||
}
|
||||
else
|
||||
if (state == FRSKY_DATA5)
|
||||
@@ -178,7 +180,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
|
||||
}
|
||||
@@ -200,14 +202,10 @@ uint16_t ReadFrSky_2way()
|
||||
}
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[counter % 47]);
|
||||
if ( prev_option != option )
|
||||
{
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); // Frequency offset hack
|
||||
prev_option = option ;
|
||||
}
|
||||
CC2500_SetFreqOffset();
|
||||
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
|
||||
CC2500_Strobe(CC2500_SFRX);
|
||||
frsky2way_data_frame();
|
||||
FRSKYD_data_frame();
|
||||
CC2500_WriteData(packet, packet[0]+1);
|
||||
state++;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ static void __attribute__((unused)) FrSkyL_encode_packet(bool type)
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t ReadFrSkyL()
|
||||
uint16_t FRSKYL_callback()
|
||||
{
|
||||
static uint8_t written=0, send=0;
|
||||
switch(send)
|
||||
@@ -200,11 +200,7 @@ uint16_t ReadFrSkyL()
|
||||
break;
|
||||
|
||||
case FRSKY_DATA1:
|
||||
if ( prev_option != option )
|
||||
{
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); //Frequency offset hack
|
||||
prev_option = option ;
|
||||
}
|
||||
CC2500_SetFreqOffset();
|
||||
FrSkyX_set_start(hopping_frequency_no);
|
||||
FrSkyL_build_packet();
|
||||
FrSkyL_encode_packet(true);
|
||||
@@ -216,7 +212,7 @@ uint16_t ReadFrSkyL()
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint16_t initFrSkyL()
|
||||
void FRSKYL_init()
|
||||
{
|
||||
set_rx_tx_addr(MProtocol_id_master);
|
||||
rx_tx_addr[1]=0x02; // ID related, hw version?
|
||||
@@ -231,7 +227,7 @@ uint16_t initFrSkyL()
|
||||
while(!FrSkyX_chanskip)
|
||||
FrSkyX_chanskip=random(0xfefefefe)%47;
|
||||
|
||||
FrSkyX_init();
|
||||
FrSkyX_RF_init();
|
||||
|
||||
//Prepare frame
|
||||
memset(FrSkyL_buffer,0x00,FRSKYL_PACKET_LEN-3);
|
||||
@@ -257,6 +253,5 @@ uint16_t initFrSkyL()
|
||||
state = FRSKY_DATA1;
|
||||
FrSkyX_initialize_data(0);
|
||||
}
|
||||
return 10000;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,96 +1,194 @@
|
||||
#if defined(FRSKYR9_SX1276_INO)
|
||||
#include "iface_sx1276.h"
|
||||
|
||||
#define FREQ_MAP_SIZE 29
|
||||
#define DISP_FREQ_TABLE
|
||||
|
||||
// TODO the channel spacing is equal, consider calculating the new channel instead of using lookup tables (first_chan + index * step)
|
||||
#define FLEX_FREQ 29
|
||||
#define FCC_FREQ 43
|
||||
#define EU_FREQ 19
|
||||
|
||||
static uint32_t FrSkyR9_freq_map_915[FREQ_MAP_SIZE] =
|
||||
{
|
||||
914472960,
|
||||
914972672,
|
||||
915472384,
|
||||
915972096,
|
||||
916471808,
|
||||
916971520,
|
||||
917471232,
|
||||
917970944,
|
||||
918470656,
|
||||
918970368,
|
||||
919470080,
|
||||
919969792,
|
||||
920469504,
|
||||
920969216,
|
||||
921468928,
|
||||
921968640,
|
||||
922468352,
|
||||
922968064,
|
||||
923467776,
|
||||
923967488,
|
||||
924467200,
|
||||
924966912,
|
||||
925466624,
|
||||
925966336,
|
||||
926466048,
|
||||
926965760,
|
||||
927465472,
|
||||
|
||||
// last two determined by FrSkyR9_step
|
||||
0,
|
||||
0
|
||||
enum {
|
||||
FRSKYR9_FREQ=0,
|
||||
FRSKYR9_DATA,
|
||||
FRSKYR9_RX1,
|
||||
FRSKYR9_RX2,
|
||||
};
|
||||
|
||||
static uint32_t FrSkyR9_freq_map_868[FREQ_MAP_SIZE] =
|
||||
void FrSkyR9_set_frequency()
|
||||
{
|
||||
859504640,
|
||||
860004352,
|
||||
860504064,
|
||||
861003776,
|
||||
861503488,
|
||||
862003200,
|
||||
862502912,
|
||||
863002624,
|
||||
863502336,
|
||||
864002048,
|
||||
864501760,
|
||||
865001472,
|
||||
865501184,
|
||||
866000896,
|
||||
866500608,
|
||||
867000320,
|
||||
867500032,
|
||||
867999744,
|
||||
868499456,
|
||||
868999168,
|
||||
869498880,
|
||||
869998592,
|
||||
870498304,
|
||||
870998016,
|
||||
871497728,
|
||||
871997440,
|
||||
872497152,
|
||||
uint8_t data[3];
|
||||
uint16_t num=0;
|
||||
hopping_frequency_no += FrSkyX_chanskip;
|
||||
switch(sub_protocol & 0xFD)
|
||||
{
|
||||
case R9_868:
|
||||
if(IS_BIND_DONE) // if bind is in progress use R9_915 instead
|
||||
{
|
||||
hopping_frequency_no %= FLEX_FREQ;
|
||||
num=hopping_frequency_no;
|
||||
if(hopping_frequency_no>=FLEX_FREQ-2)
|
||||
num+=FrSkyX_chanskip-FLEX_FREQ+2; // the last 2 values are FrSkyX_chanskip and FrSkyX_chanskip+1
|
||||
num <<= 5;
|
||||
num += 0xD700;
|
||||
break;
|
||||
}//else use R9_915
|
||||
case R9_915:
|
||||
hopping_frequency_no %= FLEX_FREQ;
|
||||
num=hopping_frequency_no;
|
||||
if(hopping_frequency_no>=FLEX_FREQ-2)
|
||||
num+=FrSkyX_chanskip-FLEX_FREQ+2; // the last 2 values are FrSkyX_chanskip and FrSkyX_chanskip+1
|
||||
num <<= 5;
|
||||
num += 0xE4C0;
|
||||
break;
|
||||
case R9_FCC:
|
||||
hopping_frequency_no %= FCC_FREQ;
|
||||
num=hopping_frequency_no;
|
||||
num <<= 5;
|
||||
num += 0xE200;
|
||||
break;
|
||||
case R9_EU:
|
||||
hopping_frequency_no %= EU_FREQ;
|
||||
num=hopping_frequency_no;
|
||||
num <<= 4;
|
||||
num += 0xD7D0;
|
||||
break;
|
||||
}
|
||||
data[0] = num>>8;
|
||||
data[1] = num&0xFF;
|
||||
data[2] = 0x00;
|
||||
|
||||
// last two determined by FrSkyR9_step
|
||||
0,
|
||||
0
|
||||
};
|
||||
#ifdef DISP_FREQ_TABLE
|
||||
if(phase==0xFF)
|
||||
debugln("F%d=%02X%02X%02X=%lu", hopping_frequency_no, data[0], data[1], data[2], (uint32_t)((data[0]<<16)+(data[1]<<8)+data[2])*61);
|
||||
#endif
|
||||
SX1276_WriteRegisterMulti(SX1276_06_FRFMSB, data, 3);
|
||||
}
|
||||
|
||||
static uint8_t FrSkyR9_step = 1;
|
||||
static uint32_t* FrSkyR9_freq_map = FrSkyR9_freq_map_915;
|
||||
|
||||
uint16_t initFrSkyR9()
|
||||
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);
|
||||
}
|
||||
|
||||
void FRSKYR9_init()
|
||||
{
|
||||
//Check frequencies
|
||||
#ifdef DISP_FREQ_TABLE
|
||||
phase=0xFF;
|
||||
FrSkyX_chanskip=1;
|
||||
hopping_frequency_no=0xFF;
|
||||
for(uint8_t i=0;i<FCC_FREQ;i++)
|
||||
FrSkyR9_set_frequency();
|
||||
#endif
|
||||
|
||||
//Reset ID
|
||||
set_rx_tx_addr(MProtocol_id_master);
|
||||
|
||||
if(sub_protocol & 0x01)
|
||||
FrSkyR9_freq_map = FrSkyR9_freq_map_868;
|
||||
//FrSkyX_chanskip
|
||||
FrSkyX_chanskip = 1 + (random(0xfefefefe) % 24);
|
||||
debugln("chanskip=%d", FrSkyX_chanskip);
|
||||
|
||||
//Set FrSkyFormat
|
||||
if((sub_protocol & 0x02) == 0)
|
||||
FrSkyFormat=0; // 16 channels
|
||||
else
|
||||
FrSkyR9_freq_map = FrSkyR9_freq_map_915;
|
||||
|
||||
FrSkyR9_step = 1 + (random(0xfefefefe) % 24);
|
||||
FrSkyR9_freq_map[27] = FrSkyR9_freq_map[FrSkyR9_step];
|
||||
FrSkyR9_freq_map[28] = FrSkyR9_freq_map[FrSkyR9_step+1];
|
||||
FrSkyFormat=1; // 8 channels
|
||||
debugln("%dCH", FrSkyFormat&1 ? 8:16);
|
||||
|
||||
//EU packet length
|
||||
if( (sub_protocol & 0xFD) == R9_EU )
|
||||
packet_length=14;
|
||||
else
|
||||
packet_length=26;
|
||||
|
||||
//SX1276 Init
|
||||
SX1276_SetMode(true, false, SX1276_OPMODE_SLEEP);
|
||||
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
|
||||
|
||||
@@ -106,103 +204,116 @@ uint16_t initFrSkyR9()
|
||||
SX1276_SetPreambleLength(9);
|
||||
SX1276_SetDetectionThreshold(SX1276_MODEM_DETECTION_THRESHOLD_SF6);
|
||||
SX1276_SetLna(1, true);
|
||||
SX1276_SetHopPeriod(0); // 0 = disabled, we hope frequencies manually
|
||||
SX1276_SetPaDac(true);
|
||||
|
||||
hopping_frequency_no = 0;
|
||||
|
||||
// TODO this can probably be shorter
|
||||
return 20000; // start calling FrSkyR9_callback in 20 milliseconds
|
||||
SX1276_SetHopPeriod(0); // 0 = disabled, we hop frequencies manually
|
||||
//RF Power
|
||||
SX1276_SetPaDac(false); // Disable 20dBm mode
|
||||
#if MULTI_5IN1_INTERNAL == JP_T18
|
||||
SX1276_SetPaConfig(true, 7, 0); // Lowest power for the T18: 2dBm
|
||||
#else
|
||||
SX1276_SetPaConfig(true, 7, option); // Use PA_HP on PA_BOOST, power=17-(15-option) dBm with option equal or lower to 15
|
||||
#endif
|
||||
SX1276_SetOcp(true,27); // Set OCP to max 240mA
|
||||
SX1276_SetTxRxMode(TX_EN); // Set RF switch to TX
|
||||
//Enable all IRQ flags
|
||||
SX1276_WriteReg(SX1276_11_IRQFLAGSMASK,0x00);
|
||||
FrSkyX_telem_init();
|
||||
|
||||
hopping_frequency_no=0;
|
||||
phase=FRSKYR9_FREQ;
|
||||
}
|
||||
|
||||
uint16_t FrSkyR9_callback()
|
||||
uint16_t FRSKYR9_callback()
|
||||
{
|
||||
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
|
||||
|
||||
//SX1276_WriteReg(SX1276_11_IRQFLAGSMASK, 0xbf); // use only RxDone interrupt
|
||||
|
||||
// uint8_t buffer[2];
|
||||
// buffer[0] = 0x00;
|
||||
// buffer[1] = 0x00;
|
||||
// SX1276_WriteRegisterMulti(SX1276_40_DIOMAPPING1, buffer, 2); // RxDone interrupt mapped to DIO0 (the rest are not used because of the REG_IRQ_FLAGS_MASK)
|
||||
|
||||
// SX1276_WriteReg(REG_PAYLOAD_LENGTH, 13);
|
||||
|
||||
// SX1276_WriteReg(REG_FIFO_ADDR_PTR, 0x00);
|
||||
|
||||
// SX1276_WriteReg(SX1276_01_OPMODE, 0x85); // RXCONTINUOUS
|
||||
// delay(10); // 10 ms
|
||||
|
||||
// SX1276_WriteReg(SX1276_01_OPMODE, 0x81); // STDBY
|
||||
|
||||
//SX1276_WriteReg(SX1276_09_PACONFIG, 0xF0);
|
||||
|
||||
// max power: 15dBm (10.8 + 0.6 * MaxPower [dBm])
|
||||
// output_power: 2 dBm (17-(15-OutputPower) (if pa_boost_pin == true))
|
||||
SX1276_SetPaConfig(true, 7, 0);
|
||||
SX1276_SetFrequency(FrSkyR9_freq_map[hopping_frequency_no]); // set current center frequency
|
||||
|
||||
delayMicroseconds(500);
|
||||
|
||||
packet[0] = 0x3C; // ????
|
||||
packet[1] = rx_tx_addr[3]; // unique radio id
|
||||
packet[2] = rx_tx_addr[2]; // unique radio id
|
||||
packet[3] = hopping_frequency_no; // current channel index
|
||||
packet[4] = FrSkyR9_step; // step size and last 2 channels start index
|
||||
packet[5] = RX_num; // receiver number from OpenTX
|
||||
|
||||
// binding mode: 0x00 regular / 0x41 bind?
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
packet[6] = 0x41;
|
||||
else
|
||||
packet[6] = 0x00;
|
||||
|
||||
// TODO
|
||||
packet[7] = 0x00; // fail safe related (looks like the same sequence of numbers as FrskyX protocol)
|
||||
|
||||
// two channel are spread over 3 bytes.
|
||||
// each channel is 11 bit + 1 bit (msb) that states whether
|
||||
// it's part of the upper channels (9-16) or lower (1-8) (0 - lower 1 - upper)
|
||||
|
||||
#define CH_POS 8
|
||||
static uint8_t chan_start=0;
|
||||
uint8_t chan_index = chan_start;
|
||||
|
||||
for(int i = 0; i < 12; i += 3)
|
||||
switch (phase)
|
||||
{
|
||||
// map channel values (0-2047) to (64-1984)
|
||||
uint16_t ch1 = FrSkyX_scaleForPXX(chan_index);
|
||||
uint16_t ch2 = FrSkyX_scaleForPXX(chan_index + 1);
|
||||
|
||||
packet[CH_POS + i] = ch1;
|
||||
packet[CH_POS + i + 1] = (ch1 >> 8) | (ch2 << 4);
|
||||
packet[CH_POS + i + 2] = (ch2 >> 4);
|
||||
|
||||
chan_index += 2;
|
||||
case FRSKYR9_FREQ:
|
||||
//Force standby
|
||||
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
|
||||
//Set frequency
|
||||
FrSkyR9_set_frequency(); // Set current center frequency
|
||||
//Set power
|
||||
// max power: 15dBm (10.8 + 0.6 * MaxPower [dBm])
|
||||
// output_power: 2 dBm ( (if pa_boost_pin == true))
|
||||
#if MULTI_5IN1_INTERNAL != JP_T18
|
||||
if(option != prev_option)
|
||||
{ // Set RF power if it has changed
|
||||
SX1276_SetPaConfig(true, 7, option); // Use PA_HP on PA_BOOST, power=17-(15-option) dBm with option equal or lower to 15
|
||||
prev_option = option;
|
||||
}
|
||||
#endif
|
||||
//Build packet
|
||||
if( packet_length == 26 )
|
||||
FrSkyR9_build_packet();
|
||||
else
|
||||
FrSkyR9_build_EU_packet();
|
||||
phase++;
|
||||
return 460; // Frequency settle time
|
||||
case FRSKYR9_DATA:
|
||||
//Set RF switch to TX
|
||||
SX1276_SetTxRxMode(TX_EN);
|
||||
//Send packet
|
||||
SX1276_WritePayloadToFifo(packet, packet_length);
|
||||
SX1276_SetMode(true, false, SX1276_OPMODE_TX);
|
||||
#if not defined TELEMETRY
|
||||
phase=FRSKYR9_FREQ;
|
||||
return 20000-460;
|
||||
#else
|
||||
phase++;
|
||||
return 11140; // Packet send time
|
||||
case FRSKYR9_RX1:
|
||||
//Force standby
|
||||
SX1276_SetMode(true, false, SX1276_OPMODE_STDBY);
|
||||
//RX packet size is 13
|
||||
SX1276_WriteReg(SX1276_22_PAYLOAD_LENGTH, 13);
|
||||
//Reset pointer
|
||||
SX1276_WriteReg(SX1276_0D_FIFOADDRPTR, 0x00);
|
||||
//Set RF switch to RX
|
||||
SX1276_SetTxRxMode(RX_EN);
|
||||
//Clear all IRQ flags
|
||||
SX1276_WriteReg(SX1276_12_REGIRQFLAGS,0xFF);
|
||||
//Switch to RX
|
||||
SX1276_WriteReg(SX1276_01_OPMODE, 0x85);
|
||||
phase++;
|
||||
return 7400;
|
||||
case FRSKYR9_RX2:
|
||||
if( (SX1276_ReadReg(SX1276_12_REGIRQFLAGS)&0xF0) == (_BV(SX1276_REGIRQFLAGS_RXDONE) | _BV(SX1276_REGIRQFLAGS_VALIDHEADER)) )
|
||||
{
|
||||
if(SX1276_ReadReg(SX1276_13_REGRXNBBYTES)==13)
|
||||
{
|
||||
SX1276_ReadRegisterMulti(SX1276_00_FIFO,packet_in,13);
|
||||
if( packet_in[9]==rx_tx_addr[1] && packet_in[10]==rx_tx_addr[2] && FrSkyX_crc(packet_in, 11, rx_tx_addr[1]+(rx_tx_addr[2]<<8))==(packet_in[11]+(packet_in[12]<<8)) )
|
||||
{
|
||||
if(packet_in[0]&0x80)
|
||||
RX_RSSI=packet_in[0]<<1;
|
||||
else
|
||||
v_lipo1=(packet_in[0]<<1)+1;
|
||||
//TX_LQI=~(SX1276_ReadReg(SX1276_19_PACKETSNR)>>2)+1;
|
||||
TX_RSSI=SX1276_ReadReg(SX1276_1A_PACKETRSSI)-157;
|
||||
for(uint8_t i=0;i<9;i++)
|
||||
packet[4+i]=packet_in[i]; // Adjust buffer to match FrSkyX
|
||||
frsky_process_telemetry(packet,len); // Process telemetry packet
|
||||
pps_counter++;
|
||||
if(TX_LQI==0)
|
||||
TX_LQI++; // Recover telemetry right away
|
||||
}
|
||||
}
|
||||
}
|
||||
if (millis() - pps_timer >= 1000)
|
||||
{//1 packet every 20ms
|
||||
pps_timer = millis();
|
||||
debugln("%d pps", pps_counter);
|
||||
TX_LQI = pps_counter<<1; // Max=100%
|
||||
pps_counter = 0;
|
||||
}
|
||||
if(TX_LQI==0)
|
||||
FrSkyX_telem_init(); // Reset telemetry
|
||||
else
|
||||
telemetry_link=1; // Send telemetry out anyway
|
||||
phase=FRSKYR9_FREQ;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if((sub_protocol & 0x02) == 0)
|
||||
chan_start ^= 0x08; // Alternate between lower and upper when 16 channels is used
|
||||
|
||||
packet[20] = 0x08; // ????
|
||||
packet[21] = 0x00; // ????
|
||||
packet[22] = 0x00; // ????
|
||||
packet[23] = 0x00; // ????
|
||||
|
||||
uint16_t crc = FrSkyX_crc(packet, 24);
|
||||
|
||||
packet[24] = crc; // low byte
|
||||
packet[25] = crc >> 8; // high byte
|
||||
|
||||
SX1276_WritePayloadToFifo(packet, 26);
|
||||
|
||||
hopping_frequency_no = (hopping_frequency_no + FrSkyR9_step) % FREQ_MAP_SIZE;
|
||||
|
||||
SX1276_SetMode(true, false, SX1276_OPMODE_TX);
|
||||
|
||||
// need to clear RegIrqFlags?
|
||||
|
||||
return 19400;
|
||||
return 1000;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -113,7 +113,7 @@ static void __attribute__((unused)) FRSKYV_build_data_packet()
|
||||
packet[14] = FRSKYV_crc8(crc8, packet, 14);
|
||||
}
|
||||
|
||||
uint16_t ReadFRSKYV()
|
||||
uint16_t FRSKYV_callback(void)
|
||||
{
|
||||
if(IS_BIND_DONE)
|
||||
{ // Normal operation
|
||||
@@ -122,11 +122,7 @@ uint16_t ReadFRSKYV()
|
||||
#endif
|
||||
uint8_t chan = FRSKYV_calc_channel();
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
if (option != prev_option)
|
||||
{
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
prev_option=option;
|
||||
}
|
||||
CC2500_SetFreqOffset();
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, chan * 5 + 6);
|
||||
FRSKYV_build_data_packet();
|
||||
|
||||
@@ -152,7 +148,7 @@ uint16_t ReadFRSKYV()
|
||||
return 53460;
|
||||
}
|
||||
|
||||
uint16_t initFRSKYV()
|
||||
void FRSKYV_init(void)
|
||||
{
|
||||
//ID is 15 bits. Using rx_tx_addr[2] and rx_tx_addr[3] since we want to use RX_Num for model match
|
||||
rx_tx_addr[2]&=0x7F;
|
||||
@@ -162,7 +158,6 @@ uint16_t initFRSKYV()
|
||||
seed = 1;
|
||||
binding_idx=0;
|
||||
phase = FRSKYV_DATA1;
|
||||
return 10000;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -80,36 +80,11 @@ static void __attribute__((unused)) FrSkyX_build_bind_packet()
|
||||
debugln("");*/
|
||||
}
|
||||
|
||||
#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 < (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++;
|
||||
#endif
|
||||
|
||||
//
|
||||
uint8_t packet_size = 0x1D;
|
||||
if(protocol==PROTO_FRSKYX && (FrSkyFormat & 2 ))
|
||||
packet_size=0x20; // FrSkyX V1 LBT
|
||||
@@ -122,123 +97,12 @@ static void __attribute__((unused)) FrSkyX_build_packet()
|
||||
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(FrSkyFormat & 0x01 ) //In X8 mode send only 8ch every 9ms
|
||||
chan_offset = 0 ;
|
||||
else
|
||||
chan_offset^=0x08;
|
||||
|
||||
//Channels
|
||||
FrSkyX_channels(7); // Set packet[7]=failsafe, packet[8]=0?? and packet[9..20]=channels data
|
||||
|
||||
//sequence and send SPort
|
||||
for (uint8_t i=22;i<packet_size-1;i++)
|
||||
packet[i]=0;
|
||||
packet[21] = FrSkyX_RX_Seq << 4; //TX=8 at startup
|
||||
#ifdef SPORT_SEND
|
||||
if (FrSkyX_TX_IN_Seq!=0xFF)
|
||||
{//RX has replied at least once
|
||||
if (FrSkyX_TX_IN_Seq & 0x08)
|
||||
{//Request init
|
||||
//debugln("Init");
|
||||
FrSkyX_TX_Seq = 0 ;
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
FrSkyX_TX_Frames[i].count=0; //Discard frames in current output buffer
|
||||
}
|
||||
else if (FrSkyX_TX_IN_Seq & 0x04)
|
||||
{//Retransmit the requested packet
|
||||
debugln("Retry:%d",FrSkyX_TX_IN_Seq&0x03);
|
||||
packet[21] |= FrSkyX_TX_IN_Seq&0x03;
|
||||
packet[22] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq&0x03].count;
|
||||
for (uint8_t i=23;i<23+FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq&0x03].count;i++)
|
||||
packet[i] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq&0x03].payload[i];
|
||||
}
|
||||
else if ( FrSkyX_TX_Seq != 0x08 )
|
||||
{
|
||||
if(FrSkyX_TX_Seq==FrSkyX_TX_IN_Seq)
|
||||
{//Send packet from the incoming radio buffer
|
||||
//debugln("Send:%d",FrSkyX_TX_Seq);
|
||||
packet[21] |= FrSkyX_TX_Seq;
|
||||
uint8_t nbr_bytes=0;
|
||||
for (uint8_t i=23;i<packet_size-1;i++)
|
||||
{
|
||||
if(SportHead==SportTail)
|
||||
break; //buffer empty
|
||||
packet[i]=SportData[SportHead];
|
||||
FrSkyX_TX_Frames[FrSkyX_TX_Seq].payload[i-23]=SportData[SportHead];
|
||||
SportHead=(SportHead+1) & (MAX_SPORT_BUFFER-1);
|
||||
nbr_bytes++;
|
||||
}
|
||||
packet[22]=nbr_bytes;
|
||||
FrSkyX_TX_Frames[FrSkyX_TX_Seq].count=nbr_bytes;
|
||||
if(nbr_bytes)
|
||||
{//Check the buffer status
|
||||
uint8_t used = SportTail;
|
||||
if ( SportHead > SportTail )
|
||||
used += MAX_SPORT_BUFFER - SportHead ;
|
||||
else
|
||||
used -= SportHead ;
|
||||
if ( used < (MAX_SPORT_BUFFER>>1) )
|
||||
{
|
||||
DATA_BUFFER_LOW_off;
|
||||
debugln("Ok buf:%d",used);
|
||||
}
|
||||
}
|
||||
FrSkyX_TX_Seq = ( FrSkyX_TX_Seq + 1 ) & 0x03 ; //Next iteration send next packet
|
||||
}
|
||||
else
|
||||
{//Not in sequence somehow, transmit what the receiver wants but why not asking for retransmit...
|
||||
//debugln("RX_Seq:%d,TX:%d",FrSkyX_TX_IN_Seq,FrSkyX_TX_Seq);
|
||||
packet[21] |= FrSkyX_TX_IN_Seq;
|
||||
packet[22] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].count;
|
||||
for (uint8_t i=23;i<23+FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].count;i++)
|
||||
packet[i] = FrSkyX_TX_Frames[FrSkyX_TX_IN_Seq].payload[i-23];
|
||||
}
|
||||
}
|
||||
else
|
||||
packet[21] |= 0x08 ; //FrSkyX_TX_Seq=8 at startup
|
||||
}
|
||||
if(packet[22])
|
||||
{//Debug
|
||||
debug("SP: ");
|
||||
for(uint8_t i=0;i<packet[22];i++)
|
||||
debug("%02X ",packet[23+i]);
|
||||
debugln("");
|
||||
}
|
||||
#else
|
||||
packet[21] |= FrSkyX_TX_Seq ;//TX=8 at startup
|
||||
if ( !(FrSkyX_TX_IN_Seq & 0xF8) )
|
||||
FrSkyX_TX_Seq = ( FrSkyX_TX_Seq + 1 ) & 0x03 ; // Next iteration send next packet
|
||||
#endif // SPORT_SEND
|
||||
//Sequence and send SPort
|
||||
FrSkyX_seq_sport(21,packet_size-2); //21=RX|TXseq, 22=bytes count, 23..packet_size-2=data
|
||||
|
||||
//CRC
|
||||
uint16_t lcrc = FrSkyX_crc(&packet[3], packet_size-4);
|
||||
@@ -252,7 +116,7 @@ static void __attribute__((unused)) FrSkyX_build_packet()
|
||||
debugln("");*/
|
||||
}
|
||||
|
||||
uint16_t ReadFrSkyX()
|
||||
uint16_t FRSKYX_callback()
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
@@ -273,23 +137,19 @@ uint16_t ReadFrSkyX()
|
||||
FrSkyX_initialize_data(0);
|
||||
hopping_frequency_no=0;
|
||||
BIND_DONE;
|
||||
state++; //FRSKY_DATA1
|
||||
state++; //FRSKY_DATA1
|
||||
break;
|
||||
|
||||
case FRSKY_DATA1:
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
if ( prev_option != option )
|
||||
{
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0,option); //Frequency offset hack
|
||||
prev_option = option ;
|
||||
}
|
||||
CC2500_SetFreqOffset();
|
||||
FrSkyX_set_start(hopping_frequency_no);
|
||||
FrSkyX_build_packet();
|
||||
if(FrSkyFormat & 2)
|
||||
{// LBT
|
||||
CC2500_Strobe(CC2500_SRX); //Acquire RSSI
|
||||
CC2500_Strobe(CC2500_SRX); //Acquire RSSI
|
||||
state++;
|
||||
return 400; // LBT v2.1
|
||||
return 400; // LBT
|
||||
}
|
||||
case FRSKY_DATA2:
|
||||
if(FrSkyFormat & 2)
|
||||
@@ -299,93 +159,94 @@ uint16_t ReadFrSkyX()
|
||||
rssi += CC2500_ReadReg(CC2500_34_RSSI | CC2500_READ_BURST); // 0.5 db/count, RSSI value read from the RSSI status register is a 2's complement number
|
||||
rssi>>=2;
|
||||
#if 0
|
||||
uint8_t rssi_level=convert_channel_8b(CH16)>>1; //CH16 0..127
|
||||
if ( rssi > rssi_level && rssi < 128) //test rssi level dynamically
|
||||
uint8_t rssi_level=convert_channel_8b(CH16)>>1; //CH16 0..127
|
||||
if ( rssi > rssi_level && rssi < 128) //test rssi level dynamically
|
||||
#else
|
||||
if ( rssi > 72 && rssi < 128) //LBT and RSSI between -36 and -8.5 dBm
|
||||
if ( rssi > 14 && rssi < 128) //if RSSI above -65dBm (12=-70) => ETSI requirement
|
||||
#endif
|
||||
{
|
||||
POWER_FLAG_off; // Reduce to low power before transmitting
|
||||
LBT_POWER_on; //Reduce to low power before transmitting
|
||||
debugln("Busy %d %d",hopping_frequency_no,rssi);
|
||||
}
|
||||
}
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_Strobe(CC2500_SFTX);
|
||||
CC2500_Strobe(CC2500_SFTX); //Flush the TXFIFO
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
CC2500_SetPower();
|
||||
hopping_frequency_no = (hopping_frequency_no+FrSkyX_chanskip)%47;
|
||||
CC2500_WriteData(packet, packet[0]+1);
|
||||
state=FRSKY_DATA3;
|
||||
if(FrSkyFormat & 2)
|
||||
return 4000; // LBT v2.1
|
||||
return 4000; // LBT
|
||||
else
|
||||
return 5200; // FCC v2.1
|
||||
return 5200; // FCC
|
||||
case FRSKY_DATA3:
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_Strobe(CC2500_SFRX); //Flush the RXFIFO
|
||||
CC2500_SetTxRxMode(RX_EN);
|
||||
CC2500_Strobe(CC2500_SRX);
|
||||
state++;
|
||||
if(FrSkyFormat & 2)
|
||||
return 4100; // LBT v2.1
|
||||
return 4200; // LBT
|
||||
else
|
||||
return 3300; // FCC v2.1
|
||||
case FRSKY_DATA4:
|
||||
return 3400; // FCC
|
||||
case FRSKY_DATA4:
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(9000);
|
||||
#endif
|
||||
#if defined TELEMETRY
|
||||
telemetry_link=1; //Send telemetry out anyway
|
||||
#endif
|
||||
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||
if (len && (len<=(0x0E + 3))) //Telemetry frame is 17
|
||||
{
|
||||
//debug("Telem:");
|
||||
packet_count=0;
|
||||
CC2500_ReadData(packet_in, len);
|
||||
#if defined TELEMETRY
|
||||
if(protocol==PROTO_FRSKYX || (protocol==PROTO_FRSKYX2 && (packet_in[len-1] & 0x80)) )
|
||||
{//with valid crc for FRSKYX2
|
||||
len = CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||
if (len && len <= 17) //Telemetry frame is 17 bytes
|
||||
{
|
||||
//debug("Telem:");
|
||||
CC2500_ReadData(packet_in, len); //Read what has been received so far
|
||||
if(len<17)
|
||||
{//not all bytes were received
|
||||
uint8_t last_len=CC2500_ReadReg(CC2500_3B_RXBYTES | CC2500_READ_BURST) & 0x7F;
|
||||
if(last_len==17) //All bytes received
|
||||
{
|
||||
CC2500_ReadData(packet_in+len, last_len-len); //Finish to read
|
||||
len=17;
|
||||
}
|
||||
}
|
||||
if(len==17 && (protocol==PROTO_FRSKYX || (protocol==PROTO_FRSKYX2 && (packet_in[len-1] & 0x80))) )
|
||||
{//Telemetry received with valid crc for FRSKYX2
|
||||
//Debug
|
||||
//for(uint8_t i=0;i<len;i++)
|
||||
// debug(" %02X",packet_in[i]);
|
||||
frsky_check_telemetry(packet_in,len); //Check and parse telemetry packets
|
||||
if(frsky_process_telemetry(packet_in,len)) //Check and process telemetry packet
|
||||
{//good packet received
|
||||
pps_counter++;
|
||||
if(TX_LQI==0)
|
||||
TX_LQI++; //Recover telemetry right away
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//debugln("");
|
||||
}
|
||||
else
|
||||
{
|
||||
packet_count++;
|
||||
//debugln("M %d",packet_count);
|
||||
// restart sequence on missed packet - might need count or timeout instead of one missed
|
||||
if(packet_count>100)
|
||||
{//~1sec
|
||||
FrSkyX_TX_Seq = 0x08 ; //Request init
|
||||
FrSkyX_TX_IN_Seq = 0xFF ; //No sequence received yet
|
||||
#ifdef SPORT_SEND
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
FrSkyX_TX_Frames[i].count=0; //Discard frames in current output buffer
|
||||
#endif
|
||||
packet_count=0;
|
||||
#if defined TELEMETRY
|
||||
telemetry_lost=1;
|
||||
telemetry_link=0; //Stop sending telemetry
|
||||
#endif
|
||||
//debugln("");
|
||||
}
|
||||
CC2500_Strobe(CC2500_SFRX); //Flush the RXFIFO
|
||||
}
|
||||
if (millis() - pps_timer >= 900)
|
||||
{//1 packet every 9ms
|
||||
pps_timer = millis();
|
||||
debugln("%d pps", pps_counter);
|
||||
TX_LQI = pps_counter; //Max=100%
|
||||
pps_counter = 0;
|
||||
}
|
||||
if(TX_LQI==0)
|
||||
FrSkyX_telem_init(); //Reset telemetry
|
||||
else
|
||||
telemetry_link=1; //Send telemetry out anyway
|
||||
#endif
|
||||
state = FRSKY_DATA1;
|
||||
return 500; // FCC & LBT v2.1
|
||||
}
|
||||
return 400; // FCC & LBT
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint16_t initFrSkyX()
|
||||
void FRSKYX_init()
|
||||
{
|
||||
set_rx_tx_addr(MProtocol_id_master);
|
||||
FrSkyFormat = sub_protocol;
|
||||
|
||||
if (sub_protocol==XCLONE)
|
||||
if (sub_protocol==XCLONE_16||sub_protocol==XCLONE_8)
|
||||
Frsky_init_clone();
|
||||
else if(protocol==PROTO_FRSKYX)
|
||||
{
|
||||
@@ -407,7 +268,7 @@ uint16_t initFrSkyX()
|
||||
while(!FrSkyX_chanskip)
|
||||
FrSkyX_chanskip=random(0xfefefefe)%47;
|
||||
|
||||
FrSkyX_init();
|
||||
FrSkyX_RF_init();
|
||||
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
@@ -419,15 +280,6 @@ uint16_t initFrSkyX()
|
||||
state = FRSKY_DATA1;
|
||||
FrSkyX_initialize_data(0);
|
||||
}
|
||||
FrSkyX_TX_Seq = 0x08 ; // Request init
|
||||
FrSkyX_TX_IN_Seq = 0xFF ; // No sequence received yet
|
||||
#ifdef SPORT_SEND
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
FrSkyX_TX_Frames[i].count=0; // discard frames in current output buffer
|
||||
SportHead=SportTail=0; // empty data buffer
|
||||
#endif
|
||||
FrSkyX_RX_Seq = 0 ; // Seq 0 to start with
|
||||
binding_idx=0; // CH1-8 and Telem on
|
||||
return 10000;
|
||||
}
|
||||
FrSkyX_telem_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -40,7 +40,7 @@ enum {
|
||||
FRSKY_RX_DATA,
|
||||
};
|
||||
|
||||
const PROGMEM uint8_t frsky_rx_common_reg[][2] = {
|
||||
const PROGMEM uint8_t FRSKY_RX_common_reg[][2] = {
|
||||
{CC2500_02_IOCFG0, 0x01},
|
||||
{CC2500_18_MCSM0, 0x18},
|
||||
{CC2500_07_PKTCTRL1, 0x05},
|
||||
@@ -68,7 +68,7 @@ const PROGMEM uint8_t frsky_rx_common_reg[][2] = {
|
||||
{CC2500_09_ADDR, 0x03},
|
||||
};
|
||||
|
||||
const PROGMEM uint8_t frsky_rx_d16fcc_reg[][2] = {
|
||||
const PROGMEM uint8_t FRSKY_RX_d16fcc_reg[][2] = {
|
||||
{CC2500_17_MCSM1, 0x0C},
|
||||
{CC2500_0E_FREQ1, 0x76},
|
||||
{CC2500_0F_FREQ0, 0x27},
|
||||
@@ -81,7 +81,7 @@ const PROGMEM uint8_t frsky_rx_d16fcc_reg[][2] = {
|
||||
{CC2500_15_DEVIATN, 0x51},
|
||||
};
|
||||
|
||||
const PROGMEM uint8_t frsky_rx_d16lbt_reg[][2] = {
|
||||
const PROGMEM uint8_t FRSKY_RX_d16lbt_reg[][2] = {
|
||||
{CC2500_17_MCSM1, 0x0E},
|
||||
{CC2500_0E_FREQ1, 0x80},
|
||||
{CC2500_0F_FREQ0, 0x00},
|
||||
@@ -94,7 +94,7 @@ const PROGMEM uint8_t frsky_rx_d16lbt_reg[][2] = {
|
||||
{CC2500_15_DEVIATN, 0x53},
|
||||
};
|
||||
|
||||
const PROGMEM uint8_t frsky_rx_d8_reg[][2] = {
|
||||
const PROGMEM uint8_t FRSKY_RX_d8_reg[][2] = {
|
||||
{CC2500_17_MCSM1, 0x0C},
|
||||
{CC2500_0E_FREQ1, 0x76},
|
||||
{CC2500_0F_FREQ0, 0x27},
|
||||
@@ -107,32 +107,32 @@ const PROGMEM uint8_t frsky_rx_d8_reg[][2] = {
|
||||
{CC2500_15_DEVIATN, 0x42},
|
||||
};
|
||||
|
||||
static uint8_t frsky_rx_chanskip;
|
||||
static int8_t frsky_rx_finetune;
|
||||
static uint8_t frsky_rx_format;
|
||||
static uint8_t FRSKY_RX_chanskip;
|
||||
static int8_t FRSKY_RX_finetune;
|
||||
static uint8_t FRSKY_RX_format;
|
||||
|
||||
static void __attribute__((unused)) frsky_rx_strobe_rx()
|
||||
static void __attribute__((unused)) FRSKY_RX_strobe_rx()
|
||||
{
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_Strobe(CC2500_SFRX);
|
||||
CC2500_Strobe(CC2500_SRX);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) frsky_rx_initialise_cc2500() {
|
||||
const uint8_t frsky_rx_length[] = { FRSKY_RX_D8_LENGTH, FRSKY_RX_D16FCC_LENGTH, FRSKY_RX_D16LBT_LENGTH, FRSKY_RX_D16v2_LENGTH, FRSKY_RX_D16v2_LENGTH };
|
||||
packet_length = frsky_rx_length[frsky_rx_format];
|
||||
static void __attribute__((unused)) FRSKY_RX_initialise_cc2500() {
|
||||
const uint8_t FRSKY_RX_length[] = { FRSKY_RX_D8_LENGTH, FRSKY_RX_D16FCC_LENGTH, FRSKY_RX_D16LBT_LENGTH, FRSKY_RX_D16v2_LENGTH, FRSKY_RX_D16v2_LENGTH };
|
||||
packet_length = FRSKY_RX_length[FRSKY_RX_format];
|
||||
CC2500_Reset();
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
for (uint8_t i = 0; i < sizeof(frsky_rx_common_reg) / 2; i++)
|
||||
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_common_reg[i][0]), pgm_read_byte_near(&frsky_rx_common_reg[i][1]));
|
||||
for (uint8_t i = 0; i < sizeof(FRSKY_RX_common_reg) / 2; i++)
|
||||
CC2500_WriteReg(pgm_read_byte_near(&FRSKY_RX_common_reg[i][0]), pgm_read_byte_near(&FRSKY_RX_common_reg[i][1]));
|
||||
|
||||
switch (frsky_rx_format)
|
||||
switch (FRSKY_RX_format)
|
||||
{
|
||||
case FRSKY_RX_D16v2FCC:
|
||||
case FRSKY_RX_D16FCC:
|
||||
for (uint8_t i = 0; i < sizeof(frsky_rx_d16fcc_reg) / 2; i++)
|
||||
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_d16fcc_reg[i][0]), pgm_read_byte_near(&frsky_rx_d16fcc_reg[i][1]));
|
||||
if(frsky_rx_format==FRSKY_RX_D16v2FCC)
|
||||
for (uint8_t i = 0; i < sizeof(FRSKY_RX_d16fcc_reg) / 2; i++)
|
||||
CC2500_WriteReg(pgm_read_byte_near(&FRSKY_RX_d16fcc_reg[i][0]), pgm_read_byte_near(&FRSKY_RX_d16fcc_reg[i][1]));
|
||||
if(FRSKY_RX_format==FRSKY_RX_D16v2FCC)
|
||||
{
|
||||
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Enable CRC
|
||||
CC2500_WriteReg(CC2500_17_MCSM1, 0x0E); // Go/Stay in RX mode
|
||||
@@ -141,36 +141,36 @@ static void __attribute__((unused)) frsky_rx_initialise_cc2500() {
|
||||
break;
|
||||
case FRSKY_RX_D16v2LBT:
|
||||
case FRSKY_RX_D16LBT:
|
||||
for (uint8_t i = 0; i < sizeof(frsky_rx_d16lbt_reg) / 2; i++)
|
||||
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_d16lbt_reg[i][0]), pgm_read_byte_near(&frsky_rx_d16lbt_reg[i][1]));
|
||||
if(frsky_rx_format==FRSKY_RX_D16v2LBT)
|
||||
for (uint8_t i = 0; i < sizeof(FRSKY_RX_d16lbt_reg) / 2; i++)
|
||||
CC2500_WriteReg(pgm_read_byte_near(&FRSKY_RX_d16lbt_reg[i][0]), pgm_read_byte_near(&FRSKY_RX_d16lbt_reg[i][1]));
|
||||
if(FRSKY_RX_format==FRSKY_RX_D16v2LBT)
|
||||
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // Enable CRC
|
||||
break;
|
||||
case FRSKY_RX_D8:
|
||||
for (uint8_t i = 0; i < sizeof(frsky_rx_d8_reg) / 2; i++)
|
||||
CC2500_WriteReg(pgm_read_byte_near(&frsky_rx_d8_reg[i][0]), pgm_read_byte_near(&frsky_rx_d8_reg[i][1]));
|
||||
for (uint8_t i = 0; i < sizeof(FRSKY_RX_d8_reg) / 2; i++)
|
||||
CC2500_WriteReg(pgm_read_byte_near(&FRSKY_RX_d8_reg[i][0]), pgm_read_byte_near(&FRSKY_RX_d8_reg[i][1]));
|
||||
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
|
||||
break;
|
||||
}
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, 0); // bind channel
|
||||
rx_disable_lna = IS_POWER_FLAG_on;
|
||||
CC2500_SetTxRxMode(rx_disable_lna ? TXRX_OFF : RX_EN); // lna disable / enable
|
||||
frsky_rx_strobe_rx();
|
||||
FRSKY_RX_strobe_rx();
|
||||
delayMicroseconds(1000); // wait for RX to activate
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) frsky_rx_set_channel(uint8_t channel)
|
||||
static void __attribute__((unused)) FRSKY_RX_set_channel(uint8_t channel)
|
||||
{
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[channel]);
|
||||
if(frsky_rx_format == FRSKY_RX_D8)
|
||||
if(FRSKY_RX_format == FRSKY_RX_D8)
|
||||
CC2500_WriteReg(CC2500_23_FSCAL3, 0x89);
|
||||
CC2500_WriteReg(CC2500_25_FSCAL1, calData[channel]);
|
||||
frsky_rx_strobe_rx();
|
||||
FRSKY_RX_strobe_rx();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) frsky_rx_calibrate()
|
||||
static void __attribute__((unused)) FRSKY_RX_calibrate()
|
||||
{
|
||||
frsky_rx_strobe_rx();
|
||||
FRSKY_RX_strobe_rx();
|
||||
for (unsigned c = 0; c < 47; c++)
|
||||
{
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
@@ -193,7 +193,7 @@ static uint8_t __attribute__((unused)) frskyx_rx_check_crc_id(bool bind,bool ini
|
||||
uint8_t offset=bind?3:1;
|
||||
|
||||
// Check D8 checksum
|
||||
if (frsky_rx_format == FRSKY_RX_D8)
|
||||
if (FRSKY_RX_format == FRSKY_RX_D8)
|
||||
{
|
||||
if((packet[packet_length+1] & 0x80) != 0x80) // Check CRC_OK flag in status byte 2
|
||||
return false; // Bad CRC
|
||||
@@ -201,15 +201,16 @@ static uint8_t __attribute__((unused)) frskyx_rx_check_crc_id(bool bind,bool ini
|
||||
{//Save TXID
|
||||
rx_tx_addr[3] = packet[3];
|
||||
rx_tx_addr[2] = packet[4];
|
||||
rx_tx_addr[1] = packet[17];
|
||||
}
|
||||
else
|
||||
if(rx_tx_addr[3] != packet[offset] || rx_tx_addr[2] != packet[offset+1])
|
||||
if(rx_tx_addr[3] != packet[offset] || rx_tx_addr[2] != packet[offset+1] || rx_tx_addr[1] != packet[bind?17:5])
|
||||
return false; // Bad address
|
||||
return true; // Full match
|
||||
}
|
||||
|
||||
// Check D16v2 checksum
|
||||
if (frsky_rx_format == FRSKY_RX_D16v2LBT || frsky_rx_format == FRSKY_RX_D16v2FCC)
|
||||
if (FRSKY_RX_format == FRSKY_RX_D16v2LBT || FRSKY_RX_format == FRSKY_RX_D16v2FCC)
|
||||
if((packet[packet_length+1] & 0x80) != 0x80) // Check CRC_OK flag in status byte 2
|
||||
return false;
|
||||
//debugln("HW Checksum ok");
|
||||
@@ -221,12 +222,12 @@ static uint8_t __attribute__((unused)) frskyx_rx_check_crc_id(bool bind,bool ini
|
||||
return false; // Bad CRC
|
||||
//debugln("Checksum ok");
|
||||
|
||||
if (bind && (frsky_rx_format == FRSKY_RX_D16v2LBT || frsky_rx_format == FRSKY_RX_D16v2FCC))
|
||||
if (bind && (FRSKY_RX_format == FRSKY_RX_D16v2LBT || FRSKY_RX_format == FRSKY_RX_D16v2FCC))
|
||||
for(uint8_t i=3; i<packet_length-2; i++) //unXOR bind packet
|
||||
packet[i] ^= 0xA7;
|
||||
|
||||
uint8_t offset2=0;
|
||||
if (bind && (frsky_rx_format == FRSKY_RX_D16LBT || frsky_rx_format == FRSKY_RX_D16FCC))
|
||||
if (bind && (FRSKY_RX_format == FRSKY_RX_D16LBT || FRSKY_RX_format == FRSKY_RX_D16FCC))
|
||||
offset2=6;
|
||||
if(init)
|
||||
{//Save TXID
|
||||
@@ -247,7 +248,7 @@ static uint8_t __attribute__((unused)) frskyx_rx_check_crc_id(bool bind,bool ini
|
||||
return true; // Full match
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) frsky_rx_build_telemetry_packet()
|
||||
static void __attribute__((unused)) FRSKY_RX_build_telemetry_packet()
|
||||
{
|
||||
uint16_t raw_channel[8];
|
||||
uint32_t bits = 0;
|
||||
@@ -255,7 +256,7 @@ static void __attribute__((unused)) frsky_rx_build_telemetry_packet()
|
||||
uint8_t idx = 0;
|
||||
uint8_t i;
|
||||
|
||||
if (frsky_rx_format == FRSKY_RX_D8)
|
||||
if (FRSKY_RX_format == FRSKY_RX_D8)
|
||||
{// decode D8 channels
|
||||
raw_channel[0] = ((packet[10] & 0x0F) << 8 | packet[6]);
|
||||
raw_channel[1] = ((packet[10] & 0xF0) << 4 | packet[7]);
|
||||
@@ -298,7 +299,7 @@ static void __attribute__((unused)) frsky_rx_build_telemetry_packet()
|
||||
packet_in[idx++] = RX_LQI;
|
||||
packet_in[idx++] = RX_RSSI;
|
||||
packet_in[idx++] = 0; // start channel
|
||||
packet_in[idx++] = frsky_rx_format == FRSKY_RX_D8 ? 8 : 16; // number of channels in packet
|
||||
packet_in[idx++] = FRSKY_RX_format == FRSKY_RX_D8 ? 8 : 16; // number of channels in packet
|
||||
|
||||
// pack channels
|
||||
for (i = 0; i < packet_in[3]; i++) {
|
||||
@@ -312,29 +313,29 @@ static void __attribute__((unused)) frsky_rx_build_telemetry_packet()
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) frsky_rx_data()
|
||||
static void __attribute__((unused)) FRSKY_RX_data()
|
||||
{
|
||||
uint16_t temp = FRSKY_RX_EEPROM_OFFSET;
|
||||
frsky_rx_format = eeprom_read_byte((EE_ADDR)temp++) % FRSKY_RX_FORMATS;
|
||||
FRSKY_RX_format = eeprom_read_byte((EE_ADDR)temp++) % FRSKY_RX_FORMATS;
|
||||
rx_tx_addr[3] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
rx_tx_addr[2] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
rx_tx_addr[1] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
rx_tx_addr[0] = RX_num;
|
||||
frsky_rx_finetune = eeprom_read_byte((EE_ADDR)temp++);
|
||||
debug("format=%d, ", frsky_rx_format);
|
||||
FRSKY_RX_finetune = eeprom_read_byte((EE_ADDR)temp++);
|
||||
debug("format=%d, ", FRSKY_RX_format);
|
||||
debug("addr[3]=%02X, ", rx_tx_addr[3]);
|
||||
debug("addr[2]=%02X, ", rx_tx_addr[2]);
|
||||
debug("addr[1]=%02X, ", rx_tx_addr[1]);
|
||||
debug("rx_num=%02X, ", rx_tx_addr[0]);
|
||||
debugln("tune=%d", (int8_t)frsky_rx_finetune);
|
||||
if(frsky_rx_format != FRSKY_RX_D16v2LBT && frsky_rx_format != FRSKY_RX_D16v2FCC)
|
||||
debugln("tune=%d", (int8_t)FRSKY_RX_finetune);
|
||||
if(FRSKY_RX_format != FRSKY_RX_D16v2LBT && FRSKY_RX_format != FRSKY_RX_D16v2FCC)
|
||||
{//D8 & D16v1
|
||||
for (uint8_t ch = 0; ch < 47; ch++)
|
||||
hopping_frequency[ch] = eeprom_read_byte((EE_ADDR)temp++);
|
||||
}
|
||||
else
|
||||
{
|
||||
FrSkyFormat=frsky_rx_format == FRSKY_RX_D16v2FCC?0:2;
|
||||
FrSkyFormat=FRSKY_RX_format == FRSKY_RX_D16v2FCC?0:2;
|
||||
FrSkyX2_init_hop();
|
||||
}
|
||||
debug("ch:");
|
||||
@@ -342,52 +343,74 @@ static void __attribute__((unused)) frsky_rx_data()
|
||||
debug(" %02X", hopping_frequency[ch]);
|
||||
debugln("");
|
||||
|
||||
frsky_rx_initialise_cc2500();
|
||||
frsky_rx_calibrate();
|
||||
FRSKY_RX_initialise_cc2500();
|
||||
FRSKY_RX_calibrate();
|
||||
CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // FS_AUTOCAL = manual
|
||||
CC2500_WriteReg(CC2500_09_ADDR, rx_tx_addr[3]); // set address
|
||||
CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x05); // check address
|
||||
if (option == 0)
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
|
||||
else
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
frsky_rx_set_channel(hopping_frequency_no);
|
||||
FRSKY_RX_set_channel(hopping_frequency_no);
|
||||
phase = FRSKY_RX_DATA;
|
||||
}
|
||||
|
||||
uint16_t initFrSky_Rx()
|
||||
void FRSKY_RX_init()
|
||||
{
|
||||
state = 0;
|
||||
frsky_rx_chanskip = 1;
|
||||
hopping_frequency_no = 0;
|
||||
rx_data_started = false;
|
||||
frsky_rx_finetune = 0;
|
||||
telemetry_link = 0;
|
||||
packet_count = 0;
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
if(sub_protocol == FRSKY_ERASE)
|
||||
{
|
||||
frsky_rx_format = FRSKY_RX_D8;
|
||||
frsky_rx_initialise_cc2500();
|
||||
phase = FRSKY_RX_TUNE_START;
|
||||
debugln("FRSKY_RX_TUNE_START");
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{// Clear all cloned addresses
|
||||
uint16_t addr[]={ FRSKYD_CLONE_EEPROM_OFFSET+1, FRSKYX_CLONE_EEPROM_OFFSET+1, FRSKYX2_CLONE_EEPROM_OFFSET+1 };
|
||||
for(uint8_t i=0; i<3;i++)
|
||||
for(uint8_t j=0; j<3;j++)
|
||||
eeprom_write_byte((EE_ADDR)(addr[i]+j), 0xFF);
|
||||
packet_count = 100;
|
||||
}
|
||||
}
|
||||
else
|
||||
frsky_rx_data();
|
||||
return 1000;
|
||||
{
|
||||
FRSKY_RX_chanskip = 1;
|
||||
hopping_frequency_no = 0;
|
||||
rx_data_started = false;
|
||||
FRSKY_RX_finetune = 0;
|
||||
telemetry_link = 0;
|
||||
packet_count = 0;
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
FRSKY_RX_format = FRSKY_RX_D8;
|
||||
FRSKY_RX_initialise_cc2500();
|
||||
phase = FRSKY_RX_TUNE_START;
|
||||
debugln("FRSKY_RX_TUNE_START");
|
||||
}
|
||||
else
|
||||
FRSKY_RX_data();
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t FrSky_Rx_callback()
|
||||
uint16_t FRSKY_RX_callback()
|
||||
{
|
||||
static 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(sub_protocol == FRSKY_ERASE)
|
||||
{
|
||||
if(packet_count)
|
||||
packet_count--;
|
||||
else
|
||||
BIND_DONE;
|
||||
return 10000; // Nothing to do...
|
||||
}
|
||||
|
||||
if(IS_BIND_DONE && phase != FRSKY_RX_DATA)
|
||||
FRSKY_RX_init(); // Abort bind
|
||||
|
||||
if ((prev_option != option) && (phase >= FRSKY_RX_DATA))
|
||||
{
|
||||
if (option == 0)
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
|
||||
else
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
prev_option = option;
|
||||
@@ -408,19 +431,20 @@ uint16_t FrSky_Rx_callback()
|
||||
CC2500_ReadData(packet, len);
|
||||
if(frskyx_rx_check_crc_id(true,true))
|
||||
{
|
||||
frsky_rx_finetune = -127;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
|
||||
FRSKY_RX_finetune = -127;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
|
||||
phase = FRSKY_RX_TUNE_LOW;
|
||||
debugln("FRSKY_RX_TUNE_LOW");
|
||||
frsky_rx_strobe_rx();
|
||||
FRSKY_RX_strobe_rx();
|
||||
state = 0;
|
||||
return 1000;
|
||||
}
|
||||
}
|
||||
frsky_rx_format = (frsky_rx_format + 1) % FRSKY_RX_FORMATS; // switch to next format (D8, D16FCC, D16LBT, D16v2FCC, D16v2LBT)
|
||||
frsky_rx_initialise_cc2500();
|
||||
frsky_rx_finetune += 10;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
|
||||
frsky_rx_strobe_rx();
|
||||
FRSKY_RX_format = (FRSKY_RX_format + 1) % FRSKY_RX_FORMATS; // switch to next format (D8, D16FCC, D16LBT, D16v2FCC, D16v2LBT)
|
||||
FRSKY_RX_initialise_cc2500();
|
||||
FRSKY_RX_finetune += 10;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
|
||||
FRSKY_RX_strobe_rx();
|
||||
return 18000;
|
||||
|
||||
case FRSKY_RX_TUNE_LOW:
|
||||
@@ -428,18 +452,18 @@ uint16_t FrSky_Rx_callback()
|
||||
{
|
||||
CC2500_ReadData(packet, len);
|
||||
if(frskyx_rx_check_crc_id(true,false)) {
|
||||
tune_low = frsky_rx_finetune;
|
||||
frsky_rx_finetune = 127;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
|
||||
tune_low = FRSKY_RX_finetune;
|
||||
FRSKY_RX_finetune = 127;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
|
||||
phase = FRSKY_RX_TUNE_HIGH;
|
||||
debugln("FRSKY_RX_TUNE_HIGH");
|
||||
frsky_rx_strobe_rx();
|
||||
FRSKY_RX_strobe_rx();
|
||||
return 1000;
|
||||
}
|
||||
}
|
||||
frsky_rx_finetune += 1;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
|
||||
frsky_rx_strobe_rx();
|
||||
FRSKY_RX_finetune += 1;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
|
||||
FRSKY_RX_strobe_rx();
|
||||
return 18000;
|
||||
|
||||
case FRSKY_RX_TUNE_HIGH:
|
||||
@@ -447,9 +471,9 @@ uint16_t FrSky_Rx_callback()
|
||||
{
|
||||
CC2500_ReadData(packet, len);
|
||||
if(frskyx_rx_check_crc_id(true,false)) {
|
||||
tune_high = frsky_rx_finetune;
|
||||
frsky_rx_finetune = (tune_low + tune_high) / 2;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, (int8_t)frsky_rx_finetune);
|
||||
tune_high = FRSKY_RX_finetune;
|
||||
FRSKY_RX_finetune = (tune_low + tune_high) / 2;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, (int8_t)FRSKY_RX_finetune);
|
||||
if(tune_low < tune_high)
|
||||
{
|
||||
phase = FRSKY_RX_BIND;
|
||||
@@ -460,13 +484,13 @@ uint16_t FrSky_Rx_callback()
|
||||
phase = FRSKY_RX_TUNE_START;
|
||||
debugln("FRSKY_RX_TUNE_START");
|
||||
}
|
||||
frsky_rx_strobe_rx();
|
||||
FRSKY_RX_strobe_rx();
|
||||
return 1000;
|
||||
}
|
||||
}
|
||||
frsky_rx_finetune -= 1;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, frsky_rx_finetune);
|
||||
frsky_rx_strobe_rx();
|
||||
FRSKY_RX_finetune -= 1;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, FRSKY_RX_finetune);
|
||||
FRSKY_RX_strobe_rx();
|
||||
return 18000;
|
||||
|
||||
case FRSKY_RX_BIND:
|
||||
@@ -474,7 +498,7 @@ uint16_t FrSky_Rx_callback()
|
||||
{
|
||||
CC2500_ReadData(packet, len);
|
||||
if(frskyx_rx_check_crc_id(true,false)) {
|
||||
if(frsky_rx_format != FRSKY_RX_D16v2LBT && frsky_rx_format != FRSKY_RX_D16v2FCC)
|
||||
if(FRSKY_RX_format != FRSKY_RX_D16v2LBT && FRSKY_RX_format != FRSKY_RX_D16v2FCC)
|
||||
{// D8 & D16v1
|
||||
if(packet[5] <= 0x2D)
|
||||
{
|
||||
@@ -484,7 +508,7 @@ uint16_t FrSky_Rx_callback()
|
||||
}
|
||||
}
|
||||
else
|
||||
state=0x3FF; //No hop table for D16v2
|
||||
state = 0x3FF; //No hop table for D16v2
|
||||
if (state == 0x3FF)
|
||||
{
|
||||
debugln("Bind complete");
|
||||
@@ -493,27 +517,27 @@ uint16_t FrSky_Rx_callback()
|
||||
uint16_t temp = FRSKY_RX_EEPROM_OFFSET;
|
||||
if(sub_protocol==FRSKY_CLONE)
|
||||
{
|
||||
if(frsky_rx_format==FRSKY_RX_D8)
|
||||
if(FRSKY_RX_format==FRSKY_RX_D8)
|
||||
temp=FRSKYD_CLONE_EEPROM_OFFSET;
|
||||
else if(frsky_rx_format == FRSKY_RX_D16FCC || frsky_rx_format == FRSKY_RX_D16LBT)
|
||||
else if(FRSKY_RX_format == FRSKY_RX_D16FCC || FRSKY_RX_format == FRSKY_RX_D16LBT)
|
||||
temp=FRSKYX_CLONE_EEPROM_OFFSET;
|
||||
else
|
||||
temp=FRSKYX2_CLONE_EEPROM_OFFSET;
|
||||
}
|
||||
eeprom_write_byte((EE_ADDR)temp++, frsky_rx_format);
|
||||
eeprom_write_byte((EE_ADDR)temp++, FRSKY_RX_format);
|
||||
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[3]);
|
||||
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[2]);
|
||||
eeprom_write_byte((EE_ADDR)temp++, rx_tx_addr[1]);
|
||||
if(sub_protocol==FRSKY_RX)
|
||||
eeprom_write_byte((EE_ADDR)temp++, frsky_rx_finetune);
|
||||
if(frsky_rx_format != FRSKY_RX_D16v2FCC && frsky_rx_format != FRSKY_RX_D16v2LBT)
|
||||
if(sub_protocol == FRSKY_RX || sub_protocol == FRSKY_CPPM) // FRSKY_RX, FRSKY_CPPM
|
||||
eeprom_write_byte((EE_ADDR)temp++, FRSKY_RX_finetune);
|
||||
if(FRSKY_RX_format != FRSKY_RX_D16v2FCC && FRSKY_RX_format != FRSKY_RX_D16v2LBT)
|
||||
for (ch = 0; ch < 47; ch++)
|
||||
eeprom_write_byte((EE_ADDR)temp++, hopping_frequency[ch]);
|
||||
frsky_rx_data();
|
||||
FRSKY_RX_data();
|
||||
debugln("FRSKY_RX_DATA");
|
||||
}
|
||||
}
|
||||
frsky_rx_strobe_rx();
|
||||
FRSKY_RX_strobe_rx();
|
||||
}
|
||||
return 1000;
|
||||
|
||||
@@ -530,31 +554,35 @@ uint16_t FrSky_Rx_callback()
|
||||
RX_RSSI += 128;
|
||||
bool chanskip_valid=true;
|
||||
// hop to next channel
|
||||
if (frsky_rx_format != FRSKY_RX_D8)
|
||||
if (FRSKY_RX_format != FRSKY_RX_D8)
|
||||
{//D16v1 & D16v2
|
||||
if(rx_data_started)
|
||||
{
|
||||
if(frsky_rx_chanskip != (((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2)))
|
||||
if(FRSKY_RX_chanskip != (((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2)))
|
||||
{
|
||||
chanskip_valid=false; // chanskip value has changed which surely indicates a bad frame
|
||||
packet_count++;
|
||||
if(packet_count>5) // the TX must have changed chanskip...
|
||||
frsky_rx_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); // chanskip init
|
||||
FRSKY_RX_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); // chanskip init
|
||||
}
|
||||
else
|
||||
packet_count=0;
|
||||
}
|
||||
else
|
||||
frsky_rx_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); // chanskip init
|
||||
FRSKY_RX_chanskip = ((packet[4] & 0xC0) >> 6) | ((packet[5] & 0x3F) << 2); // chanskip init
|
||||
}
|
||||
hopping_frequency_no = (hopping_frequency_no + frsky_rx_chanskip) % 47;
|
||||
frsky_rx_set_channel(hopping_frequency_no);
|
||||
hopping_frequency_no = (hopping_frequency_no + FRSKY_RX_chanskip) % 47;
|
||||
FRSKY_RX_set_channel(hopping_frequency_no);
|
||||
if(chanskip_valid)
|
||||
{
|
||||
if (telemetry_link == 0)
|
||||
if ((telemetry_link & 0x7F) == 0)
|
||||
{ // send channels to TX
|
||||
frsky_rx_build_telemetry_packet();
|
||||
FRSKY_RX_build_telemetry_packet();
|
||||
telemetry_link = 1;
|
||||
#ifdef SEND_CPPM
|
||||
if(sub_protocol == FRSKY_CPPM)
|
||||
telemetry_link |= 0x80; // Disable telemetry output
|
||||
#endif
|
||||
}
|
||||
pps_counter++;
|
||||
}
|
||||
@@ -578,8 +606,8 @@ uint16_t FrSky_Rx_callback()
|
||||
|
||||
// skip channel if no packet received in time
|
||||
if (read_retry++ >= 9) {
|
||||
hopping_frequency_no = (hopping_frequency_no + frsky_rx_chanskip) % 47;
|
||||
frsky_rx_set_channel(hopping_frequency_no);
|
||||
hopping_frequency_no = (hopping_frequency_no + FRSKY_RX_chanskip) % 47;
|
||||
FRSKY_RX_set_channel(hopping_frequency_no);
|
||||
if(rx_data_started)
|
||||
read_retry = 0;
|
||||
else
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
*/
|
||||
// Last sync with main deviation/sfhss_cc2500.c dated 2016-03-23
|
||||
|
||||
#if defined(SFHSS_CC2500_INO)
|
||||
#if defined(FUTABA_CC2500_INO)
|
||||
|
||||
#include "iface_cc2500.h"
|
||||
|
||||
//#define SFHSS_DEBUG_TIMING
|
||||
|
||||
#define SFHSS_COARSE 0
|
||||
|
||||
#define SFHSS_PACKET_LEN 13
|
||||
@@ -79,7 +81,6 @@ static void __attribute__((unused)) SFHSS_rf_init()
|
||||
for (uint8_t i = 0; i < 39; ++i)
|
||||
CC2500_WriteReg(i, pgm_read_byte_near(&SFHSS_init_values[i]));
|
||||
|
||||
prev_option = option;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
@@ -125,7 +126,7 @@ static void __attribute__((unused)) SFHSS_calc_next_chan()
|
||||
// Channel values are 12-bit values between 1020 and 2020, 1520 is the middle.
|
||||
// Futaba @140% is 2070...1520...970
|
||||
// Values grow down and to the right.
|
||||
static void __attribute__((unused)) SFHSS_build_data_packet()
|
||||
static void __attribute__((unused)) SFHSS_send_packet()
|
||||
{
|
||||
uint16_t ch[4];
|
||||
// command.bit0 is the packet number indicator: =0 -> SFHSS_DATA1, =1 -> SFHSS_DATA2
|
||||
@@ -165,16 +166,14 @@ static void __attribute__((unused)) SFHSS_build_data_packet()
|
||||
// 3584-4095 -> looks to be used for the throttle channel with values ranging from 880µs to 1520µs
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
{
|
||||
ch[i]=Failsafe_data[CH_AETR[ch_offset+i]];
|
||||
if(ch[i]==FAILSAFE_CHANNEL_HOLD)
|
||||
uint16_t val=Failsafe_data[CH_AETR[ch_offset+i]];
|
||||
if(val==FAILSAFE_CHANNEL_HOLD)
|
||||
ch[i]=1024;
|
||||
else if(ch[i]==FAILSAFE_CHANNEL_NOPULSES)
|
||||
else if(val==FAILSAFE_CHANNEL_NOPULSES)
|
||||
ch[i]=0;
|
||||
else
|
||||
{ //Use channel value
|
||||
ch[i]=(ch[i]>>1)+2560;
|
||||
//if(IS_DISABLE_CH_MAP_off && ch_offset+i==CH3 && ch[i]<3072) // Throttle
|
||||
// ch[i]+=1024;
|
||||
ch[i] = convert_channel_16b_nolimit(CH_AETR[ch_offset+i],3571,2571,true); //3472,2672: not enough throw
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,7 +181,7 @@ static void __attribute__((unused)) SFHSS_build_data_packet()
|
||||
#endif
|
||||
{ //Normal data
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
ch[i] = convert_channel_16b_nolimit(CH_AETR[ch_offset+i],2020,1020);
|
||||
ch[i] = convert_channel_16b_nolimit(CH_AETR[ch_offset+i],2020,1020,false);
|
||||
}
|
||||
|
||||
|
||||
@@ -203,15 +202,17 @@ static void __attribute__((unused)) SFHSS_build_data_packet()
|
||||
packet[10] = (ch[2] << 7) | ((ch[3] >> 5) & 0x7F );
|
||||
packet[11] = (ch[3] << 3) | ((fhss_code >> 2) & 0x07 );
|
||||
packet[12] = (fhss_code << 6) | command;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SFHSS_send_packet()
|
||||
{
|
||||
CC2500_WriteData(packet, SFHSS_PACKET_LEN);
|
||||
}
|
||||
|
||||
uint16_t ReadSFHSS()
|
||||
uint16_t SFHSS_callback()
|
||||
{
|
||||
#ifdef SFHSS_DEBUG_TIMING
|
||||
static uint16_t prev_adjust_timing=1024;
|
||||
uint16_t adjust_timing = (Channel_data[CH15]>>3) - (1024>>3); // +-102 @ 100%
|
||||
#endif
|
||||
|
||||
switch(phase)
|
||||
{
|
||||
case SFHSS_START:
|
||||
@@ -238,16 +239,27 @@ uint16_t ReadSFHSS()
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(6800);
|
||||
#endif
|
||||
SFHSS_build_data_packet();
|
||||
SFHSS_send_packet();
|
||||
phase = SFHSS_DATA2;
|
||||
#ifdef SFHSS_DEBUG_TIMING
|
||||
return SFHSS_DATA2_TIMING - adjust_timing;
|
||||
#else
|
||||
return SFHSS_DATA2_TIMING; // original 1650
|
||||
#endif
|
||||
case SFHSS_DATA2:
|
||||
SFHSS_build_data_packet();
|
||||
SFHSS_send_packet();
|
||||
SFHSS_calc_next_chan();
|
||||
phase = SFHSS_TUNE;
|
||||
return (SFHSS_PACKET_PERIOD -2000 -SFHSS_DATA2_TIMING); // original 2000
|
||||
#ifdef SFHSS_DEBUG_TIMING
|
||||
if(prev_adjust_timing != adjust_timing)
|
||||
{
|
||||
debugln("A:%d",(uint16_t)(SFHSS_DATA2_TIMING - adjust_timing));
|
||||
prev_adjust_timing = adjust_timing;
|
||||
}
|
||||
return SFHSS_PACKET_PERIOD -2000 -(SFHSS_DATA2_TIMING - adjust_timing);
|
||||
#else
|
||||
return SFHSS_PACKET_PERIOD -2000 -SFHSS_DATA2_TIMING; // original 2000
|
||||
#endif
|
||||
case SFHSS_TUNE:
|
||||
phase = SFHSS_DATA1;
|
||||
SFHSS_tune_freq();
|
||||
@@ -288,7 +300,7 @@ static void __attribute__((unused)) SFHSS_get_tx_id()
|
||||
rx_tx_addr[1] = fixed_id >> 0;
|
||||
}
|
||||
|
||||
uint16_t initSFHSS()
|
||||
void SFHSS_init()
|
||||
{
|
||||
BIND_DONE; // Not a TX bind protocol
|
||||
SFHSS_get_tx_id();
|
||||
@@ -297,7 +309,6 @@ uint16_t initSFHSS()
|
||||
|
||||
SFHSS_rf_init();
|
||||
phase = SFHSS_START;
|
||||
return 10000;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -14,7 +14,7 @@ Multiprotocol is distributed in the hope that it will be useful,
|
||||
*/
|
||||
// Compatible with GD005 C-17 and GD006 DA62 planes.
|
||||
|
||||
#if defined(GD00X_NRF24L01_INO)
|
||||
#if defined(GD00X_CCNRF_INO)
|
||||
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
@@ -127,7 +127,7 @@ static void __attribute__((unused)) GD00X_send_packet()
|
||||
XN297L_SetFreqOffset(); // Set frequency offset
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) GD00X_init()
|
||||
static void __attribute__((unused)) GD00X_RF_init()
|
||||
{
|
||||
XN297L_Init();
|
||||
if(sub_protocol==GD_V1)
|
||||
@@ -204,28 +204,27 @@ static void __attribute__((unused)) GD00X_initialize_txid()
|
||||
|
||||
uint16_t GD00X_callback()
|
||||
{
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
if(--bind_counter==0)
|
||||
BIND_DONE;
|
||||
GD00X_send_packet();
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
if(bind_counter)
|
||||
if(--bind_counter==0)
|
||||
BIND_DONE;
|
||||
GD00X_send_packet();
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
uint16_t initGD00X()
|
||||
void GD00X_init()
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
GD00X_initialize_txid();
|
||||
GD00X_init();
|
||||
GD00X_RF_init();
|
||||
hopping_frequency_no = 0;
|
||||
bind_counter=GD00X_BIND_COUNT;
|
||||
packet_period=sub_protocol==GD_V1?GD00X_PACKET_PERIOD:GD00X_V2_BIND_PACKET_PERIOD;
|
||||
packet_length=sub_protocol==GD_V1?GD00X_PAYLOAD_SIZE:GD00X_V2_PAYLOAD_SIZE;
|
||||
packet_count=0;
|
||||
len=0;
|
||||
return GD00X_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -32,10 +32,10 @@ enum {
|
||||
GW008_DATA
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) GW008_send_packet(uint8_t bind)
|
||||
static void __attribute__((unused)) GW008_send_packet()
|
||||
{
|
||||
packet[0] = rx_tx_addr[0];
|
||||
if(bind)
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet[1] = 0x55;
|
||||
packet[2] = hopping_frequency[0];
|
||||
@@ -65,7 +65,7 @@ static void __attribute__((unused)) GW008_send_packet(uint8_t bind)
|
||||
|
||||
// Power on, TX mode, CRC enabled
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? GW008_RF_BIND_CHANNEL : hopping_frequency[(hopping_frequency_no++)/2]);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? GW008_RF_BIND_CHANNEL : hopping_frequency[(hopping_frequency_no++)/2]);
|
||||
hopping_frequency_no %= 8;
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
@@ -75,26 +75,13 @@ static void __attribute__((unused)) GW008_send_packet(uint8_t bind)
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) GW008_init()
|
||||
static void __attribute__((unused)) GW008_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
XN297_SetTXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
|
||||
XN297_SetRXAddr((uint8_t*)"\xcc\xcc\xcc\xcc\xcc", 5);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01);
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, GW008_PAYLOAD_SIZE+2); // payload + 2 bytes for pcf
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M);
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01); // Set feature bits on
|
||||
NRF24L01_Activate(0x73);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) GW008_initialize_txid()
|
||||
@@ -123,7 +110,7 @@ uint16_t GW008_callback()
|
||||
{
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
GW008_send_packet(1);
|
||||
GW008_send_packet();
|
||||
phase = GW008_BIND2;
|
||||
return 850; // minimum value 750 for STM32
|
||||
}
|
||||
@@ -142,20 +129,19 @@ uint16_t GW008_callback()
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(GW008_PACKET_PERIOD);
|
||||
#endif
|
||||
GW008_send_packet(0);
|
||||
GW008_send_packet();
|
||||
break;
|
||||
}
|
||||
return GW008_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initGW008()
|
||||
void GW008_init()
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
GW008_initialize_txid();
|
||||
phase = GW008_BIND1;
|
||||
GW008_init();
|
||||
GW008_RF_init();
|
||||
hopping_frequency_no = 0;
|
||||
return GW008_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -50,7 +50,7 @@ enum H8_3D_FLAGS_2 {
|
||||
H8_3D_FLAG_CAM_UP = 0x04,
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) H8_3D_send_packet(uint8_t bind)
|
||||
static void __attribute__((unused)) H8_3D_send_packet()
|
||||
{
|
||||
if(sub_protocol==H20H)
|
||||
packet[0] = 0x14;
|
||||
@@ -63,7 +63,7 @@ static void __attribute__((unused)) H8_3D_send_packet(uint8_t bind)
|
||||
packet[4] = rx_tx_addr[3];
|
||||
packet[8] = rx_tx_addr[0]+rx_tx_addr[1]+rx_tx_addr[2]+rx_tx_addr[3]; // txid checksum
|
||||
memset(&packet[9], 0, 10);
|
||||
if (bind)
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet[5] = 0x00;
|
||||
packet[6] = 0x00;
|
||||
@@ -127,13 +127,13 @@ static void __attribute__((unused)) H8_3D_send_packet(uint8_t bind)
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
if(sub_protocol!=H20H)
|
||||
{ // H8_3D, H20MINI, H30MINI
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? hopping_frequency[0] : hopping_frequency[hopping_frequency_no++]);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? hopping_frequency[0] : hopping_frequency[hopping_frequency_no++]);
|
||||
hopping_frequency_no %= H8_3D_RF_NUM_CHANNELS;
|
||||
}
|
||||
else
|
||||
{ //H20H
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? H20H_BIND_RF : hopping_frequency[packet_count>>3]);
|
||||
if(!bind)
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? H20H_BIND_RF : hopping_frequency[packet_count>>3]);
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
packet_count++;
|
||||
if(packet_count>15)
|
||||
@@ -155,47 +155,33 @@ static void __attribute__((unused)) H8_3D_send_packet(uint8_t bind)
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) H8_3D_init()
|
||||
static void __attribute__((unused)) H8_3D_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_Initialize();
|
||||
|
||||
if(sub_protocol==H20H)
|
||||
XN297_SetTXAddr((uint8_t *)"\xEE\xDD\xCC\xBB\x11", 5);
|
||||
else // H8_3D, H20MINI, H30MINI
|
||||
XN297_SetTXAddr((uint8_t *)"\xC4\x57\x09\x65\x21", 5);
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
uint16_t H8_3D_callback()
|
||||
{
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
H8_3D_send_packet(0);
|
||||
}
|
||||
else
|
||||
if(bind_counter)
|
||||
{
|
||||
bind_counter--;
|
||||
if (bind_counter == 0)
|
||||
{
|
||||
BIND_DONE;
|
||||
packet_count=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
H8_3D_send_packet(1);
|
||||
bind_counter--;
|
||||
}
|
||||
}
|
||||
#ifdef MULTI_SYNC
|
||||
else
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
|
||||
H8_3D_send_packet();
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
@@ -238,12 +224,12 @@ static void __attribute__((unused)) H8_3D_initialize_txid()
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t initH8_3D(void)
|
||||
void H8_3D_init(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
bind_counter = H8_3D_BIND_COUNT;
|
||||
H8_3D_initialize_txid();
|
||||
H8_3D_init();
|
||||
H8_3D_RF_init();
|
||||
switch(sub_protocol)
|
||||
{
|
||||
case H8_3D:
|
||||
@@ -257,7 +243,6 @@ uint16_t initH8_3D(void)
|
||||
packet_period=H20MINI_PACKET_PERIOD;
|
||||
break;
|
||||
}
|
||||
return H8_3D_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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,
|
||||
@@ -75,7 +86,6 @@ static void __attribute__((unused)) HOTT_rf_init()
|
||||
for (uint8_t i = 0; i < 39; ++i)
|
||||
CC2500_WriteReg(i, pgm_read_byte_near(&HOTT_init_values[i]));
|
||||
|
||||
prev_option = option;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
@@ -103,7 +113,7 @@ static void __attribute__((unused)) HOTT_tune_freq()
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
CC2500_WriteReg(CC2500_0F_FREQ0, HOTT_FREQ0_VAL + HOTT_COARSE);
|
||||
prev_option = option ;
|
||||
phase = HOTT_START; // Restart the tune process if option is changed to get good tuned values
|
||||
phase = HOTT_START; // Restart the tune process if option is changed to get good tuned values
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,43 +137,45 @@ const uint8_t PROGMEM HOTT_hop[][HOTT_NUM_RF_CHANNELS]=
|
||||
};
|
||||
const uint16_t PROGMEM HOTT_hop_val[] = { 0xC06B, 0xC34A, 0xDB24, 0x8E09, 0x272E, 0x217F, 0x155B, 0xEDE8, 0x1D31, 0x0986, 0x56F7, 0x6454, 0xC42D, 0x01D2, 0xC253, 0x1180 };
|
||||
|
||||
static void __attribute__((unused)) HOTT_init()
|
||||
static void __attribute__((unused)) HOTT_TXID_init()
|
||||
{
|
||||
packet[0] = pgm_read_word_near( &HOTT_hop_val[num_ch] );
|
||||
packet[1] = pgm_read_word_near( &HOTT_hop_val[num_ch] )>>8;
|
||||
|
||||
for(uint8_t i=0; i<HOTT_NUM_RF_CHANNELS; i++)
|
||||
hopping_frequency[i]=pgm_read_byte_near( &HOTT_hop[num_ch][i] );
|
||||
|
||||
#ifdef HOTT_FORCE_ID
|
||||
memcpy(rx_tx_addr,"\x7C\x94\x00\x0D\x50",5);
|
||||
memcpy(rx_tx_addr,"\x7C\x94\x00\x0D\x50",5); //TX1
|
||||
memcpy(rx_tx_addr,"\xEA\x4D\x00\x01\x50",5); //TX2
|
||||
#endif
|
||||
memset(&packet[30],0xFF,9);
|
||||
packet[39]=0x07; // unknown and constant
|
||||
packet[39]=0x07; // unknown and constant
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet[28] = 0x80; // unknown 0x80 when bind starts then when RX replies start normal, 0x89/8A/8B/8C/8D/8E during normal packets
|
||||
packet[29] = 0x02; // unknown 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets
|
||||
memset(&packet[40],0xFA,5);
|
||||
memcpy(&packet[45],rx_tx_addr,5);
|
||||
}
|
||||
else
|
||||
{
|
||||
packet[28] = 0x8C; // unknown 0x80 when bind starts then when RX replies start normal, 0x89/8A/8B/8C/8D/8E during normal packets, 0x0F->config menu
|
||||
packet[29] = 0x02; // unknown 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets, 0x01->config menu, 0x0A->no more RX telemetry
|
||||
memcpy(&packet[40],rx_tx_addr,5);
|
||||
|
||||
uint8_t addr=HOTT_EEPROM_OFFSET+RX_num*5;
|
||||
uint16_t addr=HOTT_EEPROM_OFFSET+RX_num*5;
|
||||
debug("RXID: ");
|
||||
for(uint8_t i=0;i<5;i++)
|
||||
{
|
||||
packet[45+i]=eeprom_read_byte((EE_ADDR)(addr+i));
|
||||
debug(" %02X",packet[45+i]);
|
||||
}
|
||||
debugln("");
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) HOTT_data_packet()
|
||||
static void __attribute__((unused)) HOTT_prep_data_packet()
|
||||
{
|
||||
static uint8_t upper=0;
|
||||
|
||||
packet[2] = hopping_frequency_no;
|
||||
|
||||
packet[3] = 0x00; // used for failsafe but may also be used for additional channels
|
||||
packet[3] = upper; // used for failsafe and upper channels (only supporting 16 channels)
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
static uint8_t failsafe_count=0;
|
||||
if(IS_FAILSAFE_VALUES_on && IS_BIND_DONE)
|
||||
@@ -183,13 +195,16 @@ static void __attribute__((unused)) HOTT_data_packet()
|
||||
uint16_t val;
|
||||
for(uint8_t i=4;i<28;i+=2)
|
||||
{
|
||||
val=Channel_data[(i-4)>>1];
|
||||
uint8_t ch=(i-4)>>1;
|
||||
if(upper && ch >= 8)
|
||||
ch+=4; // when upper swap CH9..CH12 by CH13..16
|
||||
val=Channel_data[ch];
|
||||
val=(((val<<2)+val)>>2)+860*2; // value range 860<->2140 *2 <-> -125%<->+125%
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
if(failsafe_count==1)
|
||||
{ // first failsafe packet
|
||||
packet[3]=0x40;
|
||||
uint16_t fs=Failsafe_data[(i-4)>>1];
|
||||
packet[3] |= 0x40;
|
||||
uint16_t fs=Failsafe_data[ch];
|
||||
if( fs == FAILSAFE_CHANNEL_HOLD || fs == FAILSAFE_CHANNEL_NOPULSES)
|
||||
val|=0x8000; // channel hold flag
|
||||
else
|
||||
@@ -200,7 +215,7 @@ static void __attribute__((unused)) HOTT_data_packet()
|
||||
}
|
||||
else if(failsafe_count==2)
|
||||
{ // second failsafe packet=timing?
|
||||
packet[3]=0x50;
|
||||
packet[3] |= 0x50;
|
||||
if(i==4)
|
||||
val=2;
|
||||
else
|
||||
@@ -210,31 +225,47 @@ static void __attribute__((unused)) HOTT_data_packet()
|
||||
packet[i] = val;
|
||||
packet[i+1] = val>>8;
|
||||
}
|
||||
|
||||
upper ^= 0x01; // toggle between CH9..CH12 and CH13..16
|
||||
|
||||
packet[28] = 0x80; // no sensor
|
||||
packet[29] = 0x02; // 0x02 when bind starts then when RX replies cycle in sequence 0x1A/22/2A/0A/12, 0x02 during normal packets, 0x01->text config menu, 0x0A->no more RX telemetry
|
||||
#ifdef HOTT_FW_TELEMETRY
|
||||
static uint8_t prev_SerialRX_val=0;
|
||||
if(HoTT_SerialRX && HoTT_SerialRX_val >= 0xD7 && HoTT_SerialRX_val <= 0xDF)
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
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
|
||||
static uint8_t prev_SerialRX_val=0;
|
||||
if(HoTT_SerialRX)
|
||||
{//Text mode
|
||||
uint8_t sensor=HoTT_SerialRX_val&0xF0;
|
||||
if((sensor&0x80) && sensor!=0xF0 && (HoTT_SerialRX_val&0x0F) >= 0x07)
|
||||
{//Valid Text query
|
||||
if(sensor==0x80) HoTT_SerialRX_val&=0x0F; // RX only
|
||||
if(prev_SerialRX_val!=HoTT_SerialRX_val)
|
||||
{
|
||||
prev_SerialRX_val=HoTT_SerialRX_val;
|
||||
packet[28] = HoTT_SerialRX_val; // send the button being pressed only once
|
||||
}
|
||||
else
|
||||
packet[28] = HoTT_SerialRX_val | 0x0F; // no button pressed
|
||||
}
|
||||
else
|
||||
packet[28] = 0x0F; // RX, no button pressed
|
||||
if(sub_protocol == HOTT_SYNC)
|
||||
packet[29] = ((HOTT_sensor_seq+1)<<3) | 1; // Telemetry packet sequence
|
||||
else
|
||||
packet[29] = 0x01; // 0x01->Text config menu
|
||||
}
|
||||
else
|
||||
packet[28] = 0xDF; // no touch pressed
|
||||
packet[29] = 0x01; // 0x01->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
|
||||
}
|
||||
//debugln("28=%02X,29=%02X",packet[28],packet[29]);
|
||||
}
|
||||
#endif
|
||||
|
||||
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++)
|
||||
@@ -246,12 +277,8 @@ static void __attribute__((unused)) HOTT_data_packet()
|
||||
rf_ch_num=hopping_frequency[hopping_frequency_no];
|
||||
}
|
||||
|
||||
uint16_t ReadHOTT()
|
||||
uint16_t HOTT_callback()
|
||||
{
|
||||
#ifdef HOTT_FW_TELEMETRY
|
||||
static uint8_t pps_counter=0;
|
||||
#endif
|
||||
|
||||
switch(phase)
|
||||
{
|
||||
case HOTT_START:
|
||||
@@ -268,47 +295,95 @@ 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)
|
||||
{// Sync 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;
|
||||
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]);
|
||||
debugln("");
|
||||
uint8_t addr=HOTT_EEPROM_OFFSET+RX_num*5;
|
||||
uint16_t addr=HOTT_EEPROM_OFFSET+RX_num*5;
|
||||
for(uint8_t i=0; i<5; i++)
|
||||
eeprom_write_byte((EE_ADDR)(addr+i),packet_in[5+i]);
|
||||
BIND_DONE;
|
||||
HOTT_init();
|
||||
HOTT_TXID_init();
|
||||
}
|
||||
#ifdef HOTT_FW_TELEMETRY
|
||||
else
|
||||
@@ -317,16 +392,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 +409,79 @@ 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;
|
||||
HOTT_sensor_seq++; // Increment RX sequence counter
|
||||
if(packet[29] & 1)
|
||||
{ //Text mode
|
||||
HOTT_sensor_seq %= 19; // 19 pages in Text mode
|
||||
HOTT_sensor_pages = 0;
|
||||
HOTT_sensor_valid = false;
|
||||
packet_in[10] = 0x80; // Marking telem Text mode
|
||||
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 %= 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("");
|
||||
telemetry_link=2;
|
||||
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,28 +492,43 @@ 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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t initHOTT()
|
||||
void HOTT_init()
|
||||
{
|
||||
num_ch=random(0xfefefefe)%16;
|
||||
HOTT_init();
|
||||
HOTT_TXID_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
|
||||
packet_sent = 0;
|
||||
phase = HOTT_START;
|
||||
return 10000;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -14,16 +14,16 @@
|
||||
*/
|
||||
// Compatible with FZ-410 TX
|
||||
|
||||
#if defined(FLYZONE_A7105_INO)
|
||||
#if defined(HEIGHT_A7105_INO)
|
||||
|
||||
#include "iface_a7105.h"
|
||||
|
||||
//#define FLYZONE_FORCEID
|
||||
//#define HEIGHT_FORCEID
|
||||
|
||||
#define FLYZONE_BIND_COUNT 220 // 5 sec
|
||||
#define FLYZONE_BIND_CH 0x18 // TX, RX for bind end is 0x17
|
||||
#define HEIGHT_BIND_COUNT 220 // 5 sec
|
||||
#define HEIGHT_BIND_CH 0x18 // TX, RX for bind end is 0x17
|
||||
|
||||
static void __attribute__((unused)) flyzone_build_packet()
|
||||
static void __attribute__((unused)) HEIGHT_build_packet()
|
||||
{
|
||||
packet[0] = 0xA5;
|
||||
packet[1] = rx_tx_addr[2];
|
||||
@@ -33,11 +33,17 @@ static void __attribute__((unused)) flyzone_build_packet()
|
||||
packet[5] = convert_channel_8b(THROTTLE); //00..FF
|
||||
packet[6] = convert_channel_8b(RUDDER); //00..80..FF
|
||||
packet[7] = convert_channel_8b(CH5); //00..80..FF
|
||||
if(sub_protocol == HEIGHT_8CH)
|
||||
{
|
||||
packet[8] = convert_channel_8b(CH6); //00..80..FF
|
||||
packet[9] = convert_channel_8b(CH7); //00..80..FF
|
||||
packet[10] = convert_channel_8b(CH8); //00..80..FF
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t ReadFlyzone()
|
||||
uint16_t HEIGHT_callback()
|
||||
{
|
||||
#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()
|
||||
void HEIGHT_init()
|
||||
{
|
||||
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,8 +93,7 @@ uint16_t initFlyzone()
|
||||
#endif
|
||||
|
||||
phase=255;
|
||||
bind_counter = FLYZONE_BIND_COUNT;
|
||||
return 2400;
|
||||
bind_counter = HEIGHT_BIND_COUNT;
|
||||
}
|
||||
#endif
|
||||
// Normal packet is 8 bytes: 0xA5 0xAF 0x59 0x84 0x7A 0x00 0x80 0xFF
|
||||
@@ -24,44 +24,7 @@
|
||||
//
|
||||
uint8_t bind_buf_arry[4][10];
|
||||
|
||||
// HiSky protocol uses TX id as an address for nRF24L01, and uses frequency hopping sequence
|
||||
// which does not depend on this id and is passed explicitly in binding sequence. So we are free
|
||||
// to generate this sequence as we wish. It should be in the range [02..77]
|
||||
static void __attribute__((unused)) calc_fh_channels()
|
||||
{
|
||||
uint8_t idx = 0;
|
||||
uint32_t rnd = MProtocol_id;
|
||||
|
||||
while (idx < HISKY_FREQUENCE_NUM)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t count_2_26 = 0, count_27_50 = 0, count_51_74 = 0;
|
||||
|
||||
rnd = rnd * 0x0019660D + 0x3C6EF35F; // Randomization
|
||||
// Use least-significant byte. 73 is prime, so channels 76..77 are unused
|
||||
uint8_t next_ch = ((rnd >> 8) % 73) + 2;
|
||||
// Keep the distance 2 between the channels - either odd or even
|
||||
if (((next_ch ^ (uint8_t)rx_tx_addr[3]) & 0x01 )== 0)
|
||||
continue;
|
||||
// Check that it's not duplicated and spread uniformly
|
||||
for (i = 0; i < idx; i++) {
|
||||
if(hopping_frequency[i] == next_ch)
|
||||
break;
|
||||
if(hopping_frequency[i] <= 26)
|
||||
count_2_26++;
|
||||
else if (hopping_frequency[i] <= 50)
|
||||
count_27_50++;
|
||||
else
|
||||
count_51_74++;
|
||||
}
|
||||
if (i != idx)
|
||||
continue;
|
||||
if ( (next_ch <= 26 && count_2_26 < 8) || (next_ch >= 27 && next_ch <= 50 && count_27_50 < 8) || (next_ch >= 51 && count_51_74 < 8) )
|
||||
hopping_frequency[idx++] = next_ch;//find hopping frequency
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) build_binding_packet(void)
|
||||
static void __attribute__((unused)) HISKY_build_binding_packet(void)
|
||||
{
|
||||
uint8_t i;
|
||||
uint16_t sum=0;
|
||||
@@ -95,28 +58,21 @@ static void __attribute__((unused)) build_binding_packet(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) hisky_init()
|
||||
static void __attribute__((unused)) HISKY_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgement
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable p0 rx
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address (byte -2)
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 81); // binding packet must be set in channel 81
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 10); // payload size = 10
|
||||
if(sub_protocol==HK310)
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
|
||||
else
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower(); // Set power
|
||||
NRF24L01_SetTxRxMode(TX_EN); // TX mode, 2-bytes CRC, radio on
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
|
||||
}
|
||||
|
||||
// HiSky channel sequence: AILE ELEV THRO RUDD GEAR PITCH, channel data value is from 0 to 1000
|
||||
// Channel 7 - Gyro mode, 0 - 6 axis, 3 - 3 axis
|
||||
static void __attribute__((unused)) build_ch_data()
|
||||
static void __attribute__((unused)) HISKY_build_ch_data()
|
||||
{
|
||||
uint16_t temp;
|
||||
uint8_t i,j;
|
||||
@@ -133,7 +89,7 @@ static void __attribute__((unused)) build_ch_data()
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t hisky_cb()
|
||||
uint16_t HISKY_callback()
|
||||
{
|
||||
phase++;
|
||||
if(sub_protocol==HK310)
|
||||
@@ -223,7 +179,7 @@ uint16_t hisky_cb()
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(9000);
|
||||
#endif
|
||||
build_ch_data();
|
||||
HISKY_build_ch_data();
|
||||
break;
|
||||
case 8:
|
||||
break;
|
||||
@@ -236,7 +192,7 @@ uint16_t hisky_cb()
|
||||
return 1000; // send 1 binding packet and 1 data packet per 9ms
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) initialize_tx_id()
|
||||
static void __attribute__((unused)) HISKY_initialize_tx_id()
|
||||
{
|
||||
//Generate frequency hopping table
|
||||
if(sub_protocol==HK310)
|
||||
@@ -248,14 +204,17 @@ static void __attribute__((unused)) initialize_tx_id()
|
||||
hopping_frequency[i]=hopping_frequency_no++; // Sequential order hop channels...
|
||||
}
|
||||
else
|
||||
calc_fh_channels();
|
||||
calc_fh_channels(HISKY_FREQUENCE_NUM);
|
||||
// HiSky air protocol uses TX id as an address for nRF24L01, and uses frequency hopping sequence
|
||||
// which does not depend on this id and is passed explicitly in binding sequence. So we are free
|
||||
// to generate this sequence as we wish. It should be in the range [02..77]
|
||||
}
|
||||
|
||||
uint16_t initHiSky()
|
||||
void HISKY_init()
|
||||
{
|
||||
initialize_tx_id();
|
||||
build_binding_packet();
|
||||
hisky_init();
|
||||
HISKY_initialize_tx_id();
|
||||
HISKY_build_binding_packet();
|
||||
HISKY_RF_init();
|
||||
phase = 0;
|
||||
hopping_frequency_no = 0;
|
||||
binding_idx = 0;
|
||||
@@ -264,7 +223,6 @@ uint16_t initHiSky()
|
||||
bind_counter = HISKY_BIND_COUNT;
|
||||
else
|
||||
bind_counter = 0;
|
||||
return 1000;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -54,7 +54,6 @@ static void __attribute__((unused)) HITEC_CC2500_init()
|
||||
for (uint8_t i = 0; i < 39; ++i)
|
||||
CC2500_WriteReg(i, pgm_read_byte_near(&HITEC_init_values[i]));
|
||||
|
||||
prev_option = option;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
@@ -165,7 +164,7 @@ static void __attribute__((unused)) HITEC_build_packet()
|
||||
packet[0] = 0x1A; // 26 bytes to follow
|
||||
for(uint8_t i=0;i<9;i++)
|
||||
{
|
||||
uint16_t ch = convert_channel_16b_nolimit(i,0x1B87,0x3905);
|
||||
uint16_t ch = convert_channel_16b_nolimit(i,0x1B87,0x3905,false);
|
||||
packet[4+2*i] = ch >> 8;
|
||||
packet[5+2*i] = ch & 0xFF;
|
||||
}
|
||||
@@ -220,7 +219,7 @@ static void __attribute__((unused)) HITEC_send_packet()
|
||||
packet[23] >>= 1; // packet sequence
|
||||
}
|
||||
|
||||
uint16_t ReadHITEC()
|
||||
uint16_t HITEC_callback()
|
||||
{
|
||||
switch(phase)
|
||||
{
|
||||
@@ -390,7 +389,7 @@ uint16_t ReadHITEC()
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t initHITEC()
|
||||
void HITEC_init()
|
||||
{
|
||||
HITEC_RF_channels();
|
||||
#ifdef HITEC_FORCE_ID // ID and channels taken from dump
|
||||
@@ -400,7 +399,6 @@ uint16_t initHITEC()
|
||||
memcpy((void *)hopping_frequency,(void *)"\x00\x3A\x4A\x32\x0C\x58\x2A\x10\x26\x20\x08\x60\x68\x70\x78\x80\x88\x56\x5E\x66\x6E",HITEC_NUM_FREQUENCE);
|
||||
#endif
|
||||
phase = HITEC_START;
|
||||
return 10000;
|
||||
}
|
||||
|
||||
/* Full telemetry
|
||||
|
||||
@@ -34,37 +34,13 @@ enum{
|
||||
HONTAI_FLAG_CALIBRATE = 0x20,
|
||||
};
|
||||
|
||||
// proudly swiped from http://www.drdobbs.com/implementing-the-ccitt-cyclical-redundan/199904926
|
||||
#define HONTAI_POLY 0x8408
|
||||
static void __attribute__((unused)) crc16(uint8_t *data_p, uint8_t length)
|
||||
static void __attribute__((unused)) HONTAI_send_packet()
|
||||
{
|
||||
uint16_t crc = 0xffff;
|
||||
|
||||
length -= 2;
|
||||
do
|
||||
{
|
||||
for (uint8_t i = 0, data = (uint8_t)*data_p++;
|
||||
i < 8;
|
||||
i++, data >>= 1)
|
||||
{
|
||||
if ((crc & 0x01) ^ (data & 0x01))
|
||||
crc = (crc >> 1) ^ HONTAI_POLY;
|
||||
else
|
||||
crc >>= 1;
|
||||
}
|
||||
} while (--length);
|
||||
|
||||
crc = ~crc;
|
||||
*data_p++ = crc & 0xff;
|
||||
*data_p = crc >> 8;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) HONTAI_send_packet(uint8_t bind)
|
||||
{
|
||||
if (bind)
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
memcpy(packet, rx_tx_addr, 5);
|
||||
memset(&packet[5], 0, 3);
|
||||
packet_length = HONTAI_BIND_PACKET_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -125,8 +101,16 @@ static void __attribute__((unused)) HONTAI_send_packet(uint8_t bind)
|
||||
packet[6] |= GET_FLAG(CH9_SW, 0x40); // Headless
|
||||
break;
|
||||
}
|
||||
packet_length = HONTAI_PACKET_SIZE;
|
||||
}
|
||||
crc16(packet, bind ? HONTAI_BIND_PACKET_SIZE:HONTAI_PACKET_SIZE);
|
||||
|
||||
// CRC 16 bits reflected in and out
|
||||
crc=0xFFFF;
|
||||
for(uint8_t i=0; i< packet_length-2; i++)
|
||||
crc16_update(bit_reverse(packet[i]),8);
|
||||
crc ^= 0xFFFF;
|
||||
packet[packet_length-2]=bit_reverse(crc>>8);
|
||||
packet[packet_length-1]=bit_reverse(crc);
|
||||
|
||||
// Power on, TX mode, 2byte CRC
|
||||
if(sub_protocol == JJRCX1)
|
||||
@@ -134,51 +118,37 @@ static void __attribute__((unused)) HONTAI_send_packet(uint8_t bind)
|
||||
else
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? HONTAI_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no++]);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? HONTAI_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no++]);
|
||||
hopping_frequency_no %= 3;
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
|
||||
if(sub_protocol == JJRCX1)
|
||||
NRF24L01_WritePayload(packet, bind ? HONTAI_BIND_PACKET_SIZE:HONTAI_PACKET_SIZE);
|
||||
NRF24L01_WritePayload(packet, packet_length);
|
||||
else
|
||||
XN297_WritePayload(packet, bind ? HONTAI_BIND_PACKET_SIZE:HONTAI_PACKET_SIZE);
|
||||
XN297_WritePayload(packet, packet_length);
|
||||
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) HONTAI_init()
|
||||
static void __attribute__((unused)) HONTAI_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
if(sub_protocol == JJRCX1)
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\xd2\xb5\x99\xb3\x4a", 5);
|
||||
else
|
||||
XN297_SetTXAddr((const uint8_t*)"\xd2\xb5\x99\xb3\x4a", 5);
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
if(sub_protocol == JJRCX1)
|
||||
{
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0xff); // JJRC uses dynamic payload length
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // match other stock settings even though AA disabled...
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07);
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x00);
|
||||
}
|
||||
NRF24L01_Activate(0x73); // Deactivate feature register
|
||||
|
||||
NRF24L01_SetTxRxMode(TX_EN); // Clear data ready, data sent, retransmit and enable CRC 16bits, ready for TX
|
||||
}
|
||||
|
||||
const uint8_t PROGMEM HONTAI_hopping_frequency_nonels[][3] = {
|
||||
@@ -231,9 +201,11 @@ static void __attribute__((unused)) HONTAI_initialize_txid()
|
||||
|
||||
uint16_t HONTAI_callback()
|
||||
{
|
||||
if(bind_counter!=0)
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
if(bind_counter)
|
||||
{
|
||||
HONTAI_send_packet(1);
|
||||
bind_counter--;
|
||||
if (bind_counter == 0)
|
||||
{
|
||||
@@ -241,24 +213,16 @@ uint16_t HONTAI_callback()
|
||||
BIND_DONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
HONTAI_send_packet(0);
|
||||
}
|
||||
|
||||
HONTAI_send_packet();
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
uint16_t initHONTAI()
|
||||
void HONTAI_init()
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
bind_counter = HONTAI_BIND_COUNT;
|
||||
HONTAI_initialize_txid();
|
||||
HONTAI_init();
|
||||
HONTAI_RF_init();
|
||||
packet_period = sub_protocol == FQ777_951 ? FQ777_951_PACKET_PERIOD : HONTAI_PACKET_PERIOD;
|
||||
return HONTAI_INITIAL_WAIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -285,7 +285,7 @@ static uint8_t __attribute__((unused)) hubsan_check_integrity()
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t ReadHubsan()
|
||||
uint16_t HUBSAN_callback()
|
||||
{
|
||||
#ifdef HUBSAN_HUB_TELEMETRY
|
||||
static uint8_t rfMode=0;
|
||||
@@ -446,7 +446,7 @@ uint16_t ReadHubsan()
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t initHubsan()
|
||||
void HUBSAN_init()
|
||||
{
|
||||
const uint8_t allowed_ch[] = {0x14, 0x1e, 0x28, 0x32, 0x3c, 0x46, 0x50, 0x5a, 0x64, 0x6e, 0x78, 0x82};
|
||||
A7105_Init();
|
||||
@@ -467,7 +467,6 @@ uint16_t initHubsan()
|
||||
}
|
||||
packet_count=0;
|
||||
bind_phase=0;
|
||||
return 10000;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -59,7 +59,7 @@ static void __attribute__((unused)) j6pro_build_data_packet()
|
||||
packet[0] = 0xaa; //FIXME what is this?
|
||||
for (i = 0; i < 12; i++)
|
||||
{
|
||||
value = convert_channel_10b(CH_AETR[i]);
|
||||
value = convert_channel_10b(CH_AETR[i], false);
|
||||
packet[i+1] = value & 0xff;
|
||||
upperbits |= (value >> 8) << (i * 2);
|
||||
}
|
||||
@@ -111,8 +111,8 @@ static void __attribute__((unused)) cyrf_datainit()
|
||||
{
|
||||
/* Use when already bound */
|
||||
uint8_t sop_idx = (0xff & (cyrfmfg_id[0] + cyrfmfg_id[1] + cyrfmfg_id[2] + cyrfmfg_id[3] - cyrfmfg_id[5])) % 19;
|
||||
uint16_t crc = (0xff & (cyrfmfg_id[1] - cyrfmfg_id[4] + cyrfmfg_id[5])) |
|
||||
((0xff & (cyrfmfg_id[2] + cyrfmfg_id[3] - cyrfmfg_id[4] + cyrfmfg_id[5])) << 8);
|
||||
crc = (0xff & (cyrfmfg_id[1] - cyrfmfg_id[4] + cyrfmfg_id[5])) |
|
||||
((0xff & (cyrfmfg_id[2] + cyrfmfg_id[3] - cyrfmfg_id[4] + cyrfmfg_id[5])) << 8);
|
||||
//CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24);
|
||||
CYRF_PROGMEM_ConfigSOPCode(DEVO_j6pro_sopcodes[sop_idx]);
|
||||
CYRF_ConfigCRCSeed(crc);
|
||||
@@ -126,7 +126,7 @@ static void __attribute__((unused)) j6pro_set_radio_channels()
|
||||
hopping_frequency[3] = hopping_frequency[0];
|
||||
}
|
||||
|
||||
uint16_t ReadJ6Pro()
|
||||
uint16_t J6PRO_callback()
|
||||
{
|
||||
uint16_t start;
|
||||
|
||||
@@ -226,7 +226,7 @@ uint16_t ReadJ6Pro()
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t initJ6Pro()
|
||||
void J6PRO_init()
|
||||
{
|
||||
j6pro_cyrf_init();
|
||||
|
||||
@@ -234,7 +234,6 @@ uint16_t initJ6Pro()
|
||||
phase = J6PRO_BIND;
|
||||
else
|
||||
phase = J6PRO_CHANSEL;
|
||||
return 2400;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
186
Multiprotocol/JJRC345_nrf24l01.ino
Normal file
186
Multiprotocol/JJRC345_nrf24l01.ino
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
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_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
uint16_t JJRC345_callback()
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(JJRC345_PACKET_PERIOD);
|
||||
#endif
|
||||
if(bind_counter)
|
||||
{
|
||||
bind_counter--;
|
||||
if (bind_counter==0)
|
||||
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
|
||||
}
|
||||
|
||||
void JJRC345_init(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
bind_counter = JJRC345_BIND_COUNT;
|
||||
JJRC345_initialize_txid();
|
||||
JJRC345_RF_init();
|
||||
}
|
||||
|
||||
#endif
|
||||
115
Multiprotocol/Joysway_a7105.ino
Normal file
115
Multiprotocol/Joysway_a7105.ino
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(JOYSWAY_A7105_INO)
|
||||
|
||||
#include "iface_a7105.h"
|
||||
|
||||
//#define JOYSWAY_FORCE_ID
|
||||
|
||||
static void __attribute__((unused)) JOYSWAY_send_packet()
|
||||
{
|
||||
static uint8_t next_ch = 0x30;
|
||||
|
||||
//RF frequency
|
||||
if (packet_count == 254)
|
||||
{
|
||||
packet_count = 0;
|
||||
A7105_WriteID(0x5475c52a);
|
||||
rf_ch_num = 0x0a;
|
||||
}
|
||||
else if (packet_count == 2)
|
||||
{
|
||||
A7105_WriteID(MProtocol_id);
|
||||
rf_ch_num = 0x30;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (packet_count & 0x01)
|
||||
rf_ch_num = 0x30;
|
||||
else
|
||||
rf_ch_num = next_ch;
|
||||
}
|
||||
if (! (packet_count & 0x01))
|
||||
{
|
||||
next_ch++;
|
||||
if (next_ch >= 0x45)
|
||||
next_ch = 0x30;
|
||||
}
|
||||
|
||||
//Payload
|
||||
packet[0] = packet_count == 0 ? 0xdd : 0xff;
|
||||
//ID
|
||||
packet[1] = rx_tx_addr[0];
|
||||
packet[2] = rx_tx_addr[1];
|
||||
packet[3] = rx_tx_addr[2];
|
||||
packet[4] = rx_tx_addr[3];
|
||||
packet[5] = 0x00;
|
||||
//Channels
|
||||
for (uint8_t i = 0; i < 4; i++)
|
||||
packet[ 6 + (i & 0x01) + ((i & 0x02)<<1)] = convert_channel_16b_limit(i, 0x00, 0xCC);
|
||||
packet[8] = 0x64;
|
||||
packet[9] = 0x64;
|
||||
packet[12] = 0x64;
|
||||
packet[13] = 0x64;
|
||||
packet[14] = packet_count == 0 ? 0x30 : 0xaa;
|
||||
//Check
|
||||
uint8_t value = 0;
|
||||
for (uint8_t i = 0; i < 15; i++)
|
||||
value += packet[i];
|
||||
packet[15] = value;
|
||||
|
||||
//Send
|
||||
#if 0
|
||||
debug("ch=%02X P=",rf_ch_num);
|
||||
for(uint8_t i=0; i<16; i++)
|
||||
debug("%02X ", packet[i]);
|
||||
debugln("");
|
||||
#endif
|
||||
A7105_WriteData(16, rf_ch_num);
|
||||
A7105_SetPower();
|
||||
packet_count++;
|
||||
}
|
||||
|
||||
uint16_t JOYSWAY_callback()
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(6000);
|
||||
#endif
|
||||
#ifndef FORCE_JOYSWAY_TUNING
|
||||
A7105_AdjustLOBaseFreq(1);
|
||||
#endif
|
||||
|
||||
JOYSWAY_send_packet();
|
||||
return 6000;
|
||||
}
|
||||
|
||||
void JOYSWAY_init()
|
||||
{
|
||||
BIND_DONE; // not a bind protocol
|
||||
|
||||
MProtocol_id &= 0x00FFFFFF;
|
||||
MProtocol_id |= 0xF8000000;
|
||||
#ifdef JOYSWAY_FORCE_ID
|
||||
MProtocol_id = 0xf82dcaa0;
|
||||
#endif
|
||||
|
||||
set_rx_tx_addr(MProtocol_id);
|
||||
|
||||
A7105_Init();
|
||||
|
||||
packet_count = 2;
|
||||
}
|
||||
#endif
|
||||
@@ -14,7 +14,7 @@ Multiprotocol is distributed in the hope that it will be useful,
|
||||
*/
|
||||
// Compatible with KF606 plane.
|
||||
|
||||
#if defined(KF606_NRF24L01_INO)
|
||||
#if defined(KF606_CCNRF_INO)
|
||||
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
@@ -76,7 +76,7 @@ static void __attribute__((unused)) KF606_initialize_txid()
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) KF606_init()
|
||||
static void __attribute__((unused)) KF606_RF_init()
|
||||
{
|
||||
XN297L_Init();
|
||||
XN297L_SetTXAddr((uint8_t*)"\xe7\xe7\xe7\xe7\xe7", 5);
|
||||
@@ -89,24 +89,23 @@ uint16_t KF606_callback()
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(KF606_PACKET_PERIOD);
|
||||
#endif
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
if(bind_counter)
|
||||
if(--bind_counter==0)
|
||||
{
|
||||
BIND_DONE;
|
||||
XN297_SetTXAddr(rx_tx_addr, 3);
|
||||
XN297L_SetTXAddr(rx_tx_addr, 3);
|
||||
}
|
||||
KF606_send_packet();
|
||||
return KF606_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initKF606()
|
||||
void KF606_init()
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
KF606_initialize_txid();
|
||||
KF606_init();
|
||||
KF606_RF_init();
|
||||
hopping_frequency_no = 0;
|
||||
bind_counter=KF606_BIND_COUNT;
|
||||
return KF606_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -125,16 +125,16 @@ static void __attribute__((unused)) kn_bind_init()
|
||||
static void __attribute__((unused)) kn_update_packet_control_data()
|
||||
{
|
||||
uint16_t value;
|
||||
value = convert_channel_10b(THROTTLE);
|
||||
value = convert_channel_10b(THROTTLE, false);
|
||||
packet[0] = (value >> 8) & 0xFF;
|
||||
packet[1] = value & 0xFF;
|
||||
value = convert_channel_10b(AILERON);
|
||||
value = convert_channel_10b(AILERON, false);
|
||||
packet[2] = (value >> 8) & 0xFF;
|
||||
packet[3] = value & 0xFF;
|
||||
value = convert_channel_10b(ELEVATOR);
|
||||
value = convert_channel_10b(ELEVATOR, false);
|
||||
packet[4] = (value >> 8) & 0xFF;
|
||||
packet[5] = value & 0xFF;
|
||||
value = convert_channel_10b(RUDDER);
|
||||
value = convert_channel_10b(RUDDER, false);
|
||||
packet[6] = (value >> 8) & 0xFF;
|
||||
packet[7] = value & 0xFF;
|
||||
// Trims, middle is 0x64 (100) range 0-200
|
||||
@@ -239,40 +239,25 @@ static void __attribute__((unused)) kn_calculate_freqency_hopping_channels()
|
||||
// V977 needs payload length in the packet. We should configure 24L01 to enable Packet Control Field(PCF)
|
||||
// Some RX reg settings are actually for enable PCF
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static void __attribute__((unused)) kn_init()
|
||||
static void __attribute__((unused)) KN_RF_init()
|
||||
{
|
||||
kn_calculate_tx_addr();
|
||||
kn_calculate_freqency_hopping_channels();
|
||||
|
||||
NRF24L01_Initialize();
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0); // Disable retransmit
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, 0x20); // bytes of data payload for pipe 0
|
||||
|
||||
|
||||
NRF24L01_Activate(0x73);
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 1); // Dynamic payload for data pipe 0
|
||||
// Enable: Dynamic Payload Length to enable PCF
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, _BV(NRF2401_1D_EN_DPL));
|
||||
|
||||
NRF24L01_SetPower();
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
// Turn radio power on
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); //USE1MBPS_YES ? NRF24L01_BR_1M : NRF24L01_BR_250K;
|
||||
NRF24L01_SetTxRxMode(TX_EN); // Clear data ready, data sent, retransmit and enable CRC 16bits, ready for TX
|
||||
}
|
||||
|
||||
//================================================================================================
|
||||
// Private Functions
|
||||
//================================================================================================
|
||||
uint16_t initKN()
|
||||
void KN_init()
|
||||
{
|
||||
if(sub_protocol==WLTOYS)
|
||||
{
|
||||
@@ -288,13 +273,11 @@ uint16_t initKN()
|
||||
packet_count = KN_FX_PACKET_SEND_COUNT;
|
||||
seed = KN_FX_PACKET_SEND_COUNT * KN_FX_SENDING_PACKET_PERIOD;
|
||||
}
|
||||
kn_init();
|
||||
KN_RF_init();
|
||||
phase = IS_BIND_IN_PROGRESS ? KN_PHASE_PRE_BIND : KN_PHASE_PRE_SEND;
|
||||
|
||||
return KN_INIT_WAIT_MS;
|
||||
}
|
||||
|
||||
uint16_t kn_callback()
|
||||
uint16_t KN_callback()
|
||||
{
|
||||
switch (phase)
|
||||
{
|
||||
|
||||
201
Multiprotocol/Kyosho_a7105.ino
Normal file
201
Multiprotocol/Kyosho_a7105.ino
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
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 KYOSHO_callback()
|
||||
{
|
||||
#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;
|
||||
}
|
||||
|
||||
void KYOSHO_init()
|
||||
{
|
||||
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
|
||||
}
|
||||
#endif
|
||||
300
Multiprotocol/LOLI_nrf24l01.ino
Normal file
300
Multiprotocol/LOLI_nrf24l01.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(LOLI_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#define LOLI_BIND_CHANNEL 33
|
||||
#define LOLI_PACKET_SIZE 11
|
||||
#define LOLI_NUM_CHANNELS 5
|
||||
|
||||
static void __attribute__((unused)) LOLI_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"LOVE!", 5);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"LOVE!", 5);
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, LOLI_PACKET_SIZE); // RX FIFO size
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
|
||||
}
|
||||
|
||||
// flags going to packet[1] for packet type 0xa2 (Rx config)
|
||||
#define LOLI_FLAG_PWM7 0x02
|
||||
#define LOLI_FLAG_PWM2 0x04
|
||||
#define LOLI_FLAG_PWM1 0x08
|
||||
#define LOLI_FLAG_SBUS 0x40
|
||||
#define LOLI_FLAG_PPM 0x80
|
||||
|
||||
// flags going to packet[2] for packet type 0xa2 (Rx config)
|
||||
#define LOLI_FLAG_SW8 0x01
|
||||
#define LOLI_FLAG_SW7 0x02
|
||||
#define LOLI_FLAG_SW6 0x04
|
||||
#define LOLI_FLAG_SW5 0x08
|
||||
#define LOLI_FLAG_SW4 0x10
|
||||
#define LOLI_FLAG_SW3 0x20
|
||||
#define LOLI_FLAG_SW2 0x40
|
||||
#define LOLI_FLAG_SW1 0x80
|
||||
|
||||
#ifdef LOLI_NRF24L01_INO
|
||||
uint8_t LOLI_P1, LOLI_P2;
|
||||
#endif
|
||||
|
||||
static void __attribute__((unused)) LOLI_send_packet()
|
||||
{
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet[0] = 0xa0;
|
||||
memcpy(&packet[1], hopping_frequency, LOLI_NUM_CHANNELS);
|
||||
memcpy(&packet[6], rx_tx_addr, 5);
|
||||
rf_ch_num = LOLI_BIND_CHANNEL;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Check RX config
|
||||
uint8_t P1=0;
|
||||
uint8_t P2=0;
|
||||
//ch1: PWM/PPM
|
||||
if(Channel_data[CH1+8] > CHANNEL_MAX_COMMAND)
|
||||
P1|=LOLI_FLAG_PWM1;
|
||||
else if(Channel_data[CH1+8] > CHANNEL_SWITCH)
|
||||
P1|=LOLI_FLAG_PPM;
|
||||
//ch2: PWM
|
||||
if(Channel_data[CH2+8] > CHANNEL_MAX_COMMAND)
|
||||
P1|=LOLI_FLAG_PWM2;
|
||||
//ch5: SBUS
|
||||
if(Channel_data[CH5+8] > CHANNEL_SWITCH)
|
||||
P1|=LOLI_FLAG_SBUS;
|
||||
//ch7: PWM
|
||||
if(Channel_data[CH7+8] > CHANNEL_MAX_COMMAND)
|
||||
P1|=LOLI_FLAG_PWM7;
|
||||
|
||||
//switches
|
||||
for(uint8_t i=0;i<8;i++)
|
||||
if(Channel_data[i+8]<CHANNEL_MIN_COMMAND)
|
||||
P2 |= 1 << (7-i);
|
||||
|
||||
if(LOLI_P1!=P1 || LOLI_P2!=P2)
|
||||
flags=10;
|
||||
if(flags)
|
||||
{// Send RX config since P1 or P2 have changed
|
||||
LOLI_P1=P1;LOLI_P2=P2;
|
||||
packet[0] = 0xa2;
|
||||
packet[1] = LOLI_P1; // CH1:LOLI_FLAG_PPM || LOLI_FLAG_PWM1, CH2:LOLI_FLAG_PWM2, CH5:LOLI_FLAG_SBUS, CH7:LOLI_FLAG_PWM7
|
||||
packet[2] = LOLI_P2; // CHx switch bit(8-x)=1
|
||||
flags--;
|
||||
}
|
||||
else
|
||||
{// Normal packet
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
packet[0] = IS_FAILSAFE_VALUES_on ? 0xa0 : 0xa1;
|
||||
#else
|
||||
packet[0] = 0xa1;
|
||||
#endif
|
||||
|
||||
//Build channels
|
||||
uint8_t ch=0, offset=1;
|
||||
uint16_t val;
|
||||
for(uint8_t i=0;i<2;i++)
|
||||
{
|
||||
val = convert_channel_10b(ch++, IS_FAILSAFE_VALUES_on);
|
||||
packet[offset++] = val >> 2;
|
||||
packet[offset ] = val << 6;
|
||||
val = convert_channel_10b(ch++, IS_FAILSAFE_VALUES_on);
|
||||
packet[offset++]|= val >> 4;
|
||||
packet[offset ] = val << 4;
|
||||
val = convert_channel_10b(ch++, IS_FAILSAFE_VALUES_on);
|
||||
packet[offset++]|= val >> 6;
|
||||
packet[offset ] = val << 2;
|
||||
val = convert_channel_10b(ch++, IS_FAILSAFE_VALUES_on);
|
||||
packet[offset++]|= val >> 8;
|
||||
packet[offset++] = val & 0xff;
|
||||
}
|
||||
FAILSAFE_VALUES_off; // Failsafe values are sent if they were available
|
||||
}
|
||||
|
||||
if (++hopping_frequency_no > LOLI_NUM_CHANNELS-1)
|
||||
hopping_frequency_no = 0;
|
||||
rf_ch_num = hopping_frequency[hopping_frequency_no];
|
||||
}
|
||||
|
||||
#if 0
|
||||
debug("P(%02X):",rf_ch_num);
|
||||
for(uint8_t i=0; i<LOLI_PACKET_SIZE; i++)
|
||||
debug(" %02X",packet[i]);
|
||||
debugln("");
|
||||
#endif
|
||||
|
||||
//Send packet
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, rf_ch_num);
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0a); // 8bit CRC, TX
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WritePayload(packet, LOLI_PACKET_SIZE);
|
||||
}
|
||||
|
||||
enum{
|
||||
LOLI_BIND1,
|
||||
LOLI_BIND2,
|
||||
LOLI_BIND3,
|
||||
LOLI_PREP_DATA,
|
||||
LOLI_DATA1,
|
||||
LOLI_DATA2,
|
||||
LOLI_SET_RX_CONFIG,
|
||||
LOLI_SET_FAILSAFE
|
||||
};
|
||||
|
||||
#define LOLI_WRITE_TIME 1000
|
||||
|
||||
uint16_t LOLI_callback()
|
||||
{
|
||||
switch (phase)
|
||||
{
|
||||
case LOLI_BIND1:
|
||||
if(bind_counter)
|
||||
if(--bind_counter==0)
|
||||
{
|
||||
phase=LOLI_PREP_DATA;
|
||||
break;
|
||||
}
|
||||
// send bind packet
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0a); // 8bit CRC, TX
|
||||
LOLI_send_packet();
|
||||
phase++;
|
||||
return 2000;
|
||||
case LOLI_BIND2:
|
||||
// switch to RX mode
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x3b); // 8bit CRC, RX
|
||||
phase++;
|
||||
packet_count = 0;
|
||||
return 2000;
|
||||
case LOLI_BIND3:
|
||||
// got bind response ?
|
||||
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{
|
||||
NRF24L01_ReadPayload(packet, LOLI_PACKET_SIZE);
|
||||
if (packet[0] == 'O' && packet[1] == 'K')
|
||||
{
|
||||
debugln("Bind OK");
|
||||
phase++; // LOLI_PREP_DATA
|
||||
break;
|
||||
}
|
||||
}
|
||||
packet_count++;
|
||||
if (packet_count > 50)
|
||||
phase = LOLI_BIND1;
|
||||
return 1000;
|
||||
|
||||
case LOLI_PREP_DATA:
|
||||
BIND_DONE;
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, rx_tx_addr, 5);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, rx_tx_addr, 5);
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushRx();
|
||||
packet_count = 0;
|
||||
//defaut RX config with servo outputs
|
||||
LOLI_P1=0;LOLI_P2=0;flags=10;
|
||||
phase++;
|
||||
|
||||
case LOLI_DATA1:
|
||||
#ifdef LOLI_HUB_TELEMETRY
|
||||
// Check telemetry
|
||||
if (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{ // RX fifo data ready
|
||||
NRF24L01_ReadPayload(packet, LOLI_PACKET_SIZE);
|
||||
#if 0
|
||||
debug("T:");
|
||||
for(uint8_t i=0; i<LOLI_PACKET_SIZE; i++)
|
||||
debug(" %02X",packet[i]);
|
||||
debugln("");
|
||||
#endif
|
||||
RX_RSSI = packet[0]<<1;
|
||||
uint16_t val=((packet[1] << 8) | packet[2])/10;
|
||||
if(val > 255) val=255;
|
||||
v_lipo1 = val;
|
||||
val=((packet[3] << 8) | packet[4])/10;
|
||||
if(val > 255) val=255;
|
||||
v_lipo2 = val;
|
||||
telemetry_link = 1;
|
||||
telemetry_counter++; // TX LQI counter
|
||||
if(telemetry_lost)
|
||||
{
|
||||
telemetry_lost = 0;
|
||||
packet_count = 100;
|
||||
telemetry_counter = 100;
|
||||
}
|
||||
}
|
||||
//LQI
|
||||
packet_count++;
|
||||
if(packet_count>=100)
|
||||
{
|
||||
packet_count=0;
|
||||
TX_LQI=telemetry_counter;
|
||||
if(telemetry_counter==0)
|
||||
telemetry_lost = 1;
|
||||
telemetry_counter = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Send data packet
|
||||
LOLI_send_packet();
|
||||
|
||||
#ifdef LOLI_HUB_TELEMETRY
|
||||
phase ++;
|
||||
return LOLI_WRITE_TIME;
|
||||
case LOLI_DATA2:
|
||||
// Wait for packet to be sent
|
||||
while( (NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS)) == 0);
|
||||
// Switch to RX mode
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_SetTxRxMode(RX_EN);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x3b); // 8bit CRC, RX
|
||||
phase = LOLI_DATA1;
|
||||
return 20000 - LOLI_WRITE_TIME;
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return 20000;
|
||||
}
|
||||
|
||||
void LOLI_init()
|
||||
{
|
||||
rx_tx_addr[1] %= 0x30;
|
||||
calc_fh_channels(LOLI_NUM_CHANNELS);
|
||||
for (uint8_t i=0; i < LOLI_NUM_CHANNELS; i++)
|
||||
if (hopping_frequency[i] == LOLI_BIND_CHANNEL)
|
||||
hopping_frequency[i]++;
|
||||
|
||||
if (IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
bind_counter=250;
|
||||
phase = LOLI_BIND1;
|
||||
}
|
||||
else
|
||||
phase = LOLI_PREP_DATA;
|
||||
|
||||
LOLI_RF_init();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -223,7 +223,7 @@ static void __attribute__((unused)) MJXQ_send_packet(uint8_t bind)
|
||||
hopping_frequency_no %= 2 * MJXQ_RF_NUM_CHANNELS; // channels repeated
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) MJXQ_init()
|
||||
static void __attribute__((unused)) MJXQ_RF_init()
|
||||
{
|
||||
uint8_t addr[MJXQ_ADDRESS_LENGTH];
|
||||
memcpy(addr, "\x6d\x6a\x77\x77\x77", MJXQ_ADDRESS_LENGTH);
|
||||
@@ -246,25 +246,15 @@ static void __attribute__((unused)) MJXQ_init()
|
||||
else
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
if (sub_protocol == H26D || sub_protocol == H26WH)
|
||||
{
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr, MJXQ_ADDRESS_LENGTH);
|
||||
}
|
||||
else
|
||||
XN297_SetTXAddr(addr, MJXQ_ADDRESS_LENGTH);
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, MJXQ_PACKET_SIZE);
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,14 +340,13 @@ uint16_t MJXQ_callback()
|
||||
return MJXQ_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initMJXQ(void)
|
||||
void MJXQ_init(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
bind_counter = MJXQ_BIND_COUNT;
|
||||
MJXQ_initialize_txid();
|
||||
MJXQ_init();
|
||||
MJXQ_RF_init();
|
||||
packet_count=0;
|
||||
return MJXQ_INITIAL_WAIT+MJXQ_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
608
Multiprotocol/MLINK_cyrf6936.ino
Normal file
608
Multiprotocol/MLINK_cyrf6936.ino
Normal file
@@ -0,0 +1,608 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(MLINK_CYRF6936_INO)
|
||||
|
||||
#include "iface_cyrf6936.h"
|
||||
|
||||
//#define MLINK_FORCE_ID
|
||||
#define MLINK_BIND_COUNT 696 // around 20s
|
||||
#define MLINK_NUM_FREQ 78
|
||||
#define MLINK_BIND_CHANNEL 0x01
|
||||
#define MLINK_PACKET_SIZE 8
|
||||
|
||||
enum {
|
||||
MLINK_BIND_TX=0,
|
||||
MLINK_BIND_PREP_RX,
|
||||
MLINK_BIND_RX,
|
||||
MLINK_PREP_DATA,
|
||||
MLINK_SEND1,
|
||||
MLINK_SEND2,
|
||||
MLINK_SEND3,
|
||||
MLINK_CHECK3,
|
||||
MLINK_RX,
|
||||
MLINK_BUILD4,
|
||||
};
|
||||
|
||||
uint8_t MLINK_Data_Code[16], MLINK_CRC_Init, MLINK_Unk_6_2;
|
||||
|
||||
const uint8_t PROGMEM MLINK_init_vals[][2] = {
|
||||
//Init from dump
|
||||
{ CYRF_01_TX_LENGTH, 0x08 }, // Length of packet
|
||||
{ CYRF_02_TX_CTRL, 0x40 }, // Clear TX Buffer
|
||||
{ CYRF_03_TX_CFG, 0x3C }, //0x3E in normal mode, 0x3C in bind mode: SDR 64 chip codes (=8 bytes data code used)
|
||||
{ CYRF_05_RX_CTRL, 0x00 },
|
||||
{ CYRF_06_RX_CFG, 0x93 }, // AGC enabled, overwrite enable, valid flag enable
|
||||
{ CYRF_0B_PWR_CTRL, 0x00 },
|
||||
//{ CYRF_0C_XTAL_CTRL, 0x00 }, // Set to GPIO on reset
|
||||
//{ CYRF_0D_IO_CFG, 0x00 }, // Set to GPIO on reset
|
||||
//{ CYRF_0E_GPIO_CTRL, 0x00 }, // Set by the CYRF_SetTxRxMode function
|
||||
{ CYRF_0F_XACT_CFG, 0x04 }, // end state idle
|
||||
{ CYRF_10_FRAMING_CFG, 0x00 }, // SOP disabled
|
||||
{ CYRF_11_DATA32_THOLD, 0x05 }, // not used???
|
||||
{ CYRF_12_DATA64_THOLD, 0x0F }, // 64 Chip Data PN Code Correlator Threshold
|
||||
{ CYRF_14_EOP_CTRL, 0x05 }, // 5 consecutive noncorrelations symbol for EOP
|
||||
{ CYRF_15_CRC_SEED_LSB, 0x00 }, // not used???
|
||||
{ CYRF_16_CRC_SEED_MSB, 0x00 }, // not used???
|
||||
{ CYRF_1B_TX_OFFSET_LSB,0x00 },
|
||||
{ CYRF_1C_TX_OFFSET_MSB,0x00 },
|
||||
{ CYRF_1D_MODE_OVERRIDE,0x00 },
|
||||
{ CYRF_1E_RX_OVERRIDE, 0x14 }, // RX CRC16 is disabled and Force Receive Data Rate
|
||||
{ CYRF_1F_TX_OVERRIDE, 0x04 }, // TX CRC16 is disabled
|
||||
{ CYRF_26_XTAL_CFG, 0x08 },
|
||||
{ CYRF_29_RX_ABORT, 0x00 },
|
||||
{ CYRF_32_AUTO_CAL_TIME,0x3C },
|
||||
{ CYRF_35_AUTOCAL_OFFSET,0x14 },
|
||||
{ CYRF_39_ANALOG_CTRL, 0x03 }, // Receive invert and all slow
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) MLINK_cyrf_config()
|
||||
{
|
||||
for(uint8_t i = 0; i < sizeof(MLINK_init_vals) / 2; i++)
|
||||
CYRF_WriteRegister(pgm_read_byte_near(&MLINK_init_vals[i][0]), pgm_read_byte_near(&MLINK_init_vals[i][1]));
|
||||
CYRF_WritePreamble(0x333304);
|
||||
CYRF_SetTxRxMode(TX_EN);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) MLINK_send_bind_packet()
|
||||
{
|
||||
uint8_t p_c=packet_count>>1;
|
||||
|
||||
memset(packet, p_c<0x16?0x00:0xFF, MLINK_PACKET_SIZE-1);
|
||||
packet[0]=0x0F; // bind
|
||||
packet[1]=p_c;
|
||||
switch(p_c)
|
||||
{
|
||||
case 0x00:
|
||||
packet[2]=0x40; //unknown but seems constant
|
||||
packet[4]=0x01; //unknown but seems constant
|
||||
packet[5]=0x03; //unknown but seems constant
|
||||
packet[6]=0xE3; //unknown but seems constant
|
||||
break;
|
||||
case 0x05:
|
||||
packet[6]=MLINK_CRC_Init; //CRC init value
|
||||
break;
|
||||
case 0x06:
|
||||
packet[2]=MLINK_Unk_6_2; //unknown and different
|
||||
//Start of hopping frequencies
|
||||
for(uint8_t i=0;i<4;i++)
|
||||
packet[i+3]=hopping_frequency[i];
|
||||
break;
|
||||
case 0x15:
|
||||
packet[6]=0x51; //unknown but seems constant
|
||||
break;
|
||||
case 0x16:
|
||||
packet[2]=0x51; //unknown but seems constant
|
||||
packet[3]=0xEC; //unknown but seems constant
|
||||
packet[4]=0x05; //unknown but seems constant
|
||||
break;
|
||||
case 0x1A:
|
||||
packet[1]=0xFF;
|
||||
memset(&packet[2],0x00,5);
|
||||
break;
|
||||
}
|
||||
if(p_c>=0x01 && p_c<=0x04)
|
||||
{//DATA_CODE
|
||||
uint8_t p_c_5=(p_c-1)*5;
|
||||
for(uint8_t i=0;i<5;i++)
|
||||
if(i+p_c_5<16)
|
||||
packet[i+2]=MLINK_Data_Code[i+p_c_5];
|
||||
}
|
||||
else
|
||||
if(p_c>=0x07 && p_c<=0x15)
|
||||
{//Hopping frequencies
|
||||
uint8_t p_c_5=5*(p_c-6)-1;
|
||||
for(uint8_t i=0;i<5;i++)
|
||||
if(i+p_c_5<MLINK_NUM_FREQ)
|
||||
packet[i+2]=hopping_frequency[i+p_c_5];
|
||||
}
|
||||
else
|
||||
if(p_c>0x19)
|
||||
{
|
||||
packet[1]=0xFF;
|
||||
memset(&packet[2], 0x00, MLINK_PACKET_SIZE-3);
|
||||
}
|
||||
|
||||
//Calculate CRC
|
||||
crc8=0xFF; // Init = 0xFF
|
||||
for(uint8_t i=0;i<MLINK_PACKET_SIZE-1;i++)
|
||||
crc8_update(bit_reverse(packet[i]));
|
||||
packet[7] = bit_reverse(crc8); // CRC reflected out
|
||||
|
||||
//Debug
|
||||
#if 0
|
||||
debug("P(%02d):",p_c);
|
||||
for(uint8_t i=0;i<8;i++)
|
||||
debug(" %02X",packet[i]);
|
||||
debugln("");
|
||||
#endif
|
||||
|
||||
//Send packet
|
||||
CYRF_WriteDataPacketLen(packet, MLINK_PACKET_SIZE);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) MLINK_send_data_packet()
|
||||
{
|
||||
static uint8_t tog=0;
|
||||
uint8_t start;
|
||||
|
||||
#ifdef FAILSAFE_ENABLE
|
||||
static uint8_t fs=0;
|
||||
if(IS_FAILSAFE_VALUES_on && phase==MLINK_SEND1)
|
||||
{
|
||||
fs=10; // Original radio is sending 70 packets
|
||||
FAILSAFE_VALUES_off;
|
||||
}
|
||||
if(fs)
|
||||
{// Failsafe packets
|
||||
switch(phase)
|
||||
{
|
||||
case MLINK_SEND2:
|
||||
packet[0]=0x06;
|
||||
start=17;
|
||||
break;
|
||||
case MLINK_SEND3:
|
||||
packet[0]=0x84;
|
||||
start=5;
|
||||
fs--;
|
||||
break;
|
||||
default: //MLINK_SEND1:
|
||||
packet[0]=0x05;
|
||||
start=11;
|
||||
break;
|
||||
}
|
||||
//Pack 6 channels per packet
|
||||
for(uint8_t i=0;i<6;i++)
|
||||
{
|
||||
uint8_t val=start<16 ? convert_channel_16b_nolimit(start,426 >> 4,3448 >> 4,true) : 0x00;
|
||||
start--; // switch to next channel
|
||||
packet[i+1]=val;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{// Normal packets
|
||||
if(hopping_frequency_no==0)
|
||||
tog=1;
|
||||
//Channels to be sent
|
||||
if(phase==MLINK_SEND1 || ((hopping_frequency_no%5==0) && (phase==MLINK_SEND2)))
|
||||
{
|
||||
if((hopping_frequency_no&1)==0)
|
||||
packet[0] = 0x09; //10,8,6
|
||||
else
|
||||
packet[0] = 0x01; //11,9,7
|
||||
}
|
||||
else
|
||||
if(phase==MLINK_SEND2)
|
||||
{
|
||||
if(tog)
|
||||
packet[0] = 0x02; //x,15,13
|
||||
else
|
||||
packet[0] = 0x0A; //x,14,12
|
||||
tog^=1;
|
||||
}
|
||||
else
|
||||
{//phase==MLINK_SEND3
|
||||
if((hopping_frequency_no&1)==0)
|
||||
packet[0] = 0x88; //4,2,0
|
||||
else
|
||||
packet[0] = 0x80; //5,3,1
|
||||
}
|
||||
|
||||
//Start channel
|
||||
start=4+6*(packet[0]&3);
|
||||
if((packet[0]&0x08)==0)
|
||||
start++;
|
||||
|
||||
//Channels 426..1937..3448
|
||||
for(uint8_t i=0;i<3;i++)
|
||||
{
|
||||
uint16_t val=start<16 ? convert_channel_16b_nolimit(start,426,3448,false) : 0x0000;
|
||||
start-=2; // switch to next channel
|
||||
packet[i*2+1]=val>>8;
|
||||
packet[i*2+2]=val;
|
||||
}
|
||||
}
|
||||
|
||||
//Calculate CRC
|
||||
crc8=bit_reverse(hopping_frequency_no + MLINK_CRC_Init); // Init = relected freq index + offset
|
||||
for(uint8_t i=0;i<MLINK_PACKET_SIZE-1;i++)
|
||||
crc8_update(bit_reverse(packet[i]));
|
||||
packet[7] = bit_reverse(crc8); // CRC reflected out
|
||||
|
||||
//Send
|
||||
CYRF_WriteDataPacketLen(packet, MLINK_PACKET_SIZE);
|
||||
|
||||
//Debug
|
||||
#if 0
|
||||
debug("P(%02d):",hopping_frequency_no);
|
||||
for(uint8_t i=0;i<8;i++)
|
||||
debug(" %02X",packet[i]);
|
||||
debugln("");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MLINK_HUB_TELEMETRY
|
||||
static void __attribute__((unused)) MLINK_Send_Telemetry()
|
||||
{ // not sure how MLINK telemetry works, the 2 RXs I have are sending something completly different...
|
||||
telemetry_counter += 2; // TX LQI counter
|
||||
telemetry_link = 1;
|
||||
|
||||
if(packet_in[0]==0x13)
|
||||
{ // RX-9-DR : 13 1A C8 00 01 64 00
|
||||
uint8_t id;
|
||||
for(uint8_t i=1; i<5; i+=3)
|
||||
{//2 sensors per packet
|
||||
id=0x00;
|
||||
switch(packet_in[i]&0x0F)
|
||||
{
|
||||
case 1: //voltage
|
||||
if((packet_in[i]&0xF0) == 0x00)
|
||||
v_lipo1 = packet_in[i+1]; // Rx_Batt*20
|
||||
else
|
||||
v_lipo2 = packet_in[i+1];
|
||||
break;
|
||||
case 2: //current
|
||||
id = 0x28;
|
||||
break;
|
||||
case 3: //vario
|
||||
id = 0x30;
|
||||
break;
|
||||
case 5: //rpm
|
||||
id = 0x03;
|
||||
break;
|
||||
case 6: //temp
|
||||
id = 0x02;
|
||||
break;
|
||||
case 10: //lqi
|
||||
RX_RSSI=RX_LQI=packet_in[i+1]>>1;
|
||||
break;
|
||||
}
|
||||
#if defined HUB_TELEMETRY
|
||||
if(id)
|
||||
{
|
||||
uint16_t val=((packet_in[i+2]&0x80)<<8)|((packet_in[i+2]&0x7F)<<7)|(packet_in[i+1]>>1); //remove the alarm LSB bit, move the sign bit to MSB
|
||||
frsky_send_user_frame(id, val, val>>8);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
if(packet_in[0]==0x03)
|
||||
{ // RX-5 : 03 15 23 00 00 01 02
|
||||
//Incoming packet values
|
||||
RX_RSSI = packet_in[2]<<1; // Looks to be the RX RSSI value
|
||||
RX_LQI = packet_in[5]; // Looks to be connection lost
|
||||
}
|
||||
else
|
||||
RX_RSSI = TX_LQI;
|
||||
|
||||
// Read TX RSSI
|
||||
TX_RSSI = CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;
|
||||
|
||||
if(telemetry_lost)
|
||||
{
|
||||
telemetry_lost = 0;
|
||||
packet_count = 50;
|
||||
telemetry_counter = 100;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MLINK_FW_TELEMETRY
|
||||
static void __attribute__((unused)) MLINK_Send_Telemetry()
|
||||
{
|
||||
telemetry_counter += 2; // TX LQI counter
|
||||
telemetry_link = 4;
|
||||
|
||||
// Read TX RSSI
|
||||
TX_RSSI = CYRF_ReadRegister(CYRF_13_RSSI)&0x1F;
|
||||
|
||||
if(telemetry_lost)
|
||||
{
|
||||
telemetry_lost = 0;
|
||||
packet_count = 50;
|
||||
telemetry_counter = 100;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t MLINK_callback()
|
||||
{
|
||||
uint8_t status;
|
||||
uint16_t start;
|
||||
|
||||
switch(phase)
|
||||
{
|
||||
case MLINK_BIND_RX:
|
||||
//debugln("RX");
|
||||
status=CYRF_ReadRegister(CYRF_05_RX_CTRL);
|
||||
if( (status&0x80) == 0 )
|
||||
{//Packet received
|
||||
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
|
||||
debugln("L=%02X",len)
|
||||
if( len==8 )
|
||||
{
|
||||
CYRF_ReadDataPacketLen(packet, len*2);
|
||||
debug("RX=");
|
||||
for(uint8_t i=0;i<8;i++)
|
||||
debug(" %02X",packet[i*2]);
|
||||
debugln("");
|
||||
//Check CRC
|
||||
crc8=0xFF; // Init = 0xFF
|
||||
for(uint8_t i=0;i<MLINK_PACKET_SIZE-1;i++)
|
||||
crc8_update(bit_reverse(packet[i<<1]));
|
||||
if(packet[14] == bit_reverse(crc8))
|
||||
{// CRC is ok
|
||||
debugln("CRC ok");
|
||||
if(packet[0]==0x7F)
|
||||
packet_count=3; // Start sending bind payload
|
||||
else if(packet_count > 0x19*2)
|
||||
{
|
||||
if(packet[0] == 0x8F)
|
||||
packet_count++;
|
||||
else if(packet[0] == 0x9F)
|
||||
packet_count=0x80; // End bind
|
||||
else
|
||||
packet_count=0; // Restart bind...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
packet_count=0;
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Enable RX abort
|
||||
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24); // Force end state
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Disable RX abort
|
||||
phase=MLINK_BIND_TX; // Retry sending bind packet
|
||||
CYRF_SetTxRxMode(TX_EN); // Transmit mode
|
||||
if(packet_count)
|
||||
return 18136;
|
||||
case MLINK_BIND_TX:
|
||||
if(--bind_counter==0 || packet_count>=0x1B*2)
|
||||
{ // Switch to normal mode
|
||||
BIND_DONE;
|
||||
phase=MLINK_PREP_DATA;
|
||||
return 22720;
|
||||
}
|
||||
MLINK_send_bind_packet();
|
||||
if(packet_count == 0 || packet_count > 0x19*2)
|
||||
{
|
||||
phase++; // MLINK_BIND_PREP_RX
|
||||
return 4700; // Original is 4900
|
||||
}
|
||||
packet_count++;
|
||||
if(packet_count&1)
|
||||
return 6000;
|
||||
return 22720;
|
||||
case MLINK_BIND_PREP_RX:
|
||||
start=micros();
|
||||
while ((uint16_t)((uint16_t)micros()-(uint16_t)start) < 200) // Wait max 200µs for TX to finish
|
||||
if((CYRF_ReadRegister(CYRF_02_TX_CTRL) & 0x80) == 0x00)
|
||||
break; // Packet transmission complete
|
||||
CYRF_SetTxRxMode(RX_EN); // Receive mode
|
||||
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x82); // Prepare to receive
|
||||
phase++; //MLINK_BIND_RX
|
||||
if(packet_count > 0x19*2)
|
||||
return 28712; // Give more time to the RX to confirm that the bind is ok...
|
||||
return 28712-4700;
|
||||
|
||||
|
||||
case MLINK_PREP_DATA:
|
||||
CYRF_ConfigDataCode(MLINK_Data_Code,16);
|
||||
MLINK_CRC_Init += 0xED;
|
||||
hopping_frequency_no = 0x00;
|
||||
CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]);
|
||||
CYRF_SetPower(0x38);
|
||||
#if defined(MLINK_HUB_TELEMETRY) || defined(MLINK_FW_TELEMETRY)
|
||||
packet_count = 0;
|
||||
telemetry_lost = 1;
|
||||
#endif
|
||||
phase++;
|
||||
|
||||
|
||||
case MLINK_SEND1:
|
||||
MLINK_send_data_packet();
|
||||
phase++;
|
||||
return 4880+1111;
|
||||
case MLINK_SEND2:
|
||||
MLINK_send_data_packet();
|
||||
phase++;
|
||||
if(hopping_frequency_no%5==0)
|
||||
return 4617+1017;
|
||||
return 4617+1422;
|
||||
case MLINK_SEND3:
|
||||
MLINK_send_data_packet();
|
||||
phase++;
|
||||
return 4611;
|
||||
case MLINK_CHECK3:
|
||||
//Switch to next channel
|
||||
hopping_frequency_no++;
|
||||
if(hopping_frequency_no>=MLINK_NUM_FREQ)
|
||||
hopping_frequency_no=0;
|
||||
CYRF_ConfigRFChannel(hopping_frequency[hopping_frequency_no]);
|
||||
|
||||
//Receive telemetry
|
||||
if(hopping_frequency_no%5==0)
|
||||
{//Receive telemetry
|
||||
CYRF_SetTxRxMode(RX_EN); // Receive mode
|
||||
CYRF_WriteRegister(CYRF_05_RX_CTRL, 0x82); // Prepare to receive
|
||||
phase++; //MLINK_RX
|
||||
return 8038+2434+410-1000;
|
||||
}
|
||||
else
|
||||
CYRF_SetPower(0x38);
|
||||
phase=MLINK_SEND1;
|
||||
return 4470;
|
||||
case MLINK_RX:
|
||||
#if defined(MLINK_HUB_TELEMETRY) || defined(MLINK_FW_TELEMETRY)
|
||||
//TX LQI calculation
|
||||
packet_count++;
|
||||
if(packet_count>=50)
|
||||
{
|
||||
packet_count=0;
|
||||
TX_LQI=telemetry_counter;
|
||||
if(telemetry_counter==0)
|
||||
telemetry_lost = 1;
|
||||
telemetry_counter = 0;
|
||||
}
|
||||
#endif
|
||||
status=CYRF_ReadRegister(CYRF_05_RX_CTRL);
|
||||
debug("T(%02X):",status);
|
||||
if( (status&0x80) == 0 )
|
||||
{//Packet received
|
||||
len=CYRF_ReadRegister(CYRF_09_RX_COUNT);
|
||||
debug("(%X)",len)
|
||||
if( len && len <= MLINK_PACKET_SIZE )
|
||||
{
|
||||
CYRF_ReadDataPacketLen(packet_in, len*2);
|
||||
#if defined(MLINK_HUB_TELEMETRY) || defined(MLINK_FW_TELEMETRY)
|
||||
if(len==MLINK_PACKET_SIZE)
|
||||
{
|
||||
for(uint8_t i=0;i<8;i++)
|
||||
//Check CRC
|
||||
crc8=bit_reverse(MLINK_CRC_Init);
|
||||
for(uint8_t i=0;i<MLINK_PACKET_SIZE-1;i++)
|
||||
{
|
||||
packet_in[i]=packet_in[i<<1];
|
||||
crc8_update(bit_reverse(packet_in[i]));
|
||||
debug(" %02X",packet_in[i]);
|
||||
}
|
||||
if(packet_in[14] == bit_reverse(crc8)) // Packet CRC is ok
|
||||
MLINK_Send_Telemetry();
|
||||
else
|
||||
debug(" NOK");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
debugln("");
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x20); // Enable RX abort
|
||||
CYRF_WriteRegister(CYRF_0F_XACT_CFG, 0x24); // Force end state
|
||||
CYRF_WriteRegister(CYRF_29_RX_ABORT, 0x00); // Disable RX abort
|
||||
CYRF_SetTxRxMode(TX_EN); // Transmit mode
|
||||
phase=MLINK_SEND2;
|
||||
return 1000;
|
||||
}
|
||||
return 1000;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) MLINK_shuffle_freqs(uint32_t seed, uint8_t *hop)
|
||||
{
|
||||
randomSeed(seed);
|
||||
|
||||
for(uint8_t i=0; i < MLINK_NUM_FREQ/2; i++)
|
||||
{
|
||||
uint8_t r = random(0xfefefefe) % (MLINK_NUM_FREQ/2);
|
||||
uint8_t tmp = hop[r];
|
||||
hop[r] = hop[i];
|
||||
hop[i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void MLINK_init()
|
||||
{
|
||||
MLINK_cyrf_config();
|
||||
|
||||
//Init ID and RF freqs
|
||||
for(uint8_t i=0; i < MLINK_NUM_FREQ/2; i++)
|
||||
{
|
||||
hopping_frequency[i ] = (i<<1) + 3;
|
||||
hopping_frequency[i+MLINK_NUM_FREQ/2] = (i<<1) + 3;
|
||||
}
|
||||
// part1
|
||||
memcpy(MLINK_Data_Code ,rx_tx_addr,4);
|
||||
MLINK_shuffle_freqs(MProtocol_id, hopping_frequency);
|
||||
|
||||
// part2
|
||||
MProtocol_id ^= 0x6FBE3201;
|
||||
set_rx_tx_addr(MProtocol_id);
|
||||
memcpy(MLINK_Data_Code+4,rx_tx_addr,4);
|
||||
MLINK_shuffle_freqs(MProtocol_id, &hopping_frequency[MLINK_NUM_FREQ/2]);
|
||||
|
||||
// part3
|
||||
MLINK_CRC_Init = rx_tx_addr[3]; //value sent during bind then used to init the CRC
|
||||
MLINK_Unk_6_2 = 0x3A; //unknown value sent during bind but doesn't seem to matter
|
||||
|
||||
#ifdef MLINK_FORCE_ID
|
||||
if(RX_num)
|
||||
{
|
||||
//Cockpit SX
|
||||
memcpy(MLINK_Data_Code,"\x4C\x97\x9D\xBF\xB8\x3D\xB5\xBE",8);
|
||||
memcpy(hopping_frequency,"\x0D\x41\x09\x43\x17\x2D\x05\x31\x13\x3B\x1B\x3D\x0B\x41\x11\x45\x09\x2B\x17\x4D\x19\x3F\x03\x3F\x0F\x37\x1F\x47\x1B\x49\x07\x35\x27\x2F\x15\x33\x23\x39\x1F\x33\x19\x45\x0D\x2D\x11\x35\x0B\x47\x25\x3D\x21\x37\x1D\x3B\x05\x2F\x21\x39\x23\x4B\x03\x31\x25\x29\x07\x4F\x1D\x4B\x15\x4D\x13\x4F\x0F\x49\x29\x2B\x27\x43",MLINK_NUM_FREQ);
|
||||
MLINK_Unk_6_2 = 0x3A; //unknown value sent during bind but doesn't seem to matter
|
||||
MLINK_CRC_Init = 0x07; //value sent during bind then used to init the CRC
|
||||
}
|
||||
else
|
||||
{
|
||||
//HFM3
|
||||
memcpy(MLINK_Data_Code,"\xC0\x90\x8F\xBB\x7C\x8E\x2B\x8E",8);
|
||||
memcpy(hopping_frequency,"\x05\x41\x27\x4B\x17\x33\x11\x39\x0F\x3F\x05\x2F\x13\x2D\x25\x31\x1F\x2D\x25\x35\x03\x41\x1B\x43\x09\x3D\x1F\x29\x1D\x35\x0D\x3B\x19\x49\x23\x3B\x17\x47\x1D\x2B\x13\x37\x0B\x31\x23\x33\x29\x3F\x07\x37\x07\x43\x11\x2B\x1B\x39\x0B\x4B\x03\x4F\x21\x47\x0F\x4D\x15\x45\x21\x4F\x09\x3D\x19\x2F\x15\x45\x0D\x49\x27\x4D",MLINK_NUM_FREQ);
|
||||
MLINK_Unk_6_2 = 0x02; //unknown value but doesn't seem to matter
|
||||
MLINK_CRC_Init = 0x3E; //value sent during bind then used to init the CRC
|
||||
}
|
||||
//Other TX
|
||||
//MLINK_Unk_6_2 = 0x7e; //unknown value but doesn't seem to matter
|
||||
//MLINK_CRC_Init = 0xA2; //value sent during bind then used to init the CRC
|
||||
#endif
|
||||
|
||||
for(uint8_t i=0;i<8;i++)
|
||||
MLINK_Data_Code[i+8]=MLINK_Data_Code[7-i];
|
||||
|
||||
debug("ID:")
|
||||
for(uint8_t i=0;i<16;i++)
|
||||
debug(" %02X", MLINK_Data_Code[i]);
|
||||
debugln("");
|
||||
|
||||
debugln("CRC init: %02X", MLINK_CRC_Init)
|
||||
|
||||
debug("RF:")
|
||||
for(uint8_t i=0;i<MLINK_NUM_FREQ;i++)
|
||||
debug(" %02X", hopping_frequency[i]);
|
||||
debugln("");
|
||||
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet_count = 0;
|
||||
bind_counter = MLINK_BIND_COUNT;
|
||||
CYRF_ConfigDataCode((uint8_t*)"\x6F\xBE\x32\x01\xDB\xF1\x2B\x01\xE3\x5C\xFA\x02\x97\x93\xF9\x02",16); //Bind data code
|
||||
CYRF_ConfigRFChannel(MLINK_BIND_CHANNEL);
|
||||
phase = MLINK_BIND_TX;
|
||||
}
|
||||
else
|
||||
phase = MLINK_PREP_DATA;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -18,20 +18,23 @@
|
||||
#if defined(MT99XX_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
#define MT99XX_BIND_COUNT 928
|
||||
#define MT99XX_PACKET_PERIOD_FY805 2460
|
||||
#define MT99XX_PACKET_PERIOD_MT 2625
|
||||
#define MT99XX_PACKET_PERIOD_YZ 3125
|
||||
#define MT99XX_INITIAL_WAIT 500
|
||||
#define MT99XX_PACKET_SIZE 9
|
||||
#define MT99XX_BIND_COUNT 928
|
||||
#define MT99XX_PACKET_PERIOD_FY805 2460
|
||||
#define MT99XX_PACKET_PERIOD_MT 2625
|
||||
#define MT99XX_PACKET_PERIOD_YZ 3125
|
||||
#define MT99XX_PACKET_PERIOD_A180 3400 // timing changes between the packets 2 x 27220 then 1x 26080, it seems that it is only on the first RF channel which jitters by 1.14ms but hard to pinpoint with XN297dump
|
||||
#define MT99XX_PACKET_PERIOD_DRAGON 1038 // there is a pause of 2x1038 between the packets 3 and 4 from what XN297dump detects which I think are used for telemetry
|
||||
#define MT99XX_INITIAL_WAIT 500
|
||||
#define MT99XX_PACKET_SIZE 9
|
||||
|
||||
#define checksum_offset rf_ch_num
|
||||
#define channel_offset phase
|
||||
//#define FORCE_A180_ID
|
||||
//#define FORCE_DRAGON_ID
|
||||
|
||||
enum{
|
||||
// flags going to packet[6] (MT99xx, H7)
|
||||
FLAG_MT_RATE1 = 0x01, // (H7 high rate)
|
||||
FLAG_MT_RATE1 = 0x01, // (H7 & A180 high rate)
|
||||
FLAG_MT_RATE2 = 0x02, // (MT9916 only)
|
||||
FLAG_MT_VIDEO = 0x10,
|
||||
FLAG_MT_SNAPSHOT= 0x20,
|
||||
@@ -53,6 +56,19 @@ enum{
|
||||
FLAG_FY805_HEADLESS= 0x10,
|
||||
};
|
||||
|
||||
enum{
|
||||
// flags going to packet[6] (A180)
|
||||
FLAG_A180_3D6G = 0x01,
|
||||
FLAG_A180_RATE = 0x02,
|
||||
};
|
||||
|
||||
enum{
|
||||
// flags going to packet[6] (DRAGON)
|
||||
FLAG_DRAGON_RATE = 0x01,
|
||||
FLAG_DRAGON_RTH = 0x80,
|
||||
FLAG_DRAGON_UNK = 0x04,
|
||||
};
|
||||
|
||||
enum {
|
||||
MT99XX_INIT = 0,
|
||||
MT99XX_BIND,
|
||||
@@ -64,89 +80,170 @@ const uint8_t h7_mys_byte[] = {
|
||||
0x05, 0x15, 0x06, 0x16, 0x07, 0x17, 0x00, 0x10
|
||||
};
|
||||
|
||||
static const uint8_t ls_mys_byte[] = {
|
||||
const uint8_t ls_mys_byte[] = {
|
||||
0x05, 0x15, 0x25, 0x06, 0x16, 0x26,
|
||||
0x07, 0x17, 0x27, 0x00, 0x10, 0x20,
|
||||
0x01, 0x11, 0x21, 0x02, 0x12, 0x22,
|
||||
0x03, 0x13, 0x23, 0x04, 0x14, 0x24
|
||||
};
|
||||
|
||||
const uint8_t yz_p4_seq[] = {0xa0, 0x20, 0x60};
|
||||
|
||||
#ifdef DRAGON_HUB_TELEMETRY
|
||||
const uint8_t DRAGON_seq[] = {0x20, 0x60, 0x20, 0x80};
|
||||
#endif
|
||||
|
||||
static void __attribute__((unused)) MT99XX_send_packet()
|
||||
{
|
||||
const uint8_t yz_p4_seq[] = {0xa0, 0x20, 0x60};
|
||||
static uint8_t yz_seq_num=0;
|
||||
static uint8_t ls_counter=0;
|
||||
static uint8_t seq_num=0;
|
||||
|
||||
if(sub_protocol != YZ)
|
||||
{ // MT99XX & H7 & LS
|
||||
packet[0] = convert_channel_16b_limit(THROTTLE,0xE1,0x00); // throttle
|
||||
packet[1] = convert_channel_16b_limit(RUDDER ,0x00,0xE1); // rudder
|
||||
packet[2] = convert_channel_16b_limit(AILERON ,0xE1,0x00); // aileron
|
||||
packet[3] = convert_channel_16b_limit(ELEVATOR,0x00,0xE1); // elevator
|
||||
packet[4] = 0x20; // pitch trim (0x3f-0x20-0x00)
|
||||
packet[5] = 0x20; // roll trim (0x00-0x20-0x3f)
|
||||
packet[6] = GET_FLAG( CH5_SW, FLAG_MT_FLIP );
|
||||
packet[7] = h7_mys_byte[hopping_frequency_no]; // next rf channel index ?
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
//Bind packet
|
||||
packet[0] = 0x20;
|
||||
switch(sub_protocol)
|
||||
{
|
||||
case YZ:
|
||||
packet_period = MT99XX_PACKET_PERIOD_YZ;
|
||||
packet[1] = 0x15;
|
||||
packet[2] = 0x05;
|
||||
packet[3] = 0x06;
|
||||
break;
|
||||
case LS:
|
||||
packet[1] = 0x14;
|
||||
packet[2] = 0x05;
|
||||
packet[3] = 0x11;
|
||||
break;
|
||||
case FY805:
|
||||
packet_period = MT99XX_PACKET_PERIOD_FY805;
|
||||
packet[1] = 0x15;
|
||||
packet[2] = 0x12;
|
||||
packet[3] = 0x17;
|
||||
break;
|
||||
case A180:
|
||||
packet_period = MT99XX_PACKET_PERIOD_A180;
|
||||
default: // MT99 & H7 & A180 & DRAGON
|
||||
packet[1] = 0x14;
|
||||
packet[2] = 0x03;
|
||||
packet[3] = 0x25;
|
||||
break;
|
||||
}
|
||||
packet[4] = rx_tx_addr[0];
|
||||
packet[5] = rx_tx_addr[1];
|
||||
packet[6] = rx_tx_addr[2];
|
||||
packet[7] = crc8; // checksum offset
|
||||
packet[8] = 0xAA; // fixed
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sub_protocol != YZ)
|
||||
{ // MT99XX & H7 & LS & FY805 & A180 & DRAGON
|
||||
packet[0] = convert_channel_16b_limit(THROTTLE,0xE1,0x00); // throttle
|
||||
packet[1] = convert_channel_16b_limit(RUDDER ,0x00,0xE1); // rudder
|
||||
packet[2] = convert_channel_16b_limit(AILERON ,0xE1,0x00); // aileron
|
||||
packet[3] = convert_channel_16b_limit(ELEVATOR,0x00,0xE1); // elevator
|
||||
packet[4] = 0x20; // pitch trim (0x3f-0x20-0x00)
|
||||
packet[5] = 0x20; // roll trim (0x00-0x20-0x3f)
|
||||
packet[6] = GET_FLAG( CH5_SW, FLAG_MT_FLIP );
|
||||
packet[7] = h7_mys_byte[hopping_frequency_no]; // next rf channel index ?
|
||||
|
||||
if(sub_protocol==H7)
|
||||
packet[6]|=FLAG_MT_RATE1; // max rate on H7
|
||||
else
|
||||
if(sub_protocol==MT99)
|
||||
packet[6] |= 0x40 | FLAG_MT_RATE2
|
||||
| GET_FLAG( CH7_SW, FLAG_MT_SNAPSHOT )
|
||||
| GET_FLAG( CH8_SW, FLAG_MT_VIDEO ); // max rate on MT99xx
|
||||
else
|
||||
if(sub_protocol==FY805)
|
||||
{
|
||||
switch(sub_protocol)
|
||||
{
|
||||
case MT99:
|
||||
packet[6] |= 0x40 | FLAG_MT_RATE2 // max rate on MT99xx
|
||||
| GET_FLAG( CH7_SW, FLAG_MT_SNAPSHOT )
|
||||
| GET_FLAG( CH8_SW, FLAG_MT_VIDEO );
|
||||
break;
|
||||
case H7:
|
||||
packet[6] |= FLAG_MT_RATE1; // max rate on H7
|
||||
break;
|
||||
case LS:
|
||||
packet[6] |= FLAG_LS_RATE // max rate
|
||||
| GET_FLAG( CH6_SW, FLAG_LS_INVERT ) // invert
|
||||
| GET_FLAG( CH7_SW, FLAG_LS_SNAPSHOT ) // snapshot
|
||||
| GET_FLAG( CH8_SW, FLAG_LS_VIDEO ) // video
|
||||
| GET_FLAG( CH9_SW, FLAG_LS_HEADLESS ); // Headless
|
||||
packet[7] = ls_mys_byte[seq_num++];
|
||||
if(seq_num >= sizeof(ls_mys_byte))
|
||||
seq_num=0;
|
||||
break;
|
||||
case FY805:
|
||||
packet[6]=0x20;
|
||||
//Rate 0x01?
|
||||
//Flip ?
|
||||
packet[7]=0x01
|
||||
|GET_FLAG( CH5_SW, FLAG_MT_FLIP )
|
||||
|GET_FLAG( CH9_SW, FLAG_FY805_HEADLESS ); //HEADLESS
|
||||
checksum_offset=0;
|
||||
}
|
||||
else //LS
|
||||
{
|
||||
packet[6] |= FLAG_LS_RATE // max rate
|
||||
| GET_FLAG( CH6_SW, FLAG_LS_INVERT ) //INVERT
|
||||
| GET_FLAG( CH7_SW, FLAG_LS_SNAPSHOT ) //SNAPSHOT
|
||||
| GET_FLAG( CH8_SW, FLAG_LS_VIDEO ) //VIDEO
|
||||
| GET_FLAG( CH9_SW, FLAG_LS_HEADLESS ); //HEADLESS
|
||||
packet[7] = ls_mys_byte[ls_counter++];
|
||||
if(ls_counter >= sizeof(ls_mys_byte))
|
||||
ls_counter=0;
|
||||
}
|
||||
|
||||
uint8_t result=checksum_offset;
|
||||
for(uint8_t i=0; i<8; i++)
|
||||
result += packet[i];
|
||||
packet[8] = result;
|
||||
}
|
||||
else
|
||||
{ // YZ
|
||||
packet[0] = convert_channel_16b_limit(THROTTLE,0x00,0x64); // throttle
|
||||
packet[1] = convert_channel_16b_limit(RUDDER ,0x64,0x00); // rudder
|
||||
packet[2] = convert_channel_16b_limit(ELEVATOR,0x00,0x64); // elevator
|
||||
packet[3] = convert_channel_16b_limit(AILERON ,0x64,0x00); // aileron
|
||||
if(packet_count++ >= 23)
|
||||
{
|
||||
yz_seq_num ++;
|
||||
if(yz_seq_num > 2)
|
||||
yz_seq_num = 0;
|
||||
packet_count=0;
|
||||
|GET_FLAG( CH9_SW, FLAG_FY805_HEADLESS ); //HEADLESS
|
||||
crc8=0;
|
||||
break;
|
||||
case A180:
|
||||
packet[6] = FLAG_A180_RATE
|
||||
| GET_FLAG( CH5_SW, FLAG_A180_3D6G );
|
||||
packet[7] = 0x00;
|
||||
break;
|
||||
case DRAGON:
|
||||
if(CH5_SW) // Advanced mode
|
||||
packet[5] |= 0x80;
|
||||
else
|
||||
if(Channel_data[CH5] > CHANNEL_MIN_COMMAND) // Beginner mode
|
||||
packet[5] |= 0x40;
|
||||
packet[6] = FLAG_DRAGON_RATE
|
||||
| GET_FLAG( CH6_SW, FLAG_DRAGON_RTH );
|
||||
|
||||
#ifdef DRAGON_HUB_TELEMETRY
|
||||
//Telemetry
|
||||
// C=48 S=Y A= 6C 00 22 CC CC P(9)= 6C 00 22 27 00 00 00 00 60
|
||||
// C=48 S=Y A= 6C 00 22 CC CC P(9)= 6C 00 22 28 00 00 00 00 61
|
||||
// C=18 S=Y A= 6C 00 22 CC CC P(9)= 6C 00 22 24 00 00 00 00 5D
|
||||
// 6C 00 22 = TX address, 27/28/24=vbatt, check = sum(P[0..7]) + AB, where AB comes from? Is it constant?
|
||||
if(hopping_frequency_no == 0)
|
||||
{
|
||||
seq_num++;
|
||||
seq_num &= 0x03;
|
||||
packet_count++;
|
||||
if(packet_count > 11)
|
||||
packet_count = 0;
|
||||
}
|
||||
if(packet_count > 10) // Telemetry packet request every 10 or 11 packets
|
||||
packet[6] |= 0x04; // Request telemetry flag
|
||||
packet[7] = DRAGON_seq[seq_num]; // seq: 20 80 20 60 20 80 20 60... 80 changes to 80+batt from telem
|
||||
if(seq_num==3)
|
||||
packet[7] |= v_lipo1;
|
||||
#else
|
||||
packet[7] = 0x20;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
uint8_t result=crc8;
|
||||
for(uint8_t i=0; i<8; i++)
|
||||
result += packet[i];
|
||||
packet[8] = result;
|
||||
}
|
||||
else
|
||||
{ // YZ
|
||||
packet[0] = convert_channel_16b_limit(THROTTLE,0x00,0x64); // throttle
|
||||
packet[1] = convert_channel_16b_limit(RUDDER ,0x64,0x00); // rudder
|
||||
packet[2] = convert_channel_16b_limit(ELEVATOR,0x00,0x64); // elevator
|
||||
packet[3] = convert_channel_16b_limit(AILERON ,0x64,0x00); // aileron
|
||||
if(packet_count++ >= 23)
|
||||
{
|
||||
seq_num ++;
|
||||
if(seq_num > 2)
|
||||
seq_num = 0;
|
||||
packet_count=0;
|
||||
}
|
||||
packet[4] = yz_p4_seq[seq_num];
|
||||
packet[5] = 0x02 // expert ? (0=unarmed, 1=normal)
|
||||
| GET_FLAG(CH8_SW, 0x10) //VIDEO
|
||||
| GET_FLAG(CH5_SW, 0x80) //FLIP
|
||||
| GET_FLAG(CH9_SW, 0x04) //HEADLESS
|
||||
| GET_FLAG(CH7_SW, 0x20); //SNAPSHOT
|
||||
packet[6] = GET_FLAG(CH6_SW, 0x80); //LED
|
||||
packet[7] = packet[0];
|
||||
for(uint8_t idx = 1; idx < MT99XX_PACKET_SIZE-2; idx++)
|
||||
packet[7] += packet[idx];
|
||||
packet[8] = 0xff;
|
||||
}
|
||||
packet[4] = yz_p4_seq[yz_seq_num];
|
||||
packet[5] = 0x02 // expert ? (0=unarmed, 1=normal)
|
||||
| GET_FLAG(CH8_SW, 0x10) //VIDEO
|
||||
| GET_FLAG(CH5_SW, 0x80) //FLIP
|
||||
| GET_FLAG(CH9_SW, 0x04) //HEADLESS
|
||||
| GET_FLAG(CH7_SW, 0x20); //SNAPSHOT
|
||||
packet[6] = GET_FLAG(CH6_SW, 0x80); //LED
|
||||
packet[7] = packet[0];
|
||||
for(uint8_t idx = 1; idx < MT99XX_PACKET_SIZE-2; idx++)
|
||||
packet[7] += packet[idx];
|
||||
packet[8] = 0xff;
|
||||
}
|
||||
|
||||
if(sub_protocol == LS)
|
||||
@@ -154,14 +251,23 @@ static void __attribute__((unused)) MT99XX_send_packet()
|
||||
else
|
||||
if(sub_protocol==FY805)
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x4B); // FY805 always transmits on the same channel
|
||||
else
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no] + channel_offset);
|
||||
else // MT99 & H7 & YZ & A180 & DRAGON
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
XN297_WritePayload(packet, MT99XX_PACKET_SIZE);
|
||||
|
||||
if(sub_protocol == DRAGON)
|
||||
{
|
||||
if(hopping_frequency_no == 6)
|
||||
packet_period = 3 * MT99XX_PACKET_PERIOD_DRAGON; // hole probably for the telemetry
|
||||
else
|
||||
packet_period = MT99XX_PACKET_PERIOD_DRAGON;
|
||||
}
|
||||
|
||||
hopping_frequency_no++;
|
||||
if(sub_protocol == YZ)
|
||||
if(sub_protocol == YZ || sub_protocol == A180 || sub_protocol == DRAGON )
|
||||
hopping_frequency_no++; // skip every other channel
|
||||
|
||||
if(hopping_frequency_no > 15)
|
||||
@@ -170,141 +276,109 @@ static void __attribute__((unused)) MT99XX_send_packet()
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) MT99XX_init()
|
||||
static void __attribute__((unused)) MT99XX_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
|
||||
if(sub_protocol == YZ)
|
||||
XN297_SetScrambledMode(XN297_UNSCRAMBLED);
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_FlushTx();
|
||||
XN297_SetTXAddr((uint8_t *)"\xCC\xCC\xCC\xCC\xCC", 5);
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5 bytes address
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no auto retransmit
|
||||
if(sub_protocol == YZ)
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps (nRF24L01+ only)
|
||||
else
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP) );
|
||||
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) MT99XX_initialize_txid()
|
||||
{
|
||||
rx_tx_addr[3] = 0xCC;
|
||||
rx_tx_addr[4] = 0xCC;
|
||||
if(sub_protocol == YZ)
|
||||
rx_tx_addr[1] = rx_tx_addr[3]; // RX_Num
|
||||
|
||||
switch(protocol)
|
||||
{
|
||||
rx_tx_addr[0] = 0x53; // test (SB id)
|
||||
rx_tx_addr[1] = 0x00;
|
||||
rx_tx_addr[2] = 0x00;
|
||||
}
|
||||
else
|
||||
if(sub_protocol == FY805)
|
||||
{
|
||||
rx_tx_addr[0] = 0x81; // test (SB id)
|
||||
case YZ:
|
||||
rx_tx_addr[0] = 0x53; // test (SB id)
|
||||
rx_tx_addr[1] = 0x00;
|
||||
rx_tx_addr[2] = 0x00;
|
||||
break;
|
||||
case FY805:
|
||||
rx_tx_addr[0] = 0x81; // test (SB id)
|
||||
rx_tx_addr[1] = 0x0F;
|
||||
rx_tx_addr[2] = 0x00;
|
||||
}
|
||||
else
|
||||
if(sub_protocol == LS)
|
||||
rx_tx_addr[0] = 0xCC;
|
||||
else //MT99 & H7
|
||||
rx_tx_addr[2] = 0x00;
|
||||
checksum_offset = rx_tx_addr[0] + rx_tx_addr[1] + rx_tx_addr[2];
|
||||
channel_offset = (((checksum_offset & 0xf0)>>4) + (checksum_offset & 0x0f)) % 8;
|
||||
break;
|
||||
case LS:
|
||||
rx_tx_addr[0] = 0xCC;
|
||||
break;
|
||||
#ifdef FORCE_A180_ID
|
||||
case A180:
|
||||
rx_tx_addr[0] = 0x84; // MikeHRC ID
|
||||
rx_tx_addr[1] = 0x62;
|
||||
rx_tx_addr[2] = 0x4A;
|
||||
//crc8 = 0x30
|
||||
//channel_offset = 0x03;
|
||||
break;
|
||||
#endif
|
||||
#ifdef FORCE_DRAGON_ID
|
||||
case DRAGON:
|
||||
rx_tx_addr[0] = 0x6C; // Laurie ID
|
||||
rx_tx_addr[1] = 0x00;
|
||||
rx_tx_addr[2] = 0x22;
|
||||
//crc8 = 0x8E
|
||||
//channel_offset = 0x06
|
||||
break;
|
||||
#endif
|
||||
default: //MT99 & H7 & A180 & DRAGON
|
||||
rx_tx_addr[2] = 0x00;
|
||||
break;
|
||||
}
|
||||
|
||||
rx_tx_addr[3] = 0xCC;
|
||||
rx_tx_addr[4] = 0xCC;
|
||||
|
||||
crc8 = rx_tx_addr[0] + rx_tx_addr[1] + rx_tx_addr[2];
|
||||
|
||||
//memcpy(hopping_frequency,"\x02\x48\x0C\x3e\x16\x34\x20\x2A\x2A\x20\x34\x16\x3e\x0c\x48\x02",16);
|
||||
for(uint8_t i=0; i<8; i++)
|
||||
{
|
||||
hopping_frequency[(i<<1) ]=0x02 + (10*i);
|
||||
hopping_frequency[(i<<1)+1]=0x48 - (10*i);
|
||||
}
|
||||
hopping_frequency_no=0;
|
||||
}
|
||||
|
||||
uint16_t MT99XX_callback()
|
||||
{
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
MT99XX_send_packet();
|
||||
}
|
||||
else
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
if(bind_counter)
|
||||
{
|
||||
bind_counter--;
|
||||
if (bind_counter == 0)
|
||||
{
|
||||
// set tx address for data packets
|
||||
XN297_SetTXAddr(rx_tx_addr, 5);
|
||||
// set tx address for data packets
|
||||
XN297_SetTXAddr(rx_tx_addr, 5);
|
||||
// set rf channels
|
||||
uint8_t channel_offset = ((crc8>>4) + (crc8 & 0x0f)) % 8;
|
||||
for(uint8_t i=0;i<16;i++)
|
||||
hopping_frequency[i] += channel_offset;
|
||||
BIND_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sub_protocol == LS)
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x2D); // LS always transmits on the same channel
|
||||
else
|
||||
if(sub_protocol==FY805)
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x4B); // FY805 always transmits on the same channel
|
||||
else
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
XN297_WritePayload(packet, MT99XX_PACKET_SIZE); // bind packet
|
||||
hopping_frequency_no++;
|
||||
if(sub_protocol == YZ)
|
||||
hopping_frequency_no++; // skip every other channel
|
||||
if(hopping_frequency_no > 15)
|
||||
hopping_frequency_no = 0;
|
||||
bind_counter--;
|
||||
}
|
||||
}
|
||||
|
||||
MT99XX_send_packet();
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
uint16_t initMT99XX(void)
|
||||
void MT99XX_init(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
if(sub_protocol != A180 && sub_protocol != DRAGON)
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
bind_counter = MT99XX_BIND_COUNT;
|
||||
|
||||
memcpy(hopping_frequency,"\x02\x48\x0C\x3e\x16\x34\x20\x2A\x2A\x20\x34\x16\x3e\x0c\x48\x02",16);
|
||||
hopping_frequency_no=0;
|
||||
|
||||
MT99XX_initialize_txid();
|
||||
MT99XX_init();
|
||||
MT99XX_RF_init();
|
||||
|
||||
packet[0] = 0x20;
|
||||
packet_period = MT99XX_PACKET_PERIOD_MT;
|
||||
switch(sub_protocol)
|
||||
{ // MT99 & H7
|
||||
case MT99:
|
||||
case H7:
|
||||
packet[1] = 0x14;
|
||||
packet[2] = 0x03;
|
||||
packet[3] = 0x25;
|
||||
break;
|
||||
case YZ:
|
||||
packet_period = MT99XX_PACKET_PERIOD_YZ;
|
||||
packet[1] = 0x15;
|
||||
packet[2] = 0x05;
|
||||
packet[3] = 0x06;
|
||||
break;
|
||||
case LS:
|
||||
packet[1] = 0x14;
|
||||
packet[2] = 0x05;
|
||||
packet[3] = 0x11;
|
||||
break;
|
||||
case FY805:
|
||||
packet_period = MT99XX_PACKET_PERIOD_FY805;
|
||||
packet[1] = 0x15;
|
||||
packet[2] = 0x12;
|
||||
packet[3] = 0x17;
|
||||
break;
|
||||
}
|
||||
packet[4] = rx_tx_addr[0];
|
||||
packet[5] = rx_tx_addr[1];
|
||||
packet[6] = rx_tx_addr[2];
|
||||
packet[7] = checksum_offset; // checksum offset
|
||||
packet[8] = 0xAA; // fixed
|
||||
|
||||
packet_count=0;
|
||||
return MT99XX_INITIAL_WAIT+MT99XX_PACKET_PERIOD_MT;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
2,Hubsan,H107,H301,H501
|
||||
3,FrskyD,D8,Cloned
|
||||
4,Hisky,Hisky,HK310
|
||||
5,V2x2,V2x2,JXD506
|
||||
6,DSM,DSM2-22,DSM2-11,DSMX-22,DSMX-11,AUTO
|
||||
5,V2x2,V2x2,JXD506,MR101
|
||||
6,DSM,DSM2_1F,DSM2_2F,DSMX_1F,DSMX_2F,AUTO
|
||||
7,Devo,8CH,10CH,12CH,6CH,7CH
|
||||
8,YD717,YD717,SKYWLKR,SYMAX4,XINXUN,NIHUI
|
||||
9,KN,WLTOYS,FEILUN
|
||||
@@ -11,21 +11,21 @@
|
||||
11,SLT,SLT_V1,SLT_V2,Q100,Q200,MR100
|
||||
12,CX10,GREEN,BLUE,DM007,---,J3015_1,J3015_2,MK33041
|
||||
13,CG023,CG023,YD829
|
||||
14,Bayang,Bayang,H8S3D,X16_AH,IRDRONE,DHD_D4
|
||||
15,FrskyX,CH_16,CH_8,EU_16,EU_8,Cloned
|
||||
14,Bayang,Bayang,H8S3D,X16_AH,IRDRONE,DHD_D4,QX100
|
||||
15,FrskyX,CH_16,CH_8,EU_16,EU_8,Cloned,Clon_8
|
||||
16,ESky,Std,ET4
|
||||
17,MT99xx,MT,H7,YZ,LS,FY805
|
||||
17,MT99xx,MT,H7,YZ,LS,FY805,A180,Dragon
|
||||
18,MJXq,WLH08,X600,X800,H26D,E010,H26WH,PHOENIX
|
||||
19,Shenqi
|
||||
20,FY326,FY326,FY319
|
||||
21,SFHSS
|
||||
21,Futaba,SFHSS
|
||||
22,J6PRO
|
||||
23,FQ777
|
||||
24,ASSAN
|
||||
25,FrskyV
|
||||
26,HONTAI,HONTAI,JJRCX1,X5C1,FQ777_951
|
||||
27,OpnLrs
|
||||
28,AFHDS2A,PWM_IBUS,PPM_IBUS,PWM_SBUS,PPM_SBUS
|
||||
28,AFHDS2A,PWM_IBUS,PPM_IBUS,PWM_SBUS,PPM_SBUS,PWM_IB16,PPM_IB16
|
||||
29,Q2X2,Q222,Q242,Q282
|
||||
30,WK2x01,WK2801,WK2401,W6_5_1,W6_6_1,W6_HEL,W6_HEL_I
|
||||
31,Q303,Q303,CX35,CX10D,CX10WD
|
||||
@@ -37,32 +37,48 @@
|
||||
37,CORONA,COR_V1,COR_V2,FD_V3
|
||||
38,CFlie
|
||||
39,Hitec,OPT_FW,OPT_HUB,MINIMA
|
||||
40,WFLY
|
||||
40,WFLY,WFR0x
|
||||
41,BUGS
|
||||
42,BUGSMINI,BUGSMINI,BUGS3H
|
||||
43,Traxxas,RX6519
|
||||
44,NCC1701
|
||||
45,E01X,E012,E015,E016H
|
||||
46,V911S,V911S,E119
|
||||
47,GD00X,GD_V1,GD_V2
|
||||
48,V761
|
||||
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,RX,CloneTX
|
||||
56,AFHDS2A_RX
|
||||
57,HoTT
|
||||
55,Frsky_RX,Multi,CloneTX,EraseTX,CPPM
|
||||
56,AFHDS2A_RX,Multi,CPPM
|
||||
57,HoTT,Sync,No_Sync
|
||||
58,FX816,P38
|
||||
59,Bayang_RX
|
||||
60,Pelikan
|
||||
59,Bayang_RX,Multi,CPPM
|
||||
60,Pelikan,Pro,Lite
|
||||
61,Tiger
|
||||
62,XK,X450,X420
|
||||
63,XN_DUMP,250K,1M,2M,AUTO
|
||||
64,FrskyX2,CH_16,CH_8,EU_16,EU_8,Cloned
|
||||
65,FrSkyR9,915MHz,868MHz,915_8ch,868_8ch
|
||||
65,FrSkyR9,915MHz,868MHz,915_8ch,868_8ch,FCC,--,FCC_8ch,--_8ch
|
||||
66,PROPEL,74-Z
|
||||
67,LR12,LR12,LR12_6ch
|
||||
68,Skyartec
|
||||
69,ESKYv2,150V2
|
||||
70,DSM_RX,Multi,CPPM
|
||||
71,JJRC345,JJRC345,SkyTmblr
|
||||
72,Q90C
|
||||
73,Kyosho,FHSS,Hype
|
||||
74,RadioLink,Surface,Air,DumboRC
|
||||
75,---
|
||||
76,Realacc,R11
|
||||
77,OMP
|
||||
78,M-Link
|
||||
79,WFLY,RF20x
|
||||
80,E016H,E016Hv2
|
||||
81,E010r5
|
||||
82,LOLI
|
||||
83,E129
|
||||
84,JOYSWAY
|
||||
@@ -1,356 +0,0 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(MULTI_NAMES)
|
||||
|
||||
const char STR_FLYSKY[] ="FlySky";
|
||||
const char STR_HUBSAN[] ="Hubsan";
|
||||
const char STR_FRSKYD[] ="FrSky D";
|
||||
const char STR_HISKY[] ="Hisky";
|
||||
const char STR_V2X2[] ="V2x2";
|
||||
const char STR_DSM[] ="DSM";
|
||||
const char STR_DEVO[] ="Devo";
|
||||
const char STR_YD717[] ="YD717";
|
||||
const char STR_KN[] ="KN";
|
||||
const char STR_SYMAX[] ="SymaX";
|
||||
const char STR_SLT[] ="SLT";
|
||||
const char STR_CX10[] ="CX10";
|
||||
const char STR_CG023[] ="CG023";
|
||||
const char STR_BAYANG[] ="Bayang";
|
||||
const char STR_FRSKYL[] ="FrSky L";
|
||||
const char STR_FRSKYX[] ="FrSky X";
|
||||
const char STR_FRSKYX2[] ="FrSkyX2";
|
||||
const char STR_ESKY[] ="ESky";
|
||||
const char STR_MT99XX[] ="MT99XX";
|
||||
const char STR_MJXQ[] ="MJXq";
|
||||
const char STR_SHENQI[] ="Shenqi";
|
||||
const char STR_FY326[] ="FY326";
|
||||
const char STR_SFHSS[] ="SFHSS";
|
||||
const char STR_J6PRO[] ="J6 Pro";
|
||||
const char STR_FQ777[] ="FQ777";
|
||||
const char STR_ASSAN[] ="Assan";
|
||||
const char STR_FRSKYV[] ="FrSky V";
|
||||
const char STR_HONTAI[] ="Hontai";
|
||||
const char STR_AFHDS2A[] ="FSky 2A";
|
||||
const char STR_Q2X2[] ="Q2x2";
|
||||
const char STR_WK2x01[] ="Walkera";
|
||||
const char STR_Q303[] ="Q303";
|
||||
const char STR_GW008[] ="GW008";
|
||||
const char STR_DM002[] ="DM002";
|
||||
const char STR_CABELL[] ="Cabell";
|
||||
const char STR_ESKY150[] ="Esky150";
|
||||
const char STR_H8_3D[] ="H8 3D";
|
||||
const char STR_CORONA[] ="Corona";
|
||||
const char STR_CFLIE[] ="CFlie";
|
||||
const char STR_HITEC[] ="Hitec";
|
||||
const char STR_WFLY[] ="WFly";
|
||||
const char STR_BUGS[] ="Bugs";
|
||||
const char STR_BUGSMINI[] ="BugMini";
|
||||
const char STR_TRAXXAS[] ="Traxxas";
|
||||
const char STR_NCC1701[] ="NCC1701";
|
||||
const char STR_E01X[] ="E01X";
|
||||
const char STR_V911S[] ="V911S";
|
||||
const char STR_GD00X[] ="GD00X";
|
||||
const char STR_V761[] ="V761";
|
||||
const char STR_KF606[] ="KF606";
|
||||
const char STR_REDPINE[] ="Redpine";
|
||||
const char STR_POTENSIC[] ="Potensi";
|
||||
const char STR_ZSX[] ="ZSX";
|
||||
const char STR_FLYZONE[] ="FlyZone";
|
||||
const char STR_SCANNER[] ="Scanner";
|
||||
const char STR_FRSKY_RX[] ="FrSkyRX";
|
||||
const char STR_AFHDS2A_RX[] ="FS2A_RX";
|
||||
const char STR_HOTT[] ="HoTT";
|
||||
const char STR_FX816[] ="FX816";
|
||||
const char STR_BAYANG_RX[] ="BayanRX";
|
||||
const char STR_PELIKAN[] ="Pelikan";
|
||||
const char STR_TIGER[] ="Tiger";
|
||||
const char STR_XK[] ="XK";
|
||||
const char STR_XN297DUMP[] ="XN297DP";
|
||||
const char STR_FRSKYR9[] ="FrSkyR9";
|
||||
const char STR_PROPEL[] ="PROPEL";
|
||||
const char STR_SKYARTEC[] ="Skyartc";
|
||||
|
||||
const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20";
|
||||
const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501";
|
||||
const char STR_SUBTYPE_FRSKYD[] = "\x06""D8\0 ""Cloned";
|
||||
const char STR_SUBTYPE_FRSKYX[] = "\x07""D16\0 ""D16 8ch""LBT(EU)""LBT 8ch""Cloned\0";
|
||||
const char STR_SUBTYPE_HISKY[] = "\x05""Std\0 ""HK310";
|
||||
const char STR_SUBTYPE_V2X2[] = "\x06""Std\0 ""JXD506";
|
||||
const char STR_SUBTYPE_DSM[] = "\x06""2 22ms""2 11ms""X 22ms""X 11ms";
|
||||
const char STR_SUBTYPE_DEVO[] = "\x04""8ch\0""10ch""12ch""6ch\0""7ch\0";
|
||||
const char STR_SUBTYPE_YD717[] = "\x07""Std\0 ""SkyWlkr""Syma X4""XINXUN\0""NIHUI\0 ";
|
||||
const char STR_SUBTYPE_KN[] = "\x06""WLtoys""FeiLun";
|
||||
const char STR_SUBTYPE_SYMAX[] = "\x03""Std""X5C";
|
||||
const char STR_SUBTYPE_SLT[] = "\x06""V1_6ch""V2_8ch""Q100\0 ""Q200\0 ""MR100\0";
|
||||
const char STR_SUBTYPE_CX10[] = "\x07""Green\0 ""Blue\0 ""DM007\0 ""-\0 ""JC3015a""JC3015b""MK33041";
|
||||
const char STR_SUBTYPE_CG023[] = "\x05""Std\0 ""YD829";
|
||||
const char STR_SUBTYPE_BAYANG[] = "\x07""Std\0 ""H8S3D\0 ""X16 AH\0""IRDrone""DHD D4";
|
||||
const char STR_SUBTYPE_MT99[] = "\x06""MT99\0 ""H7\0 ""YZ\0 ""LS\0 ""FY805";
|
||||
const char STR_SUBTYPE_MJXQ[] = "\x07""WLH08\0 ""X600\0 ""X800\0 ""H26D\0 ""E010\0 ""H26WH\0 ""Phoenix";
|
||||
const char STR_SUBTYPE_FY326[] = "\x05""Std\0 ""FY319";
|
||||
const char STR_SUBTYPE_HONTAI[] = "\x07""Std\0 ""JJRC X1""X5C1\0 ""FQ_951";
|
||||
const char STR_SUBTYPE_AFHDS2A[] = "\x08""PWM,IBUS""PPM,IBUS""PWM,SBUS""PPM,SBUS";
|
||||
const char STR_SUBTYPE_Q2X2[] = "\x04""Q222""Q242""Q282";
|
||||
const char STR_SUBTYPE_WK2x01[] = "\x06""WK2801""WK2401""W6_5_1""W6_6_1""W6_HeL""W6_HeI";
|
||||
const char STR_SUBTYPE_Q303[] = "\x06""Std\0 ""CX35\0 ""CX10D\0""CX10WD";
|
||||
const char STR_SUBTYPE_CABELL[] = "\x07""V3\0 ""V3 Telm""-\0 ""-\0 ""-\0 ""-\0 ""F-Safe\0""Unbind\0";
|
||||
const char STR_SUBTYPE_H83D[] = "\x07""Std\0 ""H20H\0 ""H20Mini""H30Mini";
|
||||
const char STR_SUBTYPE_CORONA[] = "\x05""V1\0 ""V2\0 ""FD V3";
|
||||
const char STR_SUBTYPE_HITEC[] = "\x07""Optima\0""Opt Hub""Minima\0";
|
||||
const char STR_SUBTYPE_BUGS_MINI[] = "\x06""Std\0 ""Bugs3H";
|
||||
const char STR_SUBTYPE_TRAXXAS[] = "\x04""6519";
|
||||
const char STR_SUBTYPE_E01X[] = "\x05""E012\0""E015\0""E016H";
|
||||
const char STR_SUBTYPE_GD00X[] = "\x05""GD_V1""GD_V2";
|
||||
const char STR_SUBTYPE_REDPINE[] = "\x04""Fast""Slow";
|
||||
const char STR_SUBTYPE_POTENSIC[] = "\x03""A20";
|
||||
const char STR_SUBTYPE_ZSX[] = "\x07""280JJRC";
|
||||
const char STR_SUBTYPE_FLYZONE[] = "\x05""FZ410";
|
||||
const char STR_SUBTYPE_FX816[] = "\x03""P38";
|
||||
const char STR_SUBTYPE_XN297DUMP[] = "\x07""250Kbps""1Mbps\0 ""2Mbps\0 ""Auto\0 ";
|
||||
const char STR_SUBTYPE_ESKY150[] = "\x03""4CH""7CH";
|
||||
const char STR_SUBTYPE_V911S[] = "\x05""V911S""E119\0";
|
||||
const char STR_SUBTYPE_XK[] = "\x04""X450""X420";
|
||||
const char STR_SUBTYPE_FRSKYR9[] = "\x07""915MHz\0""868MHz\0""915 8ch""868 8ch";
|
||||
const char STR_SUBTYPE_ESKY[] = "\x03""Std""ET4";
|
||||
const char STR_SUBTYPE_PROPEL[] = "\x04""74-Z";
|
||||
const char STR_SUBTYPE_FRSKY_RX[] = "\x07""RX\0 ""CloneTX";
|
||||
const char STR_SUBTYPE_FRSKYL[] = "\x08""LR12\0 ""LR12 6ch";
|
||||
|
||||
enum
|
||||
{
|
||||
OPTION_NONE,
|
||||
OPTION_OPTION,
|
||||
OPTION_RFTUNE,
|
||||
OPTION_VIDFREQ,
|
||||
OPTION_FIXEDID,
|
||||
OPTION_TELEM,
|
||||
OPTION_SRVFREQ,
|
||||
OPTION_MAXTHR,
|
||||
OPTION_RFCHAN
|
||||
};
|
||||
|
||||
#define NO_SUBTYPE nullptr
|
||||
|
||||
const mm_protocol_definition multi_protocols[] = {
|
||||
// Protocol number, Protocol String, Number of sub_protocols, Sub_protocol strings, Option type
|
||||
#if defined(ASSAN_NRF24L01_INO)
|
||||
{PROTO_ASSAN, STR_ASSAN, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(BAYANG_NRF24L01_INO)
|
||||
{PROTO_BAYANG, STR_BAYANG, 5, STR_SUBTYPE_BAYANG, OPTION_TELEM },
|
||||
#endif
|
||||
#if defined(BAYANG_RX_NRF24L01_INO)
|
||||
{PROTO_BAYANG_RX, STR_BAYANG_RX, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(BUGS_A7105_INO)
|
||||
{PROTO_BUGS, STR_BUGS, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(BUGSMINI_NRF24L01_INO)
|
||||
{PROTO_BUGSMINI, STR_BUGSMINI, 2, STR_SUBTYPE_BUGS_MINI, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(CABELL_NRF24L01_INO)
|
||||
{PROTO_CABELL, STR_CABELL, 8, STR_SUBTYPE_CABELL, OPTION_OPTION },
|
||||
#endif
|
||||
#if defined(CFLIE_NRF24L01_INO)
|
||||
{PROTO_CFLIE, STR_CFLIE, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(E01X_NRF24L01_INO)
|
||||
{PROTO_E01X, STR_E01X, 3, STR_SUBTYPE_E01X, OPTION_OPTION },
|
||||
#endif
|
||||
#if defined(CG023_NRF24L01_INO)
|
||||
{PROTO_CG023, STR_CG023, 2, STR_SUBTYPE_CG023, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(CORONA_CC2500_INO)
|
||||
{PROTO_CORONA, STR_CORONA, 3, STR_SUBTYPE_CORONA, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(CX10_NRF24L01_INO)
|
||||
{PROTO_CX10, STR_CX10, 7, STR_SUBTYPE_CX10, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(DEVO_CYRF6936_INO)
|
||||
{PROTO_DEVO, STR_DEVO, 5, STR_SUBTYPE_DEVO, OPTION_FIXEDID },
|
||||
#endif
|
||||
#if defined(DM002_NRF24L01_INO)
|
||||
{PROTO_DM002, STR_DM002, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(DSM_CYRF6936_INO)
|
||||
{PROTO_DSM, STR_DSM, 4, STR_SUBTYPE_DSM, OPTION_MAXTHR },
|
||||
#endif
|
||||
#if defined(ESKY_NRF24L01_INO)
|
||||
{PROTO_ESKY, STR_ESKY, 2, STR_SUBTYPE_ESKY, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(ESKY150_NRF24L01_INO)
|
||||
{PROTO_ESKY150, STR_ESKY150, 2, STR_SUBTYPE_ESKY150, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(FLYSKY_A7105_INO)
|
||||
{PROTO_FLYSKY, STR_FLYSKY, 5, STR_SUBTYPE_FLYSKY, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(AFHDS2A_A7105_INO)
|
||||
{PROTO_AFHDS2A, STR_AFHDS2A, 4, STR_SUBTYPE_AFHDS2A, OPTION_SRVFREQ },
|
||||
#endif
|
||||
#if defined(AFHDS2A_RX_A7105_INO)
|
||||
{PROTO_AFHDS2A_RX, STR_AFHDS2A_RX,0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(FLYZONE_A7105_INO)
|
||||
{PROTO_FLYZONE, STR_FLYZONE, 1, STR_SUBTYPE_FLYZONE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(FQ777_NRF24L01_INO)
|
||||
{PROTO_FQ777, STR_FQ777, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
//OpenTX 2.3.x issue: DO NOT CHANGE ORDER below
|
||||
#if defined(FRSKY_RX_CC2500_INO)
|
||||
{PROTO_FRSKY_RX, STR_FRSKY_RX, 2, STR_SUBTYPE_FRSKY_RX, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(FRSKYD_CC2500_INO)
|
||||
{PROTO_FRSKYD, STR_FRSKYD, 2, STR_SUBTYPE_FRSKYD, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(FRSKYV_CC2500_INO)
|
||||
{PROTO_FRSKYV, STR_FRSKYV, 0, NO_SUBTYPE, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(FRSKYX_CC2500_INO)
|
||||
{PROTO_FRSKYX, STR_FRSKYX, 5, STR_SUBTYPE_FRSKYX, OPTION_RFTUNE },
|
||||
{PROTO_FRSKYX2, STR_FRSKYX2, 5, STR_SUBTYPE_FRSKYX, OPTION_RFTUNE },
|
||||
#endif
|
||||
//OpenTX 2.3.x issue: DO NOT CHANGE ORDER above
|
||||
#if defined(FRSKYL_CC2500_INO)
|
||||
{PROTO_FRSKYL, STR_FRSKYL, 2, STR_SUBTYPE_FRSKYL, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(FRSKYR9_SX1276_INO)
|
||||
{PROTO_FRSKY_R9, STR_FRSKYR9, 4, STR_SUBTYPE_FRSKYR9, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(FX816_NRF24L01_INO)
|
||||
{PROTO_FX816, STR_FX816, 1, STR_SUBTYPE_FX816, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(FY326_NRF24L01_INO)
|
||||
{PROTO_FY326, STR_FY326, 2, STR_SUBTYPE_FY326, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(GD00X_NRF24L01_INO)
|
||||
{PROTO_GD00X, STR_GD00X, 2, STR_SUBTYPE_GD00X, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(GW008_NRF24L01_INO)
|
||||
{PROTO_GW008, STR_GW008, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(H8_3D_NRF24L01_INO)
|
||||
{PROTO_H8_3D, STR_H8_3D, 4, STR_SUBTYPE_H83D, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(HISKY_NRF24L01_INO)
|
||||
{PROTO_HISKY, STR_HISKY, 2, STR_SUBTYPE_HISKY, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(HITEC_CC2500_INO)
|
||||
{PROTO_HITEC, STR_HITEC, 3, STR_SUBTYPE_HITEC, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(HONTAI_NRF24L01_INO)
|
||||
{PROTO_HONTAI, STR_HONTAI, 4, STR_SUBTYPE_HONTAI, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(HOTT_CC2500_INO)
|
||||
{PROTO_HOTT, STR_HOTT, 0, NO_SUBTYPE, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(HUBSAN_A7105_INO)
|
||||
{PROTO_HUBSAN, STR_HUBSAN, 3, STR_SUBTYPE_HUBSAN, OPTION_VIDFREQ },
|
||||
#endif
|
||||
#if defined(J6PRO_CYRF6936_INO)
|
||||
{PROTO_J6PRO, STR_J6PRO, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(KF606_NRF24L01_INO)
|
||||
{PROTO_KF606, STR_KF606, 0, NO_SUBTYPE, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(KN_NRF24L01_INO)
|
||||
{PROTO_KN, STR_KN, 2, STR_SUBTYPE_KN, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(MJXQ_NRF24L01_INO)
|
||||
{PROTO_MJXQ, STR_MJXQ, 7, STR_SUBTYPE_MJXQ, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(MT99XX_NRF24L01_INO)
|
||||
{PROTO_MT99XX, STR_MT99XX, 5, STR_SUBTYPE_MT99, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(NCC1701_NRF24L01_INO)
|
||||
{PROTO_NCC1701, STR_NCC1701, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(PELIKAN_A7105_INO)
|
||||
{PROTO_PELIKAN, STR_PELIKAN , 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(POTENSIC_NRF24L01_INO)
|
||||
{PROTO_POTENSIC, STR_POTENSIC, 1, STR_SUBTYPE_POTENSIC, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(PROPEL_NRF24L01_INO)
|
||||
{PROTO_PROPEL, STR_PROPEL, 4, STR_SUBTYPE_PROPEL, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(CX10_NRF24L01_INO)
|
||||
{PROTO_Q2X2, STR_Q2X2, 3, STR_SUBTYPE_Q2X2, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(Q303_NRF24L01_INO)
|
||||
{PROTO_Q303, STR_Q303, 4, STR_SUBTYPE_Q303, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(REDPINE_CC2500_INO)
|
||||
{PROTO_REDPINE, STR_REDPINE, 2, STR_SUBTYPE_REDPINE, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(SCANNER_CC2500_INO)
|
||||
{PROTO_SCANNER, STR_SCANNER, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(SFHSS_CC2500_INO)
|
||||
{PROTO_SFHSS, STR_SFHSS, 0, NO_SUBTYPE, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(SHENQI_NRF24L01_INO)
|
||||
{PROTO_SHENQI, STR_SHENQI, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(SKYARTEC_CC2500_INO)
|
||||
{PROTO_SKYARTEC, STR_SKYARTEC, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(SLT_NRF24L01_INO)
|
||||
{PROTO_SLT, STR_SLT, 5, STR_SUBTYPE_SLT, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(SYMAX_NRF24L01_INO)
|
||||
{PROTO_SYMAX, STR_SYMAX, 2, STR_SUBTYPE_SYMAX, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(TIGER_NRF24L01_INO)
|
||||
{PROTO_TIGER, STR_TIGER , 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(TRAXXAS_CYRF6936_INO)
|
||||
{PROTO_TRAXXAS, STR_TRAXXAS, 1, STR_SUBTYPE_TRAXXAS, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(V2X2_NRF24L01_INO)
|
||||
{PROTO_V2X2, STR_V2X2, 2, STR_SUBTYPE_V2X2, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(V761_NRF24L01_INO)
|
||||
{PROTO_V761, STR_V761, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(V911S_NRF24L01_INO)
|
||||
{PROTO_V911S, STR_V911S, 2, STR_SUBTYPE_V911S, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(WFLY_CYRF6936_INO)
|
||||
{PROTO_WFLY, STR_WFLY, 0, NO_SUBTYPE, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(WK2x01_CYRF6936_INO)
|
||||
{PROTO_WK2x01, STR_WK2x01, 6, STR_SUBTYPE_WK2x01, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(XK_NRF24L01_INO)
|
||||
{PROTO_XK, STR_XK , 2, STR_SUBTYPE_XK, OPTION_RFTUNE },
|
||||
#endif
|
||||
#if defined(XN297DUMP_NRF24L01_INO)
|
||||
{PROTO_XN297DUMP, STR_XN297DUMP, 4, STR_SUBTYPE_XN297DUMP, OPTION_RFCHAN },
|
||||
#endif
|
||||
#if defined(YD717_NRF24L01_INO)
|
||||
{PROTO_YD717, STR_YD717, 5, STR_SUBTYPE_YD717, OPTION_NONE },
|
||||
#endif
|
||||
#if defined(ZSX_NRF24L01_INO)
|
||||
{PROTO_ZSX, STR_ZSX, 1, STR_SUBTYPE_ZSX, OPTION_NONE },
|
||||
#endif
|
||||
{0x00, nullptr, 0, nullptr, 0 }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
449
Multiprotocol/Multi_Protos.ino
Normal file
449
Multiprotocol/Multi_Protos.ino
Normal file
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const char STR_FLYSKY[] ="FlySky";
|
||||
const char STR_HUBSAN[] ="Hubsan";
|
||||
const char STR_FRSKYD[] ="FrSky D";
|
||||
const char STR_HISKY[] ="Hisky";
|
||||
const char STR_V2X2[] ="V2x2";
|
||||
const char STR_DSM[] ="DSM";
|
||||
const char STR_DSM_RX[] ="DSM_RX";
|
||||
const char STR_DEVO[] ="Devo";
|
||||
const char STR_YD717[] ="YD717";
|
||||
const char STR_KN[] ="KN";
|
||||
const char STR_SYMAX[] ="SymaX";
|
||||
const char STR_SLT[] ="SLT";
|
||||
const char STR_CX10[] ="CX10";
|
||||
const char STR_CG023[] ="CG023";
|
||||
const char STR_BAYANG[] ="Bayang";
|
||||
const char STR_FRSKYL[] ="FrSky L";
|
||||
const char STR_FRSKYX[] ="FrSky X";
|
||||
const char STR_FRSKYX2[] ="FrSkyX2";
|
||||
const char STR_ESKY[] ="ESky";
|
||||
const char STR_MT99XX[] ="MT99XX";
|
||||
const char STR_MJXQ[] ="MJXq";
|
||||
const char STR_SHENQI[] ="Shenqi";
|
||||
const char STR_FY326[] ="FY326";
|
||||
const char STR_FUTABA[] ="Futaba";
|
||||
const char STR_J6PRO[] ="J6 Pro";
|
||||
const char STR_JJRC345[] ="JJRC345";
|
||||
const char STR_JOYSWAY[] ="JOYSWAY";
|
||||
const char STR_FQ777[] ="FQ777";
|
||||
const char STR_ASSAN[] ="Assan";
|
||||
const char STR_FRSKYV[] ="FrSky V";
|
||||
const char STR_HONTAI[] ="Hontai";
|
||||
const char STR_AFHDS2A[] ="FlSky2A";
|
||||
const char STR_Q2X2[] ="Q2x2";
|
||||
const char STR_WK2x01[] ="Walkera";
|
||||
const char STR_Q303[] ="Q303";
|
||||
const char STR_Q90C[] ="Q90C";
|
||||
const char STR_GW008[] ="GW008";
|
||||
const char STR_DM002[] ="DM002";
|
||||
const char STR_CABELL[] ="Cabell";
|
||||
const char STR_ESKY150[] ="Esky150";
|
||||
const char STR_ESKY150V2[] ="EskyV2";
|
||||
const char STR_H8_3D[] ="H8 3D";
|
||||
const char STR_CORONA[] ="Corona";
|
||||
const char STR_CFLIE[] ="CFlie";
|
||||
const char STR_HITEC[] ="Hitec";
|
||||
const char STR_WFLY[] ="WFLY";
|
||||
const char STR_WFLY2[] ="WFLY2";
|
||||
const char STR_BUGS[] ="Bugs";
|
||||
const char STR_BUGSMINI[] ="BugMini";
|
||||
const char STR_TRAXXAS[] ="Traxxas";
|
||||
const char STR_NCC1701[] ="NCC1701";
|
||||
const char STR_E01X[] ="E01X";
|
||||
const char STR_V911S[] ="V911S";
|
||||
const char STR_GD00X[] ="GD00x";
|
||||
const char STR_V761[] ="V761";
|
||||
const char STR_KF606[] ="KF606";
|
||||
const char STR_REDPINE[] ="Redpine";
|
||||
const char STR_POTENSIC[] ="Potensi";
|
||||
const char STR_ZSX[] ="ZSX";
|
||||
const char STR_HEIGHT[] ="Height";
|
||||
const char STR_SCANNER[] ="Scanner";
|
||||
const char STR_FRSKY_RX[] ="FrSkyRX";
|
||||
const char STR_AFHDS2A_RX[] ="FS2A_RX";
|
||||
const char STR_HOTT[] ="HoTT";
|
||||
const char STR_FX816[] ="FX816";
|
||||
const char STR_BAYANG_RX[] ="BayanRX";
|
||||
const char STR_PELIKAN[] ="Pelikan";
|
||||
const char STR_TIGER[] ="Tiger";
|
||||
const char STR_XK[] ="XK";
|
||||
const char STR_XN297DUMP[] ="XN297DP";
|
||||
const char STR_FRSKYR9[] ="FrSkyR9";
|
||||
const char STR_PROPEL[] ="Propel";
|
||||
const char STR_SKYARTEC[] ="Skyartc";
|
||||
const char STR_KYOSHO[] ="Kyosho";
|
||||
const char STR_RLINK[] ="RadLink";
|
||||
const char STR_REALACC[] ="Realacc";
|
||||
const char STR_OMP[] ="OMP";
|
||||
const char STR_MLINK[] ="M-Link";
|
||||
const char STR_TEST[] ="Test";
|
||||
const char STR_NANORF[] ="NanoRF";
|
||||
const char STR_E016HV2[] ="E016Hv2";
|
||||
const char STR_E010R5[] ="E010r5";
|
||||
const char STR_LOLI[] ="LOLI";
|
||||
const char STR_E129[] ="E129";
|
||||
|
||||
const char STR_SUBTYPE_FLYSKY[] = "\x04""Std\0""V9x9""V6x6""V912""CX20";
|
||||
const char STR_SUBTYPE_HUBSAN[] = "\x04""H107""H301""H501";
|
||||
const char STR_SUBTYPE_FRSKYD[] = "\x06""D8\0 ""Cloned";
|
||||
const char STR_SUBTYPE_FRSKYX[] = "\x07""D16\0 ""D16 8ch""LBT(EU)""LBT 8ch""Cloned\0""Clo 8ch";
|
||||
const char STR_SUBTYPE_HISKY[] = "\x05""Std\0 ""HK310";
|
||||
const char STR_SUBTYPE_V2X2[] = "\x06""Std\0 ""JXD506""MR101\0";
|
||||
const char STR_SUBTYPE_DSM[] = "\x04""2 1F""2 2F""X 1F""X 2F""Auto";
|
||||
const char STR_SUBTYPE_DEVO[] = "\x04""8ch\0""10ch""12ch""6ch\0""7ch\0";
|
||||
const char STR_SUBTYPE_YD717[] = "\x07""Std\0 ""SkyWlkr""Syma X4""XINXUN\0""NIHUI\0 ";
|
||||
const char STR_SUBTYPE_KN[] = "\x06""WLtoys""FeiLun";
|
||||
const char STR_SUBTYPE_SYMAX[] = "\x03""Std""X5C";
|
||||
const char STR_SUBTYPE_SLT[] = "\x06""V1_6ch""V2_8ch""Q100\0 ""Q200\0 ""MR100\0";
|
||||
const char STR_SUBTYPE_CX10[] = "\x07""Green\0 ""Blue\0 ""DM007\0 ""-\0 ""JC3015a""JC3015b""MK33041";
|
||||
const char STR_SUBTYPE_CG023[] = "\x05""Std\0 ""YD829";
|
||||
const char STR_SUBTYPE_BAYANG[] = "\x07""Std\0 ""H8S3D\0 ""X16 AH\0""IRDrone""DHD D4\0""QX100\0 ";
|
||||
const char STR_SUBTYPE_MT99[] = "\x06""MT99\0 ""H7\0 ""YZ\0 ""LS\0 ""FY805\0""A180\0 ""Dragon";
|
||||
const char STR_SUBTYPE_MJXQ[] = "\x07""WLH08\0 ""X600\0 ""X800\0 ""H26D\0 ""E010\0 ""H26WH\0 ""Phoenix";
|
||||
const char STR_SUBTYPE_FY326[] = "\x05""Std\0 ""FY319";
|
||||
const char STR_SUBTYPE_HONTAI[] = "\x07""Std\0 ""JJRC X1""X5C1\0 ""FQ_951";
|
||||
const char STR_SUBTYPE_AFHDS2A[] = "\x08""PWM,IBUS""PPM,IBUS""PWM,SBUS""PPM,SBUS""PWM,IB16""PPM,IB16""PWM,SB16""PPM,SB16";
|
||||
const char STR_SUBTYPE_Q2X2[] = "\x04""Q222""Q242""Q282";
|
||||
const char STR_SUBTYPE_WK2x01[] = "\x06""WK2801""WK2401""W6_5_1""W6_6_1""W6_HeL""W6_HeI";
|
||||
const char STR_SUBTYPE_Q303[] = "\x06""Std\0 ""CX35\0 ""CX10D\0""CX10WD";
|
||||
const char STR_SUBTYPE_CABELL[] = "\x07""V3\0 ""V3 Telm""-\0 ""-\0 ""-\0 ""-\0 ""F-Safe\0""Unbind\0";
|
||||
const char STR_SUBTYPE_H83D[] = "\x07""Std\0 ""H20H\0 ""H20Mini""H30Mini";
|
||||
const char STR_SUBTYPE_CORONA[] = "\x05""V1\0 ""V2\0 ""FD V3";
|
||||
const char STR_SUBTYPE_HITEC[] = "\x07""Optima\0""Opt Hub""Minima\0";
|
||||
const char STR_SUBTYPE_BUGS_MINI[] = "\x06""Std\0 ""Bugs3H";
|
||||
const char STR_SUBTYPE_TRAXXAS[] = "\x04""6519";
|
||||
const char STR_SUBTYPE_E01X[] = "\x05""E012\0""E015\0""E016H";
|
||||
const char STR_SUBTYPE_GD00X[] = "\x05""GD_V1""GD_V2";
|
||||
const char STR_SUBTYPE_REDPINE[] = "\x04""Fast""Slow";
|
||||
const char STR_SUBTYPE_POTENSIC[] = "\x03""A20";
|
||||
const char STR_SUBTYPE_ZSX[] = "\x07""280JJRC";
|
||||
const char STR_SUBTYPE_HEIGHT[] = "\x03""5ch""8ch";
|
||||
const char STR_SUBTYPE_FX816[] = "\x03""P38";
|
||||
const char STR_SUBTYPE_XN297DUMP[] = "\x07""250Kbps""1Mbps\0 ""2Mbps\0 ""Auto\0 ""NRF\0 ";
|
||||
const char STR_SUBTYPE_ESKY150[] = "\x03""4ch""7ch";
|
||||
const char STR_SUBTYPE_ESKY150V2[] = "\x05""150V2";
|
||||
const char STR_SUBTYPE_V911S[] = "\x05""V911S""E119\0";
|
||||
const char STR_SUBTYPE_XK[] = "\x04""X450""X420";
|
||||
const char STR_SUBTYPE_FRSKYR9[] = "\x07""915MHz\0""868MHz\0""915 8ch""868 8ch""FCC\0 ""--\0 ""FCC 8ch""-- 8ch\0";
|
||||
const char STR_SUBTYPE_ESKY[] = "\x03""Std""ET4";
|
||||
const char STR_SUBTYPE_PROPEL[] = "\x04""74-Z";
|
||||
const char STR_SUBTYPE_FRSKYL[] = "\x08""LR12\0 ""LR12 6ch";
|
||||
const char STR_SUBTYPE_WFLY[] = "\x05""WFR0x";
|
||||
const char STR_SUBTYPE_WFLY2[] = "\x05""RF20x";
|
||||
const char STR_SUBTYPE_HOTT[] = "\x07""Sync\0 ""No_Sync";
|
||||
const char STR_SUBTYPE_PELIKAN[] = "\x04""Pro\0""Lite";
|
||||
const char STR_SUBTYPE_V761[] = "\x03""3ch""4ch";
|
||||
const char STR_SUBTYPE_RLINK[] = "\x07""Surface""Air\0 ""DumboRC";
|
||||
const char STR_SUBTYPE_REALACC[] = "\x03""R11";
|
||||
const char STR_SUBTYPE_KYOSHO[] = "\x04""FHSS""Hype";
|
||||
const char STR_SUBTYPE_FUTABA[] = "\x05""SFHSS";
|
||||
const char STR_SUBTYPE_JJRC345[] = "\x08""JJRC345\0""SkyTmblr";
|
||||
|
||||
#define NO_SUBTYPE nullptr
|
||||
|
||||
#ifdef SEND_CPPM
|
||||
const char STR_SUB_FRSKY_RX[] = "\x07""Multi\0 ""CloneTX""EraseTX""CPPM\0 ";
|
||||
#define FRCPPM 4
|
||||
const char STR_CPPM[] = "\x05""Multi""CPPM\0";
|
||||
#define NBR_CPPM 2
|
||||
#else
|
||||
const char STR_SUB_FRSKY_RX[] = "\x07""Multi\0 ""CloneTX""EraseTX";
|
||||
#define FRCPPM 3
|
||||
#define STR_CPPM NO_SUBTYPE
|
||||
#define NBR_CPPM 0
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
OPTION_NONE,
|
||||
OPTION_OPTION,
|
||||
OPTION_RFTUNE,
|
||||
OPTION_VIDFREQ,
|
||||
OPTION_FIXEDID,
|
||||
OPTION_TELEM,
|
||||
OPTION_SRVFREQ,
|
||||
OPTION_MAXTHR,
|
||||
OPTION_RFCHAN,
|
||||
OPTION_RFPOWER,
|
||||
OPTION_WBUS,
|
||||
};
|
||||
|
||||
const mm_protocol_definition multi_protocols[] = {
|
||||
// Protocol number, Protocol String, Sub_protocol strings, Number of sub_protocols, Option type, Failsafe, ChMap, RF switch, Init, Callback
|
||||
#if defined(MULTI_CONFIG_INO)
|
||||
{PROTO_CONFIG, STR_CONFIG, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, 0, CONFIG_init, CONFIG_callback },
|
||||
#endif
|
||||
#if defined(ASSAN_NRF24L01_INO)
|
||||
{PROTO_ASSAN, STR_ASSAN, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, ASSAN_init, ASSAN_callback },
|
||||
#endif
|
||||
#if defined(BAYANG_NRF24L01_INO)
|
||||
{PROTO_BAYANG, STR_BAYANG, STR_SUBTYPE_BAYANG, 6, OPTION_TELEM, 0, 0, SW_NRF, BAYANG_init, BAYANG_callback },
|
||||
#endif
|
||||
#if defined(BAYANG_RX_NRF24L01_INO)
|
||||
{PROTO_BAYANG_RX, STR_BAYANG_RX, STR_CPPM, NBR_CPPM, OPTION_NONE, 0, 0, SW_NRF, BAYANG_RX_init, BAYANG_RX_callback },
|
||||
#endif
|
||||
#if defined(BUGS_A7105_INO)
|
||||
{PROTO_BUGS, STR_BUGS, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_A7105, BUGS_init, BUGS_callback },
|
||||
#endif
|
||||
#if defined(BUGSMINI_NRF24L01_INO)
|
||||
{PROTO_BUGSMINI, STR_BUGSMINI, STR_SUBTYPE_BUGS_MINI, 2, OPTION_NONE, 0, 0, SW_NRF, BUGSMINI_init, BUGSMINI_callback },
|
||||
#endif
|
||||
#if defined(CABELL_NRF24L01_INO)
|
||||
{PROTO_CABELL, STR_CABELL, STR_SUBTYPE_CABELL, 8, OPTION_OPTION, 0, 0, SW_NRF, CABELL_init, CABELL_callback },
|
||||
#endif
|
||||
#if defined(CFLIE_NRF24L01_INO)
|
||||
{PROTO_CFLIE, STR_CFLIE, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, CFLIE_init, CFLIE_callback }, // review protocol
|
||||
#endif
|
||||
#if defined(CG023_NRF24L01_INO)
|
||||
{PROTO_CG023, STR_CG023, STR_SUBTYPE_CG023, 2, OPTION_NONE, 0, 0, SW_NRF, CG023_init, CG023_callback },
|
||||
#endif
|
||||
#if defined(CORONA_CC2500_INO)
|
||||
{PROTO_CORONA, STR_CORONA, STR_SUBTYPE_CORONA, 3, OPTION_RFTUNE, 0, 0, SW_CC2500, CORONA_init, CORONA_callback },
|
||||
#endif
|
||||
#if defined(CX10_NRF24L01_INO)
|
||||
{PROTO_CX10, STR_CX10, STR_SUBTYPE_CX10, 7, OPTION_NONE, 0, 0, SW_NRF, CX10_init, CX10_callback },
|
||||
#endif
|
||||
#if defined(DEVO_CYRF6936_INO)
|
||||
{PROTO_DEVO, STR_DEVO, STR_SUBTYPE_DEVO, 5, OPTION_FIXEDID, 1, 1, SW_CYRF, DEVO_init, DEVO_callback },
|
||||
#endif
|
||||
#if defined(DM002_NRF24L01_INO)
|
||||
{PROTO_DM002, STR_DM002, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, DM002_init, DM002_callback },
|
||||
#endif
|
||||
#if defined(DSM_CYRF6936_INO)
|
||||
{PROTO_DSM, STR_DSM, STR_SUBTYPE_DSM, 5, OPTION_MAXTHR, 0, 1, SW_CYRF, DSM_init, DSM_callback },
|
||||
#endif
|
||||
#if defined(DSM_RX_CYRF6936_INO)
|
||||
{PROTO_DSM_RX, STR_DSM_RX, STR_CPPM, NBR_CPPM, OPTION_NONE, 0, 1, SW_CYRF, DSM_RX_init, DSM_RX_callback },
|
||||
#endif
|
||||
#if defined(E010R5_CYRF6936_INO)
|
||||
{PROTO_E010R5, STR_E010R5, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_CYRF, E010R5_init, E010R5_callback },
|
||||
#endif
|
||||
#if defined(E016HV2_CC2500_INO)
|
||||
{PROTO_E016HV2, STR_E016HV2, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_CC2500, E016HV2_init, E016HV2_callback },
|
||||
#endif
|
||||
#if defined(E01X_NRF24L01_INO)
|
||||
{PROTO_E01X, STR_E01X, STR_SUBTYPE_E01X, 3, OPTION_OPTION, 0, 0, SW_NRF, E01X_init, E01X_callback },
|
||||
#endif
|
||||
#if defined(E129_CYRF6936_INO)
|
||||
{PROTO_E129, STR_E129, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_CYRF, E129_init, E129_callback },
|
||||
#endif
|
||||
#if defined(ESKY_NRF24L01_INO)
|
||||
{PROTO_ESKY, STR_ESKY, STR_SUBTYPE_ESKY, 2, OPTION_NONE, 0, 1, SW_NRF, ESKY_init, ESKY_callback },
|
||||
#endif
|
||||
#if defined(ESKY150_NRF24L01_INO)
|
||||
{PROTO_ESKY150, STR_ESKY150, STR_SUBTYPE_ESKY150, 2, OPTION_NONE, 0, 0, SW_NRF, ESKY150_init, ESKY150_callback },
|
||||
#endif
|
||||
#if defined(ESKY150V2_CC2500_INO)
|
||||
{PROTO_ESKY150V2, STR_ESKY150V2, STR_SUBTYPE_ESKY150V2, 1, OPTION_RFTUNE, 0, 1, SW_CC2500, ESKY150V2_init, ESKY150V2_callback },
|
||||
#endif
|
||||
#if defined(FLYSKY_A7105_INO)
|
||||
{PROTO_FLYSKY, STR_FLYSKY, STR_SUBTYPE_FLYSKY, 5, OPTION_NONE, 0, 1, SW_A7105, FLYSKY_init, FLYSKY_callback },
|
||||
#endif
|
||||
#if defined(AFHDS2A_A7105_INO)
|
||||
{PROTO_AFHDS2A, STR_AFHDS2A, STR_SUBTYPE_AFHDS2A, 8, OPTION_SRVFREQ, 1, 1, SW_A7105, AFHDS2A_init, AFHDS2A_callback },
|
||||
#endif
|
||||
#if defined(AFHDS2A_RX_A7105_INO)
|
||||
{PROTO_AFHDS2A_RX, STR_AFHDS2A_RX,STR_CPPM, NBR_CPPM, OPTION_NONE, 0, 0, SW_A7105, AFHDS2A_RX_init, AFHDS2A_RX_callback },
|
||||
#endif
|
||||
#if defined(FQ777_NRF24L01_INO)
|
||||
{PROTO_FQ777, STR_FQ777, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, FQ777_init, FQ777_callback },
|
||||
#endif
|
||||
//OpenTX 2.3.x issue: DO NOT CHANGE ORDER below
|
||||
#if defined(FRSKY_RX_CC2500_INO)
|
||||
{PROTO_FRSKY_RX, STR_FRSKY_RX, STR_SUB_FRSKY_RX, FRCPPM, OPTION_RFTUNE, 0, 0, SW_CC2500, FRSKY_RX_init, FRSKY_RX_callback },
|
||||
#endif
|
||||
#if defined(FRSKYD_CC2500_INO)
|
||||
{PROTO_FRSKYD, STR_FRSKYD, STR_SUBTYPE_FRSKYD, 2, OPTION_RFTUNE, 0, 0, SW_CC2500, FRSKYD_init, FRSKYD_callback },
|
||||
#endif
|
||||
#if defined(FRSKYV_CC2500_INO)
|
||||
{PROTO_FRSKYV, STR_FRSKYV, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_CC2500, FRSKYV_init, FRSKYV_callback },
|
||||
#endif
|
||||
#if defined(FRSKYX_CC2500_INO)
|
||||
{PROTO_FRSKYX, STR_FRSKYX, STR_SUBTYPE_FRSKYX, 6, OPTION_RFTUNE, 1, 0, SW_CC2500, FRSKYX_init, FRSKYX_callback },
|
||||
{PROTO_FRSKYX2, STR_FRSKYX2, STR_SUBTYPE_FRSKYX, 6, OPTION_RFTUNE, 1, 0, SW_CC2500, FRSKYX_init, FRSKYX_callback },
|
||||
#endif
|
||||
//OpenTX 2.3.x issue: DO NOT CHANGE ORDER above
|
||||
#if defined(FRSKYL_CC2500_INO)
|
||||
{PROTO_FRSKYL, STR_FRSKYL, STR_SUBTYPE_FRSKYL, 2, OPTION_RFTUNE, 0, 0, SW_CC2500, FRSKYL_init, FRSKYL_callback },
|
||||
#endif
|
||||
#if defined(FRSKYR9_SX1276_INO)
|
||||
#if MULTI_5IN1_INTERNAL == T18
|
||||
{PROTO_FRSKY_R9, STR_FRSKYR9, STR_SUBTYPE_FRSKYR9, 8, OPTION_NONE, 1, 0, 0, FRSKYR9_init, FRSKYR9_callback },
|
||||
#else // DIY & T-Lite
|
||||
{PROTO_FRSKY_R9, STR_FRSKYR9, STR_SUBTYPE_FRSKYR9, 8, OPTION_RFPOWER, 1, 0, 0, FRSKYR9_init, FRSKYR9_callback },
|
||||
#endif
|
||||
#endif
|
||||
#if defined(FUTABA_CC2500_INO)
|
||||
{PROTO_FUTABA, STR_FUTABA, STR_SUBTYPE_FUTABA, 1, OPTION_RFTUNE, 1, 1, SW_CC2500, SFHSS_init, SFHSS_callback },
|
||||
#endif
|
||||
#if defined(FX816_NRF24L01_INO)
|
||||
{PROTO_FX816, STR_FX816, STR_SUBTYPE_FX816, 1, OPTION_NONE, 0, 0, SW_NRF, FX816_init, FX816_callback },
|
||||
#endif
|
||||
#if defined(FY326_NRF24L01_INO)
|
||||
{PROTO_FY326, STR_FY326, STR_SUBTYPE_FY326, 2, OPTION_NONE, 0, 0, SW_NRF, FY326_init, FY326_callback },
|
||||
#endif
|
||||
#if defined(GD00X_CCNRF_INO)
|
||||
{PROTO_GD00X, STR_GD00X, STR_SUBTYPE_GD00X, 2, OPTION_RFTUNE, 0, 0, SW_NRF, GD00X_init, GD00X_callback },
|
||||
#endif
|
||||
#if defined(GW008_NRF24L01_INO)
|
||||
{PROTO_GW008, STR_GW008, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, GW008_init, GW008_callback },
|
||||
#endif
|
||||
#if defined(H8_3D_NRF24L01_INO)
|
||||
{PROTO_H8_3D, STR_H8_3D, STR_SUBTYPE_H83D, 4, OPTION_NONE, 0, 0, SW_NRF, H8_3D_init, H8_3D_callback },
|
||||
#endif
|
||||
#if defined(HEIGHT_A7105_INO)
|
||||
{PROTO_HEIGHT, STR_HEIGHT, STR_SUBTYPE_HEIGHT, 2, OPTION_NONE, 0, 0, SW_A7105, HEIGHT_init, HEIGHT_callback },
|
||||
#endif
|
||||
#if defined(HISKY_NRF24L01_INO)
|
||||
{PROTO_HISKY, STR_HISKY, STR_SUBTYPE_HISKY, 2, OPTION_NONE, 1, 1, SW_NRF, HISKY_init, HISKY_callback },
|
||||
#endif
|
||||
#if defined(HITEC_CC2500_INO)
|
||||
{PROTO_HITEC, STR_HITEC, STR_SUBTYPE_HITEC, 3, OPTION_RFTUNE, 0, 0, SW_CC2500, HITEC_init, HITEC_callback },
|
||||
#endif
|
||||
#if defined(HONTAI_NRF24L01_INO)
|
||||
{PROTO_HONTAI, STR_HONTAI, STR_SUBTYPE_HONTAI, 4, OPTION_NONE, 0, 0, SW_NRF, HONTAI_init, HONTAI_callback },
|
||||
#endif
|
||||
#if defined(HOTT_CC2500_INO)
|
||||
{PROTO_HOTT, STR_HOTT, STR_SUBTYPE_HOTT, 2, OPTION_RFTUNE, 1, 0, SW_CC2500, HOTT_init, HOTT_callback },
|
||||
#endif
|
||||
#if defined(HUBSAN_A7105_INO)
|
||||
{PROTO_HUBSAN, STR_HUBSAN, STR_SUBTYPE_HUBSAN, 3, OPTION_VIDFREQ, 0, 0, SW_A7105, HUBSAN_init, HUBSAN_callback },
|
||||
#endif
|
||||
#if defined(J6PRO_CYRF6936_INO)
|
||||
{PROTO_J6PRO, STR_J6PRO, NO_SUBTYPE, 0, OPTION_NONE, 0, 1, SW_CYRF, J6PRO_init, J6PRO_callback },
|
||||
#endif
|
||||
#if defined(JJRC345_NRF24L01_INO)
|
||||
{PROTO_JJRC345, STR_JJRC345, STR_SUBTYPE_JJRC345, 2, OPTION_NONE, 0, 0, SW_NRF, JJRC345_init, JJRC345_callback },
|
||||
#endif
|
||||
#if defined(JOYSWAY_A7105_INO)
|
||||
{PROTO_JOYSWAY, STR_JOYSWAY, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_A7105, JOYSWAY_init, JOYSWAY_callback },
|
||||
#endif
|
||||
#if defined(KF606_CCNRF_INO)
|
||||
{PROTO_KF606, STR_KF606, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, KF606_init, KF606_callback },
|
||||
#endif
|
||||
#if defined(KN_NRF24L01_INO)
|
||||
{PROTO_KN, STR_KN, STR_SUBTYPE_KN, 2, OPTION_NONE, 0, 0, SW_NRF, KN_init, KN_callback },
|
||||
#endif
|
||||
#if defined(KYOSHO_A7105_INO)
|
||||
{PROTO_KYOSHO, STR_KYOSHO, STR_SUBTYPE_KYOSHO, 2, OPTION_NONE, 0, 1, SW_A7105, KYOSHO_init, KYOSHO_callback },
|
||||
#endif
|
||||
#if defined(LOLI_NRF24L01_INO)
|
||||
{PROTO_LOLI, STR_LOLI, NO_SUBTYPE, 0, OPTION_NONE, 1, 0, SW_NRF, LOLI_init, LOLI_callback },
|
||||
#endif
|
||||
#if defined(MJXQ_NRF24L01_INO)
|
||||
{PROTO_MJXQ, STR_MJXQ, STR_SUBTYPE_MJXQ, 7, OPTION_RFTUNE, 0, 0, SW_NRF, MJXQ_init, MJXQ_callback },
|
||||
#endif
|
||||
#if defined(MLINK_CYRF6936_INO)
|
||||
{PROTO_MLINK, STR_MLINK, NO_SUBTYPE, 0, OPTION_NONE, 1, 0, SW_CYRF, MLINK_init, MLINK_callback },
|
||||
#endif
|
||||
#if defined(MT99XX_NRF24L01_INO)
|
||||
{PROTO_MT99XX, STR_MT99XX, STR_SUBTYPE_MT99, 7, OPTION_NONE, 0, 0, SW_NRF, MT99XX_init, MT99XX_callback },
|
||||
#endif
|
||||
#if defined(NCC1701_NRF24L01_INO)
|
||||
{PROTO_NCC1701, STR_NCC1701, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, NCC_init, NCC_callback },
|
||||
#endif
|
||||
#if defined(OMP_CC2500_INO)
|
||||
{PROTO_OMP, STR_OMP, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, OMP_init, OMP_callback },
|
||||
#endif
|
||||
#if defined(PELIKAN_A7105_INO)
|
||||
{PROTO_PELIKAN, STR_PELIKAN, STR_SUBTYPE_PELIKAN, 2, OPTION_NONE, 0, 1, SW_A7105, PELIKAN_init, PELIKAN_callback },
|
||||
#endif
|
||||
#if defined(POTENSIC_NRF24L01_INO)
|
||||
{PROTO_POTENSIC, STR_POTENSIC, STR_SUBTYPE_POTENSIC, 1, OPTION_NONE, 0, 0, SW_NRF, POTENSIC_init, POTENSIC_callback },
|
||||
#endif
|
||||
#if defined(PROPEL_NRF24L01_INO)
|
||||
{PROTO_PROPEL, STR_PROPEL, STR_SUBTYPE_PROPEL, 1, OPTION_NONE, 0, 0, SW_NRF, PROPEL_init, PROPEL_callback },
|
||||
#endif
|
||||
#if defined(CX10_NRF24L01_INO)
|
||||
{PROTO_Q2X2, STR_Q2X2, STR_SUBTYPE_Q2X2, 3, OPTION_NONE, 0, 0, SW_NRF, CX10_init, CX10_callback },
|
||||
#endif
|
||||
#if defined(Q303_NRF24L01_INO)
|
||||
{PROTO_Q303, STR_Q303, STR_SUBTYPE_Q303, 4, OPTION_NONE, 0, 0, SW_NRF, Q303_init, Q303_callback },
|
||||
#endif
|
||||
#if defined(Q90C_CCNRF_INO)
|
||||
{PROTO_Q90C, STR_Q90C, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, Q90C_init, Q90C_callback },
|
||||
#endif
|
||||
#if defined(RLINK_CC2500_INO)
|
||||
{PROTO_RLINK, STR_RLINK, STR_SUBTYPE_RLINK, 3, OPTION_RFTUNE, 0, 0, SW_CC2500, RLINK_init, RLINK_callback },
|
||||
#endif
|
||||
#if defined(REALACC_NRF24L01_INO)
|
||||
{PROTO_REALACC, STR_REALACC, STR_SUBTYPE_REALACC, 1, OPTION_NONE, 0, 0, SW_NRF, REALACC_init, REALACC_callback },
|
||||
#endif
|
||||
#if defined(REDPINE_CC2500_INO)
|
||||
{PROTO_REDPINE, STR_REDPINE, STR_SUBTYPE_REDPINE, 2, OPTION_RFTUNE, 0, 0, SW_CC2500, REDPINE_init, REDPINE_callback },
|
||||
#endif
|
||||
#if defined(SCANNER_CC2500_INO)
|
||||
{PROTO_SCANNER, STR_SCANNER, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_CC2500, SCANNER_init, SCANNER_callback },
|
||||
#endif
|
||||
#if defined(SHENQI_NRF24L01_INO)
|
||||
{PROTO_SHENQI, STR_SHENQI, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, SHENQI_init, SHENQI_callback },
|
||||
#endif
|
||||
#if defined(SKYARTEC_CC2500_INO)
|
||||
{PROTO_SKYARTEC, STR_SKYARTEC, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 1, SW_CC2500, SKYARTEC_init, SKYARTEC_callback },
|
||||
#endif
|
||||
#if defined(SLT_CCNRF_INO)
|
||||
{PROTO_SLT, STR_SLT, STR_SUBTYPE_SLT, 5, OPTION_RFTUNE, 0, 1, SW_NRF, SLT_init, SLT_callback },
|
||||
#endif
|
||||
#if defined(SYMAX_NRF24L01_INO)
|
||||
{PROTO_SYMAX, STR_SYMAX, STR_SUBTYPE_SYMAX, 2, OPTION_NONE, 0, 0, SW_NRF, SYMAX_init, SYMAX_callback },
|
||||
#endif
|
||||
#if defined(TIGER_NRF24L01_INO)
|
||||
{PROTO_TIGER, STR_TIGER, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, TIGER_init, TIGER_callback },
|
||||
#endif
|
||||
#if defined(TRAXXAS_CYRF6936_INO)
|
||||
{PROTO_TRAXXAS, STR_TRAXXAS, STR_SUBTYPE_TRAXXAS, 1, OPTION_NONE, 0, 0, SW_CYRF, TRAXXAS_init, TRAXXAS_callback },
|
||||
#endif
|
||||
#if defined(V2X2_NRF24L01_INO)
|
||||
{PROTO_V2X2, STR_V2X2, STR_SUBTYPE_V2X2, 3, OPTION_NONE, 0, 0, SW_NRF, V2X2_init, V2X2_callback },
|
||||
#endif
|
||||
#if defined(V761_NRF24L01_INO)
|
||||
{PROTO_V761, STR_V761, STR_SUBTYPE_V761, 2, OPTION_NONE, 0, 0, SW_NRF, V761_init, V761_callback },
|
||||
#endif
|
||||
#if defined(V911S_CCNRF_INO)
|
||||
{PROTO_V911S, STR_V911S, STR_SUBTYPE_V911S, 2, OPTION_RFTUNE, 0, 0, SW_NRF, V911S_init, V911S_callback },
|
||||
#endif
|
||||
#if defined(WK2x01_CYRF6936_INO)
|
||||
{PROTO_WK2x01, STR_WK2x01, STR_SUBTYPE_WK2x01, 6, OPTION_NONE, 1, 1, SW_CYRF, WK_init, WK_callback },
|
||||
#endif
|
||||
#if defined(WFLY_CYRF6936_INO)
|
||||
{PROTO_WFLY, STR_WFLY, STR_SUBTYPE_WFLY, 1, OPTION_NONE, 1, 0, SW_CYRF, WFLY_init, WFLY_callback },
|
||||
#endif
|
||||
#if defined(WFLY2_A7105_INO)
|
||||
{PROTO_WFLY2, STR_WFLY2, STR_SUBTYPE_WFLY2, 1, OPTION_OPTION, 1, 0, SW_A7105, WFLY2_init, WFLY2_callback },
|
||||
// {PROTO_WFLY2, STR_WFLY2, STR_SUBTYPE_WFLY2, 1, OPTION_WBUS, 1, 0, SW_A7105, WFLY2_init, WFLY2_callback },// crash OpenTX...
|
||||
#endif
|
||||
#if defined(XK_NRF24L01_INO)
|
||||
{PROTO_XK, STR_XK, STR_SUBTYPE_XK, 2, OPTION_RFTUNE, 0, 0, SW_NRF, XK_init, XK_callback },
|
||||
#endif
|
||||
#if defined(XN297DUMP_NRF24L01_INO)
|
||||
{PROTO_XN297DUMP, STR_XN297DUMP, STR_SUBTYPE_XN297DUMP, 5, OPTION_RFCHAN, 0, 0, SW_NRF, XN297Dump_init, XN297Dump_callback },
|
||||
#endif
|
||||
#if defined(YD717_NRF24L01_INO)
|
||||
{PROTO_YD717, STR_YD717, STR_SUBTYPE_YD717, 5, OPTION_NONE, 0, 0, SW_NRF, YD717_init, YD717_callback },
|
||||
#endif
|
||||
#if defined(ZSX_NRF24L01_INO)
|
||||
{PROTO_ZSX, STR_ZSX, STR_SUBTYPE_ZSX, 1, OPTION_NONE, 0, 0, SW_NRF, ZSX_init, ZSX_callback },
|
||||
#endif
|
||||
#if defined(TEST_CC2500_INO)
|
||||
{PROTO_TEST, STR_TEST, NO_SUBTYPE, 0, OPTION_RFTUNE, 0, 0, SW_NRF, TEST_init, TEST_callback },
|
||||
#endif
|
||||
#if defined(NANORF_NRF24L01_INO)
|
||||
{PROTO_NANORF, STR_NANORF, NO_SUBTYPE, 0, OPTION_NONE, 0, 0, SW_NRF, NANORF_init, NANORF_callback },
|
||||
#endif
|
||||
{0x00, nullptr, nullptr, 0, 0, 0, 0, 0, nullptr, nullptr }
|
||||
};
|
||||
@@ -18,15 +18,17 @@
|
||||
//******************
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 3
|
||||
#define VERSION_REVISION 0
|
||||
#define VERSION_PATCH_LEVEL 89
|
||||
#define VERSION_REVISION 2
|
||||
#define VERSION_PATCH_LEVEL 61
|
||||
|
||||
#define MODE_SERIAL 0
|
||||
|
||||
//******************
|
||||
// Protocols
|
||||
//******************
|
||||
enum PROTOCOLS
|
||||
{
|
||||
MODE_SERIAL = 0, // Serial commands
|
||||
PROTO_CONFIG = 0, // Module config
|
||||
PROTO_FLYSKY = 1, // =>A7105
|
||||
PROTO_HUBSAN = 2, // =>A7105
|
||||
PROTO_FRSKYD = 3, // =>CC2500
|
||||
@@ -47,7 +49,7 @@ enum PROTOCOLS
|
||||
PROTO_MJXQ = 18, // =>NRF24L01
|
||||
PROTO_SHENQI = 19, // =>NRF24L01
|
||||
PROTO_FY326 = 20, // =>NRF24L01
|
||||
PROTO_SFHSS = 21, // =>CC2500
|
||||
PROTO_FUTABA = 21, // =>CC2500
|
||||
PROTO_J6PRO = 22, // =>CYRF6936
|
||||
PROTO_FQ777 = 23, // =>NRF24L01
|
||||
PROTO_ASSAN = 24, // =>NRF24L01
|
||||
@@ -79,7 +81,7 @@ enum PROTOCOLS
|
||||
PROTO_REDPINE = 50, // =>CC2500
|
||||
PROTO_POTENSIC = 51, // =>NRF24L01
|
||||
PROTO_ZSX = 52, // =>NRF24L01
|
||||
PROTO_FLYZONE = 53, // =>A7105
|
||||
PROTO_HEIGHT = 53, // =>A7105
|
||||
PROTO_SCANNER = 54, // =>CC2500
|
||||
PROTO_FRSKY_RX = 55, // =>CC2500
|
||||
PROTO_AFHDS2A_RX= 56, // =>A7105
|
||||
@@ -95,6 +97,24 @@ enum PROTOCOLS
|
||||
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_WFLY2 = 79, // =>A7105
|
||||
PROTO_E016HV2 = 80, // =>CC2500 & NRF24L01
|
||||
PROTO_E010R5 = 81, // =>CYRF6936
|
||||
PROTO_LOLI = 82, // =>NRF24L01
|
||||
PROTO_E129 = 83, // =>CYRF6936
|
||||
PROTO_JOYSWAY = 84, // =>A7105
|
||||
|
||||
PROTO_NANORF = 126, // =>NRF24L01
|
||||
PROTO_TEST = 127, // =>CC2500
|
||||
};
|
||||
|
||||
enum Flysky
|
||||
@@ -105,7 +125,7 @@ enum Flysky
|
||||
V912 = 3,
|
||||
CX20 = 4,
|
||||
};
|
||||
enum Flyzone
|
||||
enum Height
|
||||
{
|
||||
FZ410 = 0,
|
||||
};
|
||||
@@ -121,6 +141,8 @@ enum AFHDS2A
|
||||
PPM_IBUS = 1,
|
||||
PWM_SBUS = 2,
|
||||
PPM_SBUS = 3,
|
||||
PWM_IB16 = 4,
|
||||
PPM_IB16 = 5,
|
||||
};
|
||||
enum Hisky
|
||||
{
|
||||
@@ -129,10 +151,10 @@ enum Hisky
|
||||
};
|
||||
enum DSM
|
||||
{
|
||||
DSM2_22 = 0,
|
||||
DSM2_11 = 1,
|
||||
DSMX_22 = 2,
|
||||
DSMX_11 = 3,
|
||||
DSM2_1F = 0,
|
||||
DSM2_2F = 1,
|
||||
DSMX_1F = 2,
|
||||
DSMX_2F = 3,
|
||||
DSM_AUTO = 4,
|
||||
};
|
||||
enum YD717
|
||||
@@ -191,6 +213,7 @@ enum BAYANG
|
||||
X16_AH = 2,
|
||||
IRDRONE = 3,
|
||||
DHD_D4 = 4,
|
||||
QX100 = 5,
|
||||
};
|
||||
enum MT99XX
|
||||
{
|
||||
@@ -199,6 +222,8 @@ enum MT99XX
|
||||
YZ = 2,
|
||||
LS = 3,
|
||||
FY805 = 4,
|
||||
A180 = 5,
|
||||
DRAGON = 6,
|
||||
};
|
||||
enum MJXQ
|
||||
{
|
||||
@@ -217,11 +242,12 @@ enum FRSKYD
|
||||
};
|
||||
enum FRSKYX
|
||||
{
|
||||
CH_16 = 0,
|
||||
CH_8 = 1,
|
||||
EU_16 = 2,
|
||||
EU_8 = 3,
|
||||
XCLONE = 4,
|
||||
CH_16 = 0,
|
||||
CH_8 = 1,
|
||||
EU_16 = 2,
|
||||
EU_8 = 3,
|
||||
XCLONE_16 = 4,
|
||||
XCLONE_8 = 5,
|
||||
};
|
||||
enum HONTAI
|
||||
{
|
||||
@@ -234,6 +260,7 @@ enum V2X2
|
||||
{
|
||||
V2X2 = 0,
|
||||
JXD506 = 1,
|
||||
V2X2_MR101 = 2,
|
||||
};
|
||||
enum FY326
|
||||
{
|
||||
@@ -335,6 +362,10 @@ enum FRSKY_R9
|
||||
R9_868 = 1,
|
||||
R9_915_8CH = 2,
|
||||
R9_868_8CH = 3,
|
||||
R9_FCC = 4,
|
||||
R9_EU = 5,
|
||||
R9_FCC_8CH = 6,
|
||||
R9_EU_8CH = 7,
|
||||
};
|
||||
enum ESKY
|
||||
{
|
||||
@@ -346,6 +377,8 @@ enum FRSKY_RX
|
||||
{
|
||||
FRSKY_RX = 0,
|
||||
FRSKY_CLONE = 1,
|
||||
FRSKY_ERASE = 2,
|
||||
FRSKY_CPPM = 3,
|
||||
};
|
||||
|
||||
enum FRSKYL
|
||||
@@ -354,12 +387,56 @@ enum FRSKYL
|
||||
LR12_6CH = 1,
|
||||
};
|
||||
|
||||
enum HOTT
|
||||
{
|
||||
HOTT_SYNC = 0,
|
||||
HOTT_NO_SYNC= 1,
|
||||
};
|
||||
|
||||
enum PELIKAN
|
||||
{
|
||||
PELIKAN_PRO = 0,
|
||||
PELIKAN_LITE= 1,
|
||||
};
|
||||
|
||||
enum V761
|
||||
{
|
||||
V761_3CH = 0,
|
||||
V761_4CH = 1,
|
||||
};
|
||||
|
||||
enum HEIGHT
|
||||
{
|
||||
HEIGHT_5CH = 0,
|
||||
HEIGHT_8CH = 1,
|
||||
};
|
||||
|
||||
enum KYOSHO
|
||||
{
|
||||
KYOSHO_FHSS = 0,
|
||||
KYOSHO_HYPE = 1,
|
||||
};
|
||||
|
||||
enum JJRC345
|
||||
{
|
||||
JJRC345 = 0,
|
||||
SKYTMBLR = 1,
|
||||
};
|
||||
|
||||
enum RLINK
|
||||
{
|
||||
RLINK_SURFACE = 0,
|
||||
RLINK_AIR = 1,
|
||||
RLINK_DUMBORC = 2,
|
||||
};
|
||||
|
||||
#define NONE 0
|
||||
#define P_HIGH 1
|
||||
#define P_LOW 0
|
||||
#define AUTOBIND 1
|
||||
#define NO_AUTOBIND 0
|
||||
|
||||
//PPM protocols
|
||||
struct PPM_Parameters
|
||||
{
|
||||
uint8_t protocol;
|
||||
@@ -371,6 +448,33 @@ struct PPM_Parameters
|
||||
uint32_t chan_order;
|
||||
};
|
||||
|
||||
//Callback
|
||||
typedef uint16_t (*uint16_function_t) (void); //pointer to a function with no parameters which return an uint16_t integer
|
||||
typedef void (*void_function_t ) (void); //pointer to a function with no parameters which returns nothing
|
||||
|
||||
//Protocols definition
|
||||
struct mm_protocol_definition {
|
||||
uint8_t protocol;
|
||||
const char *ProtoString;
|
||||
const char *SubProtoString;
|
||||
uint8_t nbrSubProto : 4;
|
||||
uint8_t optionType : 4;
|
||||
uint8_t failSafe : 1;
|
||||
uint8_t chMap : 1;
|
||||
uint8_t rfSwitch : 2;
|
||||
void_function_t Init;
|
||||
uint16_function_t CallBack;
|
||||
};
|
||||
extern const mm_protocol_definition multi_protocols[];
|
||||
|
||||
enum RF_SWITCH
|
||||
{
|
||||
SW_A7105 = 0, //antenna RF1
|
||||
SW_CC2500 = 1, //antenna RF2
|
||||
SW_NRF = 2, //antenna RF3
|
||||
SW_CYRF = 3, //antenna RF4
|
||||
};
|
||||
|
||||
// Telemetry
|
||||
enum MultiPacketTypes
|
||||
{
|
||||
@@ -388,17 +492,13 @@ enum MultiPacketTypes
|
||||
MULTI_TELEMETRY_AFHDS2A_AC = 12,
|
||||
MULTI_TELEMETRY_RX_CHANNELS = 13,
|
||||
MULTI_TELEMETRY_HOTT = 14,
|
||||
MULTI_TELEMETRY_MLINK = 15,
|
||||
MULTI_TELEMETRY_CONFIG = 16,
|
||||
};
|
||||
|
||||
// Macros
|
||||
#define NOP() __asm__ __volatile__("nop")
|
||||
|
||||
//***************
|
||||
//*** Tests ***
|
||||
//***************
|
||||
#define IS_FAILSAFE_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_SFHSS || protocol==PROTO_WK2x01 || protocol== PROTO_HOTT || protocol==PROTO_FRSKYX || protocol==PROTO_FRSKYX2 )
|
||||
#define IS_CHMAP_PROTOCOL ( (protocol==PROTO_HISKY && sub_protocol==HK310) || protocol==PROTO_AFHDS2A || protocol==PROTO_DEVO || protocol==PROTO_SFHSS || protocol==PROTO_WK2x01 || protocol== PROTO_DSM || protocol==PROTO_SLT || protocol==PROTO_FLYSKY || protocol==PROTO_ESKY || protocol==PROTO_J6PRO || protocol==PROTO_PELIKAN || protocol==PROTO_SKYARTEC )
|
||||
|
||||
//***************
|
||||
//*** Flags ***
|
||||
//***************
|
||||
@@ -487,6 +587,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
|
||||
@@ -498,8 +603,9 @@ enum MultiPacketTypes
|
||||
//********************
|
||||
#if defined(STM32_BOARD) && (defined (DEBUG_SERIAL) || defined (ARDUINO_MULTI_DEBUG))
|
||||
uint16_t debug_time=0;
|
||||
#define debug(msg, ...) {char debug_buf[64]; sprintf(debug_buf, msg, ##__VA_ARGS__); Serial.write(debug_buf);}
|
||||
#define debugln(msg, ...) {char debug_buf[64]; sprintf(debug_buf, msg "\r\n", ##__VA_ARGS__); Serial.write(debug_buf);}
|
||||
char debug_buf[64];
|
||||
#define debug(msg, ...) { sprintf(debug_buf, msg, ##__VA_ARGS__); Serial.write(debug_buf);}
|
||||
#define debugln(msg, ...) { sprintf(debug_buf, msg "\r\n", ##__VA_ARGS__); Serial.write(debug_buf);}
|
||||
#define debug_time(msg) { uint16_t debug_time_TCNT1=TCNT1; debug_time=debug_time_TCNT1-debug_time; debug(msg "%u", debug_time>>1); debug_time=debug_time_TCNT1; }
|
||||
#define debugln_time(msg) { uint16_t debug_time_TCNT1=TCNT1; debug_time=debug_time_TCNT1-debug_time; debug(msg "%u\r\n", debug_time>>1); debug_time=debug_time_TCNT1; }
|
||||
#else
|
||||
@@ -555,17 +661,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
|
||||
@@ -573,14 +679,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
|
||||
@@ -611,11 +716,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
|
||||
@@ -632,6 +739,10 @@ enum CYRF_POWER
|
||||
#define CYRF_RANGE_POWER CYRF_POWER_1 // 1/30 of the full power distance
|
||||
#define CYRF_BIND_POWER CYRF_POWER_0
|
||||
|
||||
// SX1276
|
||||
#define JP_T18 1
|
||||
#define JP_TLite 2
|
||||
|
||||
enum TXRX_State {
|
||||
TXRX_OFF,
|
||||
TX_EN,
|
||||
@@ -667,7 +778,17 @@ enum {
|
||||
#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 CONFIG_EEPROM_OFFSET 877 // Current configuration of the multimodule
|
||||
#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 ***
|
||||
@@ -683,8 +804,9 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
0x54 sub_protocol values are 32..63 Stream contains channels
|
||||
0x57 sub_protocol values are 0..31 Stream contains failsafe
|
||||
0x56 sub_protocol values are 32..63 Stream contains failsafe
|
||||
Note: V2 adds the 2 top bits to extend the number of protocols to 256 in Stream[26]
|
||||
Stream[1] = sub_protocol|BindBit|RangeCheckBit|AutoBindBit;
|
||||
sub_protocol is 0..31 (bits 0..4), value should be added with 32 if Stream[0] = 0x54 | 0x56
|
||||
sub_protocol is 0..31 (bits 0..4)
|
||||
Reserved 0
|
||||
Flysky 1
|
||||
Hubsan 2
|
||||
@@ -706,7 +828,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
MJXQ 18
|
||||
SHENQI 19
|
||||
FY326 20
|
||||
SFHSS 21
|
||||
Futaba 21
|
||||
J6PRO 22
|
||||
FQ777 23
|
||||
ASSAN 24
|
||||
@@ -738,7 +860,7 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
REDPINE 50
|
||||
POTENSIC 51
|
||||
ZSX 52
|
||||
FLYZONE 53
|
||||
HEIGHT 53
|
||||
SCANNER 54
|
||||
FRSKY_RX 55
|
||||
AFHDS2A_RX 56
|
||||
@@ -754,6 +876,20 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
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
|
||||
WFLY2 79
|
||||
E016HV2 80
|
||||
E010R5 81
|
||||
LOLI 82
|
||||
E129 83
|
||||
BindBit=> 0x80 1=Bind/0=No
|
||||
AutoBindBit=> 0x40 1=Yes /0=No
|
||||
RangeCheck=> 0x20 1=Yes /0=No
|
||||
@@ -774,10 +910,10 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
Hisky 0
|
||||
HK310 1
|
||||
sub_protocol==DSM
|
||||
DSM2_22 0
|
||||
DSM2_11 1
|
||||
DSMX_22 2
|
||||
DSMX_11 3
|
||||
DSM2_1F 0
|
||||
DSM2_2F 1
|
||||
DSMX_1F 2
|
||||
DSMX_2F 3
|
||||
DSM_AUTO 4
|
||||
sub_protocol==YD717
|
||||
YD717 0
|
||||
@@ -851,9 +987,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
|
||||
@@ -919,6 +1058,10 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
R9_868 1
|
||||
R9_915_8CH 2
|
||||
R9_868_8CH 3
|
||||
R9_FCC 4
|
||||
R9_EU 5
|
||||
R9_FCC_8CH 6
|
||||
R9_EU_8CH 7
|
||||
sub_protocol==ESKY
|
||||
ESKY_STD 0
|
||||
ESKY_ET4 1
|
||||
@@ -928,6 +1071,25 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
sub_protocol==FRSKYL
|
||||
LR12 0
|
||||
LR12_6CH 1
|
||||
sub_protocol==HOTT
|
||||
HOTT_SYNC 0
|
||||
HOTT_NO_SYNC 1
|
||||
sub_protocol==PELIKAN
|
||||
PELIKAN_PRO 0
|
||||
PELIKAN_LITE 1
|
||||
sub_protocol==V761
|
||||
V761_3CH 0
|
||||
V761_4CH 1
|
||||
sub_protocol==HEIGHT
|
||||
HEIGHT_5CH 0
|
||||
HEIGHT_8CH 1
|
||||
sub_protocol==JJRC345
|
||||
JJRC345 0
|
||||
SKYTMBLR 1
|
||||
sub_protocol==RLINK
|
||||
RLINK_SURFACE 0
|
||||
RLINK_AIR 1
|
||||
RLINK_DUMBORC 2
|
||||
|
||||
Power value => 0x80 0=High/1=Low
|
||||
Stream[3] = option_protocol;
|
||||
@@ -954,37 +1116,11 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
FrSkyX and FrSkyX2: Stream[27] during bind Telem on=0x00,off=0x01 | CH1-8=0x00,CH9-16=0x02
|
||||
FrSkyX and FrSkyX2: Stream[27..34] during normal operation unstuffed SPort data to be sent
|
||||
HoTT: Stream[27] 1 byte for telemetry type
|
||||
DSM: Stream[27..33] Forward Programming
|
||||
*/
|
||||
/*
|
||||
Multimodule Status
|
||||
Based on #define MULTI_STATUS
|
||||
|
||||
Serial: 100000 Baud 8e2 (same as input)
|
||||
|
||||
Format: header (2 bytes) + data (variable)
|
||||
[0] = 'M' (0x4d)
|
||||
[1] Length (excluding the 2 header bytes)
|
||||
[2-xx] data
|
||||
|
||||
Type = 0x01 Multimodule Status:
|
||||
[2] Flags
|
||||
0x01 = Input signal detected
|
||||
0x02 = Serial mode enabled
|
||||
0x04 = Protocol is valid
|
||||
0x08 = Module is in binding mode
|
||||
0x10 = Module waits a bind event to load the protocol
|
||||
0x20 = Current protocol supports failsafe
|
||||
0x40 = Current protocol supports disable channel mapping
|
||||
0x80 = Data buffer is almost full
|
||||
[3] major
|
||||
[4] minor
|
||||
[5] revision
|
||||
[6] patchlevel,
|
||||
version of multi code, should be displayed as major.minor.revision.patchlevel
|
||||
*/
|
||||
/*
|
||||
Multiprotocol telemetry/command definition for OpenTX
|
||||
Based on #define MULTI_TELEMETRY enables OpenTX to get the multimodule status and select the correct telemetry type automatically.
|
||||
Multiprotocol telemetry/command definition for OpenTX and erskyTX
|
||||
Based on #define MULTI_TELEMETRY enables OpenTX and erskyTX to get the multimodule status and select the correct telemetry type automatically.
|
||||
|
||||
Serial: 100000 Baud 8e2 (same as input)
|
||||
|
||||
@@ -1025,18 +1161,21 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
[11] Prev valid protocol number, can be used to skip invalid protocols
|
||||
[12..18] Protocol name [7], not null terminated if prototcol len == 7
|
||||
[19>>4] Option text to be displayed:
|
||||
OPTION_NONE 0
|
||||
OPTION_OPTION 1
|
||||
OPTION_RFTUNE 2
|
||||
OPTION_VIDFREQ 3
|
||||
OPTION_FIXEDID 4
|
||||
OPTION_TELEM 5
|
||||
OPTION_SRVFREQ 6
|
||||
OPTION_MAXTHR 7
|
||||
OPTION_RFCHAN 8
|
||||
OPTION_NONE 0 Hidden field
|
||||
OPTION_OPTION 1 "Option:" value=-128..0(default)..127
|
||||
OPTION_RFTUNE 2 "RF freq tune:" value=-128..0(default)..127
|
||||
OPTION_VIDFREQ 3 "Video freq:" value=-128..0(default)..127
|
||||
OPTION_FIXEDID 4 "ID type:" value="Auto":0(default), "Fixed":1
|
||||
OPTION_TELEM 5 "Telem:" value="Off":0(default), "On":1, "Off+Aux":2, "On+Aux":3
|
||||
OPTION_SRVFREQ 6 "Servo freq(Hz):" value="50":0(default).."400":70 => display=50+5*option with option=0..70
|
||||
OPTION_MAXTHR 7 "Max throw:" value="Disabled":0, "Enabled":1
|
||||
OPTION_RFCHAN 8 "Select RF chan:" value=-128..0(default)..127
|
||||
OPTION_RFPOWER 9 "RF power:" "1.6mW":0(default),"2.0mW":1,"2.5mW":2,"3.2mW":3,"4.0mW":4,"5.0mW":5,"6.3mW":6,"7.9mW":7,"10mW\0":8,"13mW\0":9,"16mW\0":10,"20mW\0":11,"25mW\0":12,"32mW\0":13,"40mW\0":14,"50mW\0":15
|
||||
OPTION_WBUS 10 "Output:" "WBUS":0(default),"PPM":1
|
||||
[19&0x0F] Number of sub protocols
|
||||
[20..27] Sub protocol name [8], not null terminated if sub prototcol len == 8
|
||||
|
||||
If the current protocol is invalid [12..27] are all 0x00.
|
||||
|
||||
more information can be added by specifing a longer length of the type, the TX will just ignore these bytes
|
||||
|
||||
Type 0x02 Frksy S.port telemetry
|
||||
@@ -1106,4 +1245,10 @@ Serial: 100000 Baud 8e2 _ xxxx xxxx p --
|
||||
data[3] = page
|
||||
data[4-13] = data
|
||||
|
||||
Type 0x0F M-Link telemetry
|
||||
length: 10
|
||||
data[0] = TX_RSSI
|
||||
data[1] = TX_LQI
|
||||
data[2] = telem_type
|
||||
data[3-9] = data
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,25 +31,16 @@ enum {
|
||||
NCC_RX3,
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) NCC_init()
|
||||
static void __attribute__((unused)) NCC_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t*)"\xE7\xE7\xC7\xD7\x67",5);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\xE7\xE7\xC7\xD7\x67",5);
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowledgment on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, NCC_RX_PACKET_LEN); // Enable rx pipe 0
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // NRF24L01_BR_1M, NRF24L01_BR_2M, NRF24L01_BR_250K
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC) // switch to TX mode and disable CRC
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, NCC_RX_PACKET_LEN); // Enable rx pipe 0
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // NRF24L01_BR_1M, NRF24L01_BR_2M, NRF24L01_BR_250K
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (0 << NRF24L01_00_EN_CRC) // switch to TX mode and disable CRC
|
||||
| (1 << NRF24L01_00_CRCO)
|
||||
| (1 << NRF24L01_00_PWR_UP)
|
||||
| (0 << NRF24L01_00_PRIM_RX));
|
||||
@@ -58,11 +49,11 @@ static void __attribute__((unused)) NCC_init()
|
||||
const uint8_t NCC_xor[]={0x80, 0x44, 0x64, 0x75, 0x6C, 0x71, 0x2A, 0x36, 0x7C, 0xF1, 0x6E, 0x52, 0x09, 0x9D};
|
||||
static void __attribute__((unused)) NCC_Crypt_Packet()
|
||||
{
|
||||
uint16_t crc=0;
|
||||
crc=0;
|
||||
for(uint8_t i=0; i< NCC_TX_PACKET_LEN-2; i++)
|
||||
{
|
||||
packet[i]^=NCC_xor[i];
|
||||
crc=crc16_update(crc, packet[i], 8);
|
||||
crc16_update(packet[i], 8);
|
||||
}
|
||||
crc^=0x60DE;
|
||||
packet[NCC_TX_PACKET_LEN-2]=crc>>8;
|
||||
@@ -70,11 +61,11 @@ static void __attribute__((unused)) NCC_Crypt_Packet()
|
||||
}
|
||||
static boolean __attribute__((unused)) NCC_Decrypt_Packet()
|
||||
{
|
||||
uint16_t crc=0;
|
||||
crc=0;
|
||||
debug("RX: ");
|
||||
for(uint8_t i=0; i< NCC_RX_PACKET_LEN-2; i++)
|
||||
{
|
||||
crc=crc16_update(crc, packet[i], 8);
|
||||
crc16_update( packet[i], 8);
|
||||
packet[i]^=NCC_xor[i];
|
||||
debug("%02X ",packet[i]);
|
||||
}
|
||||
@@ -247,7 +238,7 @@ const uint8_t PROGMEM NCC_TX_DATA[][6]= {
|
||||
{ 0xC2, 0x93, 0x55, 0x44, 0x4C, 0x0B },
|
||||
};
|
||||
|
||||
uint16_t initNCC(void)
|
||||
void NCC_init(void)
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
|
||||
@@ -269,9 +260,8 @@ uint16_t initNCC(void)
|
||||
hopping_frequency[4]=0x08; // bind channel 1
|
||||
hopping_frequency[5]=0x2A; // bind channel 2
|
||||
hopping_frequency_no=4; // start with bind
|
||||
NCC_init();
|
||||
NCC_RF_init();
|
||||
phase=NCC_BIND_TX1;
|
||||
return 10000;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#ifdef NRF24L01_INSTALLED
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#include "iface_xn297.h"
|
||||
|
||||
//---------------------------
|
||||
// NRF24L01+ SPI Specific Functions
|
||||
@@ -29,6 +29,19 @@ void NRF24L01_Initialize()
|
||||
rf_setup = 0x09;
|
||||
prev_power = 0x00; // Make sure prev_power is inline with current power
|
||||
XN297_SetScrambledMode(XN297_SCRAMBLED);
|
||||
|
||||
//Load most likely default NRF config
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5 bytes rx/tx address
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01); // Set feature bits off and enable the command NRF24L01_B0_TX_PYLD_NOACK
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_SetTxRxMode(TX_EN); // Clear data ready, data sent, retransmit and enable CRC 16bits, ready for TX
|
||||
}
|
||||
|
||||
void NRF24L01_WriteReg(uint8_t reg, uint8_t data)
|
||||
@@ -117,13 +130,13 @@ static uint8_t NRF24L01_GetDynamicPayloadSize()
|
||||
return len;
|
||||
}
|
||||
|
||||
void NRF24L01_Activate(uint8_t code)
|
||||
/*void NRF24L01_Activate(uint8_t code)
|
||||
{
|
||||
NRF_CSN_off;
|
||||
SPI_Write(ACTIVATE);
|
||||
SPI_Write(code);
|
||||
NRF_CSN_on;
|
||||
}
|
||||
}*/
|
||||
|
||||
void NRF24L01_SetBitrate(uint8_t bitrate)
|
||||
{
|
||||
@@ -217,13 +230,6 @@ void NRF24L01_SetTxRxMode(enum TXRX_State mode)
|
||||
|
||||
void NRF24L01_Reset()
|
||||
{
|
||||
//** not in deviation but needed to hot switch between models
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x00); // Set feature bits off
|
||||
NRF24L01_Activate(0x73);
|
||||
//**
|
||||
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_Strobe(0xff); // NOP
|
||||
@@ -244,342 +250,6 @@ uint8_t NRF24L01_packet_ack()
|
||||
return PKT_PENDING;
|
||||
}
|
||||
|
||||
|
||||
///////////////
|
||||
// XN297 emulation layer
|
||||
uint8_t xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
|
||||
uint8_t xn297_addr_len;
|
||||
uint8_t xn297_tx_addr[5];
|
||||
uint8_t xn297_rx_addr[5];
|
||||
uint8_t xn297_crc = 0;
|
||||
|
||||
// xn297 address / pcf / payload scramble table
|
||||
const uint8_t xn297_scramble[] = {
|
||||
0xE3, 0xB1, 0x4B, 0xEA, 0x85, 0xBC, 0xE5, 0x66,
|
||||
0x0D, 0xAE, 0x8C, 0x88, 0x12, 0x69, 0xEE, 0x1F,
|
||||
0xC7, 0x62, 0x97, 0xD5, 0x0B, 0x79, 0xCA, 0xCC,
|
||||
0x1B, 0x5D, 0x19, 0x10, 0x24, 0xD3, 0xDC, 0x3F,
|
||||
0x8E, 0xC5, 0x2F, 0xAA, 0x16, 0xF3, 0x95 };
|
||||
|
||||
// scrambled, standard mode crc xorout table
|
||||
const uint16_t PROGMEM xn297_crc_xorout_scrambled[] = {
|
||||
0x0000, 0x3448, 0x9BA7, 0x8BBB, 0x85E1, 0x3E8C,
|
||||
0x451E, 0x18E6, 0x6B24, 0xE7AB, 0x3828, 0x814B,
|
||||
0xD461, 0xF494, 0x2503, 0x691D, 0xFE8B, 0x9BA7,
|
||||
0x8B17, 0x2920, 0x8B5F, 0x61B1, 0xD391, 0x7401,
|
||||
0x2138, 0x129F, 0xB3A0, 0x2988, 0x23CA, 0xC0CB,
|
||||
0x0C6C, 0xB329, 0xA0A1, 0x0A16, 0xA9D0 };
|
||||
|
||||
// unscrambled, standard mode crc xorout table
|
||||
const uint16_t PROGMEM xn297_crc_xorout[] = {
|
||||
0x0000, 0x3D5F, 0xA6F1, 0x3A23, 0xAA16, 0x1CAF,
|
||||
0x62B2, 0xE0EB, 0x0821, 0xBE07, 0x5F1A, 0xAF15,
|
||||
0x4F0A, 0xAD24, 0x5E48, 0xED34, 0x068C, 0xF2C9,
|
||||
0x1852, 0xDF36, 0x129D, 0xB17C, 0xD5F5, 0x70D7,
|
||||
0xB798, 0x5133, 0x67DB, 0xD94E, 0x0A5B, 0xE445,
|
||||
0xE6A5, 0x26E7, 0xBDAB, 0xC379, 0x8E20 };
|
||||
|
||||
// scrambled enhanced mode crc xorout table
|
||||
const uint16_t PROGMEM xn297_crc_xorout_scrambled_enhanced[] = {
|
||||
0x0000, 0x7EBF, 0x3ECE, 0x07A4, 0xCA52, 0x343B,
|
||||
0x53F8, 0x8CD0, 0x9EAC, 0xD0C0, 0x150D, 0x5186,
|
||||
0xD251, 0xA46F, 0x8435, 0xFA2E, 0x7EBD, 0x3C7D,
|
||||
0x94E0, 0x3D5F, 0xA685, 0x4E47, 0xF045, 0xB483,
|
||||
0x7A1F, 0xDEA2, 0x9642, 0xBF4B, 0x032F, 0x01D2,
|
||||
0xDC86, 0x92A5, 0x183A, 0xB760, 0xA953 };
|
||||
|
||||
// unscrambled enhanced mode crc xorout table
|
||||
// unused so far
|
||||
#ifdef XN297DUMP_NRF24L01_INO
|
||||
const uint16_t xn297_crc_xorout_enhanced[] = {
|
||||
0x0000, 0x8BE6, 0xD8EC, 0xB87A, 0x42DC, 0xAA89,
|
||||
0x83AF, 0x10E4, 0xE83E, 0x5C29, 0xAC76, 0x1C69,
|
||||
0xA4B2, 0x5961, 0xB4D3, 0x2A50, 0xCB27, 0x5128,
|
||||
0x7CDB, 0x7A14, 0xD5D2, 0x57D7, 0xE31D, 0xCE42,
|
||||
0x648D, 0xBF2D, 0x653B, 0x190C, 0x9117, 0x9A97,
|
||||
0xABFC, 0xE68E, 0x0DE7, 0x28A2, 0x1965 };
|
||||
#endif
|
||||
|
||||
static uint8_t bit_reverse(uint8_t b_in)
|
||||
{
|
||||
uint8_t b_out = 0;
|
||||
for (uint8_t i = 0; i < 8; ++i)
|
||||
{
|
||||
b_out = (b_out << 1) | (b_in & 1);
|
||||
b_in >>= 1;
|
||||
}
|
||||
return b_out;
|
||||
}
|
||||
|
||||
static const uint16_t polynomial = 0x1021;
|
||||
static uint16_t crc16_update(uint16_t crc, uint8_t a, uint8_t bits)
|
||||
{
|
||||
crc ^= a << 8;
|
||||
while(bits--)
|
||||
if (crc & 0x8000)
|
||||
crc = (crc << 1) ^ polynomial;
|
||||
else
|
||||
crc = crc << 1;
|
||||
return crc;
|
||||
}
|
||||
|
||||
void XN297_SetTXAddr(const uint8_t* addr, uint8_t len)
|
||||
{
|
||||
if (len > 5) len = 5;
|
||||
if (len < 3) len = 3;
|
||||
uint8_t buf[] = { 0x55, 0x0F, 0x71, 0x0C, 0x00 }; // bytes for XN297 preamble 0xC710F55 (28 bit)
|
||||
xn297_addr_len = len;
|
||||
if (xn297_addr_len < 4)
|
||||
for (uint8_t i = 0; i < 4; ++i)
|
||||
buf[i] = buf[i+1];
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, buf, 5);
|
||||
// Receive address is complicated. We need to use scrambled actual address as a receive address
|
||||
// but the TX code now assumes fixed 4-byte transmit address for preamble. We need to adjust it
|
||||
// first. Also, if the scrambled address begins with 1 nRF24 will look for preamble byte 0xAA
|
||||
// instead of 0x55 to ensure enough 0-1 transitions to tune the receiver. Still need to experiment
|
||||
// with receiving signals.
|
||||
memcpy(xn297_tx_addr, addr, len);
|
||||
}
|
||||
|
||||
void XN297_SetRXAddr(const uint8_t* addr, uint8_t len)
|
||||
{
|
||||
if (len > 5) len = 5;
|
||||
if (len < 3) len = 3;
|
||||
uint8_t buf[] = { 0, 0, 0, 0, 0 };
|
||||
memcpy(buf, addr, len);
|
||||
memcpy(xn297_rx_addr, addr, len);
|
||||
for (uint8_t i = 0; i < xn297_addr_len; ++i)
|
||||
{
|
||||
buf[i] = xn297_rx_addr[i];
|
||||
if(xn297_scramble_enabled)
|
||||
buf[i] ^= xn297_scramble[xn297_addr_len-i-1];
|
||||
}
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, buf, 5);
|
||||
}
|
||||
|
||||
void XN297_Configure(uint8_t flags)
|
||||
{
|
||||
xn297_crc = !!(flags & _BV(NRF24L01_00_EN_CRC));
|
||||
flags &= ~(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, flags & 0xFF);
|
||||
}
|
||||
|
||||
void XN297_SetScrambledMode(const uint8_t mode)
|
||||
{
|
||||
xn297_scramble_enabled = mode;
|
||||
}
|
||||
|
||||
void XN297_WritePayload(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
uint8_t buf[32];
|
||||
uint8_t last = 0;
|
||||
|
||||
if (xn297_addr_len < 4)
|
||||
{
|
||||
// If address length (which is defined by receive address length)
|
||||
// is less than 4 the TX address can't fit the preamble, so the last
|
||||
// byte goes here
|
||||
buf[last++] = 0x55;
|
||||
}
|
||||
for (uint8_t i = 0; i < xn297_addr_len; ++i)
|
||||
{
|
||||
buf[last] = xn297_tx_addr[xn297_addr_len-i-1];
|
||||
if(xn297_scramble_enabled)
|
||||
buf[last] ^= xn297_scramble[i];
|
||||
last++;
|
||||
}
|
||||
for (uint8_t i = 0; i < len; ++i)
|
||||
{
|
||||
// bit-reverse bytes in packet
|
||||
buf[last] = bit_reverse(msg[i]);
|
||||
if(xn297_scramble_enabled)
|
||||
buf[last] ^= xn297_scramble[xn297_addr_len+i];
|
||||
last++;
|
||||
}
|
||||
if (xn297_crc)
|
||||
{
|
||||
uint8_t offset = xn297_addr_len < 4 ? 1 : 0;
|
||||
uint16_t crc = 0xb5d2;
|
||||
for (uint8_t i = offset; i < last; ++i)
|
||||
crc = crc16_update(crc, buf[i], 8);
|
||||
if(xn297_scramble_enabled)
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
|
||||
else
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]);
|
||||
buf[last++] = crc >> 8;
|
||||
buf[last++] = crc & 0xff;
|
||||
}
|
||||
NRF24L01_WritePayload(buf, last);
|
||||
}
|
||||
|
||||
void XN297_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
|
||||
{
|
||||
uint8_t packet[32];
|
||||
uint8_t scramble_index=0;
|
||||
uint8_t last = 0;
|
||||
static uint8_t pid=0;
|
||||
|
||||
// address
|
||||
if (xn297_addr_len < 4)
|
||||
{
|
||||
// If address length (which is defined by receive address length)
|
||||
// is less than 4 the TX address can't fit the preamble, so the last
|
||||
// byte goes here
|
||||
packet[last++] = 0x55;
|
||||
}
|
||||
for (uint8_t i = 0; i < xn297_addr_len; ++i)
|
||||
{
|
||||
packet[last] = xn297_tx_addr[xn297_addr_len-i-1];
|
||||
if(xn297_scramble_enabled)
|
||||
packet[last] ^= xn297_scramble[scramble_index++];
|
||||
last++;
|
||||
}
|
||||
|
||||
// pcf
|
||||
packet[last] = (len << 1) | (pid>>1);
|
||||
if(xn297_scramble_enabled)
|
||||
packet[last] ^= xn297_scramble[scramble_index++];
|
||||
last++;
|
||||
packet[last] = (pid << 7) | (noack << 6);
|
||||
|
||||
// payload
|
||||
packet[last]|= bit_reverse(msg[0]) >> 2; // first 6 bit of payload
|
||||
if(xn297_scramble_enabled)
|
||||
packet[last] ^= xn297_scramble[scramble_index++];
|
||||
|
||||
for (uint8_t i = 0; i < len-1; ++i)
|
||||
{
|
||||
last++;
|
||||
packet[last] = (bit_reverse(msg[i]) << 6) | (bit_reverse(msg[i+1]) >> 2);
|
||||
if(xn297_scramble_enabled)
|
||||
packet[last] ^= xn297_scramble[scramble_index++];
|
||||
}
|
||||
|
||||
last++;
|
||||
packet[last] = bit_reverse(msg[len-1]) << 6; // last 2 bit of payload
|
||||
if(xn297_scramble_enabled)
|
||||
packet[last] ^= xn297_scramble[scramble_index++] & 0xc0;
|
||||
|
||||
// crc
|
||||
if (xn297_crc)
|
||||
{
|
||||
uint8_t offset = xn297_addr_len < 4 ? 1 : 0;
|
||||
uint16_t crc = 0xb5d2;
|
||||
for (uint8_t i = offset; i < last; ++i)
|
||||
crc = crc16_update(crc, packet[i], 8);
|
||||
crc = crc16_update(crc, packet[last] & 0xc0, 2);
|
||||
if (xn297_scramble_enabled)
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
|
||||
//else
|
||||
// crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
|
||||
|
||||
packet[last++] |= (crc >> 8) >> 2;
|
||||
packet[last++] = ((crc >> 8) << 6) | ((crc & 0xff) >> 2);
|
||||
packet[last++] = (crc & 0xff) << 6;
|
||||
}
|
||||
NRF24L01_WritePayload(packet, last);
|
||||
|
||||
pid++;
|
||||
if(pid>3)
|
||||
pid=0;
|
||||
}
|
||||
|
||||
boolean XN297_ReadPayload(uint8_t* msg, uint8_t len)
|
||||
{ //!!! Don't forget if using CRC to do a +2 on any of the used NRF24L01_11_RX_PW_Px !!!
|
||||
uint8_t buf[32];
|
||||
if (xn297_crc)
|
||||
NRF24L01_ReadPayload(buf, len+2); // Read payload + CRC
|
||||
else
|
||||
NRF24L01_ReadPayload(buf, len);
|
||||
// Decode payload
|
||||
for(uint8_t i=0; i<len; i++)
|
||||
{
|
||||
uint8_t b_in=buf[i];
|
||||
if(xn297_scramble_enabled)
|
||||
b_in ^= xn297_scramble[i+xn297_addr_len];
|
||||
msg[i] = bit_reverse(b_in);
|
||||
}
|
||||
if (!xn297_crc)
|
||||
return true; // No CRC so OK by default...
|
||||
|
||||
// Calculate CRC
|
||||
uint16_t crc = 0xb5d2;
|
||||
//process address
|
||||
for (uint8_t i = 0; i < xn297_addr_len; ++i)
|
||||
{
|
||||
uint8_t b_in=xn297_rx_addr[xn297_addr_len-i-1];
|
||||
if(xn297_scramble_enabled)
|
||||
b_in ^= xn297_scramble[i];
|
||||
crc = crc16_update(crc, b_in, 8);
|
||||
}
|
||||
//process payload
|
||||
for (uint8_t i = 0; i < len; ++i)
|
||||
crc = crc16_update(crc, buf[i], 8);
|
||||
//xorout
|
||||
if(xn297_scramble_enabled)
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
|
||||
else
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout[xn297_addr_len - 3 + len]);
|
||||
//test
|
||||
if( (crc >> 8) == buf[len] && (crc & 0xff) == buf[len+1])
|
||||
return true; // CRC OK
|
||||
return false; // CRC NOK
|
||||
}
|
||||
|
||||
uint8_t XN297_ReadEnhancedPayload(uint8_t* msg, uint8_t len)
|
||||
{ //!!! Don't forget do a +2 and if using CRC add +2 on any of the used NRF24L01_11_RX_PW_Px !!!
|
||||
uint8_t buffer[32];
|
||||
uint8_t pcf_size; // pcf payload size
|
||||
if (xn297_crc)
|
||||
NRF24L01_ReadPayload(buffer, len+4); // Read pcf + payload + CRC
|
||||
else
|
||||
NRF24L01_ReadPayload(buffer, len+2); // Read pcf + payload
|
||||
pcf_size = buffer[0];
|
||||
if(xn297_scramble_enabled)
|
||||
pcf_size ^= xn297_scramble[xn297_addr_len];
|
||||
pcf_size = pcf_size >> 1;
|
||||
for(int i=0; i<len; i++)
|
||||
{
|
||||
msg[i] = bit_reverse((buffer[i+1] << 2) | (buffer[i+2] >> 6));
|
||||
if(xn297_scramble_enabled)
|
||||
msg[i] ^= bit_reverse((xn297_scramble[xn297_addr_len+i+1] << 2) |
|
||||
(xn297_scramble[xn297_addr_len+i+2] >> 6));
|
||||
}
|
||||
|
||||
if (!xn297_crc)
|
||||
return pcf_size; // No CRC so OK by default...
|
||||
|
||||
// Calculate CRC
|
||||
uint16_t crc = 0xb5d2;
|
||||
//process address
|
||||
for (uint8_t i = 0; i < xn297_addr_len; ++i)
|
||||
{
|
||||
uint8_t b_in=xn297_rx_addr[xn297_addr_len-i-1];
|
||||
if(xn297_scramble_enabled)
|
||||
b_in ^= xn297_scramble[i];
|
||||
crc = crc16_update(crc, b_in, 8);
|
||||
}
|
||||
//process payload
|
||||
for (uint8_t i = 0; i < len+1; ++i)
|
||||
crc = crc16_update(crc, buffer[i], 8);
|
||||
crc = crc16_update(crc, buffer[len+1] & 0xc0, 2);
|
||||
//xorout
|
||||
if (xn297_scramble_enabled)
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
|
||||
#ifdef XN297DUMP_NRF24L01_INO
|
||||
else
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout_enhanced[xn297_addr_len - 3 + len]);
|
||||
#endif
|
||||
uint16_t crcxored=(buffer[len+1]<<10)|(buffer[len+2]<<2)|(buffer[len+3]>>6) ;
|
||||
if( crc == crcxored)
|
||||
return pcf_size; // CRC OK
|
||||
return 0; // CRC NOK
|
||||
}
|
||||
|
||||
// End of XN297 emulation
|
||||
|
||||
//
|
||||
// HS6200 emulation layer
|
||||
///////////////////////////
|
||||
@@ -606,9 +276,10 @@ void HS6200_SetTXAddr(const uint8_t* addr, uint8_t len)
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t*)"\xaa\xaa\xaa\xaa\xaa", 5);
|
||||
|
||||
// precompute address crc
|
||||
hs6200_crc_init = 0xffff;
|
||||
crc = 0xffff;
|
||||
for(int i=0; i<len; i++)
|
||||
hs6200_crc_init = crc16_update(hs6200_crc_init, addr[len-1-i], 8);
|
||||
crc16_update(addr[len-1-i], 8);
|
||||
hs6200_crc_init=crc;
|
||||
memcpy(hs6200_tx_addr, addr, len);
|
||||
hs6200_address_length = len;
|
||||
}
|
||||
@@ -616,14 +287,14 @@ void HS6200_SetTXAddr(const uint8_t* addr, uint8_t len)
|
||||
static uint16_t hs6200_calc_crc(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
uint8_t pos;
|
||||
uint16_t crc = hs6200_crc_init;
|
||||
|
||||
crc = hs6200_crc_init;
|
||||
// pcf + payload
|
||||
for(pos=0; pos < len-1; pos++)
|
||||
crc = crc16_update(crc, msg[pos], 8);
|
||||
crc16_update(msg[pos], 8);
|
||||
// last byte (1 bit only)
|
||||
if(len > 0)
|
||||
crc = crc16_update(crc, msg[pos+1], 1);
|
||||
crc16_update(msg[pos+1], 1);
|
||||
return crc;
|
||||
}
|
||||
|
||||
@@ -797,7 +468,8 @@ void LT8900_SetAddress(uint8_t *address,uint8_t addr_size)
|
||||
uint8_t LT8900_ReadPayload(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
uint8_t i,pos=0,shift,end,buffer[32];
|
||||
unsigned int crc=LT8900_CRC_Initial_Data,a;
|
||||
unsigned int a;
|
||||
crc=LT8900_CRC_Initial_Data;
|
||||
pos=LT8900_buffer_overhead_bits/8-LT8900_buffer_start;
|
||||
end=pos+len+(LT8900_Flags&_BV(LT8900_PACKET_LENGTH_EN)?1:0)+(LT8900_Flags&_BV(LT8900_CRC_ON)?2:0);
|
||||
//Read payload
|
||||
@@ -817,14 +489,14 @@ uint8_t LT8900_ReadPayload(uint8_t* msg, uint8_t len)
|
||||
//Check len
|
||||
if(LT8900_Flags&_BV(LT8900_PACKET_LENGTH_EN))
|
||||
{
|
||||
crc=crc16_update(crc,buffer[pos],8);
|
||||
crc16_update(buffer[pos],8);
|
||||
if(bit_reverse(len)!=buffer[pos++])
|
||||
return 0; // wrong len...
|
||||
}
|
||||
//Decode message
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
crc=crc16_update(crc,buffer[pos],8);
|
||||
crc16_update(buffer[pos],8);
|
||||
msg[i]=bit_reverse(buffer[pos++]);
|
||||
}
|
||||
//Check CRC
|
||||
@@ -839,21 +511,22 @@ uint8_t LT8900_ReadPayload(uint8_t* msg, uint8_t len)
|
||||
|
||||
void LT8900_WritePayload(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
unsigned int crc=LT8900_CRC_Initial_Data,a,mask;
|
||||
unsigned int a,mask;
|
||||
uint8_t i, pos=0,tmp, buffer[64], pos_final,shift;
|
||||
crc=LT8900_CRC_Initial_Data;
|
||||
//Add packet len
|
||||
if(LT8900_Flags&_BV(LT8900_PACKET_LENGTH_EN))
|
||||
{
|
||||
tmp=bit_reverse(len);
|
||||
buffer[pos++]=tmp;
|
||||
crc=crc16_update(crc,tmp,8);
|
||||
crc16_update(tmp,8);
|
||||
}
|
||||
//Add payload
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
tmp=bit_reverse(msg[i]);
|
||||
buffer[pos++]=tmp;
|
||||
crc=crc16_update(crc,tmp,8);
|
||||
crc16_update(tmp,8);
|
||||
}
|
||||
//Add CRC
|
||||
if(LT8900_Flags&_BV(LT8900_CRC_ON))
|
||||
|
||||
@@ -12,121 +12,45 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifdef NRF24L01_INSTALLED
|
||||
#if defined(CC2500_INSTALLED) || defined(NRF24L01_INSTALLED)
|
||||
|
||||
#include "iface_nrf250k.h"
|
||||
#include "iface_xn297.h"
|
||||
|
||||
static void __attribute__((unused)) XN297L_Init()
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
debugln("Using NRF");
|
||||
PE1_on; //NRF24L01 antenna RF3 by default
|
||||
PE2_off; //NRF24L01 antenna RF3 by default
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
|
||||
NRF24L01_SetPower();
|
||||
return;
|
||||
}
|
||||
//CC2500
|
||||
#ifdef CC2500_INSTALLED
|
||||
#if defined(CC2500_INSTALLED)
|
||||
debugln("Using CC2500");
|
||||
PE1_off; // antenna RF2
|
||||
PE2_on;
|
||||
CC2500_Reset();
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
|
||||
// Address Config = No address check
|
||||
// Base Frequency = 2400
|
||||
// CRC Autoflush = false
|
||||
// CRC Enable = false
|
||||
// Channel Spacing = 333.251953
|
||||
// Data Format = Normal mode
|
||||
// Data Rate = 249.939
|
||||
// Deviation = 126.953125
|
||||
// Device Address = 0
|
||||
// Manchester Enable = false
|
||||
// Modulated = true
|
||||
// Modulation Format = GFSK
|
||||
// Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word
|
||||
// RX Filter BW = 203.125000
|
||||
// Sync Word Qualifier Mode = No preamble/sync
|
||||
// TX Power = 0
|
||||
// Whitening = false
|
||||
// Fast Frequency Hopping - no PLL auto calibration
|
||||
|
||||
CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x01); // Packet Automation Control
|
||||
CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x0A); // Frequency Synthesizer Control
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option); // Frequency offset hack
|
||||
CC2500_WriteReg(CC2500_0D_FREQ2, 0x5C); // Frequency Control Word, High Byte
|
||||
CC2500_WriteReg(CC2500_0E_FREQ1, 0x4E); // Frequency Control Word, Middle Byte
|
||||
CC2500_WriteReg(CC2500_0F_FREQ0, 0xC3); // Frequency Control Word, Low Byte
|
||||
CC2500_WriteReg(CC2500_10_MDMCFG4, 0x8D); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_11_MDMCFG3, 0x3B); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_12_MDMCFG2, 0x10); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_14_MDMCFG0, 0xA4); // Modem Configuration
|
||||
CC2500_WriteReg(CC2500_15_DEVIATN, 0x62); // Modem Deviation Setting
|
||||
CC2500_WriteReg(CC2500_18_MCSM0, 0x08); // Main Radio Control State Machine Configuration
|
||||
CC2500_WriteReg(CC2500_19_FOCCFG, 0x1D); // Frequency Offset Compensation Configuration
|
||||
CC2500_WriteReg(CC2500_1A_BSCFG, 0x1C); // Bit Synchronization Configuration
|
||||
CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0xC7); // AGC Control
|
||||
CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x00); // AGC Control
|
||||
CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0xB0); // AGC Control
|
||||
CC2500_WriteReg(CC2500_21_FREND1, 0xB6); // Front End RX Configuration
|
||||
CC2500_WriteReg(CC2500_23_FSCAL3, 0xEA); // Frequency Synthesizer Calibration
|
||||
CC2500_WriteReg(CC2500_25_FSCAL1, 0x00); // Frequency Synthesizer Calibration
|
||||
CC2500_WriteReg(CC2500_26_FSCAL0, 0x11); // Frequency Synthesizer Calibration
|
||||
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
CC2500_SetPower();
|
||||
xn297_scramble_enabled=XN297_SCRAMBLED; //enabled by default
|
||||
rf_switch(SW_CC2500);
|
||||
CC2500_250K_Init();
|
||||
#elif defined(NRF24L01_INSTALLED)
|
||||
debugln("Using NRF");
|
||||
rf_switch(SW_NRF);
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_SetTXAddr(const uint8_t* addr, uint8_t len)
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
XN297_SetTXAddr(addr,len);
|
||||
return;
|
||||
}
|
||||
//CC2500
|
||||
#ifdef CC2500_INSTALLED
|
||||
#if defined(CC2500_INSTALLED)
|
||||
if (len > 5) len = 5;
|
||||
if (len < 3) len = 3;
|
||||
xn297_addr_len = len;
|
||||
memcpy(xn297_tx_addr, addr, len);
|
||||
#elif defined(NRF24L01_INSTALLED)
|
||||
XN297_SetTXAddr(addr,len);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
XN297_WritePayload(msg, len);
|
||||
return;
|
||||
}
|
||||
//CC2500
|
||||
#ifdef CC2500_INSTALLED
|
||||
#if defined(CC2500_INSTALLED)
|
||||
uint8_t buf[32];
|
||||
uint8_t last = 0;
|
||||
uint8_t i;
|
||||
static const uint16_t initial = 0xb5d2;
|
||||
|
||||
// address
|
||||
for (i = 0; i < xn297_addr_len; ++i)
|
||||
@@ -147,9 +71,9 @@ static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t le
|
||||
}
|
||||
|
||||
// crc
|
||||
uint16_t crc = initial;
|
||||
crc = 0xb5d2;
|
||||
for (uint8_t i = 0; i < last; ++i)
|
||||
crc = crc16_update(crc, buf[i], 8);
|
||||
crc16_update( buf[i], 8);
|
||||
if(xn297_scramble_enabled)
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled[xn297_addr_len - 3 + len]);
|
||||
else
|
||||
@@ -169,36 +93,23 @@ static void __attribute__((unused)) XN297L_WritePayload(uint8_t* msg, uint8_t le
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last);
|
||||
// transmit
|
||||
CC2500_Strobe(CC2500_STX);
|
||||
#elif defined(NRF24L01_INSTALLED)
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
XN297_WritePayload(msg, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, uint8_t len, uint8_t noack)
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
XN297_WriteEnhancedPayload(msg, len, noack);
|
||||
return;
|
||||
}
|
||||
//CC2500
|
||||
#ifdef CC2500_INSTALLED
|
||||
#if defined(CC2500_INSTALLED)
|
||||
uint8_t buf[32];
|
||||
uint8_t scramble_index=0;
|
||||
uint8_t last = 0;
|
||||
static uint8_t pid=0;
|
||||
|
||||
// address
|
||||
if (xn297_addr_len < 4)
|
||||
{
|
||||
// If address length (which is defined by receive address length)
|
||||
// is less than 4 the TX address can't fit the preamble, so the last
|
||||
// byte goes here
|
||||
buf[last++] = 0x55;
|
||||
}
|
||||
for (uint8_t i = 0; i < xn297_addr_len; ++i)
|
||||
{
|
||||
buf[last] = xn297_tx_addr[xn297_addr_len-i-1];
|
||||
@@ -235,11 +146,10 @@ static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, ui
|
||||
// crc
|
||||
//if (xn297_crc)
|
||||
{
|
||||
uint8_t offset = xn297_addr_len < 4 ? 1 : 0;
|
||||
uint16_t crc = 0xb5d2;
|
||||
for (uint8_t i = offset; i < last; ++i)
|
||||
crc = crc16_update(crc, buf[i], 8);
|
||||
crc = crc16_update(crc, buf[last] & 0xc0, 2);
|
||||
crc = 0xb5d2;
|
||||
for (uint8_t i = 0; i < last; ++i)
|
||||
crc16_update( buf[i], 8);
|
||||
crc16_update( buf[last] & 0xc0, 2);
|
||||
if (xn297_scramble_enabled)
|
||||
crc ^= pgm_read_word(&xn297_crc_xorout_scrambled_enhanced[xn297_addr_len-3+len]);
|
||||
//else
|
||||
@@ -265,89 +175,54 @@ static void __attribute__((unused)) XN297L_WriteEnhancedPayload(uint8_t* msg, ui
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last);
|
||||
// transmit
|
||||
CC2500_Strobe(CC2500_STX);
|
||||
#elif defined(NRF24L01_INSTALLED)
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
XN297_WriteEnhancedPayload(msg, len, noack);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_HoppingCalib(uint8_t num_freq)
|
||||
{ //calibrate hopping frequencies
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
return; //NRF
|
||||
#ifdef CC2500_INSTALLED
|
||||
for (uint8_t i = 0; i < num_freq; i++)
|
||||
{
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[i]*3);
|
||||
CC2500_Strobe(CC2500_SCAL);
|
||||
delayMicroseconds(900);
|
||||
calData[i]=CC2500_ReadReg(CC2500_25_FSCAL1);
|
||||
}
|
||||
#if defined(CC2500_INSTALLED)
|
||||
CC2500_250K_HoppingCalib(num_freq);
|
||||
#elif defined(NRF24L01_INSTALLED)
|
||||
(void)num_freq;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_Hopping(uint8_t index)
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
#if defined(CC2500_INSTALLED)
|
||||
CC2500_250K_Hopping(index);
|
||||
#elif defined(NRF24L01_INSTALLED)
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[index]);
|
||||
return;
|
||||
}
|
||||
#ifdef CC2500_INSTALLED
|
||||
// spacing is 333.25 kHz, must multiply xn297 channel by 3
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[index] * 3);
|
||||
// set PLL calibration
|
||||
CC2500_WriteReg(CC2500_25_FSCAL1, calData[index]);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_RFChannel(uint8_t number)
|
||||
{ //change channel
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
#if defined(CC2500_INSTALLED)
|
||||
CC2500_250K_RFChannel(number);
|
||||
#elif defined(NRF24L01_INSTALLED)
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, number);
|
||||
return;
|
||||
}
|
||||
#ifdef CC2500_INSTALLED
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, number*3);
|
||||
CC2500_Strobe(CC2500_SCAL);
|
||||
delayMicroseconds(900);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_SetPower()
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
NRF24L01_SetPower();
|
||||
return;
|
||||
}
|
||||
#ifdef CC2500_INSTALLED
|
||||
#if defined(CC2500_INSTALLED)
|
||||
CC2500_SetPower();
|
||||
#elif defined(NRF24L01_INSTALLED)
|
||||
NRF24L01_SetPower();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) XN297L_SetFreqOffset()
|
||||
{ // Frequency offset
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0 && prev_option==0)
|
||||
#endif
|
||||
return; //NRF
|
||||
#ifdef CC2500_INSTALLED
|
||||
if (prev_option != option)
|
||||
{
|
||||
if(prev_option==0 || option==0)
|
||||
CHANGE_PROTOCOL_FLAG_on;
|
||||
prev_option = option;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
}
|
||||
#if defined(CC2500_INSTALLED)
|
||||
CC2500_SetFreqOffset();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -355,84 +230,31 @@ static void __attribute__((unused)) NRF250K_SetTXAddr(uint8_t* addr, uint8_t len
|
||||
{
|
||||
if (len > 5) len = 5;
|
||||
if (len < 3) len = 3;
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
#if defined(CC2500_INSTALLED)
|
||||
CC2500_250K_NRF_SetTXAddr(addr, len);
|
||||
#elif defined(NRF24L01_INSTALLED)
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, len-2);
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, addr, len);
|
||||
return;
|
||||
}
|
||||
//CC2500
|
||||
#ifdef CC2500_INSTALLED
|
||||
xn297_addr_len = len;
|
||||
memcpy(xn297_tx_addr, addr, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) NRF250K_WritePayload(uint8_t* msg, uint8_t len)
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{//NRF
|
||||
#if defined(CC2500_INSTALLED)
|
||||
CC2500_250K_NRF_WritePayload(msg, len);
|
||||
#elif defined(NRF24L01_INSTALLED)
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, _BV(NRF24L01_07_TX_DS) | _BV(NRF24L01_07_RX_DR) | _BV(NRF24L01_07_MAX_RT));
|
||||
NRF24L01_WritePayload(msg, len);
|
||||
return;
|
||||
}
|
||||
//CC2500
|
||||
#ifdef CC2500_INSTALLED
|
||||
uint8_t buf[35];
|
||||
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);
|
||||
// nrf packet
|
||||
CC2500_WriteRegisterMulti(CC2500_3F_TXFIFO, buf, last);
|
||||
// transmit
|
||||
CC2500_Strobe(CC2500_STX);
|
||||
#endif
|
||||
}
|
||||
|
||||
static boolean __attribute__((unused)) NRF250K_IsPacketSent()
|
||||
{
|
||||
#ifdef CC2500_INSTALLED
|
||||
if(option==0)
|
||||
#endif
|
||||
{ //NRF
|
||||
#if defined(CC2500_INSTALLED)
|
||||
return true; // don't know on the CC2500 how to detect if the packet has been transmitted...
|
||||
#elif defined(NRF24L01_INSTALLED)
|
||||
return NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_TX_DS);
|
||||
}
|
||||
return true; // don't know on the CC2500 how to detect if the packet has been transmitted...
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
65
Multiprotocol/NanoRF_nrf24l01.ino
Normal file
65
Multiprotocol/NanoRF_nrf24l01.ino
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(NANORF_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf24l01.h"
|
||||
|
||||
#define NANORF_PACKET_PERIOD 40000
|
||||
#define NANORF_INITIAL_WAIT 500
|
||||
#define NANORF_RF_CHANNEL 40
|
||||
#define NANORF_PAYLOADSIZE 7
|
||||
|
||||
static void __attribute__((unused)) NANORF_send_packet()
|
||||
{
|
||||
packet[0] = convert_channel_8b(AILERON);
|
||||
packet[1] = convert_channel_8b(ELEVATOR);
|
||||
packet[2] = convert_channel_8b(THROTTLE);
|
||||
packet[3] = convert_channel_8b(RUDDER);
|
||||
packet[4] = convert_channel_8b(CH5);
|
||||
packet[5] = convert_channel_8b(CH6);
|
||||
packet[6] = 0;
|
||||
for (uint8_t i=0; i < NANORF_PAYLOADSIZE-1; i++)
|
||||
packet[6] += packet[i];
|
||||
packet[6] += 0x55;
|
||||
|
||||
// clear packet status bits and TX FIFO
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_WritePayload(packet, NANORF_PAYLOADSIZE);
|
||||
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) NANORF_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR , (uint8_t *)"Nano1",5);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, NANORF_RF_CHANNEL);
|
||||
}
|
||||
|
||||
uint16_t NANORF_callback()
|
||||
{
|
||||
NANORF_send_packet();
|
||||
return NANORF_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
void NANORF_init()
|
||||
{
|
||||
BIND_DONE;
|
||||
NANORF_RF_init();
|
||||
}
|
||||
|
||||
#endif
|
||||
298
Multiprotocol/OMP_cc2500.ino
Normal file
298
Multiprotocol/OMP_cc2500.ino
Normal file
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(OMP_CC2500_INO)
|
||||
|
||||
#ifndef NRF24L01_INSTALLED
|
||||
#undef OMP_HUB_TELEMETRY
|
||||
#endif
|
||||
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
//#define FORCE_OMP_ORIGINAL_ID
|
||||
//#define OMP_TELEM_DEBUG
|
||||
|
||||
#define OMP_INITIAL_WAIT 500
|
||||
#define OMP_PACKET_PERIOD 5000
|
||||
#define OMP_RF_BIND_CHANNEL 35
|
||||
#define OMP_RF_NUM_CHANNELS 8
|
||||
#define OMP_PAYLOAD_SIZE 16
|
||||
#define OMP_BIND_COUNT 600 //3sec
|
||||
|
||||
static void __attribute__((unused)) OMP_send_packet()
|
||||
{
|
||||
#ifdef OMP_HUB_TELEMETRY
|
||||
rf_switch(SW_CC2500);
|
||||
#endif
|
||||
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
memcpy(packet,"BND",3);
|
||||
memcpy(&packet[3],rx_tx_addr,5);
|
||||
memcpy(&packet[8],hopping_frequency,8);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(packet,0x00,OMP_PAYLOAD_SIZE);
|
||||
|
||||
#ifdef OMP_HUB_TELEMETRY
|
||||
//RX telem request every 7*5=35ms
|
||||
packet_sent++;
|
||||
packet_sent %= OMP_RF_NUM_CHANNELS-1; // Change telem RX channels every time
|
||||
if(packet_sent==0)
|
||||
{
|
||||
packet[0] |= 0x40; // |0x40 to request RX telemetry
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, hopping_frequency[hopping_frequency_no]);
|
||||
}
|
||||
#endif
|
||||
|
||||
//hopping frequency
|
||||
packet[0 ] |= hopping_frequency_no;
|
||||
XN297L_Hopping(hopping_frequency_no);
|
||||
hopping_frequency_no++;
|
||||
hopping_frequency_no &= OMP_RF_NUM_CHANNELS-1; // 8 RF channels
|
||||
|
||||
//flags
|
||||
packet[1 ] = 0x08 //unknown
|
||||
| GET_FLAG(CH5_SW, 0x20); // HOLD
|
||||
|
||||
packet[2 ] = 0x40; //unknown
|
||||
|
||||
if(Channel_data[CH6] > CHANNEL_MAX_COMMAND)
|
||||
packet[2 ] |= 0x20; // IDLE2
|
||||
else if(Channel_data[CH6] > CHANNEL_MIN_COMMAND)
|
||||
packet[1 ] |= 0x40; // IDLE1
|
||||
|
||||
if(Channel_data[CH7] > CHANNEL_MAX_COMMAND)
|
||||
packet[2 ] |= 0x08; // 3D
|
||||
else if(Channel_data[CH7] > CHANNEL_MIN_COMMAND)
|
||||
packet[2 ] |= 0x04; // ATTITUDE
|
||||
|
||||
//trims??
|
||||
//packet[3..6]
|
||||
|
||||
//channels TAER packed 11bits
|
||||
uint16_t channel=convert_channel_16b_limit(THROTTLE,0,2047);
|
||||
packet[7 ] = channel;
|
||||
packet[8 ] = channel>>8;
|
||||
channel=convert_channel_16b_limit(AILERON,2047,0);
|
||||
packet[8 ] |= channel<<3;
|
||||
packet[9 ] = channel>>5;
|
||||
channel=convert_channel_16b_limit(ELEVATOR,0,2047);
|
||||
packet[9] |= channel<<6;
|
||||
packet[10] = channel>>2;
|
||||
packet[11] = channel>>10;
|
||||
channel=convert_channel_16b_limit(RUDDER,2047,0);
|
||||
packet[11] |= channel<<1;
|
||||
packet[12] = channel>>7;
|
||||
|
||||
//unknown
|
||||
//packet[13..15]
|
||||
packet[15] = 0x04;
|
||||
}
|
||||
|
||||
XN297L_SetPower(); // Set tx_power
|
||||
XN297L_SetFreqOffset(); // Set frequency offset
|
||||
XN297L_WriteEnhancedPayload(packet, OMP_PAYLOAD_SIZE, packet_sent!=0);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) OMP_RF_init()
|
||||
{
|
||||
//Config CC2500
|
||||
XN297L_Init();
|
||||
XN297L_SetTXAddr((uint8_t*)"FLPBD", 5);
|
||||
XN297L_HoppingCalib(OMP_RF_NUM_CHANNELS); // Calibrate all channels
|
||||
XN297L_RFChannel(OMP_RF_BIND_CHANNEL); // Set bind channel
|
||||
|
||||
#ifdef OMP_HUB_TELEMETRY
|
||||
//Config NRF
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K); // 250Kbps
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC));
|
||||
XN297_SetRXAddr(rx_tx_addr, 5); // Set the RX address
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF); // Turn it off for now
|
||||
NRF24L01_WriteReg(NRF24L01_11_RX_PW_P0, OMP_PAYLOAD_SIZE + 4); // packet length +4 bytes of PCF+CRC
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) OMP_initialize_txid()
|
||||
{
|
||||
calc_fh_channels(OMP_RF_NUM_CHANNELS);
|
||||
#ifdef FORCE_OMP_ORIGINAL_ID
|
||||
rx_tx_addr[0]=0x4E;
|
||||
rx_tx_addr[1]=0x72;
|
||||
rx_tx_addr[2]=0x8E;
|
||||
rx_tx_addr[3]=0x70;
|
||||
rx_tx_addr[4]=0x62;
|
||||
for(uint8_t i=0; i<OMP_RF_NUM_CHANNELS;i++)
|
||||
hopping_frequency[i]=(i+3)*5;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef OMP_HUB_TELEMETRY
|
||||
static void __attribute__((unused)) OMP_Send_Telemetry(uint8_t v)
|
||||
{
|
||||
v_lipo1=v;
|
||||
telemetry_counter++; //LQI
|
||||
telemetry_link=1;
|
||||
if(telemetry_lost)
|
||||
{
|
||||
telemetry_lost = 0;
|
||||
packet_count = 100;
|
||||
telemetry_counter = 100;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
enum {
|
||||
OMP_BIND = 0x00,
|
||||
OMP_PREPDATA = 0x01,
|
||||
OMP_DATA = 0x02,
|
||||
OMP_RX = 0x03,
|
||||
};
|
||||
|
||||
#define OMP_WRITE_TIME 850
|
||||
|
||||
uint16_t OMP_callback()
|
||||
{
|
||||
switch(phase)
|
||||
{
|
||||
case OMP_BIND:
|
||||
if(--bind_counter==0)
|
||||
phase++; // OMP_PREPDATA
|
||||
OMP_send_packet();
|
||||
return OMP_PACKET_PERIOD;
|
||||
case OMP_PREPDATA:
|
||||
BIND_DONE;
|
||||
XN297L_SetTXAddr(rx_tx_addr, 5);
|
||||
phase++; // OMP_DATA
|
||||
case OMP_DATA:
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(OMP_PACKET_PERIOD);
|
||||
#endif
|
||||
OMP_send_packet();
|
||||
#ifdef OMP_HUB_TELEMETRY
|
||||
if(packet_sent == 0)
|
||||
{
|
||||
phase++; // OMP_RX
|
||||
return OMP_WRITE_TIME;
|
||||
}
|
||||
else if(packet_sent == 1)
|
||||
{
|
||||
if( NRF24L01_ReadReg(NRF24L01_07_STATUS) & _BV(NRF24L01_07_RX_DR))
|
||||
{ // a packet has been received
|
||||
if(XN297_ReadEnhancedPayload(packet_in, OMP_PAYLOAD_SIZE) == OMP_PAYLOAD_SIZE)
|
||||
{ // packet with good CRC and length
|
||||
#ifdef OMP_TELEM_DEBUG
|
||||
debug("OK :");
|
||||
for(uint8_t i=0;i<OMP_PAYLOAD_SIZE;i++)
|
||||
debug(" %02X",packet_in[i]);
|
||||
#endif
|
||||
// packet_in = 01 00 98 2C 03 19 19 F0 49 02 00 00 00 00 00 00
|
||||
// all bytes are fixed and unknown except 2 and 3 which represent the battery voltage: packet_in[3]*256+packet_in[2]=lipo voltage*100 in V
|
||||
uint16_t v=((packet_in[3]<<8)+packet_in[2]-400)/50;
|
||||
if(v>255) v=255;
|
||||
v_lipo2=v;
|
||||
OMP_Send_Telemetry(v);
|
||||
}
|
||||
else
|
||||
{ // As soon as the motor spins the telem packets are becoming really bad and the CRC throws most of them in error as it should but...
|
||||
#ifdef OMP_TELEM_DEBUG
|
||||
debug("NOK:");
|
||||
for(uint8_t i=0;i<OMP_PAYLOAD_SIZE;i++)
|
||||
debug(" %02X",packet_in[i]);
|
||||
#endif
|
||||
if(packet_in[0]==0x01 && packet_in[1]==0x00)
|
||||
{// the start of the packet looks ok...
|
||||
uint16_t v=((packet_in[3]<<8)+packet_in[2]-400)/50;
|
||||
if(v<260 && v>180)
|
||||
{ //voltage is less than 13V and more than 9V (3V/element)
|
||||
if(v>255) v=255;
|
||||
uint16_t v1=v-v_lipo2;
|
||||
if(v1&0x8000) v1=-v1;
|
||||
if(v1<20) // the batt voltage is within 1V from a good reading...
|
||||
{
|
||||
OMP_Send_Telemetry(v); // ok to send
|
||||
#ifdef OMP_TELEM_DEBUG
|
||||
debug(" OK");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
telemetry_counter++; //LQI
|
||||
}
|
||||
#ifdef OMP_TELEM_DEBUG
|
||||
debugln("");
|
||||
#endif
|
||||
}
|
||||
NRF24L01_SetTxRxMode(TXRX_OFF);
|
||||
packet_count++;
|
||||
if(packet_count>=100)
|
||||
{//LQI calculation
|
||||
packet_count=0;
|
||||
TX_LQI=telemetry_counter;
|
||||
RX_RSSI=telemetry_counter;
|
||||
if(telemetry_counter==0)
|
||||
telemetry_lost = 1;
|
||||
telemetry_counter = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return OMP_PACKET_PERIOD;
|
||||
#ifdef OMP_HUB_TELEMETRY
|
||||
case OMP_RX:
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, (1 << NRF24L01_07_RX_DR) //reset the flag(s)
|
||||
| (1 << NRF24L01_07_TX_DS)
|
||||
| (1 << NRF24L01_07_MAX_RT));
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, (1 << NRF24L01_00_PWR_UP) | (1 << NRF24L01_00_PRIM_RX) ); // Start RX
|
||||
{
|
||||
uint16_t start=(uint16_t)micros();
|
||||
while ((uint16_t)((uint16_t)micros()-(uint16_t)start) < 500)
|
||||
{
|
||||
if(CC2500_ReadReg(CC2500_35_MARCSTATE | CC2500_READ_BURST) != 0x13)
|
||||
break;
|
||||
}
|
||||
}
|
||||
NRF_CE_on;
|
||||
rf_switch(SW_NRF);
|
||||
phase = OMP_DATA;
|
||||
return OMP_PACKET_PERIOD-OMP_WRITE_TIME;
|
||||
#endif
|
||||
}
|
||||
return OMP_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
void OMP_init()
|
||||
{
|
||||
OMP_initialize_txid();
|
||||
OMP_RF_init();
|
||||
hopping_frequency_no = 0;
|
||||
packet_sent = 0;
|
||||
#ifdef OMP_HUB_TELEMETRY
|
||||
packet_count = 0;
|
||||
telemetry_lost = 1;
|
||||
#endif
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
bind_counter = OMP_BIND_COUNT;
|
||||
phase = OMP_BIND;
|
||||
}
|
||||
else
|
||||
phase = OMP_PREPDATA;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -71,26 +71,14 @@ static void __attribute__((unused)) POTENSIC_send_packet()
|
||||
NRF24L01_SetPower();
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) POTENSIC_init()
|
||||
static void __attribute__((unused)) POTENSIC_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
XN297_SetTXAddr((uint8_t*)"\x01\x01\x01\x01\x06", 5); // Bind address
|
||||
else
|
||||
XN297_SetTXAddr(rx_tx_addr,5); // Normal address
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01); // Enable data pipe 0 only
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // set address length (5 bytes)
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01);
|
||||
NRF24L01_Activate(0x73);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) POTENSIC_initialize_txid()
|
||||
@@ -103,26 +91,25 @@ static void __attribute__((unused)) POTENSIC_initialize_txid()
|
||||
|
||||
uint16_t POTENSIC_callback()
|
||||
{
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(POTENSIC_PACKET_PERIOD);
|
||||
#endif
|
||||
if(bind_counter)
|
||||
if(--bind_counter==0)
|
||||
{
|
||||
BIND_DONE;
|
||||
XN297_SetTXAddr(rx_tx_addr,5);
|
||||
}
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(POTENSIC_PACKET_PERIOD);
|
||||
#endif
|
||||
POTENSIC_send_packet();
|
||||
return POTENSIC_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initPOTENSIC(void)
|
||||
void POTENSIC_init(void)
|
||||
{
|
||||
bind_counter = POTENSIC_BIND_COUNT;
|
||||
POTENSIC_initialize_txid();
|
||||
POTENSIC_init();
|
||||
POTENSIC_RF_init();
|
||||
hopping_frequency_no = 0;
|
||||
return POTENSIC_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,11 +19,14 @@
|
||||
#include "iface_a7105.h"
|
||||
|
||||
//#define PELIKAN_FORCE_ID
|
||||
//#define PELIKAN_LITE_FORCE_ID
|
||||
#define PELIKAN_LITE_FORCE_HOP
|
||||
|
||||
#define PELIKAN_BIND_COUNT 400
|
||||
#define PELIKAN_BIND_RF 0x3C
|
||||
#define PELIKAN_NUM_RF_CHAN 0x1D
|
||||
#define PELIKAN_PAQUET_PERIOD 7980
|
||||
#define PELIKAN_PACKET_PERIOD 7980
|
||||
#define PELIKAN_LITE_PACKET_PERIOD 18000
|
||||
|
||||
static void __attribute__((unused)) pelikan_build_packet()
|
||||
{
|
||||
@@ -36,7 +39,10 @@ static void __attribute__((unused)) pelikan_build_packet()
|
||||
packet[3] = rx_tx_addr[1];
|
||||
packet[4] = rx_tx_addr[2];
|
||||
packet[5] = rx_tx_addr[3];
|
||||
packet[6] = 0x05; //??
|
||||
if(sub_protocol==PELIKAN_PRO)
|
||||
packet[6] = 0x05; //sub version??
|
||||
else //PELIKAN_LITE
|
||||
packet[6] = 0x03; //sub version??
|
||||
packet[7] = 0x00; //??
|
||||
packet[8] = 0x55; //??
|
||||
packet_length = 10;
|
||||
@@ -50,16 +56,16 @@ static void __attribute__((unused)) pelikan_build_packet()
|
||||
packet[13] = rx_tx_addr[3];
|
||||
//Channels
|
||||
uint8_t offset=upper?4:0;
|
||||
uint16_t channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871);
|
||||
uint16_t channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871,false);
|
||||
uint8_t top=(channel>>2) & 0xC0;
|
||||
packet[2] = channel;
|
||||
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871);
|
||||
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871,false);
|
||||
top|=(channel>>4) & 0x30;
|
||||
packet[3] = channel;
|
||||
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871);
|
||||
channel=convert_channel_16b_nolimit(CH_AETR[offset++], 153, 871,false);
|
||||
top|=(channel>>6) & 0x0C;
|
||||
packet[4] = channel;
|
||||
channel=convert_channel_16b_nolimit(CH_AETR[offset], 153, 871);
|
||||
channel=convert_channel_16b_nolimit(CH_AETR[offset], 153, 871,false);
|
||||
top|=(channel>>8) & 0x03;
|
||||
packet[5] = channel;
|
||||
packet[6] = top;
|
||||
@@ -72,7 +78,7 @@ static void __attribute__((unused)) pelikan_build_packet()
|
||||
packet[9]=upper?0xAA:0x00;
|
||||
upper=!upper;
|
||||
//Hopping counters
|
||||
if(++packet_count>4)
|
||||
if(sub_protocol==PELIKAN_LITE || ++packet_count>4)
|
||||
{
|
||||
packet_count=0;
|
||||
if(++hopping_frequency_no>=PELIKAN_NUM_RF_CHAN)
|
||||
@@ -104,26 +110,43 @@ static void __attribute__((unused)) pelikan_build_packet()
|
||||
A7105_SetPower();
|
||||
}
|
||||
|
||||
uint16_t ReadPelikan()
|
||||
uint16_t PELIKAN_callback()
|
||||
{
|
||||
#ifndef FORCE_PELIKAN_TUNING
|
||||
A7105_AdjustLOBaseFreq(1);
|
||||
#endif
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
if(phase==0)
|
||||
{
|
||||
bind_counter--;
|
||||
if (bind_counter==0)
|
||||
#ifndef FORCE_PELIKAN_TUNING
|
||||
A7105_AdjustLOBaseFreq(1);
|
||||
#endif
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
BIND_DONE;
|
||||
A7105_Strobe(A7105_STANDBY);
|
||||
A7105_WriteReg(A7105_03_FIFOI,0x28);
|
||||
bind_counter--;
|
||||
if (bind_counter==0)
|
||||
{
|
||||
BIND_DONE;
|
||||
A7105_Strobe(A7105_STANDBY);
|
||||
if(sub_protocol==PELIKAN_PRO)
|
||||
A7105_WriteReg(A7105_03_FIFOI,0x28);
|
||||
else//PELIKAN_LITE
|
||||
A7105_WriteID(MProtocol_id);
|
||||
}
|
||||
}
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(sub_protocol==PELIKAN_PRO?PELIKAN_PACKET_PERIOD:PELIKAN_LITE_PACKET_PERIOD);
|
||||
#endif
|
||||
pelikan_build_packet();
|
||||
if(sub_protocol==PELIKAN_PRO || IS_BIND_IN_PROGRESS)
|
||||
return PELIKAN_PACKET_PERIOD;
|
||||
//PELIKAN_LITE
|
||||
phase++;
|
||||
return 942;
|
||||
}
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(PELIKAN_PAQUET_PERIOD);
|
||||
#endif
|
||||
pelikan_build_packet();
|
||||
return PELIKAN_PAQUET_PERIOD;
|
||||
//PELIKAN_LITE
|
||||
A7105_Strobe(A7105_TX);
|
||||
phase++;
|
||||
if(phase==1)
|
||||
return 942;
|
||||
phase=0;
|
||||
return PELIKAN_LITE_PACKET_PERIOD-942-942;
|
||||
}
|
||||
|
||||
static uint8_t pelikan_firstCh(uint8_t u, uint8_t l)
|
||||
@@ -213,27 +236,57 @@ const uint8_t PROGMEM pelikan_hopp[][PELIKAN_NUM_RF_CHAN] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
uint16_t initPelikan()
|
||||
#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
|
||||
|
||||
void PELIKAN_init()
|
||||
{
|
||||
A7105_Init();
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
if(IS_BIND_IN_PROGRESS || sub_protocol==PELIKAN_LITE)
|
||||
A7105_WriteReg(A7105_03_FIFOI,0x10);
|
||||
|
||||
|
||||
pelikan_init_hop();
|
||||
|
||||
//ID from dump
|
||||
#ifdef PELIKAN_FORCE_ID
|
||||
rx_tx_addr[0]=0x0D; // hopping freq
|
||||
rx_tx_addr[1]=0xF4; // hopping freq
|
||||
rx_tx_addr[2]=0x50; // ID
|
||||
rx_tx_addr[3]=0x18; // ID
|
||||
// Fill frequency table
|
||||
for(uint8_t i=0;i<PELIKAN_NUM_RF_CHAN;i++)
|
||||
hopping_frequency[i]=pgm_read_byte_near(&pelikan_hopp[0][i]);
|
||||
#else
|
||||
pelikan_init_hop();
|
||||
#if defined(PELIKAN_FORCE_ID)
|
||||
if(sub_protocol==PELIKAN_PRO)
|
||||
{
|
||||
rx_tx_addr[0]=0x0D; // hopping freq
|
||||
rx_tx_addr[1]=0xF4; // hopping freq
|
||||
rx_tx_addr[2]=0x50; // ID
|
||||
rx_tx_addr[3]=0x18; // ID
|
||||
// Fill frequency table
|
||||
for(uint8_t i=0;i<PELIKAN_NUM_RF_CHAN;i++)
|
||||
hopping_frequency[i]=pgm_read_byte_near(&pelikan_hopp[0][i]);
|
||||
}
|
||||
#endif
|
||||
#if defined(PELIKAN_LITE_FORCE_ID) || defined(PELIKAN_LITE_FORCE_HOP)
|
||||
if(sub_protocol==PELIKAN_LITE)
|
||||
{
|
||||
#if defined(PELIKAN_LITE_FORCE_ID)
|
||||
// ID
|
||||
rx_tx_addr[2]=0x60;
|
||||
rx_tx_addr[3]=0x18;
|
||||
#endif
|
||||
#if defined(PELIKAN_LITE_FORCE_HOP)
|
||||
// Hop frequency table
|
||||
rx_tx_addr[0]=0x04; // hopping freq
|
||||
rx_tx_addr[1]=0x63; // hopping freq
|
||||
for(uint8_t i=0;i<PELIKAN_NUM_RF_CHAN;i++)
|
||||
hopping_frequency[i]=pgm_read_byte_near(&pelikan_lite_hopp[0][i]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
MProtocol_id=((uint32_t)rx_tx_addr[0]<<24)|((uint32_t)rx_tx_addr[1]<<16)|((uint32_t)rx_tx_addr[2]<<8)|(rx_tx_addr[3]);
|
||||
if(sub_protocol==PELIKAN_LITE && IS_BIND_DONE)
|
||||
A7105_WriteID(MProtocol_id);
|
||||
|
||||
hopping_frequency_no=PELIKAN_NUM_RF_CHAN;
|
||||
packet_count=5;
|
||||
return 2400;
|
||||
phase=0;
|
||||
}
|
||||
#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)
|
||||
|
||||
@@ -155,27 +155,21 @@ static void __attribute__((unused)) PROPEL_data_packet()
|
||||
NRF24L01_WritePayload(packet, PROPEL_PACKET_SIZE);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) PROPEL_init()
|
||||
static void __attribute__((unused)) PROPEL_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x7f);
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x3f); // AA on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3f); // Enable all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte address
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x36); // retransmit 1ms, 6 times
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x07); // ?? match protocol capture
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x3f); // AA on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3f); // Enable all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x36); // retransmit 1ms, 6 times
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_0A_RX_ADDR_P0, (uint8_t *)"\x99\x77\x55\x33\x11", PROPEL_ADDRESS_LENGTH); //Bind address
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR, (uint8_t *)"\x99\x77\x55\x33\x11", PROPEL_ADDRESS_LENGTH); //Bind address
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, PROPEL_BIND_RF_CHANNEL);
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // Enable dynamic payload length
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Enable all features
|
||||
// Beken 2425 register bank 1 initialized here in stock tx capture
|
||||
// Hopefully won't matter for nRF compatibility
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x3f); // Enable dynamic payload length
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x07); // Enable all features
|
||||
|
||||
NRF24L01_SetTxRxMode(TX_EN); // Clear data ready, data sent, retransmit and enable CRC 16bits, ready for TX
|
||||
}
|
||||
|
||||
const uint8_t PROGMEM PROPEL_hopping []= { 0x47,0x36,0x27,0x44,0x33,0x0D,0x3C,0x2E,0x1B,0x39,0x2A,0x18 };
|
||||
@@ -252,41 +246,42 @@ uint16_t PROPEL_callback()
|
||||
break;
|
||||
|
||||
case PROPEL_DATA1:
|
||||
if (_BV(NRF24L01_07_RX_DR) & NRF24L01_ReadReg(NRF24L01_07_STATUS))
|
||||
{// data received from the model
|
||||
NRF24L01_ReadPayload(packet_in, PROPEL_PACKET_SIZE);
|
||||
if (packet_in[0] == 0xa3 && memcmp(&packet_in[1],rx_id,3)==0)
|
||||
{
|
||||
telemetry_counter++; //LQI
|
||||
v_lipo1=packet[5]; //number of life left?
|
||||
v_lipo2=packet[4]; //bit mask: 0x80=flying, 0x08=taking off, 0x04=landing, 0x00=landed/crashed
|
||||
if(telemetry_lost==0)
|
||||
telemetry_link=1;
|
||||
#ifdef PROPEL_HUB_TELEMETRY
|
||||
if (_BV(NRF24L01_07_RX_DR) & NRF24L01_ReadReg(NRF24L01_07_STATUS))
|
||||
{// data received from the model
|
||||
NRF24L01_ReadPayload(packet_in, PROPEL_PACKET_SIZE);
|
||||
if (packet_in[0] == 0xa3 && memcmp(&packet_in[1],rx_id,3)==0)
|
||||
{
|
||||
telemetry_counter++; //LQI
|
||||
v_lipo1=packet[5]; //number of life left?
|
||||
v_lipo2=packet[4]; //bit mask: 0x80=flying, 0x08=taking off, 0x04=landing, 0x00=landed/crashed
|
||||
if(telemetry_lost==0)
|
||||
telemetry_link=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
packet_count++;
|
||||
if(packet_count>=100)
|
||||
{//LQI calculation
|
||||
packet_count=0;
|
||||
TX_LQI=telemetry_counter;
|
||||
RX_RSSI=telemetry_counter;
|
||||
telemetry_counter = 0;
|
||||
telemetry_lost=0;
|
||||
}
|
||||
#endif
|
||||
PROPEL_data_packet();
|
||||
packet_count++;
|
||||
if(packet_count>=100)
|
||||
{//LQI calculation
|
||||
packet_count=0;
|
||||
TX_LQI=telemetry_counter;
|
||||
RX_RSSI=telemetry_counter;
|
||||
telemetry_counter = 0;
|
||||
telemetry_lost=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return PROPEL_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initPROPEL()
|
||||
void PROPEL_init()
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
PROPEL_initialize_txid();
|
||||
PROPEL_init();
|
||||
PROPEL_RF_init();
|
||||
hopping_frequency_no = 0;
|
||||
phase=PROPEL_BIND1;
|
||||
return PROPEL_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -174,10 +174,10 @@ static uint8_t __attribute__((unused)) cx35_lastButton()
|
||||
return command;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) Q303_send_packet(uint8_t bind)
|
||||
static void __attribute__((unused)) Q303_send_packet()
|
||||
{
|
||||
uint16_t aileron, elevator, throttle, rudder, slider;
|
||||
if(bind)
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
packet[0] = 0xaa;
|
||||
memcpy(&packet[1], rx_tx_addr + 1, 4);
|
||||
@@ -270,7 +270,7 @@ static void __attribute__((unused)) Q303_send_packet(uint8_t bind)
|
||||
// Power on, TX mode, CRC enabled
|
||||
XN297_Configure(_BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO) | _BV(NRF24L01_00_PWR_UP));
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, bind ? Q303_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no++]);
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, IS_BIND_IN_PROGRESS ? Q303_RF_BIND_CHANNEL : hopping_frequency[hopping_frequency_no++]);
|
||||
hopping_frequency_no %= rf_ch_num;
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70);
|
||||
@@ -281,37 +281,18 @@ static void __attribute__((unused)) Q303_send_packet(uint8_t bind)
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) Q303_init()
|
||||
static void __attribute__((unused)) Q303_RF_init()
|
||||
{
|
||||
const uint8_t bind_address[] = {0xcc,0xcc,0xcc,0xcc,0xcc};
|
||||
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
switch(sub_protocol)
|
||||
|
||||
if(sub_protocol==Q303)
|
||||
{
|
||||
case CX35:
|
||||
case CX10D:
|
||||
case CX10WD:
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M);
|
||||
break;
|
||||
case Q303:
|
||||
XN297_SetScrambledMode(XN297_UNSCRAMBLED);
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K);
|
||||
break;
|
||||
XN297_SetScrambledMode(XN297_UNSCRAMBLED);
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_250K);
|
||||
}
|
||||
XN297_SetTXAddr(bind_address, 5);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_FlushRx();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x01);
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03);
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0x00); // no retransmits
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_Activate(0x73); // Activate feature register
|
||||
NRF24L01_WriteReg(NRF24L01_1C_DYNPD, 0x00); // Disable dynamic payload length on all pipes
|
||||
NRF24L01_WriteReg(NRF24L01_1D_FEATURE, 0x01); // Set feature bits on
|
||||
NRF24L01_Activate(0x73);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) Q303_initialize_txid()
|
||||
@@ -353,34 +334,27 @@ static void __attribute__((unused)) Q303_initialize_txid()
|
||||
|
||||
uint16_t Q303_callback()
|
||||
{
|
||||
if(IS_BIND_DONE)
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
Q303_send_packet(0);
|
||||
}
|
||||
else
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
if(bind_counter)
|
||||
{
|
||||
bind_counter--;
|
||||
if (bind_counter == 0)
|
||||
{
|
||||
XN297_SetTXAddr(rx_tx_addr, 5);
|
||||
packet_count = 0;
|
||||
BIND_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Q303_send_packet(1);
|
||||
bind_counter--;
|
||||
}
|
||||
}
|
||||
Q303_send_packet();
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
uint16_t initQ303()
|
||||
void Q303_init()
|
||||
{
|
||||
Q303_initialize_txid();
|
||||
Q303_init();
|
||||
Q303_RF_init();
|
||||
bind_counter = Q303_BIND_COUNT;
|
||||
switch(sub_protocol)
|
||||
{
|
||||
@@ -407,7 +381,6 @@ uint16_t initQ303()
|
||||
}
|
||||
hopping_frequency_no = 0;
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
return Q303_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
175
Multiprotocol/Q90C_ccnrf.ino
Normal file
175
Multiprotocol/Q90C_ccnrf.ino
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
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_CCNRF_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_RF_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(bind_counter)
|
||||
if(--bind_counter==0)
|
||||
{
|
||||
BIND_DONE;
|
||||
XN297L_SetTXAddr(rx_tx_addr, Q90C_ADDRESS_LENGTH);
|
||||
}
|
||||
Q90C_send_packet();
|
||||
return Q90C_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
void Q90C_init()
|
||||
{
|
||||
Q90C_initialize_txid();
|
||||
Q90C_RF_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;
|
||||
}
|
||||
|
||||
#endif
|
||||
149
Multiprotocol/REALACC_nrf24l01.ino
Normal file
149
Multiprotocol/REALACC_nrf24l01.ino
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
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_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void REALACC_init()
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
REALACC_initialize_txid();
|
||||
REALACC_RF_init();
|
||||
bind_counter=REALACC_BIND_COUNT;
|
||||
hopping_frequency_no=0;
|
||||
}
|
||||
|
||||
#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
|
||||
104
Multiprotocol/RF2500_EMU.ino
Normal file
104
Multiprotocol/RF2500_EMU.ino
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifdef CYRF6936_INSTALLED
|
||||
#include "iface_rf2500.h"
|
||||
|
||||
#define RF2500_ADDR_LENGTH 4
|
||||
|
||||
uint8_t RF2500_payload_length, RF2500_tx_addr[RF2500_ADDR_LENGTH], RF2500_buf[80];
|
||||
bool RF2500_scramble_enabled;
|
||||
|
||||
static void __attribute__((unused)) RF2500_Init(uint8_t payload_length, bool scramble)
|
||||
{
|
||||
CYRF_GFSK1M_Init( RF2500_ADDR_LENGTH + 2 + (payload_length+2)*4, 2 ); // full payload length with CRC + address + 5 + FEC
|
||||
|
||||
RF2500_payload_length=payload_length;
|
||||
RF2500_scramble_enabled=scramble;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) RF2500_SetTXAddr(const uint8_t* addr)
|
||||
{
|
||||
memcpy(RF2500_tx_addr, addr, RF2500_ADDR_LENGTH);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) RF2500_BuildPayload(uint8_t* buffer)
|
||||
{
|
||||
const uint8_t RF2500_scramble[] = { 0xD0, 0x9E, 0x53, 0x33, 0xD8, 0xBA, 0x98, 0x08, 0x24, 0xCB, 0x3B, 0xFC, 0x71, 0xA3, 0xF4, 0x55 };
|
||||
const uint16_t RF2500_crc_xorout_scramble = 0xAEE4;
|
||||
|
||||
//Scramble the incoming buffer
|
||||
if(RF2500_scramble_enabled)
|
||||
for(uint8_t i=0; i<RF2500_payload_length; i++)
|
||||
buffer[i] ^= RF2500_scramble[i];
|
||||
|
||||
//Add CRC to the buffer
|
||||
crc=0x0000;
|
||||
for(uint8_t i=0;i<RF2500_payload_length;i++)
|
||||
crc16_update(bit_reverse(buffer[i]),8);
|
||||
buffer[RF2500_payload_length ] = bit_reverse(crc>>8);
|
||||
buffer[RF2500_payload_length+1] = bit_reverse(crc);
|
||||
|
||||
if(RF2500_scramble_enabled)
|
||||
{
|
||||
buffer[RF2500_payload_length ] ^= RF2500_crc_xorout_scramble>>8;
|
||||
buffer[RF2500_payload_length+1] ^= RF2500_crc_xorout_scramble;
|
||||
}
|
||||
|
||||
#if 0
|
||||
debug("B:");
|
||||
for(uint8_t i=0; i<RF2500_payload_length+2; i++)
|
||||
debug(" %02X",buffer[i]);
|
||||
debugln("");
|
||||
#endif
|
||||
|
||||
memcpy(RF2500_buf,RF2500_tx_addr,RF2500_ADDR_LENGTH); // Address
|
||||
|
||||
uint8_t pos = RF2500_ADDR_LENGTH;
|
||||
|
||||
RF2500_buf[pos++]=0xC3;RF2500_buf[pos++]=0xC3; // 5 FEC encoded
|
||||
memset(&RF2500_buf[pos],0x00,(RF2500_payload_length+2)*4); // + CRC) * 4 FEC bytes per byte
|
||||
|
||||
//FEC encode
|
||||
for(uint8_t i=0; i<RF2500_payload_length+2; i++) // Include CRC
|
||||
{
|
||||
for(uint8_t j=0;j<8;j++)
|
||||
{
|
||||
uint8_t offset=pos + (i<<2) + (j>>1);
|
||||
RF2500_buf[offset] <<= 4;
|
||||
if( (buffer[i]>>j) & 0x01 )
|
||||
RF2500_buf[offset] |= 0x0C;
|
||||
else
|
||||
RF2500_buf[offset] |= 0x03;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
debug("E:");
|
||||
for(uint8_t i=0; i<RF2500_ADDR_LENGTH+2+(RF2500_payload_length+2)*4; i++)
|
||||
debug(" %02X",RF2500_buf[i]);
|
||||
debugln("");
|
||||
#endif
|
||||
|
||||
//CYRF wants LSB first
|
||||
for(uint8_t i=0; i<RF2500_ADDR_LENGTH+2+(RF2500_payload_length+2)*4; i++)
|
||||
RF2500_buf[i]=bit_reverse(RF2500_buf[i]);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) RF2500_SendPayload()
|
||||
{
|
||||
CYRF_GFSK1M_SendPayload(RF2500_buf, RF2500_ADDR_LENGTH + 2 + (RF2500_payload_length+2)*4 );
|
||||
}
|
||||
|
||||
#endif
|
||||
308
Multiprotocol/RadioLink_cc2500.ino
Normal file
308
Multiprotocol/RadioLink_cc2500.ino
Normal file
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
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_TXID_init()
|
||||
{
|
||||
#ifdef RLINK_FORCE_ID
|
||||
//surface RC6GS
|
||||
memcpy(rx_tx_addr,"\x3A\x99\x22\x3A",RLINK_TX_ID_LEN);
|
||||
//air T8FB
|
||||
//memcpy(rx_tx_addr,"\xFC\x11\x0D\x20",RLINK_TX_ID_LEN);
|
||||
#endif
|
||||
// channels order depend on ID
|
||||
RLINK_hop();
|
||||
|
||||
#if 0
|
||||
debug("ID:");
|
||||
for(uint8_t i=0;i<RLINK_TX_ID_LEN;i++)
|
||||
debug(" 0x%02X",rx_tx_addr[i]);
|
||||
debugln("");
|
||||
debug("Hop(%d):", rf_ch_num);
|
||||
for(uint8_t i=0;i<RLINK_HOP;i++)
|
||||
debug(" 0x%02X",hopping_frequency[i]);
|
||||
debugln("");
|
||||
#endif
|
||||
}
|
||||
|
||||
const PROGMEM uint8_t RLINK_init_values[] = {
|
||||
/* 00 */ 0x5B, 0x06, 0x5C, 0x07, 0xAB, 0xCD, 0x40, 0x04,
|
||||
/* 08 */ 0x45, 0x00, 0x00, 0x06, 0x00, 0x5C, 0x62, 0x76,
|
||||
/* 10 */ 0x7A, 0x7F, 0x13, 0x23, 0xF8, 0x44, 0x07, 0x30,
|
||||
/* 18 */ 0x18, 0x16, 0x6C, 0x43, 0x40, 0x91, 0x87, 0x6B,
|
||||
/* 20 */ 0xF8, 0x56, 0x10, 0xA9, 0x0A, 0x00, 0x11
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) RLINK_rf_init()
|
||||
{
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
|
||||
for (uint8_t i = 0; i < 39; ++i)
|
||||
CC2500_WriteReg(i, pgm_read_byte_near(&RLINK_init_values[i]));
|
||||
|
||||
if(sub_protocol==RLINK_DUMBORC)
|
||||
{
|
||||
CC2500_WriteReg(4, 0xBA);
|
||||
CC2500_WriteReg(5, 0xDC);
|
||||
}
|
||||
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) RLINK_send_packet()
|
||||
{
|
||||
static uint32_t pseudo=0;
|
||||
uint32_t bits = 0;
|
||||
uint8_t bitsavailable = 0;
|
||||
uint8_t idx = 6;
|
||||
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
|
||||
// packet length
|
||||
packet[0] = RLINK_TX_PACKET_LEN;
|
||||
// header
|
||||
if(packet_count>3)
|
||||
packet[1] = 0x02; // 0x02 telemetry request flag
|
||||
switch(sub_protocol)
|
||||
{
|
||||
case RLINK_SURFACE:
|
||||
packet[1] |= 0x01;
|
||||
//radiolink additionnal ID which is working only on a small set of RXs
|
||||
//if(RX_num) packet[1] |= ((RX_num+2)<<4)+4; // RX number limited to 10 values, 0 is a wildcard
|
||||
break;
|
||||
case RLINK_AIR:
|
||||
packet[1] |= 0x21; //air 0x21 on dump but it looks to support telemetry at least RSSI
|
||||
break;
|
||||
case RLINK_DUMBORC:
|
||||
packet[1] = 0x00; //always 0x00 on dump
|
||||
break;
|
||||
}
|
||||
|
||||
// ID
|
||||
memcpy(&packet[2],rx_tx_addr,RLINK_TX_ID_LEN);
|
||||
|
||||
// pack 16 channels on 11 bits values between 170 and 1876, 1023 middle. The last 8 channels are failsafe values associated to the first 8 values.
|
||||
for (uint8_t i = 0; i < 16; i++)
|
||||
{
|
||||
uint32_t val = convert_channel_16b_nolimit(i,170,1876,false); // allow extended limits
|
||||
if (val & 0x8000)
|
||||
val = 0;
|
||||
else if (val > 2047)
|
||||
val=2047;
|
||||
|
||||
bits |= val << bitsavailable;
|
||||
bitsavailable += 11;
|
||||
while (bitsavailable >= 8) {
|
||||
packet[idx++] = bits & 0xff;
|
||||
bits >>= 8;
|
||||
bitsavailable -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
// hop
|
||||
pseudo=((pseudo * 0xAA) + 0x03) % 0x7673; // calc next pseudo random value
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[pseudo & 0x0F]);
|
||||
packet[28]= pseudo;
|
||||
packet[29]= pseudo >> 8;
|
||||
packet[30]= 0x00; // unknown
|
||||
packet[31]= 0x00; // unknown
|
||||
packet[32]= rf_ch_num; // index of value changed in the RF table
|
||||
|
||||
// check
|
||||
uint8_t sum=0;
|
||||
for(uint8_t i=1;i<33;i++)
|
||||
sum+=packet[i];
|
||||
packet[33]=sum;
|
||||
|
||||
// send packet
|
||||
CC2500_WriteData(packet, RLINK_TX_PACKET_LEN+1);
|
||||
|
||||
// packets type
|
||||
packet_count++;
|
||||
if(packet_count>5) packet_count=0;
|
||||
|
||||
//debugln("C= 0x%02X",hopping_frequency[pseudo & 0x0F]);
|
||||
//debug("P=");
|
||||
//for(uint8_t i=1;i<RLINK_TX_PACKET_LEN+1;i++)
|
||||
// debug(" 0x%02X",packet[i]);
|
||||
//debugln("");
|
||||
}
|
||||
|
||||
#define RLINK_TIMING_PROTO 20000-100 // -100 for compatibility with R8EF
|
||||
#define RLINK_TIMING_RFSEND 10500
|
||||
#define RLINK_TIMING_CHECK 2000
|
||||
uint16_t RLINK_callback()
|
||||
{
|
||||
switch(phase)
|
||||
{
|
||||
case RLINK_DATA:
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(RLINK_TIMING_PROTO);
|
||||
#endif
|
||||
CC2500_SetPower();
|
||||
CC2500_SetFreqOffset();
|
||||
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;
|
||||
}
|
||||
|
||||
void RLINK_init()
|
||||
{
|
||||
BIND_DONE; // Not a TX bind protocol
|
||||
RLINK_TXID_init();
|
||||
RLINK_rf_init();
|
||||
packet_count = 0;
|
||||
phase = RLINK_DATA;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -96,17 +96,13 @@ static void REDPINE_data_frame() {
|
||||
packet[10] = REDPINE_LOOPTIME_SLOW;
|
||||
}
|
||||
|
||||
static uint16_t ReadREDPINE()
|
||||
uint16_t REDPINE_callback()
|
||||
{
|
||||
if ( prev_option != option )
|
||||
{ // Frequency adjust
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
prev_option = option ;
|
||||
}
|
||||
CC2500_SetFreqOffset();
|
||||
if(IS_BIND_IN_PROGRESS)
|
||||
{
|
||||
if (state == REDPINE_BIND) {
|
||||
REDPINE_init(0);
|
||||
REDPINE_RF_init(0);
|
||||
}
|
||||
REDPINE_set_channel(49);
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
@@ -118,26 +114,22 @@ static uint16_t ReadREDPINE()
|
||||
if(--bind_counter==0)
|
||||
{
|
||||
BIND_DONE;
|
||||
REDPINE_init(sub_protocol);
|
||||
REDPINE_RF_init(sub_protocol);
|
||||
}
|
||||
return 4000;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
REDPINE_set_channel(hopping_frequency_no);
|
||||
CC2500_SetPower();
|
||||
CC2500_Strobe(CC2500_SFRX);
|
||||
REDPINE_data_frame();
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
hopping_frequency_no = (hopping_frequency_no + 1) % 49;
|
||||
CC2500_WriteData(packet, REDPINE_PACKET_SIZE);
|
||||
return packet_period;
|
||||
}
|
||||
return 1;
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(packet_period);
|
||||
#endif
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
REDPINE_set_channel(hopping_frequency_no);
|
||||
CC2500_SetPower();
|
||||
CC2500_Strobe(CC2500_SFRX);
|
||||
REDPINE_data_frame();
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
hopping_frequency_no = (hopping_frequency_no + 1) % 49;
|
||||
CC2500_WriteData(packet, REDPINE_PACKET_SIZE);
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
// register, fast 250k, slow
|
||||
@@ -179,7 +171,7 @@ static const uint8_t REDPINE_init_data[][3] = {
|
||||
{CC2500_3E_PATABLE, 0xff, 0xff}
|
||||
};
|
||||
|
||||
static void REDPINE_init(uint8_t format)
|
||||
static void REDPINE_RF_init(uint8_t format)
|
||||
{
|
||||
CC2500_Reset();
|
||||
|
||||
@@ -189,7 +181,6 @@ static void REDPINE_init(uint8_t format)
|
||||
CC2500_WriteReg(REDPINE_init_data[i][0], REDPINE_init_data[i][format+1]);
|
||||
}
|
||||
|
||||
prev_option = option;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
|
||||
@@ -204,7 +195,7 @@ static void REDPINE_init(uint8_t format)
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t initREDPINE()
|
||||
void REDPINE_init()
|
||||
{
|
||||
hopping_frequency_no = 0;
|
||||
// Used from kn_nrf24l01.c : kn_calculate_freqency_hopping_channels
|
||||
@@ -237,8 +228,7 @@ static uint16_t initREDPINE()
|
||||
packet_period = REDPINE_LOOPTIME_SLOW*1000;
|
||||
|
||||
bind_counter=REDPINE_BIND;
|
||||
REDPINE_init(sub_protocol);
|
||||
REDPINE_RF_init(sub_protocol);
|
||||
CC2500_SetTxRxMode(TX_EN); // enable PA
|
||||
return 10000;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -29,15 +29,9 @@ const uint8_t PROGMEM SHENQI_Freq[] = {
|
||||
10,60,10,50,30,40,
|
||||
20,10,40,30,60,20 };
|
||||
|
||||
void SHENQI_init()
|
||||
void SHENQI_RF_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknowldgement on all data pipes
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M); // 1Mbps
|
||||
NRF24L01_SetPower();
|
||||
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5 bytes rx/tx address
|
||||
|
||||
LT8900_Config(4, 8, _BV(LT8900_CRC_ON)|_BV(LT8900_PACKET_LENGTH_EN), 0xAA);
|
||||
LT8900_SetChannel(2);
|
||||
@@ -116,14 +110,13 @@ uint16_t SHENQI_callback()
|
||||
return packet_period;
|
||||
}
|
||||
|
||||
uint16_t initSHENQI()
|
||||
void SHENQI_init()
|
||||
{
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
SHENQI_init();
|
||||
SHENQI_RF_init();
|
||||
hopping_frequency_no = 0;
|
||||
packet_count=0;
|
||||
packet_period=500;
|
||||
return 1000;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,281 +1,281 @@
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Last sync with deviation main github branch
|
||||
|
||||
#if defined(SLT_NRF24L01_INO)
|
||||
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
//#define SLT_Q200_FORCE_ID
|
||||
|
||||
// For code readability
|
||||
#define SLT_PAYLOADSIZE_V1 7
|
||||
#define SLT_PAYLOADSIZE_V2 11
|
||||
#define SLT_NFREQCHANNELS 15
|
||||
#define SLT_TXID_SIZE 4
|
||||
#define SLT_BIND_CHANNEL 0x50
|
||||
|
||||
enum{
|
||||
// flags going to packet[6] (Q200)
|
||||
FLAG_Q200_FMODE = 0x20,
|
||||
FLAG_Q200_VIDON = 0x10,
|
||||
FLAG_Q200_FLIP = 0x08,
|
||||
FLAG_Q200_VIDOFF= 0x04,
|
||||
};
|
||||
|
||||
enum{
|
||||
// flags going to packet[6] (MR100 & Q100)
|
||||
FLAG_MR100_FMODE = 0x20,
|
||||
FLAG_MR100_FLIP = 0x04,
|
||||
FLAG_MR100_VIDEO = 0x02,
|
||||
FLAG_MR100_PICTURE = 0x01,
|
||||
};
|
||||
|
||||
enum {
|
||||
SLT_BUILD=0,
|
||||
SLT_DATA1,
|
||||
SLT_DATA2,
|
||||
SLT_DATA3,
|
||||
SLT_BIND1,
|
||||
SLT_BIND2,
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) SLT_init()
|
||||
{
|
||||
NRF250K_Init();
|
||||
NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_set_freq(void)
|
||||
{
|
||||
// Frequency hopping sequence generation
|
||||
for (uint8_t i = 0; i < SLT_TXID_SIZE; ++i)
|
||||
{
|
||||
uint8_t next_i = (i+1) % SLT_TXID_SIZE; // is & 3 better than % 4 ?
|
||||
uint8_t base = i < 2 ? 0x03 : 0x10;
|
||||
hopping_frequency[i*4 + 0] = (rx_tx_addr[i] & 0x3f) + base;
|
||||
hopping_frequency[i*4 + 1] = (rx_tx_addr[i] >> 2) + base;
|
||||
hopping_frequency[i*4 + 2] = (rx_tx_addr[i] >> 4) + (rx_tx_addr[next_i] & 0x03)*0x10 + base;
|
||||
hopping_frequency[i*4 + 3] = (rx_tx_addr[i] >> 6) + (rx_tx_addr[next_i] & 0x0f)*0x04 + base;
|
||||
}
|
||||
|
||||
// Unique freq
|
||||
uint8_t max_freq=0x50; //V1 and V2
|
||||
if(sub_protocol==Q200)
|
||||
max_freq=45;
|
||||
for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i)
|
||||
{
|
||||
if(sub_protocol==Q200 && hopping_frequency[i] >= max_freq)
|
||||
hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03;
|
||||
uint8_t done = 0;
|
||||
while (!done)
|
||||
{
|
||||
done = 1;
|
||||
for (uint8_t j = 0; j < i; ++j)
|
||||
if (hopping_frequency[i] == hopping_frequency[j])
|
||||
{
|
||||
done = 0;
|
||||
hopping_frequency[i] += 7;
|
||||
if (hopping_frequency[i] >= max_freq)
|
||||
hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Bind channel
|
||||
hopping_frequency[SLT_NFREQCHANNELS]=SLT_BIND_CHANNEL;
|
||||
|
||||
//Calib all channels
|
||||
NRF250K_HoppingCalib(SLT_NFREQCHANNELS+1);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_wait_radio()
|
||||
{
|
||||
if (packet_sent)
|
||||
while (!NRF250K_IsPacketSent());
|
||||
packet_sent = 0;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_send_packet(uint8_t len)
|
||||
{
|
||||
SLT_wait_radio();
|
||||
NRF250K_WritePayload(packet, len);
|
||||
packet_sent = 1;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_build_packet()
|
||||
{
|
||||
static uint8_t calib_counter=0;
|
||||
|
||||
// Set radio channel - once per packet batch
|
||||
NRF250K_SetFreqOffset(); // Set frequency offset
|
||||
NRF250K_Hopping(hopping_frequency_no);
|
||||
if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
|
||||
hopping_frequency_no = 0;
|
||||
|
||||
// aileron, elevator, throttle, rudder, gear, pitch
|
||||
uint8_t e = 0; // byte where extension 2 bits for every 10-bit channel are packed
|
||||
for (uint8_t i = 0; i < 4; ++i)
|
||||
{
|
||||
uint16_t v = convert_channel_10b(CH_AETR[i]);
|
||||
if(sub_protocol>SLT_V2 && (i==CH2 || i==CH3) )
|
||||
v=1023-v; // reverse throttle and elevator channels for Q100/Q200/MR100 protocols
|
||||
packet[i] = v;
|
||||
e = (e >> 2) | (uint8_t) ((v >> 2) & 0xC0);
|
||||
}
|
||||
// Extra bits for AETR
|
||||
packet[4] = e;
|
||||
// 8-bit channels
|
||||
packet[5] = convert_channel_8b(CH5);
|
||||
packet[6] = convert_channel_8b(CH6);
|
||||
if(sub_protocol!=SLT_V1)
|
||||
{
|
||||
if(sub_protocol==Q200)
|
||||
packet[6] = GET_FLAG(CH9_SW , FLAG_Q200_FMODE)
|
||||
|GET_FLAG(CH10_SW, FLAG_Q200_FLIP)
|
||||
|GET_FLAG(CH11_SW, FLAG_Q200_VIDON)
|
||||
|GET_FLAG(CH12_SW, FLAG_Q200_VIDOFF);
|
||||
else if(sub_protocol==MR100 || sub_protocol==Q100)
|
||||
packet[6] = GET_FLAG(CH9_SW , FLAG_MR100_FMODE)
|
||||
|GET_FLAG(CH10_SW, FLAG_MR100_FLIP)
|
||||
|GET_FLAG(CH11_SW, FLAG_MR100_VIDEO) // Does not exist on the Q100 but...
|
||||
|GET_FLAG(CH12_SW, FLAG_MR100_PICTURE); // Does not exist on the Q100 but...
|
||||
packet[7]=convert_channel_8b(CH7);
|
||||
packet[8]=convert_channel_8b(CH8);
|
||||
packet[9]=0xAA; //normal mode for Q100/Q200, unknown for V2/MR100
|
||||
packet[10]=0x00; //normal mode for Q100/Q200, unknown for V2/MR100
|
||||
if((sub_protocol==Q100 || sub_protocol==Q200) && CH13_SW)
|
||||
{//Calibrate
|
||||
packet[9]=0x77; //enter calibration
|
||||
if(calib_counter>=20 && calib_counter<=25) // 7 packets for Q100 / 3 packets for Q200
|
||||
packet[10]=0x20; //launch calibration
|
||||
calib_counter++;
|
||||
if(calib_counter>250) calib_counter=250;
|
||||
}
|
||||
else
|
||||
calib_counter=0;
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_send_bind_packet()
|
||||
{
|
||||
SLT_wait_radio();
|
||||
NRF250K_Hopping(SLT_NFREQCHANNELS); //Bind channel
|
||||
BIND_IN_PROGRESS; //Limit TX power to bind level
|
||||
NRF250K_SetPower();
|
||||
BIND_DONE;
|
||||
NRF250K_SetTXAddr((uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
|
||||
memcpy((void*)packet,(void*)rx_tx_addr,SLT_TXID_SIZE);
|
||||
if(phase==SLT_BIND2)
|
||||
SLT_send_packet(SLT_TXID_SIZE);
|
||||
else // SLT_BIND1
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V2);
|
||||
}
|
||||
|
||||
#define SLT_TIMING_BUILD 1000
|
||||
#define SLT_V1_TIMING_PACKET 1000
|
||||
#define SLT_V2_TIMING_PACKET 2042
|
||||
#define SLT_V1_TIMING_BIND2 1000
|
||||
#define SLT_V2_TIMING_BIND1 6507
|
||||
#define SLT_V2_TIMING_BIND2 2112
|
||||
uint16_t SLT_callback()
|
||||
{
|
||||
switch (phase)
|
||||
{
|
||||
case SLT_BUILD:
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(sub_protocol==SLT_V1?20000:13730);
|
||||
#endif
|
||||
SLT_build_packet();
|
||||
NRF250K_SetPower(); //Change power level
|
||||
NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE);
|
||||
phase++;
|
||||
return SLT_TIMING_BUILD;
|
||||
case SLT_DATA1:
|
||||
case SLT_DATA2:
|
||||
phase++;
|
||||
if(sub_protocol==SLT_V1)
|
||||
{
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V1);
|
||||
return SLT_V1_TIMING_PACKET;
|
||||
}
|
||||
else //V2
|
||||
{
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V2);
|
||||
return SLT_V2_TIMING_PACKET;
|
||||
}
|
||||
case SLT_DATA3:
|
||||
if(sub_protocol==SLT_V1)
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V1);
|
||||
else //V2
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V2);
|
||||
if (++packet_count >= 100)
|
||||
{// Send bind packet
|
||||
packet_count = 0;
|
||||
if(sub_protocol==SLT_V1)
|
||||
{
|
||||
phase=SLT_BIND2;
|
||||
return SLT_V1_TIMING_BIND2;
|
||||
}
|
||||
else //V2
|
||||
{
|
||||
phase=SLT_BIND1;
|
||||
return SLT_V2_TIMING_BIND1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{// Continue to send normal packets
|
||||
phase = SLT_BUILD;
|
||||
if(sub_protocol==SLT_V1)
|
||||
return 20000-SLT_TIMING_BUILD;
|
||||
else //V2
|
||||
return 13730-SLT_TIMING_BUILD;
|
||||
}
|
||||
case SLT_BIND1:
|
||||
SLT_send_bind_packet();
|
||||
phase++;
|
||||
return SLT_V2_TIMING_BIND2;
|
||||
case SLT_BIND2:
|
||||
SLT_send_bind_packet();
|
||||
phase = SLT_BUILD;
|
||||
if(sub_protocol==SLT_V1)
|
||||
return 20000-SLT_TIMING_BUILD-SLT_V1_TIMING_BIND2;
|
||||
else //V2
|
||||
return 13730-SLT_TIMING_BUILD-SLT_V2_TIMING_BIND1-SLT_V2_TIMING_BIND2;
|
||||
}
|
||||
return 19000;
|
||||
}
|
||||
|
||||
uint16_t initSLT()
|
||||
{
|
||||
packet_count = 0;
|
||||
packet_sent = 0;
|
||||
hopping_frequency_no = 0;
|
||||
if(sub_protocol==Q200)
|
||||
{ //Q200: Force high part of the ID otherwise it won't bind
|
||||
rx_tx_addr[0]=0x01;
|
||||
rx_tx_addr[1]=0x02;
|
||||
#ifdef SLT_Q200_FORCE_ID // ID taken from TX dumps
|
||||
rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x6A;rx_tx_addr[3]=0x31;
|
||||
/* rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x0B;rx_tx_addr[3]=0x57;*/
|
||||
#endif
|
||||
}
|
||||
SLT_init();
|
||||
SLT_set_freq();
|
||||
phase = SLT_BUILD;
|
||||
return 50000;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
This project is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Multiprotocol is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Multiprotocol. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Last sync with deviation main github branch
|
||||
|
||||
#if defined(SLT_CCNRF_INO)
|
||||
|
||||
#include "iface_nrf250k.h"
|
||||
|
||||
//#define SLT_Q200_FORCE_ID
|
||||
|
||||
// For code readability
|
||||
#define SLT_PAYLOADSIZE_V1 7
|
||||
#define SLT_PAYLOADSIZE_V2 11
|
||||
#define SLT_NFREQCHANNELS 15
|
||||
#define SLT_TXID_SIZE 4
|
||||
#define SLT_BIND_CHANNEL 0x50
|
||||
|
||||
enum{
|
||||
// flags going to packet[6] (Q200)
|
||||
FLAG_Q200_FMODE = 0x20,
|
||||
FLAG_Q200_VIDON = 0x10,
|
||||
FLAG_Q200_FLIP = 0x08,
|
||||
FLAG_Q200_VIDOFF= 0x04,
|
||||
};
|
||||
|
||||
enum{
|
||||
// flags going to packet[6] (MR100 & Q100)
|
||||
FLAG_MR100_FMODE = 0x20,
|
||||
FLAG_MR100_FLIP = 0x04,
|
||||
FLAG_MR100_VIDEO = 0x02,
|
||||
FLAG_MR100_PICTURE = 0x01,
|
||||
};
|
||||
|
||||
enum {
|
||||
SLT_BUILD=0,
|
||||
SLT_DATA1,
|
||||
SLT_DATA2,
|
||||
SLT_DATA3,
|
||||
SLT_BIND1,
|
||||
SLT_BIND2,
|
||||
};
|
||||
|
||||
static void __attribute__((unused)) SLT_RF_init()
|
||||
{
|
||||
NRF250K_Init();
|
||||
NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_set_freq(void)
|
||||
{
|
||||
// Frequency hopping sequence generation
|
||||
for (uint8_t i = 0; i < SLT_TXID_SIZE; ++i)
|
||||
{
|
||||
uint8_t next_i = (i+1) % SLT_TXID_SIZE; // is & 3 better than % 4 ?
|
||||
uint8_t base = i < 2 ? 0x03 : 0x10;
|
||||
hopping_frequency[i*4 + 0] = (rx_tx_addr[i] & 0x3f) + base;
|
||||
hopping_frequency[i*4 + 1] = (rx_tx_addr[i] >> 2) + base;
|
||||
hopping_frequency[i*4 + 2] = (rx_tx_addr[i] >> 4) + (rx_tx_addr[next_i] & 0x03)*0x10 + base;
|
||||
hopping_frequency[i*4 + 3] = (rx_tx_addr[i] >> 6) + (rx_tx_addr[next_i] & 0x0f)*0x04 + base;
|
||||
}
|
||||
|
||||
// Unique freq
|
||||
uint8_t max_freq=0x50; //V1 and V2
|
||||
if(sub_protocol==Q200)
|
||||
max_freq=45;
|
||||
for (uint8_t i = 0; i < SLT_NFREQCHANNELS; ++i)
|
||||
{
|
||||
if(sub_protocol==Q200 && hopping_frequency[i] >= max_freq)
|
||||
hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03;
|
||||
uint8_t done = 0;
|
||||
while (!done)
|
||||
{
|
||||
done = 1;
|
||||
for (uint8_t j = 0; j < i; ++j)
|
||||
if (hopping_frequency[i] == hopping_frequency[j])
|
||||
{
|
||||
done = 0;
|
||||
hopping_frequency[i] += 7;
|
||||
if (hopping_frequency[i] >= max_freq)
|
||||
hopping_frequency[i] = hopping_frequency[i] - max_freq + 0x03;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Bind channel
|
||||
hopping_frequency[SLT_NFREQCHANNELS]=SLT_BIND_CHANNEL;
|
||||
|
||||
//Calib all channels
|
||||
NRF250K_HoppingCalib(SLT_NFREQCHANNELS+1);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_wait_radio()
|
||||
{
|
||||
if (packet_sent)
|
||||
while (!NRF250K_IsPacketSent());
|
||||
packet_sent = 0;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_send_packet(uint8_t len)
|
||||
{
|
||||
SLT_wait_radio();
|
||||
NRF250K_WritePayload(packet, len);
|
||||
packet_sent = 1;
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_build_packet()
|
||||
{
|
||||
static uint8_t calib_counter=0;
|
||||
|
||||
// Set radio channel - once per packet batch
|
||||
NRF250K_SetFreqOffset(); // Set frequency offset
|
||||
NRF250K_Hopping(hopping_frequency_no);
|
||||
if (++hopping_frequency_no >= SLT_NFREQCHANNELS)
|
||||
hopping_frequency_no = 0;
|
||||
|
||||
// aileron, elevator, throttle, rudder, gear, pitch
|
||||
uint8_t e = 0; // byte where extension 2 bits for every 10-bit channel are packed
|
||||
for (uint8_t i = 0; i < 4; ++i)
|
||||
{
|
||||
uint16_t v = convert_channel_10b(CH_AETR[i], false);
|
||||
if(sub_protocol>SLT_V2 && (i==CH2 || i==CH3) )
|
||||
v=1023-v; // reverse throttle and elevator channels for Q100/Q200/MR100 protocols
|
||||
packet[i] = v;
|
||||
e = (e >> 2) | (uint8_t) ((v >> 2) & 0xC0);
|
||||
}
|
||||
// Extra bits for AETR
|
||||
packet[4] = e;
|
||||
// 8-bit channels
|
||||
packet[5] = convert_channel_8b(CH5);
|
||||
packet[6] = convert_channel_8b(CH6);
|
||||
if(sub_protocol!=SLT_V1)
|
||||
{
|
||||
if(sub_protocol==Q200)
|
||||
packet[6] = GET_FLAG(CH9_SW , FLAG_Q200_FMODE)
|
||||
|GET_FLAG(CH10_SW, FLAG_Q200_FLIP)
|
||||
|GET_FLAG(CH11_SW, FLAG_Q200_VIDON)
|
||||
|GET_FLAG(CH12_SW, FLAG_Q200_VIDOFF);
|
||||
else if(sub_protocol==MR100 || sub_protocol==Q100)
|
||||
packet[6] = GET_FLAG(CH9_SW , FLAG_MR100_FMODE)
|
||||
|GET_FLAG(CH10_SW, FLAG_MR100_FLIP)
|
||||
|GET_FLAG(CH11_SW, FLAG_MR100_VIDEO) // Does not exist on the Q100 but...
|
||||
|GET_FLAG(CH12_SW, FLAG_MR100_PICTURE); // Does not exist on the Q100 but...
|
||||
packet[7]=convert_channel_8b(CH7);
|
||||
packet[8]=convert_channel_8b(CH8);
|
||||
packet[9]=0xAA; //normal mode for Q100/Q200, unknown for V2/MR100
|
||||
packet[10]=0x00; //normal mode for Q100/Q200, unknown for V2/MR100
|
||||
if((sub_protocol==Q100 || sub_protocol==Q200) && CH13_SW)
|
||||
{//Calibrate
|
||||
packet[9]=0x77; //enter calibration
|
||||
if(calib_counter>=20 && calib_counter<=25) // 7 packets for Q100 / 3 packets for Q200
|
||||
packet[10]=0x20; //launch calibration
|
||||
calib_counter++;
|
||||
if(calib_counter>250) calib_counter=250;
|
||||
}
|
||||
else
|
||||
calib_counter=0;
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) SLT_send_bind_packet()
|
||||
{
|
||||
SLT_wait_radio();
|
||||
NRF250K_Hopping(SLT_NFREQCHANNELS); //Bind channel
|
||||
BIND_IN_PROGRESS; //Limit TX power to bind level
|
||||
NRF250K_SetPower();
|
||||
BIND_DONE;
|
||||
NRF250K_SetTXAddr((uint8_t *)"\x7E\xB8\x63\xA9", SLT_TXID_SIZE);
|
||||
memcpy((void*)packet,(void*)rx_tx_addr,SLT_TXID_SIZE);
|
||||
if(phase==SLT_BIND2)
|
||||
SLT_send_packet(SLT_TXID_SIZE);
|
||||
else // SLT_BIND1
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V2);
|
||||
}
|
||||
|
||||
#define SLT_TIMING_BUILD 1000
|
||||
#define SLT_V1_TIMING_PACKET 1000
|
||||
#define SLT_V2_TIMING_PACKET 2042
|
||||
#define SLT_V1_TIMING_BIND2 1000
|
||||
#define SLT_V2_TIMING_BIND1 6507
|
||||
#define SLT_V2_TIMING_BIND2 2112
|
||||
uint16_t SLT_callback()
|
||||
{
|
||||
switch (phase)
|
||||
{
|
||||
case SLT_BUILD:
|
||||
#ifdef MULTI_SYNC
|
||||
telemetry_set_input_sync(sub_protocol==SLT_V1?20000:13730);
|
||||
#endif
|
||||
SLT_build_packet();
|
||||
NRF250K_SetPower(); //Change power level
|
||||
NRF250K_SetTXAddr(rx_tx_addr, SLT_TXID_SIZE);
|
||||
phase++;
|
||||
return SLT_TIMING_BUILD;
|
||||
case SLT_DATA1:
|
||||
case SLT_DATA2:
|
||||
phase++;
|
||||
if(sub_protocol==SLT_V1)
|
||||
{
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V1);
|
||||
return SLT_V1_TIMING_PACKET;
|
||||
}
|
||||
else //V2
|
||||
{
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V2);
|
||||
return SLT_V2_TIMING_PACKET;
|
||||
}
|
||||
case SLT_DATA3:
|
||||
if(sub_protocol==SLT_V1)
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V1);
|
||||
else //V2
|
||||
SLT_send_packet(SLT_PAYLOADSIZE_V2);
|
||||
if (++packet_count >= 100)
|
||||
{// Send bind packet
|
||||
packet_count = 0;
|
||||
if(sub_protocol==SLT_V1)
|
||||
{
|
||||
phase=SLT_BIND2;
|
||||
return SLT_V1_TIMING_BIND2;
|
||||
}
|
||||
else //V2
|
||||
{
|
||||
phase=SLT_BIND1;
|
||||
return SLT_V2_TIMING_BIND1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{// Continue to send normal packets
|
||||
phase = SLT_BUILD;
|
||||
if(sub_protocol==SLT_V1)
|
||||
return 20000-SLT_TIMING_BUILD;
|
||||
else //V2
|
||||
return 13730-SLT_TIMING_BUILD;
|
||||
}
|
||||
case SLT_BIND1:
|
||||
SLT_send_bind_packet();
|
||||
phase++;
|
||||
return SLT_V2_TIMING_BIND2;
|
||||
case SLT_BIND2:
|
||||
SLT_send_bind_packet();
|
||||
phase = SLT_BUILD;
|
||||
if(sub_protocol==SLT_V1)
|
||||
return 20000-SLT_TIMING_BUILD-SLT_V1_TIMING_BIND2;
|
||||
else //V2
|
||||
return 13730-SLT_TIMING_BUILD-SLT_V2_TIMING_BIND1-SLT_V2_TIMING_BIND2;
|
||||
}
|
||||
return 19000;
|
||||
}
|
||||
|
||||
void SLT_init()
|
||||
{
|
||||
BIND_DONE; // Not a TX bind protocol
|
||||
packet_count = 0;
|
||||
packet_sent = 0;
|
||||
hopping_frequency_no = 0;
|
||||
if(sub_protocol==Q200)
|
||||
{ //Q200: Force high part of the ID otherwise it won't bind
|
||||
rx_tx_addr[0]=0x01;
|
||||
rx_tx_addr[1]=0x02;
|
||||
#ifdef SLT_Q200_FORCE_ID // ID taken from TX dumps
|
||||
rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x6A;rx_tx_addr[3]=0x31;
|
||||
/* rx_tx_addr[0]=0x01;rx_tx_addr[1]=0x02;rx_tx_addr[2]=0x0B;rx_tx_addr[3]=0x57;*/
|
||||
#endif
|
||||
}
|
||||
SLT_RF_init();
|
||||
SLT_set_freq();
|
||||
phase = SLT_BUILD;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifdef SX1276_INSTALLED
|
||||
#include "iface_sx1276.h"
|
||||
|
||||
bool SX1276_Mode_LoRa=false;
|
||||
|
||||
void SX1276_WriteReg(uint8_t address, uint8_t data)
|
||||
{
|
||||
SPI_CSN_off;
|
||||
@@ -14,9 +16,8 @@ uint8_t SX1276_ReadReg(uint8_t address)
|
||||
{
|
||||
SPI_CSN_off;
|
||||
SPI_Write(address & 0x7F);
|
||||
uint8_t result = SPI_Read();
|
||||
uint8_t result = SPI_Read();
|
||||
SPI_CSN_on;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -31,20 +32,78 @@ void SX1276_WriteRegisterMulti(uint8_t address, const uint8_t* data, uint8_t len
|
||||
SPI_CSN_on;
|
||||
}
|
||||
|
||||
void SX1276_ReadRegisterMulti(uint8_t address, uint8_t* data, uint8_t length)
|
||||
{
|
||||
SPI_CSN_off;
|
||||
SPI_Write(address & 0x7F);
|
||||
|
||||
for(uint8_t i = 0; i < length; i++)
|
||||
data[i]=SPI_Read();
|
||||
|
||||
SPI_CSN_on;
|
||||
}
|
||||
|
||||
uint8_t SX1276_Reset()
|
||||
{
|
||||
//TODO
|
||||
|
||||
//TODO when pin is not wired
|
||||
#ifdef SX1276_RST_pin
|
||||
SX1276_RST_off;
|
||||
delayMicroseconds(200);
|
||||
SX1276_RST_on;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SX1276_DetectChip() //to be called after reset, verfies the chip has been detected
|
||||
{
|
||||
#define SX1276_Detect_MaxAttempts 5
|
||||
uint8_t i = 0;
|
||||
bool chipFound = false;
|
||||
while ((i < SX1276_Detect_MaxAttempts) && !chipFound)
|
||||
{
|
||||
uint8_t ChipVersion = SX1276_ReadReg(SX1276_42_VERSION);
|
||||
if (ChipVersion == 0x12)
|
||||
{
|
||||
debugln("SX1276 reg version=%d", ChipVersion);
|
||||
chipFound = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("SX1276 not found! attempts: %d", i);
|
||||
debug(" of ");
|
||||
debugln("%d SX1276 reg version=%d", SX1276_Detect_MaxAttempts, ChipVersion);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (!chipFound)
|
||||
{
|
||||
debugln("SX1276 not detected!!!");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
debugln("Found SX1276 Device!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void SX1276_SetTxRxMode(uint8_t mode)
|
||||
{
|
||||
#ifdef SX1276_TXEN_pin
|
||||
if(mode == TX_EN)
|
||||
SX1276_TXEN_on;
|
||||
else
|
||||
SX1276_RXEN_on;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SX1276_SetFrequency(uint32_t frequency)
|
||||
{
|
||||
uint32_t f = frequency / 61;
|
||||
uint8_t data[3];
|
||||
data[0] = (f & (0xFF << 16)) >> 16;
|
||||
data[1] = (f & (0xFF << 8)) >> 8;
|
||||
data[2] = f & 0xFF;
|
||||
data[0] = f >> 16;
|
||||
data[1] = f >> 8;
|
||||
data[2] = f;
|
||||
|
||||
SX1276_WriteRegisterMulti(SX1276_06_FRFMSB, data, 3);
|
||||
}
|
||||
@@ -53,6 +112,8 @@ void SX1276_SetMode(bool lora, bool low_freq_mode, uint8_t mode)
|
||||
{
|
||||
uint8_t data = 0x00;
|
||||
|
||||
SX1276_Mode_LoRa=lora;
|
||||
|
||||
if(lora)
|
||||
{
|
||||
data = data | (1 << 7);
|
||||
@@ -89,6 +150,14 @@ void SX1276_ConfigModem1(uint8_t bandwidth, uint8_t coding_rate, bool implicit_h
|
||||
data = data | implicit_header_mode;
|
||||
|
||||
SX1276_WriteReg(SX1276_1D_MODEMCONFIG1, data);
|
||||
|
||||
if (bandwidth == SX1276_MODEM_CONFIG1_BW_500KHZ) //datasheet errata reconmendation http://caxapa.ru/thumbs/972894/SX1276_77_8_ErrataNote_1.1_STD.pdf
|
||||
{
|
||||
SX1276_WriteReg(SX1276_36_LORA_REGHIGHBWOPTIMIZE1, 0x02);
|
||||
SX1276_WriteReg(SX1276_3A_LORA_REGHIGHBWOPTIMIZE2, 0x64);
|
||||
}
|
||||
else
|
||||
SX1276_WriteReg(SX1276_36_LORA_REGHIGHBWOPTIMIZE1, 0x03);
|
||||
}
|
||||
|
||||
void SX1276_ConfigModem2(uint8_t spreading_factor, bool tx_continuous_mode, bool rx_payload_crc_on)
|
||||
@@ -161,11 +230,16 @@ void SX1276_SetPaConfig(bool pa_boost_pin, uint8_t max_power, uint8_t output_pow
|
||||
uint8_t data = 0x00;
|
||||
data = data | (pa_boost_pin << 7);
|
||||
data = data | (max_power << 4);
|
||||
data = data | output_power;
|
||||
data = data | (output_power & 0x0F);
|
||||
|
||||
SX1276_WriteReg(SX1276_09_PACONFIG, data);
|
||||
}
|
||||
|
||||
void SX1276_SetOcp(bool OcpOn, uint8_t OcpTrim)
|
||||
{
|
||||
SX1276_WriteReg(SX1276_0B_OCP, (OcpOn << 5) | OcpTrim);
|
||||
}
|
||||
|
||||
void SX1276_WritePayloadToFifo(uint8_t* payload, uint8_t length)
|
||||
{
|
||||
SX1276_WriteReg(SX1276_22_PAYLOAD_LENGTH, length);
|
||||
|
||||
@@ -93,7 +93,7 @@ static int __attribute__((unused)) Scanner_scan_rssi()
|
||||
return rssi_rel;
|
||||
}
|
||||
|
||||
uint16_t Scanner_callback()
|
||||
uint16_t SCANNER_callback()
|
||||
{
|
||||
uint8_t rssi,max_rssi;
|
||||
|
||||
@@ -131,7 +131,7 @@ uint16_t Scanner_callback()
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t initScanner(void)
|
||||
void SCANNER_init(void)
|
||||
{
|
||||
rf_ch_num = 0;
|
||||
telemetry_link = 0;
|
||||
@@ -141,7 +141,6 @@ uint16_t initScanner(void)
|
||||
CC2500_Strobe(CC2500_SIDLE);
|
||||
CC2500_SetTxRxMode(RX_EN);
|
||||
CC2500_Strobe(CC2500_SRX); // Receive mode
|
||||
return 1250;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
//#define SKYARTEC_FORCE_ID
|
||||
|
||||
#define SKYARTEC_BIND_CHANNEL 0x7D
|
||||
#define SKYARTEC_COARSE 0x00
|
||||
#define SKYARTEC_TX_ADDR rx_tx_addr[1]
|
||||
#define SKYARTEC_TX_CHANNEL rx_tx_addr[0]
|
||||
@@ -41,7 +40,7 @@ enum {
|
||||
|
||||
const PROGMEM uint8_t SKYARTEC_init_values[] = {
|
||||
/* 04 */ 0x13, 0x18, 0xFF, 0x05,
|
||||
/* 08 */ 0x05, 0x43, SKYARTEC_BIND_CHANNEL, 0x09, 0x00, 0x5D, 0x93, 0xB1 + SKYARTEC_COARSE,
|
||||
/* 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,
|
||||
@@ -55,11 +54,14 @@ static void __attribute__((unused)) SKYARTEC_rf_init()
|
||||
for (uint8_t i = 4; i <= 0x2E; ++i)
|
||||
CC2500_WriteReg(i, pgm_read_byte_near(&SKYARTEC_init_values[i-4]));
|
||||
|
||||
prev_option = option;
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
|
||||
CC2500_SetTxRxMode(TX_EN);
|
||||
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()
|
||||
@@ -78,13 +80,12 @@ static void __attribute__((unused)) SKYARTEC_send_data_packet()
|
||||
}
|
||||
//checks
|
||||
uint8_t xor1 = 0;
|
||||
for(uint8_t i = 3; i <= 16; i++)
|
||||
xor1 ^= packet[i];
|
||||
packet[17] = xor1;
|
||||
uint8_t xor2 = 0;
|
||||
for(uint8_t i = 3; i <= 14; i++)
|
||||
xor2 ^= packet[i];
|
||||
packet[18] = xor2;
|
||||
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]);
|
||||
@@ -101,7 +102,10 @@ static void __attribute__((unused)) SKYARTEC_send_bind_packet()
|
||||
packet[1] = 0x7d;
|
||||
packet[2] = 0x01;
|
||||
packet[3] = 0x01;
|
||||
memcpy(&packet[4], rx_tx_addr, 4);
|
||||
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;
|
||||
@@ -112,11 +116,11 @@ static void __attribute__((unused)) SKYARTEC_send_bind_packet()
|
||||
CC2500_WriteReg(CC2500_04_SYNC1, 0x7d);
|
||||
CC2500_WriteReg(CC2500_05_SYNC0, 0x7d);
|
||||
CC2500_WriteReg(CC2500_09_ADDR, 0x7d);
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, SKYARTEC_BIND_CHANNEL);
|
||||
CC2500_WriteReg(CC2500_0A_CHANNR, 0x7d);
|
||||
CC2500_WriteData(packet, 12);
|
||||
}
|
||||
|
||||
uint16_t ReadSKYARTEC()
|
||||
uint16_t SKYARTEC_callback()
|
||||
{
|
||||
if (phase & 0x01)
|
||||
{
|
||||
@@ -125,11 +129,7 @@ uint16_t ReadSKYARTEC()
|
||||
{
|
||||
CC2500_SetPower();
|
||||
// Tune frequency if it has been changed
|
||||
if ( prev_option != option )
|
||||
{
|
||||
CC2500_WriteReg(CC2500_0C_FSCTRL0, option);
|
||||
prev_option = option ;
|
||||
}
|
||||
CC2500_SetFreqOffset();
|
||||
phase = SKYARTEC_PKT1;
|
||||
}
|
||||
else
|
||||
@@ -154,11 +154,11 @@ uint16_t ReadSKYARTEC()
|
||||
return 3000;
|
||||
}
|
||||
|
||||
uint16_t initSKYARTEC()
|
||||
void SKYARTEC_init()
|
||||
{
|
||||
SKYARTEC_rf_init();
|
||||
|
||||
#ifdef SKYARTEC_FORCEID
|
||||
#ifdef SKYARTEC_FORCE_ID
|
||||
memset(rx_tx_addr,0x00,4);
|
||||
#endif
|
||||
if(rx_tx_addr[0]==0) rx_tx_addr[0]=0xB2;
|
||||
@@ -168,7 +168,6 @@ uint16_t initSKYARTEC()
|
||||
|
||||
bind_counter = 250;
|
||||
phase = SKYARTEC_PKT1;
|
||||
return 10000;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -189,23 +189,17 @@ static void __attribute__((unused)) SYMAX_send_packet(uint8_t bind)
|
||||
NRF24L01_SetPower(); // Set tx_power
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) symax_init()
|
||||
static void __attribute__((unused)) symax_rf_init()
|
||||
{
|
||||
NRF24L01_Initialize();
|
||||
//
|
||||
NRF24L01_SetTxRxMode(TX_EN);
|
||||
//
|
||||
NRF24L01_ReadReg(NRF24L01_07_STATUS);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, _BV(NRF24L01_00_EN_CRC) | _BV(NRF24L01_00_CRCO));
|
||||
NRF24L01_WriteReg(NRF24L01_01_EN_AA, 0x00); // No Auto Acknoledgement
|
||||
NRF24L01_WriteReg(NRF24L01_02_EN_RXADDR, 0x3F); // Enable all data pipes (even though not used?)
|
||||
NRF24L01_WriteReg(NRF24L01_03_SETUP_AW, 0x03); // 5-byte RX/TX address
|
||||
NRF24L01_WriteReg(NRF24L01_04_SETUP_RETR, 0xff); // 4mS retransmit t/o, 15 tries (retries w/o AA?)
|
||||
NRF24L01_WriteReg(NRF24L01_05_RF_CH, 0x08);
|
||||
|
||||
if (sub_protocol==SYMAX5C)
|
||||
{
|
||||
NRF24L01_SetBitrate(NRF24L01_BR_1M);
|
||||
//NRF24L01_SetBitrate(NRF24L01_BR_1M);
|
||||
packet_length = 16;
|
||||
}
|
||||
else
|
||||
@@ -214,8 +208,6 @@ static void __attribute__((unused)) symax_init()
|
||||
packet_length = 10;
|
||||
}
|
||||
//
|
||||
NRF24L01_SetPower();
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x70); // Clear data ready, data sent, and retransmit
|
||||
NRF24L01_WriteReg(NRF24L01_08_OBSERVE_TX, 0x00);
|
||||
NRF24L01_WriteReg(NRF24L01_09_CD, 0x00);
|
||||
NRF24L01_WriteReg(NRF24L01_0C_RX_ADDR_P2, 0xC3); // LSB byte of pipe 2 receive address
|
||||
@@ -231,14 +223,6 @@ static void __attribute__((unused)) symax_init()
|
||||
NRF24L01_WriteReg(NRF24L01_17_FIFO_STATUS, 0x00); // Just in case, no real bits to write here
|
||||
|
||||
NRF24L01_WriteRegisterMulti(NRF24L01_10_TX_ADDR , sub_protocol==SYMAX5C ? (uint8_t *)"\x6D\x6A\x73\x73\x73" : (uint8_t *)"\xAB\xAC\xAD\xAE\xAF" ,5);
|
||||
|
||||
NRF24L01_ReadReg(NRF24L01_07_STATUS);
|
||||
NRF24L01_FlushTx();
|
||||
NRF24L01_ReadReg(NRF24L01_07_STATUS);
|
||||
NRF24L01_WriteReg(NRF24L01_07_STATUS, 0x0e);
|
||||
NRF24L01_ReadReg(NRF24L01_00_CONFIG);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0c);
|
||||
NRF24L01_WriteReg(NRF24L01_00_CONFIG, 0x0e); // power on
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) symax_init1()
|
||||
@@ -331,7 +315,7 @@ static uint8_t chans_data_x5c[] = {0x1d, 0x2f, 0x26, 0x3d, 0x15, 0x2b, 0x25, 0x2
|
||||
packet_count = 0;
|
||||
}
|
||||
|
||||
uint16_t symax_callback()
|
||||
uint16_t SYMAX_callback()
|
||||
{
|
||||
switch (phase)
|
||||
{
|
||||
@@ -368,14 +352,13 @@ uint16_t symax_callback()
|
||||
return SYMAX_PACKET_PERIOD;
|
||||
}
|
||||
|
||||
uint16_t initSymax()
|
||||
void SYMAX_init()
|
||||
{
|
||||
packet_count = 0;
|
||||
flags = 0;
|
||||
BIND_IN_PROGRESS; // autobind protocol
|
||||
symax_init();
|
||||
symax_rf_init();
|
||||
phase = SYMAX_INIT1;
|
||||
return SYMAX_INITIAL_WAIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
62
Multiprotocol/TEST_cc2500.ino
Normal file
62
Multiprotocol/TEST_cc2500.ino
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
void TEST_init()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user