mirror of https://github.com/arendst/Tasmota.git
Merge pull request #7394 from Staars/nrf24_PR
BLE-bridge for certain Mijia-Bluetooth-sensors via NRF24L01
This commit is contained in:
commit
5489c91172
|
@ -0,0 +1,26 @@
|
|||
*.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/*.*
|
||||
.directory
|
||||
.idea
|
|
@ -0,0 +1 @@
|
|||
Try your best to follow the NASA C style http://homepages.inf.ed.ac.uk/dts/pm/Papers/nasa-c-style.pdf
|
File diff suppressed because it is too large
Load Diff
|
@ -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.
|
|
@ -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
|
||||
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"
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
**See http://tmrh20.github.io/RF24 for all documentation**
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,166 @@
|
|||
|
||||
/*
|
||||
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
|
||||
|
||||
/**********************/
|
||||
#define rf24_max(a,b) (a>b?a:b)
|
||||
#define rf24_min(a,b) (a<b?a:b)
|
||||
|
||||
#if defined (SPI_HAS_TRANSACTION) && !defined (SPI_UART) && !defined (SOFTSPI)
|
||||
#define RF24_SPI_TRANSACTIONS
|
||||
#endif // defined (SPI_HAS_TRANSACTION) && !defined (SPI_UART) && !defined (SOFTSPI)
|
||||
|
||||
//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__)
|
||||
#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>
|
||||
|
||||
// RF modules support 10 Mhz SPI bus speed
|
||||
const uint32_t RF24_SPI_SPEED = 10000000;
|
||||
|
||||
#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__)
|
||||
|
||||
#define _BV(x) (1<<(x))
|
||||
#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"
|
||||
|
||||
#elif defined (ESP32)
|
||||
#include <pgmspace.h>
|
||||
#define PRIPSTR "%s"
|
||||
|
||||
#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
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#endif // !defined (ARDUINO)
|
||||
|
||||
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 pgm_read_ptr(p) (*(p))
|
||||
#define PRIPSTR "%s"
|
||||
|
||||
#endif // !defined (ARDUINO) || defined (ESP_PLATFORM) || defined (__arm__) || defined (__ARDUINO_X86__) && !defined (XMEGA)
|
||||
#endif //Everything else
|
||||
|
||||
#endif // __RF24_CONFIG_H__
|
|
@ -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 /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="-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."
|
|
@ -0,0 +1,835 @@
|
|||
/* 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;
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
|
||||
/*
|
||||
* Getting Started example sketch for nRF24L01+ radios
|
||||
* This is a very basic example of how to send data from one node to another
|
||||
* Updated: Dec 2014 by TMRh20
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include "RF24.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;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("RF24/examples/GettingStarted"));
|
||||
Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
|
||||
/****************** 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
|
||||
boolean 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{
|
||||
unsigned long got_time; // Grab the response, compare, and send to debugging spew
|
||||
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"));
|
||||
}
|
||||
|
||||
// Try again 1s later
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************** Pong Back Role ***************************/
|
||||
|
||||
if ( role == 0 )
|
||||
{
|
||||
unsigned long got_time;
|
||||
|
||||
if( radio.available()){
|
||||
// Variable for the received timestamp
|
||||
while (radio.available()) { // While there is data ready
|
||||
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,138 @@
|
|||
/*
|
||||
Dec 2014 - TMRh20 - Updated
|
||||
Derived from examples by J. Coliz <maniacbug@ymail.com>
|
||||
*/
|
||||
/**
|
||||
* Example for efficient call-response using ack-payloads
|
||||
*
|
||||
* This example continues to make use of all the normal functionality of the radios including
|
||||
* the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
|
||||
* This allows very fast call-response communication, with the responding radio never having to
|
||||
* switch out of Primary Receiver mode to send back a payload, but having the option to switch to
|
||||
* primary transmitter if wanting to initiate communication instead of respond to a commmunication.
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include "RF24.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);
|
||||
/**********************************************************/
|
||||
// Topology
|
||||
byte addresses[][6] = {"1Node","2Node"}; // 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.
|
||||
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 = role_pong_back; // The role of the current running sketch
|
||||
|
||||
byte counter = 1; // A single byte to keep track of the data being sent back and forth
|
||||
|
||||
|
||||
void setup(){
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("RF24/examples/GettingStarted_CallResponse"));
|
||||
Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
|
||||
|
||||
// Setup and configure radio
|
||||
|
||||
radio.begin();
|
||||
|
||||
radio.enableAckPayload(); // Allow optional ack payloads
|
||||
radio.enableDynamicPayloads(); // Ack payloads are dynamic payloads
|
||||
|
||||
if(radioNumber){
|
||||
radio.openWritingPipe(addresses[1]); // Both radios listen on the same pipes by default, but opposite addresses
|
||||
radio.openReadingPipe(1,addresses[0]); // Open a reading pipe on address 0, pipe 1
|
||||
}else{
|
||||
radio.openWritingPipe(addresses[0]);
|
||||
radio.openReadingPipe(1,addresses[1]);
|
||||
}
|
||||
radio.startListening(); // Start listening
|
||||
|
||||
radio.writeAckPayload(1,&counter,1); // Pre-load an ack-paylod into the FIFO buffer for pipe 1
|
||||
//radio.printDetails();
|
||||
}
|
||||
|
||||
void loop(void) {
|
||||
|
||||
|
||||
/****************** Ping Out Role ***************************/
|
||||
|
||||
if (role == role_ping_out){ // Radio is in ping mode
|
||||
|
||||
byte gotByte; // Initialize a variable for the incoming response
|
||||
|
||||
radio.stopListening(); // First, stop listening so we can talk.
|
||||
Serial.print(F("Now sending ")); // Use a simple byte counter as payload
|
||||
Serial.println(counter);
|
||||
|
||||
unsigned long time = micros(); // Record the current microsecond count
|
||||
|
||||
if ( radio.write(&counter,1) ){ // Send the counter variable to the other radio
|
||||
if(!radio.available()){ // If nothing in the buffer, we got an ack but it is blank
|
||||
Serial.print(F("Got blank response. round-trip delay: "));
|
||||
Serial.print(micros()-time);
|
||||
Serial.println(F(" microseconds"));
|
||||
}else{
|
||||
while(radio.available() ){ // If an ack with payload was received
|
||||
radio.read( &gotByte, 1 ); // Read it, and display the response time
|
||||
unsigned long timer = micros();
|
||||
|
||||
Serial.print(F("Got response "));
|
||||
Serial.print(gotByte);
|
||||
Serial.print(F(" round-trip delay: "));
|
||||
Serial.print(timer-time);
|
||||
Serial.println(F(" microseconds"));
|
||||
counter++; // Increment the counter variable
|
||||
}
|
||||
}
|
||||
|
||||
}else{ Serial.println(F("Sending failed.")); } // If no ack response, sending failed
|
||||
|
||||
delay(1000); // Try again later
|
||||
}
|
||||
|
||||
|
||||
/****************** Pong Back Role ***************************/
|
||||
|
||||
if ( role == role_pong_back ) {
|
||||
byte pipeNo, gotByte; // Declare variables for the pipe and the byte received
|
||||
while( radio.available(&pipeNo)){ // Read all available payloads
|
||||
radio.read( &gotByte, 1 );
|
||||
// Since this is a call-response. Respond directly with an ack payload.
|
||||
gotByte += 1; // Ack payloads are much more efficient than switching to transmit mode to respond to a call
|
||||
radio.writeAckPayload(pipeNo,&gotByte, 1 ); // This can be commented out to send empty payloads.
|
||||
Serial.print(F("Loaded next response "));
|
||||
Serial.println(gotByte);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************** Change Roles via Serial Commands ***************************/
|
||||
|
||||
if ( Serial.available() )
|
||||
{
|
||||
char c = toupper(Serial.read());
|
||||
if ( c == 'T' && role == role_pong_back ){
|
||||
Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
|
||||
role = role_ping_out; // Become the primary transmitter (ping out)
|
||||
counter = 1;
|
||||
}else
|
||||
if ( c == 'R' && role == role_ping_out ){
|
||||
Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
|
||||
role = role_pong_back; // Become the primary receiver (pong back)
|
||||
radio.startListening();
|
||||
counter = 1;
|
||||
radio.writeAckPayload(1,&counter,1);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
|
||||
/*
|
||||
* Getting Started example sketch for nRF24L01+ radios
|
||||
* This is an example of how to send data from one node to another using data structures
|
||||
* Updated: Dec 2014 by TMRh20
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include "RF24.h"
|
||||
|
||||
byte addresses[][6] = {"1Node","2Node"};
|
||||
|
||||
|
||||
/****************** User Config ***************************/
|
||||
/*** Set this radio as radio number 0 or 1 ***/
|
||||
bool radioNumber = 1;
|
||||
|
||||
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7 & 8 */
|
||||
RF24 radio(7,8);
|
||||
/**********************************************************/
|
||||
|
||||
|
||||
// Used to control whether this node is sending or receiving
|
||||
bool role = 0;
|
||||
|
||||
/**
|
||||
* Create a data structure for transmitting and receiving data
|
||||
* This allows many variables to be easily sent and received in a single transmission
|
||||
* See http://www.cplusplus.com/doc/tutorial/structures/
|
||||
*/
|
||||
struct dataStruct{
|
||||
unsigned long _micros;
|
||||
float value;
|
||||
}myData;
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("RF24/examples/GettingStarted_HandlingData"));
|
||||
Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
myData.value = 1.22;
|
||||
// Start the radio listening for data
|
||||
radio.startListening();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void loop() {
|
||||
|
||||
|
||||
/****************** Ping Out Role ***************************/
|
||||
if (role == 1) {
|
||||
|
||||
radio.stopListening(); // First, stop listening so we can talk.
|
||||
|
||||
|
||||
Serial.println(F("Now sending"));
|
||||
|
||||
myData._micros = micros();
|
||||
if (!radio.write( &myData, sizeof(myData) )){
|
||||
Serial.println(F("failed"));
|
||||
}
|
||||
|
||||
radio.startListening(); // Now, continue listening
|
||||
|
||||
unsigned long started_waiting_at = micros(); // Set up a timeout period, get the current microseconds
|
||||
boolean 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
|
||||
radio.read( &myData, sizeof(myData) );
|
||||
unsigned long time = micros();
|
||||
|
||||
// Spew it
|
||||
Serial.print(F("Sent "));
|
||||
Serial.print(time);
|
||||
Serial.print(F(", Got response "));
|
||||
Serial.print(myData._micros);
|
||||
Serial.print(F(", Round-trip delay "));
|
||||
Serial.print(time-myData._micros);
|
||||
Serial.print(F(" microseconds Value "));
|
||||
Serial.println(myData.value);
|
||||
}
|
||||
|
||||
// Try again 1s later
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************** Pong Back Role ***************************/
|
||||
|
||||
if ( role == 0 )
|
||||
{
|
||||
|
||||
if( radio.available()){
|
||||
// Variable for the received timestamp
|
||||
while (radio.available()) { // While there is data ready
|
||||
radio.read( &myData, sizeof(myData) ); // Get the payload
|
||||
}
|
||||
|
||||
radio.stopListening(); // First, stop listening so we can talk
|
||||
myData.value += 0.01; // Increment the float value
|
||||
radio.write( &myData, sizeof(myData) ); // Send the final one back.
|
||||
radio.startListening(); // Now, resume listening so we catch the next packets.
|
||||
Serial.print(F("Sent response "));
|
||||
Serial.print(myData._micros);
|
||||
Serial.print(F(" : "));
|
||||
Serial.println(myData.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/****************** Change Roles via Serial Commands ***************************/
|
||||
|
||||
if ( Serial.available() )
|
||||
{
|
||||
char c = toupper(Serial.read());
|
||||
if ( c == 'T' && role == 0 ){
|
||||
Serial.print(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,218 @@
|
|||
|
||||
/*
|
||||
* 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
|
||||
boolean 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{
|
||||
unsigned long got_time; // Grab the response, compare, and send to debugging spew
|
||||
|
||||
//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"));
|
||||
}
|
||||
|
||||
// Try again 1s later
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************** Pong Back Role ***************************/
|
||||
|
||||
if ( role == 0 )
|
||||
{
|
||||
unsigned long got_time;
|
||||
|
||||
if( radio.available()){
|
||||
|
||||
uint32_t failTimer = millis(); // Variable for the received timestamp
|
||||
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,149 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
/*
|
||||
General Data Transfer Rate Test
|
||||
|
||||
This example demonstrates basic data transfer functionality with the
|
||||
updated library. This example will display the transfer rates acheived
|
||||
using the slower form of high-speed transfer using blocking-writes.
|
||||
*/
|
||||
|
||||
|
||||
#include <SPI.h>
|
||||
#include "RF24.h"
|
||||
|
||||
/************* USER Configuration *****************************/
|
||||
// Hardware configuration
|
||||
RF24 radio(7,8); // Set up nRF24L01 radio on SPI bus plus pins 7 & 8
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
const uint64_t pipes[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; // Radio pipe addresses for the 2 nodes to communicate.
|
||||
|
||||
byte data[32]; //Data buffer for testing data transfer speeds
|
||||
|
||||
unsigned long counter, rxTimer; //Counter and timer for keeping track transfer info
|
||||
unsigned long startTime, stopTime;
|
||||
bool TX=1,RX=0,role=0;
|
||||
|
||||
void setup(void) {
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
radio.begin(); // Setup and configure rf radio
|
||||
radio.setChannel(1);
|
||||
radio.setPALevel(RF24_PA_MAX); // If you want to save power use "RF24_PA_MIN" but keep in mind that reduces the module's range
|
||||
radio.setDataRate(RF24_1MBPS);
|
||||
radio.setAutoAck(1); // Ensure autoACK is enabled
|
||||
radio.setRetries(2,15); // Optionally, increase the delay between retries & # of retries
|
||||
|
||||
radio.setCRCLength(RF24_CRC_8); // Use 8-bit CRC for performance
|
||||
radio.openWritingPipe(pipes[0]);
|
||||
radio.openReadingPipe(1,pipes[1]);
|
||||
|
||||
radio.startListening(); // Start listening
|
||||
radio.printDetails(); // Dump the configuration of the rf unit for debugging
|
||||
|
||||
Serial.println(F("\n\rRF24/examples/Transfer/"));
|
||||
Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
|
||||
|
||||
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);
|
||||
|
||||
Serial.println(F("Initiating Basic Data Transfer"));
|
||||
|
||||
|
||||
unsigned long cycles = 10000; //Change this to a higher or lower number.
|
||||
|
||||
startTime = millis();
|
||||
unsigned long pauseTime = millis();
|
||||
|
||||
for(int 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.writeFast(&data,32)){ //Write to the FIFO buffers
|
||||
counter++; //Keep count of failed payloads
|
||||
}
|
||||
|
||||
//This is only required when NO ACK ( enableAutoAck(0) ) payloads are used
|
||||
// if(millis() - pauseTime > 3){
|
||||
// pauseTime = millis();
|
||||
// radio.txStandBy(); // Need to drop out of TX mode every 4ms if sending a steady stream of multicast data
|
||||
// //delayMicroseconds(130); // This gives the PLL time to sync back up
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
stopTime = millis();
|
||||
//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(!radio.txStandBy()){ counter+=3; } //Standby, block only until FIFO empty or auto-retry timeout. Flush TX FIFO if failed
|
||||
//radio.txStandBy(1000); //Standby, using extended timeout period of 1 second
|
||||
|
||||
float numBytes = cycles*32;
|
||||
float rate = numBytes / (stopTime - startTime);
|
||||
|
||||
Serial.print("Transfer complete at "); Serial.print(rate); Serial.println(" KB/s");
|
||||
Serial.print(counter); Serial.print(" of "); Serial.print(cycles); Serial.println(" Packets Failed to Send");
|
||||
counter = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(role == RX){
|
||||
while(radio.available()){
|
||||
radio.read(&data,32);
|
||||
counter++;
|
||||
}
|
||||
if(millis() - rxTimer > 1000){
|
||||
rxTimer = millis();
|
||||
unsigned long numBytes = counter*32;
|
||||
Serial.print(F("Rate: "));
|
||||
//Prevent dividing into 0, which will cause issues over a period of time
|
||||
Serial.println(numBytes > 0 ? numBytes/1000.0:0);
|
||||
Serial.print(F("Payload Count: "));
|
||||
Serial.println(counter);
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Change roles
|
||||
//
|
||||
|
||||
if ( Serial.available() )
|
||||
{
|
||||
char c = toupper(Serial.read());
|
||||
if ( c == 'T' && role == RX )
|
||||
{
|
||||
Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
|
||||
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();
|
||||
Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
|
||||
role = RX; // Become the primary receiver (pong back)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
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(int 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");
|
||||
printf("Payload Count: %d \n\r", 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,206 @@
|
|||
PROJECT_NAME = $(PWD:B) ;
|
||||
PROJECT_DIR = . ;
|
||||
PROJECT_LIBS = SPI 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 ;
|
||||
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 = $(HOME)/Source/Arduino/libraries ;
|
||||
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 ;
|
||||
CTUNING = -ffunction-sections -fdata-sections ;
|
||||
CXXTUNING = -fno-exceptions -fno-strict-aliasing ;
|
||||
CFLAGS = -Os -Wall -Wextra -mmcu=$(MCU) $(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) : [^.]* ] ;
|
||||
|
||||
# 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) $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp ] ;
|
||||
|
||||
# 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 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 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 .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 ;
|
||||
|
|
@ -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,219 @@
|
|||
# (1) Project Information
|
||||
|
||||
PROJECT_LIBS = RF24 SPI ;
|
||||
PROJECT_DIRS = $(PWD) ;
|
||||
|
||||
# (2) Board Information
|
||||
|
||||
UPLOAD_PROTOCOL ?= stk500v1 ;
|
||||
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 $(<) : libs core ;
|
||||
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,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,182 @@
|
|||
MCU = cortex-m3 ;
|
||||
CHIP = STM32F103ZE ;
|
||||
BOARD = maple_native ;
|
||||
|
||||
#CHIP = at91sam3u4 ;
|
||||
#BOARD = sam3u-ek ;
|
||||
|
||||
if ! $(TOOLSET)
|
||||
{
|
||||
TOOLSET = devkit ;
|
||||
Echo "Assuming TOOLSET=devkit" ;
|
||||
}
|
||||
|
||||
if $(TOOLSET) = yagarto
|
||||
{
|
||||
TOOLS_PATH = ~/Source/yagarto-4.6.2/bin ;
|
||||
TOOLS_ARCH = arm-none-eabi- ;
|
||||
}
|
||||
if $(TOOLSET) = yagarto-install
|
||||
{
|
||||
TOOLS_PATH = ~/Source/yagarto/install/bin ;
|
||||
TOOLS_ARCH = arm-none-eabi- ;
|
||||
}
|
||||
else if $(TOOLSET) = devkit
|
||||
{
|
||||
TOOLS_PATH = /opt/devkitARM/bin ;
|
||||
TOOLS_ARCH = arm-eabi- ;
|
||||
}
|
||||
else if $(TOOLSET) = maple
|
||||
{
|
||||
TOOLS_PATH = /opt/Maple/Resources/Java/hardware/tools/arm/bin ;
|
||||
TOOLS_ARCH = arm-none-eabi- ;
|
||||
}
|
||||
else if $(TOOLSET) = ports
|
||||
{
|
||||
TOOLS_PATH = /opt/local/bin ;
|
||||
TOOLS_ARCH = arm-none-eabi- ;
|
||||
}
|
||||
|
||||
CC = $(TOOLS_PATH)/$(TOOLS_ARCH)gcc ;
|
||||
C++ = $(TOOLS_PATH)/$(TOOLS_ARCH)g++ ;
|
||||
AS = $(TOOLS_PATH)/$(TOOLS_ARCH)gcc -c ;
|
||||
LINK = $(TOOLS_PATH)/$(TOOLS_ARCH)g++ ;
|
||||
OBJCOPY = $(TOOLS_PATH)/$(TOOLS_ARCH)objcopy ;
|
||||
DFU = dfu-util ;
|
||||
|
||||
DEFINES += VECT_TAB_FLASH BOARD_$(BOARD) MCU_$(CHIP) ERROR_LED_PORT=GPIOC ERROR_LED_PIN=15 STM32_HIGH_DENSITY MAPLE_IDE ;
|
||||
OPTIM = -Os ;
|
||||
MFLAGS = cpu=$(MCU) thumb arch=armv7-m ;
|
||||
CCFLAGS = -Wall -m$(MFLAGS) -g -nostdlib -ffunction-sections -fdata-sections -Wl,--gc-sections ;
|
||||
C++FLAGS = $(CCFLAGS) -fno-rtti -fno-exceptions ;
|
||||
LINKFLAGS += -m$(MFLAGS) -Xlinker --gc-sections ;
|
||||
DFUFLAGS = -a1 -d 0x1eaf:0x0003 -R ;
|
||||
|
||||
MAPLE_DIR = $(HOME)/Source/SAM3U/libmaple ;
|
||||
MAPLE_LIBS = Servo LiquidCrystal Wire FreeRTOS ;
|
||||
MAPLE_SUBDIRS = wirish wirish/comm wirish/boards libmaple libmaple/usb libmaple/usb/usb_lib ;
|
||||
|
||||
SKETCH_DIR = $(HOME)/Source/Arduino ;
|
||||
SKETCH_LIBS = RF24 ;
|
||||
|
||||
MODULE_DIRS = . $(MAPLE_DIR)/$(MAPLE_SUBDIRS) $(MAPLE_DIR)/libraries/$(MAPLE_LIBS) $(SKETCH_DIR)/libraries/$(SKETCH_LIBS) ;
|
||||
HDRS = $(MODULE_DIRS) ;
|
||||
LOCATE_TARGET = out/$(TOOLSET) ;
|
||||
LOCATE_SOURCE = $(LOCATE_TARGET) ;
|
||||
|
||||
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 Hex
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
MakeLocate $(<) : $(LOCATE_TARGET) ;
|
||||
Depends hex : $(<) ;
|
||||
Clean clean : $(<) ;
|
||||
}
|
||||
|
||||
actions Hex
|
||||
{
|
||||
$(OBJCOPY) -O ihex $(>) $(<)
|
||||
}
|
||||
|
||||
rule Binary
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
MakeLocate $(<) : $(LOCATE_TARGET) ;
|
||||
Depends binary : $(<) ;
|
||||
Clean clean : $(<) ;
|
||||
}
|
||||
|
||||
actions Binary
|
||||
{
|
||||
$(OBJCOPY) -O binary $(>) $(<)
|
||||
}
|
||||
|
||||
rule UserObject
|
||||
{
|
||||
switch $(>:S)
|
||||
{
|
||||
case .S : As $(<) : $(>) ;
|
||||
case .ino : C++Pde $(<) : $(>) ;
|
||||
case .pde : C++Pde $(<) : $(>) ;
|
||||
}
|
||||
}
|
||||
|
||||
rule Upload
|
||||
{
|
||||
Depends up : $(<) ;
|
||||
NotFile up ;
|
||||
Always $(<) ;
|
||||
Always up ;
|
||||
}
|
||||
|
||||
actions Upload
|
||||
{
|
||||
$(DFU) $(DFUFLAGS) -D $(<)
|
||||
}
|
||||
|
||||
# Override base objects rule, so all output can go in the output dir
|
||||
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) ;
|
||||
}
|
||||
}
|
||||
|
||||
# Override base main rule, so all output can go in the output dir
|
||||
rule Main
|
||||
{
|
||||
MainFromObjects $(<) : $(>:B)$(SUFOBJ) ;
|
||||
Objects $(>) ;
|
||||
}
|
||||
|
||||
# Modules
|
||||
MODULES = [ GLOB $(MODULE_DIRS) : *.pde *.c *.cpp *.S ] ;
|
||||
|
||||
# Main output executable
|
||||
MAIN = $(PWD:B).elf ;
|
||||
|
||||
# Linker script
|
||||
LINK_DIR = $(MAPLE_DIR)/support/ld ;
|
||||
LINKSCRIPT = $(LINK_DIR)/$(BOARD)/flash.ld ;
|
||||
|
||||
# Bring in the map and link script
|
||||
LINKFLAGS += -Wl,-Map=$(LOCATE_TARGET)/$(MAIN:B).map -T$(LINKSCRIPT) -L$(LINK_DIR) ;
|
||||
|
||||
Main $(MAIN) : $(MODULES) ;
|
||||
Binary $(MAIN:B).bin : $(MAIN) ;
|
||||
Upload $(MAIN:B).bin ;
|
|
@ -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 @@
|
|||
Note: These examples may have not been maintained with library updates, and are provided as-is for reference purposes.
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
// March 2014 - TMRh20 - Updated along with High Speed RF24 Library fork
|
||||
// Parts derived from examples by J. Coliz <maniacbug@ymail.com>
|
||||
*/
|
||||
/**
|
||||
* Example for efficient call-response using ack-payloads
|
||||
*
|
||||
* This example continues to make use of all the normal functionality of the radios including
|
||||
* the auto-ack and auto-retry features, but allows ack-payloads to be written optionally as well.
|
||||
* This allows very fast call-response communication, with the responding radio never having to
|
||||
* switch out of Primary Receiver mode to send back a payload, but having the option to if wanting
|
||||
* to initiate communication instead of respond to a commmunication.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <SPI.h>
|
||||
#include "nRF24L01.h"
|
||||
#include "RF24.h"
|
||||
#include "printf.h"
|
||||
|
||||
// Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7 & 8
|
||||
RF24 radio(7,8);
|
||||
|
||||
// Topology
|
||||
const uint64_t pipes[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; // 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.
|
||||
|
||||
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 = role_pong_back; // The role of the current running sketch
|
||||
|
||||
// A single byte to keep track of the data being sent back and forth
|
||||
byte counter = 1;
|
||||
|
||||
void setup(){
|
||||
|
||||
Serial.begin(115200);
|
||||
printf_begin();
|
||||
Serial.print(F("\n\rRF24/examples/pingpair_ack/\n\rROLE: "));
|
||||
Serial.println(role_friendly_name[role]);
|
||||
Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));
|
||||
|
||||
// Setup and configure rf radio
|
||||
|
||||
radio.begin();
|
||||
radio.setAutoAck(1); // Ensure autoACK is enabled
|
||||
radio.enableAckPayload(); // Allow optional ack payloads
|
||||
radio.setRetries(0,15); // Smallest time between retries, max no. of retries
|
||||
radio.setPayloadSize(1); // Here we are sending 1-byte payloads to test the call-response speed
|
||||
radio.openWritingPipe(pipes[1]); // Both radios listen on the same pipes by default, and switch when writing
|
||||
radio.openReadingPipe(1,pipes[0]);
|
||||
radio.startListening(); // Start listening
|
||||
radio.printDetails(); // Dump the configuration of the rf unit for debugging
|
||||
}
|
||||
|
||||
void loop(void) {
|
||||
|
||||
if (role == role_ping_out){
|
||||
|
||||
radio.stopListening(); // First, stop listening so we can talk.
|
||||
|
||||
printf("Now sending %d as payload. ",counter);
|
||||
byte gotByte;
|
||||
unsigned long time = micros(); // Take the time, and send it. This will block until complete
|
||||
//Called when STANDBY-I mode is engaged (User is finished sending)
|
||||
if (!radio.write( &counter, 1 )){
|
||||
Serial.println(F("failed."));
|
||||
}else{
|
||||
|
||||
if(!radio.available()){
|
||||
Serial.println(F("Blank Payload Received."));
|
||||
}else{
|
||||
while(radio.available() ){
|
||||
unsigned long tim = micros();
|
||||
radio.read( &gotByte, 1 );
|
||||
printf("Got response %d, round-trip delay: %lu microseconds\n\r",gotByte,tim-time);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Try again later
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// Pong back role. Receive each packet, dump it out, and send it back
|
||||
|
||||
if ( role == role_pong_back ) {
|
||||
byte pipeNo;
|
||||
byte gotByte; // Dump the payloads until we've gotten everything
|
||||
while( radio.available(&pipeNo)){
|
||||
radio.read( &gotByte, 1 );
|
||||
radio.writeAckPayload(pipeNo,&gotByte, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
// Change roles
|
||||
|
||||
if ( Serial.available() )
|
||||
{
|
||||
char c = toupper(Serial.read());
|
||||
if ( c == 'T' && role == role_pong_back )
|
||||
{
|
||||
Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
|
||||
|
||||
role = role_ping_out; // Become the primary transmitter (ping out)
|
||||
radio.openWritingPipe(pipes[0]);
|
||||
radio.openReadingPipe(1,pipes[1]);
|
||||
}
|
||||
else if ( c == 'R' && role == role_ping_out )
|
||||
{
|
||||
Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
|
||||
|
||||
role = role_pong_back; // Become the primary receiver (pong back)
|
||||
radio.openWritingPipe(pipes[1]);
|
||||
radio.openReadingPipe(1,pipes[0]);
|
||||
radio.startListening();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,206 @@
|
|||
PROJECT_NAME = $(PWD:B) ;
|
||||
PROJECT_DIR = . ;
|
||||
PROJECT_LIBS = SPI 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 ;
|
||||
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 = $(HOME)/Source/Arduino/libraries ;
|
||||
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 ;
|
||||
CTUNING = -ffunction-sections -fdata-sections ;
|
||||
CXXTUNING = -fno-exceptions -fno-strict-aliasing ;
|
||||
CFLAGS = -Os -Wall -Wextra -mmcu=$(MCU) $(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) : [^.]* ] ;
|
||||
|
||||
# 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) $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp ] ;
|
||||
|
||||
# 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 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 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 .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 ;
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
//
|
||||
// Hardware configuration
|
||||
//
|
||||
|
||||
// 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;
|
||||
|
||||
//
|
||||
// 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;
|
||||
|
||||
//
|
||||
// Payload
|
||||
//
|
||||
|
||||
const int min_payload_size = 4;
|
||||
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)
|
||||
{
|
||||
//
|
||||
// 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_dyn/"));
|
||||
Serial.print(F("ROLE: "));
|
||||
Serial.println(role_friendly_name[role]);
|
||||
|
||||
//
|
||||
// Setup and configure rf radio
|
||||
//
|
||||
|
||||
radio.begin();
|
||||
|
||||
// enable dynamic payloads
|
||||
radio.enableDynamicPayloads();
|
||||
|
||||
// optionally, increase the delay between retries & # of retries
|
||||
radio.setRetries(5,15);
|
||||
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
// 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 );
|
||||
|
||||
// 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();
|
||||
|
||||
// If a corrupt dynamic payload is received, it will be flushed
|
||||
if(!len){
|
||||
return;
|
||||
}
|
||||
|
||||
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(100);
|
||||
}
|
||||
|
||||
//
|
||||
// Pong back role. Receive each packet, dump it out, and send it back
|
||||
//
|
||||
|
||||
if ( role == role_pong_back )
|
||||
{
|
||||
// if there is data ready
|
||||
while ( radio.available() )
|
||||
{
|
||||
|
||||
// Fetch the payload, and see if this was the last one.
|
||||
uint8_t len = radio.getDynamicPayloadSize();
|
||||
|
||||
// If a corrupt dynamic payload is received, it will be flushed
|
||||
if(!len){
|
||||
continue;
|
||||
}
|
||||
|
||||
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 );
|
||||
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,143 @@
|
|||
/*
|
||||
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
|
||||
|
||||
const short role_pin = 5; // sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver
|
||||
// Leave open to be the 'ping' transmitter
|
||||
|
||||
// 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 hardware itself specifies
|
||||
// which node it is.
|
||||
// This is done through the role_pin
|
||||
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
|
||||
|
||||
static uint32_t message_count = 0;
|
||||
|
||||
|
||||
/********************** Setup *********************/
|
||||
|
||||
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 address pin, establish our role
|
||||
role = role_sender;
|
||||
else
|
||||
role = role_receiver;
|
||||
|
||||
|
||||
Serial.begin(115200);
|
||||
printf_begin();
|
||||
Serial.print(F("\n\rRF24/examples/pingpair_irq\n\rROLE: "));
|
||||
Serial.println(role_friendly_name[role]);
|
||||
|
||||
// Setup and configure rf radio
|
||||
radio.begin();
|
||||
//radio.setPALevel(RF24_PA_LOW);
|
||||
radio.enableAckPayload(); // We will be using the Ack Payload feature, so please enable it
|
||||
radio.enableDynamicPayloads(); // Ack payloads are dynamic payloads
|
||||
// Open pipes to other node for communication
|
||||
if ( role == role_sender ) { // This simple sketch opens a pipe on a single address for these two nodes to
|
||||
radio.openWritingPipe(address[0]); // communicate back and forth. One listens on it, the other talks to it.
|
||||
radio.openReadingPipe(1,address[1]);
|
||||
}else{
|
||||
radio.openWritingPipe(address[1]);
|
||||
radio.openReadingPipe(1,address[0]);
|
||||
radio.startListening();
|
||||
radio.writeAckPayload( 1, &message_count, sizeof(message_count) ); // Add an ack packet for the next time around. This is a simple
|
||||
++message_count;
|
||||
}
|
||||
radio.printDetails(); // Dump the configuration of the rf unit for debugging
|
||||
delay(50);
|
||||
attachInterrupt(0, check_radio, LOW); // Attach interrupt handler to interrupt #0 (using pin 2) on BOTH the sender and receiver
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************** Main Loop *********************/
|
||||
void loop() {
|
||||
|
||||
|
||||
if (role == role_sender) { // Sender role. Repeatedly send the current time
|
||||
unsigned long time = millis(); // Take the time, and send it.
|
||||
Serial.print(F("Now sending "));
|
||||
Serial.println(time);
|
||||
radio.startWrite( &time, sizeof(unsigned long) ,0);
|
||||
delay(2000); // Try again soon
|
||||
}
|
||||
|
||||
|
||||
if(role == role_receiver){ // Receiver does nothing except in IRQ
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************** Interrupt *********************/
|
||||
|
||||
void check_radio(void) // Receiver role: Does nothing! All the work is in IRQ
|
||||
{
|
||||
|
||||
bool tx,fail,rx;
|
||||
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?
|
||||
|
||||
if ( role == role_sender ) { // If we're the sender, we've received an ack payload
|
||||
radio.read(&message_count,sizeof(message_count));
|
||||
Serial.print(F("Ack: "));
|
||||
Serial.println(message_count);
|
||||
}
|
||||
|
||||
|
||||
if ( role == role_receiver ) { // If we're the receiver, we've received a time message
|
||||
static unsigned long got_time; // Get this payload and dump it
|
||||
radio.read( &got_time, sizeof(got_time) );
|
||||
Serial.print(F("Got payload "));
|
||||
Serial.println(got_time);
|
||||
radio.writeAckPayload( 1, &message_count, sizeof(message_count) ); // Add an ack packet for the next time around. This is a simple
|
||||
++message_count; // packet counter
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
Created Dec 2014 - TMRh20
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example of using interrupts
|
||||
*
|
||||
* This is a very simple example of using two devices to communicate using interrupts.
|
||||
* With multiple devices, each device would need to have a separate reading pipe
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include "RF24.h"
|
||||
#include <printf.h>
|
||||
|
||||
// Hardware configuration
|
||||
// Set up nRF24L01 radio on SPI bus plus pins 7 & 8
|
||||
RF24 radio(7,8);
|
||||
|
||||
// Use the same address for both devices
|
||||
uint8_t address[] = { "radio" };
|
||||
|
||||
// Simple messages to represent a 'ping' and 'pong'
|
||||
uint8_t ping = 111;
|
||||
uint8_t pong = 222;
|
||||
|
||||
volatile uint32_t round_trip_timer = 0;
|
||||
|
||||
|
||||
/********************** Setup *********************/
|
||||
|
||||
void setup(){
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("Simple pingpair example"));
|
||||
Serial.println(F("Send a 'T' via Serial to transmit a single 'ping' "));
|
||||
//printf_begin();
|
||||
|
||||
// Setup and configure rf radio
|
||||
radio.begin();
|
||||
|
||||
// Use dynamic payloads to improve response time
|
||||
radio.enableDynamicPayloads();
|
||||
radio.openWritingPipe(address); // communicate back and forth. One listens on it, the other talks to it.
|
||||
radio.openReadingPipe(1,address);
|
||||
radio.startListening();
|
||||
|
||||
//radio.printDetails(); // Dump the configuration of the rf unit for debugging
|
||||
|
||||
attachInterrupt(0, check_radio, LOW); // Attach interrupt handler to interrupt #0 (using pin 2) on BOTH the sender and receiver
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************** Main Loop *********************/
|
||||
void loop() {
|
||||
|
||||
if(Serial.available()){
|
||||
switch(toupper(Serial.read())){
|
||||
case 'T':
|
||||
// Only allow 1 transmission per 45ms to prevent overlapping IRQ/reads/writes
|
||||
// Default retries = 5,15 = ~20ms per transmission max
|
||||
while(micros() - round_trip_timer < 45000){
|
||||
//delay between writes
|
||||
}
|
||||
Serial.print(F("Sending Ping"));
|
||||
radio.stopListening();
|
||||
round_trip_timer = micros();
|
||||
radio.startWrite( &ping, sizeof(uint8_t),0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************** Interrupt *********************/
|
||||
|
||||
void check_radio(void) // Receiver role: Does nothing! All the work is in IRQ
|
||||
{
|
||||
|
||||
bool tx,fail,rx;
|
||||
radio.whatHappened(tx,fail,rx); // What happened?
|
||||
|
||||
|
||||
// If data is available, handle it accordingly
|
||||
if ( rx ){
|
||||
|
||||
if(radio.getDynamicPayloadSize() < 1){
|
||||
// Corrupt payload has been flushed
|
||||
return;
|
||||
}
|
||||
// Read in the data
|
||||
uint8_t received;
|
||||
radio.read(&received,sizeof(received));
|
||||
|
||||
// If this is a ping, send back a pong
|
||||
if(received == ping){
|
||||
radio.stopListening();
|
||||
// Normal delay will not work here, so cycle through some no-operations (16nops @16mhz = 1us delay)
|
||||
for(uint32_t i=0; i<130;i++){
|
||||
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||
}
|
||||
radio.startWrite(&pong,sizeof(pong),0);
|
||||
Serial.print("pong");
|
||||
}else
|
||||
// If this is a pong, get the current micros()
|
||||
if(received == pong){
|
||||
round_trip_timer = micros() - round_trip_timer;
|
||||
Serial.print(F("Received Pong, Round Trip Time: "));
|
||||
Serial.println(round_trip_timer);
|
||||
}
|
||||
}
|
||||
|
||||
// Start listening if transmission is complete
|
||||
if( tx || fail ){
|
||||
radio.startListening();
|
||||
Serial.println(tx ? F(":OK") : F(":Fail"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,206 @@
|
|||
PROJECT_NAME = $(PWD:B) ;
|
||||
PROJECT_DIR = . ;
|
||||
PROJECT_LIBS = SPI 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 ;
|
||||
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 = $(HOME)/Source/Arduino/libraries ;
|
||||
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 ;
|
||||
CTUNING = -ffunction-sections -fdata-sections ;
|
||||
CXXTUNING = -fno-exceptions -fno-strict-aliasing ;
|
||||
CFLAGS = -Os -Wall -Wextra -mmcu=$(MCU) $(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) : [^.]* ] ;
|
||||
|
||||
# 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) $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp ] ;
|
||||
|
||||
# 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 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 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 .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 ;
|
||||
|
|
@ -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(8,9);
|
||||
|
||||
// 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 = 7;
|
||||
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,101 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
rf24ping85.ino by tong67 ( https://github.com/tong67 )
|
||||
This is an example of how to use the RF24 class to communicate with ATtiny85 and other node.
|
||||
Write this sketch to an ATtiny85. It will act like the 'transmit' mode of GettingStarted.ino
|
||||
Write GettingStarted.ino sketch to UNO (or other board or RPi) and put the node in 'receiver' mode.
|
||||
The ATtiny85 will transmit a counting number every second starting from 1.
|
||||
The ATtiny85 uses the tiny-core by CodingBadly (https://code.google.com/p/arduino-tiny/)
|
||||
When direct use of 3v3 does not work (UNO boards have bad 3v3 line) use 5v with LED (1.8V ~ 2.2V drop)
|
||||
For low power consumption solutions floating pins (SCK and MOSI) should be pulled high or low with eg. 10K
|
||||
|
||||
** Hardware configuration **
|
||||
ATtiny25/45/85 Pin map with CE_PIN 3 and CSN_PIN 4
|
||||
+-\/-+
|
||||
NC PB5 1|o |8 Vcc --- nRF24L01 VCC, pin2 --- LED --- 5V
|
||||
nRF24L01 CE, pin3 --- PB3 2| |7 PB2 --- nRF24L01 SCK, pin5
|
||||
nRF24L01 CSN, pin4 --- PB4 3| |6 PB1 --- nRF24L01 MOSI, pin7
|
||||
nRF24L01 GND, pin1 --- GND 4| |5 PB0 --- nRF24L01 MISO, pin6
|
||||
+----+
|
||||
|
||||
ATtiny25/45/85 Pin map with CE_PIN 3 and CSN_PIN 3 => PB3 and PB4 are free to use for application
|
||||
Circuit idea from 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 settletime delay value in RF24::csn() the timingSearch3pin.ino scatch can be used.
|
||||
This configuration is enabled when CE_PIN and CSN_PIN are equal, e.g. both 3
|
||||
Because CE is always high the power consumption is higher than for 5 pins solution
|
||||
^^
|
||||
+-\/-+ nRF24L01 CE, pin3 ------| //
|
||||
PB5 1|o |8 Vcc --- nRF24L01 VCC, pin2 ------x----------x--|<|-- 5V
|
||||
NC PB3 2| |7 PB2 --- nRF24L01 SCK, pin5 --|<|---x-[22k]--| LED
|
||||
NC PB4 3| |6 PB1 --- nRF24L01 MOSI, pin6 1n4148 |
|
||||
nRF24L01 GND, pin1 -x- GND 4| |5 PB0 --- nRF24L01 MISO, pin7 |
|
||||
| +----+ |
|
||||
|-----------------------------------------------||----x-- nRF24L01 CSN, pin4
|
||||
10nF
|
||||
|
||||
ATtiny24/44/84 Pin map with CE_PIN 8 and CSN_PIN 7
|
||||
Schematic provided and successfully tested by Carmine Pastore (https://github.com/Carminepz)
|
||||
+-\/-+
|
||||
nRF24L01 VCC, pin2 --- VCC 1|o |14 GND --- nRF24L01 GND, pin1
|
||||
PB0 2| |13 AREF
|
||||
PB1 3| |12 PA1
|
||||
PB3 4| |11 PA2 --- nRF24L01 CE, pin3
|
||||
PB2 5| |10 PA3 --- nRF24L01 CSN, pin4
|
||||
PA7 6| |9 PA4 --- nRF24L01 SCK, pin5
|
||||
nRF24L01 MOSI, pin7 --- PA6 7| |8 PA5 --- nRF24L01 MISO, pin6
|
||||
+----+
|
||||
*/
|
||||
|
||||
// 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
|
||||
|
||||
#include "RF24.h"
|
||||
|
||||
RF24 radio(CE_PIN, CSN_PIN);
|
||||
|
||||
byte addresses[][6] = {
|
||||
"1Node","2Node"};
|
||||
unsigned long payload = 0;
|
||||
|
||||
void setup() {
|
||||
// Setup and configure rf radio
|
||||
radio.begin(); // Start up the radio
|
||||
radio.setAutoAck(1); // Ensure autoACK is enabled
|
||||
radio.setRetries(15,15); // Max delay between retries & number of retries
|
||||
radio.openWritingPipe(addresses[1]); // Write to device address '2Node'
|
||||
radio.openReadingPipe(1,addresses[0]); // Read on pipe 1 for device address '1Node'
|
||||
radio.startListening(); // Start listening
|
||||
}
|
||||
|
||||
void loop(void){
|
||||
|
||||
radio.stopListening(); // First, stop listening so we can talk.
|
||||
payload++;
|
||||
radio.write( &payload, sizeof(unsigned long) );
|
||||
radio.startListening(); // Now, continue listening
|
||||
|
||||
unsigned long started_waiting_at = micros(); // Set up a timeout period, get the current microseconds
|
||||
boolean 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
|
||||
unsigned long got_time; // Grab the response, compare, and send to debugging spew
|
||||
radio.read( &got_time, sizeof(unsigned long) );
|
||||
}
|
||||
|
||||
// Try again 1s later
|
||||
delay(1000);
|
||||
}
|
|
@ -0,0 +1,396 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
timingSearch3pin.ino by tong67 ( https://github.com/tong67 )
|
||||
This sketch can be used to determine the best settleTime values to use in RF24::csn().
|
||||
The used settleTimeValues are 100/20. Depend on used RC combiniation and voltage drop by LED.
|
||||
It is setup to be completely selfcontained, copied defines and code from RF24 library.
|
||||
The ATtiny85 uses the tiny-core by CodingBadly (https://code.google.com/p/arduino-tiny/)
|
||||
(Intermediate) results are written to TX (PB3, pin 2). For schematic see rf24ping85.ino
|
||||
*/
|
||||
|
||||
// nRF24L01.h copy
|
||||
|
||||
/* Memory Map */
|
||||
#define 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 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 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
|
||||
/****************************************************************************/
|
||||
|
||||
//ATTiny support code pulled in from https://github.com/jscrane/RF24
|
||||
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
|
||||
// see http://gammon.com.au/spi
|
||||
# define DI 0 // D0, pin 5 Data In
|
||||
# define DO 1 // D1, pin 6 Data Out (this is *not* MOSI)
|
||||
# define USCK 2 // D2, pin 7 Universal Serial Interface clock
|
||||
# define SS 3 // D3, pin 2 Slave Select
|
||||
#elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
// these depend on the core used (check pins_arduino.h)
|
||||
// this is for jeelabs' one (based on google-code core)
|
||||
# define DI 4 // PA6
|
||||
# define DO 5 // PA5
|
||||
# define USCK 6 // PA4
|
||||
# define SS 3 // PA7
|
||||
#endif
|
||||
|
||||
#if defined (ARDUINO) && !defined (__arm__)
|
||||
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
|
||||
#define RF24_TINY
|
||||
#else
|
||||
// #include <SPI.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(RF24_TINY)
|
||||
#include <stdio.h>
|
||||
#include <Arduino.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#define SPI_CLOCK_DIV4 0x00
|
||||
#define SPI_CLOCK_DIV16 0x01
|
||||
#define SPI_CLOCK_DIV64 0x02
|
||||
#define SPI_CLOCK_DIV128 0x03
|
||||
#define SPI_CLOCK_DIV2 0x04
|
||||
#define SPI_CLOCK_DIV8 0x05
|
||||
#define SPI_CLOCK_DIV32 0x06
|
||||
//#define SPI_CLOCK_DIV64 0x07
|
||||
|
||||
#define SPI_MODE0 0x00
|
||||
#define SPI_MODE1 0x04
|
||||
#define SPI_MODE2 0x08
|
||||
#define SPI_MODE3 0x0C
|
||||
|
||||
#define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
|
||||
#define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
|
||||
#define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
|
||||
|
||||
class SPIClass {
|
||||
public:
|
||||
static byte transfer(byte _data);
|
||||
|
||||
// SPI Configuration methods
|
||||
|
||||
inline static void attachInterrupt();
|
||||
inline static void detachInterrupt(); // Default
|
||||
|
||||
static void begin(); // Default
|
||||
static void end();
|
||||
|
||||
// static void setBitOrder(uint8_t);
|
||||
// static void setDataMode(uint8_t);
|
||||
// static void setClockDivider(uint8_t);
|
||||
};
|
||||
extern SPIClass SPI;
|
||||
|
||||
#endif /* RF24_TINY */
|
||||
|
||||
|
||||
#if defined(RF24_TINY)
|
||||
|
||||
void SPIClass::begin() {
|
||||
digitalWrite(SS, HIGH);
|
||||
pinMode(USCK, OUTPUT);
|
||||
pinMode(DO, OUTPUT);
|
||||
pinMode(SS, OUTPUT);
|
||||
pinMode(DI, INPUT);
|
||||
USICR = _BV(USIWM0);
|
||||
}
|
||||
|
||||
byte SPIClass::transfer(byte b) {
|
||||
USIDR = b;
|
||||
USISR = _BV(USIOIF);
|
||||
do
|
||||
USICR = _BV(USIWM0) | _BV(USICS1) | _BV(USICLK) | _BV(USITC);
|
||||
while ((USISR & _BV(USIOIF)) == 0);
|
||||
return USIDR;
|
||||
}
|
||||
|
||||
void SPIClass::end() {}
|
||||
|
||||
#endif /* RF24_TINY */
|
||||
|
||||
/****************************************************************************/
|
||||
uint8_t ce_pin; /**< "Chip Enable" pin, activates the RX or TX role */
|
||||
uint8_t csn_pin; /**< SPI Chip select */
|
||||
uint8_t csnHighSettle = 255;
|
||||
uint8_t csnLowSettle = 255;
|
||||
/****************************************************************************/
|
||||
void ce(bool level) {
|
||||
if (ce_pin != csn_pin) digitalWrite(ce_pin,level);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
void setCsnHighSettle(uint8_t level) {
|
||||
csnHighSettle = level;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
void setCsnLowSettle(uint8_t level) {
|
||||
csnLowSettle = level;
|
||||
}
|
||||
/****************************************************************************/
|
||||
void csn(bool mode) {
|
||||
if (ce_pin != csn_pin) {
|
||||
digitalWrite(csn_pin,mode);
|
||||
} else {
|
||||
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 | ( REGISTER_MASK & reg ) );
|
||||
uint8_t result = SPI.transfer(0xff);
|
||||
csn(HIGH);
|
||||
return result;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
uint8_t write_register2(uint8_t reg, uint8_t value)
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
csn(LOW);
|
||||
status = SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) );
|
||||
SPI.transfer(value);
|
||||
csn(HIGH);
|
||||
return status;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
#if defined(RF24_TINY)
|
||||
#define CE_PIN 3
|
||||
#define CSN_PIN 3
|
||||
#else
|
||||
#define CE_PIN 7
|
||||
#define CSN_PIN 8
|
||||
#endif
|
||||
|
||||
#define MAX_HIGH 100
|
||||
#define MAX_LOW 100
|
||||
#define MINIMAL 8
|
||||
|
||||
void setup(void) {
|
||||
uint8_t status;
|
||||
|
||||
// start serial port and SPI
|
||||
Serial.begin(9600);
|
||||
SPI.begin();
|
||||
|
||||
// configure ce and scn as output when used
|
||||
ce_pin = CE_PIN;
|
||||
csn_pin = CSN_PIN;
|
||||
|
||||
setCsnHighSettle(MAX_HIGH);
|
||||
setCsnLowSettle(MAX_LOW);
|
||||
// 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 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_register2(CONFIG, read_register(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_register2(CONFIG, read_register(CONFIG) | _BV(PWR_UP));
|
||||
delay(5) ;
|
||||
|
||||
// Goto Standby-II
|
||||
ce(HIGH);
|
||||
Serial.print("Scanning for optimal setting time for scn");
|
||||
}
|
||||
|
||||
|
||||
void loop(void) {
|
||||
uint8_t status;
|
||||
uint8_t i;
|
||||
uint8_t j;
|
||||
uint8_t k;
|
||||
bool success = true;
|
||||
uint8_t csnHigh = MAX_HIGH;
|
||||
uint8_t csnLow = MAX_LOW;
|
||||
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 (k=0;k<2;k++) {
|
||||
bottom_found = false;
|
||||
bottom_success = 0;
|
||||
while(bottom_success < 255) {
|
||||
setCsnHighSettle(limit[0]);
|
||||
setCsnLowSettle(limit[1]);
|
||||
// check current values
|
||||
i = 0;
|
||||
while(i<255 & success) {
|
||||
for (j=0;j<2;j++) {
|
||||
write_register2(EN_AA, value[j]);
|
||||
status = read_register(EN_AA);
|
||||
if (value[j] != status) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
// process result of current values
|
||||
if (!success) {
|
||||
Serial.print("Settle NOK. 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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
Serial.print("Adviced Settle times are: csnHigh=");
|
||||
Serial.print(advice[0],DEC);
|
||||
Serial.print(" csnLow=");
|
||||
Serial.println(advice[1],DEC);
|
||||
while (true)
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
# (1) Project Information
|
||||
|
||||
PROJECT_LIBS = SPI RF24 ;
|
||||
|
||||
# (2) Board Information
|
||||
|
||||
UPLOAD_PROTOCOL ?= stk500v1 ;
|
||||
UPLOAD_SPEED ?= 57600 ;
|
||||
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 ;
|
||||
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 -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 = $(PWD) $(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 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
|
||||
}
|
||||
|
||||
#
|
||||
# Targets
|
||||
#
|
||||
|
||||
# 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 ] ;
|
||||
|
||||
# Grab everything from the current dir
|
||||
PROJECT_MODULES += [ GLOB $(PWD) : *.c *.cpp *.pde *.ino ] ;
|
||||
|
||||
# Main output executable
|
||||
MAIN = $(PWD:B).elf ;
|
||||
|
||||
Main $(MAIN) : $(CORE_MODULES) $(LIB_MODULES) $(PROJECT_MODULES) ;
|
||||
Hex $(MAIN:B).hex : $(MAIN) ;
|
||||
|
||||
# Upload targets
|
||||
for _p in $(PORTS)
|
||||
{
|
||||
Upload $(_p) : $(PORT_$(_p)) : $(MAIN:B).hex ;
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Channel scanner
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Inspired by cpixip.
|
||||
* See http://arduino.cc/forum/index.php/topic,54795.0.html
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include "nRF24L01.h"
|
||||
#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();
|
||||
|
||||
// Print out header, high then low digit
|
||||
int i = 0;
|
||||
while ( i < num_channels )
|
||||
{
|
||||
printf("%x",i>>4);
|
||||
++i;
|
||||
}
|
||||
Serial.println();
|
||||
i = 0;
|
||||
while ( i < num_channels )
|
||||
{
|
||||
printf("%x",i&0xf);
|
||||
++i;
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
//
|
||||
// Loop
|
||||
//
|
||||
|
||||
const int num_reps = 100;
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
// 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 )
|
||||
{
|
||||
printf("%x",min(0xf,values[i]));
|
||||
++i;
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// vim:ai:cin:sts=2 sw=2 ft=cpp
|
|
@ -0,0 +1,206 @@
|
|||
PROJECT_NAME = $(PWD:B) ;
|
||||
PROJECT_DIR = . ;
|
||||
PROJECT_LIBS = EEPROM SPI 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 ;
|
||||
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 = $(HOME)/Source/Arduino/libraries ;
|
||||
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 ;
|
||||
CTUNING = -ffunction-sections -fdata-sections ;
|
||||
CXXTUNING = -fno-exceptions -fno-strict-aliasing ;
|
||||
CFLAGS = -Os -Wall -Wextra -mmcu=$(MCU) $(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) : [^.]* ] ;
|
||||
|
||||
# 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) $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp ] ;
|
||||
|
||||
# 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 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 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 .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 ;
|
||||
|
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
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 Star Group
|
||||
*
|
||||
* This sketch is a more complex example of using the RF24 library for Arduino.
|
||||
* Deploy this on up to six nodes. Set one as the 'pong receiver' by tying the
|
||||
* role_pin low, and the others will be 'ping transmit' units. The ping units
|
||||
* unit will send out the value of millis() once a second. The pong unit will
|
||||
* respond back with a copy of the value. Each ping unit can get that response
|
||||
* back, and determine how long the whole cycle took.
|
||||
*
|
||||
* This example requires a bit more complexity to determine which unit is which.
|
||||
* The pong receiver is identified by having its role_pin tied to ground.
|
||||
* The ping senders are further differentiated by a byte in eeprom.
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <EEPROM.h>
|
||||
#include "nRF24L01.h"
|
||||
#include "RF24.h"
|
||||
#include "printf.h"
|
||||
|
||||
//
|
||||
// Hardware configuration
|
||||
//
|
||||
|
||||
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
|
||||
|
||||
RF24 radio(9,10);
|
||||
|
||||
// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver
|
||||
// Leave open to be the 'pong' receiver.
|
||||
const int role_pin = 7;
|
||||
|
||||
//
|
||||
// Topology
|
||||
//
|
||||
|
||||
// Radio pipe addresses for the nodes to communicate. Only ping nodes need
|
||||
// dedicated pipes in this topology. Each ping node has a talking pipe
|
||||
// that it will ping into, and a listening pipe that it will listen for
|
||||
// the pong. The pong node listens on all the ping node talking pipes
|
||||
// and sends the pong back on the sending node's specific listening pipe.
|
||||
|
||||
const uint64_t talking_pipes[5] = { 0xF0F0F0F0D2LL, 0xF0F0F0F0C3LL, 0xF0F0F0F0B4LL, 0xF0F0F0F0A5LL, 0xF0F0F0F096LL };
|
||||
const uint64_t listening_pipes[5] = { 0x3A3A3A3AD2LL, 0x3A3A3A3AC3LL, 0x3A3A3A3AB4LL, 0x3A3A3A3AA5LL, 0x3A3A3A3A96LL };
|
||||
|
||||
//
|
||||
// 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_invalid = 0, role_ping_out, 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;
|
||||
|
||||
//
|
||||
// Address management
|
||||
//
|
||||
|
||||
// Where in EEPROM is the address stored?
|
||||
const uint8_t address_at_eeprom_location = 0;
|
||||
|
||||
// What is our address (SRAM cache of the address from EEPROM)
|
||||
// Note that zero is an INVALID address. The pong back unit takes address
|
||||
// 1, and the rest are 2-6
|
||||
uint8_t node_address;
|
||||
|
||||
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;
|
||||
|
||||
//
|
||||
// Address
|
||||
//
|
||||
|
||||
if ( role == role_pong_back )
|
||||
node_address = 1;
|
||||
else
|
||||
{
|
||||
// Read the address from EEPROM
|
||||
uint8_t reading = EEPROM.read(address_at_eeprom_location);
|
||||
|
||||
// If it is in a valid range for node addresses, it is our
|
||||
// address.
|
||||
if ( reading >= 2 && reading <= 6 )
|
||||
node_address = reading;
|
||||
|
||||
// Otherwise, it is invalid, so set our address AND ROLE to 'invalid'
|
||||
else
|
||||
{
|
||||
node_address = 0;
|
||||
role = role_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Print preamble
|
||||
//
|
||||
|
||||
Serial.begin(115200);
|
||||
printf_begin();
|
||||
printf("\n\rRF24/examples/starping/\n\r");
|
||||
printf("ROLE: %s\n\r",role_friendly_name[role]);
|
||||
printf("ADDRESS: %i\n\r",node_address);
|
||||
|
||||
//
|
||||
// Setup and configure rf radio
|
||||
//
|
||||
|
||||
radio.begin();
|
||||
|
||||
//
|
||||
// Open pipes to other nodes for communication
|
||||
//
|
||||
|
||||
// The pong node listens on all the ping node talking pipes
|
||||
// and sends the pong back on the sending node's specific listening pipe.
|
||||
if ( role == role_pong_back )
|
||||
{
|
||||
radio.openReadingPipe(1,talking_pipes[0]);
|
||||
radio.openReadingPipe(2,talking_pipes[1]);
|
||||
radio.openReadingPipe(3,talking_pipes[2]);
|
||||
radio.openReadingPipe(4,talking_pipes[3]);
|
||||
radio.openReadingPipe(5,talking_pipes[4]);
|
||||
}
|
||||
|
||||
// Each ping node has a talking pipe that it will ping into, and a listening
|
||||
// pipe that it will listen for the pong.
|
||||
if ( role == role_ping_out )
|
||||
{
|
||||
// Write on our talking pipe
|
||||
radio.openWritingPipe(talking_pipes[node_address-2]);
|
||||
// Listen on our listening pipe
|
||||
radio.openReadingPipe(1,listening_pipes[node_address-2]);
|
||||
}
|
||||
|
||||
//
|
||||
// Start listening
|
||||
//
|
||||
|
||||
radio.startListening();
|
||||
|
||||
//
|
||||
// Dump the configuration of the rf unit for debugging
|
||||
//
|
||||
|
||||
radio.printDetails();
|
||||
|
||||
//
|
||||
// Prompt the user to assign a node address if we don't have one
|
||||
//
|
||||
|
||||
if ( role == role_invalid )
|
||||
{
|
||||
printf("\n\r*** NO NODE ADDRESS ASSIGNED *** Send 1 through 6 to assign an address\n\r");
|
||||
}
|
||||
}
|
||||
|
||||
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 > 250 )
|
||||
timeout = true;
|
||||
|
||||
// Describe the results
|
||||
if ( timeout )
|
||||
{
|
||||
printf("Failed, response timed out.\n\r");
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
// 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
|
||||
uint8_t pipe_num;
|
||||
if ( radio.available(&pipe_num) )
|
||||
{
|
||||
// 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 from node %i...",got_time,pipe_num+1);
|
||||
}
|
||||
|
||||
// First, stop listening so we can talk
|
||||
radio.stopListening();
|
||||
|
||||
// Open the correct pipe for writing
|
||||
radio.openWritingPipe(listening_pipes[pipe_num-1]);
|
||||
|
||||
// Retain the low 2 bytes to identify the pipe for the spew
|
||||
uint16_t pipe_id = listening_pipes[pipe_num-1] & 0xffff;
|
||||
|
||||
// Send the final one back.
|
||||
radio.write( &got_time, sizeof(unsigned long) );
|
||||
printf("Sent response to %04x.\n\r",pipe_id);
|
||||
|
||||
// Now, resume listening so we catch the next packets.
|
||||
radio.startListening();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Listen for serial input, which is how we set the address
|
||||
//
|
||||
if (Serial.available())
|
||||
{
|
||||
// If the character on serial input is in a valid range...
|
||||
char c = Serial.read();
|
||||
if ( c >= '1' && c <= '6' )
|
||||
{
|
||||
// It is our address
|
||||
EEPROM.write(address_at_eeprom_location,c-'0');
|
||||
|
||||
// And we are done right now (no easy way to soft reset)
|
||||
printf("\n\rManually reset address to: %c\n\rPress RESET to continue!",c);
|
||||
while(1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// vim:ai:ci sts=2 sw=2 ft=cpp
|
|
@ -0,0 +1,52 @@
|
|||
#############################################################################
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
BINARY_PREFIX = rf24
|
||||
SOURCES = $(PROGRAMS:=.cpp)
|
||||
|
||||
LIBS=-l$(LIB)
|
||||
ifeq ($(DRIVER), LittleWire)
|
||||
LIBS+= -llittlewire-spi
|
||||
endif
|
||||
|
||||
all: $(PROGRAMS)
|
||||
|
||||
$(PROGRAMS): $(SOURCES)
|
||||
$(CXX) $(CFLAGS) -I$(HEADER_DIR)/.. -I.. -L$(LIB_DIR) $@.cpp $(LIBS) -o $@
|
||||
|
||||
clean:
|
||||
@echo "[Cleaning]"
|
||||
rm -rf $(PROGRAMS)
|
||||
|
||||
install: all
|
||||
@echo "[Installing examples to $(EXAMPLES_DIR)]"
|
||||
@mkdir -p $(EXAMPLES_DIR)
|
||||
@for prog in $(PROGRAMS); do \
|
||||
install -m 0755 $${prog} $(EXAMPLES_DIR)/$(BINARY_PREFIX)-$${prog}; \
|
||||
done
|
||||
|
||||
upload: all
|
||||
@echo "[Uploading examples to $(REMOTE):$(REMOTE_EXAMPLES_DIR)]"
|
||||
ifeq ($(REMOTE),)
|
||||
@echo "[ERROR] Remote machine not configured. Run configure with respective arguments."
|
||||
@exit 1
|
||||
endif
|
||||
@ssh -q -t -p $(REMOTE_PORT) $(REMOTE) "mkdir -p $(REMOTE_EXAMPLES_DIR)"
|
||||
@ssh -q -t -p $(REMOTE_PORT) $(REMOTE) "mkdir -p /tmp/RF24_examples"
|
||||
@scp -q -P $(REMOTE_PORT) $(PROGRAMS) $(REMOTE):/tmp/RF24_examples
|
||||
@for prog in $(PROGRAMS); do \
|
||||
ssh -q -t -p $(REMOTE_PORT) $(REMOTE) "sudo install -m 0755 /tmp/RF24_examples/$${prog} $(REMOTE_EXAMPLES_DIR)/$(BINARY_PREFIX)-$${prog}"; \
|
||||
done
|
||||
@ssh -q -t -p $(REMOTE_PORT) $(REMOTE) "rm -rf /tmp/RF24_examples"
|
||||
|
||||
.PHONY: install upload
|
|
@ -0,0 +1,24 @@
|
|||
#############################################################################
|
||||
#
|
||||
# Makefile for librf24 examples on Raspberry Pi
|
||||
#
|
||||
# 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
|
||||
# You can change the install directory by editing the prefix line
|
||||
#
|
||||
|
||||
ifeq ($(wildcard ../../Makefile.inc), )
|
||||
$(error Configuration not found. Run ./configure first)
|
||||
endif
|
||||
|
||||
include ../../Makefile.inc
|
||||
|
||||
# define all programs
|
||||
PROGRAMS = rpi-hub scanner
|
||||
|
||||
include ../Makefile.examples
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
*
|
||||
* Filename : rpi-hub.cpp
|
||||
*
|
||||
* This program makes the RPi as a hub listening to all six pipes from the remote sensor nodes ( usually Arduino )
|
||||
* and will return the packet back to the sensor on pipe0 so that the sender can calculate the round trip delays
|
||||
* when the payload matches.
|
||||
*
|
||||
* I encounter that at times, it also receive from pipe7 ( or pipe0 ) with content of FFFFFFFFF that I will not sent
|
||||
* back to the sender
|
||||
*
|
||||
* Refer to RF24/examples/rpi_hub_arduino/ for the corresponding Arduino sketches to work with this code.
|
||||
*
|
||||
*
|
||||
* CE is not used and CSN is GPIO25 (not pinout)
|
||||
*
|
||||
* Refer to RPi docs for GPIO numbers
|
||||
*
|
||||
* Author : Stanley Seow
|
||||
* e-mail : stanleyseow@gmail.com
|
||||
* date : 6th Mar 2013
|
||||
*
|
||||
* 03/17/2013 : Charles-Henri Hallard (http://hallard.me)
|
||||
* Modified to use with Arduipi board http://hallard.me/arduipi
|
||||
* Changed to use modified bcm2835 and RF24 library
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <RF24/RF24.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Radio pipe addresses for the 2 nodes to communicate.
|
||||
// First pipe is for writing, 2nd, 3rd, 4th, 5th & 6th is for reading...
|
||||
const uint64_t pipes[6] =
|
||||
{ 0xF0F0F0F0D2LL, 0xF0F0F0F0E1LL,
|
||||
0xF0F0F0F0E2LL, 0xF0F0F0F0E3LL,
|
||||
0xF0F0F0F0F1, 0xF0F0F0F0F2
|
||||
};
|
||||
|
||||
// CE Pin, CSN Pin, SPI Speed
|
||||
|
||||
// Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz
|
||||
//RF24 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
|
||||
//RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
|
||||
|
||||
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 8Mhz
|
||||
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
uint8_t len;
|
||||
|
||||
// Refer to RF24.h or nRF24L01 DS for settings
|
||||
radio.begin();
|
||||
radio.enableDynamicPayloads();
|
||||
radio.setAutoAck(1);
|
||||
radio.setRetries(15,15);
|
||||
radio.setDataRate(RF24_1MBPS);
|
||||
radio.setPALevel(RF24_PA_MAX);
|
||||
radio.setChannel(76);
|
||||
radio.setCRCLength(RF24_CRC_16);
|
||||
|
||||
// Open 6 pipes for readings ( 5 plus pipe0, also can be used for reading )
|
||||
radio.openWritingPipe(pipes[0]);
|
||||
radio.openReadingPipe(1,pipes[1]);
|
||||
radio.openReadingPipe(2,pipes[2]);
|
||||
radio.openReadingPipe(3,pipes[3]);
|
||||
radio.openReadingPipe(4,pipes[4]);
|
||||
radio.openReadingPipe(5,pipes[5]);
|
||||
|
||||
//
|
||||
// Start listening
|
||||
//
|
||||
radio.startListening();
|
||||
|
||||
//
|
||||
// Dump the configuration of the rf unit for debugging
|
||||
//
|
||||
radio.printDetails();
|
||||
|
||||
printf("Output below : \n");
|
||||
delay(1);
|
||||
|
||||
while(1)
|
||||
{
|
||||
char receivePayload[32];
|
||||
uint8_t pipe = 1;
|
||||
|
||||
// Start listening
|
||||
radio.startListening();
|
||||
|
||||
while ( radio.available(&pipe) )
|
||||
{
|
||||
len = radio.getDynamicPayloadSize();
|
||||
radio.read( receivePayload, len );
|
||||
|
||||
// Display it on screen
|
||||
printf("Recv: size=%i payload=%s pipe=%i",len,receivePayload,pipe);
|
||||
|
||||
// Send back payload to sender
|
||||
radio.stopListening();
|
||||
|
||||
// if pipe is 7, do not send it back
|
||||
if ( pipe != 7 )
|
||||
{
|
||||
radio.write(receivePayload,len);
|
||||
receivePayload[len]=0;
|
||||
printf("\t Send: size=%i payload=%s pipe:%i\n",len,receivePayload,pipe);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
pipe++;
|
||||
|
||||
// reset pipe to 0
|
||||
if ( pipe > 6 )
|
||||
pipe = 0;
|
||||
}
|
||||
|
||||
delayMicroseconds(20);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
|
||||
03/17/2013 : Charles-Henri Hallard (http://hallard.me)
|
||||
Modified to use with Arduipi board http://hallard.me/arduipi
|
||||
Changed to use modified bcm2835 and RF24 library
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* Channel scanner
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Inspired by cpixip.
|
||||
* See http://arduino.cc/forum/index.php/topic,54795.0.html
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <RF24/RF24.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//
|
||||
// Hardware configuration
|
||||
//
|
||||
|
||||
// CE Pin, CSN Pin, SPI Speed
|
||||
|
||||
// Setup for GPIO 22 CE and GPIO 25 CSN with SPI Speed @ 1Mhz
|
||||
//RF24 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
|
||||
//RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
|
||||
|
||||
// Setup for GPIO 22 CE and CE1 CSN with SPI Speed @ 8Mhz
|
||||
//RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
|
||||
|
||||
// Generic setup
|
||||
RF24 radio(22, 0);
|
||||
|
||||
//
|
||||
// Channel info
|
||||
//
|
||||
const uint8_t num_channels = 126;
|
||||
uint8_t values[num_channels];
|
||||
|
||||
|
||||
const int num_reps = 100;
|
||||
int reset_array=0;
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
//
|
||||
// Print preamble
|
||||
//
|
||||
|
||||
//Serial.begin(115200);
|
||||
//printf_begin();
|
||||
printf("RF24/examples/scanner/\n");
|
||||
|
||||
//
|
||||
// Setup and configure rf radio
|
||||
//
|
||||
radio.begin();
|
||||
|
||||
radio.setAutoAck(false);
|
||||
|
||||
// Get into standby mode
|
||||
radio.startListening();
|
||||
radio.stopListening();
|
||||
|
||||
radio.printDetails();
|
||||
|
||||
// Print out header, high then low digit
|
||||
int i = 0;
|
||||
|
||||
while ( i < num_channels )
|
||||
{
|
||||
printf("%x",i>>4);
|
||||
++i;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
i = 0;
|
||||
while ( i < num_channels )
|
||||
{
|
||||
printf("%x",i&0xf);
|
||||
++i;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// forever loop
|
||||
while(1)
|
||||
{
|
||||
// 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
|
||||
i = 0;
|
||||
while ( i < num_channels )
|
||||
{
|
||||
printf("%x",min(0xf,(values[i]&0xf)));
|
||||
++i;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// vim:ai:cin:sts=2 sw=2 ft=cpp
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
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.
|
||||
|
||||
03/17/2013 : Charles-Henri Hallard (http://hallard.me)
|
||||
Modified to use with Arduipi board http://hallard.me/arduipi
|
||||
Changed to use modified bcm2835 and RF24 library
|
||||
TMRh20 2014 - Updated to work with optimized RF24 Arduino library
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example RF Radio Ping Pair
|
||||
*
|
||||
* This is an example of how to use the RF24 class on RPi, communicating to an Arduino running
|
||||
* the GettingStarted sketch.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <RF24/RF24.h>
|
||||
|
||||
using namespace std;
|
||||
//
|
||||
// Hardware configuration
|
||||
// Configure the appropriate pins for your connections
|
||||
|
||||
/****************** Raspberry Pi ***********************/
|
||||
|
||||
// Radio CE Pin, CSN Pin, SPI Speed
|
||||
// See http://www.airspayce.com/mikem/bcm2835/group__constants.html#ga63c029bd6500167152db4e57736d0939 and the related enumerations for pin information.
|
||||
|
||||
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
|
||||
//RF24 radio(RPI_V2_GPIO_P1_22, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
|
||||
|
||||
// NEW: Setup for RPi B+
|
||||
//RF24 radio(RPI_BPLUS_GPIO_J8_15,RPI_BPLUS_GPIO_J8_24, BCM2835_SPI_SPEED_8MHZ);
|
||||
|
||||
// Setup for GPIO 15 CE and CE0 CSN with SPI Speed @ 8Mhz
|
||||
//RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
|
||||
|
||||
// RPi generic:
|
||||
RF24 radio(22,0);
|
||||
|
||||
/*** RPi Alternate ***/
|
||||
//Note: Specify SPI BUS 0 or 1 instead of CS pin number.
|
||||
// See http://tmrh20.github.io/RF24/RPi.html for more information on usage
|
||||
|
||||
//RPi Alternate, with MRAA
|
||||
//RF24 radio(15,0);
|
||||
|
||||
//RPi Alternate, with SPIDEV - Note: Edit RF24/arch/BBB/spi.cpp and set 'this->device = "/dev/spidev0.0";;' or as listed in /dev
|
||||
//RF24 radio(22,0);
|
||||
|
||||
|
||||
/****************** Linux (BBB,x86,etc) ***********************/
|
||||
|
||||
// See http://tmrh20.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 for ARM(Linux) devices like BBB using spidev (default is "/dev/spidev1.0" )
|
||||
//RF24 radio(115,0);
|
||||
|
||||
//BBB Alternate, with mraa
|
||||
// CE pin = (Header P9, Pin 13) = 59 = 13 + 46
|
||||
//Note: Specify SPI BUS 0 or 1 instead of CS pin number.
|
||||
//RF24 radio(59,0);
|
||||
|
||||
/********** User Config *********/
|
||||
// Assign a unique identifier for this node, 0 or 1
|
||||
bool radioNumber = 1;
|
||||
|
||||
/********************************/
|
||||
|
||||
// Radio pipe addresses for the 2 nodes to communicate.
|
||||
const uint8_t pipes[][6] = {"1Node","2Node"};
|
||||
|
||||
|
||||
int main(int argc, char** argv){
|
||||
|
||||
bool role_ping_out = true, role_pong_back = false;
|
||||
bool role = role_pong_back;
|
||||
|
||||
cout << "RF24/examples/GettingStarted/\n";
|
||||
|
||||
// Setup and configure rf radio
|
||||
radio.begin();
|
||||
|
||||
// optionally, increase the delay between retries & # of retries
|
||||
radio.setRetries(15,15);
|
||||
// Dump the configuration of the rf unit for debugging
|
||||
radio.printDetails();
|
||||
|
||||
|
||||
/********* Role chooser ***********/
|
||||
|
||||
printf("\n ************ Role Setup ***********\n");
|
||||
string input = "";
|
||||
char myChar = {0};
|
||||
cout << "Choose a role: Enter 0 for pong_back, 1 for ping_out (CTRL+C to exit) \n>";
|
||||
getline(cin,input);
|
||||
|
||||
if(input.length() == 1) {
|
||||
myChar = input[0];
|
||||
if(myChar == '0'){
|
||||
cout << "Role: Pong Back, awaiting transmission " << endl << endl;
|
||||
}else{ cout << "Role: Ping Out, starting transmission " << endl << endl;
|
||||
role = role_ping_out;
|
||||
}
|
||||
}
|
||||
/***********************************/
|
||||
// This simple sketch opens two pipes for these two nodes to communicate
|
||||
// back and forth.
|
||||
|
||||
if ( !radioNumber ) {
|
||||
radio.openWritingPipe(pipes[0]);
|
||||
radio.openReadingPipe(1,pipes[1]);
|
||||
} else {
|
||||
radio.openWritingPipe(pipes[1]);
|
||||
radio.openReadingPipe(1,pipes[0]);
|
||||
}
|
||||
|
||||
radio.startListening();
|
||||
|
||||
// forever loop
|
||||
while (1)
|
||||
{
|
||||
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
|
||||
|
||||
printf("Now sending...\n");
|
||||
unsigned long time = millis();
|
||||
|
||||
bool ok = radio.write( &time, sizeof(unsigned long) );
|
||||
|
||||
if (!ok){
|
||||
printf("failed.\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.\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\n",got_time,millis()-got_time);
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
//
|
||||
// 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;
|
||||
|
||||
// Fetch the payload, and see if this was the last one.
|
||||
while(radio.available()){
|
||||
radio.read( &got_time, sizeof(unsigned long) );
|
||||
}
|
||||
radio.stopListening();
|
||||
|
||||
radio.write( &got_time, sizeof(unsigned long) );
|
||||
|
||||
// Now, resume listening so we catch the next packets.
|
||||
radio.startListening();
|
||||
|
||||
// Spew it
|
||||
printf("Got payload(%d) %lu...\n",sizeof(unsigned long), got_time);
|
||||
|
||||
delay(925); //Delay after payload responded to, minimize RPi CPU time
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // forever loop
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
TMRh20 2014 - Updated to work with optimized RF24 Arduino library
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Example for efficient call-response using ack-payloads
|
||||
*
|
||||
* This example continues to make use of all the normal functionality of the radios including
|
||||
* the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
|
||||
* This allows very fast call-response communication, with the responding radio never having to
|
||||
* switch out of Primary Receiver mode to send back a payload, but having the option to switch to
|
||||
* primary transmitter if wanting to initiate communication instead of respond to a commmunication.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <RF24/RF24.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//
|
||||
// Hardware configuration
|
||||
// Configure the appropriate pins for your connections
|
||||
|
||||
/****************** Raspberry Pi ***********************/
|
||||
|
||||
// Radio CE Pin, CSN Pin, SPI Speed
|
||||
// See http://www.airspayce.com/mikem/bcm2835/group__constants.html#ga63c029bd6500167152db4e57736d0939 and the related enumerations for pin information.
|
||||
|
||||
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
|
||||
//RF24 radio(RPI_V2_GPIO_P1_22, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
|
||||
|
||||
// NEW: Setup for RPi B+
|
||||
//RF24 radio(RPI_BPLUS_GPIO_J8_15,RPI_BPLUS_GPIO_J8_24, BCM2835_SPI_SPEED_8MHZ);
|
||||
|
||||
// Setup for GPIO 15 CE and CE0 CSN with SPI Speed @ 8Mhz
|
||||
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
|
||||
|
||||
/*** RPi Alternate ***/
|
||||
//Note: Specify SPI BUS 0 or 1 instead of CS pin number.
|
||||
// See http://tmrh20.github.io/RF24/RPi.html for more information on usage
|
||||
|
||||
//RPi Alternate, with MRAA
|
||||
//RF24 radio(15,0);
|
||||
|
||||
//RPi Alternate, with SPIDEV - Note: Edit RF24/arch/BBB/spi.cpp and set 'this->device = "/dev/spidev0.0";;' or as listed in /dev
|
||||
//RF24 radio(22,0);
|
||||
|
||||
|
||||
/****************** Linux (BBB,x86,etc) ***********************/
|
||||
|
||||
// See http://tmrh20.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 for ARM(Linux) devices like BBB using spidev (default is "/dev/spidev1.0" )
|
||||
//RF24 radio(115,0);
|
||||
|
||||
//BBB Alternate, with mraa
|
||||
// CE pin = (Header P9, Pin 13) = 59 = 13 + 46
|
||||
//Note: Specify SPI BUS 0 or 1 instead of CS pin number.
|
||||
//RF24 radio(59,0);
|
||||
|
||||
/********** User Config *********/
|
||||
// Assign a unique identifier for this node, 0 or 1. Arduino example uses radioNumber 0 by default.
|
||||
bool radioNumber = 1;
|
||||
|
||||
/********************************/
|
||||
|
||||
|
||||
// Radio pipe addresses for the 2 nodes to communicate.
|
||||
const uint8_t addresses[][6] = {"1Node","2Node"};
|
||||
|
||||
bool role_ping_out = 1, role_pong_back = 0, role = 0;
|
||||
uint8_t counter = 1; // A single byte to keep track of the data being sent back and forth
|
||||
|
||||
|
||||
int main(int argc, char** argv){
|
||||
|
||||
|
||||
cout << "RPi/RF24/examples/gettingstarted_call_response\n";
|
||||
radio.begin();
|
||||
radio.enableAckPayload(); // Allow optional ack payloads
|
||||
radio.enableDynamicPayloads();
|
||||
radio.printDetails(); // Dump the configuration of the rf unit for debugging
|
||||
|
||||
|
||||
/********* Role chooser ***********/
|
||||
|
||||
printf("\n ************ Role Setup ***********\n");
|
||||
string input = "";
|
||||
char myChar = {0};
|
||||
cout << "Choose a role: Enter 0 for pong_back, 1 for ping_out (CTRL+C to exit)\n>";
|
||||
getline(cin,input);
|
||||
|
||||
if(input.length() == 1) {
|
||||
myChar = input[0];
|
||||
if(myChar == '0'){
|
||||
cout << "Role: Pong Back, awaiting transmission " << endl << endl;
|
||||
}else{ cout << "Role: Ping Out, starting transmission " << endl << endl;
|
||||
role = role_ping_out;
|
||||
}
|
||||
}
|
||||
/***********************************/
|
||||
// This opens two pipes for these two nodes to communicate
|
||||
// back and forth.
|
||||
if ( !radioNumber ) {
|
||||
radio.openWritingPipe(addresses[0]);
|
||||
radio.openReadingPipe(1,addresses[1]);
|
||||
}else{
|
||||
radio.openWritingPipe(addresses[1]);
|
||||
radio.openReadingPipe(1,addresses[0]);
|
||||
}
|
||||
radio.startListening();
|
||||
radio.writeAckPayload(1,&counter,1);
|
||||
|
||||
// forever loop
|
||||
while (1){
|
||||
|
||||
|
||||
/****************** Ping Out Role ***************************/
|
||||
|
||||
if (role == role_ping_out){ // Radio is in ping mode
|
||||
|
||||
uint8_t gotByte; // Initialize a variable for the incoming response
|
||||
|
||||
radio.stopListening(); // First, stop listening so we can talk.
|
||||
printf("Now sending %d as payload. ",counter); // Use a simple byte counter as payload
|
||||
unsigned long time = millis(); // Record the current microsecond count
|
||||
|
||||
if ( radio.write(&counter,1) ){ // Send the counter variable to the other radio
|
||||
if(!radio.available()){ // If nothing in the buffer, we got an ack but it is blank
|
||||
printf("Got blank response. round-trip delay: %lu ms\n\r",millis()-time);
|
||||
}else{
|
||||
while(radio.available() ){ // If an ack with payload was received
|
||||
radio.read( &gotByte, 1 ); // Read it, and display the response time
|
||||
printf("Got response %d, round-trip delay: %lu ms\n\r",gotByte,millis()-time);
|
||||
counter++; // Increment the counter variable
|
||||
}
|
||||
}
|
||||
|
||||
}else{ printf("Sending failed.\n\r"); } // If no ack response, sending failed
|
||||
|
||||
sleep(1); // Try again later
|
||||
}
|
||||
|
||||
/****************** Pong Back Role ***************************/
|
||||
|
||||
if ( role == role_pong_back ) {
|
||||
uint8_t pipeNo, gotByte; // Declare variables for the pipe and the byte received
|
||||
if( radio.available(&pipeNo)){ // Read all available payloads
|
||||
radio.read( &gotByte, 1 );
|
||||
// Since this is a call-response. Respond directly with an ack payload.
|
||||
gotByte += 1; // Ack payloads are much more efficient than switching to transmit mode to respond to a call
|
||||
radio.writeAckPayload(pipeNo,&gotByte, 1 ); // This can be commented out to send empty payloads.
|
||||
printf("Loaded next response %d \n\r", gotByte);
|
||||
delay(900); //Delay after a response to minimize CPU usage on RPi
|
||||
//Expects a payload every second
|
||||
}
|
||||
}
|
||||
|
||||
} //while 1
|
||||
} //main
|
||||
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#############################################################################
|
||||
#
|
||||
# Makefile for librf24 examples on Raspberry Pi
|
||||
#
|
||||
# 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
|
||||
# You can change the install directory by editing the prefix line
|
||||
#
|
||||
|
||||
ifeq ($(wildcard ../../Makefile.inc), )
|
||||
$(error Configuration not found. Run ./configure first)
|
||||
endif
|
||||
|
||||
include ../../Makefile.inc
|
||||
|
||||
# define all programs
|
||||
PROGRAMS = gettingstarted_call_response_int gettingstarted_call_response_int2 transfer_interrupt pingpair_dyn_int
|
||||
|
||||
include ../Makefile.examples
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
TMRh20 2014 - Updated to work with optimized RF24 Arduino library
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Example for efficient call-response using ack-payloads and interrupts
|
||||
*
|
||||
* This example continues to make use of all the normal functionality of the radios including
|
||||
* the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
|
||||
* This allows very fast call-response communication, with the responding radio never having to
|
||||
* switch out of Primary Receiver mode to send back a payload, but having the option to switch to
|
||||
* primary transmitter if wanting to initiate communication instead of respond to a commmunication.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <RF24/RF24.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//
|
||||
// Hardware configuration
|
||||
// Configure the appropriate pins for your connections
|
||||
|
||||
/****************** Raspberry Pi ***********************/
|
||||
|
||||
RF24 radio(22,0); //GPIO, SPI-BUS
|
||||
|
||||
/********** User Config *********/
|
||||
// Assign a unique identifier for this node, 0 or 1. Arduino example uses radioNumber 0 by default.
|
||||
bool radioNumber = 1;
|
||||
int interruptPin = 23;
|
||||
/********************************/
|
||||
|
||||
|
||||
// Radio pipe addresses for the 2 nodes to communicate.
|
||||
const uint8_t addresses[][6] = {"1Node","2Node"};
|
||||
|
||||
volatile bool role_ping_out = 1, role_pong_back = 0, role = 0;
|
||||
uint8_t counter = 1; // A single byte to keep track of the data being sent back and forth
|
||||
|
||||
volatile bool gotResponse = false;
|
||||
|
||||
void intHandler(){
|
||||
|
||||
if ( role == role_pong_back ) {
|
||||
uint8_t pipeNo, gotByte; // Declare variables for the pipe and the byte received
|
||||
if( radio.available(&pipeNo)){ // Read all available payloads
|
||||
radio.read( &gotByte, 1 );
|
||||
// Since this is a call-response. Respond directly with an ack payload.
|
||||
gotByte += 1; // Ack payloads are much more efficient than switching to transmit mode to respond to a call
|
||||
radio.writeAckPayload(pipeNo,&gotByte, 1 ); // This can be commented out to send empty payloads.
|
||||
printf("Loaded next response %d \n\r", gotByte);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv){
|
||||
|
||||
|
||||
cout << "RPi/RF24/examples/gettingstarted_call_response_int\n";
|
||||
radio.begin();
|
||||
radio.enableAckPayload(); // Allow optional ack payloads
|
||||
radio.enableDynamicPayloads();
|
||||
radio.printDetails(); // Dump the configuration of the rf unit for debugging
|
||||
|
||||
|
||||
/********* Role chooser ***********/
|
||||
|
||||
printf("\n ************ Role Setup ***********\n");
|
||||
string input = "";
|
||||
char myChar = {0};
|
||||
cout << "Choose a role: Enter 0 for pong_back, 1 for ping_out (CTRL+C to exit)\n>";
|
||||
getline(cin,input);
|
||||
|
||||
if(input.length() == 1) {
|
||||
myChar = input[0];
|
||||
if(myChar == '0'){
|
||||
cout << "Role: Pong Back, awaiting transmission " << endl << endl;
|
||||
}else{ cout << "Role: Ping Out, starting transmission " << endl << endl;
|
||||
role = role_ping_out;
|
||||
}
|
||||
}
|
||||
/***********************************/
|
||||
// This opens two pipes for these two nodes to communicate
|
||||
// back and forth.
|
||||
if ( !radioNumber ) {
|
||||
radio.openWritingPipe(addresses[0]);
|
||||
radio.openReadingPipe(1,addresses[1]);
|
||||
}else{
|
||||
radio.openWritingPipe(addresses[1]);
|
||||
radio.openReadingPipe(1,addresses[0]);
|
||||
}
|
||||
radio.startListening();
|
||||
radio.writeAckPayload(1,&counter,1);
|
||||
|
||||
radio.maskIRQ(1,1,0); //Mask tx_ok & tx_fail interrupts
|
||||
attachInterrupt(interruptPin, INT_EDGE_FALLING, intHandler); //Attach interrupt to bcm pin 23
|
||||
|
||||
// forever loop
|
||||
while (1){
|
||||
|
||||
|
||||
/****************** Ping Out Role ***************************/
|
||||
|
||||
if (role == role_ping_out){ // Radio is in ping mode
|
||||
|
||||
uint8_t gotByte; // Initialize a variable for the incoming response
|
||||
|
||||
radio.stopListening(); // First, stop listening so we can talk.
|
||||
printf("Now sending %d as payload. ",counter); // Use a simple byte counter as payload
|
||||
unsigned long time = millis(); // Record the current microsecond count
|
||||
|
||||
if ( radio.write(&counter,1) ){ // Send the counter variable to the other radio
|
||||
if(!radio.available()){ // If nothing in the buffer, we got an ack but it is blank
|
||||
printf("Got blank response. round-trip delay: %lu ms\n\r",millis()-time);
|
||||
}else{
|
||||
|
||||
while(radio.available() ){ // If an ack with payload was received
|
||||
radio.read( &gotByte, 1 ); // Read it, and display the response time
|
||||
printf("Got response %d, round-trip delay: %lu ms\n\r",gotByte,millis()-time);
|
||||
counter++; // Increment the counter variable
|
||||
}
|
||||
}
|
||||
|
||||
}else{ printf("Sending failed.\n\r"); } // If no ack response, sending failed
|
||||
|
||||
sleep(1); // Try again later
|
||||
}
|
||||
|
||||
/****************** Pong Back Role ***************************/
|
||||
|
||||
|
||||
|
||||
} //while 1
|
||||
} //main
|
||||
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
TMRh20 2014 - Updated to work with optimized RF24 Arduino library
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Example for efficient call-response using ack-payloads
|
||||
*
|
||||
* This example continues to make use of all the normal functionality of the radios including
|
||||
* the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
|
||||
* This allows very fast call-response communication, with the responding radio never having to
|
||||
* switch out of Primary Receiver mode to send back a payload, but having the option to switch to
|
||||
* primary transmitter if wanting to initiate communication instead of respond to a commmunication.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <RF24/RF24.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//
|
||||
// Hardware configuration
|
||||
// Configure the appropriate pins for your connections
|
||||
|
||||
/****************** Raspberry Pi ***********************/
|
||||
|
||||
RF24 radio(22,0);
|
||||
|
||||
/********** User Config *********/
|
||||
// Assign a unique identifier for this node, 0 or 1. Arduino example uses radioNumber 0 by default.
|
||||
bool radioNumber = 1;
|
||||
int interruptPin = 23;
|
||||
/********************************/
|
||||
|
||||
|
||||
// Radio pipe addresses for the 2 nodes to communicate.
|
||||
const uint8_t addresses[][6] = {"1Node","2Node"};
|
||||
|
||||
bool role_ping_out = 1, role_pong_back = 0, role = 0;
|
||||
uint8_t counter = 1; // A single byte to keep track of the data being sent back and forth
|
||||
uint32_t timer = 0;
|
||||
|
||||
void intHandler(){
|
||||
|
||||
bool tx_ok,tx_fail,rx;
|
||||
radio.whatHappened(tx_ok,tx_fail,rx);
|
||||
|
||||
if(tx_fail){
|
||||
printf("Sending failed.\n\r");
|
||||
}
|
||||
|
||||
if(role == role_ping_out && tx_ok){
|
||||
if(!radio.available()){
|
||||
printf("Got blank response. round-trip delay: %u ms\n\r",millis()-timer);
|
||||
}
|
||||
}
|
||||
|
||||
if(role == role_ping_out ){
|
||||
while(radio.available() ){
|
||||
uint8_t gotByte;
|
||||
radio.read( &gotByte, 1 );
|
||||
printf("Got response %d, round-trip delay: %u ms\n\r",gotByte,millis()-timer);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( role == role_pong_back){
|
||||
if(tx_ok) {
|
||||
printf("Ack Payload Sent\n");
|
||||
}
|
||||
uint8_t pipeNo, gotByte;
|
||||
if( radio.available(&pipeNo)){
|
||||
radio.read( &gotByte, 1 );
|
||||
|
||||
gotByte += 1;
|
||||
radio.writeAckPayload(pipeNo,&gotByte, 1 );
|
||||
printf("Loaded next response %d \n\r", gotByte);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv){
|
||||
|
||||
|
||||
cout << "RPi/RF24/examples/gettingstarted_call_response\n";
|
||||
radio.begin();
|
||||
radio.enableAckPayload(); // Allow optional ack payloads
|
||||
radio.enableDynamicPayloads();
|
||||
radio.printDetails(); // Dump the configuration of the rf unit for debugging
|
||||
|
||||
|
||||
/********* Role chooser ***********/
|
||||
|
||||
printf("\n ************ Role Setup ***********\n");
|
||||
string input = "";
|
||||
char myChar = {0};
|
||||
cout << "Choose a role: Enter 0 for pong_back, 1 for ping_out (CTRL+C to exit)\n>";
|
||||
getline(cin,input);
|
||||
|
||||
if(input.length() == 1) {
|
||||
myChar = input[0];
|
||||
if(myChar == '0'){
|
||||
cout << "Role: Pong Back, awaiting transmission " << endl << endl;
|
||||
}else{ cout << "Role: Ping Out, starting transmission " << endl << endl;
|
||||
role = role_ping_out;
|
||||
}
|
||||
}
|
||||
/***********************************/
|
||||
// This opens two pipes for these two nodes to communicate
|
||||
// back and forth.
|
||||
if ( !radioNumber ) {
|
||||
radio.openWritingPipe(addresses[0]);
|
||||
radio.openReadingPipe(1,addresses[1]);
|
||||
}else{
|
||||
radio.openWritingPipe(addresses[1]);
|
||||
radio.openReadingPipe(1,addresses[0]);
|
||||
}
|
||||
radio.startListening();
|
||||
radio.writeAckPayload(1,&counter,1);
|
||||
|
||||
attachInterrupt(interruptPin, INT_EDGE_FALLING, intHandler); //Attach interrupt to bcm pin 23
|
||||
|
||||
// forever loop
|
||||
while (1){
|
||||
|
||||
|
||||
/****************** Ping Out Role ***************************/
|
||||
|
||||
if (role == role_ping_out){ // Radio is in ping mode
|
||||
|
||||
//uint8_t gotByte; // Initialize a variable for the incoming response
|
||||
|
||||
radio.stopListening(); // First, stop listening so we can talk.
|
||||
printf("Now sending %d as payload. ",counter); // Use a simple byte counter as payload
|
||||
timer = millis(); // Record the current microsecond count
|
||||
|
||||
radio.startWrite(&counter,1,false); // Send the counter variable to the other radio
|
||||
sleep(1); // Try again later
|
||||
}
|
||||
|
||||
/****************** Pong Back Role ***************************/
|
||||
|
||||
|
||||
|
||||
} //while 1
|
||||
} //main
|
||||
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
TMRh20 2014 - Optimized RF24 Library Fork
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example using Dynamic Payloads
|
||||
*
|
||||
* This is an example of how to use payloads of a varying (dynamic) size.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <RF24/RF24.h>
|
||||
|
||||
|
||||
using namespace std;
|
||||
//
|
||||
// Hardware configuration
|
||||
// Configure the appropriate pins for your connections
|
||||
|
||||
/****************** Raspberry Pi ***********************/
|
||||
|
||||
RF24 radio(22,0); // CE GPIO, CSN SPI-BUS
|
||||
|
||||
int interruptPin = 23; // GPIO pin for interrupts
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
// Radio pipe addresses for the 2 nodes to communicate.
|
||||
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
|
||||
|
||||
|
||||
|
||||
const int min_payload_size = 4;
|
||||
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
|
||||
bool role_ping_out = 1, role_pong_back = 0;
|
||||
bool role = 0;
|
||||
|
||||
void intHandler(){
|
||||
//
|
||||
// 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=0;
|
||||
|
||||
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
|
||||
printf("Got payload size=%i value=%s\n\r",len,receive_payload);
|
||||
}
|
||||
|
||||
// First, stop listening so we can talk
|
||||
radio.stopListening();
|
||||
|
||||
// Send the final one back.
|
||||
radio.write( receive_payload, len );
|
||||
printf("Sent response.\n\r");
|
||||
|
||||
// Now, resume listening so we catch the next packets.
|
||||
radio.startListening();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv){
|
||||
|
||||
|
||||
// Print preamble:
|
||||
cout << "RF24/examples/pingpair_dyn/\n";
|
||||
|
||||
// Setup and configure rf radio
|
||||
radio.begin();
|
||||
radio.enableDynamicPayloads();
|
||||
radio.setRetries(5,15);
|
||||
radio.printDetails();
|
||||
|
||||
|
||||
/********* Role chooser ***********/
|
||||
|
||||
printf("\n ************ Role Setup ***********\n");
|
||||
string input = "";
|
||||
char myChar = {0};
|
||||
cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit) \n>";
|
||||
getline(cin,input);
|
||||
|
||||
if(input.length() == 1) {
|
||||
myChar = input[0];
|
||||
if(myChar == '0'){
|
||||
cout << "Role: Pong Back, awaiting transmission " << endl << endl;
|
||||
}else{ cout << "Role: Ping Out, starting transmission " << endl << endl;
|
||||
role = role_ping_out;
|
||||
}
|
||||
}
|
||||
/***********************************/
|
||||
|
||||
if ( role == role_ping_out ) {
|
||||
radio.openWritingPipe(pipes[0]);
|
||||
radio.openReadingPipe(1,pipes[1]);
|
||||
} else {
|
||||
radio.openWritingPipe(pipes[1]);
|
||||
radio.openReadingPipe(1,pipes[0]);
|
||||
radio.startListening();
|
||||
}
|
||||
attachInterrupt(interruptPin, INT_EDGE_FALLING, intHandler); //Attach interrupt to bcm pin 23
|
||||
|
||||
// forever loop
|
||||
while (1)
|
||||
{
|
||||
|
||||
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
|
||||
printf("Now sending length %i...",next_payload_size);
|
||||
radio.write( send_payload, next_payload_size );
|
||||
|
||||
// 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 )
|
||||
{
|
||||
printf("Failed, response timed out.\n\r");
|
||||
}
|
||||
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
|
||||
printf("Got response size=%i value=%s\n\r",len,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(100);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
/** General Data Transfer Rate Test
|
||||
* This example demonstrates basic data transfer functionality with the
|
||||
updated library. This example will display the transfer rates acheived using
|
||||
the slower form of high-speed transfer using blocking-writes.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <RF24/RF24.h>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace std;
|
||||
//
|
||||
// Hardware configuration
|
||||
//
|
||||
|
||||
/****************** Raspberry Pi ***********************/
|
||||
|
||||
// Radio CE Pin, CSN Pin, SPI Speed
|
||||
// See http://www.airspayce.com/mikem/bcm2835/group__constants.html#ga63c029bd6500167152db4e57736d0939 and the related enumerations for pin information.
|
||||
|
||||
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
|
||||
//RF24 radio(RPI_V2_GPIO_P1_22, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
|
||||
|
||||
// NEW: Setup for RPi B+
|
||||
//RF24 radio(RPI_BPLUS_GPIO_J8_15,RPI_BPLUS_GPIO_J8_24, BCM2835_SPI_SPEED_8MHZ);
|
||||
|
||||
// Setup for GPIO 15 CE and CE0 CSN with SPI Speed @ 8Mhz
|
||||
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
|
||||
|
||||
/*** RPi Alternate ***/
|
||||
//Note: Specify SPI BUS 0 or 1 instead of CS pin number.
|
||||
// See http://tmrh20.github.io/RF24/RPi.html for more information on usage
|
||||
|
||||
//RPi Alternate, with MRAA
|
||||
//RF24 radio(15,0);
|
||||
|
||||
//RPi Alternate, with SPIDEV - Note: Edit RF24/arch/BBB/spi.cpp and set 'this->device = "/dev/spidev0.0";;' or as listed in /dev
|
||||
//RF24 radio(22,0);
|
||||
|
||||
|
||||
/****************** Linux (BBB,x86,etc) ***********************/
|
||||
|
||||
// See http://tmrh20.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 for ARM(Linux) devices like BBB using spidev (default is "/dev/spidev1.0" )
|
||||
//RF24 radio(115,0);
|
||||
|
||||
//BBB Alternate, with mraa
|
||||
// CE pin = (Header P9, Pin 13) = 59 = 13 + 46
|
||||
//Note: Specify SPI BUS 0 or 1 instead of CS pin number.
|
||||
//RF24 radio(59,0);
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
// Radio pipe addresses for the 2 nodes to communicate.
|
||||
const uint64_t addresses[2] = { 0xABCDABCD71LL, 0x544d52687CLL };
|
||||
|
||||
|
||||
uint8_t data[32];
|
||||
unsigned long startTime, stopTime, counter, rxTimer=0;
|
||||
|
||||
void intHandler()
|
||||
{
|
||||
//Read as long data is available
|
||||
//Single interrupts may be lost if a lot of data comes in.
|
||||
while(radio.available())
|
||||
{
|
||||
radio.read(&data,32);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv){
|
||||
|
||||
bool role_ping_out = 1, role_pong_back = 0;
|
||||
bool role = 0;
|
||||
|
||||
// Print preamble:
|
||||
|
||||
cout << "RF24/examples/Transfer/\n";
|
||||
|
||||
radio.begin(); // Setup and configure rf radio
|
||||
radio.setChannel(1);
|
||||
radio.setPALevel(RF24_PA_MAX);
|
||||
radio.setDataRate(RF24_1MBPS);
|
||||
radio.setAutoAck(1); // Ensure autoACK is enabled
|
||||
radio.setRetries(2,15); // Optionally, increase the delay between retries & # of retries
|
||||
radio.setCRCLength(RF24_CRC_8); // Use 8-bit CRC for performance
|
||||
radio.printDetails();
|
||||
/********* Role chooser ***********/
|
||||
|
||||
printf("\n ************ Role Setup ***********\n");
|
||||
string input = "";
|
||||
char myChar = {0};
|
||||
cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit)\n>";
|
||||
getline(cin,input);
|
||||
|
||||
attachInterrupt(23, INT_EDGE_FALLING, intHandler); //Attach interrupt to bcm pin 23
|
||||
|
||||
if(input.length() == 1) {
|
||||
myChar = input[0];
|
||||
if(myChar == '0'){
|
||||
cout << "Role: Pong Back, awaiting transmission " << endl << endl;
|
||||
}else{ cout << "Role: Ping Out, starting transmission " << endl << endl;
|
||||
role = role_ping_out;
|
||||
}
|
||||
}
|
||||
/***********************************/
|
||||
|
||||
if ( role == role_ping_out ) {
|
||||
radio.openWritingPipe(addresses[1]);
|
||||
radio.openReadingPipe(1,addresses[0]);
|
||||
radio.stopListening();
|
||||
} else {
|
||||
radio.openWritingPipe(addresses[0]);
|
||||
radio.openReadingPipe(1,addresses[1]);
|
||||
radio.startListening();
|
||||
}
|
||||
|
||||
|
||||
for(int i=0; i<32; i++){
|
||||
data[i] = rand() % 255; //Load the buffer with random data
|
||||
}
|
||||
|
||||
// forever loop
|
||||
while (1)
|
||||
{
|
||||
if (role == role_ping_out){
|
||||
sleep(2);
|
||||
printf("Initiating Basic Data Transfer\n\r");
|
||||
|
||||
long int cycles = 10000; //Change this to a higher or lower number.
|
||||
|
||||
// unsigned long pauseTime = millis(); //Uncomment if autoAck == 1 ( NOACK )
|
||||
startTime = millis();
|
||||
|
||||
for(int 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.writeFast(&data,32)){ //Write to the FIFO buffers
|
||||
counter++; //Keep count of failed payloads
|
||||
}
|
||||
|
||||
|
||||
//This is only required when NO ACK ( enableAutoAck(0) ) payloads are used
|
||||
/* if(millis() - pauseTime > 3){ // Need to drop out of TX mode every 4ms if sending a steady stream of multicast data
|
||||
pauseTime = millis();
|
||||
radio.txStandBy(); // This gives the PLL time to sync back up
|
||||
}
|
||||
*/
|
||||
}
|
||||
stopTime = millis();
|
||||
|
||||
if(!radio.txStandBy()){ counter+=3; }
|
||||
|
||||
float numBytes = cycles*32;
|
||||
float rate = numBytes / (stopTime - startTime);
|
||||
|
||||
printf("Transfer complete at %.2f KB/s \n\r",rate);
|
||||
printf("%lu of %lu Packets Failed to Send\n\r",counter,cycles);
|
||||
counter = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(role == role_pong_back)
|
||||
{
|
||||
if(millis() - rxTimer > 1000){
|
||||
rxTimer = millis();
|
||||
printf("Rate: ");
|
||||
float numBytes = counter*32;
|
||||
printf("%.2f KB/s \n\r",numBytes/1000);
|
||||
printf("Payload Count: %lu \n\r", counter);
|
||||
counter = 0;
|
||||
}
|
||||
delay(2);
|
||||
}
|
||||
|
||||
} // loop
|
||||
} // main
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
TMRh20 2014 - Optimized RF24 Library Fork
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example using Dynamic Payloads
|
||||
*
|
||||
* This is an example of how to use payloads of a varying (dynamic) size.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include "./RF24.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
//
|
||||
// Hardware configuration
|
||||
// Configure the appropriate pins for your connections
|
||||
|
||||
/****************** Raspberry Pi ***********************/
|
||||
|
||||
// Radio CE Pin, CSN Pin, SPI Speed
|
||||
// See http://www.airspayce.com/mikem/bcm2835/group__constants.html#ga63c029bd6500167152db4e57736d0939 and the related enumerations for pin information.
|
||||
|
||||
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
|
||||
//RF24 radio(RPI_V2_GPIO_P1_22, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
|
||||
|
||||
// NEW: Setup for RPi B+
|
||||
//RF24 radio(RPI_BPLUS_GPIO_J8_15,RPI_BPLUS_GPIO_J8_24, BCM2835_SPI_SPEED_8MHZ);
|
||||
|
||||
// Setup for GPIO 15 CE and CE0 CSN with SPI Speed @ 8Mhz
|
||||
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
|
||||
|
||||
/*** RPi Alternate ***/
|
||||
//Note: Specify SPI BUS 0 or 1 instead of CS pin number.
|
||||
// See http://tmrh20.github.io/RF24/RPi.html for more information on usage
|
||||
|
||||
//RPi Alternate, with MRAA
|
||||
//RF24 radio(15,0);
|
||||
|
||||
//RPi Alternate, with SPIDEV - Note: Edit RF24/arch/BBB/spi.cpp and set 'this->device = "/dev/spidev0.0";;' or as listed in /dev
|
||||
//RF24 radio(22,0);
|
||||
|
||||
|
||||
/****************** Linux (BBB,x86,etc) ***********************/
|
||||
|
||||
// See http://tmrh20.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 for ARM(Linux) devices like BBB using spidev (default is "/dev/spidev1.0" )
|
||||
//RF24 radio(115,0);
|
||||
|
||||
//BBB Alternate, with mraa
|
||||
// CE pin = (Header P9, Pin 13) = 59 = 13 + 46
|
||||
//Note: Specify SPI BUS 0 or 1 instead of CS pin number.
|
||||
//RF24 radio(59,0);
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
// Radio pipe addresses for the 2 nodes to communicate.
|
||||
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
|
||||
|
||||
|
||||
|
||||
const int min_payload_size = 4;
|
||||
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
|
||||
|
||||
int main(int argc, char** argv){
|
||||
|
||||
bool role_ping_out = 1, role_pong_back = 0;
|
||||
bool role = 0;
|
||||
|
||||
// Print preamble:
|
||||
cout << "RF24/examples/pingpair_dyn/\n";
|
||||
|
||||
// Setup and configure rf radio
|
||||
radio.begin();
|
||||
radio.enableDynamicPayloads();
|
||||
radio.setRetries(5,15);
|
||||
radio.printDetails();
|
||||
|
||||
|
||||
/********* Role chooser ***********/
|
||||
|
||||
printf("\n ************ Role Setup ***********\n");
|
||||
string input = "";
|
||||
char myChar = {0};
|
||||
cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit) \n>";
|
||||
getline(cin,input);
|
||||
|
||||
if(input.length() == 1) {
|
||||
myChar = input[0];
|
||||
if(myChar == '0'){
|
||||
cout << "Role: Pong Back, awaiting transmission " << endl << endl;
|
||||
}else{ cout << "Role: Ping Out, starting transmission " << endl << endl;
|
||||
role = role_ping_out;
|
||||
}
|
||||
}
|
||||
/***********************************/
|
||||
|
||||
if ( role == role_ping_out ) {
|
||||
radio.openWritingPipe(pipes[0]);
|
||||
radio.openReadingPipe(1,pipes[1]);
|
||||
} else {
|
||||
radio.openWritingPipe(pipes[1]);
|
||||
radio.openReadingPipe(1,pipes[0]);
|
||||
radio.startListening();
|
||||
}
|
||||
|
||||
|
||||
// forever loop
|
||||
while (1)
|
||||
{
|
||||
|
||||
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
|
||||
printf("Now sending length %i...",next_payload_size);
|
||||
radio.write( send_payload, next_payload_size );
|
||||
|
||||
// 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 )
|
||||
{
|
||||
printf("Failed, response timed out.\n\r");
|
||||
}
|
||||
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
|
||||
printf("Got response size=%i value=%s\n\r",len,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(100);
|
||||
}
|
||||
|
||||
//
|
||||
// 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;
|
||||
|
||||
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
|
||||
printf("Got payload size=%i value=%s\n\r",len,receive_payload);
|
||||
}
|
||||
|
||||
// First, stop listening so we can talk
|
||||
radio.stopListening();
|
||||
|
||||
// Send the final one back.
|
||||
radio.write( receive_payload, len );
|
||||
printf("Sent response.\n\r");
|
||||
|
||||
// Now, resume listening so we catch the next packets.
|
||||
radio.startListening();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
#
|
||||
# Example using Dynamic Payloads
|
||||
#
|
||||
# This is an example of how to use payloads of a varying (dynamic) size.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
import time
|
||||
from RF24 import *
|
||||
import RPi.GPIO as GPIO
|
||||
|
||||
irq_gpio_pin = None
|
||||
|
||||
########### USER CONFIGURATION ###########
|
||||
# See https://github.com/TMRh20/RF24/blob/master/pyRF24/readme.md
|
||||
|
||||
# CE Pin, CSN Pin, SPI Speed
|
||||
|
||||
# Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 8Mhz
|
||||
#radio = RF24(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ)
|
||||
|
||||
#RPi B
|
||||
# Setup for GPIO 15 CE and CE1 CSN with SPI Speed @ 8Mhz
|
||||
#radio = RF24(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ)
|
||||
|
||||
#RPi B+
|
||||
# Setup for GPIO 22 CE and CE0 CSN for RPi B+ with SPI Speed @ 8Mhz
|
||||
#radio = RF24(RPI_BPLUS_GPIO_J8_15, RPI_BPLUS_GPIO_J8_24, BCM2835_SPI_SPEED_8MHZ)
|
||||
|
||||
# RPi Alternate, with SPIDEV - Note: Edit RF24/arch/BBB/spi.cpp and set 'this->device = "/dev/spidev0.0";;' or as listed in /dev
|
||||
radio = RF24(22, 0);
|
||||
|
||||
|
||||
# Setup for connected IRQ pin, GPIO 24 on RPi B+; uncomment to activate
|
||||
#irq_gpio_pin = RPI_BPLUS_GPIO_J8_18
|
||||
#irq_gpio_pin = 24
|
||||
|
||||
##########################################
|
||||
def try_read_data(channel=0):
|
||||
if radio.available():
|
||||
while radio.available():
|
||||
len = radio.getDynamicPayloadSize()
|
||||
receive_payload = radio.read(len)
|
||||
print('Got payload size={} value="{}"'.format(len, receive_payload.decode('utf-8')))
|
||||
# First, stop listening so we can talk
|
||||
radio.stopListening()
|
||||
|
||||
# Send the final one back.
|
||||
radio.write(receive_payload)
|
||||
print('Sent response.')
|
||||
|
||||
# Now, resume listening so we catch the next packets.
|
||||
radio.startListening()
|
||||
|
||||
pipes = [0xF0F0F0F0E1, 0xF0F0F0F0D2]
|
||||
min_payload_size = 4
|
||||
max_payload_size = 32
|
||||
payload_size_increments_by = 1
|
||||
next_payload_size = min_payload_size
|
||||
inp_role = 'none'
|
||||
send_payload = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ789012'
|
||||
millis = lambda: int(round(time.time() * 1000))
|
||||
|
||||
print('pyRF24/examples/pingpair_dyn/')
|
||||
radio.begin()
|
||||
radio.enableDynamicPayloads()
|
||||
radio.setRetries(5,15)
|
||||
radio.printDetails()
|
||||
|
||||
print(' ************ Role Setup *********** ')
|
||||
while (inp_role !='0') and (inp_role !='1'):
|
||||
inp_role = str(input('Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit) '))
|
||||
|
||||
if inp_role == '0':
|
||||
print('Role: Pong Back, awaiting transmission')
|
||||
if irq_gpio_pin is not None:
|
||||
# set up callback for irq pin
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.setup(irq_gpio_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
|
||||
GPIO.add_event_detect(irq_gpio_pin, GPIO.FALLING, callback=try_read_data)
|
||||
|
||||
radio.openWritingPipe(pipes[1])
|
||||
radio.openReadingPipe(1,pipes[0])
|
||||
radio.startListening()
|
||||
else:
|
||||
print('Role: Ping Out, starting transmission')
|
||||
radio.openWritingPipe(pipes[0])
|
||||
radio.openReadingPipe(1,pipes[1])
|
||||
|
||||
# forever loop
|
||||
while 1:
|
||||
if inp_role == '1': # ping out
|
||||
# The payload will always be the same, what will change is how much of it we send.
|
||||
|
||||
# First, stop listening so we can talk.
|
||||
radio.stopListening()
|
||||
|
||||
# Take the time, and send it. This will block until complete
|
||||
print('Now sending length {} ... '.format(next_payload_size), end="")
|
||||
radio.write(send_payload[:next_payload_size])
|
||||
|
||||
# Now, continue listening
|
||||
radio.startListening()
|
||||
|
||||
# Wait here until we get a response, or timeout
|
||||
started_waiting_at = millis()
|
||||
timeout = False
|
||||
while (not radio.available()) and (not timeout):
|
||||
if (millis() - started_waiting_at) > 500:
|
||||
timeout = True
|
||||
|
||||
# Describe the results
|
||||
if timeout:
|
||||
print('failed, response timed out.')
|
||||
else:
|
||||
# Grab the response, compare, and send to debugging spew
|
||||
len = radio.getDynamicPayloadSize()
|
||||
receive_payload = radio.read(len)
|
||||
|
||||
# Spew it
|
||||
print('got response size={} value="{}"'.format(len, receive_payload.decode('utf-8')))
|
||||
|
||||
# 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
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
# Pong back role. Receive each packet, dump it out, and send it back
|
||||
|
||||
# if there is data ready
|
||||
if irq_gpio_pin is None:
|
||||
# no irq pin is set up -> poll it
|
||||
try_read_data()
|
||||
else:
|
||||
# callback routine set for irq pin takes care for reading -
|
||||
# do nothing, just sleeps in order not to burn cpu by looping
|
||||
time.sleep(1000)
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
Note: These examples were originally designed for RPi, but should work on any supported Linux platform, with the proper pin configuration.
|
||||
|
||||
See http://tmrh20.github.io/RF24 for more information
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
/** General Data Transfer Rate Test
|
||||
* This example demonstrates basic data transfer functionality with the
|
||||
updated library. This example will display the transfer rates acheived using
|
||||
the slower form of high-speed transfer using blocking-writes.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <RF24/RF24.h>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace std;
|
||||
//
|
||||
// Hardware configuration
|
||||
//
|
||||
|
||||
/****************** Raspberry Pi ***********************/
|
||||
|
||||
// Radio CE Pin, CSN Pin, SPI Speed
|
||||
// See http://www.airspayce.com/mikem/bcm2835/group__constants.html#ga63c029bd6500167152db4e57736d0939 and the related enumerations for pin information.
|
||||
|
||||
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
|
||||
//RF24 radio(RPI_V2_GPIO_P1_22, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
|
||||
|
||||
// NEW: Setup for RPi B+
|
||||
//RF24 radio(RPI_BPLUS_GPIO_J8_15,RPI_BPLUS_GPIO_J8_24, BCM2835_SPI_SPEED_8MHZ);
|
||||
|
||||
// Setup for GPIO 15 CE and CE0 CSN with SPI Speed @ 8Mhz
|
||||
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
|
||||
|
||||
/*** RPi Alternate ***/
|
||||
//Note: Specify SPI BUS 0 or 1 instead of CS pin number.
|
||||
// See http://tmrh20.github.io/RF24/RPi.html for more information on usage
|
||||
|
||||
//RPi Alternate, with MRAA
|
||||
//RF24 radio(15,0);
|
||||
|
||||
//RPi Alternate, with SPIDEV - Note: Edit RF24/arch/BBB/spi.cpp and set 'this->device = "/dev/spidev0.0";;' or as listed in /dev
|
||||
//RF24 radio(22,0);
|
||||
|
||||
|
||||
/****************** Linux (BBB,x86,etc) ***********************/
|
||||
|
||||
// See http://tmrh20.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 for ARM(Linux) devices like BBB using spidev (default is "/dev/spidev1.0" )
|
||||
//RF24 radio(115,0);
|
||||
|
||||
//BBB Alternate, with mraa
|
||||
// CE pin = (Header P9, Pin 13) = 59 = 13 + 46
|
||||
//Note: Specify SPI BUS 0 or 1 instead of CS pin number.
|
||||
//RF24 radio(59,0);
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
// Radio pipe addresses for the 2 nodes to communicate.
|
||||
const uint64_t addresses[2] = { 0xABCDABCD71LL, 0x544d52687CLL };
|
||||
|
||||
|
||||
uint8_t data[32];
|
||||
unsigned long startTime, stopTime, counter, rxTimer=0;
|
||||
|
||||
int main(int argc, char** argv){
|
||||
|
||||
bool role_ping_out = 1, role_pong_back = 0;
|
||||
bool role = 0;
|
||||
|
||||
// Print preamble:
|
||||
|
||||
cout << "RF24/examples/Transfer/\n";
|
||||
|
||||
radio.begin(); // Setup and configure rf radio
|
||||
radio.setChannel(1);
|
||||
radio.setPALevel(RF24_PA_MAX);
|
||||
radio.setDataRate(RF24_1MBPS);
|
||||
radio.setAutoAck(1); // Ensure autoACK is enabled
|
||||
radio.setRetries(2,15); // Optionally, increase the delay between retries & # of retries
|
||||
radio.setCRCLength(RF24_CRC_8); // Use 8-bit CRC for performance
|
||||
radio.printDetails();
|
||||
/********* Role chooser ***********/
|
||||
|
||||
printf("\n ************ Role Setup ***********\n");
|
||||
string input = "";
|
||||
char myChar = {0};
|
||||
cout << "Choose a role: Enter 0 for receiver, 1 for transmitter (CTRL+C to exit)\n>";
|
||||
getline(cin,input);
|
||||
|
||||
if(input.length() == 1) {
|
||||
myChar = input[0];
|
||||
if(myChar == '0'){
|
||||
cout << "Role: Pong Back, awaiting transmission " << endl << endl;
|
||||
}else{ cout << "Role: Ping Out, starting transmission " << endl << endl;
|
||||
role = role_ping_out;
|
||||
}
|
||||
}
|
||||
/***********************************/
|
||||
|
||||
if ( role == role_ping_out ) {
|
||||
radio.openWritingPipe(addresses[1]);
|
||||
radio.openReadingPipe(1,addresses[0]);
|
||||
radio.stopListening();
|
||||
} else {
|
||||
radio.openWritingPipe(addresses[0]);
|
||||
radio.openReadingPipe(1,addresses[1]);
|
||||
radio.startListening();
|
||||
}
|
||||
|
||||
|
||||
for(int i=0; i<32; i++){
|
||||
data[i] = rand() % 255; //Load the buffer with random data
|
||||
}
|
||||
|
||||
// forever loop
|
||||
while (1){
|
||||
|
||||
if (role == role_ping_out){
|
||||
sleep(2);
|
||||
printf("Initiating Basic Data Transfer\n\r");
|
||||
|
||||
long int cycles = 10000; //Change this to a higher or lower number.
|
||||
|
||||
// unsigned long pauseTime = millis(); //Uncomment if autoAck == 1 ( NOACK )
|
||||
startTime = millis();
|
||||
|
||||
for(int 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.writeFast(&data,32)){ //Write to the FIFO buffers
|
||||
counter++; //Keep count of failed payloads
|
||||
}
|
||||
|
||||
|
||||
//This is only required when NO ACK ( enableAutoAck(0) ) payloads are used
|
||||
/* if(millis() - pauseTime > 3){ // Need to drop out of TX mode every 4ms if sending a steady stream of multicast data
|
||||
pauseTime = millis();
|
||||
radio.txStandBy(); // This gives the PLL time to sync back up
|
||||
}
|
||||
*/
|
||||
}
|
||||
stopTime = millis();
|
||||
|
||||
if(!radio.txStandBy()){ counter+=3; }
|
||||
|
||||
float numBytes = cycles*32;
|
||||
float rate = numBytes / (stopTime - startTime);
|
||||
|
||||
printf("Transfer complete at %.2f KB/s \n\r",rate);
|
||||
printf("%lu of %lu Packets Failed to Send\n\r",counter,cycles);
|
||||
counter = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
if(role == role_pong_back){
|
||||
while(radio.available()){
|
||||
radio.read(&data,32);
|
||||
counter++;
|
||||
}
|
||||
if(millis() - rxTimer > 1000){
|
||||
rxTimer = millis();
|
||||
printf("Rate: ");
|
||||
float numBytes = counter*32;
|
||||
printf("%.2f KB/s \n\r",numBytes/1000);
|
||||
printf("Payload Count: %lu \n\r", counter);
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // loop
|
||||
} // main
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
RF24 KEYWORD1
|
||||
begin KEYWORD2
|
||||
setChannel KEYWORD2
|
||||
setPayloadSize KEYWORD2
|
||||
getPayloadSize KEYWORD2
|
||||
print_details KEYWORD2
|
||||
startListening KEYWORD2
|
||||
stopListening KEYWORD2
|
||||
write KEYWORD2
|
||||
writeFast KEYWORD2
|
||||
writeBlocking KEYWORD2
|
||||
txStandBy KEYWORD2
|
||||
available KEYWORD2
|
||||
read KEYWORD2
|
||||
openWritingPipe KEYWORD2
|
||||
openReadingPipe KEYWORD2
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "RF24",
|
||||
"keywords": "rf, radio, wireless, spi",
|
||||
"description": "Optimized High Speed Driver for nRF24L01(+) 2.4GHz Wireless Transceiver",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/nRF24/RF24.git"
|
||||
},
|
||||
"version": "1.3.3",
|
||||
"frameworks": "arduino",
|
||||
"platforms": [
|
||||
"atmelavr",
|
||||
"atmelsam",
|
||||
"teensy",
|
||||
"espressif32",
|
||||
"espressif8266",
|
||||
"linux_arm"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
name=RF24
|
||||
version=1.3.3
|
||||
author=TMRh20
|
||||
maintainer=TMRh20,Avamander
|
||||
sentence=A library for NRF24L01(+) communication.
|
||||
paragraph=Optimized library for nRF24L01(+) that is simple to use for beginners, but yet offers a lot for advanced users. It also has a lot of good examples how to use the library.
|
||||
category=Communication
|
||||
url=https://tmrh20.github.io/RF24/
|
||||
architectures=avr,arm,x86,esp8266,esp32
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
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 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
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
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
|
||||
}
|
||||
|
||||
#endif // __PRINTF_H__
|
|
@ -0,0 +1,38 @@
|
|||
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
|
|
@ -0,0 +1,330 @@
|
|||
#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);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
// exposing '#define's for SPI speed as this is needed for RF24 constructor
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_64MHZ") = BCM2835_SPI_SPEED_64MHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_32MHZ") = BCM2835_SPI_SPEED_32MHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_16MHZ") = BCM2835_SPI_SPEED_16MHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_8MHZ") = BCM2835_SPI_SPEED_8MHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_4MHZ") = BCM2835_SPI_SPEED_4MHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_2MHZ") = BCM2835_SPI_SPEED_2MHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_1MHZ") = BCM2835_SPI_SPEED_1MHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_512KHZ") = BCM2835_SPI_SPEED_512KHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_256KHZ") = BCM2835_SPI_SPEED_256KHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_128KHZ") = BCM2835_SPI_SPEED_128KHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_64KHZ") = BCM2835_SPI_SPEED_64KHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_32KHZ") = BCM2835_SPI_SPEED_32KHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_16KHZ") = BCM2835_SPI_SPEED_16KHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_8KHZ") = BCM2835_SPI_SPEED_8KHZ;
|
||||
#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("flush_tx", &RF24::flush_tx)
|
||||
.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("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("setChannel", &RF24::setChannel, ( bp::arg("channel") ) )
|
||||
.def("setDataRate", &RF24::setDataRate, ( bp::arg("speed") ) )
|
||||
.def("setPALevel", &RF24::setPALevel, ( 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("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("payloadSize", &RF24::getPayloadSize, &RF24::setPayloadSize)
|
||||
.def_readwrite( "failureDetected", &RF24::failureDetected );
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
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
|
|
@ -0,0 +1,328 @@
|
|||
#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);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
// exposing '#define's for SPI speed as this is needed for RF24 constructor
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_64MHZ") = BCM2835_SPI_SPEED_64MHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_32MHZ") = BCM2835_SPI_SPEED_32MHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_16MHZ") = BCM2835_SPI_SPEED_16MHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_8MHZ") = BCM2835_SPI_SPEED_8MHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_4MHZ") = BCM2835_SPI_SPEED_4MHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_2MHZ") = BCM2835_SPI_SPEED_2MHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_1MHZ") = BCM2835_SPI_SPEED_1MHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_512KHZ") = BCM2835_SPI_SPEED_512KHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_256KHZ") = BCM2835_SPI_SPEED_256KHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_128KHZ") = BCM2835_SPI_SPEED_128KHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_64KHZ") = BCM2835_SPI_SPEED_64KHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_32KHZ") = BCM2835_SPI_SPEED_32KHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_16KHZ") = BCM2835_SPI_SPEED_16KHZ;
|
||||
bp::scope().attr("BCM2835_SPI_SPEED_8KHZ") = BCM2835_SPI_SPEED_8KHZ;
|
||||
#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") )) )
|
||||
.def( bp::init< uint8_t, uint8_t, uint32_t >(( bp::arg("_cepin"), bp::arg("_cspin"), bp::arg("spispeed") )) )
|
||||
.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("flush_tx", &RF24::flush_tx)
|
||||
.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("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("setChannel", &RF24::setChannel, ( bp::arg("channel") ) )
|
||||
.def("setDataRate", &RF24::setDataRate, ( bp::arg("speed") ) )
|
||||
.def("setPALevel", &RF24::setPALevel, ( 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("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("payloadSize", &RF24::getPayloadSize, &RF24::setPayloadSize)
|
||||
.def_readwrite( "failureDetected", &RF24::failureDetected );
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
Python Wrapper for RF24
|
||||
See http://tmrh20.github.io/RF24 for more information
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
import setuptools
|
||||
import crossunixccompiler
|
||||
|
||||
version = ''
|
||||
|
||||
|
||||
def process_configparams():
|
||||
global version
|
||||
|
||||
with open('../Makefile.inc') 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
|
||||
|
||||
|
||||
if sys.version_info >= (3,):
|
||||
BOOST_LIB = 'boost_python3'
|
||||
else:
|
||||
BOOST_LIB = 'boost_python'
|
||||
|
||||
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])
|
|
@ -0,0 +1,22 @@
|
|||
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)
|
|
@ -0,0 +1,105 @@
|
|||
#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")));
|
||||
}
|
||||
}
|
|
@ -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,56 @@
|
|||
#!/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.')
|
|
@ -0,0 +1,143 @@
|
|||
#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 );
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#!/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]
|
||||
)
|
|
@ -0,0 +1,2 @@
|
|||
Python Wrapper for RF24
|
||||
See http://tmrh20.github.io/RF24 for more information
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
import setuptools
|
||||
import crossunixccompiler
|
||||
|
||||
version = ''
|
||||
|
||||
|
||||
def process_configparams():
|
||||
global version
|
||||
|
||||
with open('../Makefile.inc') 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
|
||||
|
||||
|
||||
if sys.version_info >= (3,):
|
||||
BOOST_LIB = 'boost_python3'
|
||||
else:
|
||||
BOOST_LIB = 'boost_python'
|
||||
|
||||
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])
|
|
@ -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
|
|
@ -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) ;
|
||||
|
|
@ -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();
|
||||
|
||||
//
|
||||
// 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
|
|
@ -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__
|
|
@ -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,273 @@
|
|||
/*
|
||||
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
|
|
@ -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__
|
|
@ -0,0 +1,25 @@
|
|||
#!/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)
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Connect u0 to receiver, u1 to sender
|
||||
|
||||
jam u0 u1 && expect test.ex
|
|
@ -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"
|
|
@ -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,435 @@
|
|||
/*
|
||||
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();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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__
|
|
@ -0,0 +1,25 @@
|
|||
#!/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)
|
|
@ -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
|
|
@ -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"
|
|
@ -0,0 +1,47 @@
|
|||
|
||||
/*
|
||||
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 the header file for SPI functions ( Main SPI code is contained in RF24.cpp for simplicity )
|
||||
#include "spi.h"
|
||||
|
||||
#define _SPI SPI
|
||||
|
||||
#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__
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
// ATTiny support code is from https://github.com/jscrane/RF24
|
||||
|
||||
/**
|
||||
* @file spi.h
|
||||
* \cond HIDDEN_SYMBOLS
|
||||
* Class declaration for SPI helper files
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Arduino.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#define SPI_CLOCK_DIV4 0x00
|
||||
#define SPI_CLOCK_DIV16 0x01
|
||||
#define SPI_CLOCK_DIV64 0x02
|
||||
#define SPI_CLOCK_DIV128 0x03
|
||||
#define SPI_CLOCK_DIV2 0x04
|
||||
#define SPI_CLOCK_DIV8 0x05
|
||||
#define SPI_CLOCK_DIV32 0x06
|
||||
//#define SPI_CLOCK_DIV64 0x07
|
||||
|
||||
#define SPI_MODE0 0x00
|
||||
#define SPI_MODE1 0x04
|
||||
#define SPI_MODE2 0x08
|
||||
#define SPI_MODE3 0x0C
|
||||
|
||||
#define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
|
||||
#define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
|
||||
#define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
|
||||
|
||||
|
||||
|
||||
class SPIClass {
|
||||
public:
|
||||
static byte transfer(byte _data);
|
||||
|
||||
// SPI Configuration methods
|
||||
|
||||
inline static void attachInterrupt();
|
||||
inline static void detachInterrupt(); // Default
|
||||
|
||||
static void begin(); // Default
|
||||
static void end();
|
||||
|
||||
static void setBitOrder(uint8_t);
|
||||
static void setDataMode(uint8_t);
|
||||
static void setClockDivider(uint8_t);
|
||||
};
|
||||
extern SPIClass SPI;
|
||||
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
|
@ -0,0 +1,54 @@
|
|||
This is a fork from **http://tmrh20.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://tmrh20.github.io/RF24 for all documentation**
|
|
@ -0,0 +1,85 @@
|
|||
|
||||
/*
|
||||
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__
|
||||
|
||||
|
||||
/*@}*/
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 */
|
||||
|
||||
/*@}*/
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @param value
|
||||
*/
|
||||
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 */
|
||||
/*@}*/
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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_ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue