Added NRF24l01 third party library
This commit is contained in:
parent
7a8577d90a
commit
807e55fa1d
21
src/libs/RF24-master/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
21
src/libs/RF24-master/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Having issues with ACK not working correctly? Please see [common issues](https://github.com/nRF24/RF24/blob/master/COMMON_ISSUES.md).
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
Please include:
|
||||
1. Code to reproduce
|
||||
2. Expected behaviour
|
||||
3. What device(es) are you using? Please specify make and model.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
20
src/libs/RF24-master/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
src/libs/RF24-master/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
10
src/libs/RF24-master/.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
10
src/libs/RF24-master/.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
name: Question
|
||||
about: Have a question?
|
||||
title: "[Question]"
|
||||
labels: question
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
157
src/libs/RF24-master/.github/workflows/build_arduino.yml
vendored
Normal file
157
src/libs/RF24-master/.github/workflows/build_arduino.yml
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
name: Arduino CLI build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- ".github/workflows/build_arduino.yml"
|
||||
- "examples/**"
|
||||
- "!examples/old_backups/recipes/pingpair_maple/**"
|
||||
|
||||
push:
|
||||
paths:
|
||||
- ".github/workflows/build_arduino.yml"
|
||||
- "examples/**"
|
||||
- "!examples/old_backups/recipes/pingpair_maple/**"
|
||||
|
||||
jobs:
|
||||
check_formatting:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Check code formatting
|
||||
uses: per1234/artistic-style-action@main
|
||||
with:
|
||||
options-file-path: ./examples/examples_formatter.conf
|
||||
name-patterns: |
|
||||
- '*.ino'
|
||||
- '*.cpp'
|
||||
- '*.hpp'
|
||||
- '*.h'
|
||||
target-paths: |
|
||||
- examples
|
||||
build:
|
||||
needs: check_formatting
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
matrix:
|
||||
fqbn:
|
||||
- "arduino:avr:yun"
|
||||
- "arduino:avr:uno"
|
||||
- "arduino:avr:diecimila"
|
||||
- "arduino:avr:nano"
|
||||
- "arduino:avr:mega"
|
||||
- "arduino:avr:megaADK"
|
||||
- "arduino:avr:leonardo"
|
||||
- "arduino:avr:micro"
|
||||
- "arduino:avr:esplora"
|
||||
- "arduino:avr:mini"
|
||||
- "arduino:avr:ethernet"
|
||||
- "arduino:avr:fio"
|
||||
- "arduino:avr:bt"
|
||||
# - "arduino:avr:LilyPad" # board not found
|
||||
- "arduino:avr:LilyPadUSB"
|
||||
- "arduino:avr:pro"
|
||||
- "arduino:avr:atmegang"
|
||||
- "arduino:avr:robotControl"
|
||||
- "arduino:avr:robotMotor"
|
||||
# - "arduino:avr:gemma" # does not support SPI
|
||||
- "arduino:avr:circuitplay32u4cat"
|
||||
- "arduino:avr:yunmini"
|
||||
- "arduino:avr:chiwawa"
|
||||
- "arduino:avr:one"
|
||||
- "arduino:avr:unowifi"
|
||||
- "arduino:mbed:nano33ble"
|
||||
# - "arduino:samd:mkr1000" # InterruptConfigure.ino uses pin 2
|
||||
# - "arduino:samd:mkrzero" # InterruptConfigure.ino uses pin 2
|
||||
# - "arduino:samd:mkrwifi1010" # InterruptConfigure.ino uses pin 2
|
||||
- "arduino:samd:nano_33_iot"
|
||||
# - "arduino:samd:mkrfox1200" # InterruptConfigure.ino uses pin 2
|
||||
# - "arduino:samd:mkrwan1300" # InterruptConfigure.ino uses pin 2
|
||||
# - "arduino:samd:mkrwan1310" # InterruptConfigure.ino uses pin 2
|
||||
# - "arduino:samd:mkrgsm1400" # InterruptConfigure.ino uses pin 2
|
||||
# - "arduino:samd:mkrnb1500" # InterruptConfigure.ino uses pin 2
|
||||
# - "arduino:samd:mkrvidor4000" # InterruptConfigure.ino uses pin 2
|
||||
- "arduino:samd:adafruit_circuitplayground_m0"
|
||||
- "arduino:samd:mzero_pro_bl"
|
||||
- "arduino:samd:mzero_bl"
|
||||
- "arduino:samd:tian"
|
||||
- "arduino:megaavr:uno2018"
|
||||
# - "arduino:megaavr:nano4809" # board not found
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Compile examples
|
||||
uses: arduino/compile-sketches@main
|
||||
with:
|
||||
sketch-paths: |
|
||||
- examples/GettingStarted
|
||||
- examples/AcknowledgementPayloads
|
||||
- examples/ManualAcknowledgements
|
||||
- examples/StreamingData
|
||||
- examples/MulticeiverDemo
|
||||
- examples/InterruptConfigure
|
||||
# - examples/old_backups/GettingStarted_HandlingFailures
|
||||
# - examples/old_backups/pingpair_dyn
|
||||
# - examples/old_backups/pingpair_irq
|
||||
# - examples/old_backups/pingpair_multi_dyn
|
||||
# - examples/old_backups/pingpair_sleepy
|
||||
# - examples/old_backups/scanner
|
||||
# - examples/old_backups/TransferTimeouts
|
||||
# - examples/old_backups/recipes/led_remote
|
||||
# - examples/old_backups/recipes/nordic_fob
|
||||
# - examples/old_backups/recipes/pingpair_maple
|
||||
fqbn: ${{ matrix.fqbn }}
|
||||
attiny:
|
||||
needs: check_formatting
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
matrix:
|
||||
fqbn:
|
||||
- ATTinyCore:avr:attinyx4
|
||||
- ATTinyCore:avr:attinyx4opti
|
||||
- ATTinyCore:avr:attinyx4micr
|
||||
- ATTinyCore:avr:attinyx5
|
||||
- ATTinyCore:avr:attinyx5micr
|
||||
- ATTinyCore:avr:attinyx8
|
||||
- ATTinyCore:avr:attinyx8opti
|
||||
- ATTinyCore:avr:attinyx8micr
|
||||
- ATTinyCore:avr:attinyx7
|
||||
- ATTinyCore:avr:attinyx7opti
|
||||
- ATTinyCore:avr:attinyx7micr
|
||||
- ATTinyCore:avr:attinyx61
|
||||
- ATTinyCore:avr:attinyx61opti
|
||||
- ATTinyCore:avr:attinyx41
|
||||
- ATTinyCore:avr:attinyx41opti
|
||||
- ATTinyCore:avr:attinyx41micr
|
||||
# - ATTinyCore:avr:attiny43 # doesn't seem to support USI implementation of SPI
|
||||
- ATTinyCore:avr:attiny828
|
||||
- ATTinyCore:avr:attiny828opti
|
||||
- ATTinyCore:avr:attiny1634
|
||||
- ATTinyCore:avr:attiny1634opti
|
||||
- ATTinyCore:avr:attinyx313
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Compile examples
|
||||
uses: arduino/compile-sketches@main
|
||||
with:
|
||||
platforms: |
|
||||
- source-url: "http://drazzy.com/package_drazzy.com_index.json"
|
||||
name: "ATTinyCore:avr"
|
||||
- name: "arduino:avr"
|
||||
sketch-paths: |
|
||||
- examples/rf24_ATTiny/rf24ping85
|
||||
- examples/rf24_ATTiny/timingSearch3pin
|
||||
fqbn: ${{ matrix.fqbn }}
|
47
src/libs/RF24-master/.github/workflows/build_linux.yml
vendored
Normal file
47
src/libs/RF24-master/.github/workflows/build_linux.yml
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
name: Linux build
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
matrix:
|
||||
config-options:
|
||||
- "--soc=BCM2835 --driver=RPi"
|
||||
- "--soc=BCM2836 --driver=RPi"
|
||||
- "--soc=BCM2835 --driver=wiringPi --extra-cflags=-I/usr/local/include"
|
||||
- "--driver=SPIDEV"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: provide toolchain
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install binutils-arm-linux-gnueabi gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
|
||||
arm-linux-gnueabihf-gcc -v
|
||||
arm-linux-gnueabihf-g++ -v
|
||||
python3 --version
|
||||
- name: provide WiringPi
|
||||
if: ${{ matrix.config-options == '--soc=BCM2835 --driver=wiringPi --extra-cflags=-I/usr/local/include' }}
|
||||
run: |
|
||||
git clone https://github.com/CoRfr/WiringPi
|
||||
cd WiringPi/wiringPi
|
||||
CC="arm-linux-gnueabihf-gcc -marm -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard" V=1 make -j5
|
||||
sudo make install
|
||||
- name: library configure
|
||||
run: ./configure ${{ matrix.config-options }}
|
||||
- name: library make
|
||||
run: make
|
||||
- name: library make install
|
||||
run: sudo make install
|
||||
- name: make linux examples
|
||||
# compiling examples for wiringPi is broken see nRF24#669 issue
|
||||
if: ${{ matrix.config-options != '--soc=BCM2835 --driver=wiringPi --extra-cflags=-I/usr/local/include' }}
|
||||
run: |
|
||||
cd examples_linux
|
||||
make
|
||||
file ./gettingstarted
|
46
src/libs/RF24-master/.github/workflows/doxygen.yml
vendored
Normal file
46
src/libs/RF24-master/.github/workflows/doxygen.yml
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
name: DoxyGen build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
release:
|
||||
branches:
|
||||
- master
|
||||
types:
|
||||
- published
|
||||
- edited
|
||||
|
||||
jobs:
|
||||
build-doxygen:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: get latest release version number
|
||||
id: latest_ver
|
||||
uses: pozetroninc/github-action-get-latest-release@master
|
||||
with:
|
||||
repository: nRF24/RF24
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: overwrite doxygen tags
|
||||
run: |
|
||||
mkdir docs
|
||||
touch doxygenAction
|
||||
echo "PROJECT_NUMBER = ${{ steps.latest_ver.outputs.release }}" >> doxygenAction
|
||||
echo "OUTPUT_DIRECTORY = ./docs" >> doxygenAction
|
||||
echo "@INCLUDE = doxygenAction" >> Doxyfile
|
||||
- name: build doxygen
|
||||
uses: mattnotmitt/doxygen-action@v1
|
||||
with:
|
||||
working-directory: '.'
|
||||
doxyfile-path: './Doxyfile'
|
||||
- name: upload to github pages
|
||||
if: ${{ github.event_name == 'release'}}
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./docs/html
|
35
src/libs/RF24-master/.gitignore
vendored
Normal file
35
src/libs/RF24-master/.gitignore
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
*.bak
|
||||
*.o
|
||||
.*.swp
|
||||
*.orig
|
||||
.swp
|
||||
docs/
|
||||
output/
|
||||
ojam/
|
||||
out/
|
||||
16000000/
|
||||
8000000/
|
||||
out_native/
|
||||
version.h
|
||||
Session.vim
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
*.dylib.*
|
||||
.DS_Store
|
||||
Makefile.inc
|
||||
utility/includes.h
|
||||
examples_linux/*
|
||||
examples_linux/**/*
|
||||
!examples_linux/*.cpp
|
||||
!examples_linux/*.py
|
||||
!examples_linux/**/*.cpp
|
||||
!examples_linux/Makefile
|
||||
!examples_linux/**/Makefile
|
||||
*__pycache__/
|
||||
.directory
|
||||
.idea
|
||||
doxygenAction
|
||||
.vscode/
|
||||
*venv
|
||||
*.pyc
|
48
src/libs/RF24-master/COMMON_ISSUES.md
Normal file
48
src/libs/RF24-master/COMMON_ISSUES.md
Normal file
@ -0,0 +1,48 @@
|
||||
# Common Issues
|
||||
|
||||
## Settings that must match
|
||||
Before you report undesirable behavior, please make sure that the
|
||||
following RF24 configurations match on both receiving and transmitting
|
||||
nRF24L01 transceivers:
|
||||
1. `RF24::setAddressWidth()`
|
||||
2. `RF24::setChannel()`
|
||||
3. `RF24::setDataRate()`
|
||||
4. `RF24::setAutoAck()`
|
||||
5. `RF24::enableDynamicPayloads()` or `RF24::disableDynamicPayloads()`
|
||||
6. `RF24::enableAckPayload()` or `RF24::disableAckPayload()` (requires auto-ack and
|
||||
dynamic payloads features)
|
||||
7. `RF24::setPayloadSize()` (only if the dynamic payloads feature is disabled -- it is disabled by default)
|
||||
8. `RF24::setCRCLength()` or `RF24::disableCRC()` (the auto-ack feature
|
||||
automatically enables CRC because it is required)
|
||||
|
||||
Also, it helps to think of an address as a path (a commonly shared route)
|
||||
instead of an identifying device destination. This means that addresses
|
||||
have to match for a payload to travel from one transceiver to another.
|
||||
However, the pipe numbers assigned with the matching address do not have
|
||||
to match. You can think of pipes as parking spots for the packets, while
|
||||
all packets' payloads live in a TX or RX FIFO buffer. Remember that the
|
||||
TX FIFO buffers and the RX FIFO buffers both have a maximum occupancy of
|
||||
3 payloads (regardless of the maximum 32-byte payload size).
|
||||
|
||||
## Here are the most common issues and their solutions.
|
||||
|
||||
### write() always returns true after setAutoAck(false)
|
||||
Don't disabled the auto-ack feature. RF24::write() has no reason to doubt
|
||||
that the payload was delivered if the auto-ack feature is disabled. We
|
||||
recommend you read the docs about RF24::setAutoAck() before disabling the
|
||||
auto-ack feature.
|
||||
|
||||
### write() returns false when the payload was received
|
||||
If the settings match on both endpoint transceivers, then this can only
|
||||
mean that the receiving nRF24L01 failed to send an acknowledgement (ACK)
|
||||
packet back to the transmitting nRF24L01. Usually this is due to
|
||||
instability (electric noise) in the power lines (VCC and GND) going to
|
||||
the receiving nRF24L01.
|
||||
|
||||
If you're not receiving ACK packets correctly/reliably on data rates
|
||||
lower than 2MBPS, try adding a big capacitor close to the module/chip.
|
||||
Example issues: [#264](https://github.com/nRF24/RF24/issues/264)
|
||||
[#211](https://github.com/nRF24/RF24/issues/211).
|
||||
|
||||
For reliability, please use Electrolytic or Tantalum capacitors. Ceramic
|
||||
capacitors may not be good enough (depending on the manufacturing source).
|
9
src/libs/RF24-master/CONTRIBUTING.md
Normal file
9
src/libs/RF24-master/CONTRIBUTING.md
Normal file
@ -0,0 +1,9 @@
|
||||
These are the current requirements for getting your code included in RF24:
|
||||
|
||||
* Try your best to follow the rest of the code, if you're unsure then the NASA C style can help as it's closest to the current style: https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19950022400.pdf
|
||||
|
||||
* Definetly follow [PEP-8](https://www.python.org/dev/peps/pep-0008/) if it's Python code.
|
||||
|
||||
* Follow the [Arduino IDE formatting style](https://www.arduino.cc/en/Reference/StyleGuide) for Arduino examples
|
||||
|
||||
* Add [doxygen-compatible documentation](https://www.doxygen.nl/manual/docblocks.html) to any new functions you add, or update existing documentation if you change behaviour
|
2586
src/libs/RF24-master/Doxyfile
Normal file
2586
src/libs/RF24-master/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
339
src/libs/RF24-master/LICENSE
Normal file
339
src/libs/RF24-master/LICENSE
Normal file
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{description}
|
||||
Copyright (C) {year} {fullname}
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
{signature of Ty Coon}, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
126
src/libs/RF24-master/Makefile
Normal file
126
src/libs/RF24-master/Makefile
Normal file
@ -0,0 +1,126 @@
|
||||
#############################################################################
|
||||
#
|
||||
# Makefile for librf24
|
||||
#
|
||||
# License: GPL (General Public License)
|
||||
# Author: Charles-Henri Hallard
|
||||
# Date: 2013/03/13
|
||||
#
|
||||
# Description:
|
||||
# ------------
|
||||
# use make all and make install to install the library
|
||||
#
|
||||
|
||||
CONFIG_FILE=Makefile.inc
|
||||
REMOTE_ERROR="[ERROR] Remote machine not configured. Run configure with respective arguments."
|
||||
|
||||
include $(CONFIG_FILE)
|
||||
|
||||
# Objects to compile
|
||||
OBJECTS=RF24.o
|
||||
ifeq ($(DRIVER), MRAA)
|
||||
OBJECTS+=spi.o gpio.o compatibility.o
|
||||
else ifeq ($(DRIVER), RPi)
|
||||
OBJECTS+=spi.o bcm2835.o interrupt.o compatibility.o
|
||||
else ifeq ($(DRIVER), SPIDEV)
|
||||
OBJECTS+=spi.o gpio.o compatibility.o interrupt.o
|
||||
else ifeq ($(DRIVER), wiringPi)
|
||||
OBJECTS+=spi.o
|
||||
endif
|
||||
|
||||
# make all
|
||||
# reinstall the library after each recompilation
|
||||
all: $(LIBNAME)
|
||||
|
||||
# Make the library
|
||||
$(LIBNAME): $(OBJECTS)
|
||||
@echo "[Linking]"
|
||||
$(CC) $(SHARED_LINKER_FLAGS) $(CFLAGS) -o $(LIBNAME) $^ $(SHARED_LINKER_LIBS)
|
||||
|
||||
# Library parts
|
||||
RF24.o: RF24.cpp
|
||||
$(CXX) -fPIC $(CFLAGS) -c $^
|
||||
|
||||
bcm2835.o: $(DRIVER_DIR)/bcm2835.c
|
||||
$(CC) -fPIC $(CFLAGS) -c $^
|
||||
|
||||
spi.o: $(DRIVER_DIR)/spi.cpp
|
||||
$(CXX) -fPIC $(CFLAGS) -c $^
|
||||
|
||||
compatibility.o: $(DRIVER_DIR)/compatibility.c
|
||||
$(CC) -fPIC $(CFLAGS) -c $(DRIVER_DIR)/compatibility.c
|
||||
|
||||
gpio.o: $(DRIVER_DIR)/gpio.cpp
|
||||
$(CXX) -fPIC $(CFLAGS) -c $(DRIVER_DIR)/gpio.cpp
|
||||
|
||||
interrupt.o: $(DRIVER_DIR)/interrupt.c
|
||||
$(CXX) -fPIC $(CFLAGS) -c $(DRIVER_DIR)/interrupt.c
|
||||
|
||||
# clear configuration files
|
||||
cleanconfig:
|
||||
@echo "[Cleaning configuration]"
|
||||
rm -rf $(CONFIG_FILE) utility/includes.h
|
||||
|
||||
# clear build files
|
||||
clean:
|
||||
@echo "[Cleaning]"
|
||||
rm -rf *.o $(LIBNAME)
|
||||
|
||||
$(CONFIG_FILE):
|
||||
@echo "[Running configure]"
|
||||
@./configure --no-clean
|
||||
|
||||
install: all install-libs install-headers
|
||||
upload: all upload-libs upload-headers
|
||||
|
||||
# Install the library to LIBPATH
|
||||
install-libs:
|
||||
@echo "[Installing Libs to $(LIB_DIR)]"
|
||||
@if ( test ! -d $(LIB_DIR) ); then mkdir -p $(LIB_DIR); fi
|
||||
@install -m 0755 $(LIBNAME) $(LIB_DIR)
|
||||
@orig=$(LIBNAME) && \
|
||||
for sl in $(LIBSYMLINKS); do \
|
||||
ln -sf $(LIB_DIR)/$${orig} $(LIB_DIR)/$${sl}; \
|
||||
orig=$${sl}; \
|
||||
done && \
|
||||
if [ "$(LIBDEPRECATE)" ]; then ln -sf $(LIB_DIR)/$${orig} $(LIB_DIR)/$(LIBDEPRECATE); fi
|
||||
ifneq ($(LDCONFIG),)
|
||||
@$(LDCONFIG)
|
||||
endif
|
||||
|
||||
upload-libs:
|
||||
@echo "[Uploading Libs to $(REMOTE):$(REMOTE_LIB_DIR)]"
|
||||
ifeq ($(REMOTE),)
|
||||
@echo "$(REMOTE_ERROR)"
|
||||
@exit 1
|
||||
endif
|
||||
@ssh -q -t -p $(REMOTE_PORT) $(REMOTE) "mkdir -p $(REMOTE_LIB_DIR)"
|
||||
@scp -q -P $(REMOTE_PORT) $(LIBNAME) $(REMOTE):/tmp
|
||||
@ssh -q -t -p $(REMOTE_PORT) $(REMOTE) "sudo install -m 0755 /tmp/$(LIBNAME) $(REMOTE_LIB_DIR) &&" \
|
||||
" orig=$(LIBNAME) && for sl in $(LIBSYMLINKS); do sudo ln -sf $(REMOTE_LIB_DIR)/\$${orig} $(REMOTE_LIB_DIR)/\$${sl}; orig=\$${sl}; done &&" \
|
||||
" if [ "$(LIBDEPRECATE)" ]; then sudo ln -sf $(REMOTE_LIB_DIR)/\$${orig} $(REMOTE_LIB_DIR)/$(LIBDEPRECATE); fi &&" \
|
||||
" rm /tmp/$(LIBNAME)"
|
||||
ifneq ($(REMOTE_LDCONFIG),)
|
||||
@ssh -q -t -p $(REMOTE_PORT) $(REMOTE) "sudo $(REMOTE_LDCONFIG)"
|
||||
endif
|
||||
|
||||
install-headers:
|
||||
@echo "[Installing Headers to $(HEADER_DIR)]"
|
||||
@mkdir -p $(HEADER_DIR)/$(DRIVER_DIR)
|
||||
@install -m 0644 *.h $(HEADER_DIR)
|
||||
@install -m 0644 $(DRIVER_DIR)/*.h $(HEADER_DIR)/$(DRIVER_DIR)
|
||||
@install -m 0644 $(ARCH_DIR)/*.h $(HEADER_DIR)/$(ARCH_DIR)
|
||||
|
||||
upload-headers:
|
||||
@echo "[Uploading Headers to $(REMOTE):$(REMOTE_HEADER_DIR)]"
|
||||
ifeq ($(REMOTE),)
|
||||
@echo "$(REMOTE_ERROR)"
|
||||
@exit 1
|
||||
endif
|
||||
@ssh -q -t -p $(REMOTE_PORT) $(REMOTE) "sudo mkdir -p $(REMOTE_HEADER_DIR)/$(DRIVER_DIR)"
|
||||
@ssh -q -t -p $(REMOTE_PORT) $(REMOTE) "mkdir -p /tmp/RF24 && rm -rf /tmp/RF24/*"
|
||||
@rsync -a --include="*.h" --include="*/" --exclude="*" -e "ssh -p $(REMOTE_PORT)" . $(REMOTE):/tmp/RF24
|
||||
@ssh -q -t -p $(REMOTE_PORT) $(REMOTE) "sudo install -m 0644 /tmp/RF24/*.h $(REMOTE_HEADER_DIR)"
|
||||
@ssh -q -t -p $(REMOTE_PORT) $(REMOTE) "sudo install -m 0644 /tmp/RF24/$(DRIVER_DIR)/*.h $(REMOTE_HEADER_DIR)/$(DRIVER_DIR)"
|
||||
@ssh -q -t -p $(REMOTE_PORT) $(REMOTE) "sudo install -m 0644 /tmp/RF24/$(ARCH_DIR)/*.h $(REMOTE_HEADER_DIR)/$(ARCH_DIR)"
|
||||
@ssh -q -t -p $(REMOTE_PORT) $(REMOTE) "rm -rf /tmp/RF24"
|
7
src/libs/RF24-master/README.md
Normal file
7
src/libs/RF24-master/README.md
Normal file
@ -0,0 +1,7 @@
|
||||

|
||||
|
||||

|
||||
|
||||
# See http://nRF24.github.io/RF24 for all documentation
|
||||
|
||||
### Check our [contributing guidelines](CONTRIBUTING.md) before opening a pull request
|
1648
src/libs/RF24-master/RF24.cpp
Normal file
1648
src/libs/RF24-master/RF24.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2751
src/libs/RF24-master/RF24.h
Normal file
2751
src/libs/RF24-master/RF24.h
Normal file
File diff suppressed because it is too large
Load Diff
196
src/libs/RF24-master/RF24_config.h
Normal file
196
src/libs/RF24-master/RF24_config.h
Normal file
@ -0,0 +1,196 @@
|
||||
|
||||
/*
|
||||
Copyright (C)
|
||||
2011 J. Coliz <maniacbug@ymail.com>
|
||||
2015-2019 TMRh20
|
||||
2015 spaniakos <spaniakos@gmail.com>
|
||||
2015 nerdralph
|
||||
2015 zador-blood-stained
|
||||
2016 akatran
|
||||
2017-2019 Avamander <avamander@gmail.com>
|
||||
2019 IkpeohaGodson
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef __RF24_CONFIG_H__
|
||||
#define __RF24_CONFIG_H__
|
||||
|
||||
/*** USER DEFINES: ***/
|
||||
#define FAILURE_HANDLING
|
||||
//#define SERIAL_DEBUG
|
||||
//#define MINIMAL
|
||||
//#define SPI_UART // Requires library from https://github.com/TMRh20/Sketches/tree/master/SPI_UART
|
||||
//#define SOFTSPI // Requires library from https://github.com/greiman/DigitalIO
|
||||
|
||||
/**
|
||||
* User access to internally used delay time (in microseconds) during RF24::powerUp()
|
||||
* @warning This default value compensates for all supported hardware. Only adjust this if you
|
||||
* know your radio's hardware is, in fact, genuine and reliable.
|
||||
*/
|
||||
#if !defined(RF24_POWERUP_DELAY)
|
||||
#define RF24_POWERUP_DELAY 5000
|
||||
#endif
|
||||
|
||||
/**********************/
|
||||
#define rf24_max(a, b) (a>b?a:b)
|
||||
#define rf24_min(a, b) (a<b?a:b)
|
||||
|
||||
#define RF24_SPI_SPEED 10000000
|
||||
|
||||
//ATXMega
|
||||
#if defined (__AVR_ATxmega64D3__) || defined (__AVR_ATxmega128D3__) || defined (__AVR_ATxmega192D3__) || defined (__AVR_ATxmega256D3__) || defined (__AVR_ATxmega384D3__) // In order to be available both in Windows and Linux this should take presence here.
|
||||
#define XMEGA
|
||||
#define XMEGA_D3
|
||||
#include "utility/ATXMegaD3/RF24_arch_config.h"
|
||||
|
||||
#elif ( !defined (ARDUINO) ) // Any non-arduino device is handled via configure/Makefile
|
||||
// The configure script detects device and copies the correct includes.h file to /utility/includes.h
|
||||
// This behavior can be overridden by calling configure with respective parameters
|
||||
// The includes.h file defines either RF24_RPi, MRAA, LITTLEWIRE or RF24_SPIDEV and includes the correct RF24_arch_config.h file
|
||||
#include "utility/includes.h"
|
||||
|
||||
//ATTiny
|
||||
#elif defined (__AVR_ATtiny25__) || defined (__AVR_ATtiny45__) || defined (__AVR_ATtiny85__) || defined (__AVR_ATtiny24__) || defined (__AVR_ATtiny44__) || defined (__AVR_ATtiny84__) || defined (__AVR_ATtiny2313__) || defined (__AVR_ATtiny4313__) || defined (__AVR_ATtiny861__) || defined (__AVR_ATtinyX5__) || defined (__AVR_ATtinyX4__) || defined (__AVR_ATtinyX313__) || defined (__AVR_ATtinyX61__)
|
||||
#define RF24_TINY
|
||||
#include "utility/ATTiny/RF24_arch_config.h"
|
||||
|
||||
#elif defined (LITTLEWIRE) //LittleWire
|
||||
#include "utility/LittleWire/RF24_arch_config.h"
|
||||
|
||||
#elif defined (TEENSYDUINO) //Teensy
|
||||
#include "utility/Teensy/RF24_arch_config.h"
|
||||
|
||||
#else //Everything else
|
||||
#include <Arduino.h>
|
||||
|
||||
|
||||
#if defined (ARDUINO) && !defined (__arm__) && !defined (__ARDUINO_X86__)
|
||||
#if defined SPI_UART
|
||||
#include <SPI_UART.h>
|
||||
#define _SPI uspi
|
||||
#elif defined (SOFTSPI)
|
||||
// change these pins to your liking
|
||||
//
|
||||
#ifndef SOFT_SPI_MISO_PIN
|
||||
#define SOFT_SPI_MISO_PIN 9
|
||||
#endif // SOFT_SPI_MISO_PIN
|
||||
|
||||
#ifndef SOFT_SPI_MOSI_PIN
|
||||
#define SOFT_SPI_MOSI_PIN 8
|
||||
#endif // SOFT_SPI_MOSI_PIN
|
||||
|
||||
#ifndef SOFT_SPI_SCK_PIN
|
||||
#define SOFT_SPI_SCK_PIN 7
|
||||
#endif // SOFT_SPI_SCK_PIN
|
||||
|
||||
const uint8_t SPI_MODE = 0;
|
||||
#define _SPI spi
|
||||
|
||||
#else // !defined (SPI_UART) && !defined (SOFTSPI)
|
||||
#include <SPI.h>
|
||||
#define _SPI SPI
|
||||
#endif // !defined (SPI_UART) && !defined (SOFTSPI)
|
||||
|
||||
#else // defined (ARDUINO) && !defined (__arm__) && !defined (__ARDUINO_X86__)
|
||||
// Define _BV for non-Arduino platforms and for Arduino DUE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__arm__) || defined (__ARDUINO_X86__)
|
||||
#if defined (__arm__) && defined (SPI_UART)
|
||||
#include <SPI_UART.h>
|
||||
#define _SPI uspi
|
||||
|
||||
#else // !defined (__arm__) || !defined (SPI_UART)
|
||||
#include <SPI.h>
|
||||
#define _SPI SPI
|
||||
|
||||
#endif // !defined (__arm__) || !defined (SPI_UART)
|
||||
#elif !defined(__arm__) && !defined (__ARDUINO_X86__)
|
||||
extern HardwareSPI SPI;
|
||||
|
||||
#endif // !defined(__arm__) && !defined (__ARDUINO_X86__)
|
||||
|
||||
#ifndef _BV
|
||||
#define _BV(x) (1<<(x))
|
||||
#endif
|
||||
#endif // defined (ARDUINO) && !defined (__arm__) && !defined (__ARDUINO_X86__)
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
#define IF_SERIAL_DEBUG(x) ({x;})
|
||||
#else
|
||||
#define IF_SERIAL_DEBUG(x)
|
||||
#if defined(RF24_TINY)
|
||||
#define printf_P(...)
|
||||
|
||||
#endif // defined(RF24_TINY)
|
||||
#endif // SERIAL_DEBUG
|
||||
|
||||
#if defined (__ARDUINO_X86__)
|
||||
#define printf_P printf
|
||||
#define _BV(bit) (1<<(bit))
|
||||
|
||||
#endif // defined (__ARDUINO_X86__)
|
||||
|
||||
// Progmem is Arduino-specific
|
||||
// Arduino DUE is arm and does not include avr/pgmspace
|
||||
#if defined (ARDUINO_ARCH_ESP8266) || defined (ESP32)
|
||||
#include <pgmspace.h>
|
||||
#define PRIPSTR "%s"
|
||||
#ifndef pgm_read_ptr
|
||||
#define pgm_read_ptr(p) (*(p))
|
||||
#endif
|
||||
#elif defined (ARDUINO) && !defined (ESP_PLATFORM) && ! defined (__arm__) && !defined (__ARDUINO_X86__) || defined (XMEGA)
|
||||
#include <avr/pgmspace.h>
|
||||
#define PRIPSTR "%S"
|
||||
|
||||
#else // !defined (ARDUINO) || defined (ESP_PLATFORM) || defined (__arm__) || defined (__ARDUINO_X86__) && !defined (XMEGA)
|
||||
#if !defined (ARDUINO) // This doesn't work on Arduino DUE
|
||||
typedef char const char;
|
||||
|
||||
#else // Fill in pgm_read_byte that is used, but missing from DUE
|
||||
#ifdef ARDUINO_ARCH_AVR
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
#ifndef pgm_read_byte
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#endif
|
||||
#endif // !defined (ARDUINO)
|
||||
|
||||
#ifndef prog_uint16_t
|
||||
typedef uint16_t prog_uint16_t;
|
||||
#endif
|
||||
#ifndef PSTR
|
||||
#define PSTR(x) (x)
|
||||
#endif
|
||||
#ifndef printf_P
|
||||
#define printf_P printf
|
||||
#endif
|
||||
#ifndef strlen_P
|
||||
#define strlen_P strlen
|
||||
#endif
|
||||
#ifndef PROGMEM
|
||||
#define PROGMEM
|
||||
#endif
|
||||
#ifndef pgm_read_word
|
||||
#define pgm_read_word(p) (*(p))
|
||||
#endif
|
||||
#if !defined pgm_read_ptr || defined ARDUINO_ARCH_MBED
|
||||
#define pgm_read_ptr(p) (*(p))
|
||||
#endif
|
||||
#ifndef PRIPSTR
|
||||
#define PRIPSTR "%s"
|
||||
#endif
|
||||
|
||||
#endif // !defined (ARDUINO) || defined (ESP_PLATFORM) || defined (__arm__) || defined (__ARDUINO_X86__) && !defined (XMEGA)
|
||||
#endif //Everything else
|
||||
|
||||
#if defined (SPI_HAS_TRANSACTION) && !defined (SPI_UART) && !defined (SOFTSPI)
|
||||
#define RF24_SPI_TRANSACTIONS
|
||||
#endif // defined (SPI_HAS_TRANSACTION) && !defined (SPI_UART) && !defined (SOFTSPI)
|
||||
|
||||
#endif // __RF24_CONFIG_H__
|
473
src/libs/RF24-master/configure
vendored
Normal file
473
src/libs/RF24-master/configure
vendored
Normal file
@ -0,0 +1,473 @@
|
||||
#!/bin/bash
|
||||
|
||||
CROSS_CC=arm-linux-gnueabihf-gcc
|
||||
CROSS_CXX=arm-linux-gnueabihf-g++
|
||||
|
||||
function help {
|
||||
cat <<EOF
|
||||
configure script for RF24 library.
|
||||
Options:
|
||||
|
||||
Help:
|
||||
-h, --help print this message
|
||||
|
||||
Driver options:
|
||||
--driver=[wiringPi|SPIDEV|MRAA|RPi|LittleWire]
|
||||
Driver for RF24 library. [configure autodetected]
|
||||
|
||||
Building options:
|
||||
--os=[LINUX|DARWIN] Operating system. [configure autodetected]
|
||||
--soc=[BCM2835|BCM2836|AM33XX|A10|A13|A20|H3]
|
||||
SoC type to be used. [configure autodetected]
|
||||
--cpu-flags=<CFLAGS> CPU defining/optimizing flags to be used. [configure autodetected]
|
||||
--extra-cflags=<CFLAGS> Extra C flags passed to C/C++ compilation. []
|
||||
--extra-ldflags=<LDFLAGS> Extra C flags passed to linking. []
|
||||
--libname=<LIBNAME> Library name. [rf24]
|
||||
--c_compiler=<CC> C compiler. [arm-linux-gnueabihf-gcc][gcc]
|
||||
--cxx_compiler=<CXX> C++ compiler [arm-linux-gnueabihf-g++][g++]
|
||||
--no-clean Don't clean previous build artifacts
|
||||
|
||||
Installation options:
|
||||
--prefix=<PREFIX> Installation prefix path. [/usr/local]
|
||||
--lib-dir=<DIR> Library target installation directory. [PREFIX/lib]
|
||||
--header-dir=<DIR> Header files target installation directory. [PREFIX/include]
|
||||
--examples-dir=<DIR> Example files installation directory. [PREFIX/bin]
|
||||
--ldconfig=<LDCONFIG> Ldconfig binary. Can be set to '' to skip ldconfig step. [ldconfig]
|
||||
|
||||
Cross-compilation options:
|
||||
--remote-host=<REMOTE_HOST> Remote hostname for installation.
|
||||
--remote-user=<REMOTE_USER> Remote username for installation. [current user]
|
||||
--remote-port=<REMOTE_PORT> Ssh port of remote machine. [22]
|
||||
--remote=<USER@HOST> Remote ssh host identification for installation [REMOTE_USER@REMOTE_HOST]
|
||||
--remote-prefix=<RPREFIX> Remote host installation prefix path. [/usr/local]
|
||||
--remote-lib-dir=<DIR> Remote library target installation directory [RPREFIX/lib]
|
||||
--remote-header-dir=<DIR> Remote header files target installation directory. [RPREFIX/include]
|
||||
--remote-ldconfig=<RLDCON> Remote ldconfig binary filename. Can be set to '' to skip ldconfig call. [ldconfig]
|
||||
--remote-examples-dir=<DIR> Example files remote installation directory. Default: [REMOTE_PREFIX/bin]
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
function execute_check {
|
||||
if [ "${REMOTE}" ]; then
|
||||
ssh -o 'PasswordAuthentication=no' -o 'PreferredAuthentications=publickey' -o 'ConnectTimeout=30' -o 'BatchMode=yes' -o 'StrictHostKeyChecking=no' -p ${REMOTE_PORT} ${REMOTE} $1
|
||||
else
|
||||
eval $1
|
||||
fi
|
||||
}
|
||||
|
||||
function die {
|
||||
echo "[ERROR] $1"
|
||||
exit $2
|
||||
}
|
||||
|
||||
function detect_machine {
|
||||
local cpu=$(execute_check "uname -m 2>/dev/null")
|
||||
local machine=$(execute_check "cat -v /sys/firmware/devicetree/base/model 2>/dev/null")
|
||||
local hardware=$(execute_check "grep sunxi_platform /sys/class/sunxi_info/sys_info 2>/dev/null | sed 's/^.*: \(.*\)$/\1/'")
|
||||
if [ -z "$hardware" ]; then
|
||||
local hardware=$(execute_check "grep Hardware /proc/cpuinfo 2>/dev/null | sed 's/^.*: \(.*\)$/\1/'")
|
||||
fi
|
||||
local soc="unknown"
|
||||
local tp="unknown"
|
||||
|
||||
if [ -z "$cpu" ]; then
|
||||
cpu="unknown"
|
||||
fi
|
||||
|
||||
case $hardware in
|
||||
BCM2708|BCM2835)
|
||||
soc="BCM2835"
|
||||
if [[ $machine == "Raspberry"* ]]; then
|
||||
tp="RPi"
|
||||
fi
|
||||
;;
|
||||
BCM2709)
|
||||
soc="BCM2836"
|
||||
if [[ $machine == "Raspberry"* ]]; then
|
||||
tp="RPi2"
|
||||
fi
|
||||
;;
|
||||
sun4i|Sun4iw1p1)
|
||||
soc="A10"
|
||||
;;
|
||||
sun5i|Sun4iw2p1)
|
||||
soc="A13"
|
||||
;;
|
||||
Sun4iw2p2)
|
||||
soc="A12"
|
||||
;;
|
||||
Sun4iw2p3)
|
||||
soc="A10s"
|
||||
;;
|
||||
sun6i|Sun8iw1p1)
|
||||
soc="A31"
|
||||
;;
|
||||
Sun8iw1p2)
|
||||
soc="A31s"
|
||||
;;
|
||||
sun7i|Sun8iw2p1)
|
||||
soc="A20"
|
||||
if [[ $machine == "Banana Pi"* ]]; then
|
||||
tp="BananaPi"
|
||||
elif [[ $machine == "Banana Pro"* ]]; then
|
||||
tp="BananaPro"
|
||||
fi
|
||||
;;
|
||||
sun8i|Sun8iw7p1)
|
||||
soc="H3"
|
||||
;;
|
||||
Sun8iw3p1)
|
||||
soc="A23"
|
||||
;;
|
||||
Sun8iw5p1)
|
||||
soc="A33"
|
||||
;;
|
||||
Sun8iw6p1)
|
||||
soc="A83t"
|
||||
;;
|
||||
sun9i|Sun9iw1p1)
|
||||
soc="A80"
|
||||
;;
|
||||
Sun9iw1p2)
|
||||
soc="A80t"
|
||||
;;
|
||||
sun50i|Sun50iw1p1)
|
||||
soc="A64"
|
||||
;;
|
||||
'Generic AM33XX'*)
|
||||
soc="AM33XX"
|
||||
;;
|
||||
*)
|
||||
soc="unknown"
|
||||
esac
|
||||
echo "${soc} ${tp} ${cpu}"
|
||||
}
|
||||
|
||||
function gcc_cpu_flags {
|
||||
local soc=$1
|
||||
case $soc in
|
||||
BCM2835)
|
||||
flags="-marm -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard"
|
||||
;;
|
||||
BCM2836)
|
||||
flags="-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard"
|
||||
;;
|
||||
AM33XX)
|
||||
flags="-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard"
|
||||
;;
|
||||
A10)
|
||||
flags="-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard"
|
||||
;;
|
||||
A13)
|
||||
flags="-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard"
|
||||
;;
|
||||
A20)
|
||||
flags="-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard"
|
||||
;;
|
||||
H3)
|
||||
flags="-march=armv8-a -mtune=cortex-a53 -mfpu=neon-vfpv4 -mfloat-abi=hard"
|
||||
;;
|
||||
*)
|
||||
flags=""
|
||||
esac
|
||||
echo ${flags}
|
||||
}
|
||||
|
||||
function detect_driver {
|
||||
if [[ $(execute_check "cat /proc/cpuinfo | grep Hardware | grep 'BCM2708\|BCM2709\|BCM2835'") ]]; then
|
||||
result=RPi
|
||||
elif [[ $(execute_check 'ls /dev/spidev* 2>/dev/null') ]]; then
|
||||
result=SPIDEV
|
||||
elif [[ $(execute_check "file /usr/lib/libwiringPi.so*") ]]; then
|
||||
result=wiringPi
|
||||
elif [[ $(execute_check "${REMOTE_LDCONFIG} -p | grep libmraa") ]]; then
|
||||
result=MRAA
|
||||
elif [[ $(execute_check "${REMOTE_LDCONFIG} -p | grep liblittlewire-spi") ]]; then
|
||||
result=LittleWire
|
||||
else
|
||||
result=""
|
||||
fi
|
||||
echo $result
|
||||
}
|
||||
|
||||
function gen_symlink_names {
|
||||
base_name="$1"
|
||||
version="$2"
|
||||
|
||||
IFS='.' read -r -a ver <<< "$version"
|
||||
versions=""
|
||||
for index in "${!ver[@]}" ; do
|
||||
verstr=""
|
||||
for ind in `seq 0 $(expr $index - 1)` ; do
|
||||
verstr="${verstr}.${ver[$ind]}"
|
||||
done
|
||||
versions="${base_name}${verstr} $versions"
|
||||
done
|
||||
echo ${versions}
|
||||
}
|
||||
|
||||
params="OS SOC DRIVER CPUFLAGS CFLAGS PREFIX REMOTE_PREFIX LIB LIBNAME LIB_VERSION LIBSYMLINKS LIBDEPRECATE CC CXX LIB_DIR REMOTE_LIB_DIR HEADER_DIR REMOTE_HEADER_DIR DRIVER_DIR ARCH_DIR REMOTE REMOTE_HOST REMOTE_USER REMOTE_PORT SHARED_LINKER_FLAGS SHARED_LINKER_LIBS LDCONFIG REMOTE_LDCONFIG EXAMPLES_DIR REMOTE_EXAMPLES_DIR"
|
||||
|
||||
for opt do
|
||||
if [ "$opt" = "-h" ] || [ "$opt" = "--help" ]; then
|
||||
help
|
||||
exit 0
|
||||
fi
|
||||
optarg="${opt#*=}"
|
||||
case "$opt" in
|
||||
--os=*)
|
||||
OS="$optarg"
|
||||
;;
|
||||
--soc=*)
|
||||
SOC="$optarg"
|
||||
;;
|
||||
--cpu-flags=*)
|
||||
CPUFLAGS="$optarg"
|
||||
;;
|
||||
--extra-cflags=*)
|
||||
CFLAGS="$optarg"
|
||||
;;
|
||||
--extra-ldflags=*)
|
||||
LDFLAGS="$optarg"
|
||||
;;
|
||||
--libname=*)
|
||||
LIB="$optarg"
|
||||
;;
|
||||
--c_compiler=*)
|
||||
CC="$optarg"
|
||||
;;
|
||||
--cxx_compiler=*)
|
||||
CXX="$optarg"
|
||||
;;
|
||||
--no-clean*)
|
||||
NO_CLEAN="1"
|
||||
;;
|
||||
--prefix=*)
|
||||
PREFIX="$optarg"
|
||||
;;
|
||||
--lib-dir=*)
|
||||
LIB_DIR="$optarg"
|
||||
;;
|
||||
--header-dir=*)
|
||||
HEADER_DIR="$optarg"
|
||||
;;
|
||||
--examples-dir=*)
|
||||
EXAMPLES_DIR="$optarg"
|
||||
;;
|
||||
--ldconfig=*)
|
||||
LDCONFIG="$optarg"
|
||||
;;
|
||||
--driver=*)
|
||||
DRIVER="$optarg"
|
||||
;;
|
||||
--remote-host=*)
|
||||
REMOTE_HOST="$optarg"
|
||||
;;
|
||||
--remote-user=*)
|
||||
REMOTE_USER="$optarg"
|
||||
;;
|
||||
--remote-port=*)
|
||||
REMOTE_PORT="$optarg"
|
||||
;;
|
||||
--remote=*)
|
||||
REMOTE="$optarg"
|
||||
;;
|
||||
--remote-prefix=*)
|
||||
REMOTE_PREFIX="$optarg"
|
||||
;;
|
||||
--remote-lib-dir=*)
|
||||
REMOTE_LIB_DIR="$optarg"
|
||||
;;
|
||||
--remote-header-dir=*)
|
||||
REMOTE_HEADER_DIR="$optarg"
|
||||
;;
|
||||
--remote-ldconfig=*)
|
||||
REMOTE_LDCONFIG="$optarg"
|
||||
;;
|
||||
--remote-examples-dir=*)
|
||||
REMOTE_EXAMPLES_DIR="$optarg"
|
||||
;;
|
||||
*)
|
||||
echo "[WARNING] Unknown option detected:$opt, ignored"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
#*******************************************
|
||||
# remote machine verification
|
||||
if [ "${REMOTE_HOST}" ]; then
|
||||
if [ "${REMOTE_USER}" ]; then
|
||||
REMOTE=${REMOTE_USER}@${REMOTE_HOST}
|
||||
else
|
||||
REMOTE=${REMOTE_HOST}
|
||||
fi
|
||||
fi
|
||||
if [ "${REMOTE}" ]; then
|
||||
echo "[SECTION] Checking remote host."
|
||||
if [ -z "${REMOTE_HOST}" ]; then
|
||||
REMOTE_HOST=${REMOTE/*@/}
|
||||
fi
|
||||
if [ -z "${REMOTE_PORT}" ]; then
|
||||
REMOTE_PORT=22
|
||||
fi
|
||||
if [ "$(nmap ${REMOTE_HOST} -Pn --host-timeout 30s -p ${REMOTE_PORT} 2>/dev/null | grep open)" ]; then
|
||||
echo " [OK] ssh daemon on ${REMOTE_HOST} port ${REMOTE_PORT} seems to be listening."
|
||||
else
|
||||
echo " [WARNING] ssh on ${REMOTE_HOST} port ${REMOTE_PORT} seems not to be listening or nmap not installed."
|
||||
fi
|
||||
if [[ "$(execute_check 'echo ok 2>/dev/null' 2>/dev/null)" ]]; then
|
||||
echo " [OK] Remote machine ssh passwordless login configured fine."
|
||||
else
|
||||
die "Remote machine ssh and/or passwordless login check failed." 4
|
||||
fi
|
||||
if [[ $(execute_check "sudo echo ok 2>/dev/null") ]]; then
|
||||
echo " [OK] Remote machine sudo configured fine."
|
||||
else
|
||||
die "Remote machine sudo test failed." 5
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "${CC}" ]; then
|
||||
echo "[SECTION] Detecting arm compilation environment."
|
||||
if [[ $(command -v ${CROSS_CC} 2>/dev/null) ]]; then
|
||||
echo " [OK] ${CROSS_CC} detected."
|
||||
CC=${CROSS_CC}
|
||||
CROSS_SYSROOT="$(${CC} --print-sysroot)"
|
||||
if [ "${CROSS_SYSROOT}" = "/" ]; then
|
||||
CROSS_SYSROOT=""
|
||||
fi
|
||||
else
|
||||
echo " [INFO] ${CROSS_CC} not found."
|
||||
fi
|
||||
if [[ $(command -v ${CROSS_CXX} 2>/dev/null) ]]; then
|
||||
echo " [OK] ${CROSS_CXX} detected."
|
||||
CXX=${CROSS_CXX}
|
||||
else
|
||||
echo " [INFO] ${CROSS_CXX} not found."
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${CROSS_SYSROOT}" ]; then
|
||||
PREFIX="${CROSS_SYSROOT}/usr/local"
|
||||
fi
|
||||
|
||||
PREFIX=${PREFIX:-/usr/local}
|
||||
REMOTE_PREFIX=${REMOTE_PREFIX:-/usr/local}
|
||||
LIB_DIR=${LIB_DIR:-${PREFIX}/lib}
|
||||
REMOTE_LIB_DIR=${REMOTE_LIB_DIR:-${REMOTE_PREFIX}/lib}
|
||||
HEADER_DIR=${HEADER_DIR:-${PREFIX}/include/RF24}
|
||||
REMOTE_HEADER_DIR=${REMOTE_HEADER_DIR:-${REMOTE_PREFIX}/include/RF24}
|
||||
EXAMPLES_DIR=${EXAMPLES_DIR:-${PREFIX}/bin}
|
||||
REMOTE_EXAMPLES_DIR=${REMOTE_EXAMPLES_DIR:-${REMOTE_PREFIX}/bin}
|
||||
LDCONFIG=${LDCONFIG-ldconfig}
|
||||
REMOTE_LDCONFIG=${REMOTE_LDCONFIG-/sbin/ldconfig}
|
||||
LIB=${LIB:-rf24}
|
||||
LIB_VERSION=${LIB_VERSION:-$(awk -F "=" '/version/ {print $2}' library.properties)}
|
||||
LIB_DEPRECATE_NAME=${LIB_DEPRECATE_NAME:-"rf24-bcm"}
|
||||
LIB_DEPRECATE_VERSION=${LIB_DEPRECATE_VERSION:-""}
|
||||
CC=${CC:-gcc}
|
||||
CXX=${CXX:-g++}
|
||||
ARCH_DIR=${ARCH_DIR:-utility}
|
||||
|
||||
|
||||
if [ -z "${SOC}" ]; then
|
||||
echo "[SECTION] Detecting target machine."
|
||||
info=($(detect_machine))
|
||||
SOC=${info[0]}
|
||||
TYPE=${info[1]}
|
||||
CPU=${info[2]}
|
||||
echo "[OK] machine detected: SoC=${SOC}, Type=${TYPE}, CPU=${CPU}."
|
||||
fi
|
||||
|
||||
if [ -z "${CPUFLAGS}" ]; then
|
||||
CPUFLAGS=$(gcc_cpu_flags $SOC)
|
||||
fi
|
||||
|
||||
|
||||
#*******************************************
|
||||
# DRIVER detection
|
||||
if [ -z "${DRIVER}" ]; then
|
||||
echo "[SECTION] Detecting DRIVER"
|
||||
DRIVER=$(detect_driver)
|
||||
if [ -z "${DRIVER}" ]; then
|
||||
die "No supported driver detected. Run configure with --driver=<driver> to set a driver explicitly." 1
|
||||
fi
|
||||
echo " [OK] DRIVER detected:${DRIVER}."
|
||||
fi
|
||||
|
||||
case ${DRIVER} in
|
||||
wiringPi)
|
||||
SHARED_LINKER_LIBS+=" -pthread -lwiringPi"
|
||||
CFLAGS+=" -lwiringPi"
|
||||
;;
|
||||
SPIDEV)
|
||||
SHARED_LINKER_LIBS+=" -pthread"
|
||||
;;
|
||||
RPi)
|
||||
SHARED_LINKER_LIBS+=" -pthread"
|
||||
;;
|
||||
MRAA)
|
||||
SHARED_LINKER_LIBS+=" -lmraa"
|
||||
;;
|
||||
LittleWire)
|
||||
SHARED_LINKER_LIBS+=" -llittlewire-spi"
|
||||
;;
|
||||
*)
|
||||
die "Unsupported DRIVER: ${DRIVER}." 2
|
||||
;;
|
||||
esac
|
||||
|
||||
#*******************************************
|
||||
# OS detection
|
||||
if [ -z "${OS}" ]; then
|
||||
echo "[SECTION] Detecting OS."
|
||||
OS=$(execute_check "uname")
|
||||
OS=${OS^^}
|
||||
echo " [INFO] OS detected:${OS}."
|
||||
fi
|
||||
|
||||
case ${OS} in
|
||||
LINUX)
|
||||
DYN_SUFFIX=so
|
||||
SHARED_LINKER_FLAGS+=" -shared -Wl,-soname,lib${LIB}.${DYN_SUFFIX}.${LIB_VERSION%%.*}"
|
||||
;;
|
||||
DARWIN)
|
||||
DYN_SUFFIX=dylib
|
||||
SHARED_LINKER_FLAGS+=" -dynamiclib -install_name ${LIB_DIR}/lib${LIB}.${DYN_SUFFIX}.${LIB_VERSION%%.*}"
|
||||
;;
|
||||
*)
|
||||
die "Unsupported OS: ${OS}." 3
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
LIBNAME=${LIBNAME:-lib${LIB}.${DYN_SUFFIX}.${LIB_VERSION}}
|
||||
LIBSYMLINKS="${LIBSYMLINKS:-$(gen_symlink_names lib${LIB}.${DYN_SUFFIX} ${LIB_VERSION})}"
|
||||
if [ "${LIB_DEPRECATE_NAME}" ]; then
|
||||
LIBDEPRECATE="${LIBDEPRECATE:-lib${LIB_DEPRECATE_NAME}.${DYN_SUFFIX}}"
|
||||
if [ "${LIB_DEPRECATE_VERSION}" ]; then
|
||||
LIBDEPRECATE="${LIBDEPRECATE}.${LIB_DEPRECATE_VERSION}"
|
||||
fi
|
||||
fi
|
||||
DRIVER_DIR=${DRIVER_DIR:-${ARCH_DIR}/${DRIVER}}
|
||||
CFLAGS="$CPUFLAGS -Ofast -Wall -pthread $CFLAGS"
|
||||
|
||||
echo "[SECTION] Preparing configuration."
|
||||
cp ${DRIVER_DIR}/includes.h ${ARCH_DIR}/includes.h
|
||||
|
||||
echo "[SECTION] Saving configuration."
|
||||
echo -n "" > Makefile.inc
|
||||
for param in ${params}; do
|
||||
if [[ ${!param} ]]; then
|
||||
echo "${param}=${!param}" >> Makefile.inc
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "${NO_CLEAN}" ]; then
|
||||
echo "[SECTION] Cleaning previous builds."
|
||||
make clean >/dev/null
|
||||
fi
|
||||
|
||||
|
||||
echo "[OK] Finished."
|
BIN
src/libs/RF24-master/datasheets/nRF24L01P_datasheet_v1.pdf
Normal file
BIN
src/libs/RF24-master/datasheets/nRF24L01P_datasheet_v1.pdf
Normal file
Binary file not shown.
BIN
src/libs/RF24-master/datasheets/nRF24L01_datasheet_v2.pdf
Normal file
BIN
src/libs/RF24-master/datasheets/nRF24L01_datasheet_v2.pdf
Normal file
Binary file not shown.
815
src/libs/RF24-master/doxygen-custom.css
Normal file
815
src/libs/RF24-master/doxygen-custom.css
Normal file
@ -0,0 +1,815 @@
|
||||
/* The standard CSS for doxygen */
|
||||
|
||||
body, table, div, p, dl {
|
||||
font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* @group Heading Levels */
|
||||
|
||||
h1 {
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 150%;
|
||||
font-weight: bold;
|
||||
margin: 10px 2px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.multicol {
|
||||
-moz-column-gap: 1em;
|
||||
-webkit-column-gap: 1em;
|
||||
-moz-column-count: 3;
|
||||
-webkit-column-count: 3;
|
||||
}
|
||||
|
||||
p.startli, p.startdd, p.starttd {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
p.endli {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
p.enddd {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
p.endtd {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
caption {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.legend {
|
||||
font-size: 70%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h3.version {
|
||||
font-size: 90%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.qindex, div.navtab {
|
||||
background-color: #EBEFF6;
|
||||
border: 1px solid #A3B4D7;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
div.qindex, div.navpath {
|
||||
width: 100%;
|
||||
line-height: 110%;
|
||||
}
|
||||
|
||||
div.navtab {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
/* @group Link Styling */
|
||||
|
||||
a {
|
||||
color: #3D578C;
|
||||
font-weight: normal;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.contents a:visited {
|
||||
color: #4665A2;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a.qindex {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
a.qindexHL {
|
||||
font-weight: bold;
|
||||
background-color: #9CAFD4;
|
||||
color: #ffffff;
|
||||
border: 1px double #869DCA;
|
||||
}
|
||||
|
||||
.contents a.qindexHL:visited {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
a.el {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
a.elRef {
|
||||
}
|
||||
|
||||
a.code {
|
||||
color: #4665A2;
|
||||
}
|
||||
|
||||
a.codeRef {
|
||||
color: #4665A2;
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
dl.el {
|
||||
margin-left: -1cm;
|
||||
}
|
||||
|
||||
.fragment {
|
||||
font-family: monospace, fixed;
|
||||
font-size: 105%;
|
||||
}
|
||||
|
||||
pre.fragment {
|
||||
border: 1px solid #C4CFE5;
|
||||
background-color: #FBFCFD;
|
||||
padding: 4px 6px;
|
||||
margin: 4px 8px 4px 2px;
|
||||
overflow: auto;
|
||||
word-wrap: break-word;
|
||||
font-size: 9pt;
|
||||
line-height: 125%;
|
||||
}
|
||||
|
||||
div.ah {
|
||||
background-color: black;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
margin-bottom: 3px;
|
||||
margin-top: 3px;
|
||||
padding: 0.2em;
|
||||
border: solid thin #333;
|
||||
border-radius: 0.5em;
|
||||
-webkit-border-radius: .5em;
|
||||
-moz-border-radius: .5em;
|
||||
box-shadow: 2px 2px 3px #999;
|
||||
-webkit-box-shadow: 2px 2px 3px #999;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000), color-stop(0.3, #444));
|
||||
background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000);
|
||||
}
|
||||
|
||||
div.groupHeader {
|
||||
margin-left: 16px;
|
||||
margin-top: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.groupText {
|
||||
margin-left: 16px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
body {
|
||||
background: white;
|
||||
color: black;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.contents {
|
||||
margin-top: 10px;
|
||||
margin-left: 10px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
td.indexkey {
|
||||
background-color: #EBEFF6;
|
||||
font-weight: bold;
|
||||
border: 1px solid #C4CFE5;
|
||||
margin: 2px 0px 2px 0;
|
||||
padding: 2px 10px;
|
||||
}
|
||||
|
||||
td.indexvalue {
|
||||
background-color: #EBEFF6;
|
||||
border: 1px solid #C4CFE5;
|
||||
padding: 2px 10px;
|
||||
margin: 2px 0px;
|
||||
}
|
||||
|
||||
tr.memlist {
|
||||
background-color: #EEF1F7;
|
||||
}
|
||||
|
||||
p.formulaDsp {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
img.formulaDsp {
|
||||
|
||||
}
|
||||
|
||||
img.formulaInl {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.center {
|
||||
text-align: center;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
div.center img {
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
address.footer {
|
||||
text-align: right;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
img.footer {
|
||||
border: 0px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* @group Code Colorization */
|
||||
|
||||
span.keyword {
|
||||
color: #008000
|
||||
}
|
||||
|
||||
span.keywordtype {
|
||||
color: #604020
|
||||
}
|
||||
|
||||
span.keywordflow {
|
||||
color: #e08000
|
||||
}
|
||||
|
||||
span.comment {
|
||||
color: #800000
|
||||
}
|
||||
|
||||
span.preprocessor {
|
||||
color: #806020
|
||||
}
|
||||
|
||||
span.stringliteral {
|
||||
color: #002080
|
||||
}
|
||||
|
||||
span.charliteral {
|
||||
color: #008080
|
||||
}
|
||||
|
||||
span.vhdldigit {
|
||||
color: #ff00ff
|
||||
}
|
||||
|
||||
span.vhdlchar {
|
||||
color: #000000
|
||||
}
|
||||
|
||||
span.vhdlkeyword {
|
||||
color: #700070
|
||||
}
|
||||
|
||||
span.vhdllogic {
|
||||
color: #ff0000
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
/*
|
||||
.search {
|
||||
color: #003399;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
form.search {
|
||||
margin-bottom: 0px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
input.search {
|
||||
font-size: 75%;
|
||||
color: #000080;
|
||||
font-weight: normal;
|
||||
background-color: #e8eef2;
|
||||
}
|
||||
*/
|
||||
|
||||
td.tiny {
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
.dirtab {
|
||||
padding: 4px;
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #A3B4D7;
|
||||
}
|
||||
|
||||
th.dirtab {
|
||||
background: #EBEFF6;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 0px;
|
||||
border: none;
|
||||
border-top: 1px solid #4A6AAA;
|
||||
}
|
||||
|
||||
hr.footer {
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
/* @group Member Descriptions */
|
||||
|
||||
table.memberdecls {
|
||||
border-spacing: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.mdescLeft, .mdescRight,
|
||||
.memItemLeft, .memItemRight,
|
||||
.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
|
||||
background-color: #F9FAFC;
|
||||
border: none;
|
||||
margin: 4px;
|
||||
padding: 1px 0 0 8px;
|
||||
}
|
||||
|
||||
.mdescLeft, .mdescRight {
|
||||
padding: 0px 8px 4px 8px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.memItemLeft, .memItemRight, .memTemplParams {
|
||||
border-top: 1px solid #C4CFE5;
|
||||
}
|
||||
|
||||
.memItemLeft, .memTemplItemLeft {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.memItemRight {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.memTemplParams {
|
||||
color: #4665A2;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
/* @group Member Details */
|
||||
|
||||
/* Styles for detailed member documentation */
|
||||
|
||||
.memtemplate {
|
||||
font-size: 80%;
|
||||
color: #4665A2;
|
||||
font-weight: normal;
|
||||
margin-left: 9px;
|
||||
}
|
||||
|
||||
.memnav {
|
||||
background-color: #EBEFF6;
|
||||
border: 1px solid #A3B4D7;
|
||||
text-align: center;
|
||||
margin: 2px;
|
||||
margin-right: 15px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.mempage {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.memitem {
|
||||
padding: 0;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.memname {
|
||||
white-space: nowrap;
|
||||
font-weight: bold;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.memproto {
|
||||
border-top: 1px solid #A8B8D9;
|
||||
border-left: 1px solid #A8B8D9;
|
||||
border-right: 1px solid #A8B8D9;
|
||||
padding: 6px 0px 6px 0px;
|
||||
color: #253555;
|
||||
font-weight: bold;
|
||||
text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
|
||||
/* opera specific markup */
|
||||
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
|
||||
border-top-right-radius: 8px;
|
||||
border-top-left-radius: 8px;
|
||||
/* firefox specific markup */
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
|
||||
-moz-border-radius-topright: 8px;
|
||||
-moz-border-radius-topleft: 8px;
|
||||
/* webkit specific markup */
|
||||
-webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
|
||||
-webkit-border-top-right-radius: 8px;
|
||||
-webkit-border-top-left-radius: 8px;
|
||||
background-image: url('nav_f.png');
|
||||
background-repeat: repeat-x;
|
||||
background-color: #E2E8F2;
|
||||
|
||||
}
|
||||
|
||||
.memdoc {
|
||||
border-bottom: 1px solid #A8B8D9;
|
||||
border-left: 1px solid #A8B8D9;
|
||||
border-right: 1px solid #A8B8D9;
|
||||
padding: 2px 5px;
|
||||
background-color: #FBFCFD;
|
||||
border-top-width: 0;
|
||||
/* opera specific markup */
|
||||
border-bottom-left-radius: 8px;
|
||||
border-bottom-right-radius: 8px;
|
||||
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
|
||||
/* firefox specific markup */
|
||||
-moz-border-radius-bottomleft: 8px;
|
||||
-moz-border-radius-bottomright: 8px;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
|
||||
background-image: -moz-linear-gradient(center top, #FFFFFF 0%, #FFFFFF 60%, #F7F8FB 95%, #EEF1F7);
|
||||
/* webkit specific markup */
|
||||
-webkit-border-bottom-left-radius: 8px;
|
||||
-webkit-border-bottom-right-radius: 8px;
|
||||
-webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
|
||||
background-image: -webkit-gradient(linear, center top, center bottom, from(#FFFFFF), color-stop(0.6, #FFFFFF), color-stop(0.60, #FFFFFF), color-stop(0.95, #F7F8FB), to(#EEF1F7));
|
||||
}
|
||||
|
||||
.paramkey {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.paramtype {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.paramname {
|
||||
color: #602020;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.paramname em {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.params, .retval, .exception, .tparams {
|
||||
border-spacing: 6px 2px;
|
||||
}
|
||||
|
||||
.params .paramname, .retval .paramname {
|
||||
font-weight: bold;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.params .paramtype {
|
||||
font-style: italic;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.params .paramdir {
|
||||
font-family: "courier new", courier, monospace;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
|
||||
/* @end */
|
||||
|
||||
/* @group Directory (tree) */
|
||||
|
||||
/* for the tree view */
|
||||
|
||||
.ftvtree {
|
||||
font-family: sans-serif;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
/* these are for tree view when used as main index */
|
||||
|
||||
.directory {
|
||||
font-size: 9pt;
|
||||
font-weight: bold;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.directory h3 {
|
||||
margin: 0px;
|
||||
margin-top: 1em;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
/*
|
||||
The following two styles can be used to replace the root node title
|
||||
with an image of your choice. Simply uncomment the next two styles,
|
||||
specify the name of your image and be sure to set 'height' to the
|
||||
proper pixel height of your image.
|
||||
*/
|
||||
|
||||
/*
|
||||
.directory h3.swap {
|
||||
height: 61px;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("yourimage.gif");
|
||||
}
|
||||
.directory h3.swap span {
|
||||
display: none;
|
||||
}
|
||||
*/
|
||||
|
||||
.directory > h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.directory p {
|
||||
margin: 0px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.directory div {
|
||||
display: none;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.directory img {
|
||||
vertical-align: -30%;
|
||||
}
|
||||
|
||||
/* these are for tree view when not used as main index */
|
||||
|
||||
.directory-alt {
|
||||
font-size: 100%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.directory-alt h3 {
|
||||
margin: 0px;
|
||||
margin-top: 1em;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
.directory-alt > h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.directory-alt p {
|
||||
margin: 0px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.directory-alt div {
|
||||
display: none;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.directory-alt img {
|
||||
vertical-align: -30%;
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
div.dynheader {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
address {
|
||||
font-style: normal;
|
||||
color: #2A3D61;
|
||||
}
|
||||
|
||||
table.doxtable {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table.doxtable td, table.doxtable th {
|
||||
border: 1px solid #2D4068;
|
||||
padding: 3px 7px 2px;
|
||||
}
|
||||
|
||||
table.doxtable th {
|
||||
background-color: #374F7F;
|
||||
color: #FFFFFF;
|
||||
font-size: 110%;
|
||||
padding-bottom: 4px;
|
||||
padding-top: 5px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.tabsearch {
|
||||
top: 0px;
|
||||
left: 10px;
|
||||
height: 36px;
|
||||
background-image: url('tab_b.png');
|
||||
z-index: 101;
|
||||
overflow: hidden;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.navpath ul {
|
||||
font-size: 11px;
|
||||
background-image: url('tab_b.png');
|
||||
background-repeat: repeat-x;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
color: #8AA0CC;
|
||||
border: solid 1px #C2CDE4;
|
||||
overflow: hidden;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.navpath li {
|
||||
list-style-type: none;
|
||||
float: left;
|
||||
padding-left: 10px;
|
||||
padding-right: 15px;
|
||||
background-image: url('bc_s.png');
|
||||
background-repeat: no-repeat;
|
||||
background-position: right;
|
||||
color: #364D7C;
|
||||
}
|
||||
|
||||
.navpath li.navelem a {
|
||||
height: 32px;
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.navpath li.navelem a:hover {
|
||||
color: #6884BD;
|
||||
}
|
||||
|
||||
.navpath li.footer {
|
||||
list-style-type: none;
|
||||
float: right;
|
||||
padding-left: 10px;
|
||||
padding-right: 15px;
|
||||
background-image: none;
|
||||
background-repeat: no-repeat;
|
||||
background-position: right;
|
||||
color: #364D7C;
|
||||
font-size: 8pt;
|
||||
}
|
||||
|
||||
|
||||
div.summary {
|
||||
float: right;
|
||||
font-size: 8pt;
|
||||
padding-right: 5px;
|
||||
width: 50%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.summary a {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.ingroups {
|
||||
font-size: 8pt;
|
||||
padding-left: 5px;
|
||||
width: 50%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.ingroups a {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.header {
|
||||
background-image: url('nav_h.png');
|
||||
background-repeat: repeat-x;
|
||||
background-color: #F9FAFC;
|
||||
margin: 0px;
|
||||
border-bottom: 1px solid #C4CFE5;
|
||||
}
|
||||
|
||||
div.headertitle {
|
||||
padding: 5px 5px 5px 10px;
|
||||
}
|
||||
|
||||
dl {
|
||||
padding: 0 0 0 10px;
|
||||
}
|
||||
|
||||
dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug {
|
||||
border-left: 4px solid;
|
||||
padding: 0 0 0 6px;
|
||||
}
|
||||
|
||||
dl.note {
|
||||
border-color: #D0C000;
|
||||
}
|
||||
|
||||
dl.warning, dl.attention {
|
||||
border-color: #FF0000;
|
||||
}
|
||||
|
||||
dl.pre, dl.post, dl.invariant {
|
||||
border-color: #00D000;
|
||||
}
|
||||
|
||||
dl.deprecated {
|
||||
border-color: #505050;
|
||||
}
|
||||
|
||||
dl.todo {
|
||||
border-color: #00C0E0;
|
||||
}
|
||||
|
||||
dl.test {
|
||||
border-color: #3030E0;
|
||||
}
|
||||
|
||||
dl.bug {
|
||||
border-color: #C08050;
|
||||
}
|
||||
|
||||
#projectlogo {
|
||||
text-align: center;
|
||||
vertical-align: bottom;
|
||||
border-collapse: separate;
|
||||
}
|
||||
|
||||
#projectlogo img {
|
||||
border: 0px none;
|
||||
}
|
||||
|
||||
#projectname {
|
||||
font: 300% Tahoma, Arial, sans-serif;
|
||||
margin: 0px;
|
||||
padding: 2px 0px;
|
||||
}
|
||||
|
||||
#projectbrief {
|
||||
font: 120% Tahoma, Arial, sans-serif;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#projectnumber {
|
||||
font: 50% Tahoma, Arial, sans-serif;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#titlearea {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #5373B4;
|
||||
}
|
||||
|
||||
.image {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.dotgraph {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mscgraph {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.caption {
|
||||
font-weight: bold;
|
||||
}
|
||||
td.fielddoc
|
||||
th.markdownTableHeadLeft,
|
||||
th.markdownTableHeadRight,
|
||||
th.markdownTableHeadCenter,
|
||||
th.markdownTableHeadNone {
|
||||
background-image: none;
|
||||
border-radius: unset;
|
||||
}
|
||||
|
||||
td.fielddoc tr:last-child {
|
||||
border-bottom: 1px solid #2D4068;
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* See documentation at https://nRF24.github.io/RF24
|
||||
* See License information at root directory of this library
|
||||
* Author: Brendan Doherty (2bndy5)
|
||||
*/
|
||||
|
||||
/**
|
||||
* A simple example of sending data from 1 nRF24L01 transceiver to another
|
||||
* with Acknowledgement (ACK) payloads attached to ACK packets.
|
||||
*
|
||||
* This example was written to be used on 2 devices acting as "nodes".
|
||||
* Use the Serial Monitor to change each node's behavior.
|
||||
*/
|
||||
#include <SPI.h>
|
||||
#include "printf.h"
|
||||
#include "RF24.h"
|
||||
|
||||
// instantiate an object for the nRF24L01 transceiver
|
||||
RF24 radio(7, 8); // using pin 7 for the CE pin, and pin 8 for the CSN pin
|
||||
|
||||
// an identifying device destination
|
||||
// Let these addresses be used for the pair
|
||||
uint8_t address[][6] = {"1Node", "2Node"};
|
||||
// It is very helpful to think of an address as a path instead of as
|
||||
// an identifying device destination
|
||||
// to use different addresses on a pair of radios, we need a variable to
|
||||
|
||||
// uniquely identify which address this radio will use to transmit
|
||||
bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
|
||||
// Used to control whether this node is sending or receiving
|
||||
bool role = false; // true = TX role, false = RX role
|
||||
|
||||
// For this example, we'll be using a payload containing
|
||||
// a string & an integer number that will be incremented
|
||||
// on every successful transmission.
|
||||
// Make a data structure to store the entire payload of different datatypes
|
||||
struct PayloadStruct {
|
||||
char message[7]; // only using 6 characters for TX & ACK payloads
|
||||
uint8_t counter;
|
||||
};
|
||||
PayloadStruct payload;
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
while (!Serial) {
|
||||
// some boards need to wait to ensure access to serial over USB
|
||||
}
|
||||
|
||||
// initialize the transceiver on the SPI bus
|
||||
if (!radio.begin()) {
|
||||
Serial.println(F("radio hardware is not responding!!"));
|
||||
while (1) {} // hold in infinite loop
|
||||
}
|
||||
|
||||
// print example's introductory prompt
|
||||
Serial.println(F("RF24/examples/AcknowledgementPayloads"));
|
||||
|
||||
// To set the radioNumber via the Serial monitor on startup
|
||||
Serial.println(F("Which radio is this? Enter '0' or '1'. Defaults to '0'"));
|
||||
while (!Serial.available()) {
|
||||
// wait for user input
|
||||
}
|
||||
char input = Serial.parseInt();
|
||||
radioNumber = input == 1;
|
||||
Serial.print(F("radioNumber = "));
|
||||
Serial.println((int)radioNumber);
|
||||
|
||||
// role variable is hardcoded to RX behavior, inform the user of this
|
||||
Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
|
||||
|
||||
// Set the PA Level low to try preventing power supply related problems
|
||||
// because these examples are likely run with nodes in close proximity to
|
||||
// each other.
|
||||
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
|
||||
|
||||
// to use ACK payloads, we need to enable dynamic payload lengths (for all nodes)
|
||||
radio.enableDynamicPayloads(); // ACK payloads are dynamically sized
|
||||
|
||||
// Acknowledgement packets have no payloads by default. We need to enable
|
||||
// this feature for all nodes (TX & RX) to use ACK payloads.
|
||||
radio.enableAckPayload();
|
||||
|
||||
// set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radioNumber]); // always uses pipe 0
|
||||
|
||||
// set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1
|
||||
|
||||
// additional setup specific to the node's role
|
||||
if (role) {
|
||||
// setup the TX payload
|
||||
|
||||
memcpy(payload.message, "Hello ", 6); // set the payload message
|
||||
radio.stopListening(); // put radio in TX mode
|
||||
} else {
|
||||
// setup the ACK payload & load the first response into the FIFO
|
||||
|
||||
memcpy(payload.message, "World ", 6); // set the payload message
|
||||
// load the payload for the first received transmission on pipe 0
|
||||
radio.writeAckPayload(1, &payload, sizeof(PayloadStruct));
|
||||
|
||||
radio.startListening(); // put radio in RX mode
|
||||
}
|
||||
|
||||
// For debugging info
|
||||
// printf_begin(); // needed only once for printing details
|
||||
// radio.printDetails(); // (smaller) function that prints raw register values
|
||||
// radio.printPrettyDetails(); // (larger) function that prints human readable data
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
if (role) {
|
||||
// This device is a TX node
|
||||
|
||||
unsigned long start_timer = micros(); // start the timer
|
||||
bool report = radio.write(&payload, sizeof(payload)); // transmit & save the report
|
||||
unsigned long end_timer = micros(); // end the timer
|
||||
|
||||
if (report) {
|
||||
Serial.print(F("Transmission successful! ")); // payload was delivered
|
||||
Serial.print(F("Time to transmit = "));
|
||||
Serial.print(end_timer - start_timer); // print the timer result
|
||||
Serial.print(F(" us. Sent: "));
|
||||
Serial.print(payload.message); // print the outgoing message
|
||||
Serial.print(payload.counter); // print the outgoing counter
|
||||
uint8_t pipe;
|
||||
if (radio.available(&pipe)) { // is there an ACK payload? grab the pipe number that received it
|
||||
PayloadStruct received;
|
||||
radio.read(&received, sizeof(received)); // get incoming ACK payload
|
||||
Serial.print(F(" Recieved "));
|
||||
Serial.print(radio.getDynamicPayloadSize()); // print incoming payload size
|
||||
Serial.print(F(" bytes on pipe "));
|
||||
Serial.print(pipe); // print pipe number that received the ACK
|
||||
Serial.print(F(": "));
|
||||
Serial.print(received.message); // print incoming message
|
||||
Serial.println(received.counter); // print incoming counter
|
||||
|
||||
// save incoming counter & increment for next outgoing
|
||||
payload.counter = received.counter + 1;
|
||||
|
||||
} else {
|
||||
Serial.println(F(" Recieved: an empty ACK packet")); // empty ACK packet received
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
Serial.println(F("Transmission failed or timed out")); // payload was not delivered
|
||||
}
|
||||
|
||||
// to make this example readable in the serial monitor
|
||||
delay(1000); // slow transmissions down by 1 second
|
||||
|
||||
} else {
|
||||
// This device is a RX node
|
||||
|
||||
uint8_t pipe;
|
||||
if (radio.available(&pipe)) { // is there a payload? get the pipe number that recieved it
|
||||
uint8_t bytes = radio.getDynamicPayloadSize(); // get the size of the payload
|
||||
PayloadStruct received;
|
||||
radio.read(&received, sizeof(received)); // get incoming payload
|
||||
Serial.print(F("Received "));
|
||||
Serial.print(bytes); // print the size of the payload
|
||||
Serial.print(F(" bytes on pipe "));
|
||||
Serial.print(pipe); // print the pipe number
|
||||
Serial.print(F(": "));
|
||||
Serial.print(received.message); // print incoming message
|
||||
Serial.print(received.counter); // print incoming counter
|
||||
Serial.print(F(" Sent: "));
|
||||
Serial.print(payload.message); // print outgoing message
|
||||
Serial.println(payload.counter); // print outgoing counter
|
||||
|
||||
// save incoming counter & increment for next outgoing
|
||||
payload.counter = received.counter + 1;
|
||||
// load the payload for the first received transmission on pipe 0
|
||||
radio.writeAckPayload(1, &payload, sizeof(payload));
|
||||
}
|
||||
} // role
|
||||
|
||||
if (Serial.available()) {
|
||||
// change the role via the serial monitor
|
||||
|
||||
char c = toupper(Serial.read());
|
||||
if (c == 'T' && !role) {
|
||||
// Become the TX node
|
||||
|
||||
role = true;
|
||||
Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
|
||||
|
||||
memcpy(payload.message, "Hello ", 6); // change payload message
|
||||
radio.stopListening(); // this also discards any unused ACK payloads
|
||||
|
||||
} else if (c == 'R' && role) {
|
||||
// Become the RX node
|
||||
|
||||
role = false;
|
||||
Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
|
||||
memcpy(payload.message, "World ", 6); // change payload message
|
||||
|
||||
// load the payload for the first received transmission on pipe 0
|
||||
radio.writeAckPayload(1, &payload, sizeof(PayloadStruct));
|
||||
radio.startListening();
|
||||
}
|
||||
}
|
||||
} // loop
|
154
src/libs/RF24-master/examples/GettingStarted/GettingStarted.ino
Normal file
154
src/libs/RF24-master/examples/GettingStarted/GettingStarted.ino
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* See documentation at https://nRF24.github.io/RF24
|
||||
* See License information at root directory of this library
|
||||
* Author: Brendan Doherty (2bndy5)
|
||||
*/
|
||||
|
||||
/**
|
||||
* A simple example of sending data from 1 nRF24L01 transceiver to another.
|
||||
*
|
||||
* This example was written to be used on 2 devices acting as "nodes".
|
||||
* Use the Serial Monitor to change each node's behavior.
|
||||
*/
|
||||
#include <SPI.h>
|
||||
#include "printf.h"
|
||||
#include "RF24.h"
|
||||
|
||||
// instantiate an object for the nRF24L01 transceiver
|
||||
RF24 radio(7, 8); // using pin 7 for the CE pin, and pin 8 for the CSN pin
|
||||
|
||||
// Let these addresses be used for the pair
|
||||
uint8_t address[][6] = {"1Node", "2Node"};
|
||||
// It is very helpful to think of an address as a path instead of as
|
||||
// an identifying device destination
|
||||
|
||||
// to use different addresses on a pair of radios, we need a variable to
|
||||
// uniquely identify which address this radio will use to transmit
|
||||
bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
|
||||
// Used to control whether this node is sending or receiving
|
||||
bool role = false; // true = TX role, false = RX role
|
||||
|
||||
// For this example, we'll be using a payload containing
|
||||
// a single float number that will be incremented
|
||||
// on every successful transmission
|
||||
float payload = 0.0;
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
while (!Serial) {
|
||||
// some boards need to wait to ensure access to serial over USB
|
||||
}
|
||||
|
||||
// initialize the transceiver on the SPI bus
|
||||
if (!radio.begin()) {
|
||||
Serial.println(F("radio hardware is not responding!!"));
|
||||
while (1) {} // hold in infinite loop
|
||||
}
|
||||
|
||||
// print example's introductory prompt
|
||||
Serial.println(F("RF24/examples/GettingStarted"));
|
||||
|
||||
// To set the radioNumber via the Serial monitor on startup
|
||||
Serial.println(F("Which radio is this? Enter '0' or '1'. Defaults to '0'"));
|
||||
while (!Serial.available()) {
|
||||
// wait for user input
|
||||
}
|
||||
char input = Serial.parseInt();
|
||||
radioNumber = input == 1;
|
||||
Serial.print(F("radioNumber = "));
|
||||
Serial.println((int)radioNumber);
|
||||
|
||||
// role variable is hardcoded to RX behavior, inform the user of this
|
||||
Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
|
||||
|
||||
// Set the PA Level low to try preventing power supply related problems
|
||||
// because these examples are likely run with nodes in close proximity to
|
||||
// each other.
|
||||
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
|
||||
|
||||
// save on transmission time by setting the radio to only transmit the
|
||||
// number of bytes we need to transmit a float
|
||||
radio.setPayloadSize(sizeof(payload)); // float datatype occupies 4 bytes
|
||||
|
||||
// set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radioNumber]); // always uses pipe 0
|
||||
|
||||
// set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1
|
||||
|
||||
// additional setup specific to the node's role
|
||||
if (role) {
|
||||
radio.stopListening(); // put radio in TX mode
|
||||
} else {
|
||||
radio.startListening(); // put radio in RX mode
|
||||
}
|
||||
|
||||
// For debugging info
|
||||
// printf_begin(); // needed only once for printing details
|
||||
// radio.printDetails(); // (smaller) function that prints raw register values
|
||||
// radio.printPrettyDetails(); // (larger) function that prints human readable data
|
||||
|
||||
} // setup
|
||||
|
||||
void loop() {
|
||||
|
||||
if (role) {
|
||||
// This device is a TX node
|
||||
|
||||
unsigned long start_timer = micros(); // start the timer
|
||||
bool report = radio.write(&payload, sizeof(float)); // transmit & save the report
|
||||
unsigned long end_timer = micros(); // end the timer
|
||||
|
||||
if (report) {
|
||||
Serial.print(F("Transmission successful! ")); // payload was delivered
|
||||
Serial.print(F("Time to transmit = "));
|
||||
Serial.print(end_timer - start_timer); // print the timer result
|
||||
Serial.print(F(" us. Sent: "));
|
||||
Serial.println(payload); // print payload sent
|
||||
payload += 0.01; // increment float payload
|
||||
} else {
|
||||
Serial.println(F("Transmission failed or timed out")); // payload was not delivered
|
||||
}
|
||||
|
||||
// to make this example readable in the serial monitor
|
||||
delay(1000); // slow transmissions down by 1 second
|
||||
|
||||
} else {
|
||||
// This device is a RX node
|
||||
|
||||
uint8_t pipe;
|
||||
if (radio.available(&pipe)) { // is there a payload? get the pipe number that recieved it
|
||||
uint8_t bytes = radio.getPayloadSize(); // get the size of the payload
|
||||
radio.read(&payload, bytes); // fetch payload from FIFO
|
||||
Serial.print(F("Received "));
|
||||
Serial.print(bytes); // print the size of the payload
|
||||
Serial.print(F(" bytes on pipe "));
|
||||
Serial.print(pipe); // print the pipe number
|
||||
Serial.print(F(": "));
|
||||
Serial.println(payload); // print the payload's value
|
||||
}
|
||||
} // role
|
||||
|
||||
if (Serial.available()) {
|
||||
// change the role via the serial monitor
|
||||
|
||||
char c = toupper(Serial.read());
|
||||
if (c == 'T' && !role) {
|
||||
// Become the TX node
|
||||
|
||||
role = true;
|
||||
Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
|
||||
radio.stopListening();
|
||||
|
||||
} else if (c == 'R' && role) {
|
||||
// Become the RX node
|
||||
|
||||
role = false;
|
||||
Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
|
||||
radio.startListening();
|
||||
}
|
||||
}
|
||||
|
||||
} // loop
|
@ -0,0 +1,346 @@
|
||||
/*
|
||||
* See documentation at https://nRF24.github.io/RF24
|
||||
* See License information at root directory of this library
|
||||
* Author: Brendan Doherty (2bndy5)
|
||||
*/
|
||||
|
||||
/**
|
||||
* This example uses Acknowledgement (ACK) payloads attached to ACK packets to
|
||||
* demonstrate how the nRF24L01's IRQ (Interrupt Request) pin can be
|
||||
* configured to detect when data is received, or when data has transmitted
|
||||
* successfully, or when data has failed to transmit.
|
||||
*
|
||||
* This example was written to be used on 2 devices acting as "nodes".
|
||||
* Use the Serial Monitor to change each node's behavior.
|
||||
*/
|
||||
#include <SPI.h>
|
||||
#include "printf.h"
|
||||
#include "RF24.h"
|
||||
|
||||
// We will be using the nRF24L01's IRQ pin for this example
|
||||
#define IRQ_PIN 2 // this needs to be a digital input capable pin
|
||||
volatile bool wait_for_event = false; // used to wait for an IRQ event to trigger
|
||||
|
||||
// instantiate an object for the nRF24L01 transceiver
|
||||
RF24 radio(7, 8); // using pin 7 for the CE pin, and pin 8 for the CSN pin
|
||||
|
||||
// Let these addresses be used for the pair
|
||||
uint8_t address[][6] = {"1Node", "2Node"};
|
||||
// It is very helpful to think of an address as a path instead of as
|
||||
// an identifying device destination
|
||||
|
||||
// to use different addresses on a pair of radios, we need a variable to
|
||||
// uniquely identify which address this radio will use to transmit
|
||||
bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
|
||||
// Used to control whether this node is sending or receiving
|
||||
bool role = false; // true = TX node, false = RX node
|
||||
|
||||
// For this example, we'll be using a payload containing
|
||||
// a string that changes on every transmission. (successful or not)
|
||||
// Make a couple arrays of payloads & an iterator to traverse them
|
||||
const uint8_t tx_pl_size = 5;
|
||||
const uint8_t ack_pl_size = 4;
|
||||
uint8_t pl_iterator = 0;
|
||||
// The " + 1" compensates for the c-string's NULL terminating 0
|
||||
char tx_payloads[][tx_pl_size + 1] = {"Ping ", "Pong ", "Radio", "1FAIL"};
|
||||
char ack_payloads[][ack_pl_size + 1] = {"Yak ", "Back", " ACK"};
|
||||
|
||||
void interruptHandler(); // prototype to handle IRQ events
|
||||
void printRxFifo(); // prototype to print RX FIFO with 1 buffer
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial) {
|
||||
// some boards need to wait to ensure access to serial over USB
|
||||
}
|
||||
|
||||
// initialize the transceiver on the SPI bus
|
||||
if (!radio.begin()) {
|
||||
Serial.println(F("radio hardware is not responding!!"));
|
||||
while (1) {} // hold in infinite loop
|
||||
}
|
||||
|
||||
// print example's introductory prompt
|
||||
Serial.println(F("RF24/examples/InterruptConfigure"));
|
||||
|
||||
// To set the radioNumber via the Serial monitor on startup
|
||||
Serial.println(F("Which radio is this? Enter '0' or '1'. Defaults to '0'"));
|
||||
while (!Serial.available()) {
|
||||
// wait for user input
|
||||
}
|
||||
char input = Serial.parseInt();
|
||||
radioNumber = input == 1;
|
||||
Serial.print(F("radioNumber = "));
|
||||
Serial.println((int)radioNumber);
|
||||
|
||||
// role variable is hardcoded to RX behavior, inform the user of this
|
||||
Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
|
||||
|
||||
// setup the IRQ_PIN
|
||||
pinMode(IRQ_PIN, INPUT);
|
||||
attachInterrupt(digitalPinToInterrupt(IRQ_PIN), interruptHandler, FALLING);
|
||||
// IMPORTANT: do not call radio.available() before calling
|
||||
// radio.whatHappened() when the interruptHandler() is triggered by the
|
||||
// IRQ pin FALLING event. According to the datasheet, the pipe information
|
||||
// is unreliable during the IRQ pin FALLING transition.
|
||||
|
||||
// Set the PA Level low to try preventing power supply related problems
|
||||
// because these examples are likely run with nodes in close proximity to
|
||||
// each other.
|
||||
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
|
||||
|
||||
// For this example we use acknowledgment (ACK) payloads to trigger the
|
||||
// IRQ pin when data is received on the TX node.
|
||||
// to use ACK payloads, we need to enable dynamic payload lengths
|
||||
radio.enableDynamicPayloads(); // ACK payloads are dynamically sized
|
||||
|
||||
// Acknowledgement packets have no payloads by default. We need to enable
|
||||
// this feature for all nodes (TX & RX) to use ACK payloads.
|
||||
radio.enableAckPayload();
|
||||
// Fot this example, we use the same address to send data back and forth
|
||||
|
||||
// set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radioNumber]); // always uses pipe 0
|
||||
|
||||
// set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1
|
||||
|
||||
// additional setup specific to the node's role
|
||||
if (role) {
|
||||
// setup for TX mode
|
||||
radio.stopListening(); // put radio in TX mode
|
||||
|
||||
} else {
|
||||
// setup for RX mode
|
||||
|
||||
// let IRQ pin only trigger on "data ready" event in RX mode
|
||||
radio.maskIRQ(1, 1, 0); // args = "data_sent", "data_fail", "data_ready"
|
||||
|
||||
// Fill the TX FIFO with 3 ACK payloads for the first 3 received
|
||||
// transmissions on pipe 1
|
||||
radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
|
||||
radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
|
||||
radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);
|
||||
|
||||
radio.startListening(); // put radio in RX mode
|
||||
}
|
||||
|
||||
// For debugging info
|
||||
// printf_begin(); // needed only once for printing details
|
||||
// radio.printDetails(); // (smaller) function that prints raw register values
|
||||
// radio.printPrettyDetails(); // (larger) function that prints human readable data
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (role && !wait_for_event) {
|
||||
|
||||
// delay(1); // wait for IRQ pin to fully RISE
|
||||
|
||||
// This device is a TX node. This if block is only triggered when
|
||||
// NOT waiting for an IRQ event to happen
|
||||
|
||||
if (pl_iterator == 0) {
|
||||
// Test the "data ready" event with the IRQ pin
|
||||
|
||||
Serial.println(F("\nConfiguring IRQ pin to ignore the 'data sent' event"));
|
||||
radio.maskIRQ(true, false, false); // args = "data_sent", "data_fail", "data_ready"
|
||||
Serial.println(F(" Pinging RX node for 'data ready' event..."));
|
||||
|
||||
} else if (pl_iterator == 1) {
|
||||
// Test the "data sent" event with the IRQ pin
|
||||
|
||||
Serial.println(F("\nConfiguring IRQ pin to ignore the 'data ready' event"));
|
||||
radio.maskIRQ(false, false, true); // args = "data_sent", "data_fail", "data_ready"
|
||||
Serial.println(F(" Pinging RX node for 'data sent' event..."));
|
||||
|
||||
} else if (pl_iterator == 2) {
|
||||
// Use this iteration to fill the RX node's FIFO which sets us up for the next test.
|
||||
|
||||
// write() uses virtual interrupt flags that work despite the masking of the IRQ pin
|
||||
radio.maskIRQ(1, 1, 1); // disable IRQ masking for this step
|
||||
|
||||
Serial.println(F("\nSending 1 payload to fill RX node's FIFO. IRQ pin is neglected."));
|
||||
// write() will call flush_tx() on 'data fail' events
|
||||
if (radio.write(&tx_payloads[pl_iterator], tx_pl_size)) {
|
||||
if (radio.rxFifoFull()) {
|
||||
Serial.println(F("RX node's FIFO is full; it is not listening any more"));
|
||||
} else {
|
||||
Serial.println("Transmission successful, but the RX node might still be listening.");
|
||||
}
|
||||
} else {
|
||||
Serial.println(F("Transmission failed or timed out. Continuing anyway."));
|
||||
radio.flush_tx(); // discard payload(s) that failed to transmit
|
||||
}
|
||||
|
||||
} else if (pl_iterator == 3) {
|
||||
// test the "data fail" event with the IRQ pin
|
||||
|
||||
Serial.println(F("\nConfiguring IRQ pin to reflect all events"));
|
||||
radio.maskIRQ(0, 0, 0); // args = "data_sent", "data_fail", "data_ready"
|
||||
Serial.println(F(" Pinging inactive RX node for 'data fail' event..."));
|
||||
}
|
||||
|
||||
if (pl_iterator < 4 && pl_iterator != 2) {
|
||||
|
||||
// IRQ pin is LOW when activated. Otherwise it is always HIGH
|
||||
// Wait until IRQ pin is activated.
|
||||
wait_for_event = true;
|
||||
|
||||
// use the non-blocking call to write a payload and begin transmission
|
||||
// the "false" argument means we are expecting an ACK packet response
|
||||
radio.startFastWrite(tx_payloads[pl_iterator++], tx_pl_size, false);
|
||||
|
||||
// In this example, the "data fail" event is always configured to
|
||||
// trigger the IRQ pin active. Because the auto-ACK feature is on by
|
||||
// default, we don't need a timeout check to prevent an infinite loop.
|
||||
|
||||
} else if (pl_iterator == 4) {
|
||||
// all IRQ tests are done; flush_tx() and print the ACK payloads for fun
|
||||
|
||||
// CE pin is still HIGH which consumes more power. Example is now idling so...
|
||||
radio.stopListening(); // ensure CE pin is LOW
|
||||
// stopListening() also calls flush_tx() when ACK payloads are enabled
|
||||
|
||||
printRxFifo();
|
||||
pl_iterator++;
|
||||
|
||||
|
||||
// inform user what to do next
|
||||
Serial.println(F("\n*** PRESS 'T' to restart the transmissions"));
|
||||
Serial.println(F("*** PRESS 'R' to change to Receive role\n"));
|
||||
|
||||
|
||||
} else if (pl_iterator == 2) {
|
||||
pl_iterator++; // proceed from step 3 to last step (stop at step 4 for readability)
|
||||
}
|
||||
|
||||
} else if (!role) {
|
||||
// This device is a RX node
|
||||
|
||||
if (radio.rxFifoFull()) {
|
||||
// wait until RX FIFO is full then stop listening
|
||||
|
||||
delay(100); // let ACK payload finish transmitting
|
||||
radio.stopListening(); // also discards unused ACK payloads
|
||||
printRxFifo(); // flush the RX FIFO
|
||||
|
||||
// Fill the TX FIFO with 3 ACK payloads for the first 3 received
|
||||
// transmissions on pipe 1.
|
||||
radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
|
||||
radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
|
||||
radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);
|
||||
|
||||
delay(100); // let TX node finish its role
|
||||
radio.startListening(); // We're ready to start over. Begin listening.
|
||||
}
|
||||
|
||||
} // role
|
||||
|
||||
if (Serial.available()) {
|
||||
// change the role via the serial monitor
|
||||
|
||||
char c = toupper(Serial.read());
|
||||
if (c == 'T') {
|
||||
// Become the TX node
|
||||
if (!role)
|
||||
Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
|
||||
else
|
||||
Serial.println(F("*** RESTARTING IRQ PIN TEST ***"));
|
||||
|
||||
role = true;
|
||||
wait_for_event = false;
|
||||
pl_iterator = 0; // reset the iterator
|
||||
radio.flush_tx(); // discard any payloads in the TX FIFO
|
||||
|
||||
// startListening() clears the IRQ masks also. This is required for
|
||||
// continued TX operations when a transmission fails.
|
||||
radio.stopListening(); // this also discards any unused ACK payloads
|
||||
|
||||
} else if (c == 'R' && role) {
|
||||
// Become the RX node
|
||||
Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
|
||||
|
||||
role = false;
|
||||
|
||||
radio.maskIRQ(0, 0, 0); // the IRQ pin should only trigger on "data ready" event
|
||||
|
||||
// Fill the TX FIFO with 3 ACK payloads for the first 3 received
|
||||
// transmissions on pipe 1
|
||||
radio.flush_tx(); // make sure there is room for 3 new ACK payloads
|
||||
radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
|
||||
radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
|
||||
radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);
|
||||
radio.startListening();
|
||||
}
|
||||
} // Serial.available()
|
||||
} // loop
|
||||
|
||||
|
||||
/**
|
||||
* when the IRQ pin goes active LOW, call this fuction print out why
|
||||
*/
|
||||
void interruptHandler() {
|
||||
// print IRQ status and all masking flags' states
|
||||
|
||||
Serial.println(F("\tIRQ pin is actively LOW")); // show that this function was called
|
||||
delayMicroseconds(250);
|
||||
bool tx_ds, tx_df, rx_dr; // declare variables for IRQ masks
|
||||
radio.whatHappened(tx_ds, tx_df, rx_dr); // get values for IRQ masks
|
||||
// whatHappened() clears the IRQ masks also. This is required for
|
||||
// continued TX operations when a transmission fails.
|
||||
// clearing the IRQ masks resets the IRQ pin to its inactive state (HIGH)
|
||||
|
||||
Serial.print(F("\tdata_sent: "));
|
||||
Serial.print(tx_ds); // print "data sent" mask state
|
||||
Serial.print(F(", data_fail: "));
|
||||
Serial.print(tx_df); // print "data fail" mask state
|
||||
Serial.print(F(", data_ready: "));
|
||||
Serial.println(rx_dr); // print "data ready" mask state
|
||||
|
||||
if (tx_df) // if TX payload failed
|
||||
radio.flush_tx(); // clear all payloads from the TX FIFO
|
||||
|
||||
// print if test passed or failed. Unintentional fails mean the RX node was not listening.
|
||||
// pl_iterator has already been incremented by now
|
||||
if (pl_iterator <= 1) {
|
||||
Serial.print(F(" 'Data Ready' event test "));
|
||||
Serial.println(rx_dr ? F("passed") : F("failed"));
|
||||
} else if (pl_iterator == 2) {
|
||||
Serial.print(F(" 'Data Sent' event test "));
|
||||
Serial.println(tx_ds ? F("passed") : F("failed"));
|
||||
} else if (pl_iterator == 4) {
|
||||
Serial.print(F(" 'Data Fail' event test "));
|
||||
Serial.println(tx_df ? F("passed") : F("failed"));
|
||||
}
|
||||
wait_for_event = false; // ready to continue with loop() operations
|
||||
} // interruptHandler
|
||||
|
||||
|
||||
/**
|
||||
* Print the entire RX FIFO with one buffer. This will also flush the RX FIFO.
|
||||
* Remember that the payload sizes are declared as tx_pl_size and ack_pl_size.
|
||||
*/
|
||||
void printRxFifo() {
|
||||
if (radio.available()) { // if there is data in the RX FIFO
|
||||
// to flush the data from the RX FIFO, we'll fetch it all using 1 buffer
|
||||
|
||||
uint8_t pl_size = !role ? tx_pl_size : ack_pl_size;
|
||||
char rx_fifo[pl_size * 3 + 1]; // RX FIFO is full & we know ACK payloads' size
|
||||
if (radio.rxFifoFull()) {
|
||||
rx_fifo[pl_size * 3] = 0; // add a NULL terminating char to use as a c-string
|
||||
radio.read(&rx_fifo, pl_size * 3); // this clears the RX FIFO (for this example)
|
||||
} else {
|
||||
uint8_t i = 0;
|
||||
while (radio.available()) {
|
||||
radio.read(&rx_fifo + (i * pl_size), pl_size);
|
||||
i++;
|
||||
}
|
||||
rx_fifo[i * pl_size] = 0; // add a NULL terminating char to use as a c-string
|
||||
}
|
||||
Serial.print(F("Complete RX FIFO: "));
|
||||
Serial.println(rx_fifo); // print the entire RX FIFO with 1 buffer
|
||||
}
|
||||
}
|
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* See documentation at https://nRF24.github.io/RF24
|
||||
* See License information at root directory of this library
|
||||
* Author: Brendan Doherty (2bndy5)
|
||||
*/
|
||||
|
||||
/**
|
||||
* A simple example of sending data from 1 nRF24L01 transceiver to another
|
||||
* with manually transmitted (non-automatic) Acknowledgement (ACK) payloads.
|
||||
* This example still uses ACK packets, but they have no payloads. Instead the
|
||||
* acknowledging response is sent with `write()`. This tactic allows for more
|
||||
* updated acknowledgement payload data, where actual ACK payloads' data are
|
||||
* outdated by 1 transmission because they have to loaded before receiving a
|
||||
* transmission.
|
||||
*
|
||||
* This example was written to be used on 2 devices acting as "nodes".
|
||||
* Use the Serial Monitor to change each node's behavior.
|
||||
*/
|
||||
#include <SPI.h>
|
||||
#include "printf.h"
|
||||
#include "RF24.h"
|
||||
|
||||
// instantiate an object for the nRF24L01 transceiver
|
||||
RF24 radio(7, 8); // using pin 7 for the CE pin, and pin 8 for the CSN pin
|
||||
|
||||
// Let these addresses be used for the pair
|
||||
uint8_t address[][6] = {"1Node", "2Node"};
|
||||
// It is very helpful to think of an address as a path instead of as
|
||||
// an identifying device destination
|
||||
|
||||
// to use different addresses on a pair of radios, we need a variable to
|
||||
// uniquely identify which address this radio will use to transmit
|
||||
bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
|
||||
// Used to control whether this node is sending or receiving
|
||||
bool role = false; // true = TX node, false = RX node
|
||||
|
||||
// For this example, we'll be using a payload containing
|
||||
// a string & an integer number that will be incremented
|
||||
// on every successful transmission.
|
||||
// Make a data structure to store the entire payload of different datatypes
|
||||
struct PayloadStruct {
|
||||
char message[7]; // only using 6 characters for TX & RX payloads
|
||||
uint8_t counter;
|
||||
};
|
||||
PayloadStruct payload;
|
||||
|
||||
void setup() {
|
||||
|
||||
// append a NULL terminating character for printing as a c-string
|
||||
payload.message[6] = 0;
|
||||
|
||||
Serial.begin(115200);
|
||||
while (!Serial) {
|
||||
// some boards need to wait to ensure access to serial over USB
|
||||
}
|
||||
|
||||
// initialize the transceiver on the SPI bus
|
||||
if (!radio.begin()) {
|
||||
Serial.println(F("radio hardware is not responding!!"));
|
||||
while (1) {} // hold in infinite loop
|
||||
}
|
||||
|
||||
// print example's introductory prompt
|
||||
Serial.println(F("RF24/examples/ManualAcknowledgements"));
|
||||
|
||||
// To set the radioNumber via the Serial monitor on startup
|
||||
Serial.println(F("Which radio is this? Enter '0' or '1'. Defaults to '0'"));
|
||||
while (!Serial.available()) {
|
||||
// wait for user input
|
||||
}
|
||||
char input = Serial.parseInt();
|
||||
radioNumber = input == 1;
|
||||
Serial.print(F("radioNumber = "));
|
||||
Serial.println((int)radioNumber);
|
||||
|
||||
// role variable is hardcoded to RX behavior, inform the user of this
|
||||
Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
|
||||
|
||||
// Set the PA Level low to try preventing power supply related problems
|
||||
// because these examples are likely run with nodes in close proximity to
|
||||
// each other.
|
||||
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
|
||||
|
||||
// save on transmission time by setting the radio to only transmit the
|
||||
// number of bytes we need to transmit a float
|
||||
radio.setPayloadSize(sizeof(payload)); // char[7] & uint8_t datatypes occupy 8 bytes
|
||||
|
||||
// set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radioNumber]); // always uses pipe 0
|
||||
|
||||
// set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1
|
||||
|
||||
if (role) {
|
||||
// setup the TX node
|
||||
|
||||
memcpy(payload.message, "Hello ", 6); // set the outgoing message
|
||||
radio.stopListening(); // put radio in TX mode
|
||||
} else {
|
||||
// setup the RX node
|
||||
|
||||
memcpy(payload.message, "World ", 6); // set the outgoing message
|
||||
radio.startListening(); // put radio in RX mode
|
||||
}
|
||||
|
||||
// For debugging info
|
||||
// printf_begin(); // needed only once for printing details
|
||||
// radio.printDetails(); // (smaller) function that prints raw register values
|
||||
// radio.printPrettyDetails(); // (larger) function that prints human readable data
|
||||
|
||||
} // setup()
|
||||
|
||||
void loop() {
|
||||
|
||||
if (role) {
|
||||
// This device is a TX node
|
||||
|
||||
unsigned long start_timer = micros(); // start the timer
|
||||
bool report = radio.write(&payload, sizeof(payload)); // transmit & save the report
|
||||
|
||||
if (report) {
|
||||
// transmission successful; wait for response and print results
|
||||
|
||||
radio.startListening(); // put in RX mode
|
||||
unsigned long start_timeout = millis(); // timer to detect timeout
|
||||
while (!radio.available()) { // wait for response
|
||||
if (millis() - start_timeout > 200) // only wait 200 ms
|
||||
break;
|
||||
}
|
||||
unsigned long end_timer = micros(); // end the timer
|
||||
radio.stopListening(); // put back in TX mode
|
||||
|
||||
// print summary of transactions
|
||||
Serial.print(F("Transmission successful!")); // payload was delivered
|
||||
uint8_t pipe;
|
||||
if (radio.available(&pipe)) { // is there a payload received
|
||||
Serial.print(F(" Round-trip delay: "));
|
||||
Serial.print(end_timer - start_timer); // print the timer result
|
||||
Serial.print(F(" us. Sent: "));
|
||||
Serial.print(payload.message); // print the outgoing payload's message
|
||||
Serial.print(payload.counter); // print outgoing payload's counter
|
||||
PayloadStruct received;
|
||||
radio.read(&received, sizeof(received)); // get payload from RX FIFO
|
||||
Serial.print(F(" Received "));
|
||||
Serial.print(radio.getPayloadSize()); // print the size of the payload
|
||||
Serial.print(F(" bytes on pipe "));
|
||||
Serial.print(pipe); // print the pipe number
|
||||
Serial.print(F(": "));
|
||||
Serial.print(received.message); // print the incoming payload's message
|
||||
Serial.println(received.counter); // print the incoming payload's counter
|
||||
payload.counter = received.counter; // save incoming counter for next outgoing counter
|
||||
} else {
|
||||
Serial.println(F(" Recieved no response.")); // no response received
|
||||
}
|
||||
} else {
|
||||
Serial.println(F("Transmission failed or timed out")); // payload was not delivered
|
||||
} // report
|
||||
|
||||
// to make this example readable in the serial monitor
|
||||
delay(1000); // slow transmissions down by 1 second
|
||||
|
||||
} else {
|
||||
// This device is a RX node
|
||||
|
||||
uint8_t pipe;
|
||||
if (radio.available(&pipe)) { // is there a payload? get the pipe number that recieved it
|
||||
PayloadStruct received;
|
||||
radio.read(&received, sizeof(received)); // get incoming payload
|
||||
payload.counter = received.counter + 1; // increment incoming counter for next outgoing response
|
||||
|
||||
// transmit response & save result to `report`
|
||||
radio.stopListening(); // put in TX mode
|
||||
|
||||
radio.writeFast(&payload, sizeof(payload)); // load response to TX FIFO
|
||||
bool report = radio.txStandBy(150); // keep retrying for 150 ms
|
||||
|
||||
radio.startListening(); // put back in RX mode
|
||||
|
||||
// print summary of transactions
|
||||
Serial.print(F("Received "));
|
||||
Serial.print(radio.getPayloadSize()); // print the size of the payload
|
||||
Serial.print(F(" bytes on pipe "));
|
||||
Serial.print(pipe); // print the pipe number
|
||||
Serial.print(F(": "));
|
||||
Serial.print(received.message); // print incoming message
|
||||
Serial.print(received.counter); // print incoming counter
|
||||
|
||||
if (report) {
|
||||
Serial.print(F(" Sent: "));
|
||||
Serial.print(payload.message); // print outgoing message
|
||||
Serial.println(payload.counter); // print outgoing counter
|
||||
} else {
|
||||
Serial.println(" Response failed."); // failed to send response
|
||||
}
|
||||
}
|
||||
} // role
|
||||
|
||||
if (Serial.available()) {
|
||||
// change the role via the serial monitor
|
||||
|
||||
char c = toupper(Serial.read());
|
||||
if (c == 'T' && !role) {
|
||||
// Become the TX node
|
||||
|
||||
role = true;
|
||||
memcpy(payload.message, "Hello ", 6); // set the outgoing message
|
||||
Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
|
||||
radio.stopListening(); // put in TX mode
|
||||
|
||||
} else if (c == 'R' && role) {
|
||||
// Become the RX node
|
||||
|
||||
role = false;
|
||||
memcpy(payload.message, "World ", 6); // set the response message
|
||||
Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
|
||||
radio.startListening(); // put in RX mode
|
||||
}
|
||||
}
|
||||
} // loop
|
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* See documentation at https://nRF24.github.io/RF24
|
||||
* See License information at root directory of this library
|
||||
* Author: Brendan Doherty 2bndy5
|
||||
*/
|
||||
|
||||
/**
|
||||
* A simple example of sending data from as many as 6 nRF24L01 transceivers to
|
||||
* 1 receiving transceiver. This technique is trademarked by
|
||||
* Nordic Semiconductors as "MultiCeiver".
|
||||
*
|
||||
* This example was written to be used on up to 6 devices acting as TX nodes &
|
||||
* only 1 device acting as the RX node (that's a maximum of 7 devices).
|
||||
* Use the Serial Monitor to change each node's behavior.
|
||||
*/
|
||||
#include <SPI.h>
|
||||
#include "printf.h"
|
||||
#include "RF24.h"
|
||||
|
||||
// instantiate an object for the nRF24L01 transceiver
|
||||
RF24 radio(7, 8); // using pin 7 for the CE pin, and pin 8 for the CSN pin
|
||||
|
||||
// For this example, we'll be using 6 addresses; 1 for each TX node
|
||||
// It is very helpful to think of an address as a path instead of as
|
||||
// an identifying device destination
|
||||
// Notice that the last byte is the only byte that changes in the last 5
|
||||
// addresses. This is a limitation of the nRF24L01 transceiver for pipes 2-5
|
||||
// because they use the same first 4 bytes from pipe 1.
|
||||
uint64_t address[6] = {0x7878787878LL,
|
||||
0xB3B4B5B6F1LL,
|
||||
0xB3B4B5B6CDLL,
|
||||
0xB3B4B5B6A3LL,
|
||||
0xB3B4B5B60FLL,
|
||||
0xB3B4B5B605LL
|
||||
};
|
||||
|
||||
// Because this example allow up to 6 nodes (specified by numbers 0-5) to
|
||||
// transmit and only 1 node to receive, we will use a negative value in our
|
||||
// role variable to signify this node is a receiver.
|
||||
// role variable is used to control whether this node is sending or receiving
|
||||
char role = 'R'; // 0-5 = TX node; any negative number = RX node
|
||||
|
||||
// For this example, we'll be using a payload containing
|
||||
// a node ID number and a single integer number that will be incremented
|
||||
// on every successful transmission.
|
||||
// Make a data structure to use as a payload.
|
||||
struct PayloadStruct
|
||||
{
|
||||
unsigned long nodeID;
|
||||
unsigned long payloadID;
|
||||
};
|
||||
PayloadStruct payload;
|
||||
|
||||
// This example uses all 6 pipes to receive while TX nodes only use 2 pipes
|
||||
// To make this easier we'll use a function to manage the addresses, and the
|
||||
// payload's nodeID
|
||||
void setRole(); // declare a prototype; definition is found after the loop()
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
while (!Serial) {
|
||||
// some boards need to wait to ensure access to serial over USB
|
||||
}
|
||||
|
||||
// initialize the transceiver on the SPI bus
|
||||
if (!radio.begin()) {
|
||||
Serial.println(F("radio hardware is not responding!!"));
|
||||
while (1) {} // hold in infinite loop
|
||||
}
|
||||
|
||||
// print example's introductory prompt
|
||||
Serial.println(F("RF24/examples/MulticeiverDemo"));
|
||||
Serial.println(F("*** Enter a number between 0 and 5 (inclusive) to change"));
|
||||
Serial.println(F(" the identifying node number that transmits."));
|
||||
|
||||
// Set the PA Level low to try preventing power supply related problems
|
||||
// because these examples are likely run with nodes in close proximity of
|
||||
// each other.
|
||||
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
|
||||
|
||||
// save on transmission time by setting the radio to only transmit the
|
||||
// number of bytes we need to transmit a float
|
||||
radio.setPayloadSize(sizeof(payload)); // 2x int datatype occupy 8 bytes
|
||||
|
||||
// Set the pipe addresses accordingly. This function additionally also
|
||||
// calls startListening() or stopListening() and sets the payload's nodeID
|
||||
setRole();
|
||||
|
||||
// For debugging info
|
||||
// printf_begin(); // needed only once for printing details
|
||||
// radio.printDetails(); // (smaller) function that prints raw register values
|
||||
// radio.printPrettyDetails(); // (larger) function that prints human readable data
|
||||
|
||||
} // setup()
|
||||
|
||||
void loop() {
|
||||
|
||||
if (role <= 53) {
|
||||
// This device is a TX node
|
||||
|
||||
unsigned long start_timer = micros(); // start the timer
|
||||
bool report = radio.write(&payload, sizeof(payload)); // transmit & save the report
|
||||
unsigned long end_timer = micros(); // end the timer
|
||||
|
||||
if (report) {
|
||||
// payload was delivered
|
||||
|
||||
Serial.print(F("Transmission of payloadID "));
|
||||
Serial.print(payload.payloadID); // print payloadID
|
||||
Serial.print(F(" as node "));
|
||||
Serial.print(payload.nodeID); // print nodeID
|
||||
Serial.print(F(" successful!"));
|
||||
Serial.print(F(" Time to transmit: "));
|
||||
Serial.print(end_timer - start_timer); // print the timer result
|
||||
Serial.println(F(" us"));
|
||||
} else {
|
||||
Serial.println(F("Transmission failed or timed out")); // payload was not delivered
|
||||
}
|
||||
payload.payloadID++; // increment payload number
|
||||
|
||||
// to make this example readable in the serial monitor
|
||||
delay(500); // slow transmissions down by 1 second
|
||||
|
||||
} else if (role == 'R') {
|
||||
// This device is the RX node
|
||||
|
||||
uint8_t pipe;
|
||||
if (radio.available(&pipe)) { // is there a payload? get the pipe number that recieved it
|
||||
uint8_t bytes = radio.getPayloadSize(); // get the size of the payload
|
||||
radio.read(&payload, bytes); // fetch payload from FIFO
|
||||
Serial.print(F("Received "));
|
||||
Serial.print(bytes); // print the size of the payload
|
||||
Serial.print(F(" bytes on pipe "));
|
||||
Serial.print(pipe); // print the pipe number
|
||||
Serial.print(F(" from node "));
|
||||
Serial.print(payload.nodeID); // print the payload's origin
|
||||
Serial.print(F(". PayloadID: "));
|
||||
Serial.println(payload.payloadID); // print the payload's number
|
||||
}
|
||||
} // role
|
||||
|
||||
if (Serial.available()) {
|
||||
// change the role via the serial monitor
|
||||
|
||||
char c = Serial.read();
|
||||
if (toupper(c) == 'R' && role <= 53) {
|
||||
// Become the RX node
|
||||
|
||||
role = 'R';
|
||||
Serial.println(F("*** CHANGING ROLE TO RECEIVER ***"));
|
||||
Serial.println(F("--- Enter a number between 0 and 5 (inclusive) to act as"));
|
||||
Serial.println(F(" a unique node number that transmits to the RX node."));
|
||||
setRole(); // change address on all pipes to TX nodes
|
||||
|
||||
} else if (c >= 48 && c <= 53 && c != role) {
|
||||
// Become a TX node with identifier 'c'
|
||||
|
||||
role = c - 48;
|
||||
Serial.print(F("*** CHANGING ROLE TO NODE "));
|
||||
Serial.print(c);
|
||||
Serial.println(F(" ***"));
|
||||
Serial.println(F("--- Enter a number between 0 and 5 (inclusive) to change"));
|
||||
Serial.println(F(" the identifying node number that transmits."));
|
||||
Serial.println(F("--- PRESS 'R' to act as the RX node."));
|
||||
setRole(); // change address on pipe 0 to the RX node
|
||||
}
|
||||
}
|
||||
|
||||
} // loop
|
||||
|
||||
void setRole() {
|
||||
if (role == 'R') {
|
||||
// For the RX node
|
||||
|
||||
// Set the addresses for all pipes to TX nodes
|
||||
for (uint8_t i = 0; i < 6; ++i)
|
||||
radio.openReadingPipe(i, address[i]);
|
||||
|
||||
radio.startListening(); // put radio in RX mode
|
||||
|
||||
} else {
|
||||
// For the TX node
|
||||
|
||||
// set the payload's nodeID & reset the payload's identifying number
|
||||
payload.nodeID = role;
|
||||
payload.payloadID = 0;
|
||||
|
||||
// Set the address on pipe 0 to the RX node.
|
||||
radio.stopListening(); // put radio in TX mode
|
||||
radio.openWritingPipe(address[role]);
|
||||
|
||||
// According to the datasheet, the auto-retry features's delay value should
|
||||
// be "skewed" to allow the RX node to receive 1 transmission at a time.
|
||||
// So, use varying delay between retry attempts and 15 (at most) retry attempts
|
||||
radio.setRetries(((role * 3) % 12) + 3, 15); // maximum value is 15 for both args
|
||||
}
|
||||
} // setRole
|
185
src/libs/RF24-master/examples/StreamingData/StreamingData.ino
Normal file
185
src/libs/RF24-master/examples/StreamingData/StreamingData.ino
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* See documentation at https://nRF24.github.io/RF24
|
||||
* See License information at root directory of this library
|
||||
* Author: Brendan Doherty 2bndy5
|
||||
*/
|
||||
|
||||
/**
|
||||
* A simple example of streaming data from 1 nRF24L01 transceiver to another.
|
||||
*
|
||||
* This example was written to be used on 2 devices acting as "nodes".
|
||||
* Use the Serial Monitor to change each node's behavior.
|
||||
*/
|
||||
#include <SPI.h>
|
||||
#include "printf.h"
|
||||
#include "RF24.h"
|
||||
|
||||
// instantiate an object for the nRF24L01 transceiver
|
||||
RF24 radio(7, 8); // using pin 7 for the CE pin, and pin 8 for the CSN pin
|
||||
|
||||
// Let these addresses be used for the pair
|
||||
uint8_t address[][6] = {"1Node", "2Node"};
|
||||
// It is very helpful to think of an address as a path instead of as
|
||||
// an identifying device destination
|
||||
|
||||
// to use different addresses on a pair of radios, we need a variable to
|
||||
// uniquely identify which address this radio will use to transmit
|
||||
bool radioNumber; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
|
||||
// Used to control whether this node is sending or receiving
|
||||
bool role = false; // true = TX node, false = RX node
|
||||
|
||||
// For this example, we'll be sending 32 payloads each containing
|
||||
// 32 bytes of data that looks like ASCII art when printed to the serial
|
||||
// monitor. The TX node and RX node needs only a single 32 byte buffer.
|
||||
#define SIZE 32 // this is the maximum for this example. (minimum is 1)
|
||||
char buffer[SIZE + 1]; // for the RX node
|
||||
uint8_t counter = 0; // for counting the number of received payloads
|
||||
void makePayload(uint8_t); // prototype to construct a payload dynamically
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
buffer[SIZE] = 0; // add a NULL terminating character (for easy printing)
|
||||
|
||||
Serial.begin(115200);
|
||||
while (!Serial) {
|
||||
// some boards need to wait to ensure access to serial over USB
|
||||
}
|
||||
|
||||
// initialize the transceiver on the SPI bus
|
||||
if (!radio.begin()) {
|
||||
Serial.println(F("radio hardware is not responding!!"));
|
||||
while (1) {} // hold in infinite loop
|
||||
}
|
||||
|
||||
// print example's introductory prompt
|
||||
Serial.println(F("RF24/examples/StreamingData"));
|
||||
|
||||
// To set the radioNumber via the Serial monitor on startup
|
||||
Serial.println(F("Which radio is this? Enter '0' or '1'. Defaults to '0'"));
|
||||
while (!Serial.available()) {
|
||||
// wait for user input
|
||||
}
|
||||
char input = Serial.parseInt();
|
||||
radioNumber = input == 1;
|
||||
Serial.print(F("radioNumber = "));
|
||||
Serial.println((int)radioNumber);
|
||||
|
||||
// role variable is hardcoded to RX behavior, inform the user of this
|
||||
Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
|
||||
|
||||
// Set the PA Level low to try preventing power supply related problems
|
||||
// because these examples are likely run with nodes in close proximity to
|
||||
// each other.
|
||||
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
|
||||
|
||||
// save on transmission time by setting the radio to only transmit the
|
||||
// number of bytes we need to transmit
|
||||
radio.setPayloadSize(SIZE); // default value is the maximum 32 bytes
|
||||
|
||||
// set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radioNumber]); // always uses pipe 0
|
||||
|
||||
// set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1
|
||||
|
||||
// additional setup specific to the node's role
|
||||
if (role) {
|
||||
radio.stopListening(); // put radio in TX mode
|
||||
} else {
|
||||
radio.startListening(); // put radio in RX mode
|
||||
}
|
||||
|
||||
// For debugging info
|
||||
// printf_begin(); // needed only once for printing details
|
||||
// radio.printDetails(); // (smaller) function that prints raw register values
|
||||
// radio.printPrettyDetails(); // (larger) function that prints human readable data
|
||||
|
||||
} // setup()
|
||||
|
||||
|
||||
void loop() {
|
||||
|
||||
if (role) {
|
||||
// This device is a TX node
|
||||
|
||||
radio.flush_tx();
|
||||
uint8_t i = 0;
|
||||
uint8_t failures = 0;
|
||||
unsigned long start_timer = micros(); // start the timer
|
||||
while (i < SIZE) {
|
||||
makePayload(i); // make the payload
|
||||
if (!radio.writeFast(&buffer, SIZE)) {
|
||||
failures++;
|
||||
radio.reUseTX();
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
|
||||
if (failures >= 100) {
|
||||
Serial.print(F("Too many failures detected. Aborting at payload "));
|
||||
Serial.println(buffer[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
unsigned long end_timer = micros(); // end the timer
|
||||
|
||||
Serial.print(F("Time to transmit = "));
|
||||
Serial.print(end_timer - start_timer); // print the timer result
|
||||
Serial.print(F(" us with "));
|
||||
Serial.print(failures); // print failures detected
|
||||
Serial.println(F(" failures detected"));
|
||||
|
||||
// to make this example readable in the serial monitor
|
||||
delay(1000); // slow transmissions down by 1 second
|
||||
|
||||
} else {
|
||||
// This device is a RX node
|
||||
|
||||
if (radio.available()) { // is there a payload?
|
||||
radio.read(&buffer, SIZE); // fetch payload from FIFO
|
||||
Serial.print(F("Received: "));
|
||||
Serial.print(buffer); // print the payload's value
|
||||
Serial.print(F(" - "));
|
||||
Serial.println(counter++); // print the received counter
|
||||
}
|
||||
} // role
|
||||
|
||||
if (Serial.available()) {
|
||||
// change the role via the serial monitor
|
||||
|
||||
char c = toupper(Serial.read());
|
||||
if (c == 'T' && !role) {
|
||||
// Become the TX node
|
||||
|
||||
role = true;
|
||||
counter = 0; //reset the RX node's counter
|
||||
Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
|
||||
radio.stopListening();
|
||||
|
||||
} else if (c == 'R' && role) {
|
||||
// Become the RX node
|
||||
|
||||
role = false;
|
||||
Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
|
||||
radio.startListening();
|
||||
}
|
||||
}
|
||||
|
||||
} // loop
|
||||
|
||||
|
||||
void makePayload(uint8_t i) {
|
||||
// Make a single payload based on position in stream.
|
||||
// This example employs function to save memory on certain boards.
|
||||
|
||||
// let the first character be an identifying alphanumeric prefix
|
||||
// this lets us see which payload didn't get received
|
||||
buffer[0] = i + (i < 26 ? 65 : 71);
|
||||
for (uint8_t j = 0; j < SIZE - 1; ++j) {
|
||||
char chr = j >= (SIZE - 1) / 2 + abs((SIZE - 1) / 2 - i);
|
||||
chr |= j < (SIZE - 1) / 2 - abs((SIZE - 1) / 2 - i);
|
||||
buffer[j + 1] = chr + 48;
|
||||
}
|
||||
}
|
31
src/libs/RF24-master/examples/examples_formatter.conf
Normal file
31
src/libs/RF24-master/examples/examples_formatter.conf
Normal file
@ -0,0 +1,31 @@
|
||||
# This configuration file contains a selection of the available options provided by the formatting tool "Artistic Style"
|
||||
# http://astyle.sourceforge.net/astyle.html
|
||||
#
|
||||
# If you wish to change them, don't edit this file.
|
||||
# Instead, copy it in the same folder of file "preferences.txt" and modify the copy. This way, you won't lose your custom formatter settings when upgrading the IDE
|
||||
# If you don't know where file preferences.txt is stored, open the IDE, File -> Preferences and you'll find a link
|
||||
|
||||
mode=c
|
||||
|
||||
# 2 spaces indentation
|
||||
indent=spaces=2
|
||||
|
||||
# also indent macros
|
||||
indent-preprocessor
|
||||
|
||||
# indent classes, switches (and cases), comments starting at column 1
|
||||
indent-classes
|
||||
indent-switches
|
||||
indent-cases
|
||||
indent-col1-comments
|
||||
|
||||
# put a space around operators
|
||||
pad-oper
|
||||
|
||||
# put a space after if/for/while
|
||||
pad-header
|
||||
|
||||
# if you like one-liners, keep them
|
||||
keep-one-line-statements
|
||||
|
||||
# remove-comment-prefix
|
@ -0,0 +1,217 @@
|
||||
|
||||
/*
|
||||
Getting Started example sketch for nRF24L01+ radios
|
||||
This is a very basic example of how to send data from one node to another
|
||||
but modified to include failure handling.
|
||||
|
||||
The nrf24l01+ radios are fairly reliable devices, but on breadboards etc, with inconsistent wiring, failures may
|
||||
occur randomly after many hours to days or weeks. This sketch demonstrates how to handle the various failures and
|
||||
keep the radio operational.
|
||||
|
||||
The three main failure modes of the radio include:
|
||||
Writing to radio: Radio unresponsive - Fixed internally by adding a timeout to the internal write functions in RF24 (failure handling)
|
||||
Reading from radio: Available returns true always - Fixed by adding a timeout to available functions by the user. This is implemented internally in RF24Network.
|
||||
Radio configuration settings are lost - Fixed by monitoring a value that is different from the default, and re-configuring the radio if this setting reverts to the default.
|
||||
|
||||
The printDetails output should appear as follows for radio #0:
|
||||
|
||||
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
|
||||
RX_ADDR_P0-1 = 0x65646f4e31 0x65646f4e32
|
||||
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
|
||||
TX_ADDR = 0x65646f4e31
|
||||
RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00
|
||||
EN_AA = 0x3f
|
||||
EN_RXADDR = 0x02
|
||||
RF_CH = 0x4c
|
||||
RF_SETUP = 0x03
|
||||
CONFIG = 0x0f
|
||||
DYNPD/FEATURE = 0x00 0x00
|
||||
Data Rate = 1MBPS
|
||||
Model = nRF24L01+
|
||||
CRC Length = 16 bits
|
||||
PA Power = PA_LOW
|
||||
|
||||
Users can use this sketch to troubleshoot radio module wiring etc. as it makes the radios hot-swapable
|
||||
|
||||
Updated: 2019 by TMRh20
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include "RF24.h"
|
||||
#include "printf.h"
|
||||
|
||||
/****************** User Config ***************************/
|
||||
/*** Set this radio as radio number 0 or 1 ***/
|
||||
bool radioNumber = 0;
|
||||
|
||||
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7 & 8 */
|
||||
RF24 radio(7, 8);
|
||||
/**********************************************************/
|
||||
|
||||
byte addresses[][6] = {"1Node", "2Node"};
|
||||
|
||||
// Used to control whether this node is sending or receiving
|
||||
bool role = 0;
|
||||
|
||||
|
||||
/**********************************************************/
|
||||
//Function to configure the radio
|
||||
void configureRadio() {
|
||||
|
||||
radio.begin();
|
||||
|
||||
// Set the PA Level low to prevent power supply related issues since this is a
|
||||
// getting_started sketch, and the likelihood of close proximity of the devices. RF24_PA_MAX is default.
|
||||
radio.setPALevel(RF24_PA_LOW);
|
||||
|
||||
// Open a writing and reading pipe on each radio, with opposite addresses
|
||||
if (radioNumber) {
|
||||
radio.openWritingPipe(addresses[1]);
|
||||
radio.openReadingPipe(1, addresses[0]);
|
||||
} else {
|
||||
radio.openWritingPipe(addresses[0]);
|
||||
radio.openReadingPipe(1, addresses[1]);
|
||||
}
|
||||
|
||||
// Start the radio listening for data
|
||||
radio.startListening();
|
||||
radio.printDetails();
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************/
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("RF24/examples/GettingStarted"));
|
||||
Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
|
||||
|
||||
printf_begin();
|
||||
|
||||
configureRadio();
|
||||
}
|
||||
|
||||
uint32_t configTimer = millis();
|
||||
|
||||
void loop() {
|
||||
|
||||
if (radio.failureDetected) {
|
||||
radio.failureDetected = false;
|
||||
delay(250);
|
||||
Serial.println("Radio failure detected, restarting radio");
|
||||
configureRadio();
|
||||
}
|
||||
// Every 5 seconds, verify the configuration of the radio. This can be
|
||||
// done using any setting that is different from the radio defaults.
|
||||
if (millis() - configTimer > 5000) {
|
||||
configTimer = millis();
|
||||
if (radio.getDataRate() != RF24_1MBPS) {
|
||||
radio.failureDetected = true;
|
||||
Serial.print("Radio configuration error detected");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************** Ping Out Role ***************************/
|
||||
|
||||
if (role == 1) {
|
||||
|
||||
radio.stopListening(); // First, stop listening so we can talk.
|
||||
|
||||
Serial.println(F("Now sending"));
|
||||
|
||||
unsigned long start_time = micros(); // Take the time, and send it. This will block until complete
|
||||
if (!radio.write(&start_time, sizeof(unsigned long))) {
|
||||
Serial.println(F("failed"));
|
||||
}
|
||||
|
||||
radio.startListening(); // Now, continue listening
|
||||
|
||||
unsigned long started_waiting_at = micros(); // Set up a timeout period, get the current microseconds
|
||||
bool timeout = false; // Set up a variable to indicate if a response was received or not
|
||||
|
||||
while (!radio.available()) // While nothing is received
|
||||
{
|
||||
if (micros() - started_waiting_at > 200000 ) // If waited longer than 200ms, indicate timeout and exit while loop
|
||||
{
|
||||
timeout = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (timeout) {
|
||||
// Describe the results
|
||||
Serial.println(F("Failed, response timed out."));
|
||||
} else {
|
||||
// Grab the response, compare, and send to debugging spew
|
||||
|
||||
unsigned long got_time; // Variable for the received timestamp
|
||||
|
||||
// Failure Handling
|
||||
uint32_t failTimer = millis();
|
||||
while (radio.available()) // If available() always returns true, there is a problem
|
||||
{
|
||||
if (millis() - failTimer > 250) {
|
||||
radio.failureDetected = true;
|
||||
Serial.println("Radio available failure detected");
|
||||
break;
|
||||
}
|
||||
radio.read(&got_time, sizeof(unsigned long));
|
||||
}
|
||||
unsigned long end_time = micros();
|
||||
|
||||
// Spew it
|
||||
Serial.print(F("Sent "));
|
||||
Serial.print(start_time);
|
||||
Serial.print(F(", Got response "));
|
||||
Serial.print(got_time);
|
||||
Serial.print(F(", Round-trip delay "));
|
||||
Serial.print(end_time - start_time);
|
||||
Serial.println(F(" microseconds"));
|
||||
}
|
||||
|
||||
delay(1000); // Try again 1s later
|
||||
}
|
||||
|
||||
|
||||
/****************** Pong Back Role ***************************/
|
||||
|
||||
if (role == 0) {
|
||||
unsigned long got_time; // Variable for the received timestamp
|
||||
|
||||
if (radio.available()) {
|
||||
uint32_t failTimer = millis();
|
||||
|
||||
while (radio.available()) // While there is data ready
|
||||
{
|
||||
if (millis() - failTimer > 500) {
|
||||
Serial.println("Radio available failure detected");
|
||||
radio.failureDetected = true;
|
||||
break;
|
||||
}
|
||||
radio.read(&got_time, sizeof(unsigned long)); // Get the payload
|
||||
}
|
||||
|
||||
radio.stopListening(); // First, stop listening so we can talk
|
||||
radio.write(&got_time, sizeof(unsigned long)); // Send the final one back.
|
||||
radio.startListening(); // Now, resume listening so we catch the next packets.
|
||||
Serial.print(F("Sent response "));
|
||||
Serial.println(got_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************** Change Roles via Serial Commands ***************************/
|
||||
|
||||
if (Serial.available()) {
|
||||
char c = toupper(Serial.read());
|
||||
if (c == 'T' && role == 0) {
|
||||
Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
|
||||
role = 1; // Become the primary transmitter (ping out)
|
||||
} else if ( c == 'R' && role == 1 ) {
|
||||
Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
|
||||
role = 0; // Become the primary receiver (pong back)
|
||||
radio.startListening();
|
||||
}
|
||||
}
|
||||
} // Loop
|
@ -0,0 +1,191 @@
|
||||
/*
|
||||
TMRh20 2014
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/** Reliably transmitting large volumes of data with a low signal or in noisy environments
|
||||
This example demonstrates data transfer functionality with the use of auto-retry
|
||||
and auto-reUse functionality enabled. This sketch demonstrates how a user can extend
|
||||
the auto-retry functionality to any chosen time period, preventing data loss and ensuring
|
||||
the consistency of data.
|
||||
|
||||
This sketh demonstrates use of the writeBlocking() functionality, and extends the standard
|
||||
retry functionality of the radio. Payloads will be auto-retried until successful or the
|
||||
extended timeout period is reached.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <SPI.h>
|
||||
#include "nRF24L01.h"
|
||||
#include "RF24.h"
|
||||
#include "printf.h"
|
||||
|
||||
/************* USER Configuration *****************************/
|
||||
|
||||
RF24 radio(7, 8); // Set up nRF24L01 radio on SPI bus plus pins 7 & 8
|
||||
unsigned long timeoutPeriod = 3000; // Set a user-defined timeout period. With auto-retransmit set to (15,15) retransmission will take up to 60ms and as little as 7.5ms with it set to (1,15).
|
||||
// With a timeout period of 1000, the radio will retry each payload for up to 1 second before giving up on the transmission and starting over
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
const uint64_t pipes[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; // Radio pipe addresses for the 2 nodes to communicate.
|
||||
|
||||
byte data[32]; //Data buffer
|
||||
|
||||
volatile unsigned long counter;
|
||||
unsigned long rxTimer, startTime, stopTime, payloads = 0;
|
||||
bool tx = 1, rx = 0, role = 0, transferInProgress = 0;
|
||||
|
||||
|
||||
void setup(void) {
|
||||
|
||||
Serial.begin(115200);
|
||||
printf_begin();
|
||||
|
||||
radio.begin(); // Setup and configure rf radio
|
||||
radio.setChannel(1); // Set the channel
|
||||
radio.setPALevel(RF24_PA_LOW); // Set PA LOW for this demonstration. We want the radio to be as lossy as possible for this example.
|
||||
radio.setDataRate(RF24_1MBPS); // Raise the data rate to reduce transmission distance and increase lossiness
|
||||
radio.setAutoAck(1); // Ensure autoACK is enabled
|
||||
radio.setRetries(2, 15); // Optionally, increase the delay between retries. Want the number of auto-retries as high as possible (15)
|
||||
radio.setCRCLength(RF24_CRC_16); // Set CRC length to 16-bit to ensure quality of data
|
||||
radio.openWritingPipe(pipes[0]); // Open the default reading and writing pipe
|
||||
radio.openReadingPipe(1, pipes[1]);
|
||||
|
||||
radio.startListening(); // Start listening
|
||||
radio.printDetails(); // Dump the configuration of the rf unit for debugging
|
||||
|
||||
printf("\n\rRF24/examples/Transfer Rates/\n\r");
|
||||
printf("*** PRESS 'T' to begin transmitting to the other node\n\r");
|
||||
|
||||
randomSeed(analogRead(0)); //Seed for random number generation
|
||||
for (int i = 0; i < 32; i++) {
|
||||
data[i] = random(255); //Load the buffer with random data
|
||||
}
|
||||
radio.powerUp(); //Power up the radio
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void loop(void) {
|
||||
|
||||
|
||||
if (role == tx) {
|
||||
delay(2000); // Pause for a couple seconds between transfers
|
||||
printf("Initiating Extended Timeout Data Transfer\n\r");
|
||||
|
||||
unsigned long cycles = 1000; // Change this to a higher or lower number. This is the number of payloads that will be sent.
|
||||
|
||||
unsigned long transferCMD[] = {'H', 'S', cycles }; // Indicate to the other radio that we are starting, and provide the number of payloads that will be sent
|
||||
radio.writeFast(&transferCMD, 12); // Send the transfer command
|
||||
if (radio.txStandBy(timeoutPeriod)) { // If transfer initiation was successful, do the following
|
||||
|
||||
startTime = millis(); // For calculating transfer rate
|
||||
boolean timedOut = 0; // Boolean for keeping track of failures
|
||||
|
||||
for (unsigned long i = 0; i < cycles; i++) // Loop through a number of cycles
|
||||
{
|
||||
data[0] = i; // Change the first byte of the payload for identification
|
||||
|
||||
if (!radio.writeBlocking(&data, 32, timeoutPeriod)) { // If retries are failing and the user defined timeout is exceeded
|
||||
timedOut = 1; // Indicate failure
|
||||
counter = cycles; // Set the fail count to maximum
|
||||
break; // Break out of the for loop
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
stopTime = millis(); // Capture the time of completion or failure
|
||||
|
||||
//This should be called to wait for completion and put the radio in standby mode after transmission, returns 0 if data still in FIFO (timed out), 1 if success
|
||||
if (timedOut) {
|
||||
radio.txStandBy(); //Partially blocking standby, blocks until success or max retries. FIFO flushed if auto timeout reached
|
||||
}
|
||||
else {
|
||||
radio.txStandBy(timeoutPeriod); //Standby, block until FIFO empty (sent) or user specified timeout reached. FIFO flushed if user timeout reached.
|
||||
}
|
||||
|
||||
} else {
|
||||
Serial.println("Communication not established"); //If unsuccessful initiating transfer, exit and retry later
|
||||
}
|
||||
|
||||
float rate = cycles * 32 / (stopTime - startTime); //Display results:
|
||||
|
||||
Serial.print("Transfer complete at "); Serial.print(rate); printf(" KB/s \n\r");
|
||||
Serial.print(counter);
|
||||
Serial.print(" of ");
|
||||
Serial.print(cycles); Serial.println(" Packets Failed to Send");
|
||||
counter = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (role == rx) {
|
||||
|
||||
if (!transferInProgress) { // If a bulk data transfer has not been started
|
||||
if (radio.available()) {
|
||||
radio.read(&data, 32); //Read any available payloads for analysis
|
||||
|
||||
if (data[0] == 'H' && data[4] == 'S') { // If a bulk data transfer command has been received
|
||||
payloads = data[8]; // Read the first two bytes of the unsigned long. Need to read the 3rd and 4th if sending more than 65535 payloads
|
||||
payloads |= data[9] << 8; // This is the number of payloads that will be sent
|
||||
counter = 0; // Reset the payload counter to 0
|
||||
transferInProgress = 1; // Indicate it has started
|
||||
startTime = rxTimer = millis(); // Capture the start time to measure transfer rate and calculate timeouts
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (radio.available()) { // If in bulk transfer mode, and a payload is available
|
||||
radio.read(&data, 32); // Read the payload
|
||||
rxTimer = millis(); // Reset the timeout timer
|
||||
counter++; // Keep a count of received payloads
|
||||
} else if (millis() - rxTimer > timeoutPeriod) { // If no data available, check the timeout period
|
||||
Serial.println("Transfer Failed"); // If per-payload timeout exceeeded, end the transfer
|
||||
transferInProgress = 0;
|
||||
} else if (counter >= payloads) { // If the specified number of payloads is reached, transfer is completed
|
||||
startTime = millis() - startTime; // Calculate the total time spent during transfer
|
||||
float numBytes = counter * 32; // Calculate the number of bytes transferred
|
||||
Serial.print("Rate: "); // Print the transfer rate and number of payloads
|
||||
Serial.print(numBytes / startTime);
|
||||
Serial.println(" KB/s");
|
||||
Serial.print("Payload Count: ");
|
||||
Serial.println(counter);
|
||||
transferInProgress = 0; // End the transfer as complete
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Change roles
|
||||
//
|
||||
|
||||
if ( Serial.available() )
|
||||
{
|
||||
char c = toupper(Serial.read());
|
||||
if ( c == 'T' && role == rx )
|
||||
{
|
||||
printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n\r");
|
||||
radio.openWritingPipe(pipes[1]);
|
||||
radio.openReadingPipe(1, pipes[0]);
|
||||
radio.stopListening();
|
||||
role = tx; // Become the primary transmitter (ping out)
|
||||
}
|
||||
else if ( c == 'R' && role == tx )
|
||||
{
|
||||
radio.openWritingPipe(pipes[0]);
|
||||
radio.openReadingPipe(1, pipes[1]);
|
||||
radio.startListening();
|
||||
printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n\r");
|
||||
role = rx; // Become the primary receiver (pong back)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example using Dynamic Payloads
|
||||
*
|
||||
* This is an example of how to use payloads of a varying (dynamic) size.
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include "nRF24L01.h"
|
||||
#include "RF24.h"
|
||||
#include "printf.h"
|
||||
|
||||
// Hardware configuration
|
||||
RF24 radio(7, 8); // Set up nRF24L01 radio on SPI bus plus pins 7 & 8
|
||||
|
||||
// Radio pipe addresses for the 2 nodes to communicate.
|
||||
const uint64_t addresses[2] = {0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL};
|
||||
|
||||
/************************* Role management ****************************/
|
||||
// Set up role. This sketch uses the same software for all the nodes in this
|
||||
// system. Doing so greatly simplifies testing.
|
||||
|
||||
// The role_pin is a digital input pin used to set the role of this radio.
|
||||
// Connect the role_pin to GND to be the 'pong' receiver
|
||||
// Leave the role_pin open to be the 'ping' transmitter
|
||||
const short role_pin = 5; // use pin 5
|
||||
typedef enum { role_ping_out = 1, role_pong_back } role_e; // The various roles supported by this sketch
|
||||
const char* role_friendly_name[] = {"invalid", "Ping out", "Pong back"}; // The debug-friendly names of those roles
|
||||
role_e role; // The role of the current running sketch
|
||||
|
||||
|
||||
// variables used for changing the payload size dynamically (used when role == role_ping_out)
|
||||
const int min_payload_size = 4;
|
||||
const int max_payload_size = 32;
|
||||
const int payload_size_increment = 1;
|
||||
int send_payload_size = min_payload_size;
|
||||
|
||||
char receive_payload[max_payload_size + 1]; // +1 to allow room for a terminating NULL char
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
pinMode(role_pin, INPUT); // set up the role pin
|
||||
digitalWrite(role_pin, HIGH);
|
||||
delay(20); // Just to get a solid reading on the role pin
|
||||
|
||||
// read the role_pin, establish our role
|
||||
if (digitalRead(role_pin)) {
|
||||
role = role_ping_out;
|
||||
} else {
|
||||
role = role_pong_back;
|
||||
}
|
||||
|
||||
Serial.begin(115200);
|
||||
printf_begin(); // needed for printDetails()
|
||||
|
||||
// Print preamble
|
||||
Serial.println(F("RF24/examples/pingpair_dyn/"));
|
||||
Serial.print(F("ROLE: "));
|
||||
Serial.println(role_friendly_name[role]);
|
||||
|
||||
// Setup and configure rf radio
|
||||
radio.begin();
|
||||
radio.enableDynamicPayloads(); // Enable dynamic payloads
|
||||
radio.setRetries(5, 15); // delay between retries = 5 * 250 + 250 = 1500 microseconds, number of retries = 15
|
||||
|
||||
// Open a writing and reading pipe on each radio, with opposite addresses
|
||||
if (role == role_ping_out) {
|
||||
radio.openWritingPipe(addresses[0]);
|
||||
radio.openReadingPipe(1, addresses[1]);
|
||||
} else {
|
||||
radio.openWritingPipe(addresses[1]);
|
||||
radio.openReadingPipe(1, addresses[0]);
|
||||
}
|
||||
|
||||
radio.startListening(); // Start listening
|
||||
radio.printDetails(); // Dump the configuration of the rf unit for debugging
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
|
||||
/****************** Ping Out Role ***************************/
|
||||
|
||||
if (role == role_ping_out) {
|
||||
// The payload will always be the same, what will change is how much of it we send.
|
||||
static char send_payload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ789012";
|
||||
|
||||
radio.stopListening(); // First, stop listening so we can talk.
|
||||
|
||||
// Send the payload
|
||||
Serial.print(F("Now sending length "));
|
||||
Serial.println(send_payload_size);
|
||||
radio.write(send_payload, send_payload_size); // This will block until complete
|
||||
|
||||
radio.startListening(); // Now, continue listening
|
||||
|
||||
unsigned long started_waiting_at = millis(); // Start a timer for measuring timout
|
||||
bool timeout = false;
|
||||
while (!radio.available() && !timeout) // Wait until we get a response or timeout is reached
|
||||
{
|
||||
if (millis() - started_waiting_at > 500) // Only wait for 500 milliseconds
|
||||
timeout = true;
|
||||
}
|
||||
|
||||
// Describe the results
|
||||
if (timeout) {
|
||||
Serial.println(F("Failed, response timed out."));
|
||||
} else {
|
||||
// Grab the response and print it
|
||||
|
||||
uint8_t len = radio.getDynamicPayloadSize(); // get payload's length
|
||||
|
||||
// If an illegal payload size was detected, all RX payloads will be flushed
|
||||
if (!len)
|
||||
return;
|
||||
|
||||
radio.read(receive_payload, len);
|
||||
|
||||
// Use payload as a C-string (for easy printing)
|
||||
receive_payload[len] = 0; // put a NULL terminating zero at the end
|
||||
|
||||
// Spew it
|
||||
Serial.print(F("Got response size="));
|
||||
Serial.print(len);
|
||||
Serial.print(F(" value="));
|
||||
Serial.println(receive_payload);
|
||||
}
|
||||
|
||||
send_payload_size += payload_size_increment; // Update size for next time.
|
||||
if (send_payload_size > max_payload_size) // if payload length is larger than the radio can handle
|
||||
send_payload_size = min_payload_size; // reset the payload length
|
||||
|
||||
delay(1000); // Try again 1s later
|
||||
}
|
||||
|
||||
|
||||
/****************** Pong Back Role ***************************/
|
||||
// Receive each packet, send it back, and dump it out
|
||||
|
||||
if (role == role_pong_back) {
|
||||
while (radio.available()) // if there is data ready
|
||||
{
|
||||
|
||||
uint8_t len = radio.getDynamicPayloadSize(); // Fetch the the payload size
|
||||
|
||||
// If an illegal payload size was detected, all RX payloads will be flushed
|
||||
if (!len)
|
||||
continue;
|
||||
|
||||
radio.read(receive_payload, len);
|
||||
|
||||
// Use payload as a C-string (for easy printing)
|
||||
receive_payload[len] = 0; // put a NULL terminating zero at the end
|
||||
|
||||
// Spew it
|
||||
Serial.print(F("Got response size="));
|
||||
Serial.print(len);
|
||||
Serial.print(F(" value="));
|
||||
Serial.println(receive_payload);
|
||||
|
||||
radio.stopListening(); // First, stop listening so we can talk
|
||||
|
||||
// Send a reply that the packet was received
|
||||
//
|
||||
// You will have better luck delivering your message if
|
||||
// you wait for the other node to start listening first
|
||||
delay(20);
|
||||
radio.write(receive_payload, len);
|
||||
Serial.println(F("Sent response."));
|
||||
|
||||
radio.startListening(); // Now, resume listening so we catch the next packets.
|
||||
}
|
||||
}
|
||||
} // loop
|
||||
// vim:cin:ai:sts=2 sw=2 ft=cpp
|
@ -0,0 +1,172 @@
|
||||
/*
|
||||
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
|
||||
|
||||
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.
|
||||
|
||||
Update 2014 - TMRh20
|
||||
*/
|
||||
|
||||
/**
|
||||
Example of using interrupts
|
||||
|
||||
This is an example of how to user interrupts to interact with the radio, and a demonstration
|
||||
of how to use them to sleep when receiving, and not miss any payloads.
|
||||
The pingpair_sleepy example expands on sleep functionality with a timed sleep option for the transmitter.
|
||||
Sleep functionality is built directly into my fork of the RF24Network library
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include "nRF24L01.h"
|
||||
#include "RF24.h"
|
||||
#include "printf.h"
|
||||
|
||||
// Hardware configuration
|
||||
RF24 radio(7, 8); // Set up nRF24L01 radio on SPI bus plus pins 7 & 8
|
||||
|
||||
// Our ACK payload will simply be 4 bytes containing the number of payloads received
|
||||
static uint32_t message_count = 1; // start counting at 1
|
||||
|
||||
// Demonstrates another method of setting up the addresses
|
||||
byte address[][5] = {0xCC, 0xCE, 0xCC, 0xCE, 0xCC, 0xCE, 0xCC, 0xCE, 0xCC, 0xCE};
|
||||
|
||||
/************************* Role management ****************************/
|
||||
// Set up role. This sketch uses the same software for all the nodes in this
|
||||
// system. Doing so greatly simplifies testing.
|
||||
|
||||
// The role_pin is a digital input pin used to set the role of this radio.
|
||||
// Connect the role_pin to GND to be the 'pong' receiver
|
||||
// Leave the role_pin open to be the 'ping' transmitter
|
||||
const short role_pin = 5; // use pin 5
|
||||
typedef enum { role_sender = 1, role_receiver } role_e; // The various roles supported by this sketch
|
||||
const char* role_friendly_name[] = {"invalid", "Sender", "Receiver"}; // The debug-friendly names of those roles
|
||||
role_e role; // The role of the current running sketch
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
pinMode(role_pin, INPUT); // set up the role pin
|
||||
digitalWrite(role_pin, HIGH); // Change this to LOW/HIGH instead of using an external pin
|
||||
delay(20); // Just to get a solid reading on the role pin
|
||||
|
||||
if (digitalRead(role_pin)) // read the role_pin pin to establish our role
|
||||
role = role_sender;
|
||||
else
|
||||
role = role_receiver;
|
||||
|
||||
|
||||
Serial.begin(115200);
|
||||
printf_begin(); // needed for printDetails()
|
||||
|
||||
// print introduction
|
||||
Serial.print(F("\n\rRF24/examples/pingpair_irq\n\rROLE: "));
|
||||
Serial.println(role_friendly_name[role]);
|
||||
|
||||
|
||||
/********************** Setup and configure rf radio *********************/
|
||||
radio.begin();
|
||||
|
||||
// Examples are usually run with both radios in close proximity to each other
|
||||
radio.setPALevel(RF24_PA_LOW); // defaults to RF24_PA_MAX
|
||||
radio.enableAckPayload(); // We will be using the ACK Payload feature which is not enabled by default
|
||||
radio.enableDynamicPayloads(); // Ack payloads are dynamic payloads
|
||||
|
||||
// Open a writing and reading pipe on each radio, with opposite addresses
|
||||
if (role == role_sender) {
|
||||
radio.openWritingPipe(address[0]);
|
||||
radio.openReadingPipe(1, address[1]);
|
||||
} else {
|
||||
radio.openWritingPipe(address[1]);
|
||||
radio.openReadingPipe(1, address[0]);
|
||||
radio.startListening(); // First we need to start listening
|
||||
|
||||
// Add an ACK payload for the first time around; 1 is the pipe number to acknowledge
|
||||
radio.writeAckPayload(1, &message_count, sizeof(message_count));
|
||||
++message_count; // increment counter by 1 for next ACK payload
|
||||
}
|
||||
|
||||
radio.printDetails(); // Dump the configuration of the rf unit for debugging
|
||||
delay(50);
|
||||
|
||||
// Attach interrupt handler to interrupt #0 (using pin 2) on BOTH the sender and receiver
|
||||
attachInterrupt(0, check_radio, LOW);
|
||||
} // setup
|
||||
|
||||
|
||||
void loop() {
|
||||
|
||||
|
||||
/****************** Ping Out Role ***************************/
|
||||
|
||||
if (role == role_sender) {
|
||||
// Repeatedly send the current time
|
||||
|
||||
unsigned long time = millis(); // Take the time
|
||||
Serial.print(F("Now sending "));
|
||||
Serial.println(time);
|
||||
radio.startWrite(&time, sizeof(unsigned long), 0); // Send the time
|
||||
delay(2000); // Try again soon (in 2 seconds)
|
||||
}
|
||||
|
||||
|
||||
/****************** Pong Back Role ***************************/
|
||||
// Receiver does nothing! All the work is in Interrupt Handler
|
||||
|
||||
if (role == role_receiver) {}
|
||||
|
||||
} // loop
|
||||
|
||||
|
||||
/********************** Interrupt Handler *********************/
|
||||
|
||||
void check_radio(void) {
|
||||
|
||||
bool tx, fail, rx; // declare variables to store IRQ flags
|
||||
radio.whatHappened(tx, fail, rx); // What happened?
|
||||
|
||||
if (tx) { // Have we successfully transmitted?
|
||||
if (role == role_sender)
|
||||
Serial.println(F("Send:OK"));
|
||||
if (role == role_receiver)
|
||||
Serial.println(F("Ack Payload:Sent"));
|
||||
}
|
||||
|
||||
if (fail) { // Have we failed to transmit?
|
||||
if (role == role_sender)
|
||||
Serial.println(F("Send:Failed"));
|
||||
if (role == role_receiver)
|
||||
Serial.println(F("Ack Payload:Failed"));
|
||||
}
|
||||
|
||||
if (rx || radio.available()) { // Did we receive a message?
|
||||
|
||||
|
||||
|
||||
|
||||
/**************** Ping Out Role (about received ACK payload) ************************/
|
||||
// If we're the sender, we've received an ack payload
|
||||
if (role == role_sender) {
|
||||
// Get the payload and dump it
|
||||
radio.read(&message_count, sizeof(message_count));
|
||||
Serial.print(F("Ack: "));
|
||||
Serial.println(message_count);
|
||||
}
|
||||
|
||||
|
||||
/****************** Pong Back Role ***************************/
|
||||
// If we're the receiver, we've received a time message
|
||||
if (role == role_receiver) {
|
||||
// Get the payload and dump it
|
||||
|
||||
static unsigned long got_time; // variable to hold the received time
|
||||
radio.read(&got_time, sizeof(got_time)); // get the payload
|
||||
Serial.print(F("Got payload "));
|
||||
Serial.println(got_time);
|
||||
|
||||
// Add an ACK payload for the next time around; 1 is the pipe number to acknowledge
|
||||
radio.writeAckPayload(1, &message_count, sizeof(message_count));
|
||||
++message_count; // increment packet counter
|
||||
}
|
||||
}
|
||||
} // check_radio
|
@ -0,0 +1,263 @@
|
||||
/*
|
||||
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
Example using Dynamic Payloads
|
||||
|
||||
This is an example of how to use payloads of a varying (dynamic) size.
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include "RF24.h"
|
||||
|
||||
//
|
||||
// Hardware configuration
|
||||
//
|
||||
|
||||
// Set up nRF24L01 radio on SPI bus plus pins 8 & 9
|
||||
RF24 radio(7, 8);
|
||||
|
||||
// Use multicast?
|
||||
// sets the multicast behavior this unit in hardware. Connect to GND to use unicast
|
||||
// Leave open (default) to use multicast.
|
||||
const int multicast_pin = 6;
|
||||
|
||||
// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver
|
||||
// Leave open to be the 'ping' transmitter
|
||||
const int role_pin = 5;
|
||||
bool multicast = true ;
|
||||
|
||||
//
|
||||
// Topology
|
||||
//
|
||||
|
||||
// Radio pipe addresses for the 2 nodes to communicate.
|
||||
const uint64_t pipes[2] = { 0xEEFAFDFDEELL, 0xEEFDFAF50DFLL };
|
||||
|
||||
//
|
||||
// Role management
|
||||
//
|
||||
// Set up role. This sketch uses the same software for all the nodes
|
||||
// in this system. Doing so greatly simplifies testing. The hardware itself specifies
|
||||
// which node it is.
|
||||
//
|
||||
// This is done through the role_pin
|
||||
//
|
||||
|
||||
// The various roles supported by this sketch
|
||||
typedef enum { role_ping_out = 1, role_pong_back } role_e;
|
||||
|
||||
// The debug-friendly names of those roles
|
||||
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};
|
||||
|
||||
// The role of the current running sketch
|
||||
role_e role;
|
||||
|
||||
//
|
||||
// Payload
|
||||
//
|
||||
|
||||
const int min_payload_size = 1;
|
||||
const int max_payload_size = 32;
|
||||
const int payload_size_increments_by = 1;
|
||||
int next_payload_size = min_payload_size;
|
||||
|
||||
char receive_payload[max_payload_size + 1]; // +1 to allow room for a terminating NULL char
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
//
|
||||
// Multicast
|
||||
//
|
||||
pinMode(multicast_pin, INPUT);
|
||||
digitalWrite(multicast_pin, HIGH);
|
||||
delay( 20 ) ;
|
||||
|
||||
// read multicast role, LOW for unicast
|
||||
if ( digitalRead( multicast_pin ) )
|
||||
multicast = true ;
|
||||
else
|
||||
multicast = false ;
|
||||
|
||||
|
||||
//
|
||||
// Role
|
||||
//
|
||||
|
||||
// set up the role pin
|
||||
pinMode(role_pin, INPUT);
|
||||
digitalWrite(role_pin, HIGH);
|
||||
delay( 20 ); // Just to get a solid reading on the role pin
|
||||
|
||||
// read the address pin, establish our role
|
||||
if ( digitalRead(role_pin) )
|
||||
role = role_ping_out;
|
||||
else
|
||||
role = role_pong_back;
|
||||
|
||||
//
|
||||
// Print preamble
|
||||
//
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.println(F("RF24/examples/pingpair_multi_dyn/"));
|
||||
Serial.print(F("ROLE: "));
|
||||
Serial.println(role_friendly_name[role]);
|
||||
|
||||
Serial.print(F("MULTICAST: "));
|
||||
Serial.println(multicast ? F("true (unreliable)") : F("false (reliable)"));
|
||||
|
||||
//
|
||||
// Setup and configure rf radio
|
||||
//
|
||||
|
||||
radio.begin();
|
||||
|
||||
// enable dynamic payloads
|
||||
radio.enableDynamicPayloads();
|
||||
radio.setCRCLength( RF24_CRC_16 ) ;
|
||||
|
||||
// optionally, increase the delay between retries & # of retries
|
||||
radio.setRetries( 15, 5 ) ;
|
||||
radio.setAutoAck( true ) ;
|
||||
//radio.setPALevel( RF24_PA_LOW ) ;
|
||||
|
||||
//
|
||||
// Open pipes to other nodes for communication
|
||||
//
|
||||
|
||||
// This simple sketch opens two pipes for these two nodes to communicate
|
||||
// back and forth.
|
||||
// Open 'our' pipe for writing
|
||||
// Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading)
|
||||
|
||||
if ( role == role_ping_out )
|
||||
{
|
||||
radio.openWritingPipe(pipes[0]);
|
||||
radio.openReadingPipe(1, pipes[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
radio.openWritingPipe(pipes[1]);
|
||||
radio.openReadingPipe(1, pipes[0]);
|
||||
}
|
||||
|
||||
//
|
||||
// Start listening
|
||||
//
|
||||
radio.powerUp() ;
|
||||
radio.startListening();
|
||||
|
||||
//
|
||||
// Dump the configuration of the rf unit for debugging
|
||||
//
|
||||
|
||||
radio.printDetails();
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
//
|
||||
// Ping out role. Repeatedly send the current time
|
||||
//
|
||||
|
||||
if (role == role_ping_out)
|
||||
{
|
||||
// The payload will always be the same, what will change is how much of it we send.
|
||||
static char send_payload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ789012";
|
||||
|
||||
// First, stop listening so we can talk.
|
||||
radio.stopListening();
|
||||
|
||||
// Take the time, and send it. This will block until complete
|
||||
Serial.print(F("Now sending length "));
|
||||
Serial.println(next_payload_size);
|
||||
radio.write( send_payload, next_payload_size, multicast );
|
||||
|
||||
// Now, continue listening
|
||||
radio.startListening();
|
||||
|
||||
// Wait here until we get a response, or timeout
|
||||
unsigned long started_waiting_at = millis();
|
||||
bool timeout = false;
|
||||
while ( ! radio.available() && ! timeout )
|
||||
if (millis() - started_waiting_at > 500 )
|
||||
timeout = true;
|
||||
|
||||
// Describe the results
|
||||
if ( timeout )
|
||||
{
|
||||
Serial.println(F("Failed, response timed out."));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Grab the response, compare, and send to debugging spew
|
||||
uint8_t len = radio.getDynamicPayloadSize();
|
||||
radio.read( receive_payload, len );
|
||||
|
||||
// Put a zero at the end for easy printing
|
||||
receive_payload[len] = 0;
|
||||
|
||||
// Spew it
|
||||
Serial.print(F("Got response size="));
|
||||
Serial.print(len);
|
||||
Serial.print(F(" value="));
|
||||
Serial.println(receive_payload);
|
||||
}
|
||||
|
||||
// Update size for next time.
|
||||
next_payload_size += payload_size_increments_by;
|
||||
if ( next_payload_size > max_payload_size )
|
||||
next_payload_size = min_payload_size;
|
||||
|
||||
// Try again 1s later
|
||||
delay(250);
|
||||
}
|
||||
|
||||
//
|
||||
// Pong back role. Receive each packet, dump it out, and send it back
|
||||
//
|
||||
|
||||
if ( role == role_pong_back )
|
||||
{
|
||||
// if there is data ready
|
||||
if ( radio.available() )
|
||||
{
|
||||
// Dump the payloads until we've gotten everything
|
||||
uint8_t len;
|
||||
bool done = false;
|
||||
while (radio.available())
|
||||
{
|
||||
// Fetch the payload, and see if this was the last one.
|
||||
len = radio.getDynamicPayloadSize();
|
||||
radio.read( receive_payload, len );
|
||||
|
||||
// Put a zero at the end for easy printing
|
||||
receive_payload[len] = 0;
|
||||
|
||||
// Spew it
|
||||
Serial.print(F("Got response size="));
|
||||
Serial.print(len);
|
||||
Serial.print(F(" value="));
|
||||
Serial.println(receive_payload);
|
||||
}
|
||||
|
||||
// First, stop listening so we can talk
|
||||
radio.stopListening();
|
||||
|
||||
// Send the final one back.
|
||||
radio.write( receive_payload, len, multicast );
|
||||
Serial.println(F("Sent response."));
|
||||
|
||||
// Now, resume listening so we catch the next packets.
|
||||
radio.startListening();
|
||||
}
|
||||
}
|
||||
}
|
||||
// vim:cin:ai:sts=2 sw=2 ft=cpp
|
@ -0,0 +1,226 @@
|
||||
/*
|
||||
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
|
||||
|
||||
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.
|
||||
|
||||
TMRh20 2014 - Updates to the library allow sleeping both in TX and RX modes:
|
||||
TX Mode: The radio can be powered down (.9uA current) and the Arduino slept using the watchdog timer
|
||||
RX Mode: The radio can be left in standby mode (22uA current) and the Arduino slept using an interrupt pin
|
||||
*/
|
||||
|
||||
/**
|
||||
Example RF Radio Ping Pair which Sleeps between Sends
|
||||
|
||||
This is an example of how to use the RF24 class to create a battery-
|
||||
efficient system. It is just like the GettingStarted_CallResponse example, but the
|
||||
ping node powers down the radio and sleeps the MCU after every
|
||||
ping/pong cycle, and the receiver sleeps between payloads.
|
||||
|
||||
Write this sketch to two different nodes,
|
||||
connect the role_pin to ground on one. The ping node sends the current
|
||||
time to the pong node, which responds by sending the value back. The ping
|
||||
node can then see how long the whole cycle took.
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <avr/sleep.h>
|
||||
#include <avr/power.h>
|
||||
#include "nRF24L01.h"
|
||||
#include "RF24.h"
|
||||
#include "printf.h"
|
||||
|
||||
|
||||
// Set up nRF24L01 radio on SPI bus plus pins 7 & 8
|
||||
RF24 radio(7, 8);
|
||||
|
||||
// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver
|
||||
// Leave open to be the 'ping' transmitter
|
||||
const int role_pin = 5;
|
||||
|
||||
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL }; // Radio pipe addresses for the 2 nodes to communicate.
|
||||
|
||||
// Role management
|
||||
// Set up role. This sketch uses the same software for all the nodes
|
||||
// in this system. Doing so greatly simplifies testing. The hardware itself specifies
|
||||
// which node it is.
|
||||
|
||||
// The various roles supported by this sketch
|
||||
typedef enum { role_ping_out = 1, role_pong_back } role_e;
|
||||
|
||||
// The debug-friendly names of those roles
|
||||
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};
|
||||
|
||||
// The role of the current running sketch
|
||||
role_e role;
|
||||
|
||||
|
||||
// Sleep declarations
|
||||
typedef enum { wdt_16ms = 0, wdt_32ms, wdt_64ms, wdt_128ms, wdt_250ms, wdt_500ms, wdt_1s, wdt_2s, wdt_4s, wdt_8s } wdt_prescalar_e;
|
||||
|
||||
void setup_watchdog(uint8_t prescalar);
|
||||
void do_sleep(void);
|
||||
|
||||
const short sleep_cycles_per_transmission = 4;
|
||||
volatile short sleep_cycles_remaining = sleep_cycles_per_transmission;
|
||||
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
// set up the role pin
|
||||
pinMode(role_pin, INPUT);
|
||||
digitalWrite(role_pin, HIGH);
|
||||
delay(20); // Just to get a solid reading on the role pin
|
||||
|
||||
// read the address pin, establish our role
|
||||
if ( digitalRead(role_pin) )
|
||||
role = role_ping_out;
|
||||
else
|
||||
role = role_pong_back;
|
||||
|
||||
Serial.begin(115200);
|
||||
printf_begin();
|
||||
Serial.print(F("\n\rRF24/examples/pingpair_sleepy/\n\rROLE: "));
|
||||
Serial.println(role_friendly_name[role]);
|
||||
|
||||
// Prepare sleep parameters
|
||||
// Only the ping out role uses WDT. Wake up every 4s to send a ping
|
||||
//if ( role == role_ping_out )
|
||||
setup_watchdog(wdt_4s);
|
||||
|
||||
// Setup and configure rf radio
|
||||
|
||||
radio.begin();
|
||||
|
||||
// Open pipes to other nodes for communication
|
||||
|
||||
// This simple sketch opens two pipes for these two nodes to communicate
|
||||
// back and forth.
|
||||
// Open 'our' pipe for writing
|
||||
// Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading)
|
||||
|
||||
if ( role == role_ping_out ) {
|
||||
radio.openWritingPipe(pipes[0]);
|
||||
radio.openReadingPipe(1, pipes[1]);
|
||||
} else {
|
||||
radio.openWritingPipe(pipes[1]);
|
||||
radio.openReadingPipe(1, pipes[0]);
|
||||
}
|
||||
|
||||
// Start listening
|
||||
radio.startListening();
|
||||
|
||||
// Dump the configuration of the rf unit for debugging
|
||||
//radio.printDetails();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
|
||||
if (role == role_ping_out) { // Ping out role. Repeatedly send the current time
|
||||
radio.powerUp(); // Power up the radio after sleeping
|
||||
radio.stopListening(); // First, stop listening so we can talk.
|
||||
|
||||
unsigned long time = millis(); // Take the time, and send it.
|
||||
Serial.print(F("Now sending... "));
|
||||
Serial.println(time);
|
||||
|
||||
radio.write( &time, sizeof(unsigned long) );
|
||||
|
||||
radio.startListening(); // Now, continue listening
|
||||
|
||||
unsigned long started_waiting_at = millis(); // Wait here until we get a response, or timeout (250ms)
|
||||
bool timeout = false;
|
||||
while ( ! radio.available() ) {
|
||||
if (millis() - started_waiting_at > 250 ) { // Break out of the while loop if nothing available
|
||||
timeout = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( timeout ) { // Describe the results
|
||||
Serial.println(F("Failed, response timed out."));
|
||||
} else {
|
||||
unsigned long got_time; // Grab the response, compare, and send to debugging spew
|
||||
radio.read( &got_time, sizeof(unsigned long) );
|
||||
|
||||
printf("Got response %lu, round-trip delay: %lu\n\r", got_time, millis() - got_time);
|
||||
}
|
||||
|
||||
// Shut down the system
|
||||
delay(500); // Experiment with some delay here to see if it has an effect
|
||||
// Power down the radio.
|
||||
radio.powerDown(); // NOTE: The radio MUST be powered back up again manually
|
||||
|
||||
// Sleep the MCU.
|
||||
do_sleep();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Pong back role. Receive each packet, dump it out, and send it back
|
||||
if ( role == role_pong_back ) {
|
||||
|
||||
if ( radio.available() ) { // if there is data ready
|
||||
|
||||
unsigned long got_time;
|
||||
while (radio.available()) { // Dump the payloads until we've gotten everything
|
||||
radio.read( &got_time, sizeof(unsigned long) ); // Get the payload, and see if this was the last one.
|
||||
// Spew it. Include our time, because the ping_out millis counter is unreliable
|
||||
printf("Got payload %lu @ %lu...", got_time, millis()); // due to it sleeping
|
||||
}
|
||||
|
||||
radio.stopListening(); // First, stop listening so we can talk
|
||||
radio.write( &got_time, sizeof(unsigned long) ); // Send the final one back.
|
||||
Serial.println(F("Sent response."));
|
||||
radio.startListening(); // Now, resume listening so we catch the next packets.
|
||||
} else {
|
||||
Serial.println(F("Sleeping"));
|
||||
delay(50); // Delay so the serial data can print out
|
||||
do_sleep();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wakeUp() {
|
||||
sleep_disable();
|
||||
}
|
||||
|
||||
// Sleep helpers
|
||||
|
||||
//Prescaler values
|
||||
// 0=16ms, 1=32ms,2=64ms,3=125ms,4=250ms,5=500ms
|
||||
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
|
||||
|
||||
void setup_watchdog(uint8_t prescalar) {
|
||||
|
||||
uint8_t wdtcsr = prescalar & 7;
|
||||
if ( prescalar & 8 )
|
||||
wdtcsr |= _BV(WDP3);
|
||||
MCUSR &= ~_BV(WDRF); // Clear the WD System Reset Flag
|
||||
WDTCSR = _BV(WDCE) | _BV(WDE); // Write the WD Change enable bit to enable changing the prescaler and enable system reset
|
||||
WDTCSR = _BV(WDCE) | wdtcsr | _BV(WDIE); // Write the prescalar bits (how long to sleep, enable the interrupt to wake the MCU
|
||||
}
|
||||
|
||||
ISR(WDT_vect)
|
||||
{
|
||||
//--sleep_cycles_remaining;
|
||||
Serial.println(F("WDT"));
|
||||
}
|
||||
|
||||
void do_sleep(void)
|
||||
{
|
||||
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
|
||||
sleep_enable();
|
||||
attachInterrupt(0, wakeUp, LOW);
|
||||
WDTCSR |= _BV(WDIE);
|
||||
sleep_mode(); // System sleeps here
|
||||
// The WDT_vect interrupt wakes the MCU from here
|
||||
sleep_disable(); // System continues execution here when watchdog timed out
|
||||
detachInterrupt(0);
|
||||
WDTCSR &= ~_BV(WDIE);
|
||||
}
|
@ -0,0 +1,254 @@
|
||||
/*
|
||||
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
Example LED Remote
|
||||
|
||||
This is an example of how to use the RF24 class to control a remote
|
||||
bank of LED's using buttons on a remote control.
|
||||
|
||||
On the 'remote', connect any number of buttons or switches from
|
||||
an arduino pin to ground. Update 'button_pins' to reflect the
|
||||
pins used.
|
||||
|
||||
On the 'led' board, connect the same number of LED's from an
|
||||
arduino pin to a resistor to ground. Update 'led_pins' to reflect
|
||||
the pins used. Also connect a separate pin to ground and change
|
||||
the 'role_pin'. This tells the sketch it's running on the LED board.
|
||||
|
||||
Every time the buttons change on the remote, the entire state of
|
||||
buttons is send to the led board, which displays the state.
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include "nRF24L01.h"
|
||||
#include "RF24.h"
|
||||
#include "printf.h"
|
||||
|
||||
//
|
||||
// Hardware configuration
|
||||
//
|
||||
|
||||
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10 (CE & CS)
|
||||
|
||||
RF24 radio(9, 10);
|
||||
|
||||
// sets the role of this unit in hardware. Connect to GND to be the 'led' board receiver
|
||||
// Leave open to be the 'remote' transmitter
|
||||
const int role_pin = A4;
|
||||
|
||||
// Pins on the remote for buttons
|
||||
const uint8_t button_pins[] = { 2, 3, 4, 5, 6, 7 };
|
||||
const uint8_t num_button_pins = sizeof(button_pins);
|
||||
|
||||
// Pins on the LED board for LED's
|
||||
const uint8_t led_pins[] = { 2, 3, 4, 5, 6, 7 };
|
||||
const uint8_t num_led_pins = sizeof(led_pins);
|
||||
|
||||
//
|
||||
// Topology
|
||||
//
|
||||
|
||||
// Single radio pipe address for the 2 nodes to communicate.
|
||||
const uint64_t pipe = 0xE8E8F0F0E1LL;
|
||||
|
||||
//
|
||||
// Role management
|
||||
//
|
||||
// Set up role. This sketch uses the same software for all the nodes in this
|
||||
// system. Doing so greatly simplifies testing. The hardware itself specifies
|
||||
// which node it is.
|
||||
//
|
||||
// This is done through the role_pin
|
||||
//
|
||||
|
||||
// The various roles supported by this sketch
|
||||
typedef enum { role_remote = 1, role_led } role_e;
|
||||
|
||||
// The debug-friendly names of those roles
|
||||
const char* role_friendly_name[] = { "invalid", "Remote", "LED Board"};
|
||||
|
||||
// The role of the current running sketch
|
||||
role_e role;
|
||||
|
||||
//
|
||||
// Payload
|
||||
//
|
||||
|
||||
uint8_t button_states[num_button_pins];
|
||||
uint8_t led_states[num_led_pins];
|
||||
|
||||
//
|
||||
// Setup
|
||||
//
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
//
|
||||
// Role
|
||||
//
|
||||
|
||||
// set up the role pin
|
||||
pinMode(role_pin, INPUT);
|
||||
digitalWrite(role_pin, HIGH);
|
||||
delay(20); // Just to get a solid reading on the role pin
|
||||
|
||||
// read the address pin, establish our role
|
||||
if ( digitalRead(role_pin) )
|
||||
role = role_remote;
|
||||
else
|
||||
role = role_led;
|
||||
|
||||
//
|
||||
// Print preamble
|
||||
//
|
||||
|
||||
Serial.begin(115200);
|
||||
printf_begin();
|
||||
printf("\n\rRF24/examples/led_remote/\n\r");
|
||||
printf("ROLE: %s\n\r", role_friendly_name[role]);
|
||||
|
||||
//
|
||||
// Setup and configure rf radio
|
||||
//
|
||||
|
||||
radio.begin();
|
||||
|
||||
//
|
||||
// Open pipes to other nodes for communication
|
||||
//
|
||||
|
||||
// This simple sketch opens a single pipes for these two nodes to communicate
|
||||
// back and forth. One listens on it, the other talks to it.
|
||||
|
||||
if ( role == role_remote )
|
||||
{
|
||||
radio.openWritingPipe(pipe);
|
||||
}
|
||||
else
|
||||
{
|
||||
radio.openReadingPipe(1, pipe);
|
||||
}
|
||||
|
||||
//
|
||||
// Start listening
|
||||
//
|
||||
|
||||
if ( role == role_led )
|
||||
radio.startListening();
|
||||
|
||||
//
|
||||
// Dump the configuration of the rf unit for debugging
|
||||
//
|
||||
|
||||
radio.printDetails();
|
||||
|
||||
//
|
||||
// Set up buttons / LED's
|
||||
//
|
||||
|
||||
// Set pull-up resistors for all buttons
|
||||
if ( role == role_remote )
|
||||
{
|
||||
int i = num_button_pins;
|
||||
while (i--)
|
||||
{
|
||||
pinMode(button_pins[i], INPUT);
|
||||
digitalWrite(button_pins[i], HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
// Turn LED's ON until we start getting keys
|
||||
if ( role == role_led )
|
||||
{
|
||||
int i = num_led_pins;
|
||||
while (i--)
|
||||
{
|
||||
pinMode(led_pins[i], OUTPUT);
|
||||
led_states[i] = HIGH;
|
||||
digitalWrite(led_pins[i], led_states[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Loop
|
||||
//
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
//
|
||||
// Remote role. If the state of any button has changed, send the whole state of
|
||||
// all buttons.
|
||||
//
|
||||
|
||||
if ( role == role_remote )
|
||||
{
|
||||
// Get the current state of buttons, and
|
||||
// Test if the current state is different from the last state we sent
|
||||
int i = num_button_pins;
|
||||
bool different = false;
|
||||
while (i--)
|
||||
{
|
||||
uint8_t state = ! digitalRead(button_pins[i]);
|
||||
if ( state != button_states[i] )
|
||||
{
|
||||
different = true;
|
||||
button_states[i] = state;
|
||||
}
|
||||
}
|
||||
|
||||
// Send the state of the buttons to the LED board
|
||||
if ( different )
|
||||
{
|
||||
printf("Now sending...");
|
||||
bool ok = radio.write( button_states, num_button_pins );
|
||||
if (ok)
|
||||
printf("ok\n\r");
|
||||
else
|
||||
printf("failed\n\r");
|
||||
}
|
||||
|
||||
// Try again in a short while
|
||||
delay(20);
|
||||
}
|
||||
|
||||
//
|
||||
// LED role. Receive the state of all buttons, and reflect that in the LEDs
|
||||
//
|
||||
|
||||
if ( role == role_led )
|
||||
{
|
||||
// if there is data ready
|
||||
if ( radio.available() )
|
||||
{
|
||||
// Dump the payloads until we've gotten everything
|
||||
while (radio.available())
|
||||
{
|
||||
// Fetch the payload, and see if this was the last one.
|
||||
radio.read( button_states, num_button_pins );
|
||||
|
||||
// Spew it
|
||||
printf("Got buttons\n\r");
|
||||
|
||||
// For each button, if the button now on, then toggle the LED
|
||||
int i = num_led_pins;
|
||||
while (i--)
|
||||
{
|
||||
if ( button_states[i] )
|
||||
{
|
||||
led_states[i] ^= HIGH;
|
||||
digitalWrite(led_pins[i], led_states[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// vim:ai:cin:sts=2 sw=2 ft=cpp
|
@ -0,0 +1,142 @@
|
||||
/*
|
||||
Copyright (C) 2012 J. Coliz <maniacbug@ymail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
Example Nordic FOB Receiver
|
||||
|
||||
This is an example of how to use the RF24 class to receive signals from the
|
||||
Sparkfun Nordic FOB. Thanks to Kirk Mower for providing test hardware.
|
||||
|
||||
See blog post at http://maniacbug.wordpress.com/2012/01/08/nordic-fob/
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <RF24.h>
|
||||
#include "nRF24L01.h"
|
||||
#include "printf.h"
|
||||
|
||||
//
|
||||
// Hardware configuration
|
||||
//
|
||||
|
||||
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
|
||||
|
||||
RF24 radio(9, 10);
|
||||
|
||||
//
|
||||
// Payload
|
||||
//
|
||||
|
||||
struct payload_t
|
||||
{
|
||||
uint8_t buttons;
|
||||
uint16_t id;
|
||||
uint8_t empty;
|
||||
};
|
||||
|
||||
const char* button_names[] = { "Up", "Down", "Left", "Right", "Center" };
|
||||
const int num_buttons = 5;
|
||||
|
||||
//
|
||||
// Forward declarations
|
||||
//
|
||||
|
||||
uint16_t flip_endian(uint16_t in);
|
||||
|
||||
//
|
||||
// Setup
|
||||
//
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
//
|
||||
// Print preamble
|
||||
//
|
||||
|
||||
Serial.begin(115200);
|
||||
printf_begin();
|
||||
printf("\r\nRF24/examples/nordic_fob/\r\n");
|
||||
|
||||
//
|
||||
// Setup and configure rf radio according to the built-in parameters
|
||||
// of the FOB.
|
||||
//
|
||||
|
||||
radio.begin();
|
||||
radio.setChannel(2);
|
||||
radio.setPayloadSize(4);
|
||||
radio.setAutoAck(false);
|
||||
radio.setCRCLength(RF24_CRC_8);
|
||||
radio.openReadingPipe(1, 0xE7E7E7E7E7LL);
|
||||
|
||||
//
|
||||
// Start listening
|
||||
//
|
||||
|
||||
radio.startListening();
|
||||
|
||||
//
|
||||
// Dump the configuration of the rf unit for debugging
|
||||
//
|
||||
|
||||
radio.printDetails();
|
||||
}
|
||||
|
||||
//
|
||||
// Loop
|
||||
//
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
//
|
||||
// Receive each packet, dump it out
|
||||
//
|
||||
|
||||
// if there is data ready
|
||||
if ( radio.available() )
|
||||
{
|
||||
// Get the packet from the radio
|
||||
payload_t payload;
|
||||
radio.read( &payload, sizeof(payload) );
|
||||
|
||||
// Print the ID of this message. Note that the message
|
||||
// is sent 'big-endian', so we have to flip it.
|
||||
printf("#%05u Buttons ", flip_endian(payload.id));
|
||||
|
||||
// Print the name of each button
|
||||
int i = num_buttons;
|
||||
while (i--)
|
||||
{
|
||||
if ( ! ( payload.buttons & _BV(i) ) )
|
||||
{
|
||||
printf("%s ", button_names[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// If no buttons, print None
|
||||
if ( payload.buttons == _BV(num_buttons) - 1 )
|
||||
printf("None");
|
||||
|
||||
printf("\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Helper functions
|
||||
//
|
||||
|
||||
// Change a big-endian word into a little-endian
|
||||
uint16_t flip_endian(uint16_t in)
|
||||
{
|
||||
uint16_t low = in >> 8;
|
||||
uint16_t high = in << 8;
|
||||
|
||||
return high | low;
|
||||
}
|
||||
|
||||
// vim:cin:ai:sts=2 sw=2 ft=cpp
|
@ -0,0 +1,87 @@
|
||||
#ifdef MAPLE_IDE
|
||||
|
||||
#include <stdio.h>
|
||||
#include "wirish.h"
|
||||
|
||||
extern void setup(void);
|
||||
extern void loop(void);
|
||||
|
||||
void board_start(const char* program_name)
|
||||
{
|
||||
// Set up the LED to steady on
|
||||
pinMode(BOARD_LED_PIN, OUTPUT);
|
||||
digitalWrite(BOARD_LED_PIN, HIGH);
|
||||
|
||||
// Setup the button as input
|
||||
pinMode(BOARD_BUTTON_PIN, INPUT);
|
||||
digitalWrite(BOARD_BUTTON_PIN, HIGH);
|
||||
|
||||
SerialUSB.begin();
|
||||
SerialUSB.println("Press BUT");
|
||||
|
||||
// Wait for button press
|
||||
while ( !isButtonPressed() )
|
||||
{
|
||||
}
|
||||
|
||||
SerialUSB.println("Welcome!");
|
||||
SerialUSB.println(program_name);
|
||||
|
||||
int i = 11;
|
||||
while (i--)
|
||||
{
|
||||
toggleLED();
|
||||
delay(50);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Custom version of _write, which will print to the USB.
|
||||
In order to use it you MUST ADD __attribute__((weak))
|
||||
to _write in libmaple/syscalls.c
|
||||
*/
|
||||
extern "C" int _write (int file, char * ptr, int len)
|
||||
{
|
||||
if ( (file != 1) && (file != 2) )
|
||||
return 0;
|
||||
else
|
||||
SerialUSB.write(ptr, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
Re-entrant version of _write. Yagarto and Devkit now use
|
||||
the re-entrant newlib, so these get called instead of the
|
||||
non_r versions.
|
||||
*/
|
||||
extern "C" int _write_r (void*, int file, char * ptr, int len)
|
||||
{
|
||||
return _write( file, ptr, len);
|
||||
}
|
||||
|
||||
__attribute__((constructor)) __attribute__ ((weak)) void premain()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
__attribute__((weak)) void setup(void)
|
||||
{
|
||||
board_start("No program defined");
|
||||
}
|
||||
|
||||
__attribute__((weak)) void loop(void)
|
||||
{
|
||||
}
|
||||
|
||||
__attribute__((weak)) int main(void)
|
||||
{
|
||||
setup();
|
||||
|
||||
while (true)
|
||||
{
|
||||
loop();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif // ifdef MAPLE_IDE
|
||||
// vim:cin:ai:sts=2 sw=2 ft=cpp
|
@ -0,0 +1,242 @@
|
||||
/*
|
||||
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
Example RF Radio Ping Pair ... for Maple
|
||||
|
||||
This is an example of how to use the RF24 class. Write this sketch to two different nodes,
|
||||
connect the role_pin to ground on one. The ping node sends the current time to the pong node,
|
||||
which responds by sending the value back. The ping node can then see how long the whole cycle
|
||||
took.
|
||||
*/
|
||||
|
||||
#include "WProgram.h"
|
||||
#include <SPI.h>
|
||||
#include "nRF24L01.h"
|
||||
#include "RF24.h"
|
||||
|
||||
//
|
||||
// Maple specific setup. Other than this section, the sketch is the same on Maple as on
|
||||
// Arduino
|
||||
//
|
||||
|
||||
#ifdef MAPLE_IDE
|
||||
|
||||
// External startup function
|
||||
extern void board_start(const char* program_name);
|
||||
|
||||
// Use SPI #2.
|
||||
HardwareSPI SPI(2);
|
||||
|
||||
#else
|
||||
#define board_startup printf
|
||||
#define toggleLED(x) (x)
|
||||
#endif
|
||||
|
||||
//
|
||||
// Hardware configuration
|
||||
//
|
||||
|
||||
// Set up nRF24L01 radio on SPI bus plus pins 7 & 6
|
||||
// (This works for the Getting Started board plugged into the
|
||||
// Maple Native backwards.)
|
||||
|
||||
RF24 radio(7, 6);
|
||||
|
||||
// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver
|
||||
// Leave open to be the 'ping' transmitter
|
||||
const int role_pin = 10;
|
||||
|
||||
//
|
||||
// Topology
|
||||
//
|
||||
|
||||
// Radio pipe addresses for the 2 nodes to communicate.
|
||||
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
|
||||
|
||||
//
|
||||
// Role management
|
||||
//
|
||||
// Set up role. This sketch uses the same software for all the nodes
|
||||
// in this system. Doing so greatly simplifies testing. The hardware itself specifies
|
||||
// which node it is.
|
||||
//
|
||||
// This is done through the role_pin
|
||||
//
|
||||
|
||||
// The various roles supported by this sketch
|
||||
typedef enum { role_ping_out = 1, role_pong_back } role_e;
|
||||
|
||||
// The debug-friendly names of those roles
|
||||
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};
|
||||
|
||||
// The role of the current running sketch
|
||||
role_e role;
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
//
|
||||
// Role
|
||||
//
|
||||
|
||||
// set up the role pin
|
||||
pinMode(role_pin, INPUT);
|
||||
digitalWrite(role_pin, HIGH);
|
||||
delay(20); // Just to get a solid reading on the role pin
|
||||
|
||||
// read the address pin, establish our role
|
||||
if ( digitalRead(role_pin) )
|
||||
role = role_ping_out;
|
||||
else
|
||||
role = role_pong_back;
|
||||
|
||||
//
|
||||
// Print preamble
|
||||
//
|
||||
|
||||
board_start("\n\rRF24/examples/pingpair/\n\r");
|
||||
printf("ROLE: %s\n\r", role_friendly_name[role]);
|
||||
|
||||
//
|
||||
// Setup and configure rf radio
|
||||
//
|
||||
|
||||
radio.begin();
|
||||
|
||||
// optionally, increase the delay between retries & # of retries
|
||||
radio.setRetries(15, 15);
|
||||
|
||||
// optionally, reduce the payload size. seems to
|
||||
// improve reliability
|
||||
radio.setPayloadSize(8);
|
||||
|
||||
//
|
||||
// Open pipes to other nodes for communication
|
||||
//
|
||||
|
||||
// This simple sketch opens two pipes for these two nodes to communicate
|
||||
// back and forth.
|
||||
// Open 'our' pipe for writing
|
||||
// Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading)
|
||||
|
||||
if ( role == role_ping_out )
|
||||
{
|
||||
radio.openWritingPipe(pipes[0]);
|
||||
radio.openReadingPipe(1, pipes[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
radio.openWritingPipe(pipes[1]);
|
||||
radio.openReadingPipe(1, pipes[0]);
|
||||
}
|
||||
|
||||
//
|
||||
// Start listening
|
||||
//
|
||||
|
||||
radio.startListening();
|
||||
|
||||
//
|
||||
// Dump the configuration of the rf unit for debugging
|
||||
//
|
||||
|
||||
radio.printDetails();
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
//
|
||||
// Ping out role. Repeatedly send the current time
|
||||
//
|
||||
|
||||
if (role == role_ping_out)
|
||||
{
|
||||
toggleLED();
|
||||
|
||||
// First, stop listening so we can talk.
|
||||
radio.stopListening();
|
||||
|
||||
// Take the time, and send it. This will block until complete
|
||||
unsigned long time = millis();
|
||||
printf("Now sending %lu...", time);
|
||||
bool ok = radio.write( &time, sizeof(unsigned long) );
|
||||
|
||||
if (ok)
|
||||
printf("ok...\r\n");
|
||||
else
|
||||
printf("failed.\r\n");
|
||||
|
||||
// Now, continue listening
|
||||
radio.startListening();
|
||||
|
||||
// Wait here until we get a response, or timeout (250ms)
|
||||
unsigned long started_waiting_at = millis();
|
||||
bool timeout = false;
|
||||
while ( ! radio.available() && ! timeout )
|
||||
if (millis() - started_waiting_at > 200 )
|
||||
timeout = true;
|
||||
|
||||
// Describe the results
|
||||
if ( timeout )
|
||||
{
|
||||
printf("Failed, response timed out.\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Grab the response, compare, and send to debugging spew
|
||||
unsigned long got_time;
|
||||
radio.read( &got_time, sizeof(unsigned long) );
|
||||
|
||||
// Spew it
|
||||
printf("Got response %lu, round-trip delay: %lu\r\n", got_time, millis() - got_time);
|
||||
}
|
||||
|
||||
toggleLED();
|
||||
|
||||
// Try again 1s later
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
//
|
||||
// Pong back role. Receive each packet, dump it out, and send it back
|
||||
//
|
||||
|
||||
if ( role == role_pong_back )
|
||||
{
|
||||
// if there is data ready
|
||||
if ( radio.available() )
|
||||
{
|
||||
// Dump the payloads until we've gotten everything
|
||||
unsigned long got_time;
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
// Fetch the payload, and see if this was the last one.
|
||||
done = radio.read( &got_time, sizeof(unsigned long) );
|
||||
|
||||
// Spew it
|
||||
printf("Got payload %lu...", got_time);
|
||||
|
||||
// Delay just a little bit to let the other unit
|
||||
// make the transition to receiver
|
||||
delay(20);
|
||||
}
|
||||
|
||||
// First, stop listening so we can talk
|
||||
radio.stopListening();
|
||||
|
||||
// Send the final one back.
|
||||
radio.write( &got_time, sizeof(unsigned long) );
|
||||
printf("Sent response.\r\n");
|
||||
|
||||
// Now, resume listening so we catch the next packets.
|
||||
radio.startListening();
|
||||
}
|
||||
}
|
||||
}
|
||||
// vim:cin:ai:sts=2 sw=2 ft=cpp
|
@ -0,0 +1,2 @@
|
||||
Note: These recipe examples may have not been maintained with library updates, and are provided as-is for reference purposes.
|
||||
Warning: These are recipe examples are intended for specific hardware usage.
|
153
src/libs/RF24-master/examples/old_backups/scanner/scanner.ino
Normal file
153
src/libs/RF24-master/examples/old_backups/scanner/scanner.ino
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
|
||||
* Updated 2020 TMRh20
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Channel scanner and Continuous Carrier Wave Output
|
||||
*
|
||||
* Example to detect interference on the various channels available.
|
||||
* This is a good diagnostic tool to check whether you're picking a
|
||||
* good channel for your application.
|
||||
*
|
||||
* Run this sketch on two devices. On one device, start CCW output by sending a 'g'
|
||||
* character over Serial. The other device scanning should detect the output of the sending
|
||||
* device on the given channel. Adjust channel and output power of CCW below.
|
||||
*
|
||||
* Inspired by cpixip.
|
||||
* See http://arduino.cc/forum/index.php/topic,54795.0.html
|
||||
*/
|
||||
|
||||
#include "RF24.h"
|
||||
#include "printf.h"
|
||||
|
||||
//
|
||||
// Hardware configuration
|
||||
//
|
||||
|
||||
// Set up nRF24L01 radio on SPI bus plus pins 7 & 8
|
||||
|
||||
RF24 radio(7, 8);
|
||||
|
||||
//
|
||||
// Channel info
|
||||
//
|
||||
|
||||
const uint8_t num_channels = 126;
|
||||
uint8_t values[num_channels];
|
||||
|
||||
//
|
||||
// Setup
|
||||
//
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
//
|
||||
// Print preamble
|
||||
//
|
||||
|
||||
Serial.begin(115200);
|
||||
printf_begin();
|
||||
Serial.println(F("\n\rRF24/examples/scanner/"));
|
||||
|
||||
//
|
||||
// Setup and configure rf radio
|
||||
//
|
||||
|
||||
radio.begin();
|
||||
radio.setAutoAck(false);
|
||||
|
||||
// Get into standby mode
|
||||
radio.startListening();
|
||||
radio.stopListening();
|
||||
radio.printDetails();
|
||||
|
||||
//delay(1000);
|
||||
// Print out header, high then low digit
|
||||
int i = 0;
|
||||
while ( i < num_channels )
|
||||
{
|
||||
Serial.print(i >> 4, HEX);
|
||||
++i;
|
||||
}
|
||||
Serial.println();
|
||||
i = 0;
|
||||
while ( i < num_channels )
|
||||
{
|
||||
Serial.print(i & 0xf, HEX);
|
||||
++i;
|
||||
}
|
||||
Serial.println();
|
||||
//delay(1000);
|
||||
}
|
||||
|
||||
//
|
||||
// Loop
|
||||
//
|
||||
|
||||
const int num_reps = 100;
|
||||
bool constCarrierMode = 0;
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
/****************************************/
|
||||
// Send g over Serial to begin CCW output
|
||||
// Configure the channel and power level below
|
||||
if (Serial.available()) {
|
||||
char c = Serial.read();
|
||||
if (c == 'g') {
|
||||
constCarrierMode = 1;
|
||||
radio.stopListening();
|
||||
delay(2);
|
||||
Serial.println("Starting Carrier Out");
|
||||
radio.startConstCarrier(RF24_PA_LOW, 40);
|
||||
} else if (c == 'e') {
|
||||
constCarrierMode = 0;
|
||||
radio.stopConstCarrier();
|
||||
Serial.println("Stopping Carrier Out");
|
||||
}
|
||||
}
|
||||
/****************************************/
|
||||
|
||||
if (constCarrierMode == 0) {
|
||||
// Clear measurement values
|
||||
memset(values, 0, sizeof(values));
|
||||
|
||||
// Scan all channels num_reps times
|
||||
int rep_counter = num_reps;
|
||||
while (rep_counter--)
|
||||
{
|
||||
int i = num_channels;
|
||||
while (i--)
|
||||
{
|
||||
// Select this channel
|
||||
radio.setChannel(i);
|
||||
|
||||
// Listen for a little
|
||||
radio.startListening();
|
||||
delayMicroseconds(128);
|
||||
radio.stopListening();
|
||||
|
||||
// Did we get a carrier?
|
||||
if ( radio.testCarrier() ) {
|
||||
++values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Print out channel measurements, clamped to a single hex digit
|
||||
int i = 0;
|
||||
while ( i < num_channels )
|
||||
{
|
||||
Serial.print(min(0xf, values[i]), HEX);
|
||||
++i;
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
}//If constCarrierMode == 0
|
||||
}
|
@ -0,0 +1,204 @@
|
||||
/**
|
||||
* See documentation at https://nRF24.github.io/RF24
|
||||
* See License information at root directory of this library
|
||||
* written in 2014 by tong67 (https://github.com/tong67)
|
||||
* Updated 2020 by 2bndy5 (http://github.com/2bndy5) for the
|
||||
* SpenceKonde ATTinyCore (https://github.com/SpenceKonde/ATTinyCore)
|
||||
*/
|
||||
|
||||
/**
|
||||
* The RF24 library uses the [ATTinyCore by
|
||||
* SpenceKonde](https://github.com/SpenceKonde/ATTinyCore)
|
||||
*
|
||||
* This sketch is a duplicate of the ManualAcknowledgements.ino example
|
||||
* (without all the Serial input/output code), and it demonstrates
|
||||
* a ATTiny25/45/85 or ATTiny24/44/84 driving the nRF24L01 transceiver using
|
||||
* the RF24 class to communicate with another node.
|
||||
*
|
||||
* A simple example of sending data from 1 nRF24L01 transceiver to another
|
||||
* with manually transmitted (non-automatic) Acknowledgement (ACK) payloads.
|
||||
* This example still uses ACK packets, but they have no payloads. Instead the
|
||||
* acknowledging response is sent with `write()`. This tactic allows for more
|
||||
* updated acknowledgement payload data, where actual ACK payloads' data are
|
||||
* outdated by 1 transmission because they have to loaded before receiving a
|
||||
* transmission.
|
||||
*
|
||||
* This example was written to be used on 2 devices acting as "nodes".
|
||||
*/
|
||||
|
||||
/*
|
||||
* ********** Hardware configuration (& schematics) *******************
|
||||
*
|
||||
* When direct use of 3V does not work (UNO boards tend to have poor 3V supply),
|
||||
* use 5V with LED (1.8V ~ 2.2V drop) instead.
|
||||
* For low power consumption solutions floating pins (SCK and MOSI) should be
|
||||
* pulled HIGH or LOW with 10K resistors.
|
||||
*
|
||||
* ATTiny25/45/85 Pin map with CE_PIN 3 and CSN_PIN 4
|
||||
* ^^
|
||||
* +-\/-+ //
|
||||
* PB5 1|o |8 Vcc --- nRF24L01 VCC --- |<|--- 5V
|
||||
* nRF24L01 CE --- PB3 2| |7 PB2 --- nRF24L01 SCK LED
|
||||
* nRF24L01 CSN --- PB4 3| |6 PB1 --- nRF24L01 MOSI
|
||||
* nRF24L01 GND --- GND 4| |5 PB0 --- nRF24L01 MISO
|
||||
* +----+
|
||||
*
|
||||
* ATTiny25/45/85 Pin map with CE_PIN 3 and CSN_PIN 3 => PB3 and PB4 are
|
||||
* free to use for other purposes. This "3 pin solution" is from
|
||||
* Ralph Doncaster (AKA NerdRalph) which is outlined on his blog at
|
||||
* http://nerdralph.blogspot.ca/2014/01/nrf24l01-control-with-3-attiny85-pins.html
|
||||
* Original RC combination was 1K/100nF. 22K/10nF combination worked better.
|
||||
*
|
||||
* For best settle time delay value to use for RF24::csDelay in RF24::csn(), use
|
||||
* the examples/rf24_ATTiny/timingSearch3pin/timingSearch3pin.ino sketch.
|
||||
*
|
||||
* This configuration is enabled in the RF24 library when CE_PIN and
|
||||
* CSN_PIN parameters to the constructor are equal. Notice (in the schematic
|
||||
* below) that these pins aren't directly to the ATTiny85. Because the CE pin
|
||||
* is always HIGH, the power consumption is higher than it would be for the
|
||||
* typical 5 pins solution.
|
||||
* ^^
|
||||
* +-\/-+ nRF24L01 CE --------| //
|
||||
* PB5 1|o |8 Vcc --- nRF24L01 VCC -------x----------x--|<|-- 5V
|
||||
* PB3 2| |7 PB2 --- nRF24L01 SCK ---|<|---x-[22k]--| LED
|
||||
* PB4 3| |6 PB1 --- nRF24L01 MOSI 1n4148 |
|
||||
* nRF24L01 GND -x- GND 4| |5 PB0 --- nRF24L01 MISO |
|
||||
* | +----+ |
|
||||
* |-----------------------------------------||----x-- nRF24L01 CSN
|
||||
* 10nF
|
||||
*
|
||||
* ATTiny24/44/84 Pin map with CE_PIN 8 and CSN_PIN 7 & assuming 1.9V to 3V on VCC
|
||||
* Schematic provided and successfully tested by
|
||||
* Carmine Pastore (https://github.com/Carminepz)
|
||||
*
|
||||
* +-\/-+
|
||||
* nRF24L01 VCC ---- VCC 1|o |14 GND --- nRF24L01 GND
|
||||
* PB0 2| |13 AREF
|
||||
* PB1 3| |12 PA1
|
||||
* PB3 4| |11 PA2 --- nRF24L01 CE
|
||||
* PB2 5| |10 PA3 --- nRF24L01 CSN
|
||||
* PA7 6| |9 PA4 --- nRF24L01 SCK
|
||||
* nRF24L01 MOSI --- PA6 7| |8 PA5 --- nRF24L01 MISO
|
||||
* +----+
|
||||
*/
|
||||
|
||||
#include "SPI.h"
|
||||
#include "RF24.h"
|
||||
|
||||
// CE and CSN are configurable, specified values for ATTiny85 as connected above
|
||||
#define CE_PIN 3
|
||||
#define CSN_PIN 4
|
||||
//#define CSN_PIN 3 // uncomment for ATTiny85 3 pins solution
|
||||
|
||||
// instantiate an object for the nRF24L01 transceiver
|
||||
RF24 radio(CE_PIN, CSN_PIN);
|
||||
|
||||
// Let these addresses be used for the pair
|
||||
uint8_t address[][6] = {"1Node", "2Node"};
|
||||
// It is very helpful to think of an address as a path instead of as
|
||||
// an identifying device destination
|
||||
|
||||
// to use different addresses on a pair of radios, we need a variable to
|
||||
// uniquely identify which address this radio will use to transmit
|
||||
bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
|
||||
// Used to control whether this node is sending or receiving
|
||||
bool role = false; // true = TX node, false = RX node
|
||||
|
||||
// For this example, we'll be using a payload containing
|
||||
// a string & an integer number that will be incremented
|
||||
// on every successful transmission.
|
||||
// Make a data structure to store the entire payload of different datatypes
|
||||
struct PayloadStruct {
|
||||
char message[7]; // only using 6 characters for TX & RX payloads
|
||||
uint8_t counter;
|
||||
};
|
||||
PayloadStruct payload;
|
||||
|
||||
void setup() {
|
||||
|
||||
// append a NULL terminating character for printing as a c-string
|
||||
payload.message[6] = 0;
|
||||
|
||||
// initialize the transceiver on the SPI bus
|
||||
if (!radio.begin()) {
|
||||
while (1) {} // hold in infinite loop
|
||||
}
|
||||
|
||||
// Set the PA Level low to try preventing power supply related problems
|
||||
// because these examples are likely run with nodes in close proximity to
|
||||
// each other.
|
||||
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
|
||||
|
||||
// save on transmission time by setting the radio to only transmit the
|
||||
// number of bytes we need to transmit a float
|
||||
radio.setPayloadSize(sizeof(payload)); // char[7] & uint8_t datatypes occupy 8 bytes
|
||||
|
||||
// set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radioNumber]); // always uses pipe 0
|
||||
|
||||
// set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1
|
||||
|
||||
if (role) {
|
||||
// setup the TX node
|
||||
|
||||
memcpy(payload.message, "Hello ", 6); // set the outgoing message
|
||||
radio.stopListening(); // put radio in TX mode
|
||||
} else {
|
||||
// setup the RX node
|
||||
|
||||
memcpy(payload.message, "World ", 6); // set the outgoing message
|
||||
radio.startListening(); // put radio in RX mode
|
||||
}
|
||||
} // setup()
|
||||
|
||||
void loop() {
|
||||
|
||||
if (role) {
|
||||
// This device is a TX node
|
||||
|
||||
bool report = radio.write(&payload, sizeof(payload)); // transmit & save the report
|
||||
|
||||
if (report) {
|
||||
// transmission successful; wait for response and print results
|
||||
|
||||
radio.startListening(); // put in RX mode
|
||||
unsigned long start_timeout = millis(); // timer to detect no response
|
||||
while (!radio.available()) { // wait for response or timeout
|
||||
if (millis() - start_timeout > 200) // only wait 200 ms
|
||||
break;
|
||||
}
|
||||
radio.stopListening(); // put back in TX mode
|
||||
|
||||
// print summary of transactions
|
||||
if (radio.available()) { // is there a payload received?
|
||||
|
||||
PayloadStruct received;
|
||||
radio.read(&received, sizeof(received)); // get payload from RX FIFO
|
||||
payload.counter = received.counter; // save incoming counter for next outgoing counter
|
||||
}
|
||||
} // report
|
||||
|
||||
// to make this example readable in the serial monitor
|
||||
delay(1000); // slow transmissions down by 1 second
|
||||
|
||||
} else {
|
||||
// This device is a RX node
|
||||
|
||||
if (radio.available()) { // is there a payload?
|
||||
|
||||
PayloadStruct received;
|
||||
radio.read(&received, sizeof(received)); // get incoming payload
|
||||
payload.counter = received.counter + 1; // increment incoming counter for next outgoing response
|
||||
|
||||
// transmit response & save result to `report`
|
||||
radio.stopListening(); // put in TX mode
|
||||
|
||||
radio.writeFast(&payload, sizeof(payload)); // load response to TX FIFO
|
||||
bool report = radio.txStandBy(150); // keep retrying for 150 ms
|
||||
|
||||
radio.startListening(); // put back in RX mode
|
||||
}
|
||||
} // role
|
||||
} // loop
|
@ -0,0 +1,209 @@
|
||||
/**
|
||||
* See documentation at https://nRF24.github.io/RF24
|
||||
* See License information at root directory of this library
|
||||
* written by tong67 (https://github.com/tong67)
|
||||
* edited by 2bndy5 (http://github.com/2bndy5) for compatibility with SpenceKonde's ATTinyCore
|
||||
*/
|
||||
|
||||
/*
|
||||
* This sketch can determine the best settle time values to use for
|
||||
* macros, defined as RF24_CSN_SETTLE_HIGH_DELAY and RF24_CSN_SETTLE_LOW_DELAY,
|
||||
* in RF24::csn().
|
||||
* The settle time values used here are 100/20. However, these values depend
|
||||
* on the actual used RC combiniation and voltage drop by LED. The
|
||||
* intermediate results are written to TX (PB3, pin 2 -- using Serial).
|
||||
*
|
||||
* For schematic details, see introductory comment block in the
|
||||
* examples/rf24_ATTiny/rf24ping85/rf24ping85.ino sketch.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <SPI.h>
|
||||
#include <Arduino.h>
|
||||
#include <nRF24L01.h>
|
||||
|
||||
|
||||
#if defined (ARDUINO) && !defined (__arm__)
|
||||
#if defined(__AVR_ATtinyX5__) || defined(__AVR_ATtinyX4__)
|
||||
#define RF24_TINY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#if defined(RF24_TINY)
|
||||
|
||||
// when Attiny84 or Attiny85 is detected
|
||||
#define CE_PIN 3 /** "Chip Enable" pin, activates the RX or TX role */
|
||||
#define CSN_PIN 3 /** SPI Chip Select Not */
|
||||
|
||||
#else
|
||||
// when not running on an ATTiny84 or ATTiny85
|
||||
#define CE_PIN 7 /** "Chip Enable" pin, activates the RX or TX role */
|
||||
#define CSN_PIN 8 /** SPI Chip Select Not */
|
||||
|
||||
#endif
|
||||
|
||||
#define MAX_HIGH 100
|
||||
#define MAX_LOW 100
|
||||
#define MINIMAL 8
|
||||
|
||||
// Use these adjustable variables to test for best configuration to be used on
|
||||
// the ATTiny chips. These variables are defined as macros in the library's
|
||||
// RF24/utility/ATTiny/RF24_arch_config.h file. To change them, simply define
|
||||
// the corresponding macro(s) before #include <RF24> in your sketch.
|
||||
uint8_t csnHighSettle = MAX_HIGH; // defined as RF24_CSN_SETTLE_HIGH_DELAY
|
||||
uint8_t csnLowSettle = MAX_LOW; // defined as RF24_CSN_SETTLE_LOW_DELAY
|
||||
|
||||
/****************************************************************************/
|
||||
void ce(bool level) {
|
||||
if (CE_PIN != CSN_PIN) digitalWrite(CE_PIN, level);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
void csn(bool mode) {
|
||||
if (CE_PIN != CSN_PIN) {
|
||||
digitalWrite(CSN_PIN, mode);
|
||||
} else {
|
||||
// digitalWrite(SCK, mode);
|
||||
if (mode == HIGH) {
|
||||
PORTB |= (1 << PINB2); // SCK->CSN HIGH
|
||||
delayMicroseconds(csnHighSettle); // allow csn to settle
|
||||
} else {
|
||||
PORTB &= ~(1 << PINB2); // SCK->CSN LOW
|
||||
delayMicroseconds(csnLowSettle); // allow csn to settle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
uint8_t read_register(uint8_t reg)
|
||||
{
|
||||
csn(LOW);
|
||||
SPI.transfer(R_REGISTER | reg);
|
||||
uint8_t result = SPI.transfer(0xff);
|
||||
csn(HIGH);
|
||||
return result;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
void write_register(uint8_t reg, uint8_t value)
|
||||
{
|
||||
csn(LOW);
|
||||
SPI.transfer(W_REGISTER | reg);
|
||||
SPI.transfer(value);
|
||||
csn(HIGH);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
void setup(void) {
|
||||
|
||||
#ifndef __AVR_ATtinyX313__
|
||||
// not enough memory on ATTiny4313 or ATTint2313(a) to use Serial I/O for this sketch
|
||||
|
||||
// start serial port and SPI
|
||||
Serial.begin(115200);
|
||||
SPI.begin();
|
||||
// configure CE and CSN as output when used
|
||||
pinMode(CE_PIN, OUTPUT);
|
||||
if (CSN_PIN != CE_PIN)
|
||||
pinMode(CSN_PIN, OUTPUT);
|
||||
|
||||
// csn is used in SPI transfers. Set to LOW at start and HIGH after transfer. Set to HIGH to reflect no transfer active
|
||||
// SPI command are accepted in Power Down state.
|
||||
// CE pin represent PRX (LOW) or PTX (HIGH) mode apart from register settings. Start in PRX mode.
|
||||
ce(LOW);
|
||||
csn(HIGH);
|
||||
|
||||
// nRF24L01 goes from to Power Down state 100ms after Power on Reset ( Vdd > 1.9V) or when PWR_UP is 0 in config register
|
||||
// Goto Power Down state (Powerup or force) and set in transmit mode
|
||||
write_register(NRF_CONFIG, read_register(NRF_CONFIG) & ~_BV(PWR_UP) & ~_BV(PRIM_RX));
|
||||
delay(100);
|
||||
|
||||
// Goto Standby-I
|
||||
// Technically we require 4.5ms Tpd2stby+ 14us as a worst case. We'll just call it 5ms for good measure.
|
||||
// WARNING: Delay is based on P-variant whereby non-P *may* require different timing.
|
||||
write_register(NRF_CONFIG, read_register(NRF_CONFIG) | _BV(PWR_UP));
|
||||
delay(5) ;
|
||||
|
||||
// Goto Standby-II
|
||||
ce(HIGH);
|
||||
Serial.print("Scanning for optimal setting time for csn");
|
||||
|
||||
|
||||
/************************** Main program *********************************/
|
||||
|
||||
uint8_t result; // used to compare read/write results with read/write cmds
|
||||
bool success = true;
|
||||
uint8_t bottom_success;
|
||||
bool bottom_found;
|
||||
uint8_t value[] = {5, 10};
|
||||
uint8_t limit[] = {MAX_HIGH, MAX_LOW};
|
||||
uint8_t advice[] = {MAX_HIGH, MAX_LOW};
|
||||
|
||||
// check max values give correct behavior
|
||||
for (uint8_t k = 0; k < 2; k++) {
|
||||
bottom_found = false;
|
||||
bottom_success = 0;
|
||||
while (bottom_success < 255) {
|
||||
csnHighSettle = limit[0];
|
||||
csnLowSettle = limit[1];
|
||||
// check current values
|
||||
uint8_t i = 0;
|
||||
while (i < 255 && success) {
|
||||
for (uint8_t j = 0; j < 2; j++) {
|
||||
write_register(EN_AA, value[j]);
|
||||
result = read_register(EN_AA);
|
||||
if (value[j] != result) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
// process result of current values
|
||||
if (!success) {
|
||||
Serial.print("Settle Not OK. csnHigh=");
|
||||
Serial.print(limit[0], DEC);
|
||||
Serial.print(" csnLow=");
|
||||
Serial.println(limit[1], DEC);
|
||||
limit[k]++;
|
||||
bottom_found = true;
|
||||
bottom_success = 0;
|
||||
success = true;
|
||||
} else {
|
||||
Serial.print("Settle OK. csnHigh=");
|
||||
Serial.print(limit[0], DEC);
|
||||
Serial.print(" csnLow=");
|
||||
Serial.println(limit[1], DEC);
|
||||
if (!bottom_found) {
|
||||
limit[k]--;
|
||||
if (limit[k] == MINIMAL) {
|
||||
bottom_found = true;
|
||||
bottom_success = 0;
|
||||
success = true;
|
||||
}
|
||||
} else {
|
||||
bottom_success++;
|
||||
}
|
||||
}
|
||||
} // while (bottom_success < 255)
|
||||
Serial.print("Settle value found for ");
|
||||
if (k == 0) {
|
||||
Serial.print("csnHigh: ");
|
||||
} else {
|
||||
Serial.print("csnLow: ");
|
||||
}
|
||||
Serial.println(limit[k], DEC);
|
||||
advice[k] = limit[k] + (limit[k] / 10);
|
||||
limit[k] = 100;
|
||||
} // for (uint8_t k = 0; k < 2; k++)
|
||||
Serial.print("Advised Settle times are: csnHigh=");
|
||||
Serial.print(advice[0], DEC);
|
||||
Serial.print(" csnLow=");
|
||||
Serial.println(advice[1], DEC);
|
||||
|
||||
#endif // not defined __AVR_ATtinyX313__
|
||||
}
|
||||
|
||||
|
||||
void loop(void) {} // this program runs only once, thus it resides in setup()
|
23
src/libs/RF24-master/examples_linux/Makefile
Normal file
23
src/libs/RF24-master/examples_linux/Makefile
Normal file
@ -0,0 +1,23 @@
|
||||
#############################################################################
|
||||
#
|
||||
# Makefile for librf24 examples on Linux
|
||||
#
|
||||
# License: GPL (General Public License)
|
||||
# Author: gnulnulf <arco@appeltaart.mine.nu>
|
||||
# Date: 2013/02/07 (version 1.0)
|
||||
#
|
||||
# Description:
|
||||
# ------------
|
||||
# use make all and make install to install the examples
|
||||
#
|
||||
|
||||
ifeq ($(wildcard ../Makefile.inc), )
|
||||
$(error Configuration not found. Run ./configure first)
|
||||
endif
|
||||
|
||||
include ../Makefile.inc
|
||||
|
||||
# define all programs
|
||||
PROGRAMS = gettingstarted acknowledgementPayloads manualAcknowledgements streamingData multiceiverDemo interruptConfigure
|
||||
|
||||
include Makefile.examples
|
230
src/libs/RF24-master/examples_linux/acknowledgementPayloads.cpp
Normal file
230
src/libs/RF24-master/examples_linux/acknowledgementPayloads.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* See documentation at https://nRF24.github.io/RF24
|
||||
* See License information at root directory of this library
|
||||
* Author: Brendan Doherty (2bndy5)
|
||||
*/
|
||||
|
||||
/**
|
||||
* A simple example of sending data from 1 nRF24L01 transceiver to another
|
||||
* with Acknowledgement (ACK) payloads attached to ACK packets.
|
||||
*
|
||||
* This example was written to be used on 2 devices acting as "nodes".
|
||||
* Use `ctrl+c` to quit at any time.
|
||||
*/
|
||||
#include <ctime> // time()
|
||||
#include <iostream> // cin, cout, endl
|
||||
#include <string> // string, getline()
|
||||
#include <time.h> // CLOCK_MONOTONIC_RAW, timespec, clock_gettime()
|
||||
#include <RF24/RF24.h> // RF24, RF24_PA_LOW, delay()
|
||||
|
||||
using namespace std;
|
||||
|
||||
/****************** Linux ***********************/
|
||||
// Radio CE Pin, CSN Pin, SPI Speed
|
||||
// CE Pin uses GPIO number with BCM and SPIDEV drivers, other platforms use their own pin numbering
|
||||
// CS Pin addresses the SPI bus number at /dev/spidev<a>.<b>
|
||||
// ie: RF24 radio(<ce_pin>, <a>*10+<b>); spidev1.0 is 10, spidev1.1 is 11 etc..
|
||||
|
||||
// Generic:
|
||||
RF24 radio(22, 0);
|
||||
/****************** Linux (BBB,x86,etc) ***********************/
|
||||
// See http://nRF24.github.io/RF24/pages.html for more information on usage
|
||||
// See http://iotdk.intel.com/docs/master/mraa/ for more information on MRAA
|
||||
// See https://www.kernel.org/doc/Documentation/spi/spidev for more information on SPIDEV
|
||||
|
||||
// For this example, we'll be using a payload containing
|
||||
// a string & an integer number that will be incremented
|
||||
// on every successful transmission.
|
||||
// Make a data structure to store the entire payload of different datatypes
|
||||
struct PayloadStruct {
|
||||
char message[7]; // only using 6 characters for TX & ACK payloads
|
||||
uint8_t counter;
|
||||
};
|
||||
PayloadStruct payload;
|
||||
|
||||
void setRole(); // prototype to set the node's role
|
||||
void master(); // prototype of the TX node's behavior
|
||||
void slave(); // prototype of the RX node's behavior
|
||||
|
||||
// custom defined timer for evaluating transmission time in microseconds
|
||||
struct timespec startTimer, endTimer;
|
||||
uint32_t getMicros(); // prototype to get ellapsed time in microseconds
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
// perform hardware check
|
||||
if (!radio.begin()) {
|
||||
cout << "radio hardware is not responding!!" << endl;
|
||||
return 0; // quit now
|
||||
}
|
||||
|
||||
// Let these addresses be used for the pair
|
||||
uint8_t address[2][6] = {"1Node", "2Node"};
|
||||
// It is very helpful to think of an address as a path instead of as
|
||||
// an identifying device destination
|
||||
|
||||
// to use different addresses on a pair of radios, we need a variable to
|
||||
// uniquely identify which address this radio will use to transmit
|
||||
bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
|
||||
// print example's name
|
||||
cout << argv[0] << endl;
|
||||
|
||||
// Set the radioNumber via the terminal on startup
|
||||
cout << "Which radio is this? Enter '0' or '1'. Defaults to '0' ";
|
||||
string input;
|
||||
getline(cin, input);
|
||||
radioNumber = input.length() > 0 && (uint8_t)input[0] == 49;
|
||||
|
||||
// to use ACK payloads, we need to enable dynamic payload lengths
|
||||
radio.enableDynamicPayloads(); // ACK payloads are dynamically sized
|
||||
|
||||
// Acknowledgement packets have no payloads by default. We need to enable
|
||||
// this feature for all nodes (TX & RX) to use ACK payloads.
|
||||
radio.enableAckPayload();
|
||||
|
||||
// Set the PA Level low to try preventing power supply related problems
|
||||
// because these examples are likely run with nodes in close proximity to
|
||||
// each other.
|
||||
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
|
||||
|
||||
// set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radioNumber]); // always uses pipe 0
|
||||
|
||||
// set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1
|
||||
|
||||
// For debugging info
|
||||
// radio.printDetails(); // (smaller) function that prints raw register values
|
||||
// radio.printPrettyDetails(); // (larger) function that prints human readable data
|
||||
|
||||
// ready to execute program now
|
||||
setRole(); // calls master() or slave() based on user input
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* set this node's role from stdin stream.
|
||||
* this only considers the first char as input.
|
||||
*/
|
||||
void setRole() {
|
||||
string input = "";
|
||||
while (!input.length()) {
|
||||
cout << "*** PRESS 'T' to begin transmitting to the other node\n";
|
||||
cout << "*** PRESS 'R' to begin receiving from the other node\n";
|
||||
cout << "*** PRESS 'Q' to exit" << endl;
|
||||
getline(cin, input);
|
||||
if (input.length() >= 1) {
|
||||
if (input[0] == 'T' || input[0] == 't')
|
||||
master();
|
||||
else if (input[0] == 'R' || input[0] == 'r')
|
||||
slave();
|
||||
else if (input[0] == 'Q' || input[0] == 'q')
|
||||
break;
|
||||
else
|
||||
cout << input[0] << " is an invalid input. Please try again." << endl;
|
||||
}
|
||||
input = ""; // stay in the while loop
|
||||
} // while
|
||||
} // setRole()
|
||||
|
||||
|
||||
/**
|
||||
* make this node act as the transmitter
|
||||
*/
|
||||
void master() {
|
||||
memcpy(payload.message, "Hello ", 6); // set the payload message
|
||||
radio.stopListening(); // put radio in TX mode
|
||||
|
||||
unsigned int failures = 0; // keep track of failures
|
||||
while (failures < 6) {
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &startTimer); // start the timer
|
||||
bool report = radio.write(&payload, sizeof(payload)); // transmit & save the report
|
||||
uint32_t timerEllapsed = getMicros(); // end the timer
|
||||
|
||||
if (report) {
|
||||
// payload was delivered
|
||||
cout << "Transmission successful! Time to transmit = ";
|
||||
cout << timerEllapsed; // print the timer result
|
||||
cout << " us. Sent: ";
|
||||
cout << payload.message; // print outgoing message
|
||||
cout << (unsigned int)payload.counter; // print outgoing counter counter
|
||||
|
||||
uint8_t pipe;
|
||||
if (radio.available(&pipe)) {
|
||||
PayloadStruct received;
|
||||
radio.read(&received, sizeof(received)); // get incoming ACK payload
|
||||
cout << " Received ";
|
||||
cout << radio.getDynamicPayloadSize(); // print incoming payload size
|
||||
cout << " bytes on pipe " << (unsigned int)pipe; // print pipe that received it
|
||||
cout << ": " << received.message; // print incoming message
|
||||
cout << (unsigned int)received.counter << endl; // print incoming counter
|
||||
payload.counter = received.counter + 1; // save incoming counter & increment for next outgoing
|
||||
} // if got an ACK payload
|
||||
else {
|
||||
cout << " Received an empty ACK packet." << endl; // ACK had no payload
|
||||
}
|
||||
} // if delivered
|
||||
else {
|
||||
cout << "Transmission failed or timed out" << endl; // payload was not delivered
|
||||
failures++; // increment failures
|
||||
}
|
||||
|
||||
// to make this example readable in the terminal
|
||||
delay(1000); // slow transmissions down by 1 second
|
||||
} // while
|
||||
cout << failures << " failures detected. Leaving TX role." << endl;
|
||||
} // master
|
||||
|
||||
|
||||
/**
|
||||
* make this node act as the receiver
|
||||
*/
|
||||
void slave() {
|
||||
memcpy(payload.message, "World ", 6); // set the payload message
|
||||
|
||||
// load the payload for the first received transmission on pipe 0
|
||||
radio.writeAckPayload(1, &payload, sizeof(payload));
|
||||
|
||||
radio.startListening(); // put radio in RX mode
|
||||
time_t startTimer = time(nullptr); // start a timer
|
||||
while (time(nullptr) - startTimer < 6) { // use 6 second timeout
|
||||
uint8_t pipe;
|
||||
if (radio.available(&pipe)) { // is there a payload? get the pipe number that recieved it
|
||||
uint8_t bytes = radio.getDynamicPayloadSize(); // get the size of the payload
|
||||
PayloadStruct received;
|
||||
radio.read(&received, sizeof(received)); // fetch payload from RX FIFO
|
||||
cout << "Received " << (unsigned int)bytes; // print the size of the payload
|
||||
cout << " bytes on pipe " << (unsigned int)pipe; // print the pipe number
|
||||
cout << ": " << received.message;
|
||||
cout << (unsigned int)received.counter; // print received payload
|
||||
cout << " Sent: ";
|
||||
cout << payload.message;
|
||||
cout << (unsigned int)payload.counter << endl; // print ACK payload sent
|
||||
startTimer = time(nullptr); // reset timer
|
||||
|
||||
// save incoming counter & increment for next outgoing
|
||||
payload.counter = received.counter + 1;
|
||||
// load the payload for the first received transmission on pipe 0
|
||||
radio.writeAckPayload(1, &payload, sizeof(payload));
|
||||
} // if received something
|
||||
} // while
|
||||
cout << "Nothing received in 6 seconds. Leaving RX role." << endl;
|
||||
radio.stopListening(); // recommended idle behavior is TX mode
|
||||
} // slave
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the ellapsed time in microseconds
|
||||
*/
|
||||
uint32_t getMicros() {
|
||||
// this function assumes that the timer was started using
|
||||
// `clock_gettime(CLOCK_MONOTONIC_RAW, &startTimer);`
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &endTimer);
|
||||
uint32_t seconds = endTimer.tv_sec - startTimer.tv_sec;
|
||||
uint32_t useconds = (endTimer.tv_nsec - startTimer.tv_nsec) / 1000;
|
||||
|
||||
return ((seconds) * 1000 + useconds) + 0.5;
|
||||
}
|
238
src/libs/RF24-master/examples_linux/acknowledgement_payloads.py
Normal file
238
src/libs/RF24-master/examples_linux/acknowledgement_payloads.py
Normal file
@ -0,0 +1,238 @@
|
||||
"""
|
||||
A simple example of sending data from 1 nRF24L01 transceiver to another
|
||||
with Acknowledgement (ACK) payloads attached to ACK packets.
|
||||
|
||||
This example was written to be used on 2 devices acting as 'nodes'.
|
||||
"""
|
||||
import sys
|
||||
import argparse
|
||||
import time
|
||||
from RF24 import RF24, RF24_PA_LOW
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--node",
|
||||
type=int,
|
||||
choices=range(2),
|
||||
help="the identifying radio number (or node ID number)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--role",
|
||||
type=int,
|
||||
choices=range(2),
|
||||
help="'1' specifies the TX role. '0' specifies the RX role."
|
||||
)
|
||||
|
||||
########### USER CONFIGURATION ###########
|
||||
# See https://github.com/TMRh20/RF24/blob/master/pyRF24/readme.md
|
||||
# Radio CE Pin, CSN Pin, SPI Speed
|
||||
# CE Pin uses GPIO number with BCM and SPIDEV drivers, other platforms use
|
||||
# their own pin numbering
|
||||
# CS Pin addresses the SPI bus number at /dev/spidev<a>.<b>
|
||||
# ie: RF24 radio(<ce_pin>, <a>*10+<b>); spidev1.0 is 10, spidev1.1 is 11 etc..
|
||||
|
||||
# Generic:
|
||||
radio = RF24(22, 0)
|
||||
################## Linux (BBB,x86,etc) #########################
|
||||
# See http://nRF24.github.io/RF24/pages.html for more information on usage
|
||||
# See http://iotdk.intel.com/docs/master/mraa/ for more information on MRAA
|
||||
# See https://www.kernel.org/doc/Documentation/spi/spidev for more
|
||||
# information on SPIDEV
|
||||
|
||||
# using the python keyword global is bad practice. Instead we'll use a
|
||||
# 1 item list to store our integer number for the payloads' counter
|
||||
counter = [0]
|
||||
|
||||
def master():
|
||||
"""Transmits a message and an incrementing integer every second."""
|
||||
radio.stopListening() # put radio in TX mode
|
||||
failures = 0
|
||||
while failures < 6:
|
||||
# construct a payload to send
|
||||
buffer = b"Hello \x00" + bytes(counter)
|
||||
|
||||
# send the payload and prompt
|
||||
start_timer = time.monotonic_ns() # start timer
|
||||
result = radio.write(buffer) # save the report
|
||||
end_timer = time.monotonic_ns() # stop timer
|
||||
if result:
|
||||
# print timer results upon transmission success
|
||||
print(
|
||||
"Transmission successful! Time to transmit: "
|
||||
"{} us. Sent: {}{}".format(
|
||||
int((end_timer - start_timer) / 1000),
|
||||
buffer[:6].decode("utf-8"),
|
||||
counter[0]
|
||||
),
|
||||
end=" "
|
||||
)
|
||||
has_payload, pipe_number = radio.available_pipe()
|
||||
if has_payload:
|
||||
# print the received ACK that was automatically sent
|
||||
length = radio.getDynamicPayloadSize()
|
||||
response = radio.read(length)
|
||||
print(
|
||||
"Received {} on pipe {}: {}{}".format(
|
||||
length,
|
||||
pipe_number,
|
||||
bytes(response[:6]).decode("utf-8"),
|
||||
response[7:8][0]
|
||||
)
|
||||
)
|
||||
# increment counter from received payload
|
||||
if response[7:8][0] < 255:
|
||||
counter[0] = response[7:8][0] + 1
|
||||
else:
|
||||
counter[0] = 0
|
||||
else:
|
||||
print("Received an empty ACK packet")
|
||||
else:
|
||||
failures += 1
|
||||
print("Transmission failed or timed out")
|
||||
time.sleep(1) # let the RX node prepare a new ACK payload
|
||||
print(failures, "failures detected. Leaving TX role.")
|
||||
|
||||
|
||||
def slave(timeout=6):
|
||||
"""Listen for any payloads and print the transaction
|
||||
|
||||
:param int timeout: The number of seconds to wait (with no transmission)
|
||||
until exiting function.
|
||||
"""
|
||||
radio.startListening() # put radio in RX mode
|
||||
|
||||
# setup the first transmission's ACK payload
|
||||
buffer = b"World \x00" + bytes(counter)
|
||||
# we must set the ACK payload data and corresponding
|
||||
# pipe number [0,5]
|
||||
radio.writeAckPayload(1, buffer) # load ACK for first response
|
||||
|
||||
start_timer = time.monotonic() # start timer
|
||||
while (time.monotonic() - start_timer) < timeout:
|
||||
has_payload, pipe_number = radio.available_pipe()
|
||||
if has_payload:
|
||||
length = radio.getDynamicPayloadSize() # grab the payload length
|
||||
received = radio.read(length) # fetch 1 payload from RX FIFO
|
||||
# increment counter from received payload
|
||||
counter[0] = received[7:8][0] + 1 if received[7:8][0] < 255 else 0
|
||||
print(
|
||||
"Received {} bytes on pipe {}: {}{} Sent: {}{}".format(
|
||||
length,
|
||||
pipe_number,
|
||||
bytes(received[:6]).decode("utf-8"),
|
||||
received[7:8][0],
|
||||
buffer[:6].decode("utf-8"),
|
||||
buffer[7:8][0]
|
||||
)
|
||||
)
|
||||
buffer = b"World \x00" + bytes(counter) # build a new ACK payload
|
||||
radio.writeAckPayload(1, buffer) # load ACK for next response
|
||||
start_timer = time.monotonic() # reset timer
|
||||
|
||||
print("Nothing received in 6 seconds. Leaving RX role")
|
||||
# recommended behavior is to keep in TX mode while idle
|
||||
radio.stopListening() # put radio in TX mode & flush unused ACK payloads
|
||||
|
||||
|
||||
def set_role():
|
||||
"""Set the role using stdin stream. Timeout arg for slave() can be
|
||||
specified using a space delimiter (e.g. 'R 10' calls `slave(10)`)
|
||||
|
||||
:return:
|
||||
- True when role is complete & app should continue running.
|
||||
- False when app should exit
|
||||
"""
|
||||
user_input = input(
|
||||
"*** Enter 'R' for receiver role.\n"
|
||||
"*** Enter 'T' for transmitter role.\n"
|
||||
"*** Enter 'Q' to quit example.\n"
|
||||
) or "?"
|
||||
user_input = user_input.split()
|
||||
if user_input[0].upper().startswith("R"):
|
||||
if len(user_input) > 1:
|
||||
slave(int(user_input[1]))
|
||||
else:
|
||||
slave()
|
||||
return True
|
||||
elif user_input[0].upper().startswith("T"):
|
||||
master()
|
||||
return True
|
||||
elif user_input[0].upper().startswith("Q"):
|
||||
radio.powerDown()
|
||||
return False
|
||||
print(user_input[0], "is an unrecognized input. Please try again.")
|
||||
return set_role()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
args = parser.parse_args() # parse any CLI args
|
||||
|
||||
# initialize the nRF24L01 on the spi bus
|
||||
if not radio.begin():
|
||||
raise RuntimeError("radio hardware is not responding")
|
||||
|
||||
# For this example, we will use different addresses
|
||||
# An address need to be a buffer protocol object (bytearray)
|
||||
address = [b"1Node", b"2Node"]
|
||||
# It is very helpful to think of an address as a path instead of as
|
||||
# an identifying device destination
|
||||
|
||||
print(sys.argv[0]) # print example name
|
||||
|
||||
# to use different addresses on a pair of radios, we need a variable to
|
||||
# uniquely identify which address this radio will use to transmit
|
||||
# 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
radio_number = args.node # uses default value from `parser`
|
||||
if args.node is None: # if '--node' arg wasn't specified
|
||||
radio_number = bool(
|
||||
int(
|
||||
input(
|
||||
"Which radio is this? Enter '0' or '1'. Defaults to '0' "
|
||||
) or 0
|
||||
)
|
||||
)
|
||||
|
||||
# set the Power Amplifier level to -12 dBm since this test example is
|
||||
# usually run with nRF24L01 transceivers in close proximity of each other
|
||||
radio.setPALevel(RF24_PA_LOW) # RF24_PA_MAX is default
|
||||
|
||||
# ACK payloads are dynamically sized.
|
||||
radio.enableDynamicPayloads() # to use ACK payloads
|
||||
|
||||
# to enable the custom ACK payload feature
|
||||
radio.enableAckPayload()
|
||||
|
||||
# set the Power Amplifier level to -12 dBm since this test example is
|
||||
# usually run with nRF24L01 transceivers in close proximity of each other
|
||||
radio.setPALevel(RF24_PA_LOW) # RF24_PA_MAX is default
|
||||
|
||||
# set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radio_number]) # always uses pipe 0
|
||||
|
||||
# set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[not radio_number]) # using pipe 1
|
||||
|
||||
# for debugging, we have 2 options that print a large block of details
|
||||
# (smaller) function that prints raw register values
|
||||
# radio.printDetails()
|
||||
# (larger) function that prints human readable data
|
||||
# radio.printPrettyDetails()
|
||||
|
||||
try:
|
||||
if args.role is None: # if not specified with CLI arg '-r'
|
||||
while set_role():
|
||||
pass # continue example until 'Q' is entered
|
||||
else: # if role was set using CLI args
|
||||
# run role once and exit
|
||||
master() if bool(args.role) else slave()
|
||||
except KeyboardInterrupt:
|
||||
print(" Keyboard Interrupt detected. Exiting...")
|
||||
radio.powerDown()
|
||||
sys.exit()
|
203
src/libs/RF24-master/examples_linux/getting_started.py
Normal file
203
src/libs/RF24-master/examples_linux/getting_started.py
Normal file
@ -0,0 +1,203 @@
|
||||
"""
|
||||
A simple example of sending data from 1 nRF24L01 transceiver to another.
|
||||
This example was written to be used on 2 devices acting as 'nodes'.
|
||||
"""
|
||||
import sys
|
||||
import argparse
|
||||
import time
|
||||
import struct
|
||||
from RF24 import RF24, RF24_PA_LOW
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--node",
|
||||
type=int,
|
||||
choices=range(2),
|
||||
help="the identifying radio number (or node ID number)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--role",
|
||||
type=int,
|
||||
choices=range(2),
|
||||
help="'1' specifies the TX role. '0' specifies the RX role."
|
||||
)
|
||||
|
||||
|
||||
########### USER CONFIGURATION ###########
|
||||
# See https://github.com/TMRh20/RF24/blob/master/pyRF24/readme.md
|
||||
# Radio CE Pin, CSN Pin, SPI Speed
|
||||
# CE Pin uses GPIO number with BCM and SPIDEV drivers, other platforms use
|
||||
# their own pin numbering
|
||||
# CS Pin addresses the SPI bus number at /dev/spidev<a>.<b>
|
||||
# ie: RF24 radio(<ce_pin>, <a>*10+<b>); spidev1.0 is 10, spidev1.1 is 11 etc..
|
||||
|
||||
# Generic:
|
||||
radio = RF24(22, 0)
|
||||
################## Linux (BBB,x86,etc) #########################
|
||||
# See http://nRF24.github.io/RF24/pages.html for more information on usage
|
||||
# See http://iotdk.intel.com/docs/master/mraa/ for more information on MRAA
|
||||
# See https://www.kernel.org/doc/Documentation/spi/spidev for more
|
||||
# information on SPIDEV
|
||||
|
||||
# using the python keyword global is bad practice. Instead we'll use a 1 item
|
||||
# list to store our float number for the payloads sent/received
|
||||
payload = [0.0]
|
||||
|
||||
|
||||
def master():
|
||||
"""Transmits an incrementing float every second"""
|
||||
radio.stopListening() # put radio in TX mode
|
||||
failures = 0
|
||||
while failures < 6:
|
||||
# use struct.pack() to packet your data into the payload
|
||||
# "<f" means a single little endian (4 byte) float value.
|
||||
buffer = struct.pack("<f", payload[0])
|
||||
start_timer = time.monotonic_ns() # start timer
|
||||
result = radio.write(buffer)
|
||||
end_timer = time.monotonic_ns() # end timer
|
||||
if not result:
|
||||
print("Transmission failed or timed out")
|
||||
failures += 1
|
||||
else:
|
||||
print(
|
||||
"Transmission successful! Time to Transmit: "
|
||||
"{} us. Sent: {}".format(
|
||||
(end_timer - start_timer) / 1000,
|
||||
payload[0]
|
||||
)
|
||||
)
|
||||
payload[0] += 0.01
|
||||
time.sleep(1)
|
||||
print(failures, "failures detected. Leaving TX role.")
|
||||
|
||||
|
||||
def slave(timeout=6):
|
||||
"""Listen for any payloads and print the transaction
|
||||
|
||||
:param int timeout: The number of seconds to wait (with no transmission)
|
||||
until exiting function.
|
||||
"""
|
||||
radio.startListening() # put radio in RX mode
|
||||
|
||||
start_timer = time.monotonic()
|
||||
while (time.monotonic() - start_timer) < timeout:
|
||||
has_payload, pipe_number = radio.available_pipe()
|
||||
if has_payload:
|
||||
# fetch 1 payload from RX FIFO
|
||||
buffer = radio.read(radio.payloadSize)
|
||||
# use struct.unpack() to convert the buffer into usable data
|
||||
# expecting a little endian float, thus the format string "<f"
|
||||
# buffer[:4] truncates padded 0s in case payloadSize was not set
|
||||
payload[0] = struct.unpack("<f", buffer[:4])[0]
|
||||
# print details about the received packet
|
||||
print(
|
||||
"Received {} bytes on pipe {}: {}".format(
|
||||
radio.payloadSize,
|
||||
pipe_number,
|
||||
payload[0]
|
||||
)
|
||||
)
|
||||
start_timer = time.monotonic() # reset the timeout timer
|
||||
|
||||
print("Nothing received in 6 seconds. Leaving RX role")
|
||||
# recommended behavior is to keep in TX mode while idle
|
||||
radio.stopListening() # put the radio in TX mode
|
||||
|
||||
|
||||
def set_role():
|
||||
"""Set the role using stdin stream. Timeout arg for slave() can be
|
||||
specified using a space delimiter (e.g. 'R 10' calls `slave(10)`)
|
||||
|
||||
:return:
|
||||
- True when role is complete & app should continue running.
|
||||
- False when app should exit
|
||||
"""
|
||||
user_input = input(
|
||||
"*** Enter 'R' for receiver role.\n"
|
||||
"*** Enter 'T' for transmitter role.\n"
|
||||
"*** Enter 'Q' to quit example.\n"
|
||||
) or "?"
|
||||
user_input = user_input.split()
|
||||
if user_input[0].upper().startswith("R"):
|
||||
if len(user_input) > 1:
|
||||
slave(int(user_input[1]))
|
||||
else:
|
||||
slave()
|
||||
return True
|
||||
elif user_input[0].upper().startswith("T"):
|
||||
master()
|
||||
return True
|
||||
elif user_input[0].upper().startswith("Q"):
|
||||
radio.powerDown()
|
||||
return False
|
||||
print(user_input[0], "is an unrecognized input. Please try again.")
|
||||
return set_role()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
args = parser.parse_args() # parse any CLI args
|
||||
|
||||
# initialize the nRF24L01 on the spi bus
|
||||
if not radio.begin():
|
||||
raise RuntimeError("radio hardware is not responding")
|
||||
|
||||
# For this example, we will use different addresses
|
||||
# An address need to be a buffer protocol object (bytearray)
|
||||
address = [b"1Node", b"2Node"]
|
||||
# It is very helpful to think of an address as a path instead of as
|
||||
# an identifying device destination
|
||||
|
||||
print(sys.argv[0]) # print example name
|
||||
|
||||
# to use different addresses on a pair of radios, we need a variable to
|
||||
# uniquely identify which address this radio will use to transmit
|
||||
# 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
radio_number = args.node # uses default value from `parser`
|
||||
if args.node is None: # if '--node' arg wasn't specified
|
||||
radio_number = bool(
|
||||
int(
|
||||
input(
|
||||
"Which radio is this? Enter '0' or '1'. Defaults to '0' "
|
||||
) or 0
|
||||
)
|
||||
)
|
||||
|
||||
# set the Power Amplifier level to -12 dBm since this test example is
|
||||
# usually run with nRF24L01 transceivers in close proximity of each other
|
||||
radio.setPALevel(RF24_PA_LOW) # RF24_PA_MAX is default
|
||||
|
||||
# set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radio_number]) # always uses pipe 0
|
||||
|
||||
# set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[not radio_number]) # using pipe 1
|
||||
|
||||
# To save time during transmission, we'll set the payload size to be only
|
||||
# what we need. A float value occupies 4 bytes in memory using
|
||||
# struct.pack(); "<f" means a little endian unsigned float
|
||||
radio.payloadSize = len(struct.pack("<f", payload[0]))
|
||||
|
||||
# for debugging, we have 2 options that print a large block of details
|
||||
# (smaller) function that prints raw register values
|
||||
# radio.printDetails()
|
||||
# (larger) function that prints human readable data
|
||||
# radio.printPrettyDetails()
|
||||
|
||||
try:
|
||||
if args.role is None: # if not specified with CLI arg '-r'
|
||||
while set_role():
|
||||
pass # continue example until 'Q' is entered
|
||||
else: # if role was set using CLI args
|
||||
# run role once and exit
|
||||
master() if bool(args.role) else slave()
|
||||
except KeyboardInterrupt:
|
||||
print(" Keyboard Interrupt detected. Exiting...")
|
||||
radio.powerDown()
|
||||
sys.exit()
|
191
src/libs/RF24-master/examples_linux/gettingstarted.cpp
Normal file
191
src/libs/RF24-master/examples_linux/gettingstarted.cpp
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* See documentation at https://nRF24.github.io/RF24
|
||||
* See License information at root directory of this library
|
||||
* Author: Brendan Doherty (2bndy5)
|
||||
*/
|
||||
|
||||
/**
|
||||
* A simple example of sending data from 1 nRF24L01 transceiver to another.
|
||||
*
|
||||
* This example was written to be used on 2 devices acting as "nodes".
|
||||
* Use `ctrl+c` to quit at any time.
|
||||
*/
|
||||
#include <ctime> // time()
|
||||
#include <iostream> // cin, cout, endl
|
||||
#include <string> // string, getline()
|
||||
#include <time.h> // CLOCK_MONOTONIC_RAW, timespec, clock_gettime()
|
||||
#include <RF24/RF24.h> // RF24, RF24_PA_LOW, delay()
|
||||
|
||||
using namespace std;
|
||||
|
||||
/****************** Linux ***********************/
|
||||
// Radio CE Pin, CSN Pin, SPI Speed
|
||||
// CE Pin uses GPIO number with BCM and SPIDEV drivers, other platforms use their own pin numbering
|
||||
// CS Pin addresses the SPI bus number at /dev/spidev<a>.<b>
|
||||
// ie: RF24 radio(<ce_pin>, <a>*10+<b>); spidev1.0 is 10, spidev1.1 is 11 etc..
|
||||
|
||||
// Generic:
|
||||
RF24 radio(22, 0);
|
||||
/****************** Linux (BBB,x86,etc) ***********************/
|
||||
// See http://nRF24.github.io/RF24/pages.html for more information on usage
|
||||
// See http://iotdk.intel.com/docs/master/mraa/ for more information on MRAA
|
||||
// See https://www.kernel.org/doc/Documentation/spi/spidev for more information on SPIDEV
|
||||
|
||||
// For this example, we'll be using a payload containing
|
||||
// a single float number that will be incremented
|
||||
// on every successful transmission
|
||||
float payload = 0.0;
|
||||
|
||||
void setRole(); // prototype to set the node's role
|
||||
void master(); // prototype of the TX node's behavior
|
||||
void slave(); // prototype of the RX node's behavior
|
||||
|
||||
// custom defined timer for evaluating transmission time in microseconds
|
||||
struct timespec startTimer, endTimer;
|
||||
uint32_t getMicros(); // prototype to get ellapsed time in microseconds
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
// perform hardware check
|
||||
if (!radio.begin()) {
|
||||
cout << "radio hardware is not responding!!" << endl;
|
||||
return 0; // quit now
|
||||
}
|
||||
|
||||
// to use different addresses on a pair of radios, we need a variable to
|
||||
// uniquely identify which address this radio will use to transmit
|
||||
bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
|
||||
// print example's name
|
||||
cout << argv[0] << endl;
|
||||
|
||||
// Let these addresses be used for the pair
|
||||
uint8_t address[2][6] = {"1Node", "2Node"};
|
||||
// It is very helpful to think of an address as a path instead of as
|
||||
// an identifying device destination
|
||||
|
||||
// Set the radioNumber via the terminal on startup
|
||||
cout << "Which radio is this? Enter '0' or '1'. Defaults to '0' ";
|
||||
string input;
|
||||
getline(cin, input);
|
||||
radioNumber = input.length() > 0 && (uint8_t)input[0] == 49;
|
||||
|
||||
// save on transmission time by setting the radio to only transmit the
|
||||
// number of bytes we need to transmit a float
|
||||
radio.setPayloadSize(sizeof(payload)); // float datatype occupies 4 bytes
|
||||
|
||||
// Set the PA Level low to try preventing power supply related problems
|
||||
// because these examples are likely run with nodes in close proximity to
|
||||
// each other.
|
||||
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
|
||||
|
||||
// set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radioNumber]); // always uses pipe 0
|
||||
|
||||
// set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1
|
||||
|
||||
// For debugging info
|
||||
// radio.printDetails(); // (smaller) function that prints raw register values
|
||||
// radio.printPrettyDetails(); // (larger) function that prints human readable data
|
||||
|
||||
// ready to execute program now
|
||||
setRole(); // calls master() or slave() based on user input
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* set this node's role from stdin stream.
|
||||
* this only considers the first char as input.
|
||||
*/
|
||||
void setRole() {
|
||||
string input = "";
|
||||
while (!input.length()) {
|
||||
cout << "*** PRESS 'T' to begin transmitting to the other node\n";
|
||||
cout << "*** PRESS 'R' to begin receiving from the other node\n";
|
||||
cout << "*** PRESS 'Q' to exit" << endl;
|
||||
getline(cin, input);
|
||||
if (input.length() >= 1) {
|
||||
if (input[0] == 'T' || input[0] == 't')
|
||||
master();
|
||||
else if (input[0] == 'R' || input[0] == 'r')
|
||||
slave();
|
||||
else if (input[0] == 'Q' || input[0] == 'q')
|
||||
break;
|
||||
else
|
||||
cout << input[0] << " is an invalid input. Please try again." << endl;
|
||||
}
|
||||
input = ""; // stay in the while loop
|
||||
} // while
|
||||
} // setRole()
|
||||
|
||||
|
||||
/**
|
||||
* make this node act as the transmitter
|
||||
*/
|
||||
void master() {
|
||||
radio.stopListening(); // put radio in TX mode
|
||||
|
||||
unsigned int failure = 0; // keep track of failures
|
||||
while (failure < 6) {
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &startTimer); // start the timer
|
||||
bool report = radio.write(&payload, sizeof(float)); // transmit & save the report
|
||||
uint32_t timerEllapsed = getMicros(); // end the timer
|
||||
|
||||
if (report) {
|
||||
// payload was delivered
|
||||
cout << "Transmission successful! Time to transmit = ";
|
||||
cout << timerEllapsed; // print the timer result
|
||||
cout << " us. Sent: " << payload << endl; // print payload sent
|
||||
payload += 0.01; // increment float payload
|
||||
|
||||
} else {
|
||||
// payload was not delivered
|
||||
cout << "Transmission failed or timed out" << endl;
|
||||
failure++;
|
||||
}
|
||||
|
||||
// to make this example readable in the terminal
|
||||
delay(1000); // slow transmissions down by 1 second
|
||||
}
|
||||
cout << failure << " failures detected. Leaving TX role." << endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* make this node act as the receiver
|
||||
*/
|
||||
void slave() {
|
||||
|
||||
radio.startListening(); // put radio in RX mode
|
||||
|
||||
time_t startTimer = time(nullptr); // start a timer
|
||||
while (time(nullptr) - startTimer < 6) { // use 6 second timeout
|
||||
uint8_t pipe;
|
||||
if (radio.available(&pipe)) { // is there a payload? get the pipe number that recieved it
|
||||
uint8_t bytes = radio.getPayloadSize(); // get the size of the payload
|
||||
radio.read(&payload, bytes); // fetch payload from FIFO
|
||||
cout << "Received " << (unsigned int)bytes; // print the size of the payload
|
||||
cout << " bytes on pipe " << (unsigned int)pipe; // print the pipe number
|
||||
cout << ": " << payload << endl; // print the payload's value
|
||||
startTimer = time(nullptr); // reset timer
|
||||
}
|
||||
}
|
||||
cout << "Nothing received in 6 seconds. Leaving RX role." << endl;
|
||||
radio.stopListening();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the ellapsed time in microseconds
|
||||
*/
|
||||
uint32_t getMicros() {
|
||||
// this function assumes that the timer was started using
|
||||
// `clock_gettime(CLOCK_MONOTONIC_RAW, &startTimer);`
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &endTimer);
|
||||
uint32_t seconds = endTimer.tv_sec - startTimer.tv_sec;
|
||||
uint32_t useconds = (endTimer.tv_nsec - startTimer.tv_nsec) / 1000;
|
||||
|
||||
return ((seconds) * 1000 + useconds) + 0.5;
|
||||
}
|
319
src/libs/RF24-master/examples_linux/interruptConfigure.cpp
Normal file
319
src/libs/RF24-master/examples_linux/interruptConfigure.cpp
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
* See documentation at https://nRF24.github.io/RF24
|
||||
* See License information at root directory of this library
|
||||
* Author: Brendan Doherty (2bndy5)
|
||||
*/
|
||||
|
||||
/**
|
||||
* This example uses Acknowledgement (ACK) payloads attached to ACK packets to
|
||||
* demonstrate how the nRF24L01's IRQ (Interrupt Request) pin can be
|
||||
* configured to detect when data is received, or when data has transmitted
|
||||
* successfully, or when data has failed to transmit.
|
||||
*
|
||||
* This example was written to be used on 2 devices acting as "nodes".
|
||||
* Use `ctrl+c` to quit at any time.
|
||||
*/
|
||||
#include <ctime> // time()
|
||||
#include <iostream> // cin, cout, endl
|
||||
#include <string> // string, getline()
|
||||
#include <time.h> // CLOCK_MONOTONIC_RAW, timespec, clock_gettime()
|
||||
#include <RF24/RF24.h> // RF24, RF24_PA_LOW, delay(), pinMode(), INPUT, attachInterrupt(), INT_EDGE_FALLING
|
||||
|
||||
using namespace std;
|
||||
|
||||
// We will be using the nRF24L01's IRQ pin for this example
|
||||
#define IRQ_PIN 12 // this needs to be a digital input capable pin
|
||||
|
||||
// this example is a sequential program. so we need to wait for the event to be handled
|
||||
volatile bool wait_for_event = false; // used to signify that the event is handled
|
||||
|
||||
/****************** Linux ***********************/
|
||||
// Radio CE Pin, CSN Pin, SPI Speed
|
||||
// CE Pin uses GPIO number with BCM and SPIDEV drivers, other platforms use their own pin numbering
|
||||
// CS Pin addresses the SPI bus number at /dev/spidev<a>.<b>
|
||||
// ie: RF24 radio(<ce_pin>, <a>*10+<b>); spidev1.0 is 10, spidev1.1 is 11 etc..
|
||||
|
||||
// Generic:
|
||||
RF24 radio(22, 0);
|
||||
/****************** Linux (BBB,x86,etc) ***********************/
|
||||
// See http://nRF24.github.io/RF24/pages.html for more information on usage
|
||||
// See http://iotdk.intel.com/docs/master/mraa/ for more information on MRAA
|
||||
// See https://www.kernel.org/doc/Documentation/spi/spidev for more information on SPIDEV
|
||||
|
||||
// For this example, we'll be using a payload containing
|
||||
// a string that changes on every transmission. (successful or not)
|
||||
// Make a couple arrays of payloads & an iterator to traverse them
|
||||
const uint8_t tx_pl_size = 5;
|
||||
const uint8_t ack_pl_size = 4;
|
||||
uint8_t pl_iterator = 0;
|
||||
// The " + 1" compensates for the c-string's NULL terminating 0
|
||||
char tx_payloads[4][tx_pl_size + 1] = {"Ping ", "Pong ", "Radio", "1FAIL"};
|
||||
char ack_payloads[3][ack_pl_size + 1] = {"Yak ", "Back", " ACK"};
|
||||
|
||||
void interruptHandler(); // prototype to handle the interrupt request (IRQ) pin
|
||||
void setRole(); // prototype to set the node's role
|
||||
void master(); // prototype of the TX node's behavior
|
||||
void slave(); // prototype of the RX node's behavior
|
||||
void ping_n_wait(); // prototype that sends a payload and waits for the IRQ pin to get triggered
|
||||
void printRxFifo(const uint8_t); // prototype to print entire contents of RX FIFO with 1 buffer
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
// perform hardware check
|
||||
if (!radio.begin()) {
|
||||
cout << "radio hardware is not responding!!" << endl;
|
||||
return 0; // quit now
|
||||
}
|
||||
|
||||
// Let these addresses be used for the pair
|
||||
uint8_t address[2][6] = {"1Node", "2Node"};
|
||||
// It is very helpful to think of an address as a path instead of as
|
||||
// an identifying device destination
|
||||
|
||||
// to use different addresses on a pair of radios, we need a variable to
|
||||
// uniquely identify which address this radio will use to transmit
|
||||
bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
|
||||
// print example's name
|
||||
cout << argv[0] << endl;
|
||||
|
||||
// Set the radioNumber via the terminal on startup
|
||||
cout << "Which radio is this? Enter '0' or '1'. Defaults to '0' ";
|
||||
string input;
|
||||
getline(cin, input);
|
||||
radioNumber = input.length() > 0 && (uint8_t)input[0] == 49;
|
||||
|
||||
// to use ACK payloads, we need to enable dynamic payload lengths
|
||||
radio.enableDynamicPayloads(); // ACK payloads are dynamically sized
|
||||
|
||||
// Acknowledgement packets have no payloads by default. We need to enable
|
||||
// this feature for all nodes (TX & RX) to use ACK payloads.
|
||||
radio.enableAckPayload();
|
||||
|
||||
// Set the PA Level low to try preventing power supply related problems
|
||||
// because these examples are likely run with nodes in close proximity to
|
||||
// each other.
|
||||
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
|
||||
|
||||
// set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radioNumber]); // always uses pipe 0
|
||||
|
||||
// set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1
|
||||
|
||||
// For debugging info
|
||||
// radio.printDetails(); // (smaller) function that prints raw register values
|
||||
// radio.printPrettyDetails(); // (larger) function that prints human readable data
|
||||
|
||||
// setup the digital input pin connected to the nRF24L01's IRQ pin
|
||||
pinMode(IRQ_PIN, INPUT);
|
||||
|
||||
// register the interrupt request (IRQ) to call our
|
||||
// Interrupt Service Routine (ISR) callback function interruptHandler()
|
||||
attachInterrupt(IRQ_PIN, INT_EDGE_FALLING, &interruptHandler);
|
||||
// IMPORTANT: do not call radio.available() before calling
|
||||
// radio.whatHappened() when the interruptHandler() is triggered by the
|
||||
// IRQ pin FALLING event. According to the datasheet, the pipe information
|
||||
// is unreliable during the IRQ pin FALLING transition.
|
||||
|
||||
// ready to execute program now
|
||||
setRole(); // calls master() or slave() based on user input
|
||||
return 0;
|
||||
} // main
|
||||
|
||||
|
||||
/**
|
||||
* set this node's role from stdin stream.
|
||||
* this only considers the first char as input.
|
||||
*/
|
||||
void setRole() {
|
||||
string input = "";
|
||||
while (!input.length()) {
|
||||
cout << "*** PRESS 'T' to begin transmitting to the other node\n";
|
||||
cout << "*** PRESS 'R' to begin receiving from the other node\n";
|
||||
cout << "*** PRESS 'Q' to exit" << endl;
|
||||
getline(cin, input);
|
||||
if (input.length() >= 1) {
|
||||
if (input[0] == 'T' || input[0] == 't')
|
||||
master();
|
||||
else if (input[0] == 'R' || input[0] == 'r')
|
||||
slave();
|
||||
else if (input[0] == 'Q' || input[0] == 'q')
|
||||
break;
|
||||
else
|
||||
cout << input[0] << " is an invalid input. Please try again." << endl;
|
||||
}
|
||||
input = ""; // stay in the while loop
|
||||
} // while
|
||||
} // setRole
|
||||
|
||||
|
||||
/**
|
||||
* act as the transmitter to show 3 different IRQ events by sending 4 payloads:
|
||||
* 1. Successfully receive ACK payload first
|
||||
* 2. Successfully transmit on second
|
||||
* 3. Send a third payload to fill RX node's RX FIFO (supposedly making RX node unresponsive)
|
||||
* 4. intentionally fail transmit on the fourth
|
||||
*/
|
||||
void master() {
|
||||
pl_iterator = 0; // reset the iterator for the following tests done in master()
|
||||
|
||||
// Test the "data ready" event with the IRQ pin
|
||||
cout << "\nConfiguring IRQ pin to ignore the 'data sent' event\n";
|
||||
radio.maskIRQ(true, false, false); // args = "data_sent", "data_fail", "data_ready"
|
||||
cout << " Pinging RX node for 'data ready' event...";
|
||||
ping_n_wait(); // transmit a payload and detect the IRQ pin
|
||||
pl_iterator++; // increment iterator for next test
|
||||
|
||||
|
||||
// Test the "data sent" event with the IRQ pin
|
||||
cout << "\nConfiguring IRQ pin to ignore the 'data ready' event\n";
|
||||
radio.maskIRQ(false, false, true); // args = "data_sent", "data_fail", "data_ready"
|
||||
cout << " Pinging RX node for 'data sent' event...";
|
||||
radio.flush_tx(); // flush payloads from any failed prior test
|
||||
ping_n_wait(); // transmit a payload and detect the IRQ pin
|
||||
pl_iterator++; // increment iterator for next test
|
||||
|
||||
|
||||
// Use this iteration to fill the RX node's FIFO which sets us up for the next test.
|
||||
// write() uses virtual interrupt flags that work despite the masking of the IRQ pin
|
||||
radio.maskIRQ(1, 1, 1); // disable IRQ masking for this step
|
||||
|
||||
cout << "\nSending 1 payload to fill RX node's FIFO. IRQ pin is neglected.\n";
|
||||
// write() will call flush_tx() on 'data fail' events
|
||||
if (radio.write(&tx_payloads[pl_iterator], tx_pl_size))
|
||||
cout << "RX node's FIFO is full; it is not listening any more" << endl;
|
||||
else {
|
||||
cout << "Transmission failed or timed out. Continuing anyway." << endl;
|
||||
radio.flush_tx();
|
||||
}
|
||||
pl_iterator++; // increment iterator for next test
|
||||
|
||||
|
||||
// test the "data fail" event with the IRQ pin
|
||||
cout << "\nConfiguring IRQ pin to reflect all events\n";
|
||||
radio.maskIRQ(0, 0, 0); // args = "data_sent", "data_fail", "data_ready"
|
||||
cout << " Pinging inactive RX node for 'data fail' event...";
|
||||
ping_n_wait(); // transmit a payload and detect the IRQ pin
|
||||
|
||||
// CE pin is still HIGH which consumes more power. Example is now idling so...
|
||||
radio.stopListening(); // ensure CE pin is LOW
|
||||
// stopListening() also calls flush_tx() when ACK payloads are enabled
|
||||
|
||||
if (radio.available()) {
|
||||
printRxFifo(ack_pl_size); // doing this will flush the RX FIFO
|
||||
}
|
||||
} // master
|
||||
|
||||
|
||||
/**
|
||||
* act as the receiver
|
||||
*/
|
||||
void slave() {
|
||||
|
||||
// let IRQ pin only trigger on "data_ready" event in RX mode
|
||||
radio.maskIRQ(1, 1, 0); // args = "data_sent", "data_fail", "data_ready"
|
||||
|
||||
// Fill the TX FIFO with 3 ACK payloads for the first 3 received
|
||||
// transmissions on pipe 0.
|
||||
radio.writeAckPayload(1, &ack_payloads[0], ack_pl_size);
|
||||
radio.writeAckPayload(1, &ack_payloads[1], ack_pl_size);
|
||||
radio.writeAckPayload(1, &ack_payloads[2], ack_pl_size);
|
||||
|
||||
radio.startListening(); // put radio in RX mode
|
||||
time_t startTimer = time(nullptr); // start a timer
|
||||
while (time(nullptr) - startTimer < 6 && !radio.rxFifoFull()) {
|
||||
// use 6 second timeout & wait till RX FIFO is full
|
||||
}
|
||||
delay(100); // wait for ACK payload to finish transmitting
|
||||
radio.stopListening(); // also discards unused ACK payloads
|
||||
|
||||
if (radio.available()) {
|
||||
printRxFifo(tx_pl_size);
|
||||
}
|
||||
else {
|
||||
cout << "Timeout was reached. Going back to setRole()" << endl;
|
||||
}
|
||||
} // slave
|
||||
|
||||
|
||||
/**
|
||||
* pings the receiver with a non-blocking startWrite(), then waits till
|
||||
* the IRQ pin is triggered
|
||||
*/
|
||||
void ping_n_wait() {
|
||||
// use the non-blocking call to write a payload and begin transmission
|
||||
// the "false" argument means we are expecting an ACK packet response
|
||||
radio.startFastWrite(tx_payloads[pl_iterator], tx_pl_size, false);
|
||||
|
||||
wait_for_event = true;
|
||||
while (wait_for_event) {
|
||||
/*
|
||||
* IRQ pin is LOW when activated. Otherwise it is always HIGH
|
||||
* Wait in this empty loop until IRQ pin is activated.
|
||||
*
|
||||
* In this example, the "data fail" event is always configured to
|
||||
* trigger the IRQ pin active. Because the auto-ACK feature is on by
|
||||
* default, we don't need a timeout check to prevent an infinite loop.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* when the IRQ pin goes active LOW, call this fuction print out why
|
||||
*/
|
||||
void interruptHandler() {
|
||||
// print IRQ status and all masking flags' states
|
||||
|
||||
cout << "\tIRQ pin is actively LOW" << endl; // show that this function was called
|
||||
|
||||
bool tx_ds, tx_df, rx_dr; // declare variables for IRQ masks
|
||||
radio.whatHappened(tx_ds, tx_df, rx_dr); // get values for IRQ masks
|
||||
// whatHappened() clears the IRQ masks also. This is required for
|
||||
// continued TX operations when a transmission fails.
|
||||
// clearing the IRQ masks resets the IRQ pin to its inactive state (HIGH)
|
||||
|
||||
cout << "\tdata_sent: " << tx_ds; // print "data sent" mask state
|
||||
cout << ", data_fail: " << tx_df; // print "data fail" mask state
|
||||
cout << ", data_ready: " << rx_dr << endl; // print "data ready" mask state
|
||||
|
||||
if (tx_df) // if TX payload failed
|
||||
radio.flush_tx(); // clear all payloads from the TX FIFO
|
||||
|
||||
// print if test passed or failed. Unintentional fails mean the RX node was not listening.
|
||||
if (pl_iterator == 0)
|
||||
cout << " 'Data Ready' event test " << (rx_dr ? "passed" : "failed") << endl;
|
||||
else if (pl_iterator == 1)
|
||||
cout << " 'Data Sent' event test " << (tx_ds ? "passed" : "failed") << endl;
|
||||
else if (pl_iterator == 3)
|
||||
cout << " 'Data Fail' event test " << (tx_df ? "passed" : "failed") << endl;
|
||||
|
||||
wait_for_event = false; // ready to continue
|
||||
} // interruptHandler
|
||||
|
||||
|
||||
/**
|
||||
* Print the entire RX FIFO with one buffer. This will also flush the RX FIFO.
|
||||
* @param pl_size used to determine received payload size. Remember that the
|
||||
* payload sizes are declared as tx_pl_size and ack_pl_size.
|
||||
*/
|
||||
void printRxFifo(const uint8_t pl_size) {
|
||||
char rx_fifo[pl_size * 3 + 1]; // assuming RX FIFO is full; declare a buffer to hold it all
|
||||
if (radio.rxFifoFull()) {
|
||||
rx_fifo[pl_size * 3] = 0; // add a NULL terminating char to use as a c-string
|
||||
radio.read(&rx_fifo, pl_size * 3); // this clears the RX FIFO (for this example)
|
||||
}
|
||||
else {
|
||||
uint8_t i = 0;
|
||||
while (radio.available()) {
|
||||
radio.read(&rx_fifo + (i * pl_size), pl_size);
|
||||
i++;
|
||||
}
|
||||
rx_fifo[i * pl_size] = 0; // add a NULL terminating char to use as a c-string
|
||||
}
|
||||
|
||||
// print the entire RX FIFO with 1 buffer
|
||||
cout << "Complete RX FIFO: " << rx_fifo << endl;
|
||||
}
|
300
src/libs/RF24-master/examples_linux/interrupt_configure.py
Normal file
300
src/libs/RF24-master/examples_linux/interrupt_configure.py
Normal file
@ -0,0 +1,300 @@
|
||||
"""
|
||||
This example uses Acknowledgement (ACK) payloads attached to ACK packets to
|
||||
demonstrate how the nRF24L01's IRQ (Interrupt Request) pin can be
|
||||
configured to detect when data is received, or when data has transmitted
|
||||
successfully, or when data has failed to transmit.
|
||||
|
||||
This example was written to be used on 2 devices acting as "nodes".
|
||||
"""
|
||||
import sys
|
||||
import argparse
|
||||
import time
|
||||
import RPi.GPIO as GPIO
|
||||
from RF24 import RF24, RF24_PA_LOW
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--node",
|
||||
type=int,
|
||||
choices=range(2),
|
||||
help="the identifying radio number (or node ID number)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--role",
|
||||
type=int,
|
||||
choices=range(2),
|
||||
help="'1' specifies the TX role. '0' specifies the RX role."
|
||||
)
|
||||
|
||||
########### USER CONFIGURATION ###########
|
||||
# See https://github.com/TMRh20/RF24/blob/master/pyRF24/readme.md
|
||||
# Radio CE Pin, CSN Pin, SPI Speed
|
||||
# CE Pin uses GPIO number with BCM and SPIDEV drivers, other platforms use
|
||||
# their own pin numbering
|
||||
# CS Pin addresses the SPI bus number at /dev/spidev<a>.<b>
|
||||
# ie: RF24 radio(<ce_pin>, <a>*10+<b>); spidev1.0 is 10, spidev1.1 is 11 etc..
|
||||
|
||||
# Generic:
|
||||
radio = RF24(22, 0)
|
||||
################## Linux (BBB,x86,etc) #########################
|
||||
# See http://nRF24.github.io/RF24/pages.html for more information on usage
|
||||
# See http://iotdk.intel.com/docs/master/mraa/ for more information on MRAA
|
||||
# See https://www.kernel.org/doc/Documentation/spi/spidev for more
|
||||
# information on SPIDEV
|
||||
|
||||
# select your digital input pin that's connected to the IRQ pin on the nRF24L01
|
||||
IRQ_PIN = 12
|
||||
|
||||
# For this example, we'll be using a payload containing
|
||||
# a string that changes on every transmission. (successful or not)
|
||||
# Make a couple tuples of payloads & an iterator to traverse them
|
||||
pl_iterator = [0] # use a 1-item list instead of python's global keyword
|
||||
tx_payloads = (b"Ping ", b"Pong ", b"Radio", b"1FAIL")
|
||||
ack_payloads = (b"Yak ", b"Back", b" ACK")
|
||||
|
||||
|
||||
def interrupt_handler(channel):
|
||||
"""This function is called when IRQ pin is detected active LOW"""
|
||||
print("IRQ pin", channel, "went active LOW.")
|
||||
tx_ds, tx_df, rx_dr = radio.whatHappened() # get IRQ status flags
|
||||
if tx_df:
|
||||
radio.flush_tx()
|
||||
print("\ttx_ds: {}, tx_df: {}, rx_dr: {}".format(tx_ds, tx_df, rx_dr))
|
||||
if pl_iterator[0] == 0:
|
||||
print(
|
||||
" 'data ready' event test {}".format(
|
||||
"passed" if rx_dr else "failed"
|
||||
)
|
||||
)
|
||||
elif pl_iterator[0] == 1:
|
||||
print(
|
||||
" 'data sent' event test {}".format(
|
||||
"passed" if tx_ds else "failed"
|
||||
)
|
||||
)
|
||||
elif pl_iterator[0] == 3:
|
||||
print(
|
||||
" 'data fail' event test {}".format(
|
||||
"passed" if tx_df else "failed"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# setup IRQ GPIO pin
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.setup(IRQ_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
|
||||
GPIO.add_event_detect(IRQ_PIN, GPIO.FALLING, callback=interrupt_handler)
|
||||
# IMPORTANT: do not call radio.available() before calling
|
||||
# radio.whatHappened() when the interruptHandler() is triggered by the
|
||||
# IRQ pin FALLING event. According to the datasheet, the pipe information
|
||||
# is unreliable during the IRQ pin FALLING transition.
|
||||
|
||||
|
||||
def _ping_n_wait(pl_iter):
|
||||
"""private function to ping RX node and wait for IRQ pin to be handled
|
||||
|
||||
:param int pl_iter: The index of the buffer in `tx_payloads` tuple to
|
||||
send. This number is also used to determine if event test was
|
||||
successful or not.
|
||||
"""
|
||||
# set pl_iterator[0] so interrupt_handler() can determine if test was
|
||||
# successful or not
|
||||
pl_iterator[0] = pl_iter
|
||||
# the following False parameter means we're expecting an ACK packet
|
||||
radio.startFastWrite(tx_payloads[pl_iter], False)
|
||||
time.sleep(0.1) # wait 100 ms for interrupt_handler() to complete
|
||||
|
||||
|
||||
def print_rx_fifo(pl_size):
|
||||
"""fush RX FIFO by printing all available payloads with 1 buffer
|
||||
|
||||
:param int pl_size: the expected size of each payload
|
||||
"""
|
||||
if radio.rxFifoFull():
|
||||
# all 3 payloads received were 5 bytes each, and RX FIFO is full
|
||||
# so, fetching 15 bytes from the RX FIFO also flushes RX FIFO
|
||||
print(
|
||||
"Complete RX FIFO:",
|
||||
radio.read(pl_size * 3).decode("utf-8")
|
||||
)
|
||||
else:
|
||||
buffer = bytearray()
|
||||
while radio.available():
|
||||
buffer += radio.read(pl_size)
|
||||
if buffer: # if any payloads were read from the RX FIFO
|
||||
print("Complete RX FIFO:", buffer.decode("utf-8"))
|
||||
|
||||
|
||||
def master():
|
||||
"""Transmits 4 times and reports results
|
||||
|
||||
1. successfully receive ACK payload first
|
||||
2. successfully transmit on second
|
||||
3. send a third payload to fill RX node's RX FIFO
|
||||
(supposedly making RX node unresponsive)
|
||||
4. intentionally fail transmit on the fourth
|
||||
"""
|
||||
radio.stopListening() # put radio in TX mode
|
||||
|
||||
# on data ready test
|
||||
print("\nConfiguring IRQ pin to only ignore 'on data sent' event")
|
||||
radio.maskIRQ(True, False, False) # args = tx_ds, tx_df, rx_dr
|
||||
print(" Pinging slave node for an ACK payload...", end=" ")
|
||||
_ping_n_wait(0)
|
||||
|
||||
# on "data sent" test
|
||||
print("\nConfiguring IRQ pin to only ignore 'on data ready' event")
|
||||
radio.maskIRQ(False, False, True) # args = tx_ds, tx_df, rx_dr
|
||||
print(" Pinging slave node again... ", end=" ")
|
||||
_ping_n_wait(1)
|
||||
|
||||
# trigger slave node to stopListening() by filling slave node's RX FIFO
|
||||
print("\nSending one extra payload to fill RX FIFO on slave node.")
|
||||
radio.maskIRQ(1, 1, 1) # disable IRQ pin for this step
|
||||
if radio.write(tx_payloads[2]):
|
||||
# when send_only parameter is True, send() ignores RX FIFO usage
|
||||
if radio.rxFifoFull():
|
||||
print("RX node's FIFO is full; it is not listening any more")
|
||||
else:
|
||||
print(
|
||||
"Transmission successful, but the RX node might still be "
|
||||
"listening."
|
||||
)
|
||||
else:
|
||||
radio.flush_tx()
|
||||
print("Transmission failed or timed out. Continuing anyway.")
|
||||
|
||||
# on "data fail" test
|
||||
print("\nConfiguring IRQ pin to go active for all events.")
|
||||
radio.maskIRQ(False, False, False) # args = tx_ds, tx_df, rx_dr
|
||||
print(" Sending a ping to inactive slave node...", end=" ")
|
||||
_ping_n_wait(3)
|
||||
|
||||
# CE pin is still HIGH which consumes more power. Example is now idling so...
|
||||
radio.stopListening() # ensure CE pin is LOW
|
||||
# stopListening() also calls flush_tx() when ACK payloads are enabled
|
||||
|
||||
print_rx_fifo(len(ack_payloads[0])) # empty RX FIFO
|
||||
|
||||
|
||||
def slave(timeout=6): # will listen for 6 seconds before timing out
|
||||
"""Only listen for 3 payload from the master node
|
||||
|
||||
:param int timeout: The number of seconds to wait (with no transmission)
|
||||
until exiting function.
|
||||
"""
|
||||
pl_iterator[0] = 0 # reset this to indicate event is a 'data_ready' event
|
||||
# setup radio to recieve pings, fill TX FIFO with ACK payloads
|
||||
radio.writeAckPayload(1, ack_payloads[0])
|
||||
radio.writeAckPayload(1, ack_payloads[1])
|
||||
radio.writeAckPayload(1, ack_payloads[2])
|
||||
radio.startListening() # start listening & clear status flags
|
||||
start_timer = time.monotonic() # start timer now
|
||||
while not radio.rxFifoFull() and time.monotonic() - start_timer < timeout:
|
||||
# if RX FIFO is not full and timeout is not reached, then keep waiting
|
||||
pass
|
||||
time.sleep(0.1) # wait for last ACK payload to transmit
|
||||
radio.stopListening() # put radio in TX mode & discard any ACK payloads
|
||||
print_rx_fifo(len(tx_payloads[0]))
|
||||
|
||||
|
||||
def set_role():
|
||||
"""Set the role using stdin stream. Timeout arg for slave() can be
|
||||
specified using a space delimiter (e.g. 'R 10' calls `slave(10)`)
|
||||
|
||||
:return:
|
||||
- True when role is complete & app should continue running.
|
||||
- False when app should exit
|
||||
"""
|
||||
user_input = input(
|
||||
"*** Enter 'R' for receiver role.\n"
|
||||
"*** Enter 'T' for transmitter role.\n"
|
||||
"*** Enter 'Q' to quit example.\n"
|
||||
) or "?"
|
||||
user_input = user_input.split()
|
||||
if user_input[0].upper().startswith("R"):
|
||||
if len(user_input) > 1:
|
||||
slave(int(user_input[1]))
|
||||
else:
|
||||
slave()
|
||||
return True
|
||||
elif user_input[0].upper().startswith("T"):
|
||||
master()
|
||||
return True
|
||||
elif user_input[0].upper().startswith("Q"):
|
||||
radio.powerDown()
|
||||
return False
|
||||
else:
|
||||
print(user_input[0], "is an unrecognized input. Please try again.")
|
||||
return set_role()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
args = parser.parse_args() # parse any CLI args
|
||||
|
||||
# initialize the nRF24L01 on the spi bus
|
||||
if not radio.begin():
|
||||
raise RuntimeError("radio hardware is not responding")
|
||||
|
||||
# For this example, we will use different addresses
|
||||
# An address need to be a buffer protocol object (bytearray)
|
||||
address = [b"1Node", b"2Node"]
|
||||
# It is very helpful to think of an address as a path instead of as
|
||||
# an identifying device destination
|
||||
|
||||
print(sys.argv[0]) # print example name
|
||||
|
||||
# to use different addresses on a pair of radios, we need a variable to
|
||||
# uniquely identify which address this radio will use to transmit
|
||||
# 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
radio_number = args.node # uses default value from `parser`
|
||||
if args.node is None: # if '--node' arg wasn't specified
|
||||
radio_number = bool(
|
||||
int(
|
||||
input(
|
||||
"Which radio is this? Enter '0' or '1'. Defaults to '0' "
|
||||
) or 0
|
||||
)
|
||||
)
|
||||
|
||||
# set the Power Amplifier level to -12 dBm since this test example is
|
||||
# usually run with nRF24L01 transceivers in close proximity of each other
|
||||
radio.setPALevel(RF24_PA_LOW) # RF24_PA_MAX is default
|
||||
|
||||
# ACK payloads are dynamically sized.
|
||||
radio.enableDynamicPayloads() # to use ACK payloads
|
||||
|
||||
# this example uses the ACK payload to trigger the IRQ pin active for
|
||||
# the "on data received" event
|
||||
radio.enableAckPayload() # enable ACK payloads
|
||||
|
||||
# set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radio_number]) # always uses pipe 0
|
||||
|
||||
# set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[not radio_number]) # using pipe 1
|
||||
|
||||
# for debugging, we have 2 options that print a large block of details
|
||||
# (smaller) function that prints raw register values
|
||||
# radio.printDetails()
|
||||
# (larger) function that prints human readable data
|
||||
# radio.printPrettyDetails()
|
||||
|
||||
try:
|
||||
if args.role is None: # if not specified with CLI arg '-r'
|
||||
while set_role():
|
||||
pass # continue example until 'Q' is entered
|
||||
else: # if role was set using CLI args
|
||||
# run role once and exit
|
||||
master() if bool(args.role) else slave()
|
||||
except KeyboardInterrupt:
|
||||
print(" Keyboard Interrupt detected. Exiting...")
|
||||
radio.powerDown()
|
||||
sys.exit()
|
259
src/libs/RF24-master/examples_linux/manualAcknowledgements.cpp
Normal file
259
src/libs/RF24-master/examples_linux/manualAcknowledgements.cpp
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* See documentation at https://nRF24.github.io/RF24
|
||||
* See License information at root directory of this library
|
||||
* Author: Brendan Doherty (2bndy5)
|
||||
*/
|
||||
|
||||
/**
|
||||
* A simple example of sending data from 1 nRF24L01 transceiver to another
|
||||
* with manually transmitted (non-automatic) Acknowledgement (ACK) payloads.
|
||||
* This example still uses ACK packets, but they have no payloads. Instead the
|
||||
* acknowledging response is sent with `write()`. This tactic allows for more
|
||||
* updated acknowledgement payload data, where actual ACK payloads' data are
|
||||
* outdated by 1 transmission because they have to loaded before receiving a
|
||||
* transmission.
|
||||
*
|
||||
* This example was written to be used on 2 devices acting as "nodes".
|
||||
* Use `ctrl+c` to quit at any time.
|
||||
*/
|
||||
#include <ctime> // time()
|
||||
#include <iostream> // cin, cout, endl
|
||||
#include <string> // string, getline()
|
||||
#include <time.h> // CLOCK_MONOTONIC_RAW, timespec, clock_gettime()
|
||||
#include <RF24/RF24.h> // RF24, RF24_PA_LOW, delay()
|
||||
|
||||
using namespace std;
|
||||
|
||||
/****************** Linux ***********************/
|
||||
// Radio CE Pin, CSN Pin, SPI Speed
|
||||
// CE Pin uses GPIO number with BCM and SPIDEV drivers, other platforms use their own pin numbering
|
||||
// CS Pin addresses the SPI bus number at /dev/spidev<a>.<b>
|
||||
// ie: RF24 radio(<ce_pin>, <a>*10+<b>); spidev1.0 is 10, spidev1.1 is 11 etc..
|
||||
|
||||
// Generic:
|
||||
RF24 radio(22, 0);
|
||||
/****************** Linux (BBB,x86,etc) ***********************/
|
||||
// See http://nRF24.github.io/RF24/pages.html for more information on usage
|
||||
// See http://iotdk.intel.com/docs/master/mraa/ for more information on MRAA
|
||||
// See https://www.kernel.org/doc/Documentation/spi/spidev for more information on SPIDEV
|
||||
|
||||
// For this example, we'll be using a payload containing
|
||||
// a string & an integer number that will be incremented
|
||||
// on every successful transmission.
|
||||
// Make a data structure to store the entire payload of different datatypes
|
||||
struct PayloadStruct {
|
||||
char message[7]; // only using 6 characters for TX & RX payloads
|
||||
uint8_t counter;
|
||||
};
|
||||
PayloadStruct payload;
|
||||
|
||||
void setRole(); // prototype to set the node's role
|
||||
void master(); // prototype of the TX node's behavior
|
||||
void slave(); // prototype of the RX node's behavior
|
||||
|
||||
// custom defined timer for evaluating transmission time in microseconds
|
||||
struct timespec startTimer, endTimer;
|
||||
uint32_t getMicros(); // prototype to get ellapsed time in microseconds
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
// perform hardware check
|
||||
if (!radio.begin()) {
|
||||
cout << "radio hardware is not responding!!" << endl;
|
||||
return 0; // quit now
|
||||
}
|
||||
|
||||
// append a NULL terminating 0 for printing as a c-string
|
||||
payload.message[6] = 0;
|
||||
|
||||
// Let these addresses be used for the pair of nodes used in this example
|
||||
uint8_t address[2][6] = {"1Node", "2Node"};
|
||||
// the TX address^ , ^the RX address
|
||||
// It is very helpful to think of an address as a path instead of as
|
||||
// an identifying device destination
|
||||
|
||||
// to use different addresses on a pair of radios, we need a variable to
|
||||
// uniquely identify which address this radio will use to transmit
|
||||
bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
|
||||
// print example's name
|
||||
cout << argv[0] << endl;
|
||||
|
||||
// Set the radioNumber via the terminal on startup
|
||||
cout << "Which radio is this? Enter '0' or '1'. Defaults to '0' ";
|
||||
string input;
|
||||
getline(cin, input);
|
||||
radioNumber = input.length() > 0 && (uint8_t)input[0] == 49;
|
||||
|
||||
// Set the PA Level low to try preventing power supply related problems
|
||||
// because these examples are likely run with nodes in close proximity to
|
||||
// each other.
|
||||
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
|
||||
|
||||
// save on transmission time by setting the radio to only transmit the
|
||||
// number of bytes we need to transmit a float
|
||||
radio.setPayloadSize(sizeof(payload)); // char[7] & uint8_t datatypes occupy 8 bytes
|
||||
|
||||
// set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radioNumber]); // always uses pipe 0
|
||||
|
||||
// set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1
|
||||
|
||||
// For debugging info
|
||||
// radio.printDetails(); // (smaller) function that prints raw register values
|
||||
// radio.printPrettyDetails(); // (larger) function that prints human readable data
|
||||
|
||||
// ready to execute program now
|
||||
setRole(); // calls master() or slave() based on user input
|
||||
return 0;
|
||||
} // main
|
||||
|
||||
|
||||
/**
|
||||
* set this node's role from stdin stream.
|
||||
* this only considers the first char as input.
|
||||
*/
|
||||
void setRole() {
|
||||
string input = "";
|
||||
while (!input.length()) {
|
||||
cout << "*** PRESS 'T' to begin transmitting to the other node\n";
|
||||
cout << "*** PRESS 'R' to begin receiving from the other node\n";
|
||||
cout << "*** PRESS 'Q' to exit" << endl;
|
||||
getline(cin, input);
|
||||
if (input.length() >= 1) {
|
||||
if (input[0] == 'T' || input[0] == 't')
|
||||
master();
|
||||
else if (input[0] == 'R' || input[0] == 'r')
|
||||
slave();
|
||||
else if (input[0] == 'Q' || input[0] == 'q')
|
||||
break;
|
||||
else
|
||||
cout << input[0] << " is an invalid input. Please try again." << endl;
|
||||
}
|
||||
input = ""; // stay in the while loop
|
||||
} // while
|
||||
} // setRole()
|
||||
|
||||
|
||||
/**
|
||||
* make this node act as the transmitter
|
||||
*/
|
||||
void master() {
|
||||
|
||||
memcpy(payload.message, "Hello ", 6); // set the outgoing message
|
||||
radio.stopListening(); // put in TX mode
|
||||
|
||||
unsigned int failures = 0; // keep track of failures
|
||||
while (failures < 6) {
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &startTimer); // start the timer
|
||||
bool report = radio.write(&payload, sizeof(payload)); // transmit & save the report
|
||||
|
||||
if (report) {
|
||||
// transmission successful; wait for response and print results
|
||||
|
||||
radio.startListening(); // put in RX mode
|
||||
unsigned long start_timeout = millis(); // timer to detect no response
|
||||
while (!radio.available()) { // wait for response
|
||||
if (millis() - start_timeout > 200) // only wait 200 ms
|
||||
break;
|
||||
}
|
||||
unsigned long ellapsedTime = getMicros(); // end the timer
|
||||
radio.stopListening(); // put back in TX mode
|
||||
|
||||
// print summary of transactions
|
||||
uint8_t pipe;
|
||||
cout << "Transmission successful! ";
|
||||
if (radio.available(&pipe)) { // is there a payload received? grab the pipe number that received it
|
||||
uint8_t bytes = radio.getPayloadSize(); // grab the incoming payload size
|
||||
cout << "Round trip delay = ";
|
||||
cout << ellapsedTime; // print the timer result
|
||||
cout << " us. Sent: " << payload.message; // print outgoing message
|
||||
cout << (unsigned int)payload.counter; // print outgoing counter
|
||||
PayloadStruct received;
|
||||
radio.read(&received, sizeof(received)); // get incoming payload
|
||||
cout << " Recieved " << (unsigned int)bytes; // print incoming payload size
|
||||
cout << " on pipe " << (unsigned int)pipe; // print RX pipe number
|
||||
cout << ": " << received.message; // print the incoming message
|
||||
cout << (unsigned int)received.counter; // print the incoming counter
|
||||
cout << endl;
|
||||
payload.counter = received.counter; // save incoming counter for next outgoing counter
|
||||
}
|
||||
else {
|
||||
cout << "Recieved no response." << endl; // no response received
|
||||
}
|
||||
}
|
||||
else {
|
||||
cout << "Transmission failed or timed out"; // payload was not delivered
|
||||
cout << endl;
|
||||
failures++; // increment failure counter
|
||||
} // report
|
||||
|
||||
// to make this example readable in the terminal
|
||||
delay(1000); // slow transmissions down by 1 second
|
||||
} // while
|
||||
|
||||
cout << failures << " failures detected. Leaving TX role." << endl;
|
||||
} // master
|
||||
|
||||
|
||||
/**
|
||||
* make this node act as the receiver
|
||||
*/
|
||||
void slave() {
|
||||
memcpy(payload.message, "World ", 6); // set the response message
|
||||
radio.startListening(); // put in RX mode
|
||||
|
||||
time_t startTimer = time(nullptr); // start a timer
|
||||
while (time(nullptr) - startTimer < 6) { // use 6 second timeout
|
||||
uint8_t pipe;
|
||||
if (radio.available(&pipe)) { // is there a payload? get the pipe number that recieved it
|
||||
uint8_t bytes = radio.getPayloadSize(); // get size of incoming payload
|
||||
PayloadStruct received;
|
||||
radio.read(&received, sizeof(received)); // get incoming payload
|
||||
payload.counter = received.counter + 1; // increment payload for response
|
||||
|
||||
// transmit response & save result to `report`
|
||||
radio.stopListening(); // put in TX mode
|
||||
radio.writeFast(&payload, sizeof(payload)); // load response into TX FIFO
|
||||
bool report = radio.txStandBy(150); // keep retrying for 150 ms
|
||||
radio.startListening(); // put back in RX mode
|
||||
|
||||
// print summary of transactions
|
||||
cout << "Received " << (unsigned int)bytes; // print the size of the payload
|
||||
cout << " bytes on pipe ";
|
||||
cout << (unsigned int)pipe; // print the pipe number
|
||||
cout << ": " << received.message; // print incoming message
|
||||
cout << (unsigned int)received.counter; // print incoming counter
|
||||
|
||||
if (report) {
|
||||
cout << " Sent: " << payload.message; // print outgoing message
|
||||
cout << (unsigned int)payload.counter; // print outgoing counter
|
||||
cout << endl;
|
||||
}
|
||||
else {
|
||||
cout << " Response failed to send." << endl; // failed to send response
|
||||
}
|
||||
startTimer = time(nullptr); // reset timer
|
||||
} // available
|
||||
} // while
|
||||
|
||||
cout << "Nothing received in 6 seconds. Leaving RX role." << endl;
|
||||
radio.stopListening(); // recommended idle mode is TX mode
|
||||
} // slave
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the ellapsed time in microseconds
|
||||
*/
|
||||
uint32_t getMicros() {
|
||||
// this function assumes that the timer was started using
|
||||
// `clock_gettime(CLOCK_MONOTONIC_RAW, &startTimer);`
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &endTimer);
|
||||
uint32_t seconds = endTimer.tv_sec - startTimer.tv_sec;
|
||||
uint32_t useconds = (endTimer.tv_nsec - startTimer.tv_nsec) / 1000;
|
||||
|
||||
return ((seconds) * 1000 + useconds) + 0.5;
|
||||
}
|
254
src/libs/RF24-master/examples_linux/manual_acknowledgements.py
Normal file
254
src/libs/RF24-master/examples_linux/manual_acknowledgements.py
Normal file
@ -0,0 +1,254 @@
|
||||
"""
|
||||
A simple example of sending data from 1 nRF24L01 transceiver to another
|
||||
with manually transmitted (non-automatic) Acknowledgement (ACK) payloads.
|
||||
This example still uses ACK packets, but they have no payloads. Instead the
|
||||
acknowledging response is sent with `write()`. This tactic allows for more
|
||||
updated acknowledgement payload data, where actual ACK payloads' data are
|
||||
outdated by 1 transmission because they have to loaded before receiving a
|
||||
transmission.
|
||||
|
||||
This example was written to be used on 2 devices acting as 'nodes'.
|
||||
"""
|
||||
import sys
|
||||
import argparse
|
||||
import time
|
||||
import struct
|
||||
from RF24 import RF24, RF24_PA_LOW
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--node",
|
||||
type=int,
|
||||
choices=range(2),
|
||||
help="the identifying radio number (or node ID number)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--role",
|
||||
type=int,
|
||||
choices=range(2),
|
||||
help="'1' specifies the TX role. '0' specifies the RX role."
|
||||
)
|
||||
|
||||
########### USER CONFIGURATION ###########
|
||||
# See https://github.com/TMRh20/RF24/blob/master/pyRF24/readme.md
|
||||
# Radio CE Pin, CSN Pin, SPI Speed
|
||||
# CE Pin uses GPIO number with BCM and SPIDEV drivers, other platforms use
|
||||
# their own pin numbering
|
||||
# CS Pin addresses the SPI bus number at /dev/spidev<a>.<b>
|
||||
# ie: RF24 radio(<ce_pin>, <a>*10+<b>); spidev1.0 is 10, spidev1.1 is 11 etc..
|
||||
|
||||
# Generic:
|
||||
radio = RF24(22, 0)
|
||||
################## Linux (BBB,x86,etc) #########################
|
||||
# See http://nRF24.github.io/RF24/pages.html for more information on usage
|
||||
# See http://iotdk.intel.com/docs/master/mraa/ for more information on MRAA
|
||||
# See https://www.kernel.org/doc/Documentation/spi/spidev for more
|
||||
# information on SPIDEV
|
||||
|
||||
# using the python keyword global is bad practice. Instead we'll use a 1 item
|
||||
# list to store our integer number for the payloads' counter
|
||||
counter = [0]
|
||||
|
||||
|
||||
def master():
|
||||
"""Transmits a message and an incrementing integer every second, then
|
||||
wait for a response for up to 200 ms.
|
||||
"""
|
||||
radio.stopListening() # put radio in TX mode
|
||||
failures = 0
|
||||
while failures < 6:
|
||||
# use bytes() to pack our counter data into the payload
|
||||
# NOTE b"\x00" byte is a c-string's NULL terminating 0
|
||||
buffer = b"Hello \x00" + bytes(counter)
|
||||
start_timer = time.monotonic_ns() # start timer
|
||||
result = radio.write(buffer)
|
||||
if not result:
|
||||
failures += 1
|
||||
print("Transmission failed or timed out")
|
||||
else:
|
||||
radio.startListening() # put radio in RX mode
|
||||
timout = time.monotonic() * 1000 + 200 # use 200 ms timeout
|
||||
# declare a variable to save the incoming response
|
||||
while not radio.available() and time.monotonic() * 1000 < timout:
|
||||
pass # wait for incoming payload or timeout
|
||||
radio.stopListening() # put radio in TX mode
|
||||
end_timer = time.monotonic_ns() # end timer
|
||||
print(
|
||||
"Transmission successful. Sent: {}{}.".format(
|
||||
buffer[:6].decode("utf-8"),
|
||||
counter[0]
|
||||
),
|
||||
end=" "
|
||||
)
|
||||
has_payload, pipe_number = radio.available_pipe()
|
||||
if has_payload:
|
||||
# grab the incoming payload
|
||||
received = radio.read(radio.payloadSize)
|
||||
# NOTE received[7:8] discards NULL terminating 0
|
||||
counter[0] = received[7:8][0] # save the counter
|
||||
print(
|
||||
"Received {} bytes on pipe {}: {}{}. "
|
||||
"Round-trip delay: {} us.".format(
|
||||
radio.payloadSize,
|
||||
pipe_number,
|
||||
bytes(received[:6]).decode("utf-8"),
|
||||
counter[0],
|
||||
(end_timer - start_timer) / 1000
|
||||
)
|
||||
)
|
||||
else:
|
||||
print("No response received.")
|
||||
time.sleep(1) # make example readable by slowing down transmissions
|
||||
print(failures, "failures detected. Leaving TX role.")
|
||||
|
||||
|
||||
def slave(timeout=6):
|
||||
"""Listen for any payloads and print the transaction
|
||||
|
||||
:param int timeout: The number of seconds to wait (with no transmission)
|
||||
until exiting function.
|
||||
"""
|
||||
radio.startListening() # put radio in RX mode
|
||||
|
||||
start_timer = time.monotonic() # start a timer to detect timeout
|
||||
while (time.monotonic() - start_timer) < timeout:
|
||||
# receive `count` payloads or wait 6 seconds till timing out
|
||||
has_payload, pipe_number = radio.available_pipe()
|
||||
if has_payload:
|
||||
received = radio.read(radio.payloadSize) # fetch the payload
|
||||
# NOTE received[7:8] discards NULL terminating 0
|
||||
# increment the counter from received payload
|
||||
counter[0] = received[7:8][0] + 1 if received[7:8][0] < 255 else 0
|
||||
# use bytes() to pack our counter data into the payload
|
||||
# NOTE b"\x00" byte is a c-string's NULL terminating 0
|
||||
buffer = b"World \x00" + bytes(counter)
|
||||
radio.stopListening() # put radio in TX mode
|
||||
radio.writeFast(buffer) # load response into TX FIFO
|
||||
# keep retrying to send response for 150 milliseconds
|
||||
result = radio.txStandBy(150) # save response's result
|
||||
# NOTE txStandBy() flushes TX FIFO on transmission failure
|
||||
radio.startListening() # put radio back in RX mode
|
||||
# print the payload received payload
|
||||
print(
|
||||
"Received {} bytes on pipe {}: {}{}.".format(
|
||||
radio.payloadSize,
|
||||
pipe_number,
|
||||
bytes(received[:6]).decode("utf-8"),
|
||||
received[7:8][0]
|
||||
),
|
||||
end=" "
|
||||
)
|
||||
if result: # did response succeed?
|
||||
# print response's payload
|
||||
print(
|
||||
"Sent: {}{}".format(
|
||||
buffer[:6].decode("utf-8"),
|
||||
counter[0]
|
||||
)
|
||||
)
|
||||
else:
|
||||
print("Response failed or timed out")
|
||||
start_timer = time.monotonic() # reset the timeout timer
|
||||
|
||||
print("Nothing received in 6 seconds. Leaving RX role")
|
||||
# recommended behavior is to keep in TX mode while idle
|
||||
radio.stopListening() # put the radio in TX mode
|
||||
|
||||
|
||||
def set_role():
|
||||
"""Set the role using stdin stream. Timeout arg for slave() can be
|
||||
specified using a space delimiter (e.g. 'R 10' calls `slave(10)`)
|
||||
|
||||
:return:
|
||||
- True when role is complete & app should continue running.
|
||||
- False when app should exit
|
||||
"""
|
||||
user_input = input(
|
||||
"*** Enter 'R' for receiver role.\n"
|
||||
"*** Enter 'T' for transmitter role.\n"
|
||||
"*** Enter 'Q' to quit example.\n"
|
||||
) or "?"
|
||||
user_input = user_input.split()
|
||||
if user_input[0].upper().startswith("R"):
|
||||
if len(user_input) > 1:
|
||||
slave(int(user_input[1]))
|
||||
else:
|
||||
slave()
|
||||
return True
|
||||
elif user_input[0].upper().startswith("T"):
|
||||
master()
|
||||
return True
|
||||
elif user_input[0].upper().startswith("Q"):
|
||||
radio.powerDown()
|
||||
return False
|
||||
print(user_input[0], "is an unrecognized input. Please try again.")
|
||||
return set_role()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
args = parser.parse_args() # parse any CLI args
|
||||
|
||||
# initialize the nRF24L01 on the spi bus
|
||||
if not radio.begin():
|
||||
raise RuntimeError("radio hardware is not responding")
|
||||
|
||||
# For this example, we will use different addresses
|
||||
# An address need to be a buffer protocol object (bytearray)
|
||||
address = [b"1Node", b"2Node"]
|
||||
# It is very helpful to think of an address as a path instead of as
|
||||
# an identifying device destination
|
||||
|
||||
print(sys.argv[0]) # print example name
|
||||
|
||||
# to use different addresses on a pair of radios, we need a variable to
|
||||
# uniquely identify which address this radio will use to transmit
|
||||
# 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
radio_number = args.node # uses default value from `parser`
|
||||
if args.node is None: # if '--node' arg wasn't specified
|
||||
radio_number = bool(
|
||||
int(
|
||||
input(
|
||||
"Which radio is this? Enter '0' or '1'. Defaults to '0' "
|
||||
) or 0
|
||||
)
|
||||
)
|
||||
|
||||
# set the Power Amplifier level to -12 dBm since this test example is
|
||||
# usually run with nRF24L01 transceivers in close proximity of each other
|
||||
radio.setPALevel(RF24_PA_LOW) # RF24_PA_MAX is default
|
||||
|
||||
# set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radio_number]) # always uses pipe 0
|
||||
|
||||
# set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[not radio_number]) # using pipe 1
|
||||
|
||||
# To save time during transmission, we'll set the payload size to be only
|
||||
# what we need. For this example, we'll be using a byte for the
|
||||
# payload counter and 7 bytes for the payload message
|
||||
radio.payloadSize = 8
|
||||
|
||||
# for debugging, we have 2 options that print a large block of details
|
||||
# (smaller) function that prints raw register values
|
||||
# radio.printDetails()
|
||||
# (larger) function that prints human readable data
|
||||
# radio.printPrettyDetails()
|
||||
|
||||
try:
|
||||
if args.role is None: # if not specified with CLI arg '-r'
|
||||
while set_role():
|
||||
pass # continue example until 'Q' is entered
|
||||
else: # if role was set using CLI args
|
||||
# run role once and exit
|
||||
master() if bool(args.role) else slave()
|
||||
except KeyboardInterrupt:
|
||||
print(" Keyboard Interrupt detected. Exiting...")
|
||||
radio.powerDown()
|
||||
sys.exit()
|
273
src/libs/RF24-master/examples_linux/multiceiverDemo.cpp
Normal file
273
src/libs/RF24-master/examples_linux/multiceiverDemo.cpp
Normal file
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* See documentation at https://nRF24.github.io/RF24
|
||||
* See License information at root directory of this library
|
||||
* Author: Brendan Doherty (2bndy5)
|
||||
*/
|
||||
|
||||
/**
|
||||
* A simple example of sending data from as many as 6 nRF24L01 transceivers to
|
||||
* 1 receiving transceiver. This technique is trademarked by
|
||||
* Nordic Semiconductors as "MultiCeiver".
|
||||
*
|
||||
* This example was written to be used on up to 6 devices acting as TX nodes &
|
||||
* only 1 device acting as the RX node (that's a maximum of 7 devices).
|
||||
* Use `ctrl+c` to quit at any time.
|
||||
*/
|
||||
#include <ctime> // time()
|
||||
#include <cstring> // strcmp()
|
||||
#include <iostream> // cin, cout, endl
|
||||
#include <string> // string, getline()
|
||||
#include <time.h> // CLOCK_MONOTONIC_RAW, timespec, clock_gettime()
|
||||
#include <RF24/RF24.h> // RF24, RF24_PA_LOW, delay()
|
||||
|
||||
using namespace std;
|
||||
|
||||
/****************** Linux ***********************/
|
||||
// Radio CE Pin, CSN Pin, SPI Speed
|
||||
// CE Pin uses GPIO number with BCM and SPIDEV drivers, other platforms use their own pin numbering
|
||||
// CS Pin addresses the SPI bus number at /dev/spidev<a>.<b>
|
||||
// ie: RF24 radio(<ce_pin>, <a>*10+<b>); spidev1.0 is 10, spidev1.1 is 11 etc..
|
||||
|
||||
// Generic:
|
||||
RF24 radio(22, 0);
|
||||
/****************** Linux (BBB,x86,etc) ***********************/
|
||||
// See http://nRF24.github.io/RF24/pages.html for more information on usage
|
||||
// See http://iotdk.intel.com/docs/master/mraa/ for more information on MRAA
|
||||
// See https://www.kernel.org/doc/Documentation/spi/spidev for more information on SPIDEV
|
||||
|
||||
|
||||
// For this example, we'll be using 6 addresses; 1 for each TX node
|
||||
// It is very helpful to think of an address as a path instead of as
|
||||
// an identifying device destination
|
||||
// Notice that the last byte is the only byte that changes in the last 5
|
||||
// addresses. This is a limitation of the nRF24L01 transceiver for pipes 2-5
|
||||
// because they use the same first 4 bytes from pipe 1.
|
||||
uint64_t address[6] = {0x7878787878LL,
|
||||
0xB3B4B5B6F1LL,
|
||||
0xB3B4B5B6CDLL,
|
||||
0xB3B4B5B6A3LL,
|
||||
0xB3B4B5B60FLL,
|
||||
0xB3B4B5B605LL};
|
||||
|
||||
|
||||
// For this example, we'll be using a payload containing
|
||||
// a node ID number and a single integer number that will be incremented
|
||||
// on every successful transmission.
|
||||
// Make a data structure to use as a payload.
|
||||
struct PayloadStruct
|
||||
{
|
||||
unsigned int nodeID;
|
||||
unsigned int payloadID;
|
||||
};
|
||||
PayloadStruct payload;
|
||||
|
||||
void setRole(); // prototype to set the node's role
|
||||
void master(unsigned int); // prototype of a TX node's behavior
|
||||
void slave(); // prototype of the RX node's behavior
|
||||
void printHelp(string); // prototype to function that explain CLI arg usage
|
||||
|
||||
// custom defined timer for evaluating transmission time in microseconds
|
||||
struct timespec startTimer, endTimer;
|
||||
uint32_t getMicros(); // prototype to get ellapsed time in microseconds
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
// perform hardware check
|
||||
if (!radio.begin()) {
|
||||
cout << "radio hardware is not responding!!" << endl;
|
||||
return 0; // quit now
|
||||
}
|
||||
|
||||
// to use different addresses on a pair of radios, we need a variable to
|
||||
// uniquely identify which address this radio will use to transmit
|
||||
unsigned int nodeNumber = 'R'; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
|
||||
bool foundArgNode = false;
|
||||
if (argc > 1) {
|
||||
if ((argc - 1) != 2) {
|
||||
// CLI arg "-n"/"--node" needs an option specified for it
|
||||
// only 1 arg is expected, so only traverse the first "--arg option" pair
|
||||
printHelp(string(argv[0]));
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp(argv[1], "-n") == 0 || strcmp(argv[1], "--node") == 0) {
|
||||
// "-n" or "--node" has been specified
|
||||
foundArgNode = true;
|
||||
if ((argv[2][0] - 48) < 6) {
|
||||
nodeNumber = argv[2][0] - 48;
|
||||
}
|
||||
else if (argv[2][0] == 'R' || argv[2][0] == 'r') {
|
||||
nodeNumber = 'R';
|
||||
}
|
||||
else {
|
||||
printHelp(string(argv[0]));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// "-n"/"--node" arg was not specified
|
||||
printHelp(string(argv[0]));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// print example's name
|
||||
cout << argv[0] << endl;
|
||||
|
||||
// Set the PA Level low to try preventing power supply related problems
|
||||
// because these examples are likely run with nodes in close proximity to
|
||||
// each other.
|
||||
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
|
||||
|
||||
// save on transmission time by setting the radio to only transmit the
|
||||
// number of bytes we need to transmit a float
|
||||
radio.setPayloadSize(sizeof(payload)); // 2x int datatype occupy 8 bytes
|
||||
|
||||
// For debugging info
|
||||
// radio.printDetails(); // (smaller) function that prints raw register values
|
||||
// radio.printPrettyDetails(); // (larger) function that prints human readable data
|
||||
|
||||
// ready to execute program now
|
||||
if (!foundArgNode) {
|
||||
setRole(); // calls master() or slave() based on user input
|
||||
}
|
||||
else {
|
||||
nodeNumber < 6 ? master(nodeNumber) : slave();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* set this node's role from stdin stream.
|
||||
* this only considers the first char as input.
|
||||
*/
|
||||
void setRole() {
|
||||
|
||||
string input = "";
|
||||
while (!input.length()) {
|
||||
cout << "*** Enter a number between 0 and 5 (inclusive) to act as\n";
|
||||
cout << " a unique node number that transmits to the RX node.\n";
|
||||
cout << "*** PRESS 'R' to begin receiving from the other nodes\n";
|
||||
cout << "*** PRESS 'Q' to exit" << endl;
|
||||
getline(cin, input);
|
||||
if (input.length() >= 1) {
|
||||
unsigned int toNumber = (unsigned int)(input[0]) - 48;
|
||||
if (toNumber < 6 && toNumber >= 0)
|
||||
master(toNumber);
|
||||
else if (input[0] == 'R' || input[0] == 'r')
|
||||
slave();
|
||||
else if (input[0] == 'Q' || input[0] == 'q')
|
||||
break;
|
||||
else
|
||||
cout << input[0] << " is an invalid input. Please try again." << endl;
|
||||
}
|
||||
input = ""; // stay in the while loop
|
||||
} // while
|
||||
} // setRole
|
||||
|
||||
|
||||
/**
|
||||
* act as unique TX node identified by the `role` number
|
||||
*/
|
||||
void master(unsigned int role) {
|
||||
// set the payload's nodeID & reset the payload's identifying number
|
||||
payload.nodeID = role;
|
||||
payload.payloadID = 0;
|
||||
|
||||
// Set the address on pipe 0 to the RX node.
|
||||
radio.stopListening(); // put radio in TX mode
|
||||
radio.openWritingPipe(address[role]);
|
||||
|
||||
// According to the datasheet, the auto-retry features's delay value should
|
||||
// be "skewed" to allow the RX node to receive 1 transmission at a time.
|
||||
// So, use varying delay between retry attempts and 15 (at most) retry attempts
|
||||
radio.setRetries(((role * 3) % 12) + 3, 15); // maximum value is 15 for both args
|
||||
|
||||
unsigned int failures = 0;
|
||||
while (failures < 6) {
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &startTimer); // start the timer
|
||||
bool report = radio.write(&payload, sizeof(payload)); // transmit & save the report
|
||||
uint32_t timerEllapsed = getMicros(); // end the timer
|
||||
|
||||
if (report) {
|
||||
// payload was delivered
|
||||
cout << "Transmission of PayloadID ";
|
||||
cout << payload.payloadID; // print payload number
|
||||
cout << " as node " << payload.nodeID; // print node number
|
||||
cout << " successful! Time to transmit = ";
|
||||
cout << timerEllapsed << " us" << endl; // print the timer result
|
||||
}
|
||||
else {
|
||||
// payload was not delivered
|
||||
failures++;
|
||||
cout << "Transmission failed or timed out" << endl;
|
||||
}
|
||||
payload.payloadID++; // increment payload number
|
||||
|
||||
// to make this example readable in the terminal
|
||||
delay(500); // slow transmissions down by 0.5 second
|
||||
} // while
|
||||
cout << failures << " failures detected. Leaving TX role." << endl;
|
||||
} // master
|
||||
|
||||
|
||||
/**
|
||||
* act as the RX node that receives from up to 6 other TX nodes
|
||||
*/
|
||||
void slave() {
|
||||
|
||||
// Set the addresses for all pipes to TX nodes
|
||||
for (uint8_t i = 0; i < 6; ++i)
|
||||
radio.openReadingPipe(i, address[i]);
|
||||
|
||||
radio.startListening(); // put radio in RX mode
|
||||
|
||||
time_t startTimer = time(nullptr); // start a timer
|
||||
while (time(nullptr) - startTimer < 6) { // use 6 second timeout
|
||||
uint8_t pipe;
|
||||
if (radio.available(&pipe)) { // is there a payload? get the pipe number that recieved it
|
||||
uint8_t bytes = radio.getPayloadSize(); // get the size of the payload
|
||||
radio.read(&payload, bytes); // fetch payload from FIFO
|
||||
cout << "Received " << (unsigned int)bytes; // print the size of the payload
|
||||
cout << " bytes on pipe " << (unsigned int)pipe; // print the pipe number
|
||||
cout << " from node " << payload.nodeID; // print the payload's origin
|
||||
cout << ". PayloadID: " << payload.payloadID << endl; // print the payload's number
|
||||
startTimer = time(nullptr); // reset timer
|
||||
}
|
||||
}
|
||||
cout << "Nothing received in 6 seconds. Leaving RX role." << endl;
|
||||
} // slave
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the ellapsed time in microseconds
|
||||
*/
|
||||
uint32_t getMicros() {
|
||||
// this function assumes that the timer was started using
|
||||
// `clock_gettime(CLOCK_MONOTONIC_RAW, &startTimer);`
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &endTimer);
|
||||
uint32_t seconds = endTimer.tv_sec - startTimer.tv_sec;
|
||||
uint32_t useconds = (endTimer.tv_nsec - startTimer.tv_nsec) / 1000;
|
||||
|
||||
return ((seconds) * 1000 + useconds) + 0.5;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* print a manual page of instructions on how to use this example's CLI args
|
||||
*/
|
||||
void printHelp(string progName) {
|
||||
cout << "usage: " << progName << " [-h] [-n {0,1,2,3,4,5,r,R}]\n\n"
|
||||
<< "A simple example of sending data from as many as 6 nRF24L01 transceivers to\n"
|
||||
<< "1 receiving transceiver. This technique is trademarked by\n"
|
||||
<< "Nordic Semiconductors as 'MultiCeiver'.\n"
|
||||
<< "\nThis example was written to be used on up to 6 devices acting as TX nodes with\n"
|
||||
<< "another device acting as a RX node (that's a total of 7 devices).\n"
|
||||
<< "\noptional arguments:\n -h, --help\t\tshow this help message and exit\n"
|
||||
<< " -n {0,1,2,3,4,5,r,R}, --node {0,1,2,3,4,5,r,R}"
|
||||
<< "\n\t\t\t0-5 specifies the identifying node ID number for the TX role."
|
||||
<< "\n\t\t\t'r' or 'R' specifies the RX role." << endl;
|
||||
}
|
199
src/libs/RF24-master/examples_linux/multiceiver_demo.py
Normal file
199
src/libs/RF24-master/examples_linux/multiceiver_demo.py
Normal file
@ -0,0 +1,199 @@
|
||||
"""
|
||||
A simple example of sending data from as many as 6 nRF24L01 transceivers to
|
||||
1 receiving transceiver. This technique is trademarked by
|
||||
Nordic Semiconductors as "MultiCeiver".
|
||||
|
||||
This example was written to be used on up to 6 devices acting as TX nodes &
|
||||
only 1 device acting as the RX node (that's a maximum of 7 devices).
|
||||
"""
|
||||
import sys
|
||||
import argparse
|
||||
import time
|
||||
import struct
|
||||
from RF24 import RF24, RF24_PA_LOW
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--node",
|
||||
choices=("0", "1", "2", "3", "4", "5", "R", "r"),
|
||||
help="the identifying node ID number for the TX role. "
|
||||
"Use 'R' or 'r' to specify the RX role"
|
||||
)
|
||||
|
||||
########### USER CONFIGURATION ###########
|
||||
# See https://github.com/TMRh20/RF24/blob/master/pyRF24/readme.md
|
||||
# Radio CE Pin, CSN Pin, SPI Speed
|
||||
# CE Pin uses GPIO number with BCM and SPIDEV drivers, other platforms use
|
||||
# their own pin numbering
|
||||
# CS Pin addresses the SPI bus number at /dev/spidev<a>.<b>
|
||||
# ie: RF24 radio(<ce_pin>, <a>*10+<b>); spidev1.0 is 10, spidev1.1 is 11 etc..
|
||||
|
||||
# Generic:
|
||||
radio = RF24(22, 0)
|
||||
################## Linux (BBB,x86,etc) #########################
|
||||
# See http://nRF24.github.io/RF24/pages.html for more information on usage
|
||||
# See http://iotdk.intel.com/docs/master/mraa/ for more information on MRAA
|
||||
# See https://www.kernel.org/doc/Documentation/spi/spidev for more
|
||||
# information on SPIDEV
|
||||
|
||||
# setup the addresses for all transmitting radio nodes
|
||||
addresses = [
|
||||
b"\x78" * 5,
|
||||
b"\xF1\xB6\xB5\xB4\xB3",
|
||||
b"\xCD\xB6\xB5\xB4\xB3",
|
||||
b"\xA3\xB6\xB5\xB4\xB3",
|
||||
b"\x0F\xB6\xB5\xB4\xB3",
|
||||
b"\x05\xB6\xB5\xB4\xB3"
|
||||
]
|
||||
# It is very helpful to think of an address as a path instead of as
|
||||
# an identifying device destination
|
||||
|
||||
|
||||
def master(node_number):
|
||||
"""start transmitting to the base station.
|
||||
|
||||
:param int node_number: the node's identifying index (from the
|
||||
the `addresses` list). This is a required parameter
|
||||
"""
|
||||
radio.stopListening() # put radio in TX mode
|
||||
# set the TX address to the address of the base station.
|
||||
radio.openWritingPipe(addresses[node_number])
|
||||
counter = 0
|
||||
failures = 0
|
||||
while failures < 6:
|
||||
counter += 1
|
||||
# payloads will include the node_number and a payload ID character
|
||||
payload = struct.pack("<ii", node_number, counter)
|
||||
start_timer = time.monotonic_ns()
|
||||
report = radio.write(payload)
|
||||
end_timer = time.monotonic_ns()
|
||||
# show something to see it isn't frozen
|
||||
print(
|
||||
"Transmission of payloadID {} as node {}".format(
|
||||
counter,
|
||||
node_number
|
||||
),
|
||||
end=" "
|
||||
)
|
||||
if report:
|
||||
print(
|
||||
"successfull! Time to transmit = {} us".format(
|
||||
(end_timer - start_timer) / 1000
|
||||
)
|
||||
)
|
||||
else:
|
||||
failures += 1
|
||||
print("failed or timed out")
|
||||
time.sleep(0.5) # slow down the test for readability
|
||||
print(failures, "failures detected. Leaving TX role.")
|
||||
|
||||
|
||||
def slave(timeout=10):
|
||||
"""Use the radio as a base station for lisening to all nodes
|
||||
|
||||
:param int timeout: The number of seconds to wait (with no transmission)
|
||||
until exiting function.
|
||||
"""
|
||||
# write the addresses to all pipes.
|
||||
for pipe_n, addr in enumerate(addresses):
|
||||
radio.openReadingPipe(pipe_n, addr)
|
||||
radio.startListening() # put radio in RX mode
|
||||
start_timer = time.monotonic() # start timer
|
||||
while time.monotonic() - start_timer < timeout:
|
||||
has_payload, pipe_number = radio.available_pipe()
|
||||
if has_payload:
|
||||
# unpack payload
|
||||
nodeID, payloadID = struct.unpack(
|
||||
"<ii",
|
||||
radio.read(radio.payloadSize)
|
||||
)
|
||||
# show the pipe number that received the payload
|
||||
print(
|
||||
"Received {} bytes on pipe {} from node {}. PayloadID: "
|
||||
"{}".format(
|
||||
radio.payloadSize,
|
||||
pipe_number,
|
||||
nodeID,
|
||||
payloadID
|
||||
)
|
||||
)
|
||||
start_timer = time.monotonic() # reset timer with every payload
|
||||
|
||||
print("Nothing received in 6 seconds. Leaving RX role")
|
||||
radio.stopListening()
|
||||
|
||||
|
||||
def set_role():
|
||||
"""Set the role using stdin stream. Timeout arg for slave() can be
|
||||
specified using a space delimiter (e.g. 'R 10' calls `slave(10)`)
|
||||
|
||||
:return:
|
||||
- True when role is complete & app should continue running.
|
||||
- False when app should exit
|
||||
"""
|
||||
user_input = input(
|
||||
"*** Enter 'R' for receiver role.\n"
|
||||
"*** Enter a number in range [0, 5] to use a specific node ID for "
|
||||
"transmitter role.\n"
|
||||
"*** Enter 'Q' to quit example.\n"
|
||||
) or "?"
|
||||
user_input = user_input.split()
|
||||
if user_input[0].upper().startswith("R"):
|
||||
if len(user_input) > 1:
|
||||
slave(int(user_input[1]))
|
||||
else:
|
||||
slave()
|
||||
return True
|
||||
elif user_input[0].isdigit() and 0 <= int(user_input[0]) <= 5:
|
||||
master(int(user_input[0]))
|
||||
return True
|
||||
elif user_input[0].upper().startswith("Q"):
|
||||
radio.powerDown()
|
||||
return False
|
||||
print(user_input[0], "is an unrecognized input. Please try again.")
|
||||
return set_role()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
args = parser.parse_args() # parse any CLI args
|
||||
|
||||
# initialize the nRF24L01 on the spi bus
|
||||
if not radio.begin():
|
||||
raise RuntimeError("radio hardware is not responding")
|
||||
|
||||
print(sys.argv[0]) # print example name
|
||||
|
||||
# set the Power Amplifier level to -12 dBm since this test example is
|
||||
# usually run with nRF24L01 transceivers in close proximity of each other
|
||||
radio.setPALevel(RF24_PA_LOW) # RF24_PA_MAX is default
|
||||
|
||||
# To save time during transmission, we'll set the payload size to be only what
|
||||
# we need.
|
||||
# 2 int occupy 8 bytes in memory using len(struct.pack())
|
||||
# "<ii" means 2x little endian unsigned int
|
||||
radio.payloadSize = len(struct.pack("<ii", 0, 0))
|
||||
|
||||
# for debugging, we have 2 options that print a large block of details
|
||||
# radio.printDetails(); # (smaller) function that prints raw register values
|
||||
# radio.printPrettyDetails(); # (larger) function that prints human readable data
|
||||
|
||||
try:
|
||||
if args.node is None: # if not specified with CLI arg '-n'
|
||||
while set_role():
|
||||
pass # continue example until 'Q' is entered
|
||||
else: # if role was set using CLI args
|
||||
# run role once and exit
|
||||
if args.node.isdigit():
|
||||
master(int(args.node))
|
||||
else:
|
||||
slave()
|
||||
except KeyboardInterrupt:
|
||||
print(" Keyboard Interrupt detected. Exiting...")
|
||||
radio.powerDown()
|
||||
sys.exit()
|
291
src/libs/RF24-master/examples_linux/streamingData.cpp
Normal file
291
src/libs/RF24-master/examples_linux/streamingData.cpp
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* See documentation at https://nRF24.github.io/RF24
|
||||
* See License information at root directory of this library
|
||||
* Author: Brendan Doherty (2bndy5)
|
||||
*/
|
||||
|
||||
/**
|
||||
* A simple example of streaming data from 1 nRF24L01 transceiver to another.
|
||||
*
|
||||
* This example was written to be used on 2 devices acting as "nodes".
|
||||
* Use `ctrl+c` to quit at any time.
|
||||
*/
|
||||
#include <cmath> // abs()
|
||||
#include <ctime> // time()
|
||||
#include <cstring> // strcmp()
|
||||
#include <iostream> // cin, cout, endl
|
||||
#include <string> // string, getline()
|
||||
#include <time.h> // CLOCK_MONOTONIC_RAW, timespec, clock_gettime()
|
||||
#include <RF24/RF24.h> // RF24, RF24_PA_LOW, delay()
|
||||
|
||||
using namespace std;
|
||||
|
||||
/****************** Linux ***********************/
|
||||
// Radio CE Pin, CSN Pin, SPI Speed
|
||||
// CE Pin uses GPIO number with BCM and SPIDEV drivers, other platforms use their own pin numbering
|
||||
// CS Pin addresses the SPI bus number at /dev/spidev<a>.<b>
|
||||
// ie: RF24 radio(<ce_pin>, <a>*10+<b>); spidev1.0 is 10, spidev1.1 is 11 etc..
|
||||
|
||||
// Generic:
|
||||
RF24 radio(22, 0);
|
||||
/****************** Linux (BBB,x86,etc) ***********************/
|
||||
// See http://nRF24.github.io/RF24/pages.html for more information on usage
|
||||
// See http://iotdk.intel.com/docs/master/mraa/ for more information on MRAA
|
||||
// See https://www.kernel.org/doc/Documentation/spi/spidev for more information on SPIDEV
|
||||
|
||||
// For this example, we'll be sending 32 payloads each containing
|
||||
// 32 bytes of data that looks like ASCII art when printed to the serial
|
||||
// monitor. The TX node and RX node needs only a single 32 byte buffer.
|
||||
#define SIZE 32 // this is the maximum for this example. (minimum is 1)
|
||||
char buffer[SIZE + 1]; // for the RX node
|
||||
unsigned int counter = 0; // for counting the number of received payloads
|
||||
void makePayload(uint8_t); // prototype to construct a payload dynamically
|
||||
void setRole(); // prototype to set the node's role
|
||||
void master(); // prototype of the TX node's behavior
|
||||
void slave(); // prototype of the RX node's behavior
|
||||
void printHelp(string); // prototype to function that explain CLI arg usage
|
||||
|
||||
// custom defined timer for evaluating transmission time in microseconds
|
||||
struct timespec startTimer, endTimer;
|
||||
uint32_t getMicros(); // prototype to get ellapsed time in microseconds
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
// perform hardware check
|
||||
if (!radio.begin()) {
|
||||
cout << "radio hardware is not responding!!" << endl;
|
||||
return 0; // quit now
|
||||
}
|
||||
|
||||
// add a NULL terminating 0 for printing as a c-string
|
||||
buffer[SIZE] = 0;
|
||||
|
||||
// Let these addresses be used for the pair of nodes used in this example
|
||||
uint8_t address[2][6] = {"1Node", "2Node"};
|
||||
// the TX address^ , ^the RX address
|
||||
// It is very helpful to think of an address as a path instead of as
|
||||
// an identifying device destination
|
||||
|
||||
// to use different addresses on a pair of radios, we need a variable to
|
||||
// uniquely identify which address this radio will use to transmit
|
||||
bool radioNumber = 1; // 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
|
||||
bool foundArgNode = false;
|
||||
bool foundArgRole = false;
|
||||
bool role = false;
|
||||
if (argc > 1) {
|
||||
// CLI args are specified
|
||||
if ((argc - 1) % 2 != 0) {
|
||||
// some CLI arg doesn't have an option specified for it
|
||||
printHelp(string(argv[0])); // all args need an option in this example
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
// iterate through args starting after program name
|
||||
int a = 1;
|
||||
while (a < argc) {
|
||||
bool invalidOption = false;
|
||||
if (strcmp(argv[a], "-n") == 0 || strcmp(argv[a], "--node") == 0) {
|
||||
// "-n" or "--node" has been specified
|
||||
foundArgNode = true;
|
||||
if (argv[a + 1][0] - 48 <= 1) {
|
||||
radioNumber = (argv[a + 1][0] - 48) == 1;
|
||||
}
|
||||
else {
|
||||
// option is invalid
|
||||
invalidOption = true;
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[a], "-r") == 0 || strcmp(argv[a], "--role") == 0) {
|
||||
// "-r" or "--role" has been specified
|
||||
foundArgRole = true;
|
||||
if (argv[a + 1][0] - 48 <= 1) {
|
||||
role = (argv[a + 1][0] - 48) == 1;
|
||||
}
|
||||
else {
|
||||
// option is invalid
|
||||
invalidOption = true;
|
||||
}
|
||||
}
|
||||
if (invalidOption) {
|
||||
printHelp(string(argv[0]));
|
||||
return 0;
|
||||
}
|
||||
a += 2;
|
||||
} // while
|
||||
if (!foundArgNode && !foundArgRole) {
|
||||
// no valid args were specified
|
||||
printHelp(string(argv[0]));
|
||||
return 0;
|
||||
}
|
||||
} // else
|
||||
} // if
|
||||
|
||||
// print example's name
|
||||
cout << argv[0] << endl;
|
||||
|
||||
if (!foundArgNode) {
|
||||
// Set the radioNumber via the terminal on startup
|
||||
cout << "Which radio is this? Enter '0' or '1'. Defaults to '0' ";
|
||||
string input;
|
||||
getline(cin, input);
|
||||
radioNumber = input.length() > 0 && (uint8_t)input[0] == 49;
|
||||
}
|
||||
|
||||
// save on transmission time by setting the radio to only transmit the
|
||||
// number of bytes we need to transmit a float
|
||||
radio.setPayloadSize(SIZE); // default value is the maximum 32 bytes
|
||||
|
||||
// Set the PA Level low to try preventing power supply related problems
|
||||
// because these examples are likely run with nodes in close proximity to
|
||||
// each other.
|
||||
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MAX is default.
|
||||
|
||||
// set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radioNumber]); // always uses pipe 0
|
||||
|
||||
// set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[!radioNumber]); // using pipe 1
|
||||
|
||||
// For debugging info
|
||||
// radio.printDetails(); // (smaller) function that prints raw register values
|
||||
// radio.printPrettyDetails(); // (larger) function that prints human readable data
|
||||
|
||||
// ready to execute program now
|
||||
if (!foundArgRole) { // if CLI arg "-r"/"--role" was not specified
|
||||
setRole(); // calls master() or slave() based on user input
|
||||
}
|
||||
else { // if CLI arg "-r"/"--role" was specified
|
||||
role ? master() : slave(); // based on CLI arg option
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* set this node's role from stdin stream.
|
||||
* this only considers the first char as input.
|
||||
*/
|
||||
void setRole() {
|
||||
string input = "";
|
||||
while (!input.length()) {
|
||||
cout << "*** PRESS 'T' to begin transmitting to the other node\n";
|
||||
cout << "*** PRESS 'R' to begin receiving from the other node\n";
|
||||
cout << "*** PRESS 'Q' to exit" << endl;
|
||||
getline(cin, input);
|
||||
if (input.length() >= 1) {
|
||||
if (input[0] == 'T' || input[0] == 't')
|
||||
master();
|
||||
else if (input[0] == 'R' || input[0] == 'r')
|
||||
slave();
|
||||
else if (input[0] == 'Q' || input[0] == 'q')
|
||||
break;
|
||||
else
|
||||
cout << input[0] << " is an invalid input. Please try again." << endl;
|
||||
}
|
||||
input = ""; // stay in the while loop
|
||||
} // while
|
||||
} // setRole()
|
||||
|
||||
|
||||
/**
|
||||
* make this node act as the transmitter
|
||||
*/
|
||||
void master() {
|
||||
radio.stopListening(); // put radio in TX mode
|
||||
|
||||
unsigned int failures = 0; // keep track of failures
|
||||
uint8_t i = 0;
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &startTimer); // start the timer
|
||||
while (i < SIZE) {
|
||||
makePayload(i);
|
||||
if (!radio.writeFast(&buffer, SIZE)) {
|
||||
failures++;
|
||||
radio.reUseTX();
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
|
||||
if (failures >= 100) {
|
||||
// most likely no device is listening for the data stream
|
||||
cout << "Too many failures detected. ";
|
||||
cout << "Aborting at payload " << buffer[0];
|
||||
break;
|
||||
}
|
||||
} // while
|
||||
uint32_t ellapsedTime = getMicros(); // end the timer
|
||||
cout << "Time to transmit data = ";
|
||||
cout << ellapsedTime; // print the timer result
|
||||
cout << " us. " << failures; // print number of retries
|
||||
cout << " failures detected. Leaving TX role." << endl;
|
||||
} // master
|
||||
|
||||
|
||||
/**
|
||||
* make this node act as the receiver
|
||||
*/
|
||||
void slave() {
|
||||
|
||||
counter = 0;
|
||||
radio.startListening(); // put radio in RX mode
|
||||
time_t startTimer = time(nullptr); // start a timer
|
||||
while (time(nullptr) - startTimer < 6) { // use 6 second timeout
|
||||
if (radio.available()) { // is there a payload
|
||||
radio.read(&buffer, SIZE); // fetch payload from FIFO
|
||||
cout << "Received: " << buffer; // print the payload's value
|
||||
cout << " - " << counter << endl; // print the counter
|
||||
counter++; // increment counter
|
||||
startTimer = time(nullptr); // reset timer
|
||||
}
|
||||
}
|
||||
radio.stopListening(); // use TX mode for idle behavior
|
||||
|
||||
cout << "Nothing received in 6 seconds. Leaving RX role." << endl;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make a single payload based on position in stream.
|
||||
* This example employs this function to save on memory allocated.
|
||||
*/
|
||||
void makePayload(uint8_t i) {
|
||||
|
||||
// let the first character be an identifying alphanumeric prefix
|
||||
// this lets us see which payload didn't get received
|
||||
buffer[0] = i + (i < 26 ? 65 : 71);
|
||||
for (uint8_t j = 0; j < SIZE - 1; ++j) {
|
||||
char chr = j >= (SIZE - 1) / 2 + abs((SIZE - 1) / 2 - i);
|
||||
chr |= j < (SIZE - 1) / 2 - abs((SIZE - 1) / 2 - i);
|
||||
buffer[j + 1] = chr + 48;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the ellapsed time in microseconds
|
||||
*/
|
||||
uint32_t getMicros() {
|
||||
// this function assumes that the timer was started using
|
||||
// `clock_gettime(CLOCK_MONOTONIC_RAW, &startTimer);`
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &endTimer);
|
||||
uint32_t seconds = endTimer.tv_sec - startTimer.tv_sec;
|
||||
uint32_t useconds = (endTimer.tv_nsec - startTimer.tv_nsec) / 1000;
|
||||
|
||||
return ((seconds) * 1000 + useconds) + 0.5;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* print a manual page of instructions on how to use this example's CLI args
|
||||
*/
|
||||
void printHelp(string progName) {
|
||||
cout << "usage: " << progName << " [-h] [-n {0,1}] [-r {0,1}]\n\n"
|
||||
<< "A simple example of streaming data from 1 nRF24L01 transceiver to another.\n"
|
||||
<< "\nThis example was written to be used on 2 devices acting as 'nodes'.\n"
|
||||
<< "\noptional arguments:\n -h, --help\t\tshow this help message and exit\n"
|
||||
<< " -n {0,1}, --node {0,1}\n\t\t\tthe identifying radio number\n"
|
||||
<< " -r {0,1}, --role {0,1}\n\t\t\t'1' specifies the TX role."
|
||||
<< " '0' specifies the RX role." << endl;
|
||||
}
|
219
src/libs/RF24-master/examples_linux/streaming_data.py
Normal file
219
src/libs/RF24-master/examples_linux/streaming_data.py
Normal file
@ -0,0 +1,219 @@
|
||||
"""
|
||||
A simple example of streaming data from 1 nRF24L01 transceiver to another.
|
||||
|
||||
This example was written to be used on 2 devices acting as 'nodes'.
|
||||
"""
|
||||
import sys
|
||||
import argparse
|
||||
import time
|
||||
from RF24 import RF24, RF24_PA_LOW
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--node",
|
||||
type=int,
|
||||
choices=range(2),
|
||||
help="the identifying radio number (or node ID number)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--role",
|
||||
type=int,
|
||||
choices=range(2),
|
||||
help="'1' specifies the TX role. '0' specifies the RX role."
|
||||
)
|
||||
|
||||
########### USER CONFIGURATION ###########
|
||||
# See https://github.com/TMRh20/RF24/blob/master/pyRF24/readme.md
|
||||
# Radio CE Pin, CSN Pin, SPI Speed
|
||||
# CE Pin uses GPIO number with BCM and SPIDEV drivers, other platforms use
|
||||
# their own pin numbering
|
||||
# CS Pin addresses the SPI bus number at /dev/spidev<a>.<b>
|
||||
# ie: RF24 radio(<ce_pin>, <a>*10+<b>); spidev1.0 is 10, spidev1.1 is 11 etc..
|
||||
|
||||
# Generic:
|
||||
radio = RF24(22, 0)
|
||||
################## Linux (BBB,x86,etc) #########################
|
||||
# See http://nRF24.github.io/RF24/pages.html for more information on usage
|
||||
# See http://iotdk.intel.com/docs/master/mraa/ for more information on MRAA
|
||||
# See https://www.kernel.org/doc/Documentation/spi/spidev for more
|
||||
# information on SPIDEV
|
||||
|
||||
# Specify the number of bytes in the payload. This is also used to
|
||||
# specify the number of payloads in 1 stream of data
|
||||
SIZE = 32 # this is the default maximum payload size
|
||||
|
||||
|
||||
def make_buffer(buf_iter):
|
||||
"""Returns a dynamically created payloads
|
||||
|
||||
:param int buf_iter: The position of the payload in the data stream
|
||||
"""
|
||||
# we'll use `SIZE` for the number of payloads in the list and the
|
||||
# payloads' length
|
||||
# prefix payload with a sequential letter to indicate which
|
||||
# payloads were lost (if any)
|
||||
buff = bytes([buf_iter + (65 if 0 <= buf_iter < 26 else 71)])
|
||||
for j in range(SIZE - 1):
|
||||
char = bool(j >= (SIZE - 1) / 2 + abs((SIZE - 1) / 2 - buf_iter))
|
||||
char |= bool(j < (SIZE - 1) / 2 - abs((SIZE - 1) / 2 - buf_iter))
|
||||
buff += bytes([char + 48])
|
||||
return buff
|
||||
|
||||
|
||||
def master(count=1):
|
||||
"""Uses all 3 levels of the TX FIFO to send a stream of data
|
||||
|
||||
:param int count: how many times to transmit the stream of data.
|
||||
"""
|
||||
radio.stopListening() # put radio in TX mode
|
||||
radio.flush_tx() # clear the TX FIFO so we can use all 3 levels
|
||||
failures = 0 # keep track of manual retries
|
||||
start_timer = time.monotonic_ns() # start timer
|
||||
for multiplier in range(count): # repeat transmit the same data stream
|
||||
buf_iter = 0 # iterator of payloads for the while loop
|
||||
while buf_iter < SIZE: # cycle through all the payloads
|
||||
buffer = make_buffer(buf_iter) # make a payload
|
||||
|
||||
if not radio.writeFast(buffer): # transmission failed
|
||||
failures += 1 # increment manual retry count
|
||||
if failures > 99 and buf_iter < 7 and multiplier < 2:
|
||||
# we need to prevent an infinite loop
|
||||
print(
|
||||
"Too many failures detected. Aborting at payload ",
|
||||
buffer[0]
|
||||
)
|
||||
multiplier = count # be sure to exit the for loop
|
||||
break # exit the while loop
|
||||
radio.reUseTX() # resend payload in top level of TX FIFO
|
||||
else: # transmission succeeded
|
||||
buf_iter += 1
|
||||
end_timer = time.monotonic_ns() # end timer
|
||||
print(
|
||||
"Time to transmit data = {} us. Detected {} failures.".format(
|
||||
(end_timer - start_timer) / 1000,
|
||||
failures
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def slave(timeout=6):
|
||||
"""Listen for any payloads and print them out (suffixed with received
|
||||
counter)
|
||||
|
||||
:param int timeout: The number of seconds to wait (with no transmission)
|
||||
until exiting function.
|
||||
"""
|
||||
radio.startListening() # put radio in RX mode
|
||||
count = 0 # keep track of the number of received payloads
|
||||
start_timer = time.monotonic() # start timer
|
||||
while (time.monotonic() - start_timer) < timeout:
|
||||
if radio.available():
|
||||
count += 1
|
||||
# retreive the received packet's payload
|
||||
receive_payload = radio.read(radio.payloadSize)
|
||||
print("Received: {} - {}".format(receive_payload, count))
|
||||
start_timer = time.monotonic() # reset timer on every RX payload
|
||||
|
||||
# recommended behavior is to keep in TX mode while idle
|
||||
radio.stopListening() # put the radio in TX mode
|
||||
|
||||
|
||||
def set_role():
|
||||
"""Set the role using stdin stream. Role args can be specified using space
|
||||
delimiters (e.g. 'R 10' calls `slave(10)` & 'T 3' calls `master(3)`)
|
||||
|
||||
:return:
|
||||
- True when role is complete & app should continue running.
|
||||
- False when app should exit
|
||||
"""
|
||||
user_input = input(
|
||||
"*** Enter 'R' for receiver role.\n"
|
||||
"*** Enter 'T' for transmitter role.\n"
|
||||
"*** Enter 'Q' to quit example.\n"
|
||||
) or "?"
|
||||
user_input = user_input.split()
|
||||
if user_input[0].upper().startswith("R"):
|
||||
if len(user_input) > 1:
|
||||
slave(int(user_input[1]))
|
||||
else:
|
||||
slave()
|
||||
return True
|
||||
elif user_input[0].upper().startswith("T"):
|
||||
if len(user_input) > 1:
|
||||
master(int(user_input[1]))
|
||||
else:
|
||||
master()
|
||||
return True
|
||||
elif user_input[0].upper().startswith("Q"):
|
||||
radio.powerDown()
|
||||
return False
|
||||
print(user_input[0], "is an unrecognized input. Please try again.")
|
||||
return set_role()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
args = parser.parse_args() # parse any CLI args
|
||||
|
||||
# initialize the nRF24L01 on the spi bus
|
||||
if not radio.begin():
|
||||
raise RuntimeError("radio hardware is not responding")
|
||||
|
||||
# For this example, we will use different addresses
|
||||
# An address need to be a buffer protocol object (bytearray)
|
||||
address = [b"1Node", b"2Node"]
|
||||
# It is very helpful to think of an address as a path instead of as
|
||||
# an identifying device destination
|
||||
|
||||
print(sys.argv[0]) # print example name
|
||||
|
||||
# to use different addresses on a pair of radios, we need a variable to
|
||||
# uniquely identify which address this radio will use to transmit
|
||||
# 0 uses address[0] to transmit, 1 uses address[1] to transmit
|
||||
radio_number = args.node # uses default value from `parser`
|
||||
if args.node is None: # if '--node' arg wasn't specified
|
||||
radio_number = bool(
|
||||
int(
|
||||
input(
|
||||
"Which radio is this? Enter '0' or '1'. Defaults to '0' "
|
||||
) or 0
|
||||
)
|
||||
)
|
||||
|
||||
# set the Power Amplifier level to -12 dBm since this test example is
|
||||
# usually run with nRF24L01 transceivers in close proximity of each other
|
||||
radio.setPALevel(RF24_PA_LOW) # RF24_PA_MAX is default
|
||||
|
||||
# set the TX address of the RX node into the TX pipe
|
||||
radio.openWritingPipe(address[radio_number]) # always uses pipe 0
|
||||
|
||||
# set the RX address of the TX node into a RX pipe
|
||||
radio.openReadingPipe(1, address[not radio_number]) # using pipe 1
|
||||
|
||||
# To save time during transmission, we'll set the payload size to be only
|
||||
# what we need. For this example, we'll be using the default maximum 32
|
||||
radio.payloadSize = SIZE
|
||||
|
||||
# for debugging, we have 2 options that print a large block of details
|
||||
# (smaller) function that prints raw register values
|
||||
# radio.printDetails()
|
||||
# (larger) function that prints human readable data
|
||||
# radio.printPrettyDetails()
|
||||
|
||||
try:
|
||||
if args.role is None: # if not specified with CLI arg '-r'
|
||||
while set_role():
|
||||
pass # continue example until 'Q' is entered
|
||||
else: # if role was set using CLI args
|
||||
# run role once and exit
|
||||
master() if bool(args.role) else slave()
|
||||
except KeyboardInterrupt:
|
||||
print(" Keyboard Interrupt detected. Exiting...")
|
||||
radio.powerDown()
|
||||
sys.exit()
|
59
src/libs/RF24-master/keywords.txt
Normal file
59
src/libs/RF24-master/keywords.txt
Normal file
@ -0,0 +1,59 @@
|
||||
RF24 KEYWORD1
|
||||
begin KEYWORD2
|
||||
isChipConnected KEYWORD2
|
||||
startListening KEYWORD2
|
||||
stopListening KEYWORD2
|
||||
available KEYWORD2
|
||||
read KEYWORD2
|
||||
write KEYWORD2
|
||||
openWritingPipe KEYWORD2
|
||||
openReadingPipe KEYWORD2
|
||||
printDetails KEYWORD2
|
||||
printPrettyDetails KEYWORD2
|
||||
rxFifoFull KEYWORD2
|
||||
powerDown KEYWORD2
|
||||
powerUp KEYWORD2
|
||||
writeFast KEYWORD2
|
||||
writeBlocking KEYWORD2
|
||||
txStandBy KEYWORD2
|
||||
writeAckPayload KEYWORD2
|
||||
whatHappened KEYWORD2
|
||||
startFastWrite KEYWORD2
|
||||
startWrite KEYWORD2
|
||||
reUseTX KEYWORD2
|
||||
flush_tx KEYWORD2
|
||||
flush_rx KEYWORD2
|
||||
testCarrier KEYWORD2
|
||||
testRPD KEYWORD2
|
||||
isValid KEYWORD2
|
||||
closeReadingPipe KEYWORD2
|
||||
failureDetected KEYWORD2
|
||||
setAddressWidth KEYWORD2
|
||||
setRetries KEYWORD2
|
||||
setChannel KEYWORD2
|
||||
getChannel KEYWORD2
|
||||
setPayloadSize KEYWORD2
|
||||
getPayloadSize KEYWORD2
|
||||
getDynamicPayloadSize KEYWORD2
|
||||
enableAckPayload KEYWORD2
|
||||
disableAckPayload KEYWORD2
|
||||
enableDynamicPayloads KEYWORD2
|
||||
disableDynamicPayloads KEYWORD2
|
||||
isPVariant KEYWORD2
|
||||
setAutoAck KEYWORD2
|
||||
setPALevel KEYWORD2
|
||||
getPALevel KEYWORD2
|
||||
getARC KEYWORD2
|
||||
setDataRate KEYWORD2
|
||||
getDataRate KEYWORD2
|
||||
setCRCLength KEYWORD2
|
||||
getCRCLength KEYWORD2
|
||||
disableCRC KEYWORD2
|
||||
maskIRQ KEYWORD2
|
||||
txDelay KEYWORD2
|
||||
csDelay KEYWORD2
|
||||
startConstCarrier KEYWORD2
|
||||
stopConstCarrier KEYWORD2
|
||||
enableDynamicAck KEYWORD2
|
||||
isAckPayloadAvailable KEYWORD2
|
||||
printf_begin KEYWORD2
|
20
src/libs/RF24-master/library.json
Normal file
20
src/libs/RF24-master/library.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "RF24",
|
||||
"keywords": "rf, radio, wireless, spi",
|
||||
"description": "Radio driver, OSI layer 2 library for nrf24L01(+) modules.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nRF24/RF24.git"
|
||||
},
|
||||
"version": "1.3.11",
|
||||
"frameworks": "arduino",
|
||||
"platforms": [
|
||||
"atmelavr",
|
||||
"atmelsam",
|
||||
"teensy",
|
||||
"atmelmegaavr",
|
||||
"espressif32",
|
||||
"espressif8266",
|
||||
"linux_arm"
|
||||
]
|
||||
}
|
9
src/libs/RF24-master/library.properties
Normal file
9
src/libs/RF24-master/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=RF24
|
||||
version=1.3.11
|
||||
author=TMRh20
|
||||
maintainer=TMRh20,Avamander
|
||||
sentence=Radio driver, OSI layer 2 library for nrf24L01(+) modules.
|
||||
paragraph=Core library for nRF24L01(+) communication. Simple to use for beginners, but offers advanced configuration options. Many examples are included to demonstrate various modes of communication.
|
||||
category=Communication
|
||||
url=https://nRF24.github.io/RF24/
|
||||
architectures=*
|
128
src/libs/RF24-master/nRF24L01.h
Normal file
128
src/libs/RF24-master/nRF24L01.h
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright (c) 2007 Stefan Engelke <mbox@stefanengelke.de>
|
||||
Portions Copyright (C) 2011 Greg Copeland
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Memory Map */
|
||||
#define NRF_CONFIG 0x00
|
||||
#define EN_AA 0x01
|
||||
#define EN_RXADDR 0x02
|
||||
#define SETUP_AW 0x03
|
||||
#define SETUP_RETR 0x04
|
||||
#define RF_CH 0x05
|
||||
#define RF_SETUP 0x06
|
||||
#define NRF_STATUS 0x07
|
||||
#define OBSERVE_TX 0x08
|
||||
#define CD 0x09
|
||||
#define RX_ADDR_P0 0x0A
|
||||
#define RX_ADDR_P1 0x0B
|
||||
#define RX_ADDR_P2 0x0C
|
||||
#define RX_ADDR_P3 0x0D
|
||||
#define RX_ADDR_P4 0x0E
|
||||
#define RX_ADDR_P5 0x0F
|
||||
#define TX_ADDR 0x10
|
||||
#define RX_PW_P0 0x11
|
||||
#define RX_PW_P1 0x12
|
||||
#define RX_PW_P2 0x13
|
||||
#define RX_PW_P3 0x14
|
||||
#define RX_PW_P4 0x15
|
||||
#define RX_PW_P5 0x16
|
||||
#define FIFO_STATUS 0x17
|
||||
#define DYNPD 0x1C
|
||||
#define FEATURE 0x1D
|
||||
|
||||
/* Bit Mnemonics */
|
||||
#define MASK_RX_DR 6
|
||||
#define MASK_TX_DS 5
|
||||
#define MASK_MAX_RT 4
|
||||
#define EN_CRC 3
|
||||
#define CRCO 2
|
||||
#define PWR_UP 1
|
||||
#define PRIM_RX 0
|
||||
#define ENAA_P5 5
|
||||
#define ENAA_P4 4
|
||||
#define ENAA_P3 3
|
||||
#define ENAA_P2 2
|
||||
#define ENAA_P1 1
|
||||
#define ENAA_P0 0
|
||||
#define ERX_P5 5
|
||||
#define ERX_P4 4
|
||||
#define ERX_P3 3
|
||||
#define ERX_P2 2
|
||||
#define ERX_P1 1
|
||||
#define ERX_P0 0
|
||||
#define AW 0
|
||||
#define ARD 4
|
||||
#define ARC 0
|
||||
#define PLL_LOCK 4
|
||||
#define CONT_WAVE 7
|
||||
#define RF_DR 3
|
||||
#define RF_PWR 6
|
||||
#define RX_DR 6
|
||||
#define TX_DS 5
|
||||
#define MAX_RT 4
|
||||
#define RX_P_NO 1
|
||||
#define TX_FULL 0
|
||||
#define PLOS_CNT 4
|
||||
#define ARC_CNT 0
|
||||
#define TX_REUSE 6
|
||||
#define FIFO_FULL 5
|
||||
#define TX_EMPTY 4
|
||||
#define RX_FULL 1
|
||||
#define RX_EMPTY 0
|
||||
#define DPL_P5 5
|
||||
#define DPL_P4 4
|
||||
#define DPL_P3 3
|
||||
#define DPL_P2 2
|
||||
#define DPL_P1 1
|
||||
#define DPL_P0 0
|
||||
#define EN_DPL 2
|
||||
#define EN_ACK_PAY 1
|
||||
#define EN_DYN_ACK 0
|
||||
|
||||
/* Instruction Mnemonics */
|
||||
#define R_REGISTER 0x00
|
||||
#define W_REGISTER 0x20
|
||||
#define REGISTER_MASK 0x1F
|
||||
#define ACTIVATE 0x50
|
||||
#define R_RX_PL_WID 0x60
|
||||
#define R_RX_PAYLOAD 0x61
|
||||
#define W_TX_PAYLOAD 0xA0
|
||||
#define W_ACK_PAYLOAD 0xA8
|
||||
#define FLUSH_TX 0xE1
|
||||
#define FLUSH_RX 0xE2
|
||||
#define REUSE_TX_PL 0xE3
|
||||
#define RF24_NOP 0xFF
|
||||
|
||||
/* Non-P omissions */
|
||||
#define LNA_HCURR 0
|
||||
|
||||
/* P model memory Map */
|
||||
#define RPD 0x09
|
||||
#define W_TX_PAYLOAD_NO_ACK 0xB0
|
||||
|
||||
/* P model bit Mnemonics */
|
||||
#define RF_DR_LOW 5
|
||||
#define RF_DR_HIGH 3
|
||||
#define RF_PWR_LOW 1
|
||||
#define RF_PWR_HIGH 2
|
42
src/libs/RF24-master/printf.h
Normal file
42
src/libs/RF24-master/printf.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
/* Galileo support from spaniakos <spaniakos@gmail.com> */
|
||||
|
||||
/**
|
||||
* @file printf.h
|
||||
*
|
||||
* Setup necessary to direct stdout to the Arduino Serial library, which
|
||||
* enables 'printf'
|
||||
*/
|
||||
|
||||
#ifndef __PRINTF_H__
|
||||
#define __PRINTF_H__
|
||||
|
||||
#if defined(ARDUINO_ARCH_AVR) || defined(__ARDUINO_X86__)
|
||||
|
||||
int serial_putc(char c, FILE *)
|
||||
{
|
||||
Serial.write(c);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
void printf_begin(void)
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_AVR)
|
||||
fdevopen(&serial_putc, 0);
|
||||
|
||||
#elif defined(__ARDUINO_X86__)
|
||||
// JESUS - For reddirect stdout to /dev/ttyGS0 (Serial Monitor port)
|
||||
stdout = freopen("/dev/ttyGS0", "w", stdout);
|
||||
delay(500);
|
||||
printf("Redirecting to Serial...");
|
||||
#endif // defined(__ARDUINO_X86__)
|
||||
}
|
||||
|
||||
#endif // __PRINTF_H__
|
70
src/libs/RF24-master/pyRF24/crossunixccompiler.py
Normal file
70
src/libs/RF24-master/pyRF24/crossunixccompiler.py
Normal file
@ -0,0 +1,70 @@
|
||||
import sys
|
||||
from distutils import unixccompiler
|
||||
from distutils import ccompiler
|
||||
|
||||
|
||||
def register():
|
||||
sys.modules["distutils.crossunixccompiler"] = sys.modules[__name__]
|
||||
ccompiler.compiler_class["crossunix"] = (
|
||||
__name__,
|
||||
"CrossUnixCCompiler",
|
||||
"UNIX-style compiler for cross compilation",
|
||||
)
|
||||
|
||||
|
||||
def try_remove_all(lst, starts):
|
||||
lst[:] = [x for x in lst if not x.startswith(starts)]
|
||||
|
||||
|
||||
class CrossUnixCCompiler(unixccompiler.UnixCCompiler):
|
||||
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
|
||||
try_remove_all(
|
||||
self.compiler_so, ("-m64", "-fstack-protector-strong", "-mtune=generic")
|
||||
)
|
||||
try_remove_all(cc_args, "-I/usr")
|
||||
try_remove_all(pp_opts, "-I/usr")
|
||||
return unixccompiler.UnixCCompiler._compile(
|
||||
self, obj, src, ext, cc_args, extra_postargs, pp_opts
|
||||
)
|
||||
|
||||
def link(
|
||||
self,
|
||||
target_desc,
|
||||
objects,
|
||||
output_filename,
|
||||
output_dir=None,
|
||||
libraries=None,
|
||||
library_dirs=None,
|
||||
runtime_library_dirs=None,
|
||||
export_symbols=None,
|
||||
debug=0,
|
||||
extra_preargs=None,
|
||||
extra_postargs=None,
|
||||
build_temp=None,
|
||||
target_lang=None,
|
||||
):
|
||||
try_remove_all(self.library_dirs, ("/usr"))
|
||||
return unixccompiler.UnixCCompiler.link(
|
||||
self,
|
||||
target_desc,
|
||||
objects,
|
||||
output_filename,
|
||||
output_dir,
|
||||
libraries,
|
||||
library_dirs,
|
||||
runtime_library_dirs,
|
||||
export_symbols,
|
||||
debug,
|
||||
extra_preargs,
|
||||
extra_postargs,
|
||||
build_temp,
|
||||
target_lang,
|
||||
)
|
||||
|
||||
def _fix_lib_args(self, libraries, library_dirs, runtime_library_dirs):
|
||||
self.__class__ = unixccompiler.UnixCCompiler
|
||||
ret = unixccompiler.UnixCCompiler._fix_lib_args(
|
||||
self, libraries, library_dirs, runtime_library_dirs
|
||||
)
|
||||
self.__class__ = CrossUnixCCompiler
|
||||
return ret
|
323
src/libs/RF24-master/pyRF24/pyRF24.cpp
Normal file
323
src/libs/RF24-master/pyRF24/pyRF24.cpp
Normal file
@ -0,0 +1,323 @@
|
||||
#include <RF24/RF24.h>
|
||||
#include <boost/python.hpp>
|
||||
|
||||
namespace bp = boost::python;
|
||||
|
||||
// ******************** explicit wrappers **************************
|
||||
// for methods which need it - mostly for buffer operations
|
||||
//
|
||||
|
||||
void throw_ba_exception(void)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "buf parameter must be bytes or bytearray");
|
||||
bp::throw_error_already_set();
|
||||
}
|
||||
|
||||
char* get_bytes_or_bytearray_str(bp::object buf)
|
||||
{
|
||||
PyObject* py_ba;
|
||||
py_ba = buf.ptr();
|
||||
if (PyByteArray_Check(py_ba)) {
|
||||
return PyByteArray_AsString(py_ba);
|
||||
} else if (PyBytes_Check(py_ba)) {
|
||||
return PyBytes_AsString(py_ba);
|
||||
} else {
|
||||
throw_ba_exception();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int get_bytes_or_bytearray_ln(bp::object buf)
|
||||
{
|
||||
PyObject* py_ba;
|
||||
py_ba = buf.ptr();
|
||||
if (PyByteArray_Check(py_ba)) {
|
||||
return PyByteArray_Size(py_ba);
|
||||
} else if (PyBytes_Check(py_ba)) {
|
||||
return PyBytes_Size(py_ba);
|
||||
} else {
|
||||
throw_ba_exception();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bp::object read_wrap(RF24& ref, int maxlen)
|
||||
{
|
||||
char* buf = new char[maxlen + 1];
|
||||
ref.read(buf, maxlen);
|
||||
bp::object
|
||||
py_ba(bp::handle<>(PyByteArray_FromStringAndSize(buf, maxlen < ref.getPayloadSize() ? maxlen : ref.getPayloadSize())));
|
||||
delete[] buf;
|
||||
return py_ba;
|
||||
}
|
||||
|
||||
bool write_wrap1(RF24& ref, bp::object buf)
|
||||
{
|
||||
return ref.write(get_bytes_or_bytearray_str(buf), get_bytes_or_bytearray_ln(buf));
|
||||
}
|
||||
|
||||
bool write_wrap2(RF24& ref, bp::object buf, const bool multicast)
|
||||
{
|
||||
return ref.write(get_bytes_or_bytearray_str(buf), get_bytes_or_bytearray_ln(buf), multicast);
|
||||
}
|
||||
|
||||
void writeAckPayload_wrap(RF24& ref, uint8_t pipe, bp::object buf)
|
||||
{
|
||||
ref.writeAckPayload(pipe, get_bytes_or_bytearray_str(buf), get_bytes_or_bytearray_ln(buf));
|
||||
|
||||
}
|
||||
|
||||
bool writeFast_wrap1(RF24& ref, bp::object buf)
|
||||
{
|
||||
return ref.writeFast(get_bytes_or_bytearray_str(buf), get_bytes_or_bytearray_ln(buf));
|
||||
}
|
||||
|
||||
bool writeFast_wrap2(RF24& ref, bp::object buf, const bool multicast)
|
||||
{
|
||||
return ref.writeFast(get_bytes_or_bytearray_str(buf), get_bytes_or_bytearray_ln(buf), multicast);
|
||||
}
|
||||
|
||||
bool writeBlocking_wrap(RF24& ref, bp::object buf, uint32_t timeout)
|
||||
{
|
||||
return ref.writeBlocking(get_bytes_or_bytearray_str(buf), get_bytes_or_bytearray_ln(buf), timeout);
|
||||
}
|
||||
|
||||
void startFastWrite_wrap1(RF24& ref, bp::object buf, const bool multicast)
|
||||
{
|
||||
ref.startFastWrite(get_bytes_or_bytearray_str(buf), get_bytes_or_bytearray_ln(buf), multicast);
|
||||
}
|
||||
|
||||
void startFastWrite_wrap2(RF24& ref, bp::object buf, const bool multicast, bool startTx)
|
||||
{
|
||||
ref.startFastWrite(get_bytes_or_bytearray_str(buf), get_bytes_or_bytearray_ln(buf), multicast, startTx);
|
||||
}
|
||||
|
||||
void startWrite_wrap(RF24& ref, bp::object buf, const bool multicast)
|
||||
{
|
||||
ref.startWrite(get_bytes_or_bytearray_str(buf), get_bytes_or_bytearray_ln(buf), multicast);
|
||||
}
|
||||
|
||||
void openWritingPipe_wrap(RF24& ref, const bp::object address)
|
||||
{
|
||||
ref.openWritingPipe((const uint8_t*) (get_bytes_or_bytearray_str(address)));
|
||||
}
|
||||
|
||||
void openReadingPipe_wrap(RF24& ref, uint8_t number, const bp::object address)
|
||||
{
|
||||
ref.openReadingPipe(number, (const uint8_t*) (get_bytes_or_bytearray_str(address)));
|
||||
}
|
||||
|
||||
bp::tuple whatHappened_wrap(RF24& ref)
|
||||
{
|
||||
bool tx_ok;
|
||||
bool tx_fail;
|
||||
bool tx_ready;
|
||||
|
||||
ref.whatHappened(tx_ok, tx_fail, tx_ready);
|
||||
return bp::make_tuple(tx_ok, tx_fail, tx_ready);
|
||||
}
|
||||
|
||||
bp::tuple available_wrap(RF24& ref)
|
||||
{
|
||||
bool result;
|
||||
uint8_t pipe;
|
||||
|
||||
result = ref.available(&pipe);
|
||||
return bp::make_tuple(result, pipe);
|
||||
}
|
||||
|
||||
void setPALevel_wrap(RF24& ref, rf24_pa_dbm_e level) {
|
||||
ref.setPALevel(level, 1);
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(txStandBy_wrap1, RF24::txStandBy,
|
||||
0, 2)
|
||||
//BOOST_PYTHON_FUNCTION_OVERLOADS(txStandBy_wrap2, RF24::txStandBy, 1, 2)
|
||||
|
||||
// ******************** enums **************************
|
||||
// from both RF24 and bcm2835
|
||||
//
|
||||
|
||||
BOOST_PYTHON_MODULE(RF24){
|
||||
|
||||
#ifdef BCM2835_H
|
||||
bp::enum_< RPiGPIOPin>("RPiGPIOPin")
|
||||
.value("RPI_GPIO_P1_03", RPI_GPIO_P1_03)
|
||||
.value("RPI_GPIO_P1_05", RPI_GPIO_P1_05)
|
||||
.value("RPI_GPIO_P1_07", RPI_GPIO_P1_07)
|
||||
.value("RPI_GPIO_P1_08", RPI_GPIO_P1_08)
|
||||
.value("RPI_GPIO_P1_10", RPI_GPIO_P1_10)
|
||||
.value("RPI_GPIO_P1_11", RPI_GPIO_P1_11)
|
||||
.value("RPI_GPIO_P1_12", RPI_GPIO_P1_12)
|
||||
.value("RPI_GPIO_P1_13", RPI_GPIO_P1_13)
|
||||
.value("RPI_GPIO_P1_15", RPI_GPIO_P1_15)
|
||||
.value("RPI_GPIO_P1_16", RPI_GPIO_P1_16)
|
||||
.value("RPI_GPIO_P1_18", RPI_GPIO_P1_18)
|
||||
.value("RPI_GPIO_P1_19", RPI_GPIO_P1_19)
|
||||
.value("RPI_GPIO_P1_21", RPI_GPIO_P1_21)
|
||||
.value("RPI_GPIO_P1_22", RPI_GPIO_P1_22)
|
||||
.value("RPI_GPIO_P1_23", RPI_GPIO_P1_23)
|
||||
.value("RPI_GPIO_P1_24", RPI_GPIO_P1_24)
|
||||
.value("RPI_GPIO_P1_26", RPI_GPIO_P1_26)
|
||||
.value("RPI_V2_GPIO_P1_03", RPI_V2_GPIO_P1_03)
|
||||
.value("RPI_V2_GPIO_P1_05", RPI_V2_GPIO_P1_05)
|
||||
.value("RPI_V2_GPIO_P1_07", RPI_V2_GPIO_P1_07)
|
||||
.value("RPI_V2_GPIO_P1_08", RPI_V2_GPIO_P1_08)
|
||||
.value("RPI_V2_GPIO_P1_10", RPI_V2_GPIO_P1_10)
|
||||
.value("RPI_V2_GPIO_P1_11", RPI_V2_GPIO_P1_11)
|
||||
.value("RPI_V2_GPIO_P1_12", RPI_V2_GPIO_P1_12)
|
||||
.value("RPI_V2_GPIO_P1_13", RPI_V2_GPIO_P1_13)
|
||||
.value("RPI_V2_GPIO_P1_15", RPI_V2_GPIO_P1_15)
|
||||
.value("RPI_V2_GPIO_P1_16", RPI_V2_GPIO_P1_16)
|
||||
.value("RPI_V2_GPIO_P1_18", RPI_V2_GPIO_P1_18)
|
||||
.value("RPI_V2_GPIO_P1_19", RPI_V2_GPIO_P1_19)
|
||||
.value("RPI_V2_GPIO_P1_21", RPI_V2_GPIO_P1_21)
|
||||
.value("RPI_V2_GPIO_P1_22", RPI_V2_GPIO_P1_22)
|
||||
.value("RPI_V2_GPIO_P1_23", RPI_V2_GPIO_P1_23)
|
||||
.value("RPI_V2_GPIO_P1_24", RPI_V2_GPIO_P1_24)
|
||||
.value("RPI_V2_GPIO_P1_26", RPI_V2_GPIO_P1_26)
|
||||
.value("RPI_V2_GPIO_P5_03", RPI_V2_GPIO_P5_03)
|
||||
.value("RPI_V2_GPIO_P5_04", RPI_V2_GPIO_P5_04)
|
||||
.value("RPI_V2_GPIO_P5_05", RPI_V2_GPIO_P5_05)
|
||||
.value("RPI_V2_GPIO_P5_06", RPI_V2_GPIO_P5_06)
|
||||
.value("RPI_BPLUS_GPIO_J8_03", RPI_BPLUS_GPIO_J8_03)
|
||||
.value("RPI_BPLUS_GPIO_J8_05", RPI_BPLUS_GPIO_J8_05)
|
||||
.value("RPI_BPLUS_GPIO_J8_07", RPI_BPLUS_GPIO_J8_07)
|
||||
.value("RPI_BPLUS_GPIO_J8_08", RPI_BPLUS_GPIO_J8_08)
|
||||
.value("RPI_BPLUS_GPIO_J8_10", RPI_BPLUS_GPIO_J8_10)
|
||||
.value("RPI_BPLUS_GPIO_J8_11", RPI_BPLUS_GPIO_J8_11)
|
||||
.value("RPI_BPLUS_GPIO_J8_12", RPI_BPLUS_GPIO_J8_12)
|
||||
.value("RPI_BPLUS_GPIO_J8_13", RPI_BPLUS_GPIO_J8_13)
|
||||
.value("RPI_BPLUS_GPIO_J8_15", RPI_BPLUS_GPIO_J8_15)
|
||||
.value("RPI_BPLUS_GPIO_J8_16", RPI_BPLUS_GPIO_J8_16)
|
||||
.value("RPI_BPLUS_GPIO_J8_18", RPI_BPLUS_GPIO_J8_18)
|
||||
.value("RPI_BPLUS_GPIO_J8_19", RPI_BPLUS_GPIO_J8_19)
|
||||
.value("RPI_BPLUS_GPIO_J8_21", RPI_BPLUS_GPIO_J8_21)
|
||||
.value("RPI_BPLUS_GPIO_J8_22", RPI_BPLUS_GPIO_J8_22)
|
||||
.value("RPI_BPLUS_GPIO_J8_23", RPI_BPLUS_GPIO_J8_23)
|
||||
.value("RPI_BPLUS_GPIO_J8_24", RPI_BPLUS_GPIO_J8_24)
|
||||
.value("RPI_BPLUS_GPIO_J8_26", RPI_BPLUS_GPIO_J8_26)
|
||||
.value("RPI_BPLUS_GPIO_J8_29", RPI_BPLUS_GPIO_J8_29)
|
||||
.value("RPI_BPLUS_GPIO_J8_31", RPI_BPLUS_GPIO_J8_31)
|
||||
.value("RPI_BPLUS_GPIO_J8_32", RPI_BPLUS_GPIO_J8_32)
|
||||
.value("RPI_BPLUS_GPIO_J8_33", RPI_BPLUS_GPIO_J8_33)
|
||||
.value("RPI_BPLUS_GPIO_J8_35", RPI_BPLUS_GPIO_J8_35)
|
||||
.value("RPI_BPLUS_GPIO_J8_36", RPI_BPLUS_GPIO_J8_36)
|
||||
.value("RPI_BPLUS_GPIO_J8_37", RPI_BPLUS_GPIO_J8_37)
|
||||
.value("RPI_BPLUS_GPIO_J8_38", RPI_BPLUS_GPIO_J8_38)
|
||||
.value("RPI_BPLUS_GPIO_J8_40", RPI_BPLUS_GPIO_J8_40)
|
||||
.export_values()
|
||||
;
|
||||
|
||||
bp::enum_< bcm2835SPIClockDivider>("bcm2835SPIClockDivider")
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_65536", BCM2835_SPI_CLOCK_DIVIDER_65536)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_32768", BCM2835_SPI_CLOCK_DIVIDER_32768)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_16384", BCM2835_SPI_CLOCK_DIVIDER_16384)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_8192", BCM2835_SPI_CLOCK_DIVIDER_8192)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_4096", BCM2835_SPI_CLOCK_DIVIDER_4096)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_2048", BCM2835_SPI_CLOCK_DIVIDER_2048)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_1024", BCM2835_SPI_CLOCK_DIVIDER_1024)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_512", BCM2835_SPI_CLOCK_DIVIDER_512)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_256", BCM2835_SPI_CLOCK_DIVIDER_256)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_128", BCM2835_SPI_CLOCK_DIVIDER_128)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_64", BCM2835_SPI_CLOCK_DIVIDER_64)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_32", BCM2835_SPI_CLOCK_DIVIDER_32)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_16", BCM2835_SPI_CLOCK_DIVIDER_16)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_8", BCM2835_SPI_CLOCK_DIVIDER_8)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_4", BCM2835_SPI_CLOCK_DIVIDER_4)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_2", BCM2835_SPI_CLOCK_DIVIDER_2)
|
||||
.value("BCM2835_SPI_CLOCK_DIVIDER_1", BCM2835_SPI_CLOCK_DIVIDER_1)
|
||||
.export_values();
|
||||
|
||||
|
||||
bp::enum_< bcm2835SPIChipSelect>("bcm2835SPIChipSelect")
|
||||
.value("BCM2835_SPI_CS0", BCM2835_SPI_CS0)
|
||||
.value("BCM2835_SPI_CS1", BCM2835_SPI_CS1)
|
||||
.value("BCM2835_SPI_CS2", BCM2835_SPI_CS2)
|
||||
.value("BCM2835_SPI_CS_NONE", BCM2835_SPI_CS_NONE)
|
||||
.export_values();
|
||||
|
||||
#endif // BCM2835_H
|
||||
|
||||
bp::enum_<rf24_crclength_e>("rf24_crclength_e").value("RF24_CRC_DISABLED", RF24_CRC_DISABLED).value("RF24_CRC_8", RF24_CRC_8).value(
|
||||
"RF24_CRC_16", RF24_CRC_16).export_values()
|
||||
;
|
||||
|
||||
bp::enum_<rf24_datarate_e>("rf24_datarate_e")
|
||||
.value("RF24_1MBPS", RF24_1MBPS)
|
||||
.value("RF24_2MBPS", RF24_2MBPS)
|
||||
.value("RF24_250KBPS", RF24_250KBPS)
|
||||
.export_values();
|
||||
|
||||
bp::enum_<rf24_pa_dbm_e>("rf24_pa_dbm_e")
|
||||
.value("RF24_PA_MIN", RF24_PA_MIN)
|
||||
.value("RF24_PA_LOW", RF24_PA_LOW)
|
||||
.value("RF24_PA_HIGH", RF24_PA_HIGH)
|
||||
.value("RF24_PA_MAX", RF24_PA_MAX)
|
||||
.value("RF24_PA_ERROR", RF24_PA_ERROR)
|
||||
.export_values();
|
||||
|
||||
// ******************** RF24 class **************************
|
||||
//
|
||||
bp::class_< RF24 >("RF24", bp::init< uint8_t, uint8_t >((bp::arg("_cepin"), bp::arg("_cspin"))))
|
||||
#if defined (RF24_LINUX) && !defined (MRAA)
|
||||
.def(bp::init< uint8_t, uint8_t, uint32_t >((bp::arg("_cepin"), bp::arg("_cspin"), bp::arg("spispeed"))))
|
||||
#endif
|
||||
.def("available", (bool (::RF24::*)())(&::RF24::available))
|
||||
.def("available_pipe", &available_wrap) // needed to rename this method as python does not allow such overloading
|
||||
.def("begin", &RF24::begin)
|
||||
.def("closeReadingPipe", &RF24::closeReadingPipe)
|
||||
.def("disableCRC", &RF24::disableCRC)
|
||||
.def("enableAckPayload", &RF24::enableAckPayload)
|
||||
.def("enableDynamicAck", &RF24::enableDynamicAck)
|
||||
.def("enableDynamicPayloads", &RF24::enableDynamicPayloads)
|
||||
.def("disableDynamicPayloads", &RF24::disableDynamicPayloads)
|
||||
.def("flush_tx", &RF24::flush_tx)
|
||||
.def("flush_rx", &RF24::flush_rx)
|
||||
.def("getCRCLength", &RF24::getCRCLength)
|
||||
.def("getDataRate", &RF24::getDataRate)
|
||||
.def("getDynamicPayloadSize", &RF24::getDynamicPayloadSize)
|
||||
.def("getPALevel", &RF24::getPALevel)
|
||||
.def("isAckPayloadAvailable", &RF24::isAckPayloadAvailable)
|
||||
.def("isPVariant", &RF24::isPVariant)
|
||||
.def("isValid", &RF24::isValid)
|
||||
.def("maskIRQ", &RF24::maskIRQ, (bp::arg("tx_ok"), bp::arg("tx_fail"), bp::arg("rx_ready")))
|
||||
.def("openReadingPipe", &openReadingPipe_wrap, (bp::arg("number"), bp::arg("address")))
|
||||
.def("openReadingPipe", (void (::RF24::*)(::uint8_t,::uint64_t))(&::RF24::openReadingPipe), (bp::arg("number"), bp::arg("address")))
|
||||
.def("openWritingPipe", &openWritingPipe_wrap, (bp::arg("address")))
|
||||
.def("openWritingPipe", (void (::RF24::*)(::uint64_t))(&::RF24::openWritingPipe), (bp::arg("address")))
|
||||
.def("powerDown", &RF24::powerDown)
|
||||
.def("powerUp", &RF24::powerUp)
|
||||
.def("printDetails", &RF24::printDetails)
|
||||
.def("printPrettyDetails", &RF24::printPrettyDetails)
|
||||
.def("reUseTX", &RF24::reUseTX)
|
||||
.def("read", &read_wrap, (bp::arg("maxlen")))
|
||||
.def("rxFifoFull", &RF24::rxFifoFull)
|
||||
.def("setAddressWidth", &RF24::setAddressWidth)
|
||||
.def("setAutoAck", (void (::RF24::*)(bool))(&::RF24::setAutoAck), (bp::arg("enable")))
|
||||
.def("setAutoAck", (void (::RF24::*)(::uint8_t, bool))(&::RF24::setAutoAck), (bp::arg("pipe"), bp::arg("enable")))
|
||||
.def("setCRCLength", &RF24::setCRCLength, (bp::arg("length")))
|
||||
.def("setDataRate", &RF24::setDataRate, (bp::arg("speed")))
|
||||
.def("setPALevel", &RF24::setPALevel, (bp::arg("level"), bp::arg("lnaEnable")=1))
|
||||
.def("setPALevel", &setPALevel_wrap, (bp::arg("level")))
|
||||
.def("setRetries", &RF24::setRetries, (bp::arg("delay"), bp::arg("count")))
|
||||
.def("startFastWrite", &startFastWrite_wrap1, (bp::arg("buf"), bp::arg("len"), bp::arg("multicast")))
|
||||
.def("startFastWrite", &startFastWrite_wrap2, (bp::arg("buf"), bp::arg("len"), bp::arg("multicast"), bp::arg("startTx")))
|
||||
.def("startListening", &RF24::startListening)
|
||||
.def("startWrite", &startWrite_wrap, (bp::arg("buf"), bp::arg("len"), bp::arg("multicast")))
|
||||
.def("stopListening", &RF24::stopListening)
|
||||
.def("testCarrier", &RF24::testCarrier)
|
||||
.def("testRPD", &RF24::testRPD)
|
||||
.def("txStandBy", (bool (::RF24::*)(::uint32_t, bool))(&RF24::txStandBy), txStandBy_wrap1(bp::args("timeout", "startTx")))
|
||||
.def("whatHappened", &whatHappened_wrap)
|
||||
.def("startConstCarrier", &RF24::startConstCarrier, (bp::arg("level"), bp::arg("channel")))
|
||||
.def("stopConstCarrier",&RF24::stopConstCarrier)
|
||||
.def("write", &write_wrap1, (bp::arg("buf")))
|
||||
.def("write", &write_wrap2, (bp::arg("buf"), bp::arg("multicast")))
|
||||
.def("writeAckPayload", writeAckPayload_wrap, (bp::arg("pipe"), bp::arg("buf")))
|
||||
.def("writeBlocking", &writeBlocking_wrap, (bp::arg("buf"), bp::arg("timeout")))
|
||||
.def("writeFast", &writeFast_wrap1, (bp::arg("buf")))
|
||||
.def("writeFast", &writeFast_wrap2, (bp::arg("buf"), bp::arg("multicast")))
|
||||
.add_property("channel", &RF24::getChannel, &RF24::setChannel)
|
||||
.add_property("payloadSize", &RF24::getPayloadSize, &RF24::setPayloadSize)
|
||||
.def_readwrite("failureDetected", &RF24::failureDetected);}
|
21
src/libs/RF24-master/pyRF24/pyRF24Mesh/example_master.py
Normal file
21
src/libs/RF24-master/pyRF24/pyRF24Mesh/example_master.py
Normal file
@ -0,0 +1,21 @@
|
||||
from RF24 import *
|
||||
from RF24Network import *
|
||||
from RF24Mesh import *
|
||||
|
||||
# radio setup for RPi B Rev2: CS0=Pin 24
|
||||
radio = RF24(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ)
|
||||
network = RF24Network(radio)
|
||||
mesh = RF24Mesh(radio, network)
|
||||
|
||||
mesh.setNodeID(0)
|
||||
mesh.begin(108, RF24_250KBPS)
|
||||
radio.setPALevel(RF24_PA_MAX) # Power Amplifier
|
||||
radio.printDetails()
|
||||
|
||||
while 1:
|
||||
mesh.update()
|
||||
mesh.DHCP()
|
||||
|
||||
while network.available():
|
||||
print("Received message")
|
||||
header, payload = network.read(10)
|
107
src/libs/RF24-master/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp
Normal file
107
src/libs/RF24-master/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
#include "boost/python.hpp"
|
||||
#include "RF24/RF24.h"
|
||||
#include "RF24Network/RF24Network.h"
|
||||
#include "RF24Mesh/RF24Mesh.h"
|
||||
|
||||
namespace bp = boost::python;
|
||||
|
||||
|
||||
// ******************** explicit wrappers **************************
|
||||
// where needed, especially where buffer is involved
|
||||
|
||||
void throw_ba_exception(void)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "buf parameter must be bytes or bytearray");
|
||||
bp::throw_error_already_set();
|
||||
}
|
||||
|
||||
char* get_bytes_or_bytearray_str(bp::object buf)
|
||||
{
|
||||
PyObject* py_ba;
|
||||
py_ba = buf.ptr();
|
||||
if (PyByteArray_Check(py_ba)) {
|
||||
return PyByteArray_AsString(py_ba);
|
||||
} else if (PyBytes_Check(py_ba)) {
|
||||
return PyBytes_AsString(py_ba);
|
||||
} else {
|
||||
throw_ba_exception();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int get_bytes_or_bytearray_ln(bp::object buf)
|
||||
{
|
||||
PyObject* py_ba;
|
||||
py_ba = buf.ptr();
|
||||
if (PyByteArray_Check(py_ba)) {
|
||||
return PyByteArray_Size(py_ba);
|
||||
} else if (PyBytes_Check(py_ba)) {
|
||||
return PyBytes_Size(py_ba);
|
||||
} else {
|
||||
throw_ba_exception();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool write_wrap1(RF24Mesh& ref, bp::object buf, uint8_t msg_type)
|
||||
{
|
||||
return ref.write(get_bytes_or_bytearray_str(buf), msg_type, get_bytes_or_bytearray_ln(buf));
|
||||
}
|
||||
|
||||
bool write_wrap2(RF24Mesh& ref, bp::object buf, uint8_t msg_type, uint8_t nodeID)
|
||||
{
|
||||
return ref.write(get_bytes_or_bytearray_str(buf), msg_type, get_bytes_or_bytearray_ln(buf), nodeID);
|
||||
}
|
||||
|
||||
bool write_to_node_wrap(RF24Mesh& ref, uint16_t to_node, bp::object buf, uint8_t msg_type)
|
||||
{
|
||||
return ref.write(to_node, get_bytes_or_bytearray_str(buf), msg_type, get_bytes_or_bytearray_ln(buf));
|
||||
}
|
||||
|
||||
// ******************** overload wrappers **************************
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(begin_overload, RF24Mesh::begin,
|
||||
0, 3)
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(getNodeID_overload, RF24Mesh::getNodeID,
|
||||
0, 1)
|
||||
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(renewAddress_overload, RF24Mesh::renewAddress,
|
||||
0, 1)
|
||||
|
||||
// ******************** RF24Mesh exposed **************************
|
||||
BOOST_PYTHON_MODULE(RF24Mesh)
|
||||
{{ //::RF24Mesh
|
||||
bp::class_<RF24Mesh>("RF24Mesh", bp::init<RF24&, RF24Network&>((bp::arg("_radio"), bp::arg("_network"))))
|
||||
//bool begin(uint8_t channel = MESH_DEFAULT_CHANNEL, rf24_datarate_e data_rate = RF24_1MBPS, uint32_t timeout=MESH_RENEWAL_TIMEOUT );
|
||||
.def("begin", &RF24Mesh::begin, begin_overload(bp::args("channel", "data_rate", "timeout")))
|
||||
//uint8_t update();
|
||||
.def("update", &RF24Mesh::update)
|
||||
//bool write(const void* data, uint8_t msg_type, size_t size, uint8_t nodeID=0);
|
||||
.def("write", &write_wrap1, (bp::arg("data"), bp::arg("msg_type"))).def("write", &write_wrap2,
|
||||
(bp::arg("data"), bp::arg("msg_type"), bp::arg("nodeID")))
|
||||
//bool write(uint16_t to_node, const void* data, uint8_t msg_type, size_t size );
|
||||
.def("write", &write_to_node_wrap, (bp::arg("to_node"), bp::arg("data"), bp::arg("msg_type"), bp::arg("size")))
|
||||
//void setNodeID(uint8_t nodeID);
|
||||
.def("setNodeID", &RF24Mesh::setNodeID, (bp::arg("nodeID")))
|
||||
//void DHCP();
|
||||
.def("DHCP", &RF24Mesh::DHCP)
|
||||
//int16_t getNodeID(uint16_t address=MESH_BLANK_ID);
|
||||
.def("getNodeID", &RF24Mesh::getNodeID, getNodeID_overload(bp::args("address")))
|
||||
//bool checkConnection();
|
||||
.def("checkConnection", &RF24Mesh::checkConnection)
|
||||
//uint16_t renewAddress(uint32_t timeout=MESH_RENEWAL_TIMEOUT);
|
||||
.def("renewAddress", &RF24Mesh::renewAddress, getNodeID_overload(bp::args("timeout")))
|
||||
//bool releaseAddress();
|
||||
.def("releaseAddress", &RF24Mesh::releaseAddress)
|
||||
//int16_t getAddress(uint8_t nodeID);
|
||||
.def("getAddress", &RF24Mesh::getAddress, (bp::arg("nodeID")))
|
||||
//void setChannel(uint8_t _channel);
|
||||
.def("setChannel", &RF24Mesh::setChannel, (bp::arg("_channel")))
|
||||
//void setChild(bool allow);
|
||||
.def("setChild", &RF24Mesh::setChild, (bp::arg("allow")))
|
||||
//void setAddress(uint8_t nodeID, uint16_t address);
|
||||
.def("setAddress", &RF24Mesh::setAddress, (bp::arg("nodeID"), bp::arg("address")))
|
||||
//void saveDHCP();
|
||||
.def("saveDHCP", &RF24Mesh::saveDHCP)
|
||||
//void loadDHCP();
|
||||
.def("loadDHCP", &RF24Mesh::loadDHCP)
|
||||
//void setStaticAddress(uint8_t nodeID, uint16_t address);
|
||||
.def("setStaticAddress", &RF24Mesh::setStaticAddress, (bp::arg("nodeID"), bp::arg("address")));}}
|
17
src/libs/RF24-master/pyRF24/pyRF24Mesh/setup.py
Normal file
17
src/libs/RF24-master/pyRF24/pyRF24Mesh/setup.py
Normal file
@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from distutils.core import setup, Extension
|
||||
import sys
|
||||
|
||||
if sys.version_info >= (3,):
|
||||
BOOST_LIB = "boost_python3"
|
||||
else:
|
||||
BOOST_LIB = "boost_python"
|
||||
|
||||
module_RF24Mesh = Extension(
|
||||
"RF24Mesh",
|
||||
libraries=["rf24mesh", "rf24network", BOOST_LIB],
|
||||
sources=["pyRF24Mesh.cpp"],
|
||||
)
|
||||
|
||||
setup(name="RF24Mesh", version="1.0", ext_modules=[module_RF24Mesh])
|
@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#
|
||||
# Simplest possible example of using RF24Network,
|
||||
#
|
||||
# RECEIVER NODE
|
||||
# Listens for messages from the transmitter and prints them out.
|
||||
#
|
||||
from __future__ import print_function
|
||||
import time
|
||||
from struct import *
|
||||
from RF24 import *
|
||||
from RF24Network import *
|
||||
|
||||
# CE Pin, CSN Pin, SPI Speed
|
||||
|
||||
# Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz
|
||||
# radio = radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_18, BCM2835_SPI_SPEED_1MHZ)
|
||||
|
||||
# Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
|
||||
# radio = RF24(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ)
|
||||
|
||||
# Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 8Mhz
|
||||
# radio = RF24(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ)
|
||||
|
||||
# Setup for GPIO 22 CE and CE0 CSN for RPi B+ with SPI Speed @ 8Mhz
|
||||
# radio = RF24(RPI_BPLUS_GPIO_J8_22, RPI_BPLUS_GPIO_J8_24, BCM2835_SPI_SPEED_8MHZ)
|
||||
|
||||
radio = RF24(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ)
|
||||
network = RF24Network(radio)
|
||||
|
||||
millis = lambda: int(round(time.time() * 1000))
|
||||
octlit = lambda n: int(n, 8)
|
||||
|
||||
# Address of our node in Octal format (01, 021, etc)
|
||||
this_node = octlit("00")
|
||||
|
||||
# Address of the other node
|
||||
other_node = octlit("01")
|
||||
|
||||
radio.begin()
|
||||
time.sleep(0.1)
|
||||
network.begin(90, this_node) # channel 90
|
||||
radio.printDetails()
|
||||
packets_sent = 0
|
||||
last_sent = 0
|
||||
|
||||
while 1:
|
||||
network.update()
|
||||
while network.available():
|
||||
header, payload = network.read(8)
|
||||
print("payload length ", len(payload))
|
||||
ms, number = unpack('<LL', bytes(payload))
|
||||
print('Received payload ', number, ' at ', ms, ' from ', oct(header.from_node))
|
||||
time.sleep(1)
|
@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#
|
||||
# Simplest possible example of using RF24Network,
|
||||
#
|
||||
# TRANSMITTER NODE
|
||||
# Sends messages from to receiver.
|
||||
#
|
||||
from __future__ import print_function
|
||||
import time
|
||||
from struct import *
|
||||
from RF24 import *
|
||||
from RF24Network import *
|
||||
|
||||
# CE Pin, CSN Pin, SPI Speed
|
||||
|
||||
# Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz
|
||||
# radio = radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_18, BCM2835_SPI_SPEED_1MHZ)
|
||||
|
||||
# Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
|
||||
# radio = RF24(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ)
|
||||
|
||||
# Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 8Mhz
|
||||
# radio = RF24(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ)
|
||||
|
||||
# Setup for GPIO 22 CE and CE0 CSN for RPi B+ with SPI Speed @ 8Mhz
|
||||
# radio = RF24(RPI_BPLUS_GPIO_J8_22, RPI_BPLUS_GPIO_J8_24, BCM2835_SPI_SPEED_8MHZ)
|
||||
|
||||
radio = RF24(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ)
|
||||
network = RF24Network(radio)
|
||||
|
||||
millis = lambda: int(round(time.time() * 1000)) & 0xffffffff
|
||||
octlit = lambda n: int(n, 8)
|
||||
|
||||
# Address of our node in Octal format (01,021, etc)
|
||||
this_node = octlit("01")
|
||||
|
||||
# Address of the other node
|
||||
other_node = octlit("00")
|
||||
|
||||
# ms - How long to wait before sending the next message
|
||||
interval = 2000
|
||||
|
||||
radio.begin()
|
||||
time.sleep(0.1);
|
||||
network.begin(90, this_node) # channel 90
|
||||
radio.printDetails()
|
||||
packets_sent = 0
|
||||
last_sent = 0
|
||||
|
||||
while 1:
|
||||
network.update()
|
||||
now = millis()
|
||||
# If it's time to send a message, send it!
|
||||
if (now - last_sent >= interval):
|
||||
last_sent = now
|
||||
print('Sending ..')
|
||||
payload = pack('<LL', millis(), packets_sent)
|
||||
packets_sent += 1
|
||||
ok = network.write(RF24NetworkHeader(other_node), payload)
|
||||
if ok:
|
||||
print('ok.')
|
||||
else:
|
||||
print('failed.')
|
133
src/libs/RF24-master/pyRF24/pyRF24Network/pyRF24Network.cpp
Normal file
133
src/libs/RF24-master/pyRF24/pyRF24Network/pyRF24Network.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
#include "boost/python.hpp"
|
||||
#include "RF24/RF24.h"
|
||||
#include "RF24Network/RF24Network.h"
|
||||
|
||||
namespace bp = boost::python;
|
||||
|
||||
// **************** expicit wrappers *****************
|
||||
// where needed, especially where buffer is involved
|
||||
//
|
||||
void throw_ba_exception(void)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "buf parameter must be bytes or bytearray");
|
||||
bp::throw_error_already_set();
|
||||
}
|
||||
|
||||
char* get_bytes_or_bytearray_str(bp::object buf)
|
||||
{
|
||||
PyObject* py_ba;
|
||||
py_ba = buf.ptr();
|
||||
if (PyByteArray_Check(py_ba)) {
|
||||
return PyByteArray_AsString(py_ba);
|
||||
} else if (PyBytes_Check(py_ba)) {
|
||||
return PyBytes_AsString(py_ba);
|
||||
} else {
|
||||
throw_ba_exception();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int get_bytes_or_bytearray_ln(bp::object buf)
|
||||
{
|
||||
PyObject* py_ba;
|
||||
py_ba = buf.ptr();
|
||||
if (PyByteArray_Check(py_ba)) {
|
||||
return PyByteArray_Size(py_ba);
|
||||
} else if (PyBytes_Check(py_ba)) {
|
||||
return PyBytes_Size(py_ba);
|
||||
} else {
|
||||
throw_ba_exception();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bp::tuple read_wrap(RF24Network& ref, size_t maxlen)
|
||||
{
|
||||
char* buf = new char[maxlen + 1];
|
||||
RF24NetworkHeader header;
|
||||
|
||||
uint16_t len = ref.read(header, buf, maxlen);
|
||||
bp::object
|
||||
py_ba(bp::handle<>(PyByteArray_FromStringAndSize(buf, len)));
|
||||
delete[] buf;
|
||||
|
||||
return bp::make_tuple(header, py_ba);
|
||||
}
|
||||
|
||||
bool write_wrap(RF24Network& ref, RF24NetworkHeader& header, bp::object buf)
|
||||
{
|
||||
return ref.write(header, get_bytes_or_bytearray_str(buf), get_bytes_or_bytearray_ln(buf));
|
||||
}
|
||||
|
||||
std::string toString_wrap(RF24NetworkHeader& ref)
|
||||
{
|
||||
return std::string(ref.toString());
|
||||
}
|
||||
|
||||
// **************** RF24Network exposed *****************
|
||||
//
|
||||
BOOST_PYTHON_MODULE(RF24Network){{ //::RF24Network
|
||||
typedef bp::class_< RF24Network > RF24Network_exposer_t;
|
||||
RF24Network_exposer_t RF24Network_exposer = RF24Network_exposer_t( "RF24Network", bp::init< RF24 & >(( bp::arg("_radio"))));
|
||||
bp::scope RF24Network_scope( RF24Network_exposer );
|
||||
bp::implicitly_convertible< RF24 &, RF24Network >();
|
||||
{ //::RF24Network::available
|
||||
|
||||
typedef bool ( ::RF24Network::*available_function_type )();
|
||||
|
||||
RF24Network_exposer.def("available", available_function_type(&::RF24Network::available));
|
||||
|
||||
}
|
||||
{ //::RF24Network::begin
|
||||
|
||||
typedef void ( ::RF24Network::*begin_function_type )(::uint8_t, ::uint16_t);
|
||||
|
||||
RF24Network_exposer.def("begin", begin_function_type(&::RF24Network::begin),
|
||||
(bp::arg("_channel"), bp::arg("_node_address")));
|
||||
|
||||
}
|
||||
{ //::RF24Network::parent
|
||||
|
||||
typedef ::uint16_t ( ::RF24Network::*parent_function_type )() const;
|
||||
|
||||
RF24Network_exposer.def("parent", parent_function_type(&::RF24Network::parent));
|
||||
|
||||
}
|
||||
{ //::RF24Network::read
|
||||
|
||||
typedef bp::tuple ( * read_function_type )(::RF24Network&, size_t);
|
||||
|
||||
RF24Network_exposer.def("read"
|
||||
//, read_function_type( &::RF24Network::read )
|
||||
, read_function_type(&read_wrap), (bp::arg("maxlen")));
|
||||
|
||||
}
|
||||
{ //::RF24Network::update
|
||||
|
||||
typedef void ( ::RF24Network::*update_function_type )();
|
||||
|
||||
RF24Network_exposer.def("update", update_function_type(&::RF24Network::update));
|
||||
|
||||
}
|
||||
{ //::RF24Network::write
|
||||
|
||||
typedef bool ( * write_function_type )(::RF24Network&, ::RF24NetworkHeader&, bp::object);
|
||||
|
||||
RF24Network_exposer.def("write", write_function_type(&write_wrap),
|
||||
(bp::arg("header"), bp::arg("buf")));
|
||||
|
||||
}
|
||||
RF24Network_exposer.def_readwrite( "txTimeout", &RF24Network::txTimeout );}
|
||||
|
||||
// **************** RF24NetworkHeader exposed *****************
|
||||
//
|
||||
bp::class_< RF24NetworkHeader >( "RF24NetworkHeader", bp::init< >())
|
||||
.def( bp::init< uint16_t, bp::optional< unsigned char > >(( bp::arg("_to"), bp::arg("_type")=(unsigned char)(0))))
|
||||
.def("toString", &toString_wrap )
|
||||
.def_readwrite( "from_node", &RF24NetworkHeader::from_node )
|
||||
.def_readwrite( "id", &RF24NetworkHeader::id )
|
||||
.def_readwrite( "next_id", RF24NetworkHeader::next_id )
|
||||
.def_readwrite( "reserved", &RF24NetworkHeader::reserved )
|
||||
.def_readwrite( "to_node", &RF24NetworkHeader::to_node )
|
||||
.def_readwrite( "type", &RF24NetworkHeader::type );}
|
||||
|
15
src/libs/RF24-master/pyRF24/pyRF24Network/setup.py
Normal file
15
src/libs/RF24-master/pyRF24/pyRF24Network/setup.py
Normal file
@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from distutils.core import setup, Extension
|
||||
import sys
|
||||
|
||||
if sys.version_info >= (3,):
|
||||
BOOST_LIB = "boost_python3"
|
||||
else:
|
||||
BOOST_LIB = "boost_python"
|
||||
|
||||
module_RF24Network = Extension(
|
||||
"RF24Network", libraries=["rf24network", BOOST_LIB], sources=["pyRF24Network.cpp"]
|
||||
)
|
||||
|
||||
setup(name="RF24Network", version="1.0", ext_modules=[module_RF24Network])
|
2
src/libs/RF24-master/pyRF24/readme.md
Normal file
2
src/libs/RF24-master/pyRF24/readme.md
Normal file
@ -0,0 +1,2 @@
|
||||
Python Wrapper for RF24
|
||||
See http://nRF24.github.io/RF24 for more information
|
56
src/libs/RF24-master/pyRF24/setup.py
Normal file
56
src/libs/RF24-master/pyRF24/setup.py
Normal file
@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
import setuptools
|
||||
import crossunixccompiler
|
||||
|
||||
version = ""
|
||||
|
||||
|
||||
def process_configparams():
|
||||
version = "" # using python keyword `global` is bad practice
|
||||
|
||||
# NOTE current repo directory structure requires the use of
|
||||
# `python3 setup.py build` and `python3 setup.py install`
|
||||
# where `pip3 install ./pyRF24` copies pyRF24 directory to
|
||||
# `tmp` folder that doesn't have the needed `../Makefile.inc`
|
||||
# NOTE can't access "../Makefile.inc" from working dir because
|
||||
# it's relative. Brute force absolute path dynamically.
|
||||
script_dir = os.path.split(os.path.abspath(os.getcwd()))[0]
|
||||
abs_file_path = os.path.join(script_dir, "Makefile.inc")
|
||||
with open(abs_file_path) as f:
|
||||
config_lines = f.read().splitlines()
|
||||
|
||||
cflags = os.getenv("CFLAGS", "")
|
||||
for line in config_lines:
|
||||
identifier, value = line.split('=', 1)
|
||||
if identifier == "CPUFLAGS":
|
||||
cflags += " " + value
|
||||
elif identifier == "HEADER_DIR":
|
||||
cflags += " -I" + os.path.dirname(value)
|
||||
elif identifier == "LIB_DIR":
|
||||
cflags += " -L" + value
|
||||
elif identifier == "LIB_VERSION":
|
||||
version = value
|
||||
elif identifier in ("CC", "CXX"):
|
||||
os.environ[identifier] = value
|
||||
|
||||
os.environ["CFLAGS"] = cflags
|
||||
return version
|
||||
|
||||
if sys.version_info >= (3,):
|
||||
BOOST_LIB = "boost_python3"
|
||||
else:
|
||||
BOOST_LIB = "boost_python"
|
||||
|
||||
version = process_configparams()
|
||||
crossunixccompiler.register()
|
||||
|
||||
module_RF24 = setuptools.Extension("RF24",
|
||||
libraries=["rf24", BOOST_LIB],
|
||||
sources=["pyRF24.cpp"])
|
||||
|
||||
setuptools.setup(name="RF24",
|
||||
version=version,
|
||||
ext_modules=[module_RF24])
|
7
src/libs/RF24-master/tests/README
Normal file
7
src/libs/RF24-master/tests/README
Normal file
@ -0,0 +1,7 @@
|
||||
The sketches in this directory are intended to be checkin tests.
|
||||
No code should be pushed to github without these tests passing.
|
||||
|
||||
See "runtests.sh" script inside each sketch dir. This script is fully compatible with
|
||||
git bisest.
|
||||
|
||||
Note that this requires python and py-serial
|
300
src/libs/RF24-master/tests/native/Jamfile
Normal file
300
src/libs/RF24-master/tests/native/Jamfile
Normal file
@ -0,0 +1,300 @@
|
||||
PROJECT_NAME = $(PWD:B) ;
|
||||
PROJECT_DIR = . ;
|
||||
PROJECT_LIBS = RF24 ;
|
||||
|
||||
OUT_DIR = ojam ;
|
||||
F_CPU = 16000000 ;
|
||||
MCU = atmega328p ;
|
||||
PORTS = /dev/tty.usbserial-A600eHIs /dev/tty.usbserial-A40081RP /dev/tty.usbserial-A9007LmI ;
|
||||
|
||||
UPLOAD_RATE = 57600 ;
|
||||
AVRDUDE_PROTOCOL = stk500v1 ;
|
||||
COM = 33 ;
|
||||
|
||||
# Host-specific overrides for locations
|
||||
if $(OS) = MACOSX
|
||||
{
|
||||
ARDUINO_VERSION = 22 ;
|
||||
OLD_DIR = /opt/arduino-0021 ;
|
||||
AVR_TOOLS_PATH = $(OLD_DIR)/hardware/tools/avr/bin ;
|
||||
AVRDUDECONFIG_PATH = $(OLD_DIR)/hardware/tools/avr/etc ;
|
||||
ARDUINO_DIR = /opt/Arduino ;
|
||||
ARDUINO_AVR = /usr/lib/avr/include ;
|
||||
}
|
||||
|
||||
# Where is everything?
|
||||
ARDUINO_VERSION ?= 22 ;
|
||||
SKETCH_DIR = $(HOME)/Source/Arduino ;
|
||||
AVR_TOOLS_PATH ?= /usr/bin ;
|
||||
ARDUINO_DIR ?= /opt/arduino-00$(ARDUINO_VERSION) ;
|
||||
ARDUINO_AVR ?= $(ARDUINO_DIR)/hardware/tools/avr/avr/include/avr ;
|
||||
AVRDUDECONFIG_PATH ?= $(ARDUINO_DIR)/hardware/tools ;
|
||||
ARDUINO_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/arduino ;
|
||||
ARDUINO_LIB = $(ARDUINO_DIR)/libraries ;
|
||||
SKETCH_LIB = $(SKETCH_DIR)/libraries ;
|
||||
AVR_AS = $(AVR_TOOLS_PATH)/avr-as ;
|
||||
AVR_CC = $(AVR_TOOLS_PATH)/avr-gcc ;
|
||||
AVR_CXX = $(AVR_TOOLS_PATH)/avr-g++ ;
|
||||
AVR_LD = $(AVR_TOOLS_PATH)/avr-gcc ;
|
||||
AVR_OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy ;
|
||||
AVRDUDE = $(AVR_TOOLS_PATH)/avrdude ;
|
||||
|
||||
DEFINES = F_CPU=$(F_CPU)L ARDUINO=$(ARDUINO_VERSION) VERSION_H HAL=1 ;
|
||||
CTUNING = -ffunction-sections -fdata-sections ;
|
||||
CXXTUNING = -fno-exceptions -fno-strict-aliasing ;
|
||||
ASFLAGS = -mmcu=$(MCU) ;
|
||||
CFLAGS = -Os -Wall -Wextra $(ASFLAGS) $(CTUNING) ;
|
||||
CXXFLAGS = $(CFLAGS) $(CXXTUNING) ;
|
||||
LDFLAGS = -Os -lm -Wl,--gc-sections -mmcu=atmega328p ;
|
||||
|
||||
# Search everywhere for headers
|
||||
HDRS = $(PROJECT_DIR) $(ARDUINO_AVR) $(ARDUINO_CORE) [ GLOB $(ARDUINO_LIB) $(SKETCH_LIB) : [^.]* ] ;
|
||||
HDRS += [ GLOB $(HDRS) : utility ] ;
|
||||
|
||||
# Grab everything from the core directory
|
||||
CORE_MODULES = [ GLOB $(ARDUINO_CORE) : *.c *.cpp ] ;
|
||||
|
||||
# Grab everything from libraries. To avoid this "grab everything" behaviour, you
|
||||
# can specify specific modules to pick up in PROJECT_MODULES
|
||||
LIB_MODULES = [ GLOB $(ARDUINO_LIB)/$(PROJECT_LIBS) $(ARDUINO_LIB)/$(PROJECT_LIBS)/utility $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp *.c ] ;
|
||||
|
||||
# In addition to explicitly-specified program modules, pick up anything from the current
|
||||
# dir.
|
||||
PROJECT_MODULES += [ GLOB $(PROJECT_DIR) : *.c *.cpp *.pde ] ;
|
||||
|
||||
# Shortcut for the out files
|
||||
OUT = $(OUT_DIR)/$(PROJECT_NAME) ;
|
||||
|
||||
# AvrDude setup
|
||||
AVRDUDE_FLAGS = -V -F -D -C $(AVRDUDECONFIG_PATH)/avrdude.conf -p $(MCU) -c $(AVRDUDE_PROTOCOL) -b $(UPLOAD_RATE) ;
|
||||
|
||||
rule GitVersion
|
||||
{
|
||||
Always $(<) ;
|
||||
Depends all : $(<) ;
|
||||
}
|
||||
|
||||
actions GitVersion
|
||||
{
|
||||
echo "const char program_version[] = \"\\" > $(<)
|
||||
git log -1 --pretty=format:%h >> $(<)
|
||||
echo "\";" >> $(<)
|
||||
}
|
||||
|
||||
# GitVersion version.h ;
|
||||
|
||||
rule AvrAsm
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
Depends $(<) : $(<:D) ;
|
||||
Clean clean : $(<) ;
|
||||
|
||||
CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
|
||||
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
|
||||
}
|
||||
|
||||
actions AvrAsm
|
||||
{
|
||||
$(AVR_AS) $(ASFLAGS) -o $(<) $(>)
|
||||
}
|
||||
|
||||
rule AvrCc
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
Depends $(<) : $(<:D) ;
|
||||
Clean clean : $(<) ;
|
||||
|
||||
CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
|
||||
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
|
||||
}
|
||||
|
||||
actions AvrCc
|
||||
{
|
||||
$(AVR_CC) -c -o $(<) $(CCHDRS) $(CCDEFS) $(CFLAGS) $(>)
|
||||
}
|
||||
|
||||
rule AvrC++
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
Depends $(<) : $(<:D) ;
|
||||
Clean clean : $(<) ;
|
||||
|
||||
CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
|
||||
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
|
||||
}
|
||||
|
||||
actions AvrC++
|
||||
{
|
||||
$(AVR_CXX) -c -o $(<) $(CCHDRS) $(CCDEFS) $(CXXFLAGS) $(>)
|
||||
}
|
||||
|
||||
rule AvrAsmFromC++
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
Depends $(<) : $(<:D) ;
|
||||
Clean clean : $(<) ;
|
||||
|
||||
CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
|
||||
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
|
||||
}
|
||||
|
||||
actions AvrAsmFromC++
|
||||
{
|
||||
$(AVR_CXX) -S -fverbose-asm -o $(<) $(CCHDRS) $(CCDEFS) $(CXXFLAGS) $(>)
|
||||
}
|
||||
|
||||
rule Pde
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
Depends $(<) : $(<:D) ;
|
||||
Clean clean : $(<) ;
|
||||
}
|
||||
|
||||
actions Pde
|
||||
{
|
||||
echo "#include <WProgram.h>" > $(<)
|
||||
echo "#line 1 \"$(>)\"" >> $(<)
|
||||
cat $(>) >> $(<)
|
||||
}
|
||||
|
||||
rule AvrPde
|
||||
{
|
||||
local _CPP = $(OUT_DIR)/$(_I:B).cpp ;
|
||||
Pde $(_CPP) : $(>) ;
|
||||
AvrC++ $(<) : $(_CPP) ;
|
||||
}
|
||||
|
||||
rule AvrObject
|
||||
{
|
||||
switch $(>:S)
|
||||
{
|
||||
case .S : AvrAsm $(<) : $(>) ;
|
||||
case .c : AvrCc $(<) : $(>) ;
|
||||
case .cpp : AvrC++ $(<) : $(>) ;
|
||||
case .pde : AvrPde $(<) : $(>) ;
|
||||
}
|
||||
}
|
||||
|
||||
rule AvrObjects
|
||||
{
|
||||
for _I in $(<)
|
||||
{
|
||||
AvrObject $(OUT_DIR)/$(_I:B).o : $(_I) ;
|
||||
}
|
||||
}
|
||||
|
||||
rule AvrMainFromObjects
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
Depends $(<) : $(<:D) ;
|
||||
MkDir $(<:D) ;
|
||||
Depends all : $(<) ;
|
||||
Clean clean : $(<) ;
|
||||
}
|
||||
|
||||
actions AvrMainFromObjects
|
||||
{
|
||||
$(AVR_LD) $(LDFLAGS) -o $(<) $(>)
|
||||
}
|
||||
|
||||
rule AvrMain
|
||||
{
|
||||
AvrMainFromObjects $(<) : $(OUT_DIR)/$(>:B).o ;
|
||||
AvrObjects $(>) ;
|
||||
}
|
||||
|
||||
rule AvrHex
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
Depends $(<) : $(<:D) ;
|
||||
Depends hex : $(<) ;
|
||||
Clean clean : $(<) ;
|
||||
}
|
||||
|
||||
actions AvrHex
|
||||
{
|
||||
$(AVR_OBJCOPY) -O ihex -R .eeprom $(>) $(<)
|
||||
}
|
||||
|
||||
rule AvrUpload
|
||||
{
|
||||
Depends $(1) : $(2) ;
|
||||
Depends $(2) : $(3) ;
|
||||
NotFile $(1) ;
|
||||
Always $(1) ;
|
||||
Always $(2) ;
|
||||
AvrUploadAction $(2) : $(3) ;
|
||||
}
|
||||
|
||||
actions AvrUploadAction
|
||||
{
|
||||
$(AVRDUDE) $(AVRDUDE_FLAGS) -P $(<) $(AVRDUDE_WRITE_FLASH) -U flash:w:$(>):i
|
||||
}
|
||||
|
||||
AvrMain $(OUT).elf : $(CORE_MODULES) $(LIB_MODULES) $(PROJECT_MODULES)
|
||||
AvrHex $(OUT).hex : $(OUT).elf ;
|
||||
|
||||
AvrUpload p6 : /dev/tty.usbserial-A600eHIs : $(OUT).hex ;
|
||||
AvrUpload p4 : /dev/tty.usbserial-A40081RP : $(OUT).hex ;
|
||||
AvrUpload p9 : /dev/tty.usbserial-A9007LmI : $(OUT).hex ;
|
||||
|
||||
#
|
||||
# Native
|
||||
#
|
||||
|
||||
OUT_DIR_NATIVE = out_native ;
|
||||
OUT_NATIVE = $(OUT_DIR_NATIVE)/$(PROJECT_NAME) ;
|
||||
NATIVE_CORE = $(SKETCH_DIR)/hardware/native ;
|
||||
HDRS = $(NATIVE_CORE) $(HDRS) ;
|
||||
NATIVE_CORE_MODULES = [ GLOB $(NATIVE_CORE) : *.c *.cpp ] ;
|
||||
NATIVE_MODULES = ;
|
||||
DEFINES += NATIVE ;
|
||||
|
||||
rule NativePde
|
||||
{
|
||||
local _CPP = $(OUT_DIR_NATIVE)/$(_I:B).cpp ;
|
||||
Pde $(_CPP) : $(>) ;
|
||||
C++ $(<) : $(_CPP) ;
|
||||
}
|
||||
|
||||
rule UserObject
|
||||
{
|
||||
switch $(>)
|
||||
{
|
||||
case *.pde : NativePde $(<) : $(>) ;
|
||||
}
|
||||
}
|
||||
|
||||
rule Objects
|
||||
{
|
||||
for _I in $(<)
|
||||
{
|
||||
local _O = $(OUT_DIR_NATIVE)/$(_I:B).o ;
|
||||
Object $(_O) : $(_I) ;
|
||||
}
|
||||
}
|
||||
|
||||
rule Main
|
||||
{
|
||||
MainFromObjects $(<) : $(OUT_DIR_NATIVE)/$(>:B).o ;
|
||||
Objects $(>) ;
|
||||
}
|
||||
|
||||
actions C++
|
||||
{
|
||||
c++ -c -o $(<) $(CCHDRS) $(CCDEFS) $(>)
|
||||
}
|
||||
|
||||
actions Link
|
||||
{
|
||||
c++ -o $(<) $(>)
|
||||
}
|
||||
|
||||
|
||||
|
||||
MkDir $(OUT_DIR_NATIVE) ;
|
||||
Depends $(OUT_NATIVE) : $(OUT_DIR_NATIVE) ;
|
||||
Main $(OUT_NATIVE) : $(NATIVE_CORE_MODULES) $(NATIVE_MODULES) $(LIB_MODULES) $(PROJECT_MODULES) ;
|
||||
|
||||
Depends native : $(OUT_NATIVE) ;
|
||||
|
223
src/libs/RF24-master/tests/native/pingpair_irq.pde
Normal file
223
src/libs/RF24-master/tests/native/pingpair_irq.pde
Normal file
@ -0,0 +1,223 @@
|
||||
/*
|
||||
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interrupt-driven test for native target
|
||||
*
|
||||
* This example is the friendliest for the native target because it doesn't do
|
||||
* any polling. Made a slight change to call done() at the end of setup.
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include "nRF24L01.h"
|
||||
#include "RF24.h"
|
||||
#include "printf.h"
|
||||
|
||||
//
|
||||
// Hardware configuration
|
||||
//
|
||||
|
||||
// Set up nRF24L01 radio on SPI bus plus pins 8 & 9
|
||||
|
||||
RF24 radio(8, 9);
|
||||
|
||||
// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver
|
||||
// Leave open to be the 'ping' transmitter
|
||||
const short role_pin = 7;
|
||||
|
||||
//
|
||||
// Topology
|
||||
//
|
||||
|
||||
// Single radio pipe address for the 2 nodes to communicate.
|
||||
const uint64_t pipe = 0xE8E8F0F0E1LL;
|
||||
|
||||
//
|
||||
// Role management
|
||||
//
|
||||
// Set up role. This sketch uses the same software for all the nodes in this
|
||||
// system. Doing so greatly simplifies testing. The hardware itself specifies
|
||||
// which node it is.
|
||||
//
|
||||
// This is done through the role_pin
|
||||
//
|
||||
|
||||
// The various roles supported by this sketch
|
||||
typedef enum{
|
||||
role_sender = 1,
|
||||
role_receiver
|
||||
} role_e;
|
||||
|
||||
// The debug-friendly names of those roles
|
||||
const char* role_friendly_name[] = {"invalid", "Sender", "Receiver"};
|
||||
|
||||
// The role of the current running sketch
|
||||
role_e role;
|
||||
|
||||
// Interrupt handler, check the radio because we got an IRQ
|
||||
void check_radio(void);
|
||||
|
||||
void setup(void){
|
||||
//
|
||||
// Role
|
||||
//
|
||||
|
||||
// set up the role pin
|
||||
pinMode(role_pin, INPUT);
|
||||
digitalWrite(role_pin, HIGH);
|
||||
delay(20); // Just to get a solid reading on the role pin
|
||||
|
||||
// read the address pin, establish our role
|
||||
if (digitalRead(role_pin)){
|
||||
role = role_sender;
|
||||
} else {
|
||||
role = role_receiver;
|
||||
}
|
||||
|
||||
//
|
||||
// Print preamble
|
||||
//
|
||||
|
||||
Serial.begin(115200);
|
||||
printf_begin();
|
||||
printf("\n\rRF24/examples/pingpair_irq/\n\r");
|
||||
printf("ROLE: %s\n\r", role_friendly_name[role]);
|
||||
|
||||
//
|
||||
// Setup and configure rf radio
|
||||
//
|
||||
|
||||
radio.begin();
|
||||
|
||||
// We will be using the Ack Payload feature, so please enable it
|
||||
radio.enableAckPayload();
|
||||
radio.enableDynamicPayloads(); // needed for using ACK payloads
|
||||
|
||||
//
|
||||
// Open pipes to other nodes for communication
|
||||
//
|
||||
|
||||
// This simple sketch opens a single pipe for these two nodes to communicate
|
||||
// back and forth. One listens on it, the other talks to it.
|
||||
|
||||
if (role == role_sender) {
|
||||
radio.openWritingPipe(pipe);
|
||||
} else {
|
||||
radio.openReadingPipe(1, pipe);
|
||||
}
|
||||
|
||||
//
|
||||
// Start listening
|
||||
//
|
||||
|
||||
if (role == role_receiver)
|
||||
radio.startListening();
|
||||
|
||||
//
|
||||
// Dump the configuration of the rf unit for debugging
|
||||
//
|
||||
|
||||
radio.printDetails();
|
||||
|
||||
//
|
||||
// Attach interrupt handler to interrupt #0 (using pin 2)
|
||||
// on BOTH the sender and receiver
|
||||
//
|
||||
|
||||
attachInterrupt(0, check_radio, FALLING);
|
||||
|
||||
//
|
||||
// On the native target, this is as far as we get
|
||||
//
|
||||
#if NATIVE
|
||||
done();
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t message_count = 0;
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
//
|
||||
// Sender role. Repeatedly send the current time
|
||||
//
|
||||
|
||||
if (role == role_sender){
|
||||
// Take the time, and send it.
|
||||
unsigned long time = millis();
|
||||
printf("Now sending %lu\n\r", time);
|
||||
radio.startWrite(&time, sizeof(unsigned long));
|
||||
|
||||
// Try again soon
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
//
|
||||
// Receiver role: Does nothing! All the work is in IRQ
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
void check_radio(void)
|
||||
{
|
||||
// What happened?
|
||||
bool tx, fail, rx;
|
||||
radio.whatHappened(tx, fail, rx);
|
||||
|
||||
// Have we successfully transmitted?
|
||||
if (tx){
|
||||
if (role == role_sender){
|
||||
printf("Send:OK\n\r");
|
||||
}
|
||||
|
||||
if (role == role_receiver){
|
||||
printf("Ack Payload:Sent\n\r");
|
||||
}
|
||||
}
|
||||
|
||||
// Have we failed to transmit?
|
||||
if (fail){
|
||||
if (role == role_sender){
|
||||
printf("Send:Failed\n\r");
|
||||
}
|
||||
|
||||
if (role == role_receiver){
|
||||
printf("Ack Payload:Failed\n\r");
|
||||
}
|
||||
}
|
||||
|
||||
// Transmitter can power down for now, because
|
||||
// the transmission is done.
|
||||
if ((tx || fail) && (role == role_sender)){
|
||||
radio.powerDown();
|
||||
}
|
||||
|
||||
// Did we receive a message?
|
||||
if (rx){
|
||||
// If we're the sender, we've received an ack payload
|
||||
if (role == role_sender){
|
||||
radio.read(&message_count, sizeof(message_count));
|
||||
printf("Ack:%lu\n\r", (unsigned long) message_count);
|
||||
}
|
||||
|
||||
// If we're the receiver, we've received a time message
|
||||
if (role == role_receiver){
|
||||
// Get this payload and dump it
|
||||
static unsigned long got_time;
|
||||
radio.read(&got_time, sizeof(got_time));
|
||||
printf("Got payload %lu\n\r", got_time);
|
||||
|
||||
// Add an ack packet for the next time around. This is a simple
|
||||
// packet counter
|
||||
radio.writeAckPayload(1, &message_count, sizeof(message_count));
|
||||
++message_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ai:cin:sts=2 sw=2 ft=cpp
|
33
src/libs/RF24-master/tests/native/printf.h
Normal file
33
src/libs/RF24-master/tests/native/printf.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file printf.h
|
||||
*
|
||||
* Setup necessary to direct stdout to the Arduino Serial library, which
|
||||
* enables 'printf'
|
||||
*/
|
||||
|
||||
#ifndef __PRINTF_H__
|
||||
#define __PRINTF_H__
|
||||
|
||||
#include "WProgram.h"
|
||||
|
||||
int serial_putc(char c, FILE*)
|
||||
{
|
||||
Serial.write(c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void printf_begin(void)
|
||||
{
|
||||
fdevopen(&serial_putc, 0);
|
||||
}
|
||||
|
||||
#endif // __PRINTF_H__
|
219
src/libs/RF24-master/tests/pingpair_blocking/Jamfile
Normal file
219
src/libs/RF24-master/tests/pingpair_blocking/Jamfile
Normal file
@ -0,0 +1,219 @@
|
||||
# (1) Project Information
|
||||
|
||||
PROJECT_LIBS = SPI RF24 ;
|
||||
PROJECT_DIRS = $(PWD) ;
|
||||
|
||||
# (2) Board Information
|
||||
|
||||
UPLOAD_PROTOCOL ?= arduino ;
|
||||
UPLOAD_SPEED ?= 115200 ;
|
||||
MCU ?= atmega328p ;
|
||||
F_CPU ?= 16000000 ;
|
||||
CORE ?= arduino ;
|
||||
VARIANT ?= standard ;
|
||||
ARDUINO_VERSION ?= 100 ;
|
||||
|
||||
# (3) USB Ports
|
||||
|
||||
PORTS = p4 p6 p9 u0 u1 u2 ;
|
||||
PORT_p6 = /dev/tty.usbserial-A600eHIs ;
|
||||
PORT_p4 = /dev/tty.usbserial-A40081RP ;
|
||||
PORT_p9 = /dev/tty.usbserial-A9007LmI ;
|
||||
PORT_u0 = /dev/ttyUSB0 ;
|
||||
PORT_u1 = /dev/ttyUSB1 ;
|
||||
PORT_u2 = /dev/ttyUSB2 ;
|
||||
|
||||
# (4) Location of AVR tools
|
||||
#
|
||||
# This configuration assumes using avr-tools that were obtained separate from the Arduino
|
||||
# distribution.
|
||||
|
||||
if $(OS) = MACOSX
|
||||
{
|
||||
AVR_BIN ?= /usr/local/avrtools/bin ;
|
||||
AVR_ETC = /usr/local/avrtools/etc ;
|
||||
AVR_INCLUDE = /usr/local/avrtools/include ;
|
||||
}
|
||||
else
|
||||
{
|
||||
AVR_BIN ?= /usr/bin ;
|
||||
AVR_INCLUDE = /usr/lib/avr/include ;
|
||||
AVR_ETC = /etc ;
|
||||
}
|
||||
|
||||
# (5) Directories where Arduino core and libraries are located
|
||||
|
||||
ARDUINO_DIR ?= /opt/Arduino ;
|
||||
ARDUINO_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/$(CORE) $(ARDUINO_DIR)/hardware/arduino/variants/$(VARIANT) ;
|
||||
ARDUINO_LIB = $(ARDUINO_DIR)/libraries ;
|
||||
SKETCH_LIB = $(HOME)/Source/Arduino/libraries ;
|
||||
|
||||
#
|
||||
# --------------------------------------------------
|
||||
# Below this line usually never needs to be modified
|
||||
#
|
||||
|
||||
# Tool locations
|
||||
|
||||
CC = $(AVR_BIN)/avr-gcc ;
|
||||
C++ = $(AVR_BIN)/avr-g++ ;
|
||||
LINK = $(AVR_BIN)/avr-gcc ;
|
||||
AR = $(AVR_BIN)/avr-ar rcs ;
|
||||
RANLIB = ;
|
||||
OBJCOPY = $(AVR_BIN)/avr-objcopy ;
|
||||
AVRDUDE ?= $(AVR_BIN)/avrdude ;
|
||||
|
||||
# Flags
|
||||
|
||||
DEFINES += F_CPU=$(F_CPU)L ARDUINO=$(ARDUINO_VERSION) VERSION_H ;
|
||||
OPTIM = -Os ;
|
||||
CCFLAGS = -Wall -Wextra -Wno-strict-aliasing -mmcu=$(MCU) -ffunction-sections -fdata-sections ;
|
||||
C++FLAGS = $(CCFLAGS) -fno-exceptions -fno-strict-aliasing ;
|
||||
LINKFLAGS = $(OPTIM) -lm -Wl,--gc-sections -mmcu=$(MCU) ;
|
||||
AVRDUDEFLAGS = -V -F -D -C $(AVR_ETC)/avrdude.conf -p $(MCU) -c $(UPLOAD_PROTOCOL) -b $(UPLOAD_SPEED) ;
|
||||
|
||||
# Search everywhere for headers
|
||||
|
||||
HDRS = $(PROJECT_DIRS) $(AVR_INCLUDE) $(ARDUINO_CORE) $(ARDUINO_LIB)/$(PROJECT_LIBS) $(ARDUINO_LIB)/$(PROJECT_LIBS)/utility $(SKETCH_LIB)/$(PROJECT_LIBS) ;
|
||||
|
||||
# Output locations
|
||||
|
||||
LOCATE_TARGET = $(F_CPU) ;
|
||||
LOCATE_SOURCE = $(F_CPU) ;
|
||||
|
||||
#
|
||||
# Custom rules
|
||||
#
|
||||
|
||||
rule GitVersion
|
||||
{
|
||||
Always $(<) ;
|
||||
Depends all : $(<) ;
|
||||
}
|
||||
|
||||
actions GitVersion
|
||||
{
|
||||
echo "const char program_version[] = \"\\" > $(<)
|
||||
git log -1 --pretty=format:%h >> $(<)
|
||||
echo "\";" >> $(<)
|
||||
}
|
||||
|
||||
GitVersion version.h ;
|
||||
|
||||
rule Pde
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
MakeLocate $(<) : $(LOCATE_SOURCE) ;
|
||||
Clean clean : $(<) ;
|
||||
}
|
||||
|
||||
if ( $(ARDUINO_VERSION) < 100 )
|
||||
{
|
||||
ARDUINO_H = WProgram.h ;
|
||||
}
|
||||
else
|
||||
{
|
||||
ARDUINO_H = Arduino.h ;
|
||||
}
|
||||
|
||||
actions Pde
|
||||
{
|
||||
echo "#include <$(ARDUINO_H)>" > $(<)
|
||||
echo "#line 1 \"$(>)\"" >> $(<)
|
||||
cat $(>) >> $(<)
|
||||
}
|
||||
|
||||
rule C++Pde
|
||||
{
|
||||
local _CPP = $(>:B).cpp ;
|
||||
Pde $(_CPP) : $(>) ;
|
||||
C++ $(<) : $(_CPP) ;
|
||||
}
|
||||
|
||||
rule UserObject
|
||||
{
|
||||
switch $(>:S)
|
||||
{
|
||||
case .ino : C++Pde $(<) : $(>) ;
|
||||
case .pde : C++Pde $(<) : $(>) ;
|
||||
}
|
||||
}
|
||||
|
||||
rule Objects
|
||||
{
|
||||
local _i ;
|
||||
|
||||
for _i in [ FGristFiles $(<) ]
|
||||
{
|
||||
local _b = $(_i:B)$(SUFOBJ) ;
|
||||
local _o = $(_b:G=$(SOURCE_GRIST:E)) ;
|
||||
Object $(_o) : $(_i) ;
|
||||
Depends obj : $(_o) ;
|
||||
}
|
||||
}
|
||||
|
||||
rule Library
|
||||
{
|
||||
LibraryFromObjects $(<) : $(>:B)$(SUFOBJ) ;
|
||||
Objects $(>) ;
|
||||
}
|
||||
|
||||
rule Main
|
||||
{
|
||||
MainFromObjects $(<) : $(>:B)$(SUFOBJ) ;
|
||||
Objects $(>) ;
|
||||
}
|
||||
|
||||
rule Hex
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
MakeLocate $(<) : $(LOCATE_TARGET) ;
|
||||
Depends hex : $(<) ;
|
||||
Clean clean : $(<) ;
|
||||
}
|
||||
|
||||
actions Hex
|
||||
{
|
||||
$(OBJCOPY) -O ihex -R .eeprom $(>) $(<)
|
||||
}
|
||||
|
||||
rule Upload
|
||||
{
|
||||
Depends $(1) : $(2) ;
|
||||
Depends $(2) : $(3) ;
|
||||
NotFile $(1) ;
|
||||
Always $(1) ;
|
||||
Always $(2) ;
|
||||
UploadAction $(2) : $(3) ;
|
||||
}
|
||||
|
||||
actions UploadAction
|
||||
{
|
||||
$(AVRDUDE) $(AVRDUDEFLAGS) -P $(<) $(AVRDUDE_WRITE_FLASH) -U flash:w:$(>):i
|
||||
}
|
||||
|
||||
rule Arduino
|
||||
{
|
||||
LINKFLAGS on $(<) = $(LINKFLAGS) -Wl,-Map=$(LOCATE_TARGET)/$(<:B).map ;
|
||||
Main $(<) : $(>) ;
|
||||
LinkLibraries $(<) : core libs ;
|
||||
Hex $(<:B).hex : $(<) ;
|
||||
for _p in $(PORTS)
|
||||
{
|
||||
Upload $(_p) : $(PORT_$(_p)) : $(<:B).hex ;
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Targets
|
||||
#
|
||||
|
||||
# Grab everything from the core directory
|
||||
Library core : [ GLOB $(ARDUINO_CORE) : *.c *.cpp ] ;
|
||||
|
||||
# Grab everything from libraries. To avoid this "grab everything" behaviour, you
|
||||
# can specify specific modules to pick up in PROJECT_MODULES
|
||||
Library libs : [ GLOB $(ARDUINO_LIB)/$(PROJECT_LIBS) $(ARDUINO_LIB)/$(PROJECT_LIBS)/utility $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp *.c ] ;
|
||||
|
||||
# Main output executable
|
||||
Arduino $(PWD:B).elf : $(PROJECT_MODULES) [ GLOB $(PROJECT_DIRS) : *.c *.cpp *.pde *.ino ] ;
|
@ -0,0 +1,272 @@
|
||||
/*
|
||||
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include "nRF24L01.h"
|
||||
#include "RF24.h"
|
||||
#include "printf.h"
|
||||
|
||||
//
|
||||
// Test version of RF24, exposes some protected interface
|
||||
//
|
||||
|
||||
class RF24Test : public RF24 {
|
||||
public:
|
||||
RF24Test(int a, int b)
|
||||
:RF24(a, b)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Hardware configuration
|
||||
//
|
||||
|
||||
// Set up nRF24L01 radio on SPI bus plus pins 8 & 9
|
||||
|
||||
RF24Test radio(48, 49);
|
||||
|
||||
// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver
|
||||
// Leave open to be the 'ping' transmitter
|
||||
const int role_pin = 5;
|
||||
|
||||
//
|
||||
// Topology
|
||||
//
|
||||
|
||||
// Radio pipe addresses for the 2 nodes to communicate.
|
||||
const uint64_t pipes[2] = {0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL};
|
||||
|
||||
//
|
||||
// Role management
|
||||
//
|
||||
// Set up role. This sketch uses the same software for all the nodes
|
||||
// in this system. Doing so greatly simplifies testing. The hardware itself specifies
|
||||
// which node it is.
|
||||
//
|
||||
// This is done through the role_pin
|
||||
//
|
||||
|
||||
// The various roles supported by this sketch
|
||||
typedef enum {
|
||||
role_ping_out = 1,
|
||||
role_pong_back
|
||||
} role_e;
|
||||
|
||||
// The debug-friendly names of those roles
|
||||
const char* role_friendly_name[] = {"invalid", "Ping out", "Pong back"};
|
||||
|
||||
// The role of the current running sketch
|
||||
role_e role;
|
||||
|
||||
//
|
||||
// Test state
|
||||
//
|
||||
|
||||
bool done; //*< Are we done with the test? */
|
||||
bool passed; //*< Have we passed the test? */
|
||||
bool notified; //*< Have we notified the user we're done? */
|
||||
const int num_needed = 10; //*< How many success/failures until we're done? */
|
||||
int receives_remaining = num_needed; //*< How many ack packets until we declare victory? */
|
||||
int failures_remaining = num_needed; //*< How many more failed sends until we declare failure? */
|
||||
const int interval = 100; //*< ms to wait between sends */
|
||||
|
||||
char configuration = '1'; //*< Configuration key, one char sent in by the test framework to tell us how to configure, this is the default */
|
||||
|
||||
void one_ok(void)
|
||||
{
|
||||
// Have we received enough yet?
|
||||
if (!--receives_remaining) {
|
||||
done = true;
|
||||
passed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void one_failed(void)
|
||||
{
|
||||
// Have we failed enough yet?
|
||||
if (!--failures_remaining) {
|
||||
done = true;
|
||||
passed = false;
|
||||
}
|
||||
}
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
//
|
||||
// Role
|
||||
//
|
||||
|
||||
// set up the role pin
|
||||
pinMode(role_pin, INPUT);
|
||||
digitalWrite(role_pin, HIGH);
|
||||
delay(20); // Just to get a solid reading on the role pin
|
||||
|
||||
// read the address pin, establish our role
|
||||
if (digitalRead(role_pin)) {
|
||||
role = role_ping_out;
|
||||
} else {
|
||||
role = role_pong_back;
|
||||
}
|
||||
|
||||
//
|
||||
// Print preamble
|
||||
//
|
||||
|
||||
Serial.begin(115200);
|
||||
printf_begin();
|
||||
printf("\n\rRF24/tests/pingpair_blocking/\n\r");
|
||||
printf("ROLE: %s\n\r", role_friendly_name[role]);
|
||||
|
||||
//
|
||||
// get test config
|
||||
//
|
||||
|
||||
printf("+READY press any key to start\n\r\n\r");
|
||||
|
||||
while (!Serial.available()) {
|
||||
}
|
||||
configuration = Serial.read();
|
||||
printf("Configuration\t = %c\n\r", configuration);
|
||||
|
||||
//
|
||||
// Setup and configure rf radio
|
||||
//
|
||||
|
||||
radio.begin();
|
||||
|
||||
//
|
||||
// Open pipes to other nodes for communication
|
||||
//
|
||||
|
||||
// This simple sketch opens two pipes for these two nodes to communicate
|
||||
// back and forth.
|
||||
// Open 'our' pipe for writing
|
||||
// Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading)
|
||||
|
||||
if (role == role_ping_out) {
|
||||
radio.openWritingPipe(pipes[0]);
|
||||
radio.openReadingPipe(1, pipes[1]);
|
||||
} else {
|
||||
radio.openWritingPipe(pipes[1]);
|
||||
radio.openReadingPipe(1, pipes[0]);
|
||||
}
|
||||
|
||||
//
|
||||
// Start listening
|
||||
//
|
||||
|
||||
radio.startListening();
|
||||
|
||||
//
|
||||
// Dump the configuration of the rf unit for debugging
|
||||
//
|
||||
|
||||
radio.printDetails();
|
||||
|
||||
if (role == role_pong_back) {
|
||||
printf("\n\r+OK ");
|
||||
}
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
//
|
||||
// Ping out role. Repeatedly send the current time
|
||||
//
|
||||
|
||||
if (role == role_ping_out) {
|
||||
// First, stop listening so we can talk.
|
||||
radio.stopListening();
|
||||
|
||||
// Take the time, and send it. This will block until complete
|
||||
unsigned long time = millis();
|
||||
printf("Now sending %lu...", time);
|
||||
radio.write(&time, sizeof(unsigned long));
|
||||
|
||||
// Now, continue listening
|
||||
radio.startListening();
|
||||
|
||||
// Wait here until we get a response, or timeout (250ms)
|
||||
unsigned long started_waiting_at = millis();
|
||||
bool timeout = false;
|
||||
while (!radio.available() && !timeout) {
|
||||
if (millis() - started_waiting_at > 200) {
|
||||
timeout = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Describe the results
|
||||
if (timeout) {
|
||||
printf("Failed, response timed out.\n\r");
|
||||
one_failed();
|
||||
} else {
|
||||
// Grab the response, compare, and send to debugging spew
|
||||
unsigned long got_time;
|
||||
radio.read(&got_time, sizeof(unsigned long));
|
||||
|
||||
// Spew it
|
||||
printf("Got response %lu, round-trip delay: %lu\n\r", got_time, millis() - got_time);
|
||||
one_ok();
|
||||
}
|
||||
|
||||
// Try again later
|
||||
delay(250);
|
||||
}
|
||||
|
||||
//
|
||||
// Pong back role. Receive each packet, dump it out, and send it back
|
||||
//
|
||||
|
||||
if (role == role_pong_back) {
|
||||
// if there is data ready
|
||||
if (radio.available()) {
|
||||
// Dump the payloads until we've gotten everything
|
||||
unsigned long got_time;
|
||||
bool done = false;
|
||||
while (radio.available()) {
|
||||
// Fetch the payload, and see if this was the last one.
|
||||
radio.read(&got_time, sizeof(unsigned long));
|
||||
}
|
||||
// Delay just a little bit to let the other unit
|
||||
// make the transition to receiver
|
||||
//delay(20);
|
||||
//}
|
||||
|
||||
// First, stop listening so we can talk
|
||||
radio.stopListening();
|
||||
|
||||
// Spew it
|
||||
printf("Got payload %lu...", got_time);
|
||||
|
||||
// Send the final one back.
|
||||
radio.write(&got_time, sizeof(unsigned long));
|
||||
|
||||
// Now, resume listening so we catch the next packets.
|
||||
radio.startListening();
|
||||
printf("Sent response.\n\r");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Stop the test if we're done and report results
|
||||
//
|
||||
if (done && !notified) {
|
||||
notified = true;
|
||||
|
||||
printf("\n\r+OK ");
|
||||
if (passed) {
|
||||
printf("PASS\n\r\n\r");
|
||||
} else {
|
||||
printf("FAIL\n\r\n\r");
|
||||
}
|
||||
}
|
||||
}
|
||||
// vim:cin:ai:sts=2 sw=2 ft=cpp
|
37
src/libs/RF24-master/tests/pingpair_blocking/printf.h
Normal file
37
src/libs/RF24-master/tests/pingpair_blocking/printf.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file printf.h
|
||||
*
|
||||
* Setup necessary to direct stdout to the Arduino Serial library, which
|
||||
* enables 'printf'
|
||||
*/
|
||||
|
||||
#ifndef __PRINTF_H__
|
||||
#define __PRINTF_H__
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
int serial_putc( char c, FILE * )
|
||||
{
|
||||
Serial.write( c );
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void printf_begin(void)
|
||||
{
|
||||
fdevopen( &serial_putc, 0 );
|
||||
}
|
||||
|
||||
#else
|
||||
#error This example is only for use on Arduino.
|
||||
#endif // ARDUINO
|
||||
|
||||
#endif // __PRINTF_H__
|
26
src/libs/RF24-master/tests/pingpair_blocking/runtest.py
Normal file
26
src/libs/RF24-master/tests/pingpair_blocking/runtest.py
Normal file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import sys, serial
|
||||
|
||||
|
||||
def read_until(token):
|
||||
while 1:
|
||||
line = ser.readline(None)
|
||||
sys.stdout.write(line)
|
||||
|
||||
if (line.startswith(token)):
|
||||
break
|
||||
return line
|
||||
|
||||
|
||||
ser = serial.Serial(sys.argv[1], 57600, timeout=5, dsrdtr=False, rtscts=False)
|
||||
|
||||
read_until("+READY")
|
||||
ser.write(sys.argv[2])
|
||||
|
||||
line = read_until("+OK")
|
||||
ser.close()
|
||||
if (line.find("PASS") != -1):
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.exit(1)
|
5
src/libs/RF24-master/tests/pingpair_blocking/runtests.sh
Normal file
5
src/libs/RF24-master/tests/pingpair_blocking/runtests.sh
Normal file
@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Connect u0 to receiver, u1 to sender
|
||||
|
||||
jam u0 u1 && expect test.ex
|
11
src/libs/RF24-master/tests/pingpair_blocking/test.ex
Normal file
11
src/libs/RF24-master/tests/pingpair_blocking/test.ex
Normal file
@ -0,0 +1,11 @@
|
||||
#/usr/bin/expect
|
||||
|
||||
set timeout 100
|
||||
spawn picocom -b 57600 /dev/ttyUSB0
|
||||
expect "+READY"
|
||||
send "1"
|
||||
expect "+OK"
|
||||
spawn picocom -b 57600 /dev/ttyUSB1
|
||||
expect "+READY"
|
||||
send "1"
|
||||
expect "+OK"
|
219
src/libs/RF24-master/tests/pingpair_test/Jamfile
Normal file
219
src/libs/RF24-master/tests/pingpair_test/Jamfile
Normal file
@ -0,0 +1,219 @@
|
||||
# (1) Project Information
|
||||
|
||||
PROJECT_LIBS = SPI RF24 ;
|
||||
PROJECT_DIRS = $(PWD) ;
|
||||
|
||||
# (2) Board Information
|
||||
|
||||
UPLOAD_PROTOCOL ?= arduino ;
|
||||
UPLOAD_SPEED ?= 115200 ;
|
||||
MCU ?= atmega328p ;
|
||||
F_CPU ?= 16000000 ;
|
||||
CORE ?= arduino ;
|
||||
VARIANT ?= standard ;
|
||||
ARDUINO_VERSION ?= 100 ;
|
||||
|
||||
# (3) USB Ports
|
||||
|
||||
PORTS = p4 p6 p9 u0 u1 u2 ;
|
||||
PORT_p6 = /dev/tty.usbserial-A600eHIs ;
|
||||
PORT_p4 = /dev/tty.usbserial-A40081RP ;
|
||||
PORT_p9 = /dev/tty.usbserial-A9007LmI ;
|
||||
PORT_u0 = /dev/ttyUSB0 ;
|
||||
PORT_u1 = /dev/ttyUSB1 ;
|
||||
PORT_u2 = /dev/ttyUSB2 ;
|
||||
|
||||
# (4) Location of AVR tools
|
||||
#
|
||||
# This configuration assumes using avr-tools that were obtained separate from the Arduino
|
||||
# distribution.
|
||||
|
||||
if $(OS) = MACOSX
|
||||
{
|
||||
AVR_BIN ?= /usr/local/avrtools/bin ;
|
||||
AVR_ETC = /usr/local/avrtools/etc ;
|
||||
AVR_INCLUDE = /usr/local/avrtools/include ;
|
||||
}
|
||||
else
|
||||
{
|
||||
AVR_BIN ?= /usr/bin ;
|
||||
AVR_INCLUDE = /usr/lib/avr/include ;
|
||||
AVR_ETC = /etc ;
|
||||
}
|
||||
|
||||
# (5) Directories where Arduino core and libraries are located
|
||||
|
||||
ARDUINO_DIR ?= /opt/Arduino ;
|
||||
ARDUINO_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/$(CORE) $(ARDUINO_DIR)/hardware/arduino/variants/$(VARIANT) ;
|
||||
ARDUINO_LIB = $(ARDUINO_DIR)/libraries ;
|
||||
SKETCH_LIB = $(HOME)/Source/Arduino/libraries ;
|
||||
|
||||
#
|
||||
# --------------------------------------------------
|
||||
# Below this line usually never needs to be modified
|
||||
#
|
||||
|
||||
# Tool locations
|
||||
|
||||
CC = $(AVR_BIN)/avr-gcc ;
|
||||
C++ = $(AVR_BIN)/avr-g++ ;
|
||||
LINK = $(AVR_BIN)/avr-gcc ;
|
||||
AR = $(AVR_BIN)/avr-ar rcs ;
|
||||
RANLIB = ;
|
||||
OBJCOPY = $(AVR_BIN)/avr-objcopy ;
|
||||
AVRDUDE ?= $(AVR_BIN)/avrdude ;
|
||||
|
||||
# Flags
|
||||
|
||||
DEFINES += F_CPU=$(F_CPU)L ARDUINO=$(ARDUINO_VERSION) VERSION_H ;
|
||||
OPTIM = -Os ;
|
||||
CCFLAGS = -Wall -Wextra -Wno-strict-aliasing -mmcu=$(MCU) -ffunction-sections -fdata-sections ;
|
||||
C++FLAGS = $(CCFLAGS) -fno-exceptions -fno-strict-aliasing ;
|
||||
LINKFLAGS = $(OPTIM) -lm -Wl,--gc-sections -mmcu=$(MCU) ;
|
||||
AVRDUDEFLAGS = -V -F -D -C $(AVR_ETC)/avrdude.conf -p $(MCU) -c $(UPLOAD_PROTOCOL) -b $(UPLOAD_SPEED) ;
|
||||
|
||||
# Search everywhere for headers
|
||||
|
||||
HDRS = $(PROJECT_DIRS) $(AVR_INCLUDE) $(ARDUINO_CORE) $(ARDUINO_LIB)/$(PROJECT_LIBS) $(ARDUINO_LIB)/$(PROJECT_LIBS)/utility $(SKETCH_LIB)/$(PROJECT_LIBS) ;
|
||||
|
||||
# Output locations
|
||||
|
||||
LOCATE_TARGET = $(F_CPU) ;
|
||||
LOCATE_SOURCE = $(F_CPU) ;
|
||||
|
||||
#
|
||||
# Custom rules
|
||||
#
|
||||
|
||||
rule GitVersion
|
||||
{
|
||||
Always $(<) ;
|
||||
Depends all : $(<) ;
|
||||
}
|
||||
|
||||
actions GitVersion
|
||||
{
|
||||
echo "const char program_version[] = \"\\" > $(<)
|
||||
git log -1 --pretty=format:%h >> $(<)
|
||||
echo "\";" >> $(<)
|
||||
}
|
||||
|
||||
GitVersion version.h ;
|
||||
|
||||
rule Pde
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
MakeLocate $(<) : $(LOCATE_SOURCE) ;
|
||||
Clean clean : $(<) ;
|
||||
}
|
||||
|
||||
if ( $(ARDUINO_VERSION) < 100 )
|
||||
{
|
||||
ARDUINO_H = WProgram.h ;
|
||||
}
|
||||
else
|
||||
{
|
||||
ARDUINO_H = Arduino.h ;
|
||||
}
|
||||
|
||||
actions Pde
|
||||
{
|
||||
echo "#include <$(ARDUINO_H)>" > $(<)
|
||||
echo "#line 1 \"$(>)\"" >> $(<)
|
||||
cat $(>) >> $(<)
|
||||
}
|
||||
|
||||
rule C++Pde
|
||||
{
|
||||
local _CPP = $(>:B).cpp ;
|
||||
Pde $(_CPP) : $(>) ;
|
||||
C++ $(<) : $(_CPP) ;
|
||||
}
|
||||
|
||||
rule UserObject
|
||||
{
|
||||
switch $(>:S)
|
||||
{
|
||||
case .ino : C++Pde $(<) : $(>) ;
|
||||
case .pde : C++Pde $(<) : $(>) ;
|
||||
}
|
||||
}
|
||||
|
||||
rule Objects
|
||||
{
|
||||
local _i ;
|
||||
|
||||
for _i in [ FGristFiles $(<) ]
|
||||
{
|
||||
local _b = $(_i:B)$(SUFOBJ) ;
|
||||
local _o = $(_b:G=$(SOURCE_GRIST:E)) ;
|
||||
Object $(_o) : $(_i) ;
|
||||
Depends obj : $(_o) ;
|
||||
}
|
||||
}
|
||||
|
||||
rule Library
|
||||
{
|
||||
LibraryFromObjects $(<) : $(>:B)$(SUFOBJ) ;
|
||||
Objects $(>) ;
|
||||
}
|
||||
|
||||
rule Main
|
||||
{
|
||||
MainFromObjects $(<) : $(>:B)$(SUFOBJ) ;
|
||||
Objects $(>) ;
|
||||
}
|
||||
|
||||
rule Hex
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
MakeLocate $(<) : $(LOCATE_TARGET) ;
|
||||
Depends hex : $(<) ;
|
||||
Clean clean : $(<) ;
|
||||
}
|
||||
|
||||
actions Hex
|
||||
{
|
||||
$(OBJCOPY) -O ihex -R .eeprom $(>) $(<)
|
||||
}
|
||||
|
||||
rule Upload
|
||||
{
|
||||
Depends $(1) : $(2) ;
|
||||
Depends $(2) : $(3) ;
|
||||
NotFile $(1) ;
|
||||
Always $(1) ;
|
||||
Always $(2) ;
|
||||
UploadAction $(2) : $(3) ;
|
||||
}
|
||||
|
||||
actions UploadAction
|
||||
{
|
||||
$(AVRDUDE) $(AVRDUDEFLAGS) -P $(<) $(AVRDUDE_WRITE_FLASH) -U flash:w:$(>):i
|
||||
}
|
||||
|
||||
rule Arduino
|
||||
{
|
||||
LINKFLAGS on $(<) = $(LINKFLAGS) -Wl,-Map=$(LOCATE_TARGET)/$(<:B).map ;
|
||||
Main $(<) : $(>) ;
|
||||
LinkLibraries $(<) : core libs ;
|
||||
Hex $(<:B).hex : $(<) ;
|
||||
for _p in $(PORTS)
|
||||
{
|
||||
Upload $(_p) : $(PORT_$(_p)) : $(<:B).hex ;
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Targets
|
||||
#
|
||||
|
||||
# Grab everything from the core directory
|
||||
Library core : [ GLOB $(ARDUINO_CORE) : *.c *.cpp ] ;
|
||||
|
||||
# Grab everything from libraries. To avoid this "grab everything" behaviour, you
|
||||
# can specify specific modules to pick up in PROJECT_MODULES
|
||||
Library libs : [ GLOB $(ARDUINO_LIB)/$(PROJECT_LIBS) $(ARDUINO_LIB)/$(PROJECT_LIBS)/utility $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp *.c ] ;
|
||||
|
||||
# Main output executable
|
||||
Arduino $(PWD:B).elf : $(PROJECT_MODULES) [ GLOB $(PROJECT_DIRS) : *.c *.cpp *.pde *.ino ] ;
|
417
src/libs/RF24-master/tests/pingpair_test/pingpair_test.pde
Normal file
417
src/libs/RF24-master/tests/pingpair_test/pingpair_test.pde
Normal file
@ -0,0 +1,417 @@
|
||||
/*
|
||||
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Full test on single RF pair
|
||||
*
|
||||
* This sketches uses as many RF24 methods as possible in a single test.
|
||||
*
|
||||
* To operate:
|
||||
* Upload this sketch on two nodes, each with IRQ -> pin 2
|
||||
* One node needs pin 7 -> GND, the other NC. That's the receiving node
|
||||
* Monitor the sending node's serial output
|
||||
* Look for "+OK PASS" or "+OK FAIL"
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include "nRF24L01.h"
|
||||
#include "RF24.h"
|
||||
#include "printf.h"
|
||||
|
||||
//
|
||||
// Hardware configuration
|
||||
//
|
||||
|
||||
// Set up nRF24L01 radio on SPI bus plus pins 8 & 9
|
||||
|
||||
RF24 radio(7, 8);
|
||||
|
||||
// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver
|
||||
// Leave open to be the 'ping' transmitter
|
||||
const short role_pin = 5;
|
||||
|
||||
//
|
||||
// Topology
|
||||
//
|
||||
|
||||
// Single radio pipe address for the 2 nodes to communicate.
|
||||
const uint64_t pipe = 0xE8E8F0F0E1LL;
|
||||
|
||||
//
|
||||
// Role management
|
||||
//
|
||||
// Set up role. This sketch uses the same software for all the nodes in this
|
||||
// system. Doing so greatly simplifies testing. The hardware itself specifies
|
||||
// which node it is.
|
||||
//
|
||||
// This is done through the role_pin
|
||||
//
|
||||
|
||||
// The various roles supported by this sketch
|
||||
typedef enum {
|
||||
role_sender = 1,
|
||||
role_receiver
|
||||
} role_e;
|
||||
|
||||
// The debug-friendly names of those roles
|
||||
const char* role_friendly_name[] = {"invalid", "Sender", "Receiver"};
|
||||
|
||||
// The role of the current running sketch
|
||||
role_e role;
|
||||
|
||||
// Interrupt handler, check the radio because we got an IRQ
|
||||
void check_radio(void);
|
||||
|
||||
//
|
||||
// Payload
|
||||
//
|
||||
|
||||
const int min_payload_size = 4;
|
||||
const int max_payload_size = 32;
|
||||
int payload_size_increments_by = 2;
|
||||
int next_payload_size = min_payload_size;
|
||||
|
||||
char receive_payload[max_payload_size + 1]; // +1 to allow room for a terminating NULL char
|
||||
|
||||
//
|
||||
// Test state
|
||||
//
|
||||
|
||||
bool done; //*< Are we done with the test? */
|
||||
bool passed; //*< Have we passed the test? */
|
||||
bool notified; //*< Have we notified the user we're done? */
|
||||
const int num_needed = 10; //*< How many success/failures until we're done? */
|
||||
int receives_remaining = num_needed; //*< How many ack packets until we declare victory? */
|
||||
int failures_remaining = num_needed; //*< How many more failed sends until we declare failure? */
|
||||
const int interval = 100; //*< ms to wait between sends */
|
||||
|
||||
char configuration = '1'; //*< Configuration key, one char sent in by the test framework to tell us how to configure, this is the default */
|
||||
|
||||
uint8_t pipe_number = 1; // Which pipe to send on.
|
||||
|
||||
void one_ok(void)
|
||||
{
|
||||
// Have we received enough yet?
|
||||
if (!--receives_remaining) {
|
||||
done = true;
|
||||
passed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void one_failed(void)
|
||||
{
|
||||
// Have we failed enough yet?
|
||||
if (!--failures_remaining) {
|
||||
done = true;
|
||||
passed = false;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Setup
|
||||
//
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
//
|
||||
// Role
|
||||
//
|
||||
|
||||
// set up the role pin
|
||||
pinMode(role_pin, INPUT);
|
||||
digitalWrite(role_pin, HIGH);
|
||||
delay(20); // Just to get a solid reading on the role pin
|
||||
|
||||
// read the address pin, establish our role
|
||||
if (digitalRead(role_pin)) {
|
||||
role = role_sender;
|
||||
} else {
|
||||
role = role_receiver;
|
||||
}
|
||||
|
||||
//
|
||||
// Print preamble
|
||||
//
|
||||
|
||||
Serial.begin(115200);
|
||||
printf_begin();
|
||||
printf("\n\rRF24/tests/pingpair_test/\n\r");
|
||||
printf("ROLE: %s\n\r", role_friendly_name[role]);
|
||||
|
||||
//
|
||||
// Read configuration from serial
|
||||
//
|
||||
// It would be a much better test if this program could accept configuration
|
||||
// from the serial port. Then it would be possible to run the same test under
|
||||
// lots of different circumstances.
|
||||
//
|
||||
// The idea is that we will print "+READY" at this point. The python script
|
||||
// will wait for it, and then send down a configuration script that we
|
||||
// execute here and then run with.
|
||||
//
|
||||
// The test controller will need to configure the receiver first, then go run
|
||||
// the test on the sender.
|
||||
//
|
||||
|
||||
printf("+READY press any key to start\n\r\n\r");
|
||||
|
||||
while (!Serial.available()) {
|
||||
}
|
||||
configuration = Serial.read();
|
||||
printf("Configuration\t = %c\n\r", configuration);
|
||||
|
||||
//
|
||||
// Setup and configure rf radio
|
||||
//
|
||||
|
||||
radio.begin();
|
||||
|
||||
// We will be using the Ack Payload feature, so please enable it
|
||||
radio.enableAckPayload();
|
||||
radio.enableDynamicPayloads(); // needed for using ACK payloads
|
||||
|
||||
// Config 2 is special radio config
|
||||
if (configuration == '2'){
|
||||
radio.setCRCLength(RF24_CRC_8);
|
||||
radio.setDataRate(RF24_250KBPS);
|
||||
radio.setChannel(10);
|
||||
}else{
|
||||
//Otherwise, default radio config
|
||||
|
||||
// Optional: Increase CRC length for improved reliability
|
||||
radio.setCRCLength(RF24_CRC_16);
|
||||
|
||||
// Optional: Decrease data rate for improved reliability
|
||||
radio.setDataRate(RF24_1MBPS);
|
||||
|
||||
// Optional: Pick a high channel
|
||||
radio.setChannel(90);
|
||||
}
|
||||
|
||||
// Config 3 is static payloads only
|
||||
if (configuration == '3'){
|
||||
next_payload_size = 16;
|
||||
payload_size_increments_by = 0;
|
||||
radio.setPayloadSize(next_payload_size);
|
||||
}else{
|
||||
// enable dynamic payloads
|
||||
radio.enableDynamicPayloads();
|
||||
}
|
||||
|
||||
// Config 4 tests out a higher pipe ##
|
||||
if (configuration == '4' && role == role_sender){
|
||||
// Set top 4 bytes of the address in pipe 1
|
||||
radio.openReadingPipe(1, pipe & 0xFFFFFFFF00ULL);
|
||||
|
||||
// indicate the pipe to use
|
||||
pipe_number = 5;
|
||||
}else if (role == role_sender){
|
||||
radio.openReadingPipe(5, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Open pipes to other nodes for communication
|
||||
//
|
||||
|
||||
// This simple sketch opens a single pipe for these two nodes to communicate
|
||||
// back and forth. One listens on it, the other talks to it.
|
||||
|
||||
if (role == role_sender){
|
||||
radio.openWritingPipe(pipe);
|
||||
}else{
|
||||
radio.openReadingPipe(pipe_number, pipe);
|
||||
}
|
||||
|
||||
//
|
||||
// Start listening
|
||||
//
|
||||
|
||||
if (role == role_receiver){
|
||||
radio.startListening();
|
||||
}
|
||||
|
||||
//
|
||||
// Dump the configuration of the rf unit for debugging
|
||||
//
|
||||
|
||||
radio.printDetails();
|
||||
|
||||
//
|
||||
// Attach interrupt handler to interrupt #0 (using pin 2)
|
||||
// on BOTH the sender and receiver
|
||||
//
|
||||
|
||||
attachInterrupt(0, check_radio, FALLING);
|
||||
delay(50);
|
||||
if (role == role_receiver){
|
||||
printf("\n\r+OK ");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Print buffer
|
||||
//
|
||||
// Printing from the interrupt handler is a bad idea, so we print from there
|
||||
// to this intermediate buffer
|
||||
//
|
||||
|
||||
char prbuf[1000];
|
||||
char* prbuf_end = prbuf + sizeof(prbuf);
|
||||
char* prbuf_in = prbuf;
|
||||
char* prbuf_out = prbuf;
|
||||
|
||||
//
|
||||
// Loop
|
||||
//
|
||||
|
||||
static uint32_t message_count = 0;
|
||||
static uint32_t last_message_count = 0;
|
||||
|
||||
void loop(void){
|
||||
//
|
||||
// Sender role. Repeatedly send the current time
|
||||
//
|
||||
|
||||
if (role == role_sender && !done){
|
||||
// The payload will always be the same, what will change is how much of it we send.
|
||||
static char send_payload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ789012";
|
||||
|
||||
// First, stop listening so we can talk.
|
||||
radio.stopListening();
|
||||
|
||||
// Send it. This will block until complete
|
||||
printf("\n\rNow sending length %i...", next_payload_size);
|
||||
radio.startWrite(send_payload, next_payload_size, 0);
|
||||
|
||||
// Update size for next time.
|
||||
next_payload_size += payload_size_increments_by;
|
||||
if (next_payload_size > max_payload_size){
|
||||
next_payload_size = min_payload_size;
|
||||
}
|
||||
|
||||
// Try again soon
|
||||
delay(interval);
|
||||
|
||||
// Timeout if we have not received anything back ever
|
||||
if (!last_message_count && millis() > interval * 100){
|
||||
printf("No responses received. Are interrupts connected??\n\r");
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Receiver role: Does nothing! All the work is in IRQ
|
||||
//
|
||||
|
||||
//
|
||||
// Spew print buffer
|
||||
//
|
||||
|
||||
size_t write_length = prbuf_in - prbuf_out;
|
||||
if (write_length){
|
||||
Serial.write(reinterpret_cast<uint8_t*>(prbuf_out), write_length);
|
||||
prbuf_out += write_length;
|
||||
}
|
||||
|
||||
//
|
||||
// Stop the test if we're done and report results
|
||||
//
|
||||
if (done && !notified){
|
||||
notified = true;
|
||||
|
||||
printf("\n\r+OK ");
|
||||
if (passed){
|
||||
printf("PASS\n\r\n\r");
|
||||
}else{
|
||||
printf("FAIL\n\r\n\r");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void check_radio(void)
|
||||
{
|
||||
// What happened?
|
||||
bool tx, fail, rx;
|
||||
radio.whatHappened(tx, fail, rx);
|
||||
|
||||
// Have we successfully transmitted?
|
||||
if (tx){
|
||||
if (role == role_sender){
|
||||
prbuf_in += sprintf(prbuf_in, "Send:OK ");
|
||||
}
|
||||
|
||||
if (role == role_receiver){
|
||||
prbuf_in += sprintf(prbuf_in, "Ack Payload:Sent\n\r");
|
||||
}
|
||||
}
|
||||
|
||||
// Have we failed to transmit?
|
||||
if (fail){
|
||||
if (role == role_sender){
|
||||
prbuf_in += sprintf(prbuf_in, "Send:Failed ");
|
||||
|
||||
// log status of this line
|
||||
one_failed();
|
||||
}
|
||||
|
||||
if (role == role_receiver){
|
||||
prbuf_in += sprintf(prbuf_in, "Ack Payload:Failed\n\r");
|
||||
}
|
||||
}
|
||||
|
||||
// Not powering down since radio is in standby mode
|
||||
//if (( tx || fail ) && ( role == role_sender )){ radio.powerDown(); }
|
||||
|
||||
// Did we receive a message?
|
||||
if (rx){
|
||||
// If we're the sender, we've received an ack payload
|
||||
if (role == role_sender){
|
||||
radio.read(&message_count, sizeof(message_count));
|
||||
prbuf_in += sprintf(prbuf_in, "Ack:%lu ", message_count);
|
||||
|
||||
// is this ack what we were expecting? to account
|
||||
// for failures, we simply want to make sure we get a
|
||||
// DIFFERENT ack every time.
|
||||
if ((message_count != last_message_count) || (configuration == '3' && message_count == 16)){
|
||||
prbuf_in += sprintf(prbuf_in, "OK ");
|
||||
one_ok();
|
||||
}else{
|
||||
prbuf_in += sprintf(prbuf_in, "FAILED ");
|
||||
one_failed();
|
||||
}
|
||||
last_message_count = message_count;
|
||||
}
|
||||
|
||||
// If we're the receiver, we've received a time message
|
||||
if (role == role_receiver){
|
||||
// Get this payload and dump it
|
||||
size_t len = max_payload_size;
|
||||
memset(receive_payload, 0, max_payload_size);
|
||||
|
||||
if (configuration == '3'){
|
||||
len = next_payload_size;
|
||||
}else{
|
||||
len = radio.getDynamicPayloadSize();
|
||||
}
|
||||
|
||||
radio.read(receive_payload, len);
|
||||
|
||||
// Put a zero at the end for easy printing
|
||||
receive_payload[len] = 0;
|
||||
|
||||
// Spew it
|
||||
prbuf_in += sprintf(prbuf_in, "Recv size=%i val=%s len=%u\n\r", len, receive_payload, strlen(receive_payload));
|
||||
|
||||
// Add an ack packet for the next time around.
|
||||
// Here we will report back how many bytes we got this time.
|
||||
radio.writeAckPayload(pipe_number, &len, sizeof(len));
|
||||
|
||||
++message_count;
|
||||
}
|
||||
}
|
||||
}
|
37
src/libs/RF24-master/tests/pingpair_test/printf.h
Normal file
37
src/libs/RF24-master/tests/pingpair_test/printf.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file printf.h
|
||||
*
|
||||
* Setup necessary to direct stdout to the Arduino Serial library, which
|
||||
* enables 'printf'
|
||||
*/
|
||||
|
||||
#ifndef __PRINTF_H__
|
||||
#define __PRINTF_H__
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
int serial_putc( char c, FILE * )
|
||||
{
|
||||
Serial.write( c );
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void printf_begin(void)
|
||||
{
|
||||
fdevopen( &serial_putc, 0 );
|
||||
}
|
||||
|
||||
#else
|
||||
#error This example is only for use on Arduino.
|
||||
#endif // ARDUINO
|
||||
|
||||
#endif // __PRINTF_H__
|
26
src/libs/RF24-master/tests/pingpair_test/runtest.py
Normal file
26
src/libs/RF24-master/tests/pingpair_test/runtest.py
Normal file
@ -0,0 +1,26 @@
|
||||
#!/opt/local/bin/python
|
||||
|
||||
import sys, serial
|
||||
|
||||
|
||||
def read_until(token):
|
||||
while 1:
|
||||
line = ser.readline(None, "\r")
|
||||
sys.stdout.write(line)
|
||||
|
||||
if (line.startswith(token)):
|
||||
break
|
||||
return line
|
||||
|
||||
|
||||
ser = serial.Serial(sys.argv[1], 57600, timeout=5, dsrdtr=False, rtscts=False)
|
||||
|
||||
read_until("+READY")
|
||||
ser.write(sys.argv[2])
|
||||
|
||||
line = read_until("+OK")
|
||||
ser.close()
|
||||
if (line.find("PASS") != -1):
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.exit(1)
|
21
src/libs/RF24-master/tests/pingpair_test/runtests.sh
Normal file
21
src/libs/RF24-master/tests/pingpair_test/runtests.sh
Normal file
@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Connect u0 to receiver, u0 to sender
|
||||
# WARNING: Test config 2 only works with PLUS units.
|
||||
|
||||
jam u0 u1 && expect test.ex 1
|
||||
sleep 1
|
||||
stty 57600 raw ignbrk hup < /dev/ttyUSB0
|
||||
sleep 1
|
||||
stty 57600 raw ignbrk hup < /dev/ttyUSB1
|
||||
expect test.ex 2
|
||||
sleep 1
|
||||
stty 57600 raw ignbrk hup < /dev/ttyUSB0
|
||||
sleep 1
|
||||
stty 57600 raw ignbrk hup < /dev/ttyUSB1
|
||||
expect test.ex 3
|
||||
sleep 1
|
||||
stty 57600 raw ignbrk hup < /dev/ttyUSB0
|
||||
sleep 1
|
||||
stty 57600 raw ignbrk hup < /dev/ttyUSB1
|
||||
expect test.ex 4
|
11
src/libs/RF24-master/tests/pingpair_test/test.ex
Normal file
11
src/libs/RF24-master/tests/pingpair_test/test.ex
Normal file
@ -0,0 +1,11 @@
|
||||
#/usr/bin/expect
|
||||
|
||||
set timeout 100
|
||||
spawn picocom -b 57600 /dev/ttyUSB0
|
||||
expect "+READY"
|
||||
send [lindex $argv 0]
|
||||
expect "+OK"
|
||||
spawn picocom -b 57600 /dev/ttyUSB1
|
||||
expect "+READY"
|
||||
send [lindex $argv 0]
|
||||
expect "+OK"
|
53
src/libs/RF24-master/utility/ATTiny/RF24_arch_config.h
Normal file
53
src/libs/RF24-master/utility/ATTiny/RF24_arch_config.h
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
/*
|
||||
TMRh20 2015
|
||||
ATTiny Configuration File
|
||||
*/
|
||||
|
||||
#ifndef __RF24_ARCH_CONFIG_H__
|
||||
#define __RF24_ARCH_CONFIG_H__
|
||||
|
||||
/*** USER DEFINES: ***/
|
||||
//#define FAILURE_HANDLING
|
||||
//#define MINIMAL
|
||||
/**********************/
|
||||
|
||||
#define rf24_max(a, b) (a>b?a:b)
|
||||
#define rf24_min(a, b) (a<b?a:b)
|
||||
|
||||
#if ARDUINO < 100
|
||||
#include <WProgram.h>
|
||||
#else
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
#define _SPI SPI
|
||||
|
||||
#if !defined(RF24_CSN_SETTLE_LOW_DELAY)
|
||||
#define RF24_CSN_SETTLE_LOW_DELAY 11
|
||||
#endif
|
||||
|
||||
#if !defined(RF24_CSN_SETTLE_HIGH_DELAY)
|
||||
#define RF24_CSN_SETTLE_HIGH_DELAY 100
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
#define IF_SERIAL_DEBUG(x) ({x;})
|
||||
#else
|
||||
#define IF_SERIAL_DEBUG(x)
|
||||
#if defined(RF24_TINY)
|
||||
#define printf_P(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#define PRIPSTR "%S"
|
||||
|
||||
#endif // __RF24_ARCH_CONFIG_H__
|
||||
|
54
src/libs/RF24-master/utility/ATXMegaD3/README.md
Normal file
54
src/libs/RF24-master/utility/ATXMegaD3/README.md
Normal file
@ -0,0 +1,54 @@
|
||||
This is a fork from **http://nRF24.github.io/RF24** which can be build as a static library for Atmel Studio 7.
|
||||
|
||||
Not all files are needed.
|
||||
|
||||
Just copy the following structure into a GCC Static Library project in AS7:
|
||||
```
|
||||
utility\
|
||||
ATXMega256D3\
|
||||
compatibility.c
|
||||
compatibility.h
|
||||
gpio.cpp
|
||||
gpio.h
|
||||
gpio_helper.c
|
||||
gpio_helper.h
|
||||
includes.h
|
||||
RF24_arch_config.h
|
||||
spi.cpp
|
||||
spi.h
|
||||
nRF24L01.h
|
||||
printf.h
|
||||
RF24.cpp
|
||||
RF24.h
|
||||
RF24_config.h
|
||||
```
|
||||
|
||||
Only ATXMega256D3 is supported right now!
|
||||
|
||||
## Notes
|
||||
The millisecond functionality is based on the TCE0 so don't use these pins as IO.
|
||||
|
||||
The operating frequency of the uC is 32MHz. If else change the TCE0 registers appropriatly in function **__start_timer()** in **compatibility.c** file for your frequency.
|
||||
|
||||
|
||||
## Usage
|
||||
Add the library to your project!
|
||||
In the file where the **main()** is put the following in order to update the millisecond functionality:
|
||||
```
|
||||
ISR(TCE0_OVF_vect)
|
||||
{
|
||||
update_milisec();
|
||||
}
|
||||
```
|
||||
|
||||
Declare the rf24 radio with **RF24 radio(XMEGA_PORTC_PIN3, XMEGA_SPI_PORT_C);**
|
||||
|
||||
First parameter is the CE pin which can be any available pin on the uC.
|
||||
|
||||
Second parameter is the CS which can be on port C (**XMEGA_SPI_PORT_C**) or on port D (**XMEGA_SPI_PORT_D**).
|
||||
|
||||
Call the **__start_timer()** to start the millisecond timer.
|
||||
|
||||
|
||||
|
||||
** For further information please see http://nRF24.github.io/RF24 for all documentation**
|
83
src/libs/RF24-master/utility/ATXMegaD3/RF24_arch_config.h
Normal file
83
src/libs/RF24-master/utility/ATXMegaD3/RF24_arch_config.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file RF24_arch_config.h
|
||||
* General defines and includes for RF24/Linux
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example of RF24_arch_config.h for RF24 portability
|
||||
*
|
||||
* @defgroup Porting_General Porting: General
|
||||
*
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __RF24_ARCH_CONFIG_H__
|
||||
#define __RF24_ARCH_CONFIG_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "spi.h"
|
||||
#include "gpio.h"
|
||||
#include "compatibility.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
//#include <time.h>
|
||||
#include <string.h>
|
||||
//#include <sys/time.h>
|
||||
|
||||
//#define _BV(x) (1<<(x))
|
||||
#define _SPI spi
|
||||
|
||||
#undef SERIAL_DEBUG
|
||||
#ifdef SERIAL_DEBUG
|
||||
#define IF_SERIAL_DEBUG(x) ({x;})
|
||||
#else
|
||||
#define IF_SERIAL_DEBUG(x)
|
||||
#endif
|
||||
|
||||
// Use the avr pgmspace commands
|
||||
//// Avoid spurious warnings
|
||||
//#if 1
|
||||
//#if ! defined( NATIVE ) && defined( ARDUINO )
|
||||
//#undef PROGMEM
|
||||
//#define PROGMEM __attribute__(( section(".progmem.data") ))
|
||||
//#undef PSTR
|
||||
//#define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];}))
|
||||
//#endif
|
||||
//#endif
|
||||
|
||||
typedef uint16_t prog_uint16_t;
|
||||
//#define PSTR(x) (x)
|
||||
//#define printf_P printf
|
||||
//#define strlen_P strlen
|
||||
//#define PROGMEM
|
||||
//#define pgm_read_word(p) (*(p))
|
||||
#define PRIPSTR "%s"
|
||||
//#define pgm_read_byte(p) (*(p))
|
||||
|
||||
// Function, constant map as a result of migrating from Arduino
|
||||
#define LOW GPIO::OUTPUT_LOW
|
||||
#define HIGH GPIO::OUTPUT_HIGH
|
||||
#define INPUT GPIO::DIRECTION_IN
|
||||
#define OUTPUT GPIO::DIRECTION_OUT
|
||||
#define digitalWrite(pin, value) GPIO::write(pin, value)
|
||||
#define pinMode(pin, direction) GPIO::open(pin, direction)
|
||||
#define delay(milisec) __msleep(milisec)
|
||||
#define delayMicroseconds(usec) __usleep(usec)
|
||||
#define millis() __millis()
|
||||
|
||||
#endif // __RF24_ARCH_CONFIG_H__
|
||||
|
||||
|
||||
/*@}*/
|
64
src/libs/RF24-master/utility/ATXMegaD3/compatibility.c
Normal file
64
src/libs/RF24-master/utility/ATXMegaD3/compatibility.c
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* compatibility.c
|
||||
*
|
||||
* Created: 19/1/2016 15:31:35
|
||||
* Author: akatran
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <stdint.h>
|
||||
#include <util/delay.h>
|
||||
|
||||
volatile uint32_t _millis;
|
||||
|
||||
void __msleep(int milisec)
|
||||
{
|
||||
while (milisec-- > 0) {
|
||||
_delay_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
void __usleep(int usec)
|
||||
{
|
||||
while (usec-- > 0) {
|
||||
_delay_us(1);
|
||||
}
|
||||
}
|
||||
|
||||
void __start_timer()
|
||||
{
|
||||
|
||||
// Timer details : Clock is 32MHz, Timer resolution is 8bit, Prescaler is 256, Period is 124, Real Time is 0.001s
|
||||
|
||||
/* Set the timer to run at the fastest rate. */
|
||||
TCE0.CTRLA = TC_CLKSEL_DIV256_gc;
|
||||
|
||||
/* Configure the timer for normal counting. */
|
||||
TCE0.CTRLB = TC_WGMODE_NORMAL_gc;
|
||||
|
||||
/* At 2 MHz, one tick is 0.5 us. Set period to 8 us. */
|
||||
TCE0.PER = 124;
|
||||
//TCC0.PER = 2;
|
||||
|
||||
/* Configure timer to generate an interrupt on overflow. */
|
||||
TCE0.INTCTRLA = TC_OVFINTLVL_HI_gc;
|
||||
|
||||
/* Enable this interrupt level. */
|
||||
PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
|
||||
|
||||
_millis = 0;
|
||||
}
|
||||
|
||||
long __millis()
|
||||
{
|
||||
return _millis;
|
||||
}
|
||||
|
||||
void update_milisec()
|
||||
{
|
||||
_millis++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
49
src/libs/RF24-master/utility/ATXMegaD3/compatibility.h
Normal file
49
src/libs/RF24-master/utility/ATXMegaD3/compatibility.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* File: compatiblity.h
|
||||
* Author: purinda
|
||||
*
|
||||
* Created on 24 June 2012, 3:08 PM
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file compatibility.h
|
||||
* Class declaration for SPI helper files
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example of compatibility.h class declaration for timing functions portability
|
||||
*
|
||||
* @defgroup Porting_Timing Porting: Timing
|
||||
*
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef COMPATIBLITY_H
|
||||
#define COMPATIBLITY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
//#include <time.h>
|
||||
//#include <sys/time.h>
|
||||
|
||||
void __msleep(int milisec);
|
||||
|
||||
void __usleep(int usec);
|
||||
|
||||
void __start_timer();
|
||||
|
||||
long __millis();
|
||||
|
||||
void update_milisec();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* COMPATIBLITY_H */
|
||||
|
||||
/*@}*/
|
46
src/libs/RF24-master/utility/ATXMegaD3/gpio.cpp
Normal file
46
src/libs/RF24-master/utility/ATXMegaD3/gpio.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* gpio.cpp
|
||||
*
|
||||
* Created: 20/1/2016 11:57:21
|
||||
* Author: akatran
|
||||
*/
|
||||
|
||||
//#include "gpio_helper.h"
|
||||
#include "gpio.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
void GPIO::open(int port, int DDR)
|
||||
{
|
||||
uint8_t pin;
|
||||
PORT_t* p = GPIO_getPort(port, &pin);
|
||||
if (DDR == 0) {
|
||||
p->DIRCLR = pin;
|
||||
} else if (DDR == 1) {
|
||||
p->DIRSET = pin;
|
||||
}
|
||||
}
|
||||
|
||||
void GPIO::close(int port)
|
||||
{
|
||||
// Nothing to do with close;
|
||||
}
|
||||
|
||||
int GPIO::read(int port)
|
||||
{
|
||||
uint8_t pin;
|
||||
PORT_t* p = GPIO_getPort(port, &pin);
|
||||
return p->IN;
|
||||
}
|
||||
|
||||
void GPIO::write(int port, int value)
|
||||
{
|
||||
uint8_t pin;
|
||||
PORT_t* p = GPIO_getPort(port, &pin);
|
||||
if (value == 0) {
|
||||
p->OUTCLR = pin;
|
||||
} else if (value == 1) {
|
||||
p->OUTSET = pin;
|
||||
}
|
||||
|
||||
}
|
||||
|
64
src/libs/RF24-master/utility/ATXMegaD3/gpio.h
Normal file
64
src/libs/RF24-master/utility/ATXMegaD3/gpio.h
Normal file
@ -0,0 +1,64 @@
|
||||
|
||||
|
||||
/**
|
||||
* @file gpio.h
|
||||
* Class declaration for SPI helper files
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example of gpio.h class declaration for GPIO portability
|
||||
*
|
||||
* @defgroup Porting_GPIO Porting: GPIO
|
||||
*
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#ifndef GPIO_H
|
||||
#define GPIO_H
|
||||
|
||||
#include <avr/io.h>
|
||||
#include "gpio_helper.h"
|
||||
|
||||
class GPIO {
|
||||
public:
|
||||
/* Constants */
|
||||
static const int DIRECTION_OUT = 1;
|
||||
static const int DIRECTION_IN = 0;
|
||||
|
||||
static const int OUTPUT_HIGH = 1;
|
||||
static const int OUTPUT_LOW = 0;
|
||||
|
||||
GPIO();
|
||||
|
||||
/**
|
||||
* Similar to Arduino pinMode(pin,mode);
|
||||
* @param port
|
||||
* @param DDR
|
||||
*/
|
||||
static void open(int port, int DDR);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param port
|
||||
*/
|
||||
static void close(int port);
|
||||
|
||||
/**
|
||||
* Similar to Arduino digitalRead(pin);
|
||||
* @param port
|
||||
*/
|
||||
static int read(int port);
|
||||
|
||||
/**
|
||||
* Similar to Arduino digitalWrite(pin,state);
|
||||
* @param port
|
||||
* @param value
|
||||
*/
|
||||
static void write(int port, int value);
|
||||
|
||||
virtual ~GPIO();
|
||||
|
||||
};
|
||||
|
||||
#endif /* GPIO_H */
|
||||
/*@}*/
|
39
src/libs/RF24-master/utility/ATXMegaD3/gpio_helper.c
Normal file
39
src/libs/RF24-master/utility/ATXMegaD3/gpio_helper.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* gpio_helper.c
|
||||
*
|
||||
* Created: 22/1/2016 15:28:48
|
||||
* Author: akatran
|
||||
*/
|
||||
|
||||
#include "gpio_helper.h"
|
||||
|
||||
/**
|
||||
* Get the port corresponding in portnum. Default is PORTC.
|
||||
*/
|
||||
PORT_t* GPIO_getPort(int pinnum, uint8_t* pin_bm)
|
||||
//PORT_t * GPIO_getPort(int portnum)
|
||||
{
|
||||
PORT_t* port = &PORTC;
|
||||
if ((pinnum >= XMEGA_PORTA_PIN0) && (pinnum <= XMEGA_PORTA_PIN7)) {
|
||||
port = &PORTA;
|
||||
*pin_bm = (1 << pinnum);
|
||||
} else if ((pinnum >= XMEGA_PORTB_PIN0) && (pinnum <= XMEGA_PORTB_PIN7)) {
|
||||
port = &PORTB;
|
||||
*pin_bm = (1 << (pinnum - 8));
|
||||
} else if ((pinnum >= XMEGA_PORTC_PIN0) && (pinnum <= XMEGA_PORTC_PIN7)) {
|
||||
port = &PORTC;
|
||||
*pin_bm = (1 << (pinnum - 16));
|
||||
} else if ((pinnum >= XMEGA_PORTD_PIN0) && (pinnum <= XMEGA_PORTD_PIN7)) {
|
||||
port = &PORTD;
|
||||
*pin_bm = (1 << (pinnum - 24));
|
||||
} else if ((pinnum >= XMEGA_PORTE_PIN0) && (pinnum <= XMEGA_PORTE_PIN7)) {
|
||||
port = &PORTE;
|
||||
*pin_bm = (1 << (pinnum - 32));
|
||||
} else if ((pinnum >= XMEGA_PORTF_PIN0) && (pinnum <= XMEGA_PORTF_PIN7)) {
|
||||
port = &PORTF;
|
||||
*pin_bm = (1 << (pinnum - 40));
|
||||
}
|
||||
|
||||
return port;
|
||||
|
||||
}
|
86
src/libs/RF24-master/utility/ATXMegaD3/gpio_helper.h
Normal file
86
src/libs/RF24-master/utility/ATXMegaD3/gpio_helper.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* gpio_helper.h
|
||||
*
|
||||
* Created: 22/1/2016 15:29:12
|
||||
* Author: akatran
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GPIO_HELPER_H_
|
||||
#define GPIO_HELPER_H_
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Defines */
|
||||
|
||||
|
||||
#define XMEGA_PORTA_PIN0 0
|
||||
#define XMEGA_PORTA_PIN1 1
|
||||
#define XMEGA_PORTA_PIN2 2
|
||||
#define XMEGA_PORTA_PIN3 3
|
||||
#define XMEGA_PORTA_PIN4 4
|
||||
#define XMEGA_PORTA_PIN5 5
|
||||
#define XMEGA_PORTA_PIN6 6
|
||||
#define XMEGA_PORTA_PIN7 7
|
||||
|
||||
#define XMEGA_PORTB_PIN0 8
|
||||
#define XMEGA_PORTB_PIN1 9
|
||||
#define XMEGA_PORTB_PIN2 10
|
||||
#define XMEGA_PORTB_PIN3 11
|
||||
#define XMEGA_PORTB_PIN4 12
|
||||
#define XMEGA_PORTB_PIN5 13
|
||||
#define XMEGA_PORTB_PIN6 14
|
||||
#define XMEGA_PORTB_PIN7 15
|
||||
|
||||
#define XMEGA_PORTC_PIN0 16
|
||||
#define XMEGA_PORTC_PIN1 17
|
||||
#define XMEGA_PORTC_PIN2 18
|
||||
#define XMEGA_PORTC_PIN3 19
|
||||
#define XMEGA_PORTC_PIN4 20
|
||||
#define XMEGA_PORTC_PIN5 21
|
||||
#define XMEGA_PORTC_PIN6 22
|
||||
#define XMEGA_PORTC_PIN7 23
|
||||
|
||||
#define XMEGA_PORTD_PIN0 24
|
||||
#define XMEGA_PORTD_PIN1 25
|
||||
#define XMEGA_PORTD_PIN2 26
|
||||
#define XMEGA_PORTD_PIN3 27
|
||||
#define XMEGA_PORTD_PIN4 28
|
||||
#define XMEGA_PORTD_PIN5 29
|
||||
#define XMEGA_PORTD_PIN6 30
|
||||
#define XMEGA_PORTD_PIN7 31
|
||||
|
||||
#define XMEGA_PORTE_PIN0 32
|
||||
#define XMEGA_PORTE_PIN1 33
|
||||
#define XMEGA_PORTE_PIN2 34
|
||||
#define XMEGA_PORTE_PIN3 35
|
||||
#define XMEGA_PORTE_PIN4 36
|
||||
#define XMEGA_PORTE_PIN5 37
|
||||
#define XMEGA_PORTE_PIN6 38
|
||||
#define XMEGA_PORTE_PIN7 39
|
||||
|
||||
#define XMEGA_PORTF_PIN0 40
|
||||
#define XMEGA_PORTF_PIN1 41
|
||||
#define XMEGA_PORTF_PIN2 42
|
||||
#define XMEGA_PORTF_PIN3 43
|
||||
#define XMEGA_PORTF_PIN4 44
|
||||
#define XMEGA_PORTF_PIN5 45
|
||||
#define XMEGA_PORTF_PIN6 46
|
||||
#define XMEGA_PORTF_PIN7 47
|
||||
|
||||
#define XMEGA_SPI_PORT_C 20
|
||||
#define XMEGA_SPI_PORT_D 28
|
||||
|
||||
//void GPIO_getPort(int pinnum, PORT_t * port, uint8_t pin);
|
||||
//void GPIO_getPort(int pinnum, PORT_t * port, uint8_t * pin_bm);
|
||||
PORT_t* GPIO_getPort(int pinnum, uint8_t* pin_bm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GPIO_HELPER_H_ */
|
30
src/libs/RF24-master/utility/ATXMegaD3/includes.h
Normal file
30
src/libs/RF24-master/utility/ATXMegaD3/includes.h
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @file includes.h
|
||||
* Configuration defines for RF24/Linux
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example of includes.h for RF24 Linux portability
|
||||
*
|
||||
* @defgroup Porting_Includes Porting: Includes
|
||||
*
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __RF24_INCLUDES_H__
|
||||
#define __RF24_INCLUDES_H__
|
||||
|
||||
/**
|
||||
* Define a specific platform for this configuration
|
||||
*/
|
||||
// #define RF24_BBB
|
||||
|
||||
/**
|
||||
* Load the correct configuration for this platform
|
||||
*/
|
||||
//#include "BBB/RF24_arch_config.h"
|
||||
|
||||
#endif
|
||||
|
||||
/*@}*/
|
64
src/libs/RF24-master/utility/ATXMegaD3/spi.cpp
Normal file
64
src/libs/RF24-master/utility/ATXMegaD3/spi.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* spi.cpp
|
||||
*
|
||||
* Created: 20/1/2016 10:10:39
|
||||
* Author: akatran
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include "gpio_helper.h"
|
||||
#include "spi.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void SPI::begin(uint8_t _port)
|
||||
{
|
||||
if (_port == XMEGA_SPI_PORT_C) // Select SPI on PORTC
|
||||
{
|
||||
device = &SPIC;
|
||||
port = &PORTC;
|
||||
} else if (_port == XMEGA_SPI_PORT_D) // Select SPI on PORTD
|
||||
{
|
||||
device = &SPID;
|
||||
port = &PORTD;
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
uint8_t SPI::transfer(uint8_t tx_)
|
||||
{
|
||||
register8_t data;
|
||||
device->DATA = tx_;
|
||||
while (!(device->STATUS & (1 << 7))) {
|
||||
}
|
||||
data = device->DATA;
|
||||
//PORTF.OUT = data;
|
||||
return data;
|
||||
}
|
||||
|
||||
void SPI::init()
|
||||
{
|
||||
port->DIRCLR = SPI_MISO_bm;
|
||||
port->DIRSET = SPI_MOSI_bm | SPI_SCK_bm | SPI_SS_bm;
|
||||
|
||||
//device->CTRL = 0;
|
||||
device->CTRL = SPI_ENABLE_bm | SPI_MASTER_bm | SPI_MODE_0_gc | SPI_PRESCALER_DIV4_gc;
|
||||
device->INTCTRL = 0; //Disable interrupts
|
||||
|
||||
}
|
||||
|
||||
SPI::SPI()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SPI::~SPI()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void operator delete(void* p) // or delete(void *, std::size_t)
|
||||
{
|
||||
|
||||
}
|
88
src/libs/RF24-master/utility/ATXMegaD3/spi.h
Normal file
88
src/libs/RF24-master/utility/ATXMegaD3/spi.h
Normal file
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* @file spi.h
|
||||
* Class declaration for SPI helper files
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example of spi.h class declaration for SPI portability
|
||||
*
|
||||
* @defgroup Porting_SPI Porting: SPI
|
||||
*
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __XMEGASPI_H__
|
||||
#define __XMEGASPI_H__
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <stdint.h>
|
||||
//#include <string.h>
|
||||
//#include <unistd.h>
|
||||
//#include <stdio.h>
|
||||
//#include <stdlib.h>
|
||||
//#include <getopt.h>
|
||||
//#include <fcntl.h>
|
||||
//#include <sys/ioctl.h>
|
||||
//#include <inttypes.h>
|
||||
//#include <linux/types.h>
|
||||
//#include <linux/spi/spidev.h>
|
||||
|
||||
#define SPI_SS_bm (1<<4) /* SPI SS pin mask 4 */
|
||||
#define SPI_MOSI_bm (1<<5) /* SPI MOSI pin mask 5 */
|
||||
#define SPI_MISO_bm (1<<6) /* SPI MISO pin mask 6 */
|
||||
#define SPI_SCK_bm (1<<7) /* SPI SCK pin mask 7 */
|
||||
|
||||
using namespace std;
|
||||
|
||||
class SPI {
|
||||
public:
|
||||
|
||||
/**
|
||||
* SPI constructor
|
||||
*/
|
||||
SPI();
|
||||
|
||||
/**
|
||||
* Start SPI
|
||||
* @param port is the SPI port (XMEGA_SPI_PORT_C for SPI on PORTC, XMEGA_SPI_PORT_D on PORTD etc).
|
||||
*/
|
||||
void begin(uint8_t port);
|
||||
|
||||
/**
|
||||
* Transfer a single byte
|
||||
* @param tx_ Byte to send
|
||||
* @return Data returned via spi
|
||||
*/
|
||||
uint8_t transfer(uint8_t tx_);
|
||||
|
||||
/**
|
||||
* Transfer a buffer of data
|
||||
* @param tbuf Transmit buffer
|
||||
* @param rbuf Receive buffer
|
||||
* @param len Length of the data
|
||||
*/
|
||||
void transfernb(char* tbuf, char* rbuf, uint32_t len);
|
||||
|
||||
/**
|
||||
* Transfer a buffer of data without an rx buffer
|
||||
* @param buf Pointer to a buffer of data
|
||||
* @param len Length of the data
|
||||
*/
|
||||
void transfern(char* buf, uint32_t len);
|
||||
|
||||
virtual ~SPI();
|
||||
|
||||
private:
|
||||
|
||||
/** Default SPI device */
|
||||
SPI_t* device;
|
||||
/* Port of the SPI */
|
||||
PORT_t* port;
|
||||
|
||||
void init();
|
||||
};
|
||||
|
||||
#endif /*__XMEGASPI_H__*/
|
||||
|
||||
/*@}*/
|
35
src/libs/RF24-master/utility/Due/RF24_arch_config.h
Normal file
35
src/libs/RF24-master/utility/Due/RF24_arch_config.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
TMRh20 2015
|
||||
RF24 Configuration file for Arduino Due
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __RF24_ARCH_CONFIG_H__
|
||||
#define __RF24_ARCH_CONFIG_H__
|
||||
|
||||
/*** USER DEFINES: ***/
|
||||
//#define FAILURE_HANDLING
|
||||
//#define SERIAL_DEBUG
|
||||
//#define MINIMAL
|
||||
/**********************/
|
||||
#define rf24_max(a, b) (a>b?a:b)
|
||||
#define rf24_min(a, b) (a<b?a:b)
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#define _BV(x) (1<<(x))
|
||||
#define _SPI SPI
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
#define IF_SERIAL_DEBUG(x) ({x;})
|
||||
#else
|
||||
#define IF_SERIAL_DEBUG(x)
|
||||
#endif
|
||||
|
||||
#define printf_P printf
|
||||
#define strlen_P strlen
|
||||
#define PRIPSTR "%s"
|
||||
|
||||
#endif // __RF24_CONFIG_H__
|
||||
|
39
src/libs/RF24-master/utility/LittleWire/RF24_arch_config.h
Normal file
39
src/libs/RF24-master/utility/LittleWire/RF24_arch_config.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef __ARCH_CONFIG_H__
|
||||
#define __ARCH_CONFIG_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// Additional fixes for LittleWire
|
||||
#include <LittleWireSPI/littlewirespi.h>
|
||||
#include <LittleWireSPI/avr_fixes.h>
|
||||
|
||||
extern LittleWireSPI _SPI;
|
||||
|
||||
// GCC a Arduino Missing
|
||||
#define _BV(x) (1<<(x))
|
||||
#define pgm_read_word(p) (*(p))
|
||||
#define pgm_read_byte(p) (*(p))
|
||||
#define pgm_read_ptr(p) (*(p))
|
||||
|
||||
//typedef uint16_t prog_uint16_t;
|
||||
#define PSTR(x) (x)
|
||||
#define printf_P printf
|
||||
#define strlen_P strlen
|
||||
#define PROGMEM
|
||||
#define PRIPSTR "%s"
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
#define IF_SERIAL_DEBUG(x) ({x;})
|
||||
#else
|
||||
#define IF_SERIAL_DEBUG(x)
|
||||
#if defined(RF24_TINY)
|
||||
#define printf_P(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user