Browse Source
Integrated lib into Project and fixed constantly showing 255 as PWMValue at no joystick modulation
master
Integrated lib into Project and fixed constantly showing 255 as PWMValue at no joystick modulation
master
Lukas Reichwein
5 years ago
147 changed files with 25722 additions and 13 deletions
-
2Code/libraries/Joystick/Steuerung.cpp
-
24Code/libraries/RF24-1.3.3/.gitignore
-
1Code/libraries/RF24-1.3.3/CONTRIBUTING.md
-
2462Code/libraries/RF24-1.3.3/Doxyfile
-
339Code/libraries/RF24-1.3.3/LICENSE
-
126Code/libraries/RF24-1.3.3/Makefile
-
2Code/libraries/RF24-1.3.3/README.md
-
1632Code/libraries/RF24-1.3.3/RF24.cpp
-
2030Code/libraries/RF24-1.3.3/RF24.h
-
166Code/libraries/RF24-1.3.3/RF24_config.h
-
473Code/libraries/RF24-1.3.3/configure
-
835Code/libraries/RF24-1.3.3/doxygen-custom.css
-
142Code/libraries/RF24-1.3.3/examples/GettingStarted/GettingStarted.ino
-
138Code/libraries/RF24-1.3.3/examples/GettingStarted_CallResponse/GettingStarted_CallResponse.ino
-
161Code/libraries/RF24-1.3.3/examples/GettingStarted_HandlingData/GettingStarted_HandlingData.ino
-
218Code/libraries/RF24-1.3.3/examples/GettingStarted_HandlingFailures/GettingStarted_HandlingFailures.ino
-
149Code/libraries/RF24-1.3.3/examples/Transfer/Transfer.ino
-
189Code/libraries/RF24-1.3.3/examples/TransferTimeouts/TransferTimeouts.ino
-
206Code/libraries/RF24-1.3.3/examples/Usage/led_remote/Jamfile
-
254Code/libraries/RF24-1.3.3/examples/Usage/led_remote/led_remote.pde
-
219Code/libraries/RF24-1.3.3/examples/Usage/nordic_fob/Jamfile
-
142Code/libraries/RF24-1.3.3/examples/Usage/nordic_fob/nordic_fob.pde
-
182Code/libraries/RF24-1.3.3/examples/Usage/pingpair_maple/Jamfile
-
87Code/libraries/RF24-1.3.3/examples/Usage/pingpair_maple/main.cpp
-
242Code/libraries/RF24-1.3.3/examples/Usage/pingpair_maple/pingpair_maple.pde
-
1Code/libraries/RF24-1.3.3/examples/Usage/readme.md
-
123Code/libraries/RF24-1.3.3/examples/pingpair_ack/pingpair_ack.ino
-
206Code/libraries/RF24-1.3.3/examples/pingpair_dyn/Jamfile
-
246Code/libraries/RF24-1.3.3/examples/pingpair_dyn/pingpair_dyn.ino
-
143Code/libraries/RF24-1.3.3/examples/pingpair_irq/pingpair_irq.ino
-
122Code/libraries/RF24-1.3.3/examples/pingpair_irq_simple/pingpair_irq_simple.ino
-
206Code/libraries/RF24-1.3.3/examples/pingpair_multi_dyn/Jamfile
-
263Code/libraries/RF24-1.3.3/examples/pingpair_multi_dyn/pingpair_multi_dyn.ino
-
226Code/libraries/RF24-1.3.3/examples/pingpair_sleepy/pingpair_sleepy.ino
-
101Code/libraries/RF24-1.3.3/examples/rf24_ATTiny/rf24ping85/rf24ping85.ino
-
396Code/libraries/RF24-1.3.3/examples/rf24_ATTiny/timingSearch3pin/timingSearch3pin.ino
-
210Code/libraries/RF24-1.3.3/examples/scanner/Jamfile
-
127Code/libraries/RF24-1.3.3/examples/scanner/scanner.ino
-
206Code/libraries/RF24-1.3.3/examples/starping/Jamfile
-
293Code/libraries/RF24-1.3.3/examples/starping/starping.pde
-
52Code/libraries/RF24-1.3.3/examples_linux/Makefile.examples
-
24Code/libraries/RF24-1.3.3/examples_linux/extra/Makefile
-
134Code/libraries/RF24-1.3.3/examples_linux/extra/rpi-hub.cpp
-
143Code/libraries/RF24-1.3.3/examples_linux/extra/scanner.cpp
-
216Code/libraries/RF24-1.3.3/examples_linux/gettingstarted.cpp
-
169Code/libraries/RF24-1.3.3/examples_linux/gettingstarted_call_response.cpp
-
24Code/libraries/RF24-1.3.3/examples_linux/interrupts/Makefile
-
143Code/libraries/RF24-1.3.3/examples_linux/interrupts/gettingstarted_call_response_int.cpp
-
155Code/libraries/RF24-1.3.3/examples_linux/interrupts/gettingstarted_call_response_int2.cpp
-
183Code/libraries/RF24-1.3.3/examples_linux/interrupts/pingpair_dyn_int.cpp
-
192Code/libraries/RF24-1.3.3/examples_linux/interrupts/transfer_interrupt.cpp
-
211Code/libraries/RF24-1.3.3/examples_linux/pingpair_dyn.cpp
-
141Code/libraries/RF24-1.3.3/examples_linux/pingpair_dyn.py
-
3Code/libraries/RF24-1.3.3/examples_linux/readme.md
-
187Code/libraries/RF24-1.3.3/examples_linux/transfer.cpp
-
16Code/libraries/RF24-1.3.3/keywords.txt
-
20Code/libraries/RF24-1.3.3/library.json
-
9Code/libraries/RF24-1.3.3/library.properties
-
127Code/libraries/RF24-1.3.3/nRF24L01.h
-
44Code/libraries/RF24-1.3.3/printf.h
-
38Code/libraries/RF24-1.3.3/pyRF24/crossunixccompiler.py
-
330Code/libraries/RF24-1.3.3/pyRF24/pyRF24.cpp
-
38Code/libraries/RF24-1.3.3/pyRF24/pyRF24/crossunixccompiler.py
-
328Code/libraries/RF24-1.3.3/pyRF24/pyRF24/pyRF24.cpp
-
2Code/libraries/RF24-1.3.3/pyRF24/pyRF24/readme.md
-
48Code/libraries/RF24-1.3.3/pyRF24/pyRF24/setup.py
-
22Code/libraries/RF24-1.3.3/pyRF24/pyRF24Mesh/example_master.py
-
105Code/libraries/RF24-1.3.3/pyRF24/pyRF24Mesh/pyRF24Mesh.cpp
-
17Code/libraries/RF24-1.3.3/pyRF24/pyRF24Mesh/setup.py
-
56Code/libraries/RF24-1.3.3/pyRF24/pyRF24Network/examples/helloworld_rx.py
-
64Code/libraries/RF24-1.3.3/pyRF24/pyRF24Network/examples/helloworld_tx.py
-
143Code/libraries/RF24-1.3.3/pyRF24/pyRF24Network/pyRF24Network.cpp
-
18Code/libraries/RF24-1.3.3/pyRF24/pyRF24Network/setup.py
-
2Code/libraries/RF24-1.3.3/pyRF24/readme.md
-
48Code/libraries/RF24-1.3.3/pyRF24/setup.py
-
7Code/libraries/RF24-1.3.3/tests/README
-
300Code/libraries/RF24-1.3.3/tests/native/Jamfile
-
223Code/libraries/RF24-1.3.3/tests/native/pingpair_irq.pde
-
33Code/libraries/RF24-1.3.3/tests/native/printf.h
-
219Code/libraries/RF24-1.3.3/tests/pingpair_blocking/Jamfile
-
273Code/libraries/RF24-1.3.3/tests/pingpair_blocking/pingpair_blocking.pde
-
37Code/libraries/RF24-1.3.3/tests/pingpair_blocking/printf.h
-
25Code/libraries/RF24-1.3.3/tests/pingpair_blocking/runtest.py
-
5Code/libraries/RF24-1.3.3/tests/pingpair_blocking/runtests.sh
-
11Code/libraries/RF24-1.3.3/tests/pingpair_blocking/test.ex
-
219Code/libraries/RF24-1.3.3/tests/pingpair_test/Jamfile
-
435Code/libraries/RF24-1.3.3/tests/pingpair_test/pingpair_test.pde
-
37Code/libraries/RF24-1.3.3/tests/pingpair_test/printf.h
-
25Code/libraries/RF24-1.3.3/tests/pingpair_test/runtest.py
-
21Code/libraries/RF24-1.3.3/tests/pingpair_test/runtests.sh
-
11Code/libraries/RF24-1.3.3/tests/pingpair_test/test.ex
-
47Code/libraries/RF24-1.3.3/utility/ATTiny/RF24_arch_config.h
-
53Code/libraries/RF24-1.3.3/utility/ATTiny/spi.h
-
54Code/libraries/RF24-1.3.3/utility/ATXMegaD3/README.md
-
85Code/libraries/RF24-1.3.3/utility/ATXMegaD3/RF24_arch_config.h
-
67Code/libraries/RF24-1.3.3/utility/ATXMegaD3/compatibility.c
-
45Code/libraries/RF24-1.3.3/utility/ATXMegaD3/compatibility.h
-
50Code/libraries/RF24-1.3.3/utility/ATXMegaD3/gpio.cpp
-
63Code/libraries/RF24-1.3.3/utility/ATXMegaD3/gpio.h
-
45Code/libraries/RF24-1.3.3/utility/ATXMegaD3/gpio_helper.c
@ -0,0 +1,24 @@ |
|||
*.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/*.* |
@ -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 |
2462
Code/libraries/RF24-1.3.3/Doxyfile
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,339 @@ |
|||
GNU GENERAL PUBLIC LICENSE |
|||
Version 2, June 1991 |
|||
|
|||
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/> |
|||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|||
Everyone is permitted to copy and distribute verbatim copies |
|||
of this license document, but changing it is not allowed. |
|||
|
|||
Preamble |
|||
|
|||
The licenses for most software are designed to take away your |
|||
freedom to share and change it. By contrast, the GNU General Public |
|||
License is intended to guarantee your freedom to share and change free |
|||
software--to make sure the software is free for all its users. This |
|||
General Public License applies to most of the Free Software |
|||
Foundation's software and to any other program whose authors commit to |
|||
using it. (Some other Free Software Foundation software is covered by |
|||
the GNU Lesser General Public License instead.) You can apply it to |
|||
your programs, too. |
|||
|
|||
When we speak of free software, we are referring to freedom, not |
|||
price. Our General Public Licenses are designed to make sure that you |
|||
have the freedom to distribute copies of free software (and charge for |
|||
this service if you wish), that you receive source code or can get it |
|||
if you want it, that you can change the software or use pieces of it |
|||
in new free programs; and that you know you can do these things. |
|||
|
|||
To protect your rights, we need to make restrictions that forbid |
|||
anyone to deny you these rights or to ask you to surrender the rights. |
|||
These restrictions translate to certain responsibilities for you if you |
|||
distribute copies of the software, or if you modify it. |
|||
|
|||
For example, if you distribute copies of such a program, whether |
|||
gratis or for a fee, you must give the recipients all the rights that |
|||
you have. You must make sure that they, too, receive or can get the |
|||
source code. And you must show them these terms so they know their |
|||
rights. |
|||
|
|||
We protect your rights with two steps: (1) copyright the software, and |
|||
(2) offer you this license which gives you legal permission to copy, |
|||
distribute and/or modify the software. |
|||
|
|||
Also, for each author's protection and ours, we want to make certain |
|||
that everyone understands that there is no warranty for this free |
|||
software. If the software is modified by someone else and passed on, we |
|||
want its recipients to know that what they have is not the original, so |
|||
that any problems introduced by others will not reflect on the original |
|||
authors' reputations. |
|||
|
|||
Finally, any free program is threatened constantly by software |
|||
patents. We wish to avoid the danger that redistributors of a free |
|||
program will individually obtain patent licenses, in effect making the |
|||
program proprietary. To prevent this, we have made it clear that any |
|||
patent must be licensed for everyone's free use or not licensed at all. |
|||
|
|||
The precise terms and conditions for copying, distribution and |
|||
modification follow. |
|||
|
|||
GNU GENERAL PUBLIC LICENSE |
|||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
|||
|
|||
0. This License applies to any program or other work which contains |
|||
a notice placed by the copyright holder saying it may be distributed |
|||
under the terms of this General Public License. The "Program", below, |
|||
refers to any such program or work, and a "work based on the Program" |
|||
means either the Program or any derivative work under copyright law: |
|||
that is to say, a work containing the Program or a portion of it, |
|||
either verbatim or with modifications and/or translated into another |
|||
language. (Hereinafter, translation is included without limitation in |
|||
the term "modification".) Each licensee is addressed as "you". |
|||
|
|||
Activities other than copying, distribution and modification are not |
|||
covered by this License; they are outside its scope. The act of |
|||
running the Program is not restricted, and the output from the Program |
|||
is covered only if its contents constitute a work based on the |
|||
Program (independent of having been made by running the Program). |
|||
Whether that is true depends on what the Program does. |
|||
|
|||
1. You may copy and distribute verbatim copies of the Program's |
|||
source code as you receive it, in any medium, provided that you |
|||
conspicuously and appropriately publish on each copy an appropriate |
|||
copyright notice and disclaimer of warranty; keep intact all the |
|||
notices that refer to this License and to the absence of any warranty; |
|||
and give any other recipients of the Program a copy of this License |
|||
along with the Program. |
|||
|
|||
You may charge a fee for the physical act of transferring a copy, and |
|||
you may at your option offer warranty protection in exchange for a fee. |
|||
|
|||
2. You may modify your copy or copies of the Program or any portion |
|||
of it, thus forming a work based on the Program, and copy and |
|||
distribute such modifications or work under the terms of Section 1 |
|||
above, provided that you also meet all of these conditions: |
|||
|
|||
a) You must cause the modified files to carry prominent notices |
|||
stating that you changed the files and the date of any change. |
|||
|
|||
b) You must cause any work that you distribute or publish, that in |
|||
whole or in part contains or is derived from the Program or any |
|||
part thereof, to be licensed as a whole at no charge to all third |
|||
parties under the terms of this License. |
|||
|
|||
c) If the modified program normally reads commands interactively |
|||
when run, you must cause it, when started running for such |
|||
interactive use in the most ordinary way, to print or display an |
|||
announcement including an appropriate copyright notice and a |
|||
notice that there is no warranty (or else, saying that you provide |
|||
a warranty) and that users may redistribute the program under |
|||
these conditions, and telling the user how to view a copy of this |
|||
License. (Exception: if the Program itself is interactive but |
|||
does not normally print such an announcement, your work based on |
|||
the Program is not required to print an announcement.) |
|||
|
|||
These requirements apply to the modified work as a whole. If |
|||
identifiable sections of that work are not derived from the Program, |
|||
and can be reasonably considered independent and separate works in |
|||
themselves, then this License, and its terms, do not apply to those |
|||
sections when you distribute them as separate works. But when you |
|||
distribute the same sections as part of a whole which is a work based |
|||
on the Program, the distribution of the whole must be on the terms of |
|||
this License, whose permissions for other licensees extend to the |
|||
entire whole, and thus to each and every part regardless of who wrote it. |
|||
|
|||
Thus, it is not the intent of this section to claim rights or contest |
|||
your rights to work written entirely by you; rather, the intent is to |
|||
exercise the right to control the distribution of derivative or |
|||
collective works based on the Program. |
|||
|
|||
In addition, mere aggregation of another work not based on the Program |
|||
with the Program (or with a work based on the Program) on a volume of |
|||
a storage or distribution medium does not bring the other work under |
|||
the scope of this License. |
|||
|
|||
3. You may copy and distribute the Program (or a work based on it, |
|||
under Section 2) in object code or executable form under the terms of |
|||
Sections 1 and 2 above provided that you also do one of the following: |
|||
|
|||
a) Accompany it with the complete corresponding machine-readable |
|||
source code, which must be distributed under the terms of Sections |
|||
1 and 2 above on a medium customarily used for software interchange; or, |
|||
|
|||
b) Accompany it with a written offer, valid for at least three |
|||
years, to give any third party, for a charge no more than your |
|||
cost of physically performing source distribution, a complete |
|||
machine-readable copy of the corresponding source code, to be |
|||
distributed under the terms of Sections 1 and 2 above on a medium |
|||
customarily used for software interchange; or, |
|||
|
|||
c) Accompany it with the information you received as to the offer |
|||
to distribute corresponding source code. (This alternative is |
|||
allowed only for noncommercial distribution and only if you |
|||
received the program in object code or executable form with such |
|||
an offer, in accord with Subsection b above.) |
|||
|
|||
The source code for a work means the preferred form of the work for |
|||
making modifications to it. For an executable work, complete source |
|||
code means all the source code for all modules it contains, plus any |
|||
associated interface definition files, plus the scripts used to |
|||
control compilation and installation of the executable. However, as a |
|||
special exception, the source code distributed need not include |
|||
anything that is normally distributed (in either source or binary |
|||
form) with the major components (compiler, kernel, and so on) of the |
|||
operating system on which the executable runs, unless that component |
|||
itself accompanies the executable. |
|||
|
|||
If distribution of executable or object code is made by offering |
|||
access to copy from a designated place, then offering equivalent |
|||
access to copy the source code from the same place counts as |
|||
distribution of the source code, even though third parties are not |
|||
compelled to copy the source along with the object code. |
|||
|
|||
4. You may not copy, modify, sublicense, or distribute the Program |
|||
except as expressly provided under this License. Any attempt |
|||
otherwise to copy, modify, sublicense or distribute the Program is |
|||
void, and will automatically terminate your rights under this License. |
|||
However, parties who have received copies, or rights, from you under |
|||
this License will not have their licenses terminated so long as such |
|||
parties remain in full compliance. |
|||
|
|||
5. You are not required to accept this License, since you have not |
|||
signed it. However, nothing else grants you permission to modify or |
|||
distribute the Program or its derivative works. These actions are |
|||
prohibited by law if you do not accept this License. Therefore, by |
|||
modifying or distributing the Program (or any work based on the |
|||
Program), you indicate your acceptance of this License to do so, and |
|||
all its terms and conditions for copying, distributing or modifying |
|||
the Program or works based on it. |
|||
|
|||
6. Each time you redistribute the Program (or any work based on the |
|||
Program), the recipient automatically receives a license from the |
|||
original licensor to copy, distribute or modify the Program subject to |
|||
these terms and conditions. You may not impose any further |
|||
restrictions on the recipients' exercise of the rights granted herein. |
|||
You are not responsible for enforcing compliance by third parties to |
|||
this License. |
|||
|
|||
7. If, as a consequence of a court judgment or allegation of patent |
|||
infringement or for any other reason (not limited to patent issues), |
|||
conditions are imposed on you (whether by court order, agreement or |
|||
otherwise) that contradict the conditions of this License, they do not |
|||
excuse you from the conditions of this License. If you cannot |
|||
distribute so as to satisfy simultaneously your obligations under this |
|||
License and any other pertinent obligations, then as a consequence you |
|||
may not distribute the Program at all. For example, if a patent |
|||
license would not permit royalty-free redistribution of the Program by |
|||
all those who receive copies directly or indirectly through you, then |
|||
the only way you could satisfy both it and this License would be to |
|||
refrain entirely from distribution of the Program. |
|||
|
|||
If any portion of this section is held invalid or unenforceable under |
|||
any particular circumstance, the balance of the section is intended to |
|||
apply and the section as a whole is intended to apply in other |
|||
circumstances. |
|||
|
|||
It is not the purpose of this section to induce you to infringe any |
|||
patents or other property right claims or to contest validity of any |
|||
such claims; this section has the sole purpose of protecting the |
|||
integrity of the free software distribution system, which is |
|||
implemented by public license practices. Many people have made |
|||
generous contributions to the wide range of software distributed |
|||
through that system in reliance on consistent application of that |
|||
system; it is up to the author/donor to decide if he or she is willing |
|||
to distribute software through any other system and a licensee cannot |
|||
impose that choice. |
|||
|
|||
This section is intended to make thoroughly clear what is believed to |
|||
be a consequence of the rest of this License. |
|||
|
|||
8. If the distribution and/or use of the Program is restricted in |
|||
certain countries either by patents or by copyrighted interfaces, the |
|||
original copyright holder who places the Program under this License |
|||
may add an explicit geographical distribution limitation excluding |
|||
those countries, so that distribution is permitted only in or among |
|||
countries not thus excluded. In such case, this License incorporates |
|||
the limitation as if written in the body of this License. |
|||
|
|||
9. The Free Software Foundation may publish revised and/or new versions |
|||
of the General Public License from time to time. Such new versions will |
|||
be similar in spirit to the present version, but may differ in detail to |
|||
address new problems or concerns. |
|||
|
|||
Each version is given a distinguishing version number. If the Program |
|||
specifies a version number of this License which applies to it and "any |
|||
later version", you have the option of following the terms and conditions |
|||
either of that version or of any later version published by the Free |
|||
Software Foundation. If the Program does not specify a version number of |
|||
this License, you may choose any version ever published by the Free Software |
|||
Foundation. |
|||
|
|||
10. If you wish to incorporate parts of the Program into other free |
|||
programs whose distribution conditions are different, write to the author |
|||
to ask for permission. For software which is copyrighted by the Free |
|||
Software Foundation, write to the Free Software Foundation; we sometimes |
|||
make exceptions for this. Our decision will be guided by the two goals |
|||
of preserving the free status of all derivatives of our free software and |
|||
of promoting the sharing and reuse of software generally. |
|||
|
|||
NO WARRANTY |
|||
|
|||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY |
|||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN |
|||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES |
|||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED |
|||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
|||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS |
|||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE |
|||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, |
|||
REPAIR OR CORRECTION. |
|||
|
|||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING |
|||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR |
|||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, |
|||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING |
|||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED |
|||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY |
|||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER |
|||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE |
|||
POSSIBILITY OF SUCH DAMAGES. |
|||
|
|||
END OF TERMS AND CONDITIONS |
|||
|
|||
How to Apply These Terms to Your New Programs |
|||
|
|||
If you develop a new program, and you want it to be of the greatest |
|||
possible use to the public, the best way to achieve this is to make it |
|||
free software which everyone can redistribute and change under these terms. |
|||
|
|||
To do so, attach the following notices to the program. It is safest |
|||
to attach them to the start of each source file to most effectively |
|||
convey the exclusion of warranty; and each file should have at least |
|||
the "copyright" line and a pointer to where the full notice is found. |
|||
|
|||
{description} |
|||
Copyright (C) {year} {fullname} |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License along |
|||
with this program; if not, write to the Free Software Foundation, Inc., |
|||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|||
|
|||
Also add information on how to contact you by electronic and paper mail. |
|||
|
|||
If the program is interactive, make it output a short notice like this |
|||
when it starts in an interactive mode: |
|||
|
|||
Gnomovision version 69, Copyright (C) year name of author |
|||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. |
|||
This is free software, and you are welcome to redistribute it |
|||
under certain conditions; type `show c' for details. |
|||
|
|||
The hypothetical commands `show w' and `show c' should show the appropriate |
|||
parts of the General Public License. Of course, the commands you use may |
|||
be called something other than `show w' and `show c'; they could even be |
|||
mouse-clicks or menu items--whatever suits your program. |
|||
|
|||
You should also get your employer (if you work as a programmer) or your |
|||
school, if any, to sign a "copyright disclaimer" for the program, if |
|||
necessary. Here is a sample; alter the names: |
|||
|
|||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program |
|||
`Gnomovision' (which makes passes at compilers) written by James Hacker. |
|||
|
|||
{signature of Ty Coon}, 1 April 1989 |
|||
Ty Coon, President of Vice |
|||
|
|||
This General Public License does not permit incorporating your program into |
|||
proprietary programs. If your program is a subroutine library, you may |
|||
consider it more useful to permit linking proprietary applications with the |
|||
library. If this is what you want to do, use the GNU Lesser General |
|||
Public License instead of this License. |
@ -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** |
1632
Code/libraries/RF24-1.3.3/RF24.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2030
Code/libraries/RF24-1.3.3/RF24.h
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -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; |
|||
|
|||
} |
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue