This commit is contained in:
15
depends/rpi-rgb-led-matrix/.editorconfig
Normal file
15
depends/rpi-rgb-led-matrix/.editorconfig
Normal file
@@ -0,0 +1,15 @@
|
||||
# Editor config file, see http://editorconfig.org/
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{h,cc}]
|
||||
indent_size = 2
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
6
depends/rpi-rgb-led-matrix/.gitignore
vendored
Normal file
6
depends/rpi-rgb-led-matrix/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
*.o
|
||||
*.a
|
||||
*~
|
||||
*.so
|
||||
.envrc
|
||||
.direnv
|
||||
339
depends/rpi-rgb-led-matrix/COPYING
Normal file
339
depends/rpi-rgb-led-matrix/COPYING
Normal file
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
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.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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.
|
||||
35
depends/rpi-rgb-led-matrix/Makefile
Normal file
35
depends/rpi-rgb-led-matrix/Makefile
Normal file
@@ -0,0 +1,35 @@
|
||||
# This toplevel Makefile compiles the library in the lib subdirectory.
|
||||
# If you want to see how to integrate the library in your own projects, check
|
||||
# out the sub-directories examples-api-use/ and utils/
|
||||
RGB_LIBDIR=./lib
|
||||
RGB_LIBRARY_NAME=rgbmatrix
|
||||
RGB_LIBRARY=$(RGB_LIBDIR)/lib$(RGB_LIBRARY_NAME).a
|
||||
|
||||
# Some language bindings.
|
||||
PYTHON_LIB_DIR=bindings/python
|
||||
CSHARP_LIB_DIR=bindings/c\#
|
||||
|
||||
all : $(RGB_LIBRARY)
|
||||
|
||||
$(RGB_LIBRARY): FORCE
|
||||
$(MAKE) -C $(RGB_LIBDIR)
|
||||
$(MAKE) -C examples-api-use
|
||||
|
||||
clean:
|
||||
$(MAKE) -C lib clean
|
||||
$(MAKE) -C utils clean
|
||||
$(MAKE) -C examples-api-use clean
|
||||
$(MAKE) -C $(PYTHON_LIB_DIR) clean
|
||||
|
||||
build-csharp:
|
||||
$(MAKE) -C $(CSHARP_LIB_DIR) nuget
|
||||
$(MAKE) -C $(CSHARP_LIB_DIR) build
|
||||
|
||||
build-python: $(RGB_LIBRARY)
|
||||
$(MAKE) -C $(PYTHON_LIB_DIR) build
|
||||
|
||||
install-python: build-python
|
||||
$(MAKE) -C $(PYTHON_LIB_DIR) install
|
||||
|
||||
FORCE:
|
||||
.PHONY: FORCE
|
||||
812
depends/rpi-rgb-led-matrix/README.md
Normal file
812
depends/rpi-rgb-led-matrix/README.md
Normal file
@@ -0,0 +1,812 @@
|
||||
Controlling RGB LED display with Raspberry Pi GPIO
|
||||
==================================================
|
||||
|
||||
A library to control commonly available 64x64, 32x32 or 16x32 RGB LED panels
|
||||
with the Raspberry Pi. Can support PWM up to 11Bit per channel, providing
|
||||
true 24bpp color with CIE1931 profile.
|
||||
|
||||
Supports 3 chains with many panels each on a regular Pi.
|
||||
On a Raspberry Pi 2 or 3, you can easily chain 12 panels in that chain
|
||||
(so 36 panels total), but you can theoretically stretch that to up
|
||||
to 96-ish panels (32 chain length) and still reach
|
||||
around 100Hz refresh rate with full 24Bit color (theoretical - never tested
|
||||
this; there might likely be timing problems with the panels that will creep
|
||||
up then).
|
||||
|
||||
With fewer colors or so-called 'outdoor panels' you can control even more,
|
||||
faster.
|
||||
|
||||
The LED-matrix library is (c) Henner Zeller <h.zeller@acm.org>, licensed with
|
||||
[GNU General Public License Version 2.0](http://www.gnu.org/licenses/gpl-2.0.txt)
|
||||
(which means, if you use it in a product somewhere, you need to make the
|
||||
source and all your modifications available to the receiver of such product so
|
||||
that they have the freedom to adapt and improve).
|
||||
|
||||
## Discourse discussion group
|
||||
|
||||
If you'd like help, please do not file a bug, use the discussion board instead:
|
||||
https://rpi-rgb-led-matrix.discourse.group/
|
||||
|
||||
Overview
|
||||
--------
|
||||
The RGB LED matrix panels can be scored at [Sparkfun][sparkfun],
|
||||
[AdaFruit][ada] or eBay and Aliexpress. If you are in China, I'd try to get
|
||||
them directly from some manufacturer, Taobao or Alibaba.
|
||||
|
||||
The `RGBMatrix` class provided in `include/led-matrix.h` does what is needed
|
||||
to control these. You can use this as a library in your own projects or just
|
||||
use the demo binary provided here which provides some useful examples.
|
||||
|
||||
Check out [utils/ directory for some ready-made tools](./utils) to get started
|
||||
using the library, or the [examples-api-use/](./examples-api-use) directory if
|
||||
you want to get started programming your own utils.
|
||||
|
||||
All Raspberry Pi versions supported
|
||||
-----------------------------------
|
||||
|
||||
This supports the old Raspberry Pi's Version 1 with 26 pin header and also the
|
||||
B+ models, the Pi Zero, Raspberry Pi 2 and 3 with 40 pins, as well as the
|
||||
Compute Modules which have 44 GPIOs.
|
||||
The 26 pin models can drive one chain of RGB panels, the 40 pin models
|
||||
**up to three** chains in parallel (each chain 12 or more panels long).
|
||||
The Compute Module can drive **up to 6 chains in parallel**.
|
||||
The Raspberry Pi 2 and 3 are faster and generally perferred to the older
|
||||
models (and the Pi Zero). With the faster models, the panels sometimes
|
||||
can't keep up with the speed; check out
|
||||
this [troubleshooting section](#troubleshooting) what to do.
|
||||
|
||||
A lightweight, non-GUI, distribution such as [DietPi] is recommended.
|
||||
[Raspbian Lite][raspbian-lite] is a bit easier to get started with and
|
||||
is a good second choice.
|
||||
|
||||
Types of Displays
|
||||
-----------------
|
||||
There are various types of displays that come all with the same Hub75 connector.
|
||||
They vary in the way the multiplexing is happening so this library supports
|
||||
options to choose that.
|
||||
All these are configured by flags (or, programmatically, in an [Options struct](include/led-matrix.h#L57)).
|
||||
|
||||
If you have a 64x32 display, you need to supply the flags
|
||||
`--led-cols=64 --led-rows=32` for instance.
|
||||
|
||||
Depending on the Matrix, there are various configuration options that
|
||||
you might need to set for it to work. See further below in the README for the
|
||||
[detailed description of these](#changing-parameters-via-command-line-flags).
|
||||
While the `--led-rows` and `--led-cols` can be derived from simply looking
|
||||
at the panels, the other options might require some experimenting to find the
|
||||
right setting if there is no description provided by the manufacturer of
|
||||
the panel. Going through these options for experiments would typically not do
|
||||
harm, so you're free to experiment to find your setting.
|
||||
|
||||
Flag | Description
|
||||
:--------------- | :-----------------
|
||||
`--led-cols` | Columns in the LED matrix, the 'width'.
|
||||
`--led-rows` | Rows in the LED matrix, the 'height'.
|
||||
`--led-multiplexing` | In particular bright outdoor panels with small multiplex ratios require this. Often an indicator: if there are fewer address lines than expected: ABC (instead of ABCD) for 32 high panels and ABCD (instead of ABCDE) for 64 high panels.
|
||||
`--led-row-addr-type` | Adressing of rows; in particular panels with only AB address lines might indicate that this is needed.
|
||||
`--led-panel-type` | Chipset of the panel. In particular if it doesn't light up at all, you might need to play with this option because it indicates that the panel requires a particular initialization sequence.
|
||||
|
||||
Panels can be chained by connecting the output of one panel to the input of
|
||||
the next panel. You can chain quite a few together, but the refresh rate will
|
||||
reduce with longer chains.
|
||||
|
||||
The 64x64 matrixes typically come in two kinds: with 5 address
|
||||
lines (A, B, C, D, E), or (A, B); the latter needs a `--led-row-addr-type=1`
|
||||
parameter. So-called 'outdoor panels' are typically brighter and allow for
|
||||
faster refresh-rate for the same size, but do some multiplexing internally
|
||||
of which there are a few types out there; they can be chosen with
|
||||
the `--led-multiplexing` parameter.
|
||||
|
||||
There are some panels that have a different chip-set than the default HUB75.
|
||||
These require some initialization sequence. The current supported types are
|
||||
`--led-panel-type=FM6126A` and `--led-panel-type=FM6127`.
|
||||
|
||||
Generally, the higher scan-rate (e.g. 1:8), a.k.a. outdoor panels generally
|
||||
allow faster refresh rate, but you might need to figure out the multiplexing
|
||||
mapping if one of the three provided does not work.
|
||||
|
||||
Some 32x16 outdoor matrixes with 1:4 scan (e.g. [Qiangli Q10(1/4) or X10(1/4)](http://qiangliled.com/products-63.html))
|
||||
have 4 address line (A, B, C, D). For such matrices is necessary to
|
||||
use `--led-row-addr-type=2` parameter. Also the matrix Qiangli Q10(1/4)
|
||||
have "Z"-stripe pixel mapping and in this case, you'd use two parameters
|
||||
at the same time `--led-row-addr-type=2 --led-multiplexing=4`.
|
||||
|
||||
Let's do it
|
||||
------------
|
||||
This documentation is split into parts that help you through the process
|
||||
|
||||
1. <a href="wiring.md"><img src="img/wire-up-icon.png"></a>
|
||||
[**Wire up the matrix to your Pi**](./wiring.md). This document describes
|
||||
what goes where. You might also be interested
|
||||
in [breakout boards](./adapter) for that.
|
||||
If you have an [Adafruit HAT] or [Adafruit Bonnet], you can choose that with
|
||||
a command line option [described below](#if-you-have-an-adafruit-hat-or-bonnet)
|
||||
2. Run a demo. You find that in the
|
||||
[examples-api-use/](./examples-api-use#running-some-demos) directory:
|
||||
```
|
||||
make -C examples-api-use
|
||||
sudo examples-api-use/demo -D0
|
||||
```
|
||||
3. Use the utilities. The [utils](./utils) directory has some ready-made
|
||||
useful utilities to show content. [Go there](./utils) to see how to
|
||||
compile and run these.
|
||||
4. Write your own programs using the Matrix in C++ or one of the
|
||||
bindings such as Python or C#.
|
||||
|
||||
### Utilities
|
||||
|
||||
The [utils directory](./utils) is meant for ready utilities to show images or
|
||||
animated gifs or videos. Read the [README](./utils/README.md) there for
|
||||
instructions how to compile.
|
||||
|
||||
There are external projects that use this library and provide higher level
|
||||
network protocols, such as the
|
||||
* [FlaschenTaschen implementation](https://github.com/hzeller/flaschen-taschen)
|
||||
(VLC can send videos to it natively)
|
||||
* [PixelPusher implementation](https://github.com/hzeller/rpi-matrix-pixelpusher) (common in light art installations)
|
||||
* [ZeroMQ-server](https://github.com/Knifa/led-matrix-zmq-server) to receive
|
||||
content.
|
||||
* Marc's [FastLED_RPIRGBPanel_GFX](http://marc.merlins.org/perso/arduino/post_2020-01-01_Running-FastLED_-Adafruit_GFX_-and-LEDMatrix-code-on-High-Resolution-RGBPanels-with-a-Raspberry-Pi.html) allows running arduino code on linux/rPi and display on bigger RGBPanel matrices than arduino chips, can.
|
||||
|
||||
### API
|
||||
|
||||
The library comes as an API that you can use for your own utilities and use-cases.
|
||||
|
||||
* The native library is a C++ library (see [include/](./include)).
|
||||
Example uses you find in the [examples-api-use/](./examples-api-use)
|
||||
directory.
|
||||
* If you prefer to program in C, there is also a
|
||||
[C API](./include/led-matrix-c.h).
|
||||
* In the [python](./bindings/python) subdirectory, you find a Python API including a
|
||||
couple of [examples](./bindings/python/samples) to get started.
|
||||
* There are a couple of external bindings, such as
|
||||
* [Nodejs binding] by Maxime Journaux
|
||||
* [Nodejs/Typescript binding] by Alex Eden
|
||||
* [Go binding] by Máximo Cuadros
|
||||
* [Rust binding] by Vincent Pasquier
|
||||
|
||||
### Changing parameters via command-line flags
|
||||
|
||||
For the programs in this distribution and also automatically in your own
|
||||
programs using this library, there are a lot of parameters provided as command
|
||||
line flags, so that you don't have to re-compile your programs to tweak them.
|
||||
Some might need to be changed for your particular kind of panel.
|
||||
|
||||
Here is a little run-down of what these command-line flags do and when you'd
|
||||
like to change them.
|
||||
|
||||
First things first: if you have a different wiring than described in
|
||||
[wiring](./wiring.md), for instance if you have an Adafruit HAT/Bonnet, you can
|
||||
choose these here:
|
||||
|
||||
```
|
||||
--led-gpio-mapping=<gpio-mapping>: Name of GPIO mapping used. Default "regular"
|
||||
```
|
||||
|
||||
This can have values such as
|
||||
- `--led-gpio-mapping=regular` The standard mapping of this library, described in the [wiring](./wiring.md) page.
|
||||
- `--led-gpio-mapping=adafruit-hat` The Adafruit HAT/Bonnet, that uses this library or
|
||||
- `--led-gpio-mapping=adafruit-hat-pwm` Adafruit HAT with the anti-flicker hardware mod [described below](#improving-flicker).
|
||||
- `--led-gpio-mapping=compute-module` Additional 3 parallel chains can be used with the Compute Module.
|
||||
|
||||
Learn more about the mappings in the [wiring documentation](wiring.md#alternative-hardware-mappings).
|
||||
|
||||
#### GPIO speed
|
||||
|
||||
```
|
||||
--led-slowdown-gpio=<0..4>: Slowdown GPIO. Needed for faster Pis and/or slower panels (Default: 1).
|
||||
```
|
||||
|
||||
The Raspberry Pi starting with Pi2 are putting out data too fast for almost
|
||||
all LED panels I have seen. In this case, you want to slow down writing to
|
||||
GPIO. Zero for this parameter means 'no slowdown'.
|
||||
|
||||
The default 1 (one) typically works fine, but often you have to even go further
|
||||
by setting it to 2 (two). If you have a Raspberry Pi with a slower processor
|
||||
(Model A, A+, B+, Zero), then a value of 0 (zero) might work and is desirable.
|
||||
|
||||
A Raspberry Pi 3 or Pi4 might even need higher values for the panels to be
|
||||
happy.
|
||||
|
||||
#### Panel Connection
|
||||
The next most important flags describe the type and number of displays connected
|
||||
|
||||
```
|
||||
--led-rows=<rows> : Panel rows. Typically 8, 16, 32 or 64. (Default: 32).
|
||||
--led-cols=<cols> : Panel columns. Typically 32 or 64. (Default: 32).
|
||||
--led-chain=<chained> : Number of daisy-chained panels. (Default: 1).
|
||||
--led-parallel=<parallel>: For A/B+ models or RPi2,3b: parallel chains. range=1..3 (Default: 1, 6 for Compute Module).
|
||||
```
|
||||
|
||||
These are the most important ones: here you choose how many panels you have
|
||||
connected and how many rows are in each panel. Panels can be chained (each panel
|
||||
has an input and output connector, see the
|
||||
[wiring documentation](wiring.md#chains)) -- the `--led-chain` flag tells the
|
||||
library how many panels are chained together. The newer Raspberry Pi's allow
|
||||
to connect multiple chains in parallel, the `--led-parallel` flag tells it how
|
||||
many there are.
|
||||
|
||||
This illustrates what each of these parameters mean:
|
||||
|
||||
<a href="wiring.md#chaining-parallel-chains-and-coordinate-system"><img src="img/coordinates.png"></a>
|
||||
|
||||
##### Panel Type
|
||||
|
||||
Typically, panels should just work out of the box, but some panels use a
|
||||
different chip-set that requires some initialization. If you don't see any
|
||||
output on your panel, try setting:
|
||||
|
||||
```
|
||||
--led-panel-type=FM6126A
|
||||
```
|
||||
|
||||
Some panels have the FM6127 chip, which is also an option.
|
||||
|
||||
##### Multiplexing
|
||||
If you have some 'outdoor' panels or panels with different multiplexing,
|
||||
the following will be useful:
|
||||
|
||||
```
|
||||
--led-multiplexing=<0..17> : Mux type: 0=direct; 1=Stripe; 2=Checkered...
|
||||
```
|
||||
|
||||
The outdoor panels have different multiplexing which allows them to be faster
|
||||
and brighter, but by default their output looks jumbled up.
|
||||
They require some pixel-mapping of which there are a few
|
||||
types you can try and hopefully one of them works for your panel; The default=0
|
||||
is no mapping ('standard' panels), while 1, 2, ... are different mappings
|
||||
to try with. If your panel has a different mapping, you find everything you
|
||||
need to implement one in [lib/multiplex-mappers.cc](lib/multiplex-mappers.cc).
|
||||
Please send a pull request if you encounter a panel for which you needed to
|
||||
implement a new mapping.
|
||||
|
||||
Note that you have to set the `--led-rows` and `--led-cols` to the rows and
|
||||
columns that are physically on each chained panel so that the multiplexing
|
||||
option can work properly. For instance a `32x16` panel with `1:4` multiplexing
|
||||
would be controlled with `--led-rows=16 --led-cols=32 --led-multiplexing=1` (or
|
||||
whatever multiplexing type your panel is, so it can also be `--led-multiplexing=2` ...).
|
||||
|
||||
For `64x32` panels with `1:8` multiplexing, this would typically be
|
||||
`--led-rows=32 --led-cols=64 --led-multiplexing=1`;
|
||||
however, there are some panels that internally behave like
|
||||
two chained panels, so then you'd use
|
||||
`--led-rows=32 --led-cols=32 --led-chain=2 --led-multiplexing=1`;
|
||||
|
||||
```
|
||||
--led-row-addr-type=<0..4>: 0 = default; 1 = AB-addressed panels; 2 = direct row select; 3 = ABC-addressed panels; 4 = ABC Shift + DE direct (Default: 0).
|
||||
```
|
||||
|
||||
This option is useful for certain 64x64 or 32x16 panels. For 64x64 panels,
|
||||
that only have an `A` and `B` address line, you'd use `--led-row-addr-type=1`.
|
||||
This is only tested with one panel so far, so if it doesn't work for you,
|
||||
please send a pull request.
|
||||
|
||||
For 32x16 outdoor panels, that have have 4 address line (A, B, C, D), it is
|
||||
necessary to use `--led-row-addr-type=2`.
|
||||
|
||||
#### Panel Arrangement
|
||||
|
||||
```
|
||||
--led-pixel-mapper : Semicolon-separated list of pixel-mappers to arrange pixels.
|
||||
```
|
||||
|
||||
Optional params after a colon e.g. "U-mapper;Rotate:90"
|
||||
|
||||
Available | Parameter after colon| Example
|
||||
----------|----------------------|----------
|
||||
Mirror | `H` or `V` for horizontal/vertical mirror. | `Mirror:H`
|
||||
Rotate | Degrees. | `Rotate:90`
|
||||
U-mapper | -
|
||||
|
||||
Mapping the logical layout of your boards to your physical arrangement. See
|
||||
more in [Remapping coordinates](./examples-api-use#remapping-coordinates).
|
||||
|
||||
#### Misc Options
|
||||
|
||||
```
|
||||
--led-brightness=<percent>: Brightness in percent (Default: 100).
|
||||
```
|
||||
|
||||
Self explanatory.
|
||||
|
||||
|
||||
```
|
||||
--led-pwm-bits=<1..11> : PWM bits (Default: 11).
|
||||
```
|
||||
|
||||
The LEDs can only be switched on or off, so the shaded brightness perception
|
||||
is achieved via PWM (Pulse Width Modulation). In order to get a good 8 Bit
|
||||
per color resolution (24Bit RGB), the 11 bits default per color are good
|
||||
(why ? Because our eyes are actually perceiving brightness logarithmically, so
|
||||
we need a lot more physical resolution to get 24Bit sRGB).
|
||||
|
||||
With this flag, you can change how many bits it should use for this; lowering it
|
||||
means the lower bits (=more subtle color nuances) are omitted.
|
||||
Typically you might be mostly interested in the extremes: 1 Bit for situations
|
||||
that only require 8 colors (e.g. for high contrast text displays) or 11 Bit
|
||||
for everything else (e.g. showing images or videos). Why would you bother at all ?
|
||||
Lower number of bits use slightly less CPU and result in a higher refresh rate.
|
||||
|
||||
```
|
||||
--led-show-refresh : Show refresh rate.
|
||||
```
|
||||
|
||||
This shows the current refresh rate of the LED panel, the time to refresh
|
||||
a full picture. Typically, you want this number to be pretty high, because the
|
||||
human eye is pretty sensitive to flicker. Depending on the settings, the
|
||||
refresh rate with this library are typically in the hundreds of Hertz but
|
||||
can drop low with very long chains. Humans have different levels of perceiving
|
||||
flicker - some are fine with 100Hz refresh, others need 250Hz.
|
||||
So if you are curious, this gives you the number (shown on the terminal).
|
||||
|
||||
The refresh rate depends on a lot of factors, from `--led-rows` and `--led-chain`
|
||||
to `--led-pwm-bits`, `--led-pwm-lsb-nanoseconds` and `--led-pwm-dither-bits`.
|
||||
If you are tweaking these parameters, showing the refresh rate can be a
|
||||
useful tool.
|
||||
|
||||
```
|
||||
--led-limit-refresh=<Hz> : Limit refresh rate to this frequency in Hz. Useful to keep a
|
||||
constant refresh rate on loaded system. 0=no limit. Default: 0
|
||||
```
|
||||
|
||||
This allows to limit the refresh rate to a particular frequency to approach
|
||||
a fixed refresh rate.
|
||||
|
||||
This can be used to mitigate some situations in which you have a faint flicker,
|
||||
which can happen due to hardware events (network access)
|
||||
or other situations such as other IO or heavy memory access by other
|
||||
processes. Also when you see wildly changing refresh frequencies with
|
||||
`--led-show-refresh`.
|
||||
|
||||
You trade a slightly slower refresh rate and display brightness for less
|
||||
visible flicker situations.
|
||||
|
||||
For this to calibrate, run your program for a while with --led-show-refresh
|
||||
and watch the line that shows the current refresh rate and minimum refresh
|
||||
rate observed. So wait a while until that value doesn't
|
||||
change anymore (e.g. a minute, so that you catch tasks that happen once
|
||||
a minute, such as ntp updated).
|
||||
Use this as a guidance what value to choose with `--led-limit-refresh`.
|
||||
|
||||
The refresh rate will now be adapted to always reach this value
|
||||
between frames, so faster refreshes will be slowed down, but the occasional
|
||||
delayed frame will fit into the time-window as well, thus reducing visible
|
||||
brightness fluctuations.
|
||||
|
||||
You can play with value a little and reduce until you find a good balance
|
||||
between refresh rate and flicker suppression.
|
||||
|
||||
Use this also if you want to have a stable baseline refresh rate when using
|
||||
the vsync-multiple flag `-V` in the [led-image-viewer] or
|
||||
[video-viewer] utility programs.
|
||||
|
||||
```
|
||||
--led-scan-mode=<0..1> : 0 = progressive; 1 = interlaced (Default: 0).
|
||||
```
|
||||
|
||||
This switches from progressive scan and interlaced scan. The latter might
|
||||
look be a little nicer when you have a very low refresh rate, but typically
|
||||
it is more annoying because of the comb-effect (remember 80ies TV ?).
|
||||
|
||||
|
||||
```
|
||||
--led-pwm-lsb-nanoseconds : PWM Nanoseconds for LSB (Default: 130)
|
||||
```
|
||||
|
||||
This allows to change the base time-unit for the on-time in the lowest
|
||||
significant bit in nanoseconds.
|
||||
Lower values will allow higher frame-rate, but will also negatively impact
|
||||
qualty in some panels (less accurate color or more ghosting).
|
||||
|
||||
Good values for full-color display (PWM=11) are somewhere between 100 and 300.
|
||||
|
||||
If you you use reduced bit color (e.g. PWM=1) and have sharp contrast
|
||||
applications, then higher values might be good to minimize ghosting.
|
||||
|
||||
How to decide ? Just leave the default if things are fine. But some panels have
|
||||
trouble with sharp contrasts and short pulses that results
|
||||
in ghosting. It is particularly apparent in situations such as bright text
|
||||
on black background. In these cases increase the value until you don't see
|
||||
this ghosting anymore.
|
||||
|
||||
The following example shows how this might look like:
|
||||
|
||||
Ghosting with low --led-pwm-lsb-nanoseconds | No ghosting after tweaking
|
||||
---------------------------------------------|------------------------------
|
||||
 |
|
||||
|
||||
If you tweak this value, watch the framerate (`--led-show-refresh`) while playing
|
||||
with this number.
|
||||
|
||||
```
|
||||
--led-pwm-dither-bits : Time dithering of lower bits (Default: 0)
|
||||
```
|
||||
|
||||
The lower bits can be time dithered, i.e. their brightness contribution is
|
||||
achieved by only showing them some frames (this is possible,
|
||||
because the PWM is implemented as binary code modulation).
|
||||
This will allow higher refresh rate (or same refresh rate with increased
|
||||
`--led-pwm-lsb-nanoseconds`).
|
||||
The disadvantage could be slightly lower brightness, in particular for longer
|
||||
chains, and higher CPU use.
|
||||
CPU use is not of concern for Rasbperry Pi 2 or 3 (as we run on a dedicated
|
||||
core anyway) but proably for Raspberry Pi 1 or Pi Zero.
|
||||
Default: no dithering; if you have a Pi 3 and struggle with low frame-rate due
|
||||
to high multiplexing panels (1:16 or 1:32) or long chains, it might be
|
||||
worthwhile to try.
|
||||
|
||||
```
|
||||
--led-no-hardware-pulse : Don't use hardware pin-pulse generation.
|
||||
```
|
||||
|
||||
This library uses a hardware subsystem that also is used by the sound. You can't
|
||||
use them together. If your panel does not work, this might be a good start
|
||||
to debug if it has something to do with the sound subsystem (see Troubleshooting
|
||||
section). This is really only recommended for debugging; typically you actually
|
||||
want the hardware pulses as it results in a much more stable picture.
|
||||
|
||||
<a name="no-drop-priv"/>
|
||||
|
||||
```
|
||||
--led-no-drop-privs : Don't drop privileges from 'root' after initializing the hardware.
|
||||
```
|
||||
|
||||
You need to start programs as root as it needs to access some low-level hardware
|
||||
at initialization time. After that, it is typically not desirable to stay in this
|
||||
role, so the library then drops the privileges.
|
||||
|
||||
This flag allows to switch off this behavior, so that you stay root.
|
||||
Not recommended unless you have a specific reason for it (e.g. you need root
|
||||
to access other hardware or you do the privilege dropping yourself).
|
||||
|
||||
```
|
||||
--led-daemon : Make the process run in the background as daemon.
|
||||
```
|
||||
|
||||
If this is set, the program puts itself into the background (running
|
||||
as 'daemon').
|
||||
You might want this if started from an init script at boot-time.
|
||||
|
||||
```
|
||||
--led-inverse : Switch if your matrix has inverse colors on.
|
||||
--led-rgb-sequence : Switch if your matrix has led colors swapped (Default: "RGB")
|
||||
```
|
||||
|
||||
These are if you have a different kind of LED panel in which the logic of the
|
||||
color bits is reversed (`--led-inverse`) or where the Red, Green and Blue LEDs
|
||||
are mixed up (`--led-rgb-sequence`). You know it when you see it.
|
||||
|
||||
Troubleshooting
|
||||
---------------
|
||||
Here are some tips in case things don't work as expected.
|
||||
|
||||
### Use minimal Raspbian distribution
|
||||
In general, run a minimal configuration on your Pi.
|
||||
|
||||
* Do not use a graphical user interface (Even though the
|
||||
Raspberry Pi foundation makes you believe that you can do that: don't.
|
||||
Using a Pi with a GUI is a frustratingly slow use of an otherwise
|
||||
perfectly good embedded device.).
|
||||
Always operate your Raspberry Pi [headless].
|
||||
|
||||
* Switch off on-board sound (`dtparam=audio=off` in `/boot/config.txt`).
|
||||
External USB sound adapters work, and are much better quality anyway,
|
||||
so that is recommended if you happen to need sound. The on-board sound
|
||||
uses a timing circuit that the RGB-Matrix needs (it seems in some
|
||||
distributions, such as arch-linux, this is not enough and you need
|
||||
to explicitly blacklist the snd_bcm2835 module).
|
||||
|
||||
* Don't run anything that messes in parallel with the GPIO pins, e.g.
|
||||
PiGPIO library/daemon or devices that use the i2c or 1-wire interface if
|
||||
they are on the same pins you need for the panel.
|
||||
|
||||
* I have also seen reports that on some Pis, the one-wire protocol is
|
||||
enabled (w1-gpio). This will also not work (disable by removing
|
||||
`dtoverlay=w1-gpio` in `/boot/config.txt`; or using `raspi-config`,
|
||||
Interface Options -> 1-Wire)
|
||||
|
||||
* If you see some regular flickering, make sure that there is no other
|
||||
process running on the system that could cause that. For instance, it is
|
||||
known that merely running `top` creates a faint flicker every second it
|
||||
updates. Or a regular ntp run can also cause flicker once a minute
|
||||
(switch off with `sudo timedatectl set-ntp false`). Maybe instead you
|
||||
might want to run ntp at system start-up but then not regularly updating.
|
||||
There might be other things running regularly you don't need;
|
||||
consider a `sudo systemctl stop cron` for instance.
|
||||
To address some irregular flicker, consider the
|
||||
[`--led-limit-refresh`](#misc-options) option.
|
||||
|
||||
* There are probably other processes that are running that you don't need
|
||||
and remove them; I usually remove right away stuff I really don't need e.g.
|
||||
```
|
||||
sudo apt-get remove bluez bluez-firmware pi-bluetooth triggerhappy pigpio
|
||||
```
|
||||
Take a close look at your systemd (`systemctl`) and see if there are other
|
||||
things running you don't need. If you have seen packages in standard
|
||||
Raspbians that interfere with the matrix code, let me know to include it
|
||||
here.
|
||||
In general: This is why starting with a minimal installation is a good
|
||||
idea: there is simply less cruft that you have to disable.
|
||||
|
||||
* It seems that more recent version of Raspbian Lite result in some faint
|
||||
brightness fluctuations of the displays and it is not quite clear why (see
|
||||
issue [#483](https://github.com/hzeller/rpi-rgb-led-matrix/issues/483)).
|
||||
If you are a Kernel person and can help figuring out what is
|
||||
happening that would be very appreciated. Also, you might know a minimal
|
||||
Linux distribution that is more suited for near realtime applications ?
|
||||
|
||||
The default install of **[Raspbian Lite][raspbian-lite]** or **[DietPi]**
|
||||
seem to be good starting points, as they have a reasonably minimal
|
||||
configuration to begin with. Raspbian Lite is not as lite anymore
|
||||
as it used to be; I prefer DietPi these days.
|
||||
|
||||
### Bad interaction with Sound
|
||||
If sound is enabled on your Pi, this will not work together with the LED matrix,
|
||||
as both need the same internal hardware sub-system (a first test to see if you
|
||||
are affected is to run the progrem with `--led-no-hardware-pulse` and see if
|
||||
things work fine then).
|
||||
|
||||
If you run `lsmod` and see the `snd_bcm2835` module, this could be causing trouble.
|
||||
(The library actually exits if it finds this module to be loaded).
|
||||
|
||||
In that case, you should create a kernel module blacklist file like the
|
||||
following on your system and update your initramfs:
|
||||
|
||||
```
|
||||
cat <<EOF | sudo tee /etc/modprobe.d/blacklist-rgb-matrix.conf
|
||||
blacklist snd_bcm2835
|
||||
EOF
|
||||
|
||||
sudo update-initramfs -u
|
||||
```
|
||||
|
||||
Reboot and confirm that the module is not loaded.
|
||||
|
||||
### I have followed some tutorial on the Internet and it doesn't work
|
||||
|
||||
Well, if you use this library, please read the documentation provided _here_,
|
||||
not on some other website. Most important for you to get started
|
||||
is the [wiring guide](./wiring.md). There are some tutorials floating around
|
||||
that refer to a very old version of this library.
|
||||
|
||||
### I have a Pi1 Revision1 and top part of Panel doesn't show green
|
||||
|
||||
Use `--led-gpio-mapping=regular-pi1`
|
||||
|
||||
### Logic level voltage not sufficient
|
||||
Some panels don't interpret the 3.3V logic level well, or the RPi output drivers
|
||||
have trouble driving longer cables, in particular with
|
||||
faster Raspberry Pis Version 2. This results in artifacts like randomly
|
||||
showing up pixels, color fringes, or parts of the panel showing 'static'.
|
||||
|
||||
If you encounter this, try these things
|
||||
|
||||
- Make sure to have as short as possible flat-cables connecting your
|
||||
Raspberry Pi with the LED panel.
|
||||
|
||||
- In particular if the chips close to the input of the LED panel
|
||||
read 74HC245 instead of 74HCT245 or 74AHCT245, then this board will not
|
||||
work properly with 3.3V inputs coming from the Pi.
|
||||
Use an [adapter board](./adapter/active-3) with a bus-driver that acts as
|
||||
level shifter between 3.3V and 5V.
|
||||
(In any case, it is always a good idea to use the level shifters).
|
||||
|
||||
- A temporary hack to make HC245 inputs work with the 3.3V levels is to
|
||||
supply only like 4V to the LED panel. But the colors will be off, so not
|
||||
really useable as long-term solution.
|
||||
|
||||
- If you can't implement the above things, or still have problems, you can
|
||||
slow down the GPIO writing a bit. This will of course reduce the
|
||||
frame-rate, so it comes at a cost.
|
||||
|
||||
For GPIO slow-down, add the flag `--led-slowdown-gpio=2` to the invocation of
|
||||
the binary.
|
||||
|
||||
If you have an Adafruit HAT or Bonnet
|
||||
---------------------------
|
||||
|
||||
Generally, if you want to connect RGB panels via an adapter instead of
|
||||
hand-wiring, I suggest to build one of the adapters whose open-hardware
|
||||
files you find in the [adapter/](./adapter) subdirectory. It is a fun solder
|
||||
exercise with large surface mount components.
|
||||
|
||||
However, Adafruit [offers an adapter][adafruit-hat] which is already ready-made,
|
||||
but it only allows for a single chain. If the
|
||||
ready-made vs. single-chain tradeoff is worthwhile, then you might go for that
|
||||
(I am not affiliated with Adafruit).
|
||||
|
||||
### Switch the Pinout
|
||||
|
||||
The Adafruit HAT/Bonnet uses this library but a modified pinout to support other
|
||||
features on the HAT. You can choose the Adafruit pinout with a command line
|
||||
flag.
|
||||
|
||||
Just pass the option `--led-gpio-mapping=adafruit-hat`. This works on the C++
|
||||
and Python examples.
|
||||
|
||||
### Improving flicker
|
||||
|
||||
To improve flicker, we need to do a little hardware modification,
|
||||
but it is very simple: solder a wire between GPIO 4 and 18 as shown in the
|
||||
following picture (click to enlarge):
|
||||
|
||||
<a href="img/adafruit-mod.jpg"><img src="img/adafruit-mod.jpg" height="80px"></a>
|
||||
|
||||
Then, start your programs with `--led-gpio-mapping=adafruit-hat-pwm`.
|
||||
|
||||
Now you should have less visible flicker. This essentially
|
||||
switches on the hardware pulses feature for the Adafruit HAT/Bonnet.
|
||||
|
||||
### 64x64 with E-line on Adafruit HAT/Bonnet
|
||||
There are LED panels that have 64x64 LEDs packed, but they need 5 address lines,
|
||||
which is 1:32 multiplexing (they have an `E` address-line). The first generation
|
||||
of the Adafruit HAT/Bonnet was not prepared for this, but it can be done with another
|
||||
hardware mod. Beginning October 2018, Adafruit began selling an updated version of
|
||||
the HAT that supports 64x64 panels simply by bridging two pads on the PCB with solder.
|
||||
|
||||
You can identify which HAT you have by looking for the **Address E** pads, circled here:
|
||||
|
||||
<a href="https://cdn-learn.adafruit.com/assets/assets/000/063/005/original/led_matrices_addr-e-pad.jpg" target="_blank"><img src="https://cdn-learn.adafruit.com/assets/assets/000/063/005/original/led_matrices_addr-e-pad.jpg" height=80></a>
|
||||
|
||||
### New Adafruit RGB Matrix Hat (with Address E pads)
|
||||
|
||||
Look for the Address E pads located between the HUB75 connector and Pi camera cutout.
|
||||
|
||||
Melt a blob of solder between the center “E” pad the the “8” pad just above it
|
||||
(for 64x64 matrices in the Adafruit shop)…*_or_* the “16” pad below (rare, for some
|
||||
third-party 64x64 matrices…check datasheet).
|
||||
|
||||
### Old Adafruit HAT/Bonnet (without)
|
||||
|
||||
It is a little more advanced hack, so it is only really for people who are
|
||||
comfortable with this kind of thing.
|
||||
First, you have to figure out which is the input of the E-Line on your matrix
|
||||
(they seem to be either on Pin 4 or Pin 8 of the IDC connector).
|
||||
You need to disconnect that Pin from the ground plane (e.g. with an Exacto
|
||||
knife) and connect GPIO 24 to it. The following images illustrate the case for
|
||||
IDC Pin 4.
|
||||
|
||||
<a href="img/adafruit-64x64-front.jpg"><img src="img/adafruit-64x64-front.jpg" height="80px"></a>
|
||||
<a href="img/adafruit-64x64-back.jpg"><img src="img/adafruit-64x64-back.jpg" height="80px"></a>
|
||||
|
||||
If the direct connection does not work, you need to send it through a free
|
||||
level converter of the Adafruit HAT/Bonnet. Since all unused inputs are grounded
|
||||
with traces under the chip, this involves lifting a leg from the
|
||||
HCT245 (figure out a free bus driver from the schematic). If all of the
|
||||
above makes sense to you, you have the Ninja level to do it!
|
||||
|
||||
It might be more convienent at this point to consider the [Active3 adapter](./adapter/active-3)
|
||||
that has that covered already.
|
||||
|
||||
Running as root
|
||||
---------------
|
||||
The library requires to access hardware registers to control the LED matrix,
|
||||
and create accurate timings. These hardware accesses require to run as root
|
||||
user.
|
||||
|
||||
For security reasons, it is usually not a good idea to run an application
|
||||
as root entirely, so this library makes sure to drop privileges immediately
|
||||
after the hardware is initialized.
|
||||
|
||||
You can switch off the privilege dropping with the
|
||||
[`--led-no-drop-privs`](#user-content-no-drop-priv) flag, or, if you do this
|
||||
programmatically,
|
||||
choose the configuration in the
|
||||
[`RuntimeOptions struct`](https://github.com/hzeller/rpi-rgb-led-matrix/blob/master/include/led-matrix.h#L401).
|
||||
|
||||
Note, you _could_ run as non-root, which will use `/dev/gpiomem`
|
||||
to at least write to GPIO, however the precise timing hardware registers are
|
||||
not accessible. This will result in flicker and color degradation. Starting
|
||||
as non-root is not recommended.
|
||||
|
||||
CPU use
|
||||
-------
|
||||
|
||||
These displays need to be updated constantly to show an image with PWMed
|
||||
LEDs. This is dependent on the length of the chain: for each chain element,
|
||||
about 1'000'000 write operations have to happen every second!
|
||||
(chain_length * 32 pixel long * 16 rows * 11 bit planes * 180 Hz refresh rate).
|
||||
|
||||
We can't use hardware support for writing these as DMA is too slow,
|
||||
thus the constant CPU use on an RPi is roughly 30-40% of one core.
|
||||
Keep that in mind if you plan to run other things on this computer (This
|
||||
is less noticable on Raspberry Pi, Version 2 or 3 that has more cores).
|
||||
|
||||
Also, the output quality is susceptible to other heavy tasks running on that
|
||||
computer - there might be changes in the overall brigthness when this affects
|
||||
the referesh rate.
|
||||
|
||||
If you have a loaded system and one of the newer Pis with 4 cores, you can
|
||||
reserve one core just for the refresh of the display:
|
||||
|
||||
```
|
||||
isolcpus=3
|
||||
```
|
||||
|
||||
.. at the end of the line of `/boot/cmdline.txt` (needs to be in the same as
|
||||
the other arguments, no newline). This will use the last core
|
||||
only to refresh the display then, but it also means, that no other process can
|
||||
utilize it then. Still, I'd typically recommend it.
|
||||
|
||||
Performance improvements and limits
|
||||
-----------------------------------
|
||||
Regardless of which driving hardware you use, ultimately you can only push pixels
|
||||
so fast to a string of panels before you get flickering due to too low a refresh
|
||||
rate (less than 80-100Hz), or before you refresh the panel lines too fast and they
|
||||
appear too dim because each line is not displayed long enough before it is turned off.
|
||||
|
||||
Basic performance tips:
|
||||
- Use --led-show-refresh to see the refresh rate while you try parameters
|
||||
- use an active-3 board with led-parallel=3
|
||||
- led-pwm-dither-bits=1 gives you a speed boost but less brightness
|
||||
- led-pwm-lsb-nanoseconds=50 also gives you a speed boost but less brightness
|
||||
- led-pwm-bits=7 or even lower decrease color depth but increases refresh speed
|
||||
- AB panels and other panels with that use values of led-multiplexing bigger than 0,
|
||||
will also go faster, although as you tune more options given above, their advantage will decrease.
|
||||
- 32x16 ABC panels are faster than ABCD which are faster than ABCDE, which are faster than 128x64 ABC panels
|
||||
(which do use 5 address lines, but over only 3 wires)
|
||||
- Use at least an rPi3 (rPi4 is still slightly faster but may need --led-slowdown-gpio=2)
|
||||
|
||||
Maximum resolutions reasonably achievable:
|
||||
A general rule of thumb is that running 16K pixels (128x128 or otherwise) on a single chain,
|
||||
is already pushing limits and you will have to make tradeoffs in visual quality. 32K pixels
|
||||
(like 128x256) is definitely pushing things and you'll get 100Hz or less depending on the
|
||||
performance options you choose.
|
||||
This puts the maximum reasonable resolution around 100K pixels (like 384x256) for 3 chains.
|
||||
You can see more examples and video capture of speed on [Marc MERLIN's page 'RGB Panels, from 192x80, to 384x192, to 384x256 and maybe not much beyond'](http://marc.merlins.org/perso/arduino/post_2020-03-13_RGB-Panels_-from-192x80_-to-384x192_-to-384x256-and-maybe-not-much-beyond.html)
|
||||
If your refresh rate is below 300Hz, expect likely black bars when taking cell phone pictures.
|
||||
A real camera with shutter speed lowered accordingly, will get around this.
|
||||
|
||||
Ultimately, you should not expect to go past 64K pixels using 3 chains without significant
|
||||
quality tradeoffs. If you need bigger displays, you should use multiple boards and synchronize the
|
||||
output.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
If you are using the Adafruit HAT/Bonnet in the default configuration, then we
|
||||
can't make use of the PWM hardware (which only outputs
|
||||
to a particular pin), so you'll see random brightness glitches. I strongly
|
||||
suggest to do the aforementioned hardware mod.
|
||||
|
||||
The system needs constant CPU to update the display. Using the DMA controller
|
||||
was considered but after extensive experiments
|
||||
( https://github.com/hzeller/rpi-gpio-dma-demo )
|
||||
dropped due to its slow speed..
|
||||
|
||||
There is an upper limit in how fast the GPIO pins can be controlled, which
|
||||
limits the frame-rate. Raspberry Pi 2's and newer are generally faster.
|
||||
|
||||
Even with everything in place, you might see faint brightness fluctuations
|
||||
in particular if there is something going on on the network or in a terminal
|
||||
on the Pi; this could probably be mitigated with some more real-time
|
||||
kernel for the Pi; maybe there are also hardware limitations (memory bus
|
||||
contention?). Anyway, if you have a realtime kernel configuration that you
|
||||
have optimized for this application, let me know.
|
||||
|
||||
To address the brightness fluctuations, you might experiment with the
|
||||
`FIXED_FRAME_MICROSECONDS` compile time option in [lib/Makefile](lib/Makefile)
|
||||
that has instructions how to set it up.
|
||||
|
||||
Fun
|
||||
---
|
||||
I am always happy to see users successfully using the software for wonderful
|
||||
things, like this installation by Dirk in Scharbeutz, Germany:
|
||||
|
||||

|
||||
|
||||
[led-image-viewer]: ./utils#image-viewer
|
||||
[video-viewer]: ./utils#video-viewer
|
||||
[matrix64]: ./img/chained-64x64.jpg
|
||||
[sparkfun]: https://www.sparkfun.com/products/12584
|
||||
[ada]: http://www.adafruit.com/product/1484
|
||||
[rt-paper]: https://www.osadl.org/fileadmin/dam/rtlws/12/Brown.pdf
|
||||
[adafruit-hat]: https://www.adafruit.com/products/2345
|
||||
[raspbian-lite]: https://downloads.raspberrypi.org/raspbian_lite_latest
|
||||
[DietPi]: https://dietpi.com/
|
||||
[Adafruit HAT]: https://www.adafruit.com/products/2345
|
||||
[Adafruit Bonnet]: https://www.adafruit.com/product/3211
|
||||
[Nodejs binding]: https://github.com/zeitungen/node-rpi-rgb-led-matrix
|
||||
[Go binding]: https://github.com/mcuadros/go-rpi-rgb-led-matrix
|
||||
[Rust binding]: https://crates.io/crates/rpi-led-matrix
|
||||
[Nodejs/Typescript binding]: https://github.com/alexeden/rpi-led-matrix
|
||||
[headless]: https://www.raspberrypi.com/documentation/computers/configuration.html#setting-up-a-headless-raspberry-pi
|
||||
23
depends/rpi-rgb-led-matrix/adapter/README.md
Normal file
23
depends/rpi-rgb-led-matrix/adapter/README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
PCB adapter for Raspberry Pi to Hub75 RGB Matrixes
|
||||
==================================================
|
||||
|
||||
Since hand-wiring can be a little tedious, here are some PCBs that help
|
||||
with the wiring when using the `rpi-rgb-led-matrix` code.
|
||||
|
||||
* [Passive-3](./passive-3) Supports three parallel chains, directly connected
|
||||
to the output of a Rapsberry Pi with 40 GPIO pins. Works, but usually it is better to
|
||||
buffer the outputs using the ...
|
||||
* [Active-3](./active-3) board. Supports three parallel chains with active buffering
|
||||
and 3.3V -> 5V level shifting for best reliability. Requires SMD soldering.
|
||||
|
||||
As another option you can buy it from these locations not affiliated with this project.
|
||||
They are given to help you locate premade boards but no guarantees are given or implied:
|
||||
* https://www.electrodragon.com/product/rgb-matrix-panel-drive-board-raspberry-pi/
|
||||
($3/board, but fairly long and/or expensive shipping from HKG)
|
||||
* Seller #2 (fill me)
|
||||
* The [Passive-RPi1](./passive-rpi1) adapter board is to connect one panel to
|
||||
Raspberry Pi 1 with 26 GPIO pins.
|
||||
|
||||
![Three Panels connected][three-panels]
|
||||
|
||||
[three-panels]: ../img/three-parallel-panels-soic.jpg
|
||||
3
depends/rpi-rgb-led-matrix/adapter/active-3/Makefile
Normal file
3
depends/rpi-rgb-led-matrix/adapter/active-3/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
include ../kicad-scripts/makefile.inc
|
||||
|
||||
active3-rpi-hub75-adapter-fab.zip:
|
||||
84
depends/rpi-rgb-led-matrix/adapter/active-3/README.md
Normal file
84
depends/rpi-rgb-led-matrix/adapter/active-3/README.md
Normal file
@@ -0,0 +1,84 @@
|
||||
Adapter PCB to support up to 3 panel chains
|
||||
===========================================
|
||||
|
||||
* Supports up to three panel chains for newer plus models and
|
||||
Raspberry Pi 2 that have 40 GPIO pins.
|
||||
* Uses HCT245 to level shift signals from 3.3V to 5V and shield
|
||||
the Raspberry Pi GPIOs from overloading.
|
||||
* Open source KiCAD PCB EDA format.
|
||||
* Optional: Pads to power the Pi with 5V, including optional capacitor footprints.
|
||||
* Connector for RxD input (literally the only GPIO pin left) in case you want to
|
||||
make your panel controlled with a serial interface (3.3V logic level).
|
||||
* Provides a way to choose the pinout for different kinds of 64x64 matrixes.
|
||||
* (not very pretty layout, was just lazy and let the auto-router generate the first pass)
|
||||
* BOM:
|
||||
- 4x 74HCT245 or 74AHCT245 in 20-SOIC, 7.5mm package which should make
|
||||
it easy to hand-solder. Make sure to get the variant with the **T**: HC**T** or AHC**T**
|
||||
(there are also HC or AHC, don't use these).
|
||||
- 4x 100nF ceramic capacitor (0805 package)
|
||||
- 1x 10kOhm resistor (0805 package). Not critcial, just a pullup (2.2k .. 15k probably ok).
|
||||
- 3x 16pin IDC (=2x8) male receptible to connect the panels.
|
||||
- 1x 40pin female connector to connect to the RPi.
|
||||
- 1x (optional) 22μF .. 100μF capacitor for 5V rail (either 1206 SMD or
|
||||
radial electrolytic with 2.5mm pitch/6.3mm diameter)
|
||||
* The Gerber FAB files are provided as [active3-rpi-hub75-adapter-fab.zip](./active3-rpi-hub75-adapter-fab.zip)
|
||||
|
||||
The board is also [shared on OSH Park][osh-active3] (not affiliated).
|
||||
|
||||
![Preview][rendering]
|
||||
![Real World][real-world]
|
||||
|
||||
Essentially, this is connecting the output pins through level shifting buffers (they
|
||||
are operated at 5V, but the HCT series chips accept 3.3V input levels from the Pi). The
|
||||
strobe, OE and clock signals are separately buffered for each connector.
|
||||
|
||||
![Schematic][schematic]
|
||||
|
||||
## Optional
|
||||
|
||||
### Power in
|
||||
|
||||
The area on the left has 5V/GND input pads, that allow you to power your Raspberry Pi from
|
||||
a 5V source ... which you are likely to have as you are powering the LED Matrix. This is often
|
||||
more convenient than using the USB connector to power the Pi.
|
||||
|
||||
If you do that, there are pads to add a capacitor to smooth the supply - two footprints are
|
||||
provided: C5 and C6 for through-hole or surface mount components. The value is not critical;
|
||||
I usually use a 22μF/6.3V ceramic capacitor on the C6 pads.
|
||||
|
||||
### Choose E-Line for 64x64 panels with 1:32 multiplexing
|
||||
|
||||
If you have a 64x64 matrix with 1:32 multiplexing, you need to supply an `E`-address line to it.
|
||||
While the Address lines `A` to `D` have fixed positions on the Hub75 connector, there
|
||||
seem to be two different ways to connect the `E` address line: it is either on pin 4 or pin 8
|
||||
of the connector. So this adapter board provides the flexibility to choose the right pin for
|
||||
your matrix.
|
||||
|
||||
Look at the back of the matrix or the documentation to find out for your specific board where
|
||||
to connect E.
|
||||
|
||||
Once you know that, the jumper area in the bottom left of this adapter board allows to choose
|
||||
to which pin to connect the E-address line to. The corresponding other pin should be connected
|
||||
to GND. Simply solder a wire bridge as indicated below (or use a jumper that you can change later).
|
||||
|
||||
If you are not using such 64x64 matrix, you can connect both these pins to GND.
|
||||
|
||||
Here are the typical configurations:
|
||||
|
||||
No 1:32 64x64: to GND | E-Line on Pin 4 | E-Line on Pin 8|
|
||||
-------------------------|-------------------|----------------
|
||||
![][config-default] |![][config-pin4] |![][config-pin8]
|
||||
|
||||
### Input for serial RxD
|
||||
|
||||
If you are not using a 64x64 display that occupies the E-Line, you can use the RxD serial input -
|
||||
this might come in handy if you are using the display to be controlled by a serial line. Be aware
|
||||
that the input requires 3.3V level, so if you have a RS232, make sure to first adapt the levels.
|
||||
|
||||
[rendering]: ../../img/active3-pcb.png
|
||||
[config-default]: ../../img/active3-pcb-config-default.png
|
||||
[config-pin4]: ../../img/active3-pcb-config-pin4.png
|
||||
[config-pin8]: ../../img/active3-pcb-config-pin8.png
|
||||
[schematic]: ../../img/active3-schematic.png
|
||||
[real-world]: ../../img/three-parallel-panels-soic.jpg
|
||||
[osh-active3]: https://oshpark.com/shared_projects/6xAD1VXr
|
||||
@@ -0,0 +1,352 @@
|
||||
EESchema-LIBRARY Version 2.4
|
||||
#encoding utf-8
|
||||
#
|
||||
# 74xx_74HC245
|
||||
#
|
||||
DEF 74xx_74HC245 U 0 40 Y Y 1 L N
|
||||
F0 "U" -300 650 50 H V C CNN
|
||||
F1 "74xx_74HC245" -300 -650 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
ALIAS 74HC245
|
||||
$FPLIST
|
||||
DIP?20*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -300 600 300 -600 1 1 10 f
|
||||
P 3 1 0 0 -25 -50 -25 50 25 50 N
|
||||
P 4 1 0 0 -50 -50 25 -50 25 50 50 50 N
|
||||
X A->B 1 -500 -400 200 R 50 50 1 0 I
|
||||
X GND 10 0 -800 200 U 50 50 1 0 W
|
||||
X B7 11 500 -200 200 L 50 50 1 0 T
|
||||
X B6 12 500 -100 200 L 50 50 1 0 T
|
||||
X B5 13 500 0 200 L 50 50 1 0 T
|
||||
X B4 14 500 100 200 L 50 50 1 0 T
|
||||
X B3 15 500 200 200 L 50 50 1 0 T
|
||||
X B2 16 500 300 200 L 50 50 1 0 T
|
||||
X B1 17 500 400 200 L 50 50 1 0 T
|
||||
X B0 18 500 500 200 L 50 50 1 0 T
|
||||
X CE 19 -500 -500 200 R 50 50 1 0 I I
|
||||
X A0 2 -500 500 200 R 50 50 1 0 T
|
||||
X VCC 20 0 800 200 D 50 50 1 0 W
|
||||
X A1 3 -500 400 200 R 50 50 1 0 T
|
||||
X A2 4 -500 300 200 R 50 50 1 0 T
|
||||
X A3 5 -500 200 200 R 50 50 1 0 T
|
||||
X A4 6 -500 100 200 R 50 50 1 0 T
|
||||
X A5 7 -500 0 200 R 50 50 1 0 T
|
||||
X A6 8 -500 -100 200 R 50 50 1 0 T
|
||||
X A7 9 -500 -200 200 R 50 50 1 0 T
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Connector_Generic_Conn_01x01
|
||||
#
|
||||
DEF Connector_Generic_Conn_01x01 J 0 40 Y N 1 F N
|
||||
F0 "J" 0 100 50 H V C CNN
|
||||
F1 "Connector_Generic_Conn_01x01" 0 -100 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
Connector*:*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -50 5 0 -5 1 1 6 N
|
||||
S -50 50 50 -50 1 1 10 f
|
||||
X Pin_1 1 -200 0 150 R 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Connector_Generic_Conn_01x02
|
||||
#
|
||||
DEF Connector_Generic_Conn_01x02 J 0 40 Y N 1 F N
|
||||
F0 "J" 0 100 50 H V C CNN
|
||||
F1 "Connector_Generic_Conn_01x02" 0 -200 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
Connector*:*_1x??_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -50 -95 0 -105 1 1 6 N
|
||||
S -50 5 0 -5 1 1 6 N
|
||||
S -50 50 50 -150 1 1 10 f
|
||||
X Pin_1 1 -200 0 150 R 50 50 1 1 P
|
||||
X Pin_2 2 -200 -100 150 R 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Connector_Generic_Conn_02x01
|
||||
#
|
||||
DEF Connector_Generic_Conn_02x01 J 0 40 Y N 1 F N
|
||||
F0 "J" 50 100 50 H V C CNN
|
||||
F1 "Connector_Generic_Conn_02x01" 50 -100 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
Connector*:*_2x??_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -50 5 0 -5 1 1 6 N
|
||||
S -50 50 150 -50 1 1 10 f
|
||||
S 150 5 100 -5 1 1 6 N
|
||||
X Pin_1 1 -200 0 150 R 50 50 1 1 P
|
||||
X Pin_2 2 300 0 150 L 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Connector_Generic_Conn_02x08_Odd_Even
|
||||
#
|
||||
DEF Connector_Generic_Conn_02x08_Odd_Even J 0 40 Y N 1 F N
|
||||
F0 "J" 50 400 50 H V C CNN
|
||||
F1 "Connector_Generic_Conn_02x08_Odd_Even" 50 -500 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
Connector*:*_2x??_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -50 -395 0 -405 1 1 6 N
|
||||
S -50 -295 0 -305 1 1 6 N
|
||||
S -50 -195 0 -205 1 1 6 N
|
||||
S -50 -95 0 -105 1 1 6 N
|
||||
S -50 5 0 -5 1 1 6 N
|
||||
S -50 105 0 95 1 1 6 N
|
||||
S -50 205 0 195 1 1 6 N
|
||||
S -50 305 0 295 1 1 6 N
|
||||
S -50 350 150 -450 1 1 10 f
|
||||
S 150 -395 100 -405 1 1 6 N
|
||||
S 150 -295 100 -305 1 1 6 N
|
||||
S 150 -195 100 -205 1 1 6 N
|
||||
S 150 -95 100 -105 1 1 6 N
|
||||
S 150 5 100 -5 1 1 6 N
|
||||
S 150 105 100 95 1 1 6 N
|
||||
S 150 205 100 195 1 1 6 N
|
||||
S 150 305 100 295 1 1 6 N
|
||||
X Pin_1 1 -200 300 150 R 50 50 1 1 P
|
||||
X Pin_10 10 300 -100 150 L 50 50 1 1 P
|
||||
X Pin_11 11 -200 -200 150 R 50 50 1 1 P
|
||||
X Pin_12 12 300 -200 150 L 50 50 1 1 P
|
||||
X Pin_13 13 -200 -300 150 R 50 50 1 1 P
|
||||
X Pin_14 14 300 -300 150 L 50 50 1 1 P
|
||||
X Pin_15 15 -200 -400 150 R 50 50 1 1 P
|
||||
X Pin_16 16 300 -400 150 L 50 50 1 1 P
|
||||
X Pin_2 2 300 300 150 L 50 50 1 1 P
|
||||
X Pin_3 3 -200 200 150 R 50 50 1 1 P
|
||||
X Pin_4 4 300 200 150 L 50 50 1 1 P
|
||||
X Pin_5 5 -200 100 150 R 50 50 1 1 P
|
||||
X Pin_6 6 300 100 150 L 50 50 1 1 P
|
||||
X Pin_7 7 -200 0 150 R 50 50 1 1 P
|
||||
X Pin_8 8 300 0 150 L 50 50 1 1 P
|
||||
X Pin_9 9 -200 -100 150 R 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Connector_Generic_Conn_02x20_Odd_Even
|
||||
#
|
||||
DEF Connector_Generic_Conn_02x20_Odd_Even J 0 40 Y N 1 F N
|
||||
F0 "J" 50 1000 50 H V C CNN
|
||||
F1 "Connector_Generic_Conn_02x20_Odd_Even" 50 -1100 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
Connector*:*_2x??_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -50 -995 0 -1005 1 1 6 N
|
||||
S -50 -895 0 -905 1 1 6 N
|
||||
S -50 -795 0 -805 1 1 6 N
|
||||
S -50 -695 0 -705 1 1 6 N
|
||||
S -50 -595 0 -605 1 1 6 N
|
||||
S -50 -495 0 -505 1 1 6 N
|
||||
S -50 -395 0 -405 1 1 6 N
|
||||
S -50 -295 0 -305 1 1 6 N
|
||||
S -50 -195 0 -205 1 1 6 N
|
||||
S -50 -95 0 -105 1 1 6 N
|
||||
S -50 5 0 -5 1 1 6 N
|
||||
S -50 105 0 95 1 1 6 N
|
||||
S -50 205 0 195 1 1 6 N
|
||||
S -50 305 0 295 1 1 6 N
|
||||
S -50 405 0 395 1 1 6 N
|
||||
S -50 505 0 495 1 1 6 N
|
||||
S -50 605 0 595 1 1 6 N
|
||||
S -50 705 0 695 1 1 6 N
|
||||
S -50 805 0 795 1 1 6 N
|
||||
S -50 905 0 895 1 1 6 N
|
||||
S -50 950 150 -1050 1 1 10 f
|
||||
S 150 -995 100 -1005 1 1 6 N
|
||||
S 150 -895 100 -905 1 1 6 N
|
||||
S 150 -795 100 -805 1 1 6 N
|
||||
S 150 -695 100 -705 1 1 6 N
|
||||
S 150 -595 100 -605 1 1 6 N
|
||||
S 150 -495 100 -505 1 1 6 N
|
||||
S 150 -395 100 -405 1 1 6 N
|
||||
S 150 -295 100 -305 1 1 6 N
|
||||
S 150 -195 100 -205 1 1 6 N
|
||||
S 150 -95 100 -105 1 1 6 N
|
||||
S 150 5 100 -5 1 1 6 N
|
||||
S 150 105 100 95 1 1 6 N
|
||||
S 150 205 100 195 1 1 6 N
|
||||
S 150 305 100 295 1 1 6 N
|
||||
S 150 405 100 395 1 1 6 N
|
||||
S 150 505 100 495 1 1 6 N
|
||||
S 150 605 100 595 1 1 6 N
|
||||
S 150 705 100 695 1 1 6 N
|
||||
S 150 805 100 795 1 1 6 N
|
||||
S 150 905 100 895 1 1 6 N
|
||||
X Pin_1 1 -200 900 150 R 50 50 1 1 P
|
||||
X Pin_10 10 300 500 150 L 50 50 1 1 P
|
||||
X Pin_11 11 -200 400 150 R 50 50 1 1 P
|
||||
X Pin_12 12 300 400 150 L 50 50 1 1 P
|
||||
X Pin_13 13 -200 300 150 R 50 50 1 1 P
|
||||
X Pin_14 14 300 300 150 L 50 50 1 1 P
|
||||
X Pin_15 15 -200 200 150 R 50 50 1 1 P
|
||||
X Pin_16 16 300 200 150 L 50 50 1 1 P
|
||||
X Pin_17 17 -200 100 150 R 50 50 1 1 P
|
||||
X Pin_18 18 300 100 150 L 50 50 1 1 P
|
||||
X Pin_19 19 -200 0 150 R 50 50 1 1 P
|
||||
X Pin_2 2 300 900 150 L 50 50 1 1 P
|
||||
X Pin_20 20 300 0 150 L 50 50 1 1 P
|
||||
X Pin_21 21 -200 -100 150 R 50 50 1 1 P
|
||||
X Pin_22 22 300 -100 150 L 50 50 1 1 P
|
||||
X Pin_23 23 -200 -200 150 R 50 50 1 1 P
|
||||
X Pin_24 24 300 -200 150 L 50 50 1 1 P
|
||||
X Pin_25 25 -200 -300 150 R 50 50 1 1 P
|
||||
X Pin_26 26 300 -300 150 L 50 50 1 1 P
|
||||
X Pin_27 27 -200 -400 150 R 50 50 1 1 P
|
||||
X Pin_28 28 300 -400 150 L 50 50 1 1 P
|
||||
X Pin_29 29 -200 -500 150 R 50 50 1 1 P
|
||||
X Pin_3 3 -200 800 150 R 50 50 1 1 P
|
||||
X Pin_30 30 300 -500 150 L 50 50 1 1 P
|
||||
X Pin_31 31 -200 -600 150 R 50 50 1 1 P
|
||||
X Pin_32 32 300 -600 150 L 50 50 1 1 P
|
||||
X Pin_33 33 -200 -700 150 R 50 50 1 1 P
|
||||
X Pin_34 34 300 -700 150 L 50 50 1 1 P
|
||||
X Pin_35 35 -200 -800 150 R 50 50 1 1 P
|
||||
X Pin_36 36 300 -800 150 L 50 50 1 1 P
|
||||
X Pin_37 37 -200 -900 150 R 50 50 1 1 P
|
||||
X Pin_38 38 300 -900 150 L 50 50 1 1 P
|
||||
X Pin_39 39 -200 -1000 150 R 50 50 1 1 P
|
||||
X Pin_4 4 300 800 150 L 50 50 1 1 P
|
||||
X Pin_40 40 300 -1000 150 L 50 50 1 1 P
|
||||
X Pin_5 5 -200 700 150 R 50 50 1 1 P
|
||||
X Pin_6 6 300 700 150 L 50 50 1 1 P
|
||||
X Pin_7 7 -200 600 150 R 50 50 1 1 P
|
||||
X Pin_8 8 300 600 150 L 50 50 1 1 P
|
||||
X Pin_9 9 -200 500 150 R 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Device_C
|
||||
#
|
||||
DEF Device_C C 0 10 N Y 1 F N
|
||||
F0 "C" 25 100 50 H V L CNN
|
||||
F1 "Device_C" 25 -100 50 H V L CNN
|
||||
F2 "" 38 -150 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
C_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
P 2 0 1 20 -80 -30 80 -30 N
|
||||
P 2 0 1 20 -80 30 80 30 N
|
||||
X ~ 1 0 150 110 D 50 50 1 1 P
|
||||
X ~ 2 0 -150 110 U 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Device_CP_Small
|
||||
#
|
||||
DEF Device_CP_Small C 0 10 N N 1 F N
|
||||
F0 "C" 10 70 50 H V L CNN
|
||||
F1 "Device_CP_Small" 10 -80 50 H V L CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
CP_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -60 -12 60 -27 0 1 0 F
|
||||
S -60 27 60 12 0 1 0 N
|
||||
P 2 0 1 0 -50 60 -30 60 N
|
||||
P 2 0 1 0 -40 50 -40 70 N
|
||||
X ~ 1 0 100 73 D 50 50 1 1 P
|
||||
X ~ 2 0 -100 73 U 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Device_C_Small
|
||||
#
|
||||
DEF Device_C_Small C 0 10 N N 1 F N
|
||||
F0 "C" 10 70 50 H V L CNN
|
||||
F1 "Device_C_Small" 10 -80 50 H V L CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
C_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
P 2 0 1 13 -60 -20 60 -20 N
|
||||
P 2 0 1 12 -60 20 60 20 N
|
||||
X ~ 1 0 100 80 D 50 50 1 1 P
|
||||
X ~ 2 0 -100 80 U 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# Device_R
|
||||
#
|
||||
DEF Device_R R 0 0 N Y 1 F N
|
||||
F0 "R" 80 0 50 V V C CNN
|
||||
F1 "Device_R" 0 0 50 V V C CNN
|
||||
F2 "" -70 0 50 V I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
$FPLIST
|
||||
R_*
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -40 -100 40 100 0 1 10 N
|
||||
X ~ 1 0 150 50 D 50 50 1 1 P
|
||||
X ~ 2 0 -150 50 U 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# power_GND
|
||||
#
|
||||
DEF power_GND #PWR 0 0 Y Y 1 F P
|
||||
F0 "#PWR" 0 -250 50 H I C CNN
|
||||
F1 "power_GND" 0 -150 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
DRAW
|
||||
P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N
|
||||
X GND 1 0 0 0 D 50 50 1 1 W N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# power_PWR_FLAG
|
||||
#
|
||||
DEF power_PWR_FLAG #FLG 0 0 N N 1 F P
|
||||
F0 "#FLG" 0 75 50 H I C CNN
|
||||
F1 "power_PWR_FLAG" 0 150 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
DRAW
|
||||
P 6 0 1 0 0 0 0 50 -40 75 0 100 40 75 0 50 N
|
||||
X pwr 1 0 0 0 U 50 50 0 0 w
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# power_VCC
|
||||
#
|
||||
DEF power_VCC #PWR 0 0 Y Y 1 F P
|
||||
F0 "#PWR" 0 -150 50 H I C CNN
|
||||
F1 "power_VCC" 0 150 50 H V C CNN
|
||||
F2 "" 0 0 50 H I C CNN
|
||||
F3 "" 0 0 50 H I C CNN
|
||||
DRAW
|
||||
C 0 75 25 0 1 0 N
|
||||
P 2 0 1 0 0 0 0 50 N
|
||||
X VCC 1 0 0 0 U 50 50 1 1 W N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
#End Library
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,33 @@
|
||||
update=Sat 06 Jul 2019 08:45:23 PM PDT
|
||||
version=1
|
||||
last_client=kicad
|
||||
[cvpcb]
|
||||
version=1
|
||||
NetIExt=net
|
||||
[cvpcb/libraries]
|
||||
EquName1=devcms
|
||||
[general]
|
||||
version=1
|
||||
[pcbnew]
|
||||
version=1
|
||||
PageLayoutDescrFile=
|
||||
LastNetListRead=
|
||||
UseCmpFile=1
|
||||
PadDrill=0.6
|
||||
PadDrillOvalY=0.6
|
||||
PadSizeH=1.5
|
||||
PadSizeV=1.5
|
||||
PcbTextSizeV=1.5
|
||||
PcbTextSizeH=1.5
|
||||
PcbTextThickness=0.3
|
||||
ModuleTextSizeV=1
|
||||
ModuleTextSizeH=1
|
||||
ModuleTextSizeThickness=0.15
|
||||
SolderMaskClearance=0
|
||||
SolderMaskMinWidth=0
|
||||
DrawSegmentWidth=0.2
|
||||
BoardOutlineThickness=0.09999999999999999
|
||||
ModuleOutlineThickness=0.15
|
||||
[eeschema]
|
||||
version=1
|
||||
LibDir=
|
||||
File diff suppressed because it is too large
Load Diff
BIN
depends/rpi-rgb-led-matrix/adapter/active-3/schematic.pdf
Normal file
BIN
depends/rpi-rgb-led-matrix/adapter/active-3/schematic.pdf
Normal file
Binary file not shown.
@@ -0,0 +1,83 @@
|
||||
'''
|
||||
Based on gen_gerber_and_drill_files_board.py in kicad/demos directory.
|
||||
'''
|
||||
|
||||
import sys
|
||||
|
||||
from pcbnew import *
|
||||
filename=sys.argv[1]
|
||||
|
||||
board = LoadBoard(filename)
|
||||
|
||||
plotDir = "plot/"
|
||||
|
||||
pctl = PLOT_CONTROLLER(board)
|
||||
|
||||
popt = pctl.GetPlotOptions()
|
||||
|
||||
popt.SetOutputDirectory(plotDir)
|
||||
|
||||
# Set some important plot options:
|
||||
popt.SetPlotFrameRef(False)
|
||||
popt.SetLineWidth(FromMM(0.35))
|
||||
|
||||
popt.SetAutoScale(False)
|
||||
popt.SetScale(1)
|
||||
popt.SetMirror(False)
|
||||
popt.SetUseGerberAttributes(False)
|
||||
popt.SetUseGerberProtelExtensions(True)
|
||||
popt.SetExcludeEdgeLayer(True);
|
||||
popt.SetScale(1)
|
||||
popt.SetUseAuxOrigin(True)
|
||||
|
||||
# This by gerbers only (also the name is truly horrid!)
|
||||
popt.SetSubtractMaskFromSilk(False)
|
||||
|
||||
# param 0 is the layer ID
|
||||
# param 1 is a string added to the file base name to identify the drawing
|
||||
# param 2 is a comment
|
||||
# Create filenames in a way that if they are sorted alphabetically, they
|
||||
# are shown in exactly the layering the board would look like. So
|
||||
# gerbv *
|
||||
# just makes sense.
|
||||
plot_plan = [
|
||||
( Edge_Cuts, "0-Edge_Cuts", "Edges" ),
|
||||
|
||||
( F_Paste, "1-PasteTop", "Paste top" ),
|
||||
( F_SilkS, "2-SilkTop", "Silk top" ),
|
||||
( F_Mask, "3-MaskTop", "Mask top" ),
|
||||
( F_Cu, "4-CuTop", "Top layer" ),
|
||||
|
||||
( B_Cu, "5-CuBottom", "Bottom layer" ),
|
||||
( B_Mask, "6-MaskBottom", "Mask bottom" ),
|
||||
( B_SilkS, "7-SilkBottom", "Silk top" ),
|
||||
( B_Paste, "8-PasteBottom", "Paste Bottom" ),
|
||||
]
|
||||
|
||||
|
||||
for layer_info in plot_plan:
|
||||
pctl.SetLayer(layer_info[0])
|
||||
pctl.OpenPlotfile(layer_info[1], PLOT_FORMAT_GERBER, layer_info[2])
|
||||
pctl.PlotLayer()
|
||||
|
||||
# At the end you have to close the last plot, otherwise you don't know when
|
||||
# the object will be recycled!
|
||||
pctl.ClosePlot()
|
||||
|
||||
# Fabricators need drill files.
|
||||
# sometimes a drill map file is asked (for verification purpose)
|
||||
drlwriter = EXCELLON_WRITER( board )
|
||||
drlwriter.SetMapFileFormat( PLOT_FORMAT_PDF )
|
||||
|
||||
mirror = False
|
||||
minimalHeader = False
|
||||
offset = wxPoint(0,0)
|
||||
mergeNPTH = True
|
||||
drlwriter.SetOptions( mirror, minimalHeader, offset, mergeNPTH )
|
||||
|
||||
metricFmt = True
|
||||
drlwriter.SetFormat( metricFmt )
|
||||
|
||||
genDrl = True
|
||||
genMap = True
|
||||
drlwriter.CreateDrillandMapFilesSet( plotDir, genDrl, genMap );
|
||||
@@ -0,0 +1,8 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
%-fab.zip : %-fab.kicad_pcb
|
||||
python ../kicad-scripts/kicad-fab.py $<
|
||||
zip -r $@ plot/
|
||||
|
||||
%-fab.kicad_pcb : %.kicad_pcb
|
||||
sed "s/%%gitversion%%/`git log --date=short --pretty=format:'%h@%cd' -n 1`/" < $^ > $@
|
||||
3
depends/rpi-rgb-led-matrix/adapter/passive-3/Makefile
Normal file
3
depends/rpi-rgb-led-matrix/adapter/passive-3/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
include ../kicad-scripts/makefile.inc
|
||||
|
||||
passive3-rpi-hub75-adapter-fab.zip:
|
||||
26
depends/rpi-rgb-led-matrix/adapter/passive-3/README.md
Normal file
26
depends/rpi-rgb-led-matrix/adapter/passive-3/README.md
Normal file
@@ -0,0 +1,26 @@
|
||||
Adapter PCB to support up to 3 panel chains
|
||||
===========================================
|
||||
|
||||
* This is a passive board. It is simple, but the logic level will be out of
|
||||
spec for the LED matrix (3.3V vs. 5V) which might or might not work.
|
||||
Driving long cables with the GPIO pins is also not a good idea.
|
||||
* You typically want to consider using the [active board](../active-3).
|
||||
* Works for Matrix up to 1:16 multiplexing (32 rows). For 1:32 multiplexing,
|
||||
you want to use the [active board](../active-3). You can of also hack
|
||||
this board as [suggested in this bugtracker entry](https://github.com/hzeller/rpi-rgb-led-matrix/issues/360#issuecomment-321104348) to make it work with
|
||||
64x64 boards.
|
||||
* Only really advisable, if the LED panels have 74HCT245 (as opposed to just
|
||||
74HC245) in their input stage, because then they can deal properly with
|
||||
the 3.3V logic levels coming from the Pi.
|
||||
* Supports up to three panel chains for newer plus models and
|
||||
Raspberry Pi 2/3 that have 40 GPIO pins.
|
||||
* Open source KiCAD PCB EDA format.
|
||||
* (not very pretty layout, was just lazy and let the auto-router do it).
|
||||
* The FAB files are provided as [passive3-rpi-hub75-adapter-fab.zip](./passive3-rpi-hub75-adapter-fab.zip)
|
||||
|
||||
This board is [shared on OSH Park][osh-passive3] (not affiliated).
|
||||
|
||||
![Preview][rendering]
|
||||
|
||||
[rendering]: ../../img/passive3-pcb.png
|
||||
[osh-passive3]: https://oshpark.com/shared_projects/FNAtZUsP
|
||||
@@ -0,0 +1,218 @@
|
||||
EESchema-LIBRARY Version 2.3
|
||||
#encoding utf-8
|
||||
#
|
||||
<<<<<<< HEAD
|
||||
# CONN_01X01
|
||||
#
|
||||
DEF CONN_01X01 P 0 40 Y N 1 F N
|
||||
F0 "P" 0 100 50 H V C CNN
|
||||
F1 "CONN_01X01" 100 0 50 V V C CNN
|
||||
F2 "" 0 0 60 H V C CNN
|
||||
F3 "" 0 0 60 H V C CNN
|
||||
$FPLIST
|
||||
Pin_Header_Straight_1X01
|
||||
Pin_Header_Angled_1X01
|
||||
Socket_Strip_Straight_1X01
|
||||
Socket_Strip_Angled_1X01
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -50 5 10 -5 0 1 0 N
|
||||
S -50 50 50 -50 0 1 0 N
|
||||
X P1 1 -200 0 150 R 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
=======
|
||||
>>>>>>> d9ecea532afc911de3244f458589b6eadd051949
|
||||
# CONN_02X08
|
||||
#
|
||||
DEF CONN_02X08 P 0 1 Y N 1 F N
|
||||
F0 "P" 0 450 50 H V C CNN
|
||||
F1 "CONN_02X08" 0 0 50 V V C CNN
|
||||
F2 "" 0 -1200 60 H V C CNN
|
||||
F3 "" 0 -1200 60 H V C CNN
|
||||
$FPLIST
|
||||
Pin_Header_Straight_2X08
|
||||
Pin_Header_Angled_2X08
|
||||
Socket_Strip_Straight_2X08
|
||||
Socket_Strip_Angled_2X08
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -100 -345 -50 -355 0 1 0 N
|
||||
S -100 -245 -50 -255 0 1 0 N
|
||||
S -100 -145 -50 -155 0 1 0 N
|
||||
S -100 -45 -50 -55 0 1 0 N
|
||||
S -100 55 -50 45 0 1 0 N
|
||||
S -100 155 -50 145 0 1 0 N
|
||||
S -100 255 -50 245 0 1 0 N
|
||||
S -100 355 -50 345 0 1 0 N
|
||||
S -100 400 100 -400 0 1 0 N
|
||||
S 50 -345 100 -355 0 1 0 N
|
||||
S 50 -245 100 -255 0 1 0 N
|
||||
S 50 -145 100 -155 0 1 0 N
|
||||
S 50 -45 100 -55 0 1 0 N
|
||||
S 50 55 100 45 0 1 0 N
|
||||
S 50 155 100 145 0 1 0 N
|
||||
S 50 255 100 245 0 1 0 N
|
||||
S 50 355 100 345 0 1 0 N
|
||||
X P1 1 -250 350 150 R 50 50 1 1 P
|
||||
X P2 2 250 350 150 L 50 50 1 1 P
|
||||
X P3 3 -250 250 150 R 50 50 1 1 P
|
||||
X P4 4 250 250 150 L 50 50 1 1 P
|
||||
X P5 5 -250 150 150 R 50 50 1 1 P
|
||||
X P6 6 250 150 150 L 50 50 1 1 P
|
||||
X P7 7 -250 50 150 R 50 50 1 1 P
|
||||
X P8 8 250 50 150 L 50 50 1 1 P
|
||||
X P9 9 -250 -50 150 R 50 50 1 1 P
|
||||
X P10 10 250 -50 150 L 50 50 1 1 P
|
||||
X P11 11 -250 -150 150 R 50 50 1 1 P
|
||||
X P12 12 250 -150 150 L 50 50 1 1 P
|
||||
X P13 13 -250 -250 150 R 50 50 1 1 P
|
||||
X P14 14 250 -250 150 L 50 50 1 1 P
|
||||
X P15 15 -250 -350 150 R 50 50 1 1 P
|
||||
X P16 16 250 -350 150 L 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# CONN_02X20
|
||||
#
|
||||
DEF CONN_02X20 P 0 1 Y N 1 F N
|
||||
F0 "P" 0 1050 50 H V C CNN
|
||||
F1 "CONN_02X20" 0 0 50 V V C CNN
|
||||
F2 "" 0 -950 60 H V C CNN
|
||||
F3 "" 0 -950 60 H V C CNN
|
||||
$FPLIST
|
||||
Pin_Header_Straight_2X20
|
||||
Pin_Header_Angled_2X20
|
||||
Socket_Strip_Straight_2X20
|
||||
Socket_Strip_Angled_2X20
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -100 -945 -50 -955 0 1 0 N
|
||||
S -100 -845 -50 -855 0 1 0 N
|
||||
S -100 -745 -50 -755 0 1 0 N
|
||||
S -100 -645 -50 -655 0 1 0 N
|
||||
S -100 -545 -50 -555 0 1 0 N
|
||||
S -100 -445 -50 -455 0 1 0 N
|
||||
S -100 -345 -50 -355 0 1 0 N
|
||||
S -100 -245 -50 -255 0 1 0 N
|
||||
S -100 -145 -50 -155 0 1 0 N
|
||||
S -100 -45 -50 -55 0 1 0 N
|
||||
S -100 55 -50 45 0 1 0 N
|
||||
S -100 155 -50 145 0 1 0 N
|
||||
S -100 255 -50 245 0 1 0 N
|
||||
S -100 355 -50 345 0 1 0 N
|
||||
S -100 455 -50 445 0 1 0 N
|
||||
S -100 555 -50 545 0 1 0 N
|
||||
S -100 655 -50 645 0 1 0 N
|
||||
S -100 755 -50 745 0 1 0 N
|
||||
S -100 855 -50 845 0 1 0 N
|
||||
S -100 955 -50 945 0 1 0 N
|
||||
S -100 1000 100 -1000 0 1 0 N
|
||||
S 50 -945 100 -955 0 1 0 N
|
||||
S 50 -845 100 -855 0 1 0 N
|
||||
S 50 -745 100 -755 0 1 0 N
|
||||
S 50 -645 100 -655 0 1 0 N
|
||||
S 50 -545 100 -555 0 1 0 N
|
||||
S 50 -445 100 -455 0 1 0 N
|
||||
S 50 -345 100 -355 0 1 0 N
|
||||
S 50 -245 100 -255 0 1 0 N
|
||||
S 50 -145 100 -155 0 1 0 N
|
||||
S 50 -45 100 -55 0 1 0 N
|
||||
S 50 55 100 45 0 1 0 N
|
||||
S 50 155 100 145 0 1 0 N
|
||||
S 50 255 100 245 0 1 0 N
|
||||
S 50 355 100 345 0 1 0 N
|
||||
S 50 455 100 445 0 1 0 N
|
||||
S 50 555 100 545 0 1 0 N
|
||||
S 50 655 100 645 0 1 0 N
|
||||
S 50 755 100 745 0 1 0 N
|
||||
S 50 855 100 845 0 1 0 N
|
||||
S 50 955 100 945 0 1 0 N
|
||||
X P1 1 -250 950 150 R 50 50 1 1 P
|
||||
X P2 2 250 950 150 L 50 50 1 1 P
|
||||
X P3 3 -250 850 150 R 50 50 1 1 P
|
||||
X P4 4 250 850 150 L 50 50 1 1 P
|
||||
X P5 5 -250 750 150 R 50 50 1 1 P
|
||||
X P6 6 250 750 150 L 50 50 1 1 P
|
||||
X P7 7 -250 650 150 R 50 50 1 1 P
|
||||
X P8 8 250 650 150 L 50 50 1 1 P
|
||||
X P9 9 -250 550 150 R 50 50 1 1 P
|
||||
X P10 10 250 550 150 L 50 50 1 1 P
|
||||
X P20 20 250 50 150 L 50 50 1 1 P
|
||||
X P30 30 250 -450 150 L 50 50 1 1 P
|
||||
X P40 40 250 -950 150 L 50 50 1 1 P
|
||||
X P11 11 -250 450 150 R 50 50 1 1 P
|
||||
X P21 21 -250 -50 150 R 50 50 1 1 P
|
||||
X P31 31 -250 -550 150 R 50 50 1 1 P
|
||||
X P12 12 250 450 150 L 50 50 1 1 P
|
||||
X P22 22 250 -50 150 L 50 50 1 1 P
|
||||
X P32 32 250 -550 150 L 50 50 1 1 P
|
||||
X P13 13 -250 350 150 R 50 50 1 1 P
|
||||
X P23 23 -250 -150 150 R 50 50 1 1 P
|
||||
X P33 33 -250 -650 150 R 50 50 1 1 P
|
||||
X P14 14 250 350 150 L 50 50 1 1 P
|
||||
X P24 24 250 -150 150 L 50 50 1 1 P
|
||||
X P34 34 250 -650 150 L 50 50 1 1 P
|
||||
X P15 15 -250 250 150 R 50 50 1 1 P
|
||||
X P25 25 -250 -250 150 R 50 50 1 1 P
|
||||
X P35 35 -250 -750 150 R 50 50 1 1 P
|
||||
X P16 16 250 250 150 L 50 50 1 1 P
|
||||
X P26 26 250 -250 150 L 50 50 1 1 P
|
||||
X P36 36 250 -750 150 L 50 50 1 1 P
|
||||
X P17 17 -250 150 150 R 50 50 1 1 P
|
||||
X P27 27 -250 -350 150 R 50 50 1 1 P
|
||||
X P37 37 -250 -850 150 R 50 50 1 1 P
|
||||
X P18 18 250 150 150 L 50 50 1 1 P
|
||||
X P28 28 250 -350 150 L 50 50 1 1 P
|
||||
X P38 38 250 -850 150 L 50 50 1 1 P
|
||||
X P19 19 -250 50 150 R 50 50 1 1 P
|
||||
X P29 29 -250 -450 150 R 50 50 1 1 P
|
||||
X P39 39 -250 -950 150 R 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# GND
|
||||
#
|
||||
DEF GND #PWR 0 0 Y Y 1 F P
|
||||
F0 "#PWR" 0 -250 50 H I C CNN
|
||||
F1 "GND" 0 -150 50 H V C CNN
|
||||
F2 "" 0 0 60 H V C CNN
|
||||
F3 "" 0 0 60 H V C CNN
|
||||
DRAW
|
||||
P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N
|
||||
X GND 1 0 0 0 D 50 50 1 1 W N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
# PWR_FLAG
|
||||
#
|
||||
DEF PWR_FLAG #FLG 0 0 N N 1 F P
|
||||
F0 "#FLG" 0 95 50 H I C CNN
|
||||
F1 "PWR_FLAG" 0 180 50 H V C CNN
|
||||
F2 "" 0 0 60 H V C CNN
|
||||
F3 "" 0 0 60 H V C CNN
|
||||
DRAW
|
||||
X pwr 1 0 0 0 U 20 20 0 0 w
|
||||
P 6 0 1 0 0 0 0 50 -75 100 0 150 75 100 0 50 N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
>>>>>>> d9ecea532afc911de3244f458589b6eadd051949
|
||||
# VCC
|
||||
#
|
||||
DEF VCC #PWR 0 0 Y Y 1 F P
|
||||
F0 "#PWR" 0 -150 50 H I C CNN
|
||||
F1 "VCC" 0 150 50 H V C CNN
|
||||
F2 "" 0 0 60 H V C CNN
|
||||
F3 "" 0 0 60 H V C CNN
|
||||
DRAW
|
||||
C 0 75 25 0 1 0 N
|
||||
P 2 0 1 0 0 0 0 50 N
|
||||
X VCC 1 0 0 0 U 50 50 1 1 W N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
#End Library
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,63 @@
|
||||
update=Wed 17 Jun 2015 07:02:16 PM PDT
|
||||
version=1
|
||||
last_client=kicad
|
||||
[cvpcb]
|
||||
version=1
|
||||
NetIExt=net
|
||||
[cvpcb/libraries]
|
||||
EquName1=devcms
|
||||
[general]
|
||||
version=1
|
||||
[pcbnew]
|
||||
version=1
|
||||
PageLayoutDescrFile=
|
||||
LastNetListRead=passive3-rpi-hub75-adapter.net
|
||||
UseCmpFile=0
|
||||
PadDrill=3.048
|
||||
PadDrillOvalY=3.048
|
||||
PadSizeH=4.064
|
||||
PadSizeV=4.064
|
||||
PcbTextSizeV=1.5
|
||||
PcbTextSizeH=1.5
|
||||
PcbTextThickness=0.3
|
||||
ModuleTextSizeV=1
|
||||
ModuleTextSizeH=1
|
||||
ModuleTextSizeThickness=0.15
|
||||
SolderMaskClearance=0
|
||||
SolderMaskMinWidth=0
|
||||
DrawSegmentWidth=0.2
|
||||
BoardOutlineThickness=0.09999999999999999
|
||||
ModuleOutlineThickness=0.15
|
||||
[eeschema]
|
||||
version=1
|
||||
LibDir=
|
||||
[eeschema/libraries]
|
||||
LibName1=power
|
||||
LibName2=device
|
||||
LibName3=transistors
|
||||
LibName4=conn
|
||||
LibName5=linear
|
||||
LibName6=regul
|
||||
LibName7=74xx
|
||||
LibName8=cmos4000
|
||||
LibName9=adc-dac
|
||||
LibName10=memory
|
||||
LibName11=xilinx
|
||||
LibName12=microcontrollers
|
||||
LibName13=dsp
|
||||
LibName14=microchip
|
||||
LibName15=analog_switches
|
||||
LibName16=motorola
|
||||
LibName17=texas
|
||||
LibName18=intel
|
||||
LibName19=audio
|
||||
LibName20=interface
|
||||
LibName21=digital-audio
|
||||
LibName22=philips
|
||||
LibName23=display
|
||||
LibName24=cypress
|
||||
LibName25=siliconi
|
||||
LibName26=opto
|
||||
LibName27=atmel
|
||||
LibName28=contrib
|
||||
LibName29=valves
|
||||
@@ -0,0 +1,408 @@
|
||||
EESchema Schematic File Version 2
|
||||
LIBS:power
|
||||
LIBS:device
|
||||
LIBS:transistors
|
||||
LIBS:conn
|
||||
LIBS:linear
|
||||
LIBS:regul
|
||||
LIBS:74xx
|
||||
LIBS:cmos4000
|
||||
LIBS:adc-dac
|
||||
LIBS:memory
|
||||
LIBS:xilinx
|
||||
LIBS:microcontrollers
|
||||
LIBS:dsp
|
||||
LIBS:microchip
|
||||
LIBS:analog_switches
|
||||
LIBS:motorola
|
||||
LIBS:texas
|
||||
LIBS:intel
|
||||
LIBS:audio
|
||||
LIBS:interface
|
||||
LIBS:digital-audio
|
||||
LIBS:philips
|
||||
LIBS:display
|
||||
LIBS:cypress
|
||||
LIBS:siliconi
|
||||
LIBS:opto
|
||||
LIBS:atmel
|
||||
LIBS:contrib
|
||||
LIBS:valves
|
||||
EELAYER 25 0
|
||||
EELAYER END
|
||||
$Descr A4 11693 8268
|
||||
encoding utf-8
|
||||
Sheet 1 1
|
||||
Title ""
|
||||
Date ""
|
||||
Rev ""
|
||||
Comp ""
|
||||
Comment1 ""
|
||||
Comment2 ""
|
||||
Comment3 ""
|
||||
Comment4 ""
|
||||
$EndDescr
|
||||
$Comp
|
||||
L CONN_02X08 Panel-1
|
||||
U 1 1 54ECB236
|
||||
P 6950 2550
|
||||
F 0 "Panel-1" H 6950 3000 50 0000 C CNN
|
||||
F 1 "CONN_02X08" V 6950 2550 50 0000 C CNN
|
||||
F 2 "Pin_Headers:Pin_Header_Straight_2x08" H 6950 1350 60 0001 C CNN
|
||||
F 3 "" H 6950 1350 60 0000 C CNN
|
||||
1 6950 2550
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L CONN_02X20 P1
|
||||
U 1 1 54ECB2B7
|
||||
P 4500 3700
|
||||
F 0 "P1" H 4500 4750 50 0000 C CNN
|
||||
F 1 "CONN_02X20" V 4500 3700 50 0000 C CNN
|
||||
F 2 "Pin_Headers:Pin_Header_Straight_2x20" H 4500 2750 60 0001 C CNN
|
||||
F 3 "" H 4500 2750 60 0000 C CNN
|
||||
1 4500 3700
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
4800 2700 4800 2850
|
||||
Wire Wire Line
|
||||
4750 2750 4950 2750
|
||||
Wire Wire Line
|
||||
4800 2850 4750 2850
|
||||
Connection ~ 4800 2750
|
||||
$Comp
|
||||
L GND #PWR01
|
||||
U 1 1 54ECB3E1
|
||||
P 4850 3350
|
||||
F 0 "#PWR01" H 4850 3350 30 0001 C CNN
|
||||
F 1 "GND" H 4850 3280 30 0001 C CNN
|
||||
F 2 "" H 4850 3350 60 0000 C CNN
|
||||
F 3 "" H 4850 3350 60 0000 C CNN
|
||||
1 4850 3350
|
||||
0 -1 -1 0
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
4750 3350 4850 3350
|
||||
$Comp
|
||||
L GND #PWR02
|
||||
U 1 1 54ECB417
|
||||
P 4850 3650
|
||||
F 0 "#PWR02" H 4850 3650 30 0001 C CNN
|
||||
F 1 "GND" H 4850 3580 30 0001 C CNN
|
||||
F 2 "" H 4850 3650 60 0000 C CNN
|
||||
F 3 "" H 4850 3650 60 0000 C CNN
|
||||
1 4850 3650
|
||||
0 -1 -1 0
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
4750 3650 4850 3650
|
||||
$Comp
|
||||
L GND #PWR03
|
||||
U 1 1 54ECB4A1
|
||||
P 4850 2950
|
||||
F 0 "#PWR03" H 4850 2950 30 0001 C CNN
|
||||
F 1 "GND" H 4850 2880 30 0001 C CNN
|
||||
F 2 "" H 4850 2950 60 0000 C CNN
|
||||
F 3 "" H 4850 2950 60 0000 C CNN
|
||||
1 4850 2950
|
||||
0 -1 -1 0
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
4750 2950 4850 2950
|
||||
$Comp
|
||||
L GND #PWR04
|
||||
U 1 1 54ECB5FE
|
||||
P 4150 4650
|
||||
F 0 "#PWR04" H 4150 4650 30 0001 C CNN
|
||||
F 1 "GND" H 4150 4580 30 0001 C CNN
|
||||
F 2 "" H 4150 4650 60 0000 C CNN
|
||||
F 3 "" H 4150 4650 60 0000 C CNN
|
||||
1 4150 4650
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
4150 4650 4250 4650
|
||||
$Comp
|
||||
L GND #PWR05
|
||||
U 1 1 54ECB73E
|
||||
P 4850 4350
|
||||
F 0 "#PWR05" H 4850 4350 30 0001 C CNN
|
||||
F 1 "GND" H 4850 4280 30 0001 C CNN
|
||||
F 2 "" H 4850 4350 60 0000 C CNN
|
||||
F 3 "" H 4850 4350 60 0000 C CNN
|
||||
1 4850 4350
|
||||
0 -1 -1 0
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
4750 4350 4850 4350
|
||||
$Comp
|
||||
L GND #PWR06
|
||||
U 1 1 54ECB7BC
|
||||
P 4150 3950
|
||||
F 0 "#PWR06" H 4150 3950 30 0001 C CNN
|
||||
F 1 "GND" H 4150 3880 30 0001 C CNN
|
||||
F 2 "" H 4150 3950 60 0000 C CNN
|
||||
F 3 "" H 4150 3950 60 0000 C CNN
|
||||
1 4150 3950
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
4150 3950 4250 3950
|
||||
Text GLabel 4250 3050 0 51 Output ~ 0
|
||||
strobe
|
||||
Text GLabel 4750 4250 2 51 Output ~ 0
|
||||
p1_r1
|
||||
Text GLabel 4250 4150 0 51 Output ~ 0
|
||||
p1_g1
|
||||
Text GLabel 4250 4250 0 51 Output ~ 0
|
||||
p1_b1
|
||||
Text GLabel 4250 4450 0 51 Output ~ 0
|
||||
p1_r2
|
||||
Text GLabel 4250 4350 0 51 Output ~ 0
|
||||
p1_g2
|
||||
Text GLabel 4750 4550 2 51 Output ~ 0
|
||||
p1_b2
|
||||
Text GLabel 4250 3450 0 51 Output ~ 0
|
||||
row_A
|
||||
Text GLabel 4750 3450 2 51 Output ~ 0
|
||||
row_B
|
||||
Text GLabel 4750 3550 2 51 Output ~ 0
|
||||
row_C
|
||||
Text GLabel 4750 3750 2 51 Output ~ 0
|
||||
row_D
|
||||
Text GLabel 4250 3250 0 51 Output ~ 0
|
||||
clock
|
||||
Text GLabel 4250 3850 0 51 Output ~ 0
|
||||
p0_r1
|
||||
Text GLabel 4250 3350 0 51 Output ~ 0
|
||||
p0_g1
|
||||
Text GLabel 4750 3950 2 51 Output ~ 0
|
||||
p0_b1
|
||||
Text GLabel 4750 3850 2 51 Output ~ 0
|
||||
p0_r2
|
||||
Text GLabel 4250 3750 0 51 Output ~ 0
|
||||
p0_g2
|
||||
Text GLabel 4250 3650 0 51 Output ~ 0
|
||||
p0_b2
|
||||
Text GLabel 4750 3250 2 51 Output ~ 0
|
||||
OE
|
||||
Wire Wire Line
|
||||
7200 2500 7750 2500
|
||||
$Comp
|
||||
L GND #PWR07
|
||||
U 1 1 54ECD031
|
||||
P 7750 2950
|
||||
F 0 "#PWR07" H 7750 2950 30 0001 C CNN
|
||||
F 1 "GND" H 7750 2880 30 0001 C CNN
|
||||
F 2 "" H 7750 2950 60 0000 C CNN
|
||||
F 3 "" H 7750 2950 60 0000 C CNN
|
||||
1 7750 2950
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
7200 2900 7750 2900
|
||||
Wire Wire Line
|
||||
7200 2300 7750 2300
|
||||
$Comp
|
||||
L CONN_02X08 Panel-2
|
||||
U 1 1 54ECE201
|
||||
P 6950 3800
|
||||
F 0 "Panel-2" H 6950 4250 50 0000 C CNN
|
||||
F 1 "CONN_02X08" V 6950 3800 50 0000 C CNN
|
||||
F 2 "Pin_Headers:Pin_Header_Straight_2x08" H 6950 2600 60 0001 C CNN
|
||||
F 3 "" H 6950 2600 60 0000 C CNN
|
||||
1 6950 3800
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
7200 3750 7750 3750
|
||||
$Comp
|
||||
L GND #PWR08
|
||||
U 1 1 54ECE20E
|
||||
P 7750 4200
|
||||
F 0 "#PWR08" H 7750 4200 30 0001 C CNN
|
||||
F 1 "GND" H 7750 4130 30 0001 C CNN
|
||||
F 2 "" H 7750 4200 60 0000 C CNN
|
||||
F 3 "" H 7750 4200 60 0000 C CNN
|
||||
1 7750 4200
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
7200 4150 7750 4150
|
||||
Wire Wire Line
|
||||
7200 3550 7750 3550
|
||||
$Comp
|
||||
L VCC #PWR09
|
||||
U 1 1 54ECD3DE
|
||||
P 4800 2700
|
||||
F 0 "#PWR09" H 4800 2800 30 0001 C CNN
|
||||
F 1 "VCC" H 4800 2800 30 0000 C CNN
|
||||
F 2 "" H 4800 2700 60 0000 C CNN
|
||||
F 3 "" H 4800 2700 60 0000 C CNN
|
||||
1 4800 2700
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
Text GLabel 7200 3650 2 51 Input ~ 0
|
||||
p1_g2
|
||||
Wire Wire Line
|
||||
7750 3550 7750 4200
|
||||
Connection ~ 7750 4150
|
||||
Connection ~ 7750 3750
|
||||
Text GLabel 7200 3450 2 51 Input ~ 0
|
||||
p1_g1
|
||||
Wire Wire Line
|
||||
7750 2300 7750 2950
|
||||
Connection ~ 7750 2500
|
||||
Connection ~ 7750 2900
|
||||
Text GLabel 7200 2400 2 51 Input ~ 0
|
||||
p0_g2
|
||||
Text GLabel 7200 2200 2 51 Input ~ 0
|
||||
p0_g1
|
||||
Text GLabel 7200 2700 2 51 Input ~ 0
|
||||
row_D
|
||||
Text GLabel 7200 2600 2 51 Input ~ 0
|
||||
row_B
|
||||
Text GLabel 7200 3850 2 51 Input ~ 0
|
||||
row_B
|
||||
Text GLabel 7200 3950 2 51 Input ~ 0
|
||||
row_D
|
||||
Text GLabel 6700 2200 0 51 Input ~ 0
|
||||
p0_r1
|
||||
Text GLabel 6700 2800 0 51 Input ~ 0
|
||||
clock
|
||||
Text GLabel 6700 2500 0 51 Input ~ 0
|
||||
p0_b2
|
||||
Text GLabel 6700 2300 0 51 Input ~ 0
|
||||
p0_b1
|
||||
Text GLabel 6700 2400 0 51 Input ~ 0
|
||||
p0_r2
|
||||
Text GLabel 6700 2900 0 51 Input ~ 0
|
||||
OE
|
||||
Text GLabel 6700 3450 0 51 Input ~ 0
|
||||
p1_r1
|
||||
Text GLabel 6700 3550 0 51 Input ~ 0
|
||||
p1_b1
|
||||
Text GLabel 6700 3650 0 51 Input ~ 0
|
||||
p1_r2
|
||||
Text GLabel 6700 3750 0 51 Input ~ 0
|
||||
p1_b2
|
||||
Text GLabel 6700 4050 0 51 Input ~ 0
|
||||
clock
|
||||
Text GLabel 6700 4150 0 51 Input ~ 0
|
||||
OE
|
||||
Text GLabel 4750 3050 2 51 Output ~ 0
|
||||
p2_r1
|
||||
Text GLabel 4250 2850 0 51 Output ~ 0
|
||||
p2_g1
|
||||
Text GLabel 4250 2950 0 51 Output ~ 0
|
||||
p2_b1
|
||||
Text GLabel 4250 4550 0 51 Output ~ 0
|
||||
p2_r2
|
||||
Text GLabel 4750 4450 2 51 Output ~ 0
|
||||
p2_g2
|
||||
Text GLabel 4750 4650 2 51 Output ~ 0
|
||||
p2_b2
|
||||
Text GLabel 6700 3850 0 51 Input ~ 0
|
||||
row_A
|
||||
Text GLabel 6700 3950 0 51 Input ~ 0
|
||||
row_C
|
||||
Text GLabel 6700 2600 0 51 Input ~ 0
|
||||
row_A
|
||||
Text GLabel 6700 2700 0 51 Input ~ 0
|
||||
row_C
|
||||
Text GLabel 7200 4050 2 51 Input ~ 0
|
||||
strobe
|
||||
Text GLabel 7200 2800 2 51 Input ~ 0
|
||||
strobe
|
||||
$Comp
|
||||
L CONN_02X08 Panel-3
|
||||
U 1 1 54F3E6D5
|
||||
P 6950 5250
|
||||
F 0 "Panel-3" H 6950 5700 50 0000 C CNN
|
||||
F 1 "CONN_02X08" V 6950 5250 50 0000 C CNN
|
||||
F 2 "Pin_Headers:Pin_Header_Straight_2x08" H 6950 4050 60 0001 C CNN
|
||||
F 3 "" H 6950 4050 60 0000 C CNN
|
||||
1 6950 5250
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
7200 5200 7750 5200
|
||||
$Comp
|
||||
L GND #PWR010
|
||||
U 1 1 54F3E6DC
|
||||
P 7750 5650
|
||||
F 0 "#PWR010" H 7750 5650 30 0001 C CNN
|
||||
F 1 "GND" H 7750 5580 30 0001 C CNN
|
||||
F 2 "" H 7750 5650 60 0000 C CNN
|
||||
F 3 "" H 7750 5650 60 0000 C CNN
|
||||
1 7750 5650
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
7200 5600 7750 5600
|
||||
Wire Wire Line
|
||||
7200 5000 7750 5000
|
||||
Text GLabel 7200 5100 2 51 Input ~ 0
|
||||
p2_g2
|
||||
Wire Wire Line
|
||||
7750 5000 7750 5650
|
||||
Connection ~ 7750 5600
|
||||
Connection ~ 7750 5200
|
||||
Text GLabel 7200 4900 2 51 Input ~ 0
|
||||
p2_g1
|
||||
Text GLabel 7200 5300 2 51 Input ~ 0
|
||||
row_B
|
||||
Text GLabel 7200 5400 2 51 Input ~ 0
|
||||
row_D
|
||||
Text GLabel 6700 4900 0 51 Input ~ 0
|
||||
p2_r1
|
||||
Text GLabel 6700 5000 0 51 Input ~ 0
|
||||
p2_b1
|
||||
Text GLabel 6700 5100 0 51 Input ~ 0
|
||||
p2_r2
|
||||
Text GLabel 6700 5200 0 51 Input ~ 0
|
||||
p2_b2
|
||||
Text GLabel 6700 5500 0 51 Input ~ 0
|
||||
clock
|
||||
Text GLabel 6700 5600 0 51 Input ~ 0
|
||||
OE
|
||||
Text GLabel 6700 5300 0 51 Input ~ 0
|
||||
row_A
|
||||
Text GLabel 6700 5400 0 51 Input ~ 0
|
||||
row_C
|
||||
Text GLabel 7200 5500 2 51 Input ~ 0
|
||||
strobe
|
||||
NoConn ~ 4250 2750
|
||||
NoConn ~ 4250 3150
|
||||
NoConn ~ 4250 3550
|
||||
NoConn ~ 4250 4050
|
||||
NoConn ~ 4750 4050
|
||||
NoConn ~ 4750 4150
|
||||
NoConn ~ 4750 3150
|
||||
$Comp
|
||||
L PWR_FLAG #FLG011
|
||||
U 1 1 557B29FD
|
||||
P 4950 2750
|
||||
F 0 "#FLG011" H 4950 2845 50 0001 C CNN
|
||||
F 1 "PWR_FLAG" H 4950 2930 50 0000 C CNN
|
||||
F 2 "" H 4950 2750 60 0000 C CNN
|
||||
F 3 "" H 4950 2750 60 0000 C CNN
|
||||
1 4950 2750
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L PWR_FLAG #FLG012
|
||||
U 1 1 557B2BFC
|
||||
P 4200 4700
|
||||
F 0 "#FLG012" H 4200 4795 50 0001 C CNN
|
||||
F 1 "PWR_FLAG" H 4200 4880 50 0000 C CNN
|
||||
F 2 "" H 4200 4700 60 0000 C CNN
|
||||
F 3 "" H 4200 4700 60 0000 C CNN
|
||||
1 4200 4700
|
||||
-1 0 0 1
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
4200 4650 4200 4700
|
||||
Connection ~ 4200 4650
|
||||
$EndSCHEMATC
|
||||
3
depends/rpi-rgb-led-matrix/adapter/passive-rpi1/Makefile
Normal file
3
depends/rpi-rgb-led-matrix/adapter/passive-rpi1/Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
include ../kicad-scripts/makefile.inc
|
||||
|
||||
passive-rpi-hub75-adapter-fab.zip:
|
||||
17
depends/rpi-rgb-led-matrix/adapter/passive-rpi1/README.md
Normal file
17
depends/rpi-rgb-led-matrix/adapter/passive-rpi1/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
Adapter PCB to connect to Rasbperry Pi1
|
||||
=======================================
|
||||
|
||||
* Passive board. Simple, but might need to define `--led-slowdown-gpio` if you see
|
||||
glitches.
|
||||
* Supports one panel connected to a 26 pin Raspberry Pi 1. If you have a newer RPi,
|
||||
check out the [Passive 3](../passive-3) or [Active 3](../active-3) adapter.
|
||||
* Open source KiCAD PCB EDA format.
|
||||
* (not very pretty layout, was just lazy and let the auto-router do it).
|
||||
* The FAB files are provided as [passive-rpi-hub75-adapter-fab.zip](./passive-rpi-hub75-adapter-fab.zip)
|
||||
|
||||
This board is [shared on OSH Park][osh-passive-rpi] (not affiliated)
|
||||
|
||||
![Preview][rendering]
|
||||
|
||||
[rendering]: ../../img/passive-rpi1-pcb.png
|
||||
[osh-passive-rpi]: https://oshpark.com/shared_projects/afEA1gNt
|
||||
@@ -0,0 +1,150 @@
|
||||
EESchema-LIBRARY Version 2.3
|
||||
#encoding utf-8
|
||||
#
|
||||
# CONN_02X08
|
||||
#
|
||||
DEF CONN_02X08 P 0 1 Y N 1 F N
|
||||
F0 "P" 0 450 50 H V C CNN
|
||||
F1 "CONN_02X08" 0 0 50 V V C CNN
|
||||
F2 "" 0 -1200 60 H V C CNN
|
||||
F3 "" 0 -1200 60 H V C CNN
|
||||
$FPLIST
|
||||
Pin_Header_Straight_2X08
|
||||
Pin_Header_Angled_2X08
|
||||
Socket_Strip_Straight_2X08
|
||||
Socket_Strip_Angled_2X08
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -100 -345 -50 -355 0 1 0 N
|
||||
S -100 -245 -50 -255 0 1 0 N
|
||||
S -100 -145 -50 -155 0 1 0 N
|
||||
S -100 -45 -50 -55 0 1 0 N
|
||||
S -100 55 -50 45 0 1 0 N
|
||||
S -100 155 -50 145 0 1 0 N
|
||||
S -100 255 -50 245 0 1 0 N
|
||||
S -100 355 -50 345 0 1 0 N
|
||||
S -100 400 100 -400 0 1 0 N
|
||||
S 50 -345 100 -355 0 1 0 N
|
||||
S 50 -245 100 -255 0 1 0 N
|
||||
S 50 -145 100 -155 0 1 0 N
|
||||
S 50 -45 100 -55 0 1 0 N
|
||||
S 50 55 100 45 0 1 0 N
|
||||
S 50 155 100 145 0 1 0 N
|
||||
S 50 255 100 245 0 1 0 N
|
||||
S 50 355 100 345 0 1 0 N
|
||||
X P1 1 -250 350 150 R 50 50 1 1 P
|
||||
X P2 2 250 350 150 L 50 50 1 1 P
|
||||
X P3 3 -250 250 150 R 50 50 1 1 P
|
||||
X P4 4 250 250 150 L 50 50 1 1 P
|
||||
X P5 5 -250 150 150 R 50 50 1 1 P
|
||||
X P6 6 250 150 150 L 50 50 1 1 P
|
||||
X P7 7 -250 50 150 R 50 50 1 1 P
|
||||
X P8 8 250 50 150 L 50 50 1 1 P
|
||||
X P9 9 -250 -50 150 R 50 50 1 1 P
|
||||
X P10 10 250 -50 150 L 50 50 1 1 P
|
||||
X P11 11 -250 -150 150 R 50 50 1 1 P
|
||||
X P12 12 250 -150 150 L 50 50 1 1 P
|
||||
X P13 13 -250 -250 150 R 50 50 1 1 P
|
||||
X P14 14 250 -250 150 L 50 50 1 1 P
|
||||
X P15 15 -250 -350 150 R 50 50 1 1 P
|
||||
X P16 16 250 -350 150 L 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# CONN_02X13
|
||||
#
|
||||
DEF CONN_02X13 P 0 1 Y N 1 F N
|
||||
F0 "P" 0 700 50 H V C CNN
|
||||
F1 "CONN_02X13" 0 0 50 V V C CNN
|
||||
F2 "" 0 -1150 60 H V C CNN
|
||||
F3 "" 0 -1150 60 H V C CNN
|
||||
$FPLIST
|
||||
Pin_Header_Straight_2X13
|
||||
Pin_Header_Angled_2X13
|
||||
Socket_Strip_Straight_2X13
|
||||
Socket_Strip_Angled_2X13
|
||||
$ENDFPLIST
|
||||
DRAW
|
||||
S -100 -595 -50 -605 0 1 0 N
|
||||
S -100 -495 -50 -505 0 1 0 N
|
||||
S -100 -395 -50 -405 0 1 0 N
|
||||
S -100 -295 -50 -305 0 1 0 N
|
||||
S -100 -195 -50 -205 0 1 0 N
|
||||
S -100 -95 -50 -105 0 1 0 N
|
||||
S -100 5 -50 -5 0 1 0 N
|
||||
S -100 105 -50 95 0 1 0 N
|
||||
S -100 205 -50 195 0 1 0 N
|
||||
S -100 305 -50 295 0 1 0 N
|
||||
S -100 405 -50 395 0 1 0 N
|
||||
S -100 505 -50 495 0 1 0 N
|
||||
S -100 605 -50 595 0 1 0 N
|
||||
S -100 650 100 -650 0 1 0 N
|
||||
S 50 -595 100 -605 0 1 0 N
|
||||
S 50 -495 100 -505 0 1 0 N
|
||||
S 50 -395 100 -405 0 1 0 N
|
||||
S 50 -295 100 -305 0 1 0 N
|
||||
S 50 -195 100 -205 0 1 0 N
|
||||
S 50 -95 100 -105 0 1 0 N
|
||||
S 50 5 100 -5 0 1 0 N
|
||||
S 50 105 100 95 0 1 0 N
|
||||
S 50 205 100 195 0 1 0 N
|
||||
S 50 305 100 295 0 1 0 N
|
||||
S 50 405 100 395 0 1 0 N
|
||||
S 50 505 100 495 0 1 0 N
|
||||
S 50 605 100 595 0 1 0 N
|
||||
X P1 1 -250 600 150 R 50 50 1 1 P
|
||||
X P2 2 250 600 150 L 50 50 1 1 P
|
||||
X P3 3 -250 500 150 R 50 50 1 1 P
|
||||
X P4 4 250 500 150 L 50 50 1 1 P
|
||||
X P5 5 -250 400 150 R 50 50 1 1 P
|
||||
X P6 6 250 400 150 L 50 50 1 1 P
|
||||
X P7 7 -250 300 150 R 50 50 1 1 P
|
||||
X P8 8 250 300 150 L 50 50 1 1 P
|
||||
X P9 9 -250 200 150 R 50 50 1 1 P
|
||||
X P10 10 250 200 150 L 50 50 1 1 P
|
||||
X P20 20 250 -300 150 L 50 50 1 1 P
|
||||
X P11 11 -250 100 150 R 50 50 1 1 P
|
||||
X P21 21 -250 -400 150 R 50 50 1 1 P
|
||||
X P12 12 250 100 150 L 50 50 1 1 P
|
||||
X P22 22 250 -400 150 L 50 50 1 1 P
|
||||
X P13 13 -250 0 150 R 50 50 1 1 P
|
||||
X P23 23 -250 -500 150 R 50 50 1 1 P
|
||||
X P14 14 250 0 150 L 50 50 1 1 P
|
||||
X P24 24 250 -500 150 L 50 50 1 1 P
|
||||
X P15 15 -250 -100 150 R 50 50 1 1 P
|
||||
X P25 25 -250 -600 150 R 50 50 1 1 P
|
||||
X P16 16 250 -100 150 L 50 50 1 1 P
|
||||
X P26 26 250 -600 150 L 50 50 1 1 P
|
||||
X P17 17 -250 -200 150 R 50 50 1 1 P
|
||||
X P18 18 250 -200 150 L 50 50 1 1 P
|
||||
X P19 19 -250 -300 150 R 50 50 1 1 P
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# GND
|
||||
#
|
||||
DEF GND #PWR 0 0 Y Y 1 F P
|
||||
F0 "#PWR" 0 -250 50 H I C CNN
|
||||
F1 "GND" 0 -150 50 H V C CNN
|
||||
F2 "" 0 0 60 H V C CNN
|
||||
F3 "" 0 0 60 H V C CNN
|
||||
DRAW
|
||||
P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N
|
||||
X GND 1 0 0 0 D 50 50 1 1 W N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
# PWR_FLAG
|
||||
#
|
||||
DEF PWR_FLAG #FLG 0 0 N N 1 F P
|
||||
F0 "#FLG" 0 95 50 H I C CNN
|
||||
F1 "PWR_FLAG" 0 180 50 H V C CNN
|
||||
F2 "" 0 0 60 H V C CNN
|
||||
F3 "" 0 0 60 H V C CNN
|
||||
DRAW
|
||||
X pwr 1 0 0 0 U 20 20 0 0 w
|
||||
P 6 0 1 0 0 0 0 50 -75 100 0 150 75 100 0 50 N
|
||||
ENDDRAW
|
||||
ENDDEF
|
||||
#
|
||||
#End Library
|
||||
Binary file not shown.
@@ -0,0 +1,591 @@
|
||||
(kicad_pcb (version 4) (host pcbnew "(2015-10-16 BZR 6271, Git e177d75)-product")
|
||||
|
||||
(general
|
||||
(links 19)
|
||||
(no_connects 0)
|
||||
(area 83.657 38.37 122.550001 58.502333)
|
||||
(thickness 1.6)
|
||||
(drawings 9)
|
||||
(tracks 128)
|
||||
(zones 0)
|
||||
(modules 2)
|
||||
(nets 15)
|
||||
)
|
||||
|
||||
(page A4)
|
||||
(layers
|
||||
(0 F.Cu signal)
|
||||
(31 B.Cu signal)
|
||||
(32 B.Adhes user)
|
||||
(33 F.Adhes user)
|
||||
(34 B.Paste user)
|
||||
(35 F.Paste user)
|
||||
(36 B.SilkS user)
|
||||
(37 F.SilkS user)
|
||||
(38 B.Mask user)
|
||||
(39 F.Mask user)
|
||||
(40 Dwgs.User user)
|
||||
(41 Cmts.User user)
|
||||
(42 Eco1.User user)
|
||||
(43 Eco2.User user)
|
||||
(44 Edge.Cuts user)
|
||||
(45 Margin user)
|
||||
(46 B.CrtYd user)
|
||||
(47 F.CrtYd user)
|
||||
(48 B.Fab user)
|
||||
(49 F.Fab user)
|
||||
)
|
||||
|
||||
(setup
|
||||
(last_trace_width 0.254)
|
||||
(trace_clearance 0.254)
|
||||
(zone_clearance 0.508)
|
||||
(zone_45_only no)
|
||||
(trace_min 0.254)
|
||||
(segment_width 0.2)
|
||||
(edge_width 0.1)
|
||||
(via_size 0.889)
|
||||
(via_drill 0.635)
|
||||
(via_min_size 0.889)
|
||||
(via_min_drill 0.508)
|
||||
(uvia_size 0.508)
|
||||
(uvia_drill 0.127)
|
||||
(uvias_allowed no)
|
||||
(uvia_min_size 0.508)
|
||||
(uvia_min_drill 0.127)
|
||||
(pcb_text_width 0.3)
|
||||
(pcb_text_size 1.5 1.5)
|
||||
(mod_edge_width 0.15)
|
||||
(mod_text_size 1 1)
|
||||
(mod_text_width 0.15)
|
||||
(pad_size 4.064 4.064)
|
||||
(pad_drill 3.048)
|
||||
(pad_to_mask_clearance 0)
|
||||
(aux_axis_origin 0 0)
|
||||
(visible_elements FFFFEF7F)
|
||||
(pcbplotparams
|
||||
(layerselection 0x010f0_80000001)
|
||||
(usegerberextensions true)
|
||||
(excludeedgelayer true)
|
||||
(linewidth 0.100000)
|
||||
(plotframeref false)
|
||||
(viasonmask false)
|
||||
(mode 1)
|
||||
(useauxorigin false)
|
||||
(hpglpennumber 1)
|
||||
(hpglpenspeed 20)
|
||||
(hpglpendiameter 15)
|
||||
(hpglpenoverlay 2)
|
||||
(psnegative false)
|
||||
(psa4output false)
|
||||
(plotreference true)
|
||||
(plotvalue true)
|
||||
(plotinvisibletext false)
|
||||
(padsonsilk false)
|
||||
(subtractmaskfromsilk false)
|
||||
(outputformat 1)
|
||||
(mirror false)
|
||||
(drillshape 0)
|
||||
(scaleselection 1)
|
||||
(outputdirectory fab/))
|
||||
)
|
||||
|
||||
(net 0 "")
|
||||
(net 1 GND)
|
||||
(net 2 strobe)
|
||||
(net 3 p0_r1)
|
||||
(net 4 p0_g1)
|
||||
(net 5 OE)
|
||||
(net 6 p0_b1)
|
||||
(net 7 p0_r2)
|
||||
(net 8 p0_g2)
|
||||
(net 9 row_D)
|
||||
(net 10 row_C)
|
||||
(net 11 p0_b2)
|
||||
(net 12 clock)
|
||||
(net 13 row_B)
|
||||
(net 14 row_A)
|
||||
|
||||
(net_class Default "This is the default net class."
|
||||
(clearance 0.254)
|
||||
(trace_width 0.254)
|
||||
(via_dia 0.889)
|
||||
(via_drill 0.635)
|
||||
(uvia_dia 0.508)
|
||||
(uvia_drill 0.127)
|
||||
(add_net OE)
|
||||
(add_net clock)
|
||||
(add_net p0_b1)
|
||||
(add_net p0_b2)
|
||||
(add_net p0_g1)
|
||||
(add_net p0_g2)
|
||||
(add_net p0_r1)
|
||||
(add_net p0_r2)
|
||||
(add_net row_A)
|
||||
(add_net row_B)
|
||||
(add_net row_C)
|
||||
(add_net row_D)
|
||||
(add_net strobe)
|
||||
)
|
||||
|
||||
(net_class power ""
|
||||
(clearance 0.254)
|
||||
(trace_width 0.254)
|
||||
(via_dia 0.889)
|
||||
(via_drill 0.635)
|
||||
(uvia_dia 0.508)
|
||||
(uvia_drill 0.127)
|
||||
(add_net GND)
|
||||
)
|
||||
|
||||
(module Pin_Headers:Pin_Header_Straight_2x08 (layer F.Cu) (tedit 557E1BCB) (tstamp 54F3AB27)
|
||||
(at 95.25 53.34 90)
|
||||
(descr "Through hole pin header")
|
||||
(tags "pin header")
|
||||
(path /54ECB236)
|
||||
(fp_text reference Panel-1 (at 1.27 -2.54 90) (layer F.SilkS) hide
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_text value CONN_02X08 (at 0 -3.1 90) (layer F.SilkS) hide
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_line (start -1.75 -1.75) (end -1.75 19.55) (layer F.CrtYd) (width 0.05))
|
||||
(fp_line (start 4.3 -1.75) (end 4.3 19.55) (layer F.CrtYd) (width 0.05))
|
||||
(fp_line (start -1.75 -1.75) (end 4.3 -1.75) (layer F.CrtYd) (width 0.05))
|
||||
(fp_line (start -1.75 19.55) (end 4.3 19.55) (layer F.CrtYd) (width 0.05))
|
||||
(fp_line (start 3.81 19.05) (end 3.81 -1.27) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start -1.27 1.27) (end -1.27 19.05) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start 3.81 19.05) (end -1.27 19.05) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start 3.81 -1.27) (end 1.27 -1.27) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start 0 -1.55) (end -1.55 -1.55) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start 1.27 -1.27) (end 1.27 1.27) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start 1.27 1.27) (end -1.27 1.27) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start -1.55 -1.55) (end -1.55 0) (layer F.SilkS) (width 0.15))
|
||||
(pad 1 thru_hole rect (at 0 0 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 3 p0_r1))
|
||||
(pad 2 thru_hole oval (at 2.54 0 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 4 p0_g1))
|
||||
(pad 3 thru_hole oval (at 0 2.54 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 6 p0_b1))
|
||||
(pad 4 thru_hole oval (at 2.54 2.54 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 1 GND))
|
||||
(pad 5 thru_hole oval (at 0 5.08 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 7 p0_r2))
|
||||
(pad 6 thru_hole oval (at 2.54 5.08 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 8 p0_g2))
|
||||
(pad 7 thru_hole oval (at 0 7.62 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 11 p0_b2))
|
||||
(pad 8 thru_hole oval (at 2.54 7.62 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 1 GND))
|
||||
(pad 9 thru_hole oval (at 0 10.16 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 14 row_A))
|
||||
(pad 10 thru_hole oval (at 2.54 10.16 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 13 row_B))
|
||||
(pad 11 thru_hole oval (at 0 12.7 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 10 row_C))
|
||||
(pad 12 thru_hole oval (at 2.54 12.7 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 9 row_D))
|
||||
(pad 13 thru_hole oval (at 0 15.24 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 12 clock))
|
||||
(pad 14 thru_hole oval (at 2.54 15.24 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 2 strobe))
|
||||
(pad 15 thru_hole oval (at 0 17.78 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 5 OE))
|
||||
(pad 16 thru_hole oval (at 2.54 17.78 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 1 GND))
|
||||
(model Pin_Headers.3dshapes/Pin_Header_Straight_2x08.wrl
|
||||
(at (xyz 0.05 -0.35 0))
|
||||
(scale (xyz 1 1 1))
|
||||
(rotate (xyz 0 0 90))
|
||||
)
|
||||
)
|
||||
|
||||
(module Pin_Headers:Pin_Header_Straight_2x13 (layer F.Cu) (tedit 557E1BBF) (tstamp 557E12E7)
|
||||
(at 88.9 43.815 90)
|
||||
(descr "Through hole pin header")
|
||||
(tags "pin header")
|
||||
(path /54ECB2B7)
|
||||
(fp_text reference P1 (at -2.413 -0.508 180) (layer F.SilkS)
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_text value RPi-Header (at -0.381 -4.064 90) (layer F.Fab) hide
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
)
|
||||
(fp_line (start -1.75 -1.75) (end -1.75 32.25) (layer F.CrtYd) (width 0.05))
|
||||
(fp_line (start 4.3 -1.75) (end 4.3 32.25) (layer F.CrtYd) (width 0.05))
|
||||
(fp_line (start -1.75 -1.75) (end 4.3 -1.75) (layer F.CrtYd) (width 0.05))
|
||||
(fp_line (start -1.75 32.25) (end 4.3 32.25) (layer F.CrtYd) (width 0.05))
|
||||
(fp_line (start 3.81 -1.27) (end 3.81 31.75) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start -1.27 1.27) (end -1.27 31.75) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start 3.81 31.75) (end -1.27 31.75) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start 3.81 -1.27) (end 1.27 -1.27) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start 0 -1.55) (end -1.55 -1.55) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start 1.27 -1.27) (end 1.27 1.27) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start 1.27 1.27) (end -1.27 1.27) (layer F.SilkS) (width 0.15))
|
||||
(fp_line (start -1.55 -1.55) (end -1.55 0) (layer F.SilkS) (width 0.15))
|
||||
(pad 1 thru_hole rect (at 0 0 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||
(pad 2 thru_hole oval (at 2.54 0 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||
(pad 3 thru_hole oval (at 0 2.54 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||
(pad 4 thru_hole oval (at 2.54 2.54 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||
(pad 5 thru_hole oval (at 0 5.08 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||
(pad 6 thru_hole oval (at 2.54 5.08 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 1 GND))
|
||||
(pad 7 thru_hole oval (at 0 7.62 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 2 strobe))
|
||||
(pad 8 thru_hole oval (at 2.54 7.62 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||
(pad 9 thru_hole oval (at 0 10.16 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||
(pad 10 thru_hole oval (at 2.54 10.16 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||
(pad 11 thru_hole oval (at 0 12.7 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 12 clock))
|
||||
(pad 12 thru_hole oval (at 2.54 12.7 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 5 OE))
|
||||
(pad 13 thru_hole oval (at 0 15.24 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 4 p0_g1))
|
||||
(pad 14 thru_hole oval (at 2.54 15.24 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 1 GND))
|
||||
(pad 15 thru_hole oval (at 0 17.78 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 14 row_A))
|
||||
(pad 16 thru_hole oval (at 2.54 17.78 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 13 row_B))
|
||||
(pad 17 thru_hole oval (at 0 20.32 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||
(pad 18 thru_hole oval (at 2.54 20.32 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 10 row_C))
|
||||
(pad 19 thru_hole oval (at 0 22.86 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 11 p0_b2))
|
||||
(pad 20 thru_hole oval (at 2.54 22.86 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 1 GND))
|
||||
(pad 21 thru_hole oval (at 0 25.4 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 8 p0_g2))
|
||||
(pad 22 thru_hole oval (at 2.54 25.4 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 9 row_D))
|
||||
(pad 23 thru_hole oval (at 0 27.94 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 3 p0_r1))
|
||||
(pad 24 thru_hole oval (at 2.54 27.94 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 7 p0_r2))
|
||||
(pad 25 thru_hole oval (at 0 30.48 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 1 GND))
|
||||
(pad 26 thru_hole oval (at 2.54 30.48 90) (size 1.7272 1.7272) (drill 1.016) (layers *.Cu *.Mask F.SilkS)
|
||||
(net 6 p0_b1))
|
||||
)
|
||||
|
||||
(gr_text %%gitversion%% (at 118.872 47.244) (layer B.SilkS)
|
||||
(effects (font (size 1.2 1.2) (thickness 0.2)) (justify left mirror))
|
||||
)
|
||||
(gr_text "↖RPi corner" (at 90.17 39.37) (layer F.SilkS)
|
||||
(effects (font (size 1 1) (thickness 0.2)))
|
||||
)
|
||||
(gr_text "↑video connector" (at 121.5 47.5 270) (layer F.SilkS)
|
||||
(effects (font (size 1 1) (thickness 0.2)))
|
||||
)
|
||||
(gr_text github.com/hzeller/rpi-rgb-led-matrix (at 104 47.5) (layer F.SilkS)
|
||||
(effects (font (size 1.1 1.1) (thickness 0.2)))
|
||||
)
|
||||
(gr_line (start 102.235 56.642) (end 106.045 56.642) (angle 90) (layer F.SilkS) (width 1.5))
|
||||
(gr_line (start 85.5 57.5) (end 85.5 38.5) (angle 90) (layer Edge.Cuts) (width 0.1) (tstamp 556C01FD))
|
||||
(gr_line (start 85.5 38.5) (end 122.5 38.5) (angle 90) (layer Edge.Cuts) (width 0.1))
|
||||
(gr_line (start 122.5 38.5) (end 122.5 57.5) (angle 90) (layer Edge.Cuts) (width 0.1) (tstamp 556BCFD7))
|
||||
(gr_line (start 122.5 57.5) (end 85.5 57.5) (angle 90) (layer Edge.Cuts) (width 0.1) (tstamp 556BCFD8))
|
||||
|
||||
(segment (start 104.14 41.275) (end 105.3849 41.275) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 112.3295 41.275) (end 111.0595 42.545) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 111.0595 42.545) (end 106.1391 42.545) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 106.1391 42.545) (end 105.3849 41.7908) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 105.3849 41.7908) (end 105.3849 41.275) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 112.3295 41.275) (end 113.0049 41.275) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 111.76 41.275) (end 112.3295 41.275) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 118.6854 43.8997) (end 117.3307 42.545) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 117.3307 42.545) (end 113.7591 42.545) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 113.7591 42.545) (end 113.0049 41.7908) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 113.0049 41.7908) (end 113.0049 41.275) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 118.8105 43.815) (end 118.7258 43.8997) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 118.7258 43.8997) (end 118.6854 43.8997) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 113.03 49.5551) (end 118.6854 43.8997) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 113.03 50.8) (end 113.03 49.5551) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 119.38 43.815) (end 118.8105 43.815) (width 0.254) (layer F.Cu) (net 1))
|
||||
(segment (start 97.79 43.2214) (end 97.79 49.5492) (width 0.254) (layer B.Cu) (net 1))
|
||||
(segment (start 95.2249 41.275) (end 95.2249 41.7419) (width 0.254) (layer B.Cu) (net 1))
|
||||
(segment (start 95.2249 41.7419) (end 96.0531 42.5701) (width 0.254) (layer B.Cu) (net 1))
|
||||
(segment (start 96.0531 42.5701) (end 97.1387 42.5701) (width 0.254) (layer B.Cu) (net 1))
|
||||
(segment (start 97.1387 42.5701) (end 97.79 43.2214) (width 0.254) (layer B.Cu) (net 1))
|
||||
(segment (start 104.14 41.275) (end 102.895 42.52) (width 0.254) (layer B.Cu) (net 1))
|
||||
(segment (start 102.895 42.52) (end 98.4914 42.52) (width 0.254) (layer B.Cu) (net 1))
|
||||
(segment (start 98.4914 42.52) (end 97.79 43.2214) (width 0.254) (layer B.Cu) (net 1))
|
||||
(segment (start 97.79 49.5492) (end 97.79 50.8) (width 0.254) (layer B.Cu) (net 1))
|
||||
(segment (start 97.79 49.5492) (end 100.8698 49.5492) (width 0.254) (layer B.Cu) (net 1))
|
||||
(segment (start 100.8698 49.5492) (end 101.6251 50.3045) (width 0.254) (layer B.Cu) (net 1))
|
||||
(segment (start 101.6251 50.3045) (end 101.6251 50.8) (width 0.254) (layer B.Cu) (net 1))
|
||||
(segment (start 102.87 50.8) (end 101.6251 50.8) (width 0.254) (layer B.Cu) (net 1))
|
||||
(segment (start 93.98 41.275) (end 95.2249 41.275) (width 0.254) (layer B.Cu) (net 1))
|
||||
(segment (start 110.49 50.8) (end 109.2451 50.8) (width 0.254) (layer F.Cu) (net 2))
|
||||
(segment (start 96.52 43.815) (end 96.52 45.0599) (width 0.254) (layer F.Cu) (net 2))
|
||||
(segment (start 96.52 45.0599) (end 93.9931 47.5868) (width 0.254) (layer F.Cu) (net 2))
|
||||
(segment (start 93.9931 47.5868) (end 93.9931 54.4202) (width 0.254) (layer F.Cu) (net 2))
|
||||
(segment (start 93.9931 54.4202) (end 94.1662 54.5933) (width 0.254) (layer F.Cu) (net 2))
|
||||
(segment (start 94.1662 54.5933) (end 100.9179 54.5933) (width 0.254) (layer F.Cu) (net 2))
|
||||
(segment (start 100.9179 54.5933) (end 101.6 53.9112) (width 0.254) (layer F.Cu) (net 2))
|
||||
(segment (start 101.6 53.9112) (end 101.6 52.835) (width 0.254) (layer F.Cu) (net 2))
|
||||
(segment (start 101.6 52.835) (end 102.365 52.07) (width 0.254) (layer F.Cu) (net 2))
|
||||
(segment (start 102.365 52.07) (end 108.4909 52.07) (width 0.254) (layer F.Cu) (net 2))
|
||||
(segment (start 108.4909 52.07) (end 109.2451 51.3158) (width 0.254) (layer F.Cu) (net 2))
|
||||
(segment (start 109.2451 51.3158) (end 109.2451 50.8) (width 0.254) (layer F.Cu) (net 2))
|
||||
(segment (start 95.25 53.34) (end 96.4949 53.34) (width 0.254) (layer F.Cu) (net 3))
|
||||
(segment (start 116.84 43.815) (end 115.5951 43.815) (width 0.254) (layer F.Cu) (net 3))
|
||||
(segment (start 115.5951 43.815) (end 115.5951 44.2818) (width 0.254) (layer F.Cu) (net 3))
|
||||
(segment (start 115.5951 44.2818) (end 111.8058 48.0711) (width 0.254) (layer F.Cu) (net 3))
|
||||
(segment (start 111.8058 48.0711) (end 103.7779 48.0711) (width 0.254) (layer F.Cu) (net 3))
|
||||
(segment (start 103.7779 48.0711) (end 101.6 50.249) (width 0.254) (layer F.Cu) (net 3))
|
||||
(segment (start 101.6 50.249) (end 101.6 51.295) (width 0.254) (layer F.Cu) (net 3))
|
||||
(segment (start 101.6 51.295) (end 100.7999 52.0951) (width 0.254) (layer F.Cu) (net 3))
|
||||
(segment (start 100.7999 52.0951) (end 97.2729 52.0951) (width 0.254) (layer F.Cu) (net 3))
|
||||
(segment (start 97.2729 52.0951) (end 96.4949 52.8731) (width 0.254) (layer F.Cu) (net 3))
|
||||
(segment (start 96.4949 52.8731) (end 96.4949 53.34) (width 0.254) (layer F.Cu) (net 3))
|
||||
(segment (start 95.25 50.8) (end 96.4949 50.8) (width 0.254) (layer F.Cu) (net 4))
|
||||
(segment (start 104.14 43.815) (end 102.8951 43.815) (width 0.254) (layer F.Cu) (net 4))
|
||||
(segment (start 102.8951 43.815) (end 102.8951 44.2819) (width 0.254) (layer F.Cu) (net 4))
|
||||
(segment (start 102.8951 44.2819) (end 102.1171 45.0599) (width 0.254) (layer F.Cu) (net 4))
|
||||
(segment (start 102.1171 45.0599) (end 101.7192 45.0599) (width 0.254) (layer F.Cu) (net 4))
|
||||
(segment (start 101.7192 45.0599) (end 96.4949 50.2842) (width 0.254) (layer F.Cu) (net 4))
|
||||
(segment (start 96.4949 50.2842) (end 96.4949 50.8) (width 0.254) (layer F.Cu) (net 4))
|
||||
(segment (start 113.03 53.34) (end 113.03 52.0951) (width 0.254) (layer B.Cu) (net 5))
|
||||
(segment (start 101.6 41.275) (end 102.8449 41.275) (width 0.254) (layer B.Cu) (net 5))
|
||||
(segment (start 102.8449 41.275) (end 102.8449 40.8082) (width 0.254) (layer B.Cu) (net 5))
|
||||
(segment (start 102.8449 40.8082) (end 104.1729 39.4802) (width 0.254) (layer B.Cu) (net 5))
|
||||
(segment (start 104.1729 39.4802) (end 114.3167 39.4802) (width 0.254) (layer B.Cu) (net 5))
|
||||
(segment (start 114.3167 39.4802) (end 115.57 40.7335) (width 0.254) (layer B.Cu) (net 5))
|
||||
(segment (start 115.57 40.7335) (end 115.57 50.0709) (width 0.254) (layer B.Cu) (net 5))
|
||||
(segment (start 115.57 50.0709) (end 113.5458 52.0951) (width 0.254) (layer B.Cu) (net 5))
|
||||
(segment (start 113.5458 52.0951) (end 113.03 52.0951) (width 0.254) (layer B.Cu) (net 5))
|
||||
(segment (start 97.79 53.34) (end 99.0349 53.34) (width 0.254) (layer B.Cu) (net 6))
|
||||
(segment (start 119.38 41.275) (end 119.38 42.5199) (width 0.254) (layer B.Cu) (net 6))
|
||||
(segment (start 119.38 42.5199) (end 119.8468 42.5199) (width 0.254) (layer B.Cu) (net 6))
|
||||
(segment (start 119.8468 42.5199) (end 120.6524 43.3255) (width 0.254) (layer B.Cu) (net 6))
|
||||
(segment (start 120.6524 43.3255) (end 120.6524 48.1982) (width 0.254) (layer B.Cu) (net 6))
|
||||
(segment (start 120.6524 48.1982) (end 112.6587 56.1919) (width 0.254) (layer B.Cu) (net 6))
|
||||
(segment (start 112.6587 56.1919) (end 101.371 56.1919) (width 0.254) (layer B.Cu) (net 6))
|
||||
(segment (start 101.371 56.1919) (end 99.0349 53.8558) (width 0.254) (layer B.Cu) (net 6))
|
||||
(segment (start 99.0349 53.8558) (end 99.0349 53.34) (width 0.254) (layer B.Cu) (net 6))
|
||||
(segment (start 100.33 53.34) (end 101.5749 53.34) (width 0.254) (layer B.Cu) (net 7))
|
||||
(segment (start 116.84 41.275) (end 116.84 42.5199) (width 0.254) (layer B.Cu) (net 7))
|
||||
(segment (start 116.84 42.5199) (end 117.3068 42.5199) (width 0.254) (layer B.Cu) (net 7))
|
||||
(segment (start 117.3068 42.5199) (end 118.11 43.3231) (width 0.254) (layer B.Cu) (net 7))
|
||||
(segment (start 118.11 43.3231) (end 118.11 50.0216) (width 0.254) (layer B.Cu) (net 7))
|
||||
(segment (start 118.11 50.0216) (end 112.4481 55.6835) (width 0.254) (layer B.Cu) (net 7))
|
||||
(segment (start 112.4481 55.6835) (end 103.4026 55.6835) (width 0.254) (layer B.Cu) (net 7))
|
||||
(segment (start 103.4026 55.6835) (end 101.5749 53.8558) (width 0.254) (layer B.Cu) (net 7))
|
||||
(segment (start 101.5749 53.8558) (end 101.5749 53.34) (width 0.254) (layer B.Cu) (net 7))
|
||||
(segment (start 114.3 43.815) (end 113.0551 43.815) (width 0.254) (layer F.Cu) (net 8))
|
||||
(segment (start 113.0551 43.815) (end 113.0551 44.2819) (width 0.254) (layer F.Cu) (net 8))
|
||||
(segment (start 113.0551 44.2819) (end 112.2771 45.0599) (width 0.254) (layer F.Cu) (net 8))
|
||||
(segment (start 112.2771 45.0599) (end 106.0701 45.0599) (width 0.254) (layer F.Cu) (net 8))
|
||||
(segment (start 106.0701 45.0599) (end 100.33 50.8) (width 0.254) (layer F.Cu) (net 8))
|
||||
(segment (start 114.3 41.275) (end 113.0551 41.275) (width 0.254) (layer B.Cu) (net 9))
|
||||
(segment (start 113.0551 41.275) (end 113.0551 40.8082) (width 0.254) (layer B.Cu) (net 9))
|
||||
(segment (start 113.0551 40.8082) (end 112.2605 40.0136) (width 0.254) (layer B.Cu) (net 9))
|
||||
(segment (start 112.2605 40.0136) (end 108.7063 40.0136) (width 0.254) (layer B.Cu) (net 9))
|
||||
(segment (start 108.7063 40.0136) (end 107.95 40.7699) (width 0.254) (layer B.Cu) (net 9))
|
||||
(segment (start 107.95 40.7699) (end 107.95 50.8) (width 0.254) (layer B.Cu) (net 9))
|
||||
(segment (start 107.95 53.34) (end 107.95 52.0951) (width 0.254) (layer B.Cu) (net 10))
|
||||
(segment (start 109.22 41.275) (end 109.22 42.5199) (width 0.254) (layer B.Cu) (net 10))
|
||||
(segment (start 109.22 42.5199) (end 109.6868 42.5199) (width 0.254) (layer B.Cu) (net 10))
|
||||
(segment (start 109.6868 42.5199) (end 110.49 43.3231) (width 0.254) (layer B.Cu) (net 10))
|
||||
(segment (start 110.49 43.3231) (end 110.49 47.1986) (width 0.254) (layer B.Cu) (net 10))
|
||||
(segment (start 110.49 47.1986) (end 109.22 48.4686) (width 0.254) (layer B.Cu) (net 10))
|
||||
(segment (start 109.22 48.4686) (end 109.22 51.3409) (width 0.254) (layer B.Cu) (net 10))
|
||||
(segment (start 109.22 51.3409) (end 108.4658 52.0951) (width 0.254) (layer B.Cu) (net 10))
|
||||
(segment (start 108.4658 52.0951) (end 107.95 52.0951) (width 0.254) (layer B.Cu) (net 10))
|
||||
(segment (start 111.76 43.815) (end 111.76 53.8323) (width 0.254) (layer B.Cu) (net 11))
|
||||
(segment (start 111.76 53.8323) (end 110.4228 55.1695) (width 0.254) (layer B.Cu) (net 11))
|
||||
(segment (start 110.4228 55.1695) (end 104.6995 55.1695) (width 0.254) (layer B.Cu) (net 11))
|
||||
(segment (start 104.6995 55.1695) (end 102.87 53.34) (width 0.254) (layer B.Cu) (net 11))
|
||||
(segment (start 110.49 53.34) (end 109.2451 53.34) (width 0.254) (layer B.Cu) (net 12))
|
||||
(segment (start 101.6 43.815) (end 101.6 45.0599) (width 0.254) (layer B.Cu) (net 12))
|
||||
(segment (start 101.6 45.0599) (end 104.14 47.5999) (width 0.254) (layer B.Cu) (net 12))
|
||||
(segment (start 104.14 47.5999) (end 104.14 53.8544) (width 0.254) (layer B.Cu) (net 12))
|
||||
(segment (start 104.14 53.8544) (end 104.94 54.6544) (width 0.254) (layer B.Cu) (net 12))
|
||||
(segment (start 104.94 54.6544) (end 108.4465 54.6544) (width 0.254) (layer B.Cu) (net 12))
|
||||
(segment (start 108.4465 54.6544) (end 109.2451 53.8558) (width 0.254) (layer B.Cu) (net 12))
|
||||
(segment (start 109.2451 53.8558) (end 109.2451 53.34) (width 0.254) (layer B.Cu) (net 12))
|
||||
(segment (start 105.41 50.8) (end 105.41 49.5551) (width 0.254) (layer B.Cu) (net 13))
|
||||
(segment (start 105.41 49.5551) (end 105.41 43.3231) (width 0.254) (layer B.Cu) (net 13))
|
||||
(segment (start 105.41 43.3231) (end 106.2132 42.5199) (width 0.254) (layer B.Cu) (net 13))
|
||||
(segment (start 106.2132 42.5199) (end 106.68 42.5199) (width 0.254) (layer B.Cu) (net 13))
|
||||
(segment (start 106.68 41.275) (end 106.68 42.5199) (width 0.254) (layer B.Cu) (net 13))
|
||||
(segment (start 105.41 53.34) (end 105.41 52.0951) (width 0.254) (layer B.Cu) (net 14))
|
||||
(segment (start 106.68 43.815) (end 106.68 51.3409) (width 0.254) (layer B.Cu) (net 14))
|
||||
(segment (start 106.68 51.3409) (end 105.9258 52.0951) (width 0.254) (layer B.Cu) (net 14))
|
||||
(segment (start 105.9258 52.0951) (end 105.41 52.0951) (width 0.254) (layer B.Cu) (net 14))
|
||||
|
||||
(zone (net 1) (net_name GND) (layer F.Cu) (tstamp 557E155F) (hatch edge 0.508)
|
||||
(connect_pads (clearance 0.508))
|
||||
(min_thickness 0.254)
|
||||
(fill yes (arc_segments 16) (thermal_gap 0.508) (thermal_bridge_width 0.508))
|
||||
(polygon
|
||||
(pts
|
||||
(xy 122.5 57.5) (xy 85.5 57.5) (xy 85.5 38.5) (xy 122.5 38.5)
|
||||
)
|
||||
)
|
||||
(filled_polygon
|
||||
(pts
|
||||
(xy 121.815 56.815) (xy 86.185 56.815) (xy 86.185 39.747041) (xy 88.9 39.747041) (xy 88.326511 39.861115)
|
||||
(xy 87.84033 40.185971) (xy 87.515474 40.672152) (xy 87.4014 41.245641) (xy 87.4014 41.304359) (xy 87.515474 41.877848)
|
||||
(xy 87.827301 42.34453) (xy 87.794277 42.350937) (xy 87.581473 42.490727) (xy 87.439023 42.70176) (xy 87.38896 42.9514)
|
||||
(xy 87.38896 44.6786) (xy 87.435937 44.920723) (xy 87.575727 45.133527) (xy 87.78676 45.275977) (xy 88.0364 45.32604)
|
||||
(xy 89.7636 45.32604) (xy 90.005723 45.279063) (xy 90.218527 45.139273) (xy 90.360977 44.92824) (xy 90.369179 44.88734)
|
||||
(xy 90.38033 44.904029) (xy 90.866511 45.228885) (xy 91.44 45.342959) (xy 92.013489 45.228885) (xy 92.49967 44.904029)
|
||||
(xy 92.71 44.589248) (xy 92.92033 44.904029) (xy 93.406511 45.228885) (xy 93.98 45.342959) (xy 94.553489 45.228885)
|
||||
(xy 95.03967 44.904029) (xy 95.25 44.589248) (xy 95.46033 44.904029) (xy 95.543001 44.959268) (xy 93.454285 47.047985)
|
||||
(xy 93.289104 47.295195) (xy 93.2311 47.5868) (xy 93.2311 54.4202) (xy 93.289104 54.711805) (xy 93.404766 54.884905)
|
||||
(xy 93.454285 54.959015) (xy 93.627384 55.132115) (xy 93.702342 55.1822) (xy 93.874595 55.297296) (xy 94.1662 55.3553)
|
||||
(xy 100.9179 55.3553) (xy 101.209505 55.297296) (xy 101.456715 55.132115) (xy 102.019822 54.569008) (xy 102.296511 54.753885)
|
||||
(xy 102.87 54.867959) (xy 103.443489 54.753885) (xy 103.92967 54.429029) (xy 104.14 54.114248) (xy 104.35033 54.429029)
|
||||
(xy 104.836511 54.753885) (xy 105.41 54.867959) (xy 105.983489 54.753885) (xy 106.46967 54.429029) (xy 106.68 54.114248)
|
||||
(xy 106.89033 54.429029) (xy 107.376511 54.753885) (xy 107.95 54.867959) (xy 108.523489 54.753885) (xy 109.00967 54.429029)
|
||||
(xy 109.22 54.114248) (xy 109.43033 54.429029) (xy 109.916511 54.753885) (xy 110.49 54.867959) (xy 111.063489 54.753885)
|
||||
(xy 111.54967 54.429029) (xy 111.76 54.114248) (xy 111.97033 54.429029) (xy 112.456511 54.753885) (xy 113.03 54.867959)
|
||||
(xy 113.603489 54.753885) (xy 114.08967 54.429029) (xy 114.414526 53.942848) (xy 114.5286 53.369359) (xy 114.5286 53.310641)
|
||||
(xy 114.414526 52.737152) (xy 114.08967 52.250971) (xy 113.818839 52.070008) (xy 114.236821 51.68849) (xy 114.484968 51.159027)
|
||||
(xy 114.364469 50.927) (xy 113.157 50.927) (xy 113.157 50.947) (xy 112.903 50.947) (xy 112.903 50.927)
|
||||
(xy 112.883 50.927) (xy 112.883 50.673) (xy 112.903 50.673) (xy 112.903 49.466183) (xy 112.670974 49.345042)
|
||||
(xy 113.389026 49.345042) (xy 113.157 49.466183) (xy 113.157 50.673) (xy 114.364469 50.673) (xy 114.484968 50.440973)
|
||||
(xy 114.236821 49.91151) (xy 113.804947 49.517312) (xy 113.389026 49.345042) (xy 112.670974 49.345042) (xy 112.255053 49.517312)
|
||||
(xy 111.823179 49.91151) (xy 111.765664 50.034228) (xy 111.54967 49.710971) (xy 111.063489 49.386115) (xy 110.49 49.272041)
|
||||
(xy 109.916511 49.386115) (xy 109.43033 49.710971) (xy 109.22 50.025752) (xy 109.00967 49.710971) (xy 108.523489 49.386115)
|
||||
(xy 107.95 49.272041) (xy 107.376511 49.386115) (xy 106.89033 49.710971) (xy 106.68 50.025752) (xy 106.46967 49.710971)
|
||||
(xy 105.983489 49.386115) (xy 105.41 49.272041) (xy 104.836511 49.386115) (xy 104.35033 49.710971) (xy 104.134336 50.034228)
|
||||
(xy 104.076821 49.91151) (xy 103.644947 49.517312) (xy 103.47833 49.448301) (xy 104.093531 48.8331) (xy 111.8058 48.8331)
|
||||
(xy 112.097405 48.775096) (xy 112.344615 48.609915) (xy 115.942286 45.012245) (xy 116.266511 45.228885) (xy 116.84 45.342959)
|
||||
(xy 117.413489 45.228885) (xy 117.89967 44.904029) (xy 118.115664 44.580772) (xy 118.173179 44.70349) (xy 118.605053 45.097688)
|
||||
(xy 119.020974 45.269958) (xy 119.253 45.148817) (xy 119.253 43.942) (xy 119.507 43.942) (xy 119.507 45.148817)
|
||||
(xy 119.739026 45.269958) (xy 120.154947 45.097688) (xy 120.586821 44.70349) (xy 120.834968 44.174027) (xy 120.714469 43.942)
|
||||
(xy 119.507 43.942) (xy 119.253 43.942) (xy 119.233 43.942) (xy 119.233 43.688) (xy 119.253 43.688)
|
||||
(xy 119.253 43.668) (xy 119.507 43.668) (xy 119.507 43.688) (xy 120.714469 43.688) (xy 120.834968 43.455973)
|
||||
(xy 120.586821 42.92651) (xy 120.168839 42.544992) (xy 120.43967 42.364029) (xy 120.764526 41.877848) (xy 120.8786 41.304359)
|
||||
(xy 120.8786 41.245641) (xy 120.764526 40.672152) (xy 120.43967 40.185971) (xy 119.953489 39.861115) (xy 119.38 39.747041)
|
||||
(xy 118.806511 39.861115) (xy 118.32033 40.185971) (xy 118.11 40.500752) (xy 117.89967 40.185971) (xy 117.413489 39.861115)
|
||||
(xy 116.84 39.747041) (xy 116.266511 39.861115) (xy 115.78033 40.185971) (xy 115.57 40.500752) (xy 115.35967 40.185971)
|
||||
(xy 114.873489 39.861115) (xy 114.3 39.747041) (xy 113.726511 39.861115) (xy 113.24033 40.185971) (xy 113.024336 40.509228)
|
||||
(xy 112.966821 40.38651) (xy 112.534947 39.992312) (xy 112.119026 39.820042) (xy 111.887 39.941183) (xy 111.887 41.148)
|
||||
(xy 111.907 41.148) (xy 111.907 41.402) (xy 111.887 41.402) (xy 111.887 41.422) (xy 111.633 41.422)
|
||||
(xy 111.633 41.402) (xy 111.613 41.402) (xy 111.613 41.148) (xy 111.633 41.148) (xy 111.633 39.941183)
|
||||
(xy 111.400974 39.820042) (xy 110.985053 39.992312) (xy 110.553179 40.38651) (xy 110.495664 40.509228) (xy 110.27967 40.185971)
|
||||
(xy 109.793489 39.861115) (xy 109.22 39.747041) (xy 108.646511 39.861115) (xy 108.16033 40.185971) (xy 107.95 40.500752)
|
||||
(xy 107.73967 40.185971) (xy 107.253489 39.861115) (xy 106.68 39.747041) (xy 106.106511 39.861115) (xy 105.62033 40.185971)
|
||||
(xy 105.404336 40.509228) (xy 105.346821 40.38651) (xy 104.914947 39.992312) (xy 104.499026 39.820042) (xy 104.267 39.941183)
|
||||
(xy 104.267 41.148) (xy 104.287 41.148) (xy 104.287 41.402) (xy 104.267 41.402) (xy 104.267 41.422)
|
||||
(xy 104.013 41.422) (xy 104.013 41.402) (xy 103.993 41.402) (xy 103.993 41.148) (xy 104.013 41.148)
|
||||
(xy 104.013 39.941183) (xy 103.780974 39.820042) (xy 103.365053 39.992312) (xy 102.933179 40.38651) (xy 102.875664 40.509228)
|
||||
(xy 102.65967 40.185971) (xy 102.173489 39.861115) (xy 101.6 39.747041) (xy 101.026511 39.861115) (xy 100.54033 40.185971)
|
||||
(xy 100.33 40.500752) (xy 100.11967 40.185971) (xy 99.633489 39.861115) (xy 99.06 39.747041) (xy 98.486511 39.861115)
|
||||
(xy 98.00033 40.185971) (xy 97.79 40.500752) (xy 97.57967 40.185971) (xy 97.093489 39.861115) (xy 96.52 39.747041)
|
||||
(xy 95.946511 39.861115) (xy 95.46033 40.185971) (xy 95.244336 40.509228) (xy 95.186821 40.38651) (xy 94.754947 39.992312)
|
||||
(xy 94.339026 39.820042) (xy 94.107 39.941183) (xy 94.107 41.148) (xy 94.127 41.148) (xy 94.127 41.402)
|
||||
(xy 94.107 41.402) (xy 94.107 41.422) (xy 93.853 41.422) (xy 93.853 41.402) (xy 93.833 41.402)
|
||||
(xy 93.833 41.148) (xy 93.853 41.148) (xy 93.853 39.941183) (xy 93.620974 39.820042) (xy 93.205053 39.992312)
|
||||
(xy 92.773179 40.38651) (xy 92.715664 40.509228) (xy 92.49967 40.185971) (xy 92.013489 39.861115) (xy 91.44 39.747041)
|
||||
(xy 90.866511 39.861115) (xy 90.38033 40.185971) (xy 90.17 40.500752) (xy 89.95967 40.185971) (xy 89.473489 39.861115)
|
||||
(xy 88.9 39.747041) (xy 86.185 39.747041) (xy 86.185 39.185) (xy 121.815 39.185) (xy 121.815 56.815)
|
||||
)
|
||||
)
|
||||
(filled_polygon
|
||||
(pts
|
||||
(xy 102.997 50.673) (xy 103.017 50.673) (xy 103.017 50.927) (xy 102.997 50.927) (xy 102.997 50.947)
|
||||
(xy 102.743 50.947) (xy 102.743 50.927) (xy 102.723 50.927) (xy 102.723 50.673) (xy 102.743 50.673)
|
||||
(xy 102.743 50.653) (xy 102.997 50.653) (xy 102.997 50.673)
|
||||
)
|
||||
)
|
||||
(filled_polygon
|
||||
(pts
|
||||
(xy 97.917 50.673) (xy 97.937 50.673) (xy 97.937 50.927) (xy 97.917 50.927) (xy 97.917 50.947)
|
||||
(xy 97.663 50.947) (xy 97.663 50.927) (xy 97.643 50.927) (xy 97.643 50.673) (xy 97.663 50.673)
|
||||
(xy 97.663 50.653) (xy 97.917 50.653) (xy 97.917 50.673)
|
||||
)
|
||||
)
|
||||
)
|
||||
(zone (net 1) (net_name GND) (layer B.Cu) (tstamp 557E1560) (hatch edge 0.508)
|
||||
(connect_pads (clearance 0.508))
|
||||
(min_thickness 0.254)
|
||||
(fill yes (arc_segments 16) (thermal_gap 0.508) (thermal_bridge_width 0.508))
|
||||
(polygon
|
||||
(pts
|
||||
(xy 122.5 57.5) (xy 85.5 57.5) (xy 85.5 38.5) (xy 122.5 38.5)
|
||||
)
|
||||
)
|
||||
(filled_polygon
|
||||
(pts
|
||||
(xy 102.497714 40.077756) (xy 102.173489 39.861115) (xy 101.6 39.747041) (xy 101.026511 39.861115) (xy 100.54033 40.185971)
|
||||
(xy 100.33 40.500752) (xy 100.11967 40.185971) (xy 99.633489 39.861115) (xy 99.06 39.747041) (xy 98.486511 39.861115)
|
||||
(xy 98.00033 40.185971) (xy 97.79 40.500752) (xy 97.57967 40.185971) (xy 97.093489 39.861115) (xy 96.52 39.747041)
|
||||
(xy 95.946511 39.861115) (xy 95.46033 40.185971) (xy 95.244336 40.509228) (xy 95.186821 40.38651) (xy 94.754947 39.992312)
|
||||
(xy 94.339026 39.820042) (xy 94.107 39.941183) (xy 94.107 41.148) (xy 94.127 41.148) (xy 94.127 41.402)
|
||||
(xy 94.107 41.402) (xy 94.107 41.422) (xy 93.853 41.422) (xy 93.853 41.402) (xy 93.833 41.402)
|
||||
(xy 93.833 41.148) (xy 93.853 41.148) (xy 93.853 39.941183) (xy 93.620974 39.820042) (xy 93.205053 39.992312)
|
||||
(xy 92.773179 40.38651) (xy 92.715664 40.509228) (xy 92.49967 40.185971) (xy 92.013489 39.861115) (xy 91.44 39.747041)
|
||||
(xy 90.866511 39.861115) (xy 90.38033 40.185971) (xy 90.17 40.500752) (xy 89.95967 40.185971) (xy 89.473489 39.861115)
|
||||
(xy 88.9 39.747041) (xy 88.326511 39.861115) (xy 87.84033 40.185971) (xy 87.515474 40.672152) (xy 87.4014 41.245641)
|
||||
(xy 87.4014 41.304359) (xy 87.515474 41.877848) (xy 87.827301 42.34453) (xy 87.794277 42.350937) (xy 87.581473 42.490727)
|
||||
(xy 87.439023 42.70176) (xy 87.38896 42.9514) (xy 87.38896 44.6786) (xy 87.435937 44.920723) (xy 87.575727 45.133527)
|
||||
(xy 87.78676 45.275977) (xy 88.0364 45.32604) (xy 89.7636 45.32604) (xy 90.005723 45.279063) (xy 90.218527 45.139273)
|
||||
(xy 90.360977 44.92824) (xy 90.369179 44.88734) (xy 90.38033 44.904029) (xy 90.866511 45.228885) (xy 91.44 45.342959)
|
||||
(xy 92.013489 45.228885) (xy 92.49967 44.904029) (xy 92.71 44.589248) (xy 92.92033 44.904029) (xy 93.406511 45.228885)
|
||||
(xy 93.98 45.342959) (xy 94.553489 45.228885) (xy 95.03967 44.904029) (xy 95.25 44.589248) (xy 95.46033 44.904029)
|
||||
(xy 95.946511 45.228885) (xy 96.52 45.342959) (xy 97.093489 45.228885) (xy 97.57967 44.904029) (xy 97.79 44.589248)
|
||||
(xy 98.00033 44.904029) (xy 98.486511 45.228885) (xy 99.06 45.342959) (xy 99.633489 45.228885) (xy 100.11967 44.904029)
|
||||
(xy 100.33 44.589248) (xy 100.54033 44.904029) (xy 100.84787 45.109521) (xy 100.896004 45.351505) (xy 101.061185 45.598715)
|
||||
(xy 103.378 47.915531) (xy 103.378 49.406745) (xy 103.229026 49.345042) (xy 102.997 49.466183) (xy 102.997 50.673)
|
||||
(xy 103.017 50.673) (xy 103.017 50.927) (xy 102.997 50.927) (xy 102.997 50.947) (xy 102.743 50.947)
|
||||
(xy 102.743 50.927) (xy 102.723 50.927) (xy 102.723 50.673) (xy 102.743 50.673) (xy 102.743 49.466183)
|
||||
(xy 102.510974 49.345042) (xy 102.095053 49.517312) (xy 101.663179 49.91151) (xy 101.605664 50.034228) (xy 101.38967 49.710971)
|
||||
(xy 100.903489 49.386115) (xy 100.33 49.272041) (xy 99.756511 49.386115) (xy 99.27033 49.710971) (xy 99.054336 50.034228)
|
||||
(xy 98.996821 49.91151) (xy 98.564947 49.517312) (xy 98.149026 49.345042) (xy 97.917 49.466183) (xy 97.917 50.673)
|
||||
(xy 97.937 50.673) (xy 97.937 50.927) (xy 97.917 50.927) (xy 97.917 50.947) (xy 97.663 50.947)
|
||||
(xy 97.663 50.927) (xy 97.643 50.927) (xy 97.643 50.673) (xy 97.663 50.673) (xy 97.663 49.466183)
|
||||
(xy 97.430974 49.345042) (xy 97.015053 49.517312) (xy 96.583179 49.91151) (xy 96.525664 50.034228) (xy 96.30967 49.710971)
|
||||
(xy 95.823489 49.386115) (xy 95.25 49.272041) (xy 94.676511 49.386115) (xy 94.19033 49.710971) (xy 93.865474 50.197152)
|
||||
(xy 93.7514 50.770641) (xy 93.7514 50.829359) (xy 93.865474 51.402848) (xy 94.177301 51.86953) (xy 94.144277 51.875937)
|
||||
(xy 93.931473 52.015727) (xy 93.789023 52.22676) (xy 93.73896 52.4764) (xy 93.73896 54.2036) (xy 93.785937 54.445723)
|
||||
(xy 93.925727 54.658527) (xy 94.13676 54.800977) (xy 94.3864 54.85104) (xy 96.1136 54.85104) (xy 96.355723 54.804063)
|
||||
(xy 96.568527 54.664273) (xy 96.710977 54.45324) (xy 96.719179 54.41234) (xy 96.73033 54.429029) (xy 97.216511 54.753885)
|
||||
(xy 97.79 54.867959) (xy 98.363489 54.753885) (xy 98.658341 54.556871) (xy 100.832184 56.730715) (xy 100.958326 56.815)
|
||||
(xy 86.185 56.815) (xy 86.185 39.185) (xy 103.390469 39.185) (xy 102.497714 40.077756)
|
||||
)
|
||||
)
|
||||
(filled_polygon
|
||||
(pts
|
||||
(xy 113.24033 44.904029) (xy 113.726511 45.228885) (xy 114.3 45.342959) (xy 114.808 45.241912) (xy 114.808 49.75527)
|
||||
(xy 114.369234 50.194036) (xy 114.236821 49.91151) (xy 113.804947 49.517312) (xy 113.389026 49.345042) (xy 113.157 49.466183)
|
||||
(xy 113.157 50.673) (xy 113.177 50.673) (xy 113.177 50.927) (xy 113.157 50.927) (xy 113.157 50.947)
|
||||
(xy 112.903 50.947) (xy 112.903 50.927) (xy 112.883 50.927) (xy 112.883 50.673) (xy 112.903 50.673)
|
||||
(xy 112.903 49.466183) (xy 112.670974 49.345042) (xy 112.522 49.406745) (xy 112.522 45.102926) (xy 112.81967 44.904029)
|
||||
(xy 113.03 44.589248) (xy 113.24033 44.904029)
|
||||
)
|
||||
)
|
||||
(filled_polygon
|
||||
(pts
|
||||
(xy 119.507 43.688) (xy 119.527 43.688) (xy 119.527 43.942) (xy 119.507 43.942) (xy 119.507 45.148817)
|
||||
(xy 119.739026 45.269958) (xy 119.8904 45.207261) (xy 119.8904 47.88257) (xy 118.872 48.90097) (xy 118.872 45.208255)
|
||||
(xy 119.020974 45.269958) (xy 119.253 45.148817) (xy 119.253 43.942) (xy 119.233 43.942) (xy 119.233 43.688)
|
||||
(xy 119.253 43.688) (xy 119.253 43.668) (xy 119.507 43.668) (xy 119.507 43.688)
|
||||
)
|
||||
)
|
||||
(filled_polygon
|
||||
(pts
|
||||
(xy 102.933179 42.16349) (xy 103.351161 42.545008) (xy 103.08033 42.725971) (xy 102.87 43.040752) (xy 102.65967 42.725971)
|
||||
(xy 102.388828 42.545) (xy 102.65967 42.364029) (xy 102.875664 42.040772) (xy 102.933179 42.16349)
|
||||
)
|
||||
)
|
||||
(filled_polygon
|
||||
(pts
|
||||
(xy 111.887 41.148) (xy 111.907 41.148) (xy 111.907 41.402) (xy 111.887 41.402) (xy 111.887 41.422)
|
||||
(xy 111.633 41.422) (xy 111.633 41.402) (xy 111.613 41.402) (xy 111.613 41.148) (xy 111.633 41.148)
|
||||
(xy 111.633 41.128) (xy 111.887 41.128) (xy 111.887 41.148)
|
||||
)
|
||||
)
|
||||
(filled_polygon
|
||||
(pts
|
||||
(xy 104.267 41.148) (xy 104.287 41.148) (xy 104.287 41.402) (xy 104.267 41.402) (xy 104.267 41.422)
|
||||
(xy 104.013 41.422) (xy 104.013 41.402) (xy 103.993 41.402) (xy 103.993 41.148) (xy 104.013 41.148)
|
||||
(xy 104.013 41.128) (xy 104.267 41.128) (xy 104.267 41.148)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,62 @@
|
||||
update=Sun 14 Jun 2015 04:45:24 PM PDT
|
||||
version=1
|
||||
last_client=kicad
|
||||
[cvpcb]
|
||||
version=1
|
||||
NetIExt=net
|
||||
[cvpcb/libraries]
|
||||
EquName1=devcms
|
||||
[general]
|
||||
version=1
|
||||
[eeschema]
|
||||
version=1
|
||||
LibDir=
|
||||
[eeschema/libraries]
|
||||
LibName1=power
|
||||
LibName2=device
|
||||
LibName3=transistors
|
||||
LibName4=conn
|
||||
LibName5=linear
|
||||
LibName6=regul
|
||||
LibName7=74xx
|
||||
LibName8=cmos4000
|
||||
LibName9=adc-dac
|
||||
LibName10=memory
|
||||
LibName11=xilinx
|
||||
LibName12=microcontrollers
|
||||
LibName13=dsp
|
||||
LibName14=microchip
|
||||
LibName15=analog_switches
|
||||
LibName16=motorola
|
||||
LibName17=texas
|
||||
LibName18=intel
|
||||
LibName19=audio
|
||||
LibName20=interface
|
||||
LibName21=digital-audio
|
||||
LibName22=philips
|
||||
LibName23=display
|
||||
LibName24=cypress
|
||||
LibName25=siliconi
|
||||
LibName26=opto
|
||||
LibName27=atmel
|
||||
LibName28=contrib
|
||||
LibName29=valves
|
||||
[pcbnew]
|
||||
version=1
|
||||
PageLayoutDescrFile=
|
||||
LastNetListRead=
|
||||
PadDrill=3.048
|
||||
PadDrillOvalY=3.048
|
||||
PadSizeH=4.064
|
||||
PadSizeV=4.064
|
||||
PcbTextSizeV=1.5
|
||||
PcbTextSizeH=1.5
|
||||
PcbTextThickness=0.3
|
||||
ModuleTextSizeV=1
|
||||
ModuleTextSizeH=1
|
||||
ModuleTextSizeThickness=0.15
|
||||
SolderMaskClearance=0
|
||||
SolderMaskMinWidth=0
|
||||
DrawSegmentWidth=0.2
|
||||
BoardOutlineThickness=0.09999999999999999
|
||||
ModuleOutlineThickness=0.15
|
||||
@@ -0,0 +1,215 @@
|
||||
EESchema Schematic File Version 2
|
||||
LIBS:power
|
||||
LIBS:device
|
||||
LIBS:transistors
|
||||
LIBS:conn
|
||||
LIBS:linear
|
||||
LIBS:regul
|
||||
LIBS:74xx
|
||||
LIBS:cmos4000
|
||||
LIBS:adc-dac
|
||||
LIBS:memory
|
||||
LIBS:xilinx
|
||||
LIBS:microcontrollers
|
||||
LIBS:dsp
|
||||
LIBS:microchip
|
||||
LIBS:analog_switches
|
||||
LIBS:motorola
|
||||
LIBS:texas
|
||||
LIBS:intel
|
||||
LIBS:audio
|
||||
LIBS:interface
|
||||
LIBS:digital-audio
|
||||
LIBS:philips
|
||||
LIBS:display
|
||||
LIBS:cypress
|
||||
LIBS:siliconi
|
||||
LIBS:opto
|
||||
LIBS:atmel
|
||||
LIBS:contrib
|
||||
LIBS:valves
|
||||
EELAYER 25 0
|
||||
EELAYER END
|
||||
$Descr A4 11693 8268
|
||||
encoding utf-8
|
||||
Sheet 1 1
|
||||
Title ""
|
||||
Date ""
|
||||
Rev ""
|
||||
Comp ""
|
||||
Comment1 ""
|
||||
Comment2 ""
|
||||
Comment3 ""
|
||||
Comment4 ""
|
||||
$EndDescr
|
||||
$Comp
|
||||
L CONN_02X08 Panel-1
|
||||
U 1 1 54ECB236
|
||||
P 6000 3450
|
||||
F 0 "Panel-1" H 6000 3900 50 0000 C CNN
|
||||
F 1 "CONN_02X08" V 6000 3450 50 0000 C CNN
|
||||
F 2 "Pin_Headers:Pin_Header_Straight_2x08" H 6000 2250 60 0001 C CNN
|
||||
F 3 "" H 6000 2250 60 0000 C CNN
|
||||
1 6000 3450
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L CONN_02X13 P1
|
||||
U 1 1 54ECB2B7
|
||||
P 4500 3350
|
||||
F 0 "P1" H 4500 4100 50 0000 C CNN
|
||||
F 1 "RPi-Header" V 4500 3350 50 0000 C CNN
|
||||
F 2 "Pin_Headers:Pin_Header_Straight_2x13" H 4500 2400 60 0001 C CNN
|
||||
F 3 "" H 4500 2400 60 0000 C CNN
|
||||
1 4500 3350
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L GND #PWR01
|
||||
U 1 1 54ECB3E1
|
||||
P 4850 3350
|
||||
F 0 "#PWR01" H 4850 3350 30 0001 C CNN
|
||||
F 1 "GND" H 4850 3280 30 0001 C CNN
|
||||
F 2 "" H 4850 3350 60 0000 C CNN
|
||||
F 3 "" H 4850 3350 60 0000 C CNN
|
||||
1 4850 3350
|
||||
0 -1 -1 0
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
4750 3350 4850 3350
|
||||
$Comp
|
||||
L GND #PWR02
|
||||
U 1 1 54ECB417
|
||||
P 4850 3650
|
||||
F 0 "#PWR02" H 4850 3650 30 0001 C CNN
|
||||
F 1 "GND" H 4850 3580 30 0001 C CNN
|
||||
F 2 "" H 4850 3650 60 0000 C CNN
|
||||
F 3 "" H 4850 3650 60 0000 C CNN
|
||||
1 4850 3650
|
||||
0 -1 -1 0
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
4750 3650 4850 3650
|
||||
$Comp
|
||||
L GND #PWR03
|
||||
U 1 1 54ECB4A1
|
||||
P 4850 2950
|
||||
F 0 "#PWR03" H 4850 2950 30 0001 C CNN
|
||||
F 1 "GND" H 4850 2880 30 0001 C CNN
|
||||
F 2 "" H 4850 2950 60 0000 C CNN
|
||||
F 3 "" H 4850 2950 60 0000 C CNN
|
||||
1 4850 2950
|
||||
0 -1 -1 0
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
4750 2950 4850 2950
|
||||
$Comp
|
||||
L GND #PWR04
|
||||
U 1 1 54ECB7BC
|
||||
P 4150 3950
|
||||
F 0 "#PWR04" H 4150 3950 30 0001 C CNN
|
||||
F 1 "GND" H 4150 3880 30 0001 C CNN
|
||||
F 2 "" H 4150 3950 60 0000 C CNN
|
||||
F 3 "" H 4150 3950 60 0000 C CNN
|
||||
1 4150 3950
|
||||
0 1 1 0
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
4150 3950 4250 3950
|
||||
Text GLabel 4250 3050 0 51 Output ~ 0
|
||||
strobe
|
||||
Text GLabel 4250 3450 0 51 Output ~ 0
|
||||
row_A
|
||||
Text GLabel 4750 3450 2 51 Output ~ 0
|
||||
row_B
|
||||
Text GLabel 4750 3550 2 51 Output ~ 0
|
||||
row_C
|
||||
Text GLabel 4750 3750 2 51 Output ~ 0
|
||||
row_D
|
||||
Text GLabel 4250 3250 0 51 Output ~ 0
|
||||
clock
|
||||
Text GLabel 4250 3850 0 51 Output ~ 0
|
||||
p0_r1
|
||||
Text GLabel 4250 3350 0 51 Output ~ 0
|
||||
p0_g1
|
||||
Text GLabel 4750 3950 2 51 Output ~ 0
|
||||
p0_b1
|
||||
Text GLabel 4750 3850 2 51 Output ~ 0
|
||||
p0_r2
|
||||
Text GLabel 4250 3750 0 51 Output ~ 0
|
||||
p0_g2
|
||||
Text GLabel 4250 3650 0 51 Output ~ 0
|
||||
p0_b2
|
||||
Text GLabel 4750 3250 2 51 Output ~ 0
|
||||
OE
|
||||
Wire Wire Line
|
||||
6250 3400 6800 3400
|
||||
$Comp
|
||||
L GND #PWR05
|
||||
U 1 1 54ECD031
|
||||
P 6800 3850
|
||||
F 0 "#PWR05" H 6800 3850 30 0001 C CNN
|
||||
F 1 "GND" H 6800 3780 30 0001 C CNN
|
||||
F 2 "" H 6800 3850 60 0000 C CNN
|
||||
F 3 "" H 6800 3850 60 0000 C CNN
|
||||
1 6800 3850
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
6250 3800 6800 3800
|
||||
Wire Wire Line
|
||||
6250 3200 6800 3200
|
||||
Wire Wire Line
|
||||
6800 3200 6800 3850
|
||||
Connection ~ 6800 3400
|
||||
Connection ~ 6800 3800
|
||||
Text GLabel 6250 3300 2 51 Input ~ 0
|
||||
p0_g2
|
||||
Text GLabel 6250 3100 2 51 Input ~ 0
|
||||
p0_g1
|
||||
Text GLabel 6250 3600 2 51 Input ~ 0
|
||||
row_D
|
||||
Text GLabel 6250 3500 2 51 Input ~ 0
|
||||
row_B
|
||||
Text GLabel 5750 3100 0 51 Input ~ 0
|
||||
p0_r1
|
||||
Text GLabel 5750 3700 0 51 Input ~ 0
|
||||
clock
|
||||
Text GLabel 5750 3400 0 51 Input ~ 0
|
||||
p0_b2
|
||||
Text GLabel 5750 3200 0 51 Input ~ 0
|
||||
p0_b1
|
||||
Text GLabel 5750 3300 0 51 Input ~ 0
|
||||
p0_r2
|
||||
Text GLabel 5750 3800 0 51 Input ~ 0
|
||||
OE
|
||||
Text GLabel 5750 3500 0 51 Input ~ 0
|
||||
row_A
|
||||
Text GLabel 5750 3600 0 51 Input ~ 0
|
||||
row_C
|
||||
Text GLabel 6250 3700 2 51 Input ~ 0
|
||||
strobe
|
||||
NoConn ~ 4250 2750
|
||||
NoConn ~ 4250 3150
|
||||
NoConn ~ 4250 3550
|
||||
NoConn ~ 4750 3150
|
||||
NoConn ~ 4750 2750
|
||||
NoConn ~ 4750 2850
|
||||
NoConn ~ 4250 2850
|
||||
NoConn ~ 4250 2950
|
||||
NoConn ~ 4750 3050
|
||||
$Comp
|
||||
L PWR_FLAG #FLG06
|
||||
U 1 1 557E1359
|
||||
P 4200 4050
|
||||
F 0 "#FLG06" H 4200 4145 50 0001 C CNN
|
||||
F 1 "PWR_FLAG" H 4200 4230 50 0000 C CNN
|
||||
F 2 "" H 4200 4050 60 0000 C CNN
|
||||
F 3 "" H 4200 4050 60 0000 C CNN
|
||||
1 4200 4050
|
||||
-1 0 0 1
|
||||
$EndComp
|
||||
Wire Wire Line
|
||||
4200 3950 4200 4050
|
||||
Connection ~ 4200 3950
|
||||
$EndSCHEMATC
|
||||
3
depends/rpi-rgb-led-matrix/bindings/README.md
Normal file
3
depends/rpi-rgb-led-matrix/bindings/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
Various bindings to other programming languages.
|
||||
Typically these are wrapping the [C-binding](../include/led-matrix-c.h) that
|
||||
comes with rpi-rgb-led-matrix
|
||||
5
depends/rpi-rgb-led-matrix/bindings/c#/.gitignore
vendored
Normal file
5
depends/rpi-rgb-led-matrix/bindings/c#/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
**/.vs
|
||||
**/bin
|
||||
**/obj
|
||||
**/*.sln
|
||||
**/*.csproj.user
|
||||
85
depends/rpi-rgb-led-matrix/bindings/c#/Bindings.cs
Normal file
85
depends/rpi-rgb-led-matrix/bindings/c#/Bindings.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
global using static RPiRgbLEDMatrix.Bindings;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace RPiRgbLEDMatrix;
|
||||
|
||||
/*
|
||||
Some of the extern methods listed below are marked with [SuppressGCTransition].
|
||||
This disables some GC checks that may take a long time. But such methods should
|
||||
be fast and trivial, otherwise the managed code may become unstable (see docs).
|
||||
Keep this in mind when changing the C/C++ side.
|
||||
|
||||
https://learn.microsoft.com/dotnet/api/system.runtime.interopservices.suppressgctransitionattribute
|
||||
*/
|
||||
internal static class Bindings
|
||||
{
|
||||
private const string Lib = "librgbmatrix.so.1";
|
||||
|
||||
[DllImport(Lib)]
|
||||
public static extern IntPtr led_matrix_create(int rows, int chained, int parallel);
|
||||
|
||||
[DllImport(Lib, CharSet = CharSet.Ansi)]
|
||||
public static extern IntPtr led_matrix_create_from_options_const_argv(
|
||||
ref InternalRGBLedMatrixOptions options,
|
||||
int argc,
|
||||
string[] argv);
|
||||
|
||||
[DllImport(Lib)]
|
||||
public static extern void led_matrix_delete(IntPtr matrix);
|
||||
|
||||
[DllImport(Lib)]
|
||||
public static extern IntPtr led_matrix_create_offscreen_canvas(IntPtr matrix);
|
||||
|
||||
[DllImport(Lib)]
|
||||
public static extern IntPtr led_matrix_swap_on_vsync(IntPtr matrix, IntPtr canvas);
|
||||
|
||||
[DllImport(Lib)]
|
||||
public static extern IntPtr led_matrix_get_canvas(IntPtr matrix);
|
||||
|
||||
[DllImport(Lib)]
|
||||
[SuppressGCTransition]
|
||||
public static extern byte led_matrix_get_brightness(IntPtr matrix);
|
||||
|
||||
[DllImport(Lib)]
|
||||
[SuppressGCTransition]
|
||||
public static extern void led_matrix_set_brightness(IntPtr matrix, byte brightness);
|
||||
|
||||
[DllImport(Lib, CharSet = CharSet.Ansi)]
|
||||
public static extern IntPtr load_font(string bdf_font_file);
|
||||
|
||||
[DllImport(Lib, CharSet = CharSet.Ansi)]
|
||||
public static extern int draw_text(IntPtr canvas, IntPtr font, int x, int y, byte r, byte g, byte b,
|
||||
string utf8_text, int extra_spacing);
|
||||
|
||||
[DllImport(Lib, CharSet = CharSet.Ansi)]
|
||||
public static extern int vertical_draw_text(IntPtr canvas, IntPtr font, int x, int y, byte r, byte g, byte b,
|
||||
string utf8_text, int kerning_offset);
|
||||
|
||||
[DllImport(Lib, CharSet = CharSet.Ansi)]
|
||||
public static extern void delete_font(IntPtr font);
|
||||
|
||||
[DllImport(Lib)]
|
||||
[SuppressGCTransition]
|
||||
public static extern void led_canvas_get_size(IntPtr canvas, out int width, out int height);
|
||||
|
||||
[DllImport(Lib)]
|
||||
[SuppressGCTransition]
|
||||
public static extern void led_canvas_set_pixel(IntPtr canvas, int x, int y, byte r, byte g, byte b);
|
||||
|
||||
[DllImport(Lib)]
|
||||
public static extern void led_canvas_set_pixels(IntPtr canvas, int x, int y, int width, int height,
|
||||
ref Color colors);
|
||||
|
||||
[DllImport(Lib)]
|
||||
public static extern void led_canvas_clear(IntPtr canvas);
|
||||
|
||||
[DllImport(Lib)]
|
||||
public static extern void led_canvas_fill(IntPtr canvas, byte r, byte g, byte b);
|
||||
|
||||
[DllImport(Lib)]
|
||||
public static extern void draw_circle(IntPtr canvas, int xx, int y, int radius, byte r, byte g, byte b);
|
||||
|
||||
[DllImport(Lib)]
|
||||
public static extern void draw_line(IntPtr canvas, int x0, int y0, int x1, int y1, byte r, byte g, byte b);
|
||||
}
|
||||
38
depends/rpi-rgb-led-matrix/bindings/c#/Color.cs
Normal file
38
depends/rpi-rgb-led-matrix/bindings/c#/Color.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
namespace RPiRgbLEDMatrix;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an RGB (red, green, blue) color
|
||||
/// </summary>
|
||||
public struct Color
|
||||
{
|
||||
/// <summary>
|
||||
/// The red component value of this instance.
|
||||
/// </summary>
|
||||
public byte R;
|
||||
|
||||
/// <summary>
|
||||
/// The green component value of this instance.
|
||||
/// </summary>
|
||||
public byte G;
|
||||
|
||||
/// <summary>
|
||||
/// The blue component value of this instance.
|
||||
/// </summary>
|
||||
public byte B;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new color from the specified color values (red, green, and blue).
|
||||
/// </summary>
|
||||
/// <param name="r">The red component value.</param>
|
||||
/// <param name="g">The green component value.</param>
|
||||
/// <param name="b">The blue component value.</param>
|
||||
public Color(int r, int g, int b) : this((byte)r, (byte)g, (byte)b) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new color from the specified color values (red, green, and blue).
|
||||
/// </summary>
|
||||
/// <param name="r">The red component value.</param>
|
||||
/// <param name="g">The green component value.</param>
|
||||
/// <param name="b">The blue component value.</param>
|
||||
public Color(byte r, byte g, byte b) => (R, G, B) = (r, g, b);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace RPiRgbLEDMatrix;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
internal struct InternalRGBLedMatrixOptions
|
||||
{
|
||||
public IntPtr hardware_mapping;
|
||||
public int rows;
|
||||
public int cols;
|
||||
public int chain_length;
|
||||
public int parallel;
|
||||
public int pwm_bits;
|
||||
public int pwm_lsb_nanoseconds;
|
||||
public int pwm_dither_bits;
|
||||
public int brightness;
|
||||
public int scan_mode;
|
||||
public int row_address_type;
|
||||
public int multiplexing;
|
||||
public IntPtr led_rgb_sequence;
|
||||
public IntPtr pixel_mapper_config;
|
||||
public IntPtr panel_type;
|
||||
public byte disable_hardware_pulsing;
|
||||
public byte show_refresh_rate;
|
||||
public byte inverse_colors;
|
||||
public int limit_refresh_rate_hz;
|
||||
|
||||
public InternalRGBLedMatrixOptions(RGBLedMatrixOptions opt)
|
||||
{
|
||||
chain_length = opt.ChainLength;
|
||||
rows = opt.Rows;
|
||||
cols = opt.Cols;
|
||||
hardware_mapping = Marshal.StringToHGlobalAnsi(opt.HardwareMapping);
|
||||
inverse_colors = (byte)(opt.InverseColors ? 1 : 0);
|
||||
led_rgb_sequence = Marshal.StringToHGlobalAnsi(opt.LedRgbSequence);
|
||||
pixel_mapper_config = Marshal.StringToHGlobalAnsi(opt.PixelMapperConfig);
|
||||
panel_type = Marshal.StringToHGlobalAnsi(opt.PanelType);
|
||||
parallel = opt.Parallel;
|
||||
multiplexing = (int)opt.Multiplexing;
|
||||
pwm_bits = opt.PwmBits;
|
||||
pwm_lsb_nanoseconds = opt.PwmLsbNanoseconds;
|
||||
pwm_dither_bits = opt.PwmDitherBits;
|
||||
scan_mode = (int)opt.ScanMode;
|
||||
show_refresh_rate = (byte)(opt.ShowRefreshRate ? 1 : 0);
|
||||
limit_refresh_rate_hz = opt.LimitRefreshRateHz;
|
||||
brightness = opt.Brightness;
|
||||
disable_hardware_pulsing = (byte)(opt.DisableHardwarePulsing ? 1 : 0);
|
||||
row_address_type = opt.RowAddressType;
|
||||
}
|
||||
};
|
||||
34
depends/rpi-rgb-led-matrix/bindings/c#/Makefile
Normal file
34
depends/rpi-rgb-led-matrix/bindings/c#/Makefile
Normal file
@@ -0,0 +1,34 @@
|
||||
# This Makefile is intended to be used only by the toplevel Makefile.
|
||||
# For any other purposes, use .NET SDK build tools directly
|
||||
|
||||
# Don't forget to synchronize these variables with the 'RPiRgbLEDMatrix.csproj' file
|
||||
RGB_LIBDIR=../../lib
|
||||
RGB_LIBRARY_NAME=rgbmatrix
|
||||
RGB_LIBRARY=$(RGB_LIBDIR)/lib$(RGB_LIBRARY_NAME).so.1
|
||||
|
||||
NUGET_VERSION = 1.0.0
|
||||
NUGET_ID = HZeller.RPiRgbLEDMatrix
|
||||
NUGET_CONFIG = Release
|
||||
|
||||
NUGET_PACKAGE = /bin/$(NUGET_CONFIG)/$(NUGET_ID).$(NUGET_VERSION).nupkg
|
||||
|
||||
$(NUGET_PACKAGE): $(RGB_LIBRARY)
|
||||
dotnet pack -c $(NUGET_CONFIG) -p:SkipNative=false -p:PackageId=$(NUGET_ID) -p:Version=$(NUGET_VERSION)
|
||||
|
||||
# The examples also depend on the 'RPiRgbLEDMatrix.csproj', but this will be handled by 'dotnet'
|
||||
build: $(RGB_LIBRARY)
|
||||
dotnet build examples/FontExample/FontExample.csproj -p:SkipNative=false
|
||||
dotnet build examples/MatrixRain/MatrixRain.csproj -p:SkipNative=false
|
||||
dotnet build examples/MinimalExample/MinimalExample.csproj -p:SkipNative=false
|
||||
dotnet build examples/PulsingBrightness/PulsingBrightness.csproj -p:SkipNative=false
|
||||
dotnet build examples/Rotating3DCube/Rotating3DCube.csproj -p:SkipNative=false
|
||||
dotnet build examples/PlayGIF/PlayGIF.csproj -p:SkipNative=false
|
||||
|
||||
$(RGB_LIBRARY):
|
||||
$(MAKE) -C $(RGB_LIBDIR)
|
||||
|
||||
# Used by toplevel Makefile
|
||||
nuget: $(NUGET_PACKAGE)
|
||||
|
||||
# Used in 'RPiRgbLEDMatrix.csproj'
|
||||
library: $(RGB_LIBRARY)
|
||||
11
depends/rpi-rgb-led-matrix/bindings/c#/Multiplexing.cs
Normal file
11
depends/rpi-rgb-led-matrix/bindings/c#/Multiplexing.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace RPiRgbLEDMatrix;
|
||||
|
||||
/// <summary>
|
||||
/// Type of multiplexing.
|
||||
/// </summary>
|
||||
public enum Multiplexing : int
|
||||
{
|
||||
Direct = 0,
|
||||
Stripe = 1,
|
||||
Checker = 2
|
||||
}
|
||||
16
depends/rpi-rgb-led-matrix/bindings/c#/README.md
Normal file
16
depends/rpi-rgb-led-matrix/bindings/c#/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
C# bindings for RGB Matrix library
|
||||
======================================
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
To build the C# wrapper for the RGB Matrix C library you need to first have __.NET SDK__ installed.
|
||||
|
||||
### Install .NET SDK
|
||||
|
||||
`sudo apt install dotnet6` should work in most cases.
|
||||
For some old distributions, read [docs](https://learn.microsoft.com/dotnet/core/install/linux)
|
||||
|
||||
Then, in the `bindings/c#` directory type: `dotnet build`
|
||||
|
||||
To run the example applications in the c#\examples\EXAMPLE folder: `sudo dotnet run`
|
||||
100
depends/rpi-rgb-led-matrix/bindings/c#/RGBLedCanvas.cs
Normal file
100
depends/rpi-rgb-led-matrix/bindings/c#/RGBLedCanvas.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
namespace RPiRgbLEDMatrix;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a canvas whose pixels can be manipulated.
|
||||
/// </summary>
|
||||
public class RGBLedCanvas
|
||||
{
|
||||
// This is a wrapper for canvas no need to implement IDisposable here
|
||||
// because RGBLedMatrix has ownership and takes care of disposing canvases
|
||||
internal IntPtr _canvas;
|
||||
|
||||
// this is not called directly by the consumer code,
|
||||
// consumer uses factory methods in RGBLedMatrix
|
||||
internal RGBLedCanvas(IntPtr canvas)
|
||||
{
|
||||
_canvas = canvas;
|
||||
led_canvas_get_size(_canvas, out var width, out var height);
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The width of the canvas in pixels.
|
||||
/// </summary>
|
||||
public int Width { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The height of the canvas in pixels.
|
||||
/// </summary>
|
||||
public int Height { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the color of a specific pixel.
|
||||
/// </summary>
|
||||
/// <param name="x">The X coordinate of the pixel.</param>
|
||||
/// <param name="y">The Y coordinate of the pixel.</param>
|
||||
/// <param name="color">New pixel color.</param>
|
||||
public void SetPixel(int x, int y, Color color) => led_canvas_set_pixel(_canvas, x, y, color.R, color.G, color.B);
|
||||
|
||||
/// <summary>
|
||||
/// Copies the colors from the specified buffer to a rectangle on the canvas.
|
||||
/// </summary>
|
||||
/// <param name="x">The X coordinate of the top-left pixel of the rectangle.</param>
|
||||
/// <param name="y">The Y coordinate of the top-left pixel of the rectangle.</param>
|
||||
/// <param name="width">Width of the rectangle.</param>
|
||||
/// <param name="height">Height of the rectangle.</param>
|
||||
/// <param name="colors">Buffer containing the colors to copy.</param>
|
||||
public void SetPixels(int x, int y, int width, int height, Span<Color> colors)
|
||||
{
|
||||
if (colors.Length < width * height)
|
||||
throw new ArgumentOutOfRangeException(nameof(colors));
|
||||
led_canvas_set_pixels(_canvas, x, y, width, height, ref colors[0]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the color of the entire canvas.
|
||||
/// </summary>
|
||||
/// <param name="color">New canvas color.</param>
|
||||
public void Fill(Color color) => led_canvas_fill(_canvas, color.R, color.G, color.B);
|
||||
|
||||
/// <summary>
|
||||
/// Cleans the entire canvas.
|
||||
/// </summary>
|
||||
public void Clear() => led_canvas_clear(_canvas);
|
||||
|
||||
/// <summary>
|
||||
/// Draws a circle of the specified color.
|
||||
/// </summary>
|
||||
/// <param name="x">The X coordinate of the center.</param>
|
||||
/// <param name="y">The Y coordinate of the center.</param>
|
||||
/// <param name="radius">The radius of the circle, in pixels.</param>
|
||||
/// <param name="color">The color of the circle.</param>
|
||||
public void DrawCircle(int x, int y, int radius, Color color) =>
|
||||
draw_circle(_canvas, x, y, radius, color.R, color.G, color.B);
|
||||
|
||||
/// <summary>
|
||||
/// Draws a line of the specified color.
|
||||
/// </summary>
|
||||
/// <param name="x0">The X coordinate of the first point.</param>
|
||||
/// <param name="y0">The Y coordinate of the first point.</param>
|
||||
/// <param name="x1">The X coordinate of the second point.</param>
|
||||
/// <param name="y1">The Y coordinate of the second point.</param>
|
||||
/// <param name="color">The color of the line.</param>
|
||||
public void DrawLine(int x0, int y0, int x1, int y1, Color color) =>
|
||||
draw_line(_canvas, x0, y0, x1, y1, color.R, color.G, color.B);
|
||||
|
||||
/// <summary>
|
||||
/// Draws the text with the specified color.
|
||||
/// </summary>
|
||||
/// <param name="font">Font to draw text with.</param>
|
||||
/// <param name="x">The X coordinate of the starting point.</param>
|
||||
/// <param name="y">The Y coordinate of the starting point.</param>
|
||||
/// <param name="color">The color of the text.</param>
|
||||
/// <param name="text">Text to draw.</param>
|
||||
/// <param name="spacing">Additional spacing between characters.</param>
|
||||
/// <param name="vertical">Whether to draw the text vertically.</param>
|
||||
/// <returns>How many pixels was advanced on the screen.</returns>
|
||||
public int DrawText(RGBLedFont font, int x, int y, Color color, string text, int spacing = 0, bool vertical = false) =>
|
||||
font.DrawText(_canvas, x, y, color, text, spacing, vertical);
|
||||
}
|
||||
40
depends/rpi-rgb-led-matrix/bindings/c#/RGBLedFont.cs
Normal file
40
depends/rpi-rgb-led-matrix/bindings/c#/RGBLedFont.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
namespace RPiRgbLEDMatrix;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a <c>.BDF</c> font.
|
||||
/// </summary>
|
||||
public class RGBLedFont : IDisposable
|
||||
{
|
||||
internal IntPtr _font;
|
||||
private bool disposedValue = false;
|
||||
|
||||
/// <summary>
|
||||
/// Loads the BDF font from the specified file.
|
||||
/// </summary>
|
||||
/// <param name="bdfFontPath">The path to the BDF file to load.</param>
|
||||
public RGBLedFont(string bdfFontPath) => _font = load_font(bdfFontPath);
|
||||
|
||||
internal int DrawText(IntPtr canvas, int x, int y, Color color, string text, int spacing = 0, bool vertical = false)
|
||||
{
|
||||
if (!vertical)
|
||||
return draw_text(canvas, _font, x, y, color.R, color.G, color.B, text, spacing);
|
||||
else
|
||||
return vertical_draw_text(canvas, _font, x, y, color.R, color.G, color.B, text, spacing);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposedValue) return;
|
||||
delete_font(_font);
|
||||
disposedValue = true;
|
||||
}
|
||||
|
||||
~RGBLedFont() => Dispose(false);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
112
depends/rpi-rgb-led-matrix/bindings/c#/RGBLedMatrix.cs
Normal file
112
depends/rpi-rgb-led-matrix/bindings/c#/RGBLedMatrix.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System.Buffers;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace RPiRgbLEDMatrix;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a RGB matrix.
|
||||
/// </summary>
|
||||
public class RGBLedMatrix : IDisposable
|
||||
{
|
||||
private IntPtr matrix;
|
||||
private bool disposedValue = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new matrix.
|
||||
/// </summary>
|
||||
/// <param name="rows">Size of a single module. Can be 32, 16 or 8.</param>
|
||||
/// <param name="chained">How many modules are connected in a chain.</param>
|
||||
/// <param name="parallel">How many modules are connected in a parallel.</param>
|
||||
public RGBLedMatrix(int rows, int chained, int parallel)
|
||||
{
|
||||
matrix = led_matrix_create(rows, chained, parallel);
|
||||
if (matrix == (IntPtr)0)
|
||||
throw new ArgumentException("Could not initialize a new matrix");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new matrix.
|
||||
/// </summary>
|
||||
/// <param name="options">A configuration of a matrix.</param>
|
||||
public RGBLedMatrix(RGBLedMatrixOptions options)
|
||||
{
|
||||
InternalRGBLedMatrixOptions opt = default;
|
||||
try
|
||||
{
|
||||
opt = new(options);
|
||||
var args = Environment.GetCommandLineArgs();
|
||||
|
||||
// Because gpio-slowdown is not provided in the options struct,
|
||||
// we manually add it.
|
||||
// Let's add it first to the command-line we pass to the
|
||||
// matrix constructor, so that it can be overridden with the
|
||||
// users' commandline.
|
||||
// As always, as the _very_ first, we need to provide the
|
||||
// program name argv[0].
|
||||
var argv = new string[args.Length + 1];
|
||||
argv[0] = args[0];
|
||||
argv[1] = $"--led-slowdown-gpio={options.GpioSlowdown}";
|
||||
Array.Copy(args, 1, argv, 2, args.Length - 1);
|
||||
|
||||
matrix = led_matrix_create_from_options_const_argv(ref opt, argv.Length, argv);
|
||||
if (matrix == (IntPtr)0)
|
||||
throw new ArgumentException("Could not initialize a new matrix");
|
||||
}
|
||||
finally
|
||||
{
|
||||
if(options.HardwareMapping is not null) Marshal.FreeHGlobal(opt.hardware_mapping);
|
||||
if(options.LedRgbSequence is not null) Marshal.FreeHGlobal(opt.led_rgb_sequence);
|
||||
if(options.PixelMapperConfig is not null) Marshal.FreeHGlobal(opt.pixel_mapper_config);
|
||||
if(options.PanelType is not null) Marshal.FreeHGlobal(opt.panel_type);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new backbuffer canvas for drawing on.
|
||||
/// </summary>
|
||||
/// <returns>An instance of <see cref="RGBLedCanvas"/> representing the canvas.</returns>
|
||||
public RGBLedCanvas CreateOffscreenCanvas() => new(led_matrix_create_offscreen_canvas(matrix));
|
||||
|
||||
/// <summary>
|
||||
/// Returns a canvas representing the current frame buffer.
|
||||
/// </summary>
|
||||
/// <returns>An instance of <see cref="RGBLedCanvas"/> representing the canvas.</returns>
|
||||
/// <remarks>Consider using <see cref="CreateOffscreenCanvas"/> instead.</remarks>
|
||||
public RGBLedCanvas GetCanvas() => new(led_matrix_get_canvas(matrix));
|
||||
|
||||
/// <summary>
|
||||
/// Swaps this canvas with the currently active canvas. The active canvas
|
||||
/// becomes a backbuffer and is mapped to <paramref name="canvas"/> instance.
|
||||
/// <br/>
|
||||
/// This operation guarantees vertical synchronization.
|
||||
/// </summary>
|
||||
/// <param name="canvas">Backbuffer canvas to swap.</param>
|
||||
public void SwapOnVsync(RGBLedCanvas canvas) =>
|
||||
canvas._canvas = led_matrix_swap_on_vsync(matrix, canvas._canvas);
|
||||
|
||||
/// <summary>
|
||||
/// The general brightness of the matrix.
|
||||
/// </summary>
|
||||
public byte Brightness
|
||||
{
|
||||
get => led_matrix_get_brightness(matrix);
|
||||
set => led_matrix_set_brightness(matrix, value);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposedValue) return;
|
||||
|
||||
led_matrix_delete(matrix);
|
||||
disposedValue = true;
|
||||
}
|
||||
|
||||
~RGBLedMatrix() => Dispose(false);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
124
depends/rpi-rgb-led-matrix/bindings/c#/RGBLedMatrixOptions.cs
Normal file
124
depends/rpi-rgb-led-matrix/bindings/c#/RGBLedMatrixOptions.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
namespace RPiRgbLEDMatrix;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the matrix settings.
|
||||
/// </summary>
|
||||
public struct RGBLedMatrixOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the hardware mapping used. If passed
|
||||
/// <see langword="null"/> here, the default is used.
|
||||
/// </summary>
|
||||
public string? HardwareMapping = null;
|
||||
|
||||
/// <summary>
|
||||
/// The "rows" are the number of rows supported by the display, so 32 or 16.
|
||||
/// Default: 32.
|
||||
/// </summary>
|
||||
public int Rows = 32;
|
||||
|
||||
/// <summary>
|
||||
/// The "cols" are the number of columns per panel. Typically something
|
||||
/// like 32, but also 64 is possible. Sometimes even 40.
|
||||
/// <c>cols * chain_length</c> is the total length of the display, so you can
|
||||
/// represent a 64 wide display as cols=32, chain=2 or cols=64, chain=1;
|
||||
/// same thing, but more convenient to think of.
|
||||
/// </summary>
|
||||
public int Cols = 32;
|
||||
|
||||
/// <summary>
|
||||
/// The chain_length is the number of displays daisy-chained together
|
||||
/// (output of one connected to input of next). Default: 1
|
||||
/// </summary>
|
||||
public int ChainLength = 1;
|
||||
|
||||
/// <summary>
|
||||
/// The number of parallel chains connected to the Pi; in old Pis with 26
|
||||
/// GPIO pins, that is 1, in newer Pis with 40 interfaces pins, that can also
|
||||
/// be 2 or 3. The effective number of pixels in vertical direction is then
|
||||
/// thus <c>rows * parallel</c>. Default: 1
|
||||
/// </summary>
|
||||
public int Parallel = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Set PWM bits used for output. Default is 11, but if you only deal with limited
|
||||
/// comic-colors, 1 might be sufficient. Lower require less CPU and increases refresh-rate.
|
||||
/// </summary>
|
||||
public int PwmBits = 11;
|
||||
|
||||
/// <summary>
|
||||
/// Change the base time-unit for the on-time in the lowest significant bit in
|
||||
/// nanoseconds. Higher numbers provide better quality (more accurate color, less
|
||||
/// ghosting), but have a negative impact on the frame rate.
|
||||
/// </summary>
|
||||
public int PwmLsbNanoseconds = 130;
|
||||
|
||||
/// <summary>
|
||||
/// The lower bits can be time-dithered for higher refresh rate.
|
||||
/// </summary>
|
||||
public int PwmDitherBits = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The initial brightness of the panel in percent. Valid range is 1..100
|
||||
/// </summary>
|
||||
public int Brightness = 100;
|
||||
|
||||
/// <summary>
|
||||
/// Scan mode.
|
||||
/// </summary>
|
||||
public ScanModes ScanMode = ScanModes.Progressive;
|
||||
|
||||
/// <summary>
|
||||
/// Default row address type is 0, corresponding to direct setting of the
|
||||
/// row, while row address type 1 is used for panels that only have A/B,
|
||||
/// typically some 64x64 panels
|
||||
/// </summary>
|
||||
public int RowAddressType = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Type of multiplexing.
|
||||
/// </summary>
|
||||
public Multiplexing Multiplexing = Multiplexing.Direct;
|
||||
|
||||
/// <summary>
|
||||
/// In case the internal sequence of mapping is not <c>"RGB"</c>, this
|
||||
/// contains the real mapping. Some panels mix up these colors.
|
||||
/// </summary>
|
||||
public string? LedRgbSequence = null;
|
||||
|
||||
/// <summary>
|
||||
/// A string describing a sequence of pixel mappers that should be applied
|
||||
/// to this matrix. A semicolon-separated list of pixel-mappers with optional
|
||||
/// parameter.
|
||||
public string? PixelMapperConfig = null;
|
||||
|
||||
/// <summary>
|
||||
/// Panel type. Typically just empty, but certain panels (FM6126)
|
||||
/// requie an initialization sequence
|
||||
/// </summary>
|
||||
public string? PanelType = null;
|
||||
|
||||
/// <summary>
|
||||
/// Allow to use the hardware subsystem to create pulses. This won't do
|
||||
/// anything if output enable is not connected to GPIO 18.
|
||||
/// </summary>
|
||||
public bool DisableHardwarePulsing = false;
|
||||
public bool ShowRefreshRate = false;
|
||||
public bool InverseColors = false;
|
||||
|
||||
/// <summary>
|
||||
/// Limit refresh rate of LED panel. This will help on a loaded system
|
||||
/// to keep a constant refresh rate. <= 0 for no limit.
|
||||
/// </summary>
|
||||
public int LimitRefreshRateHz = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Slowdown GPIO. Needed for faster Pis/slower panels.
|
||||
/// </summary>
|
||||
public int GpioSlowdown = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Creates default matrix settings.
|
||||
/// </summary>
|
||||
public RGBLedMatrixOptions() { }
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Skip builing native libraries by default on Windows -->
|
||||
<PropertyGroup Condition="$(SkipNative) == '' and $(OS) != 'Unix'">
|
||||
<SkipNative>true</SkipNative>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="examples\**" />
|
||||
<None Remove="examples\**" />
|
||||
<None Condition="$(SkipNative) != 'true'" Pack="true"
|
||||
Include="..\..\lib\librgbmatrix.so.1"
|
||||
PackagePath="\runtimes\linux-arm64\native" >
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CompileNative" BeforeTargets="Compile" Condition="$(SkipNative) != 'true'">
|
||||
<Message Text="Building native libraries" />
|
||||
<Exec Command="make library" />
|
||||
</Target>
|
||||
</Project>
|
||||
10
depends/rpi-rgb-led-matrix/bindings/c#/ScanModes.cs
Normal file
10
depends/rpi-rgb-led-matrix/bindings/c#/ScanModes.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace RPiRgbLEDMatrix;
|
||||
|
||||
/// <summary>
|
||||
/// Scan modes.
|
||||
/// </summary>
|
||||
public enum ScanModes
|
||||
{
|
||||
Progressive = 0,
|
||||
Interlaced = 1
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\RPiRgbLEDMatrix.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,29 @@
|
||||
using RPiRgbLEDMatrix;
|
||||
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Console.WriteLine("font-example.exe [font_path] <text>");
|
||||
return -1;
|
||||
}
|
||||
string text = "Hello World!";
|
||||
if (args.Length > 1)
|
||||
text = args[1];
|
||||
|
||||
|
||||
using var matrix = new RGBLedMatrix(32, 2, 1);
|
||||
var canvas = matrix.CreateOffscreenCanvas();
|
||||
using var font = new RGBLedFont(args[0]);
|
||||
|
||||
canvas.DrawText(font, 1, 6, new Color(0, 255, 0), text);
|
||||
matrix.SwapOnVsync(canvas);
|
||||
|
||||
// run until user presses Ctrl+C
|
||||
var running = true;
|
||||
Console.CancelKeyPress += (_, e) =>
|
||||
{
|
||||
running = false;
|
||||
e.Cancel = true; // do not terminate program with Ctrl+C, we need to dispose
|
||||
};
|
||||
while (running) Thread.Yield();
|
||||
|
||||
return 0;
|
||||
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\RPiRgbLEDMatrix.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,74 @@
|
||||
using RPiRgbLEDMatrix;
|
||||
|
||||
const int MaxHeight = 16;
|
||||
const int ColorStep = 15;
|
||||
const int FrameStep = 1;
|
||||
|
||||
using var matrix = new RGBLedMatrix(new RGBLedMatrixOptions { ChainLength = 2 });
|
||||
var canvas = matrix.CreateOffscreenCanvas();
|
||||
|
||||
var rnd = new Random();
|
||||
var points = new List<Point>();
|
||||
var recycled = new Stack<Point>();
|
||||
var frame = 0;
|
||||
|
||||
var running = true;
|
||||
Console.CancelKeyPress += (s, e) =>
|
||||
{
|
||||
running = false;
|
||||
e.Cancel = true; // don't terminate, we need to dispose
|
||||
};
|
||||
|
||||
// run until user presses Ctrl+C
|
||||
while (running)
|
||||
{
|
||||
var frameStart = Environment.TickCount64;
|
||||
frame++;
|
||||
|
||||
if (frame % FrameStep == 0)
|
||||
{
|
||||
if (recycled.Count == 0)
|
||||
points.Add(new Point(rnd.Next(0, canvas.Width - 1), 0));
|
||||
else
|
||||
{
|
||||
var point = recycled.Pop();
|
||||
point.X = rnd.Next(0, canvas.Width - 1);
|
||||
point.Y = 0;
|
||||
point.Recycled = false;
|
||||
}
|
||||
}
|
||||
|
||||
canvas.Clear();
|
||||
|
||||
foreach (var point in points)
|
||||
{
|
||||
if (point.Recycled) continue;
|
||||
point.Y++;
|
||||
|
||||
if (point.Y - MaxHeight > canvas.Height)
|
||||
{
|
||||
point.Recycled = true;
|
||||
recycled.Push(point);
|
||||
}
|
||||
|
||||
for (var i = 0; i < MaxHeight; i++)
|
||||
{
|
||||
canvas.SetPixel(point.X, point.Y - i, new Color(0, 255 - i * ColorStep, 0));
|
||||
}
|
||||
}
|
||||
|
||||
matrix.SwapOnVsync(canvas);
|
||||
|
||||
// force 30 FPS
|
||||
var elapsed = Environment.TickCount64 - frameStart;
|
||||
if (elapsed < 33) Thread.Sleep(33 - (int)elapsed);
|
||||
}
|
||||
|
||||
class Point
|
||||
{
|
||||
public int X;
|
||||
public int Y;
|
||||
public bool Recycled = false;
|
||||
|
||||
public Point(int x, int y) => (X, Y) = (x, y);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\RPiRgbLEDMatrix.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,19 @@
|
||||
using RPiRgbLEDMatrix;
|
||||
|
||||
using var matrix = new RGBLedMatrix(32, 2, 1);
|
||||
var canvas = matrix.CreateOffscreenCanvas();
|
||||
|
||||
var centerX = canvas.Width / 2;
|
||||
var centerY = canvas.Height / 2;
|
||||
for (var i = 0; i < 1000; ++i)
|
||||
{
|
||||
for (var y = 0; y < canvas.Height; ++y)
|
||||
for (var x = 0; x < canvas.Width; ++x)
|
||||
canvas.SetPixel(x, y, new Color(i & 0xFF, x, y));
|
||||
|
||||
canvas.DrawCircle(centerX, centerY, 6, new Color(0, 0, 255));
|
||||
canvas.DrawLine(centerX - 3, centerY - 3, centerX + 3, centerY + 3, new Color(0, 0, 255));
|
||||
canvas.DrawLine(centerX - 3, centerY + 3, centerX + 3, centerY - 3, new Color(0, 0, 255));
|
||||
|
||||
matrix.SwapOnVsync(canvas);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\RPiRgbLEDMatrix.csproj" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.0.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,40 @@
|
||||
using RPiRgbLEDMatrix;
|
||||
using System.Runtime.InteropServices;
|
||||
using Color = RPiRgbLEDMatrix.Color;
|
||||
|
||||
Console.Write("GIF path: ");
|
||||
var path = Console.ReadLine()!;
|
||||
|
||||
using var matrix = new RGBLedMatrix(32, 2, 1);
|
||||
var canvas = matrix.CreateOffscreenCanvas();
|
||||
|
||||
Configuration.Default.PreferContiguousImageBuffers = true;
|
||||
using var image = Image.Load<Rgb24>(path);
|
||||
image.Mutate(o => o.Resize(canvas.Width, canvas.Height));
|
||||
|
||||
var running = true;
|
||||
Console.CancelKeyPress += (s, e) =>
|
||||
{
|
||||
running = false;
|
||||
e.Cancel = true; // don't terminate, we need to dispose
|
||||
};
|
||||
|
||||
var frame = -1;
|
||||
// preprocess frames to get delays and pixel buffers
|
||||
var frames = image.Frames
|
||||
.Select(f => (
|
||||
Pixels: f.DangerousTryGetSinglePixelMemory(out var memory) ? memory : throw new("Could not get pixel buffer"),
|
||||
Delay: f.Metadata.GetGifMetadata().FrameDelay * 10
|
||||
)).ToArray();
|
||||
|
||||
// run until user presses Ctrl+C
|
||||
while (running)
|
||||
{
|
||||
frame = (frame + 1) % frames.Length;
|
||||
|
||||
var data = MemoryMarshal.Cast<Rgb24, Color>(frames[frame].Pixels.Span);
|
||||
canvas.SetPixels(0, 0, canvas.Width, canvas.Height, data);
|
||||
|
||||
matrix.SwapOnVsync(canvas);
|
||||
Thread.Sleep(frames[frame].Delay);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using RPiRgbLEDMatrix;
|
||||
|
||||
using var matrix = new RGBLedMatrix(new RGBLedMatrixOptions { Rows = 32, Cols = 64 });
|
||||
var canvas = matrix.CreateOffscreenCanvas();
|
||||
|
||||
var maxBrightness = matrix.Brightness;
|
||||
var rnd = new Random();
|
||||
|
||||
// run until user presses Ctrl+C
|
||||
var running = true;
|
||||
Console.CancelKeyPress += (_, e) =>
|
||||
{
|
||||
running = false;
|
||||
e.Cancel = true; // do not terminate program with Ctrl+C, we need to dispose
|
||||
};
|
||||
|
||||
var color = new Color(rnd.Next(0, 256), rnd.Next(0, 256), rnd.Next(0, 256));
|
||||
while (running)
|
||||
{
|
||||
if (matrix.Brightness < 1)
|
||||
{
|
||||
matrix.Brightness = maxBrightness;
|
||||
color = new Color(rnd.Next(0, 256), rnd.Next(0, 256), rnd.Next(0, 256));
|
||||
}
|
||||
else
|
||||
{
|
||||
matrix.Brightness--;
|
||||
}
|
||||
|
||||
canvas.Fill(color);
|
||||
matrix.SwapOnVsync(canvas);
|
||||
Thread.Sleep(20);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\RPiRgbLEDMatrix.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,90 @@
|
||||
using RPiRgbLEDMatrix;
|
||||
using System.Numerics;
|
||||
|
||||
const float MaxModuleSpeed = 0.1f;
|
||||
const float FOV = 60f;
|
||||
const float Scale = 1.1f;
|
||||
const float LerpPow = 0.002f;
|
||||
const int ChangePerFrames = 50;
|
||||
|
||||
using var leds = new RGBLedMatrix(32, 1, 1);
|
||||
var canvas = leds.CreateOffscreenCanvas();
|
||||
|
||||
var (centerX, centerY) = (canvas.Width / 2, canvas.Height / 2);
|
||||
|
||||
var rnd = new Random();
|
||||
var angleSpeed = new Vector3();
|
||||
var nextAngleSpeed = new Vector3();
|
||||
var frame = -1;
|
||||
|
||||
var rotateMatrix = Matrix4x4.Identity;
|
||||
var scaleMatrix = Matrix4x4.CreateScale(Scale);
|
||||
var projectMatrix = Matrix4x4.CreatePerspectiveFieldOfView(FOV / 180 * MathF.PI, 1, 0.1f, 100f);
|
||||
var cameraMatrix = Matrix4x4.CreateLookAt(new(0, 0, 4), new(0, 0, 0), new(0, 1, 0));
|
||||
|
||||
// run until user presses Ctrl+C
|
||||
var running = true;
|
||||
Console.CancelKeyPress += (_, e) =>
|
||||
{
|
||||
running = false;
|
||||
e.Cancel = true; // do not terminate program with Ctrl+C, we need to dispose
|
||||
};
|
||||
while (running)
|
||||
{
|
||||
var frameStart = Environment.TickCount64;
|
||||
|
||||
// update angle speed
|
||||
frame = (frame + 1) % ChangePerFrames;
|
||||
if(frame == 0)
|
||||
nextAngleSpeed = new Vector3(
|
||||
(rnd.NextSingle() * 2 - 1) * MaxModuleSpeed,
|
||||
(rnd.NextSingle() * 2 - 1) * MaxModuleSpeed,
|
||||
(rnd.NextSingle() * 2 - 1) * MaxModuleSpeed
|
||||
);
|
||||
|
||||
angleSpeed = Vector3.Lerp(angleSpeed, nextAngleSpeed, LerpPow);
|
||||
|
||||
// update matrices
|
||||
rotateMatrix *= Matrix4x4.CreateRotationX(angleSpeed.X);
|
||||
rotateMatrix *= Matrix4x4.CreateRotationY(angleSpeed.Y);
|
||||
rotateMatrix *= Matrix4x4.CreateRotationZ(angleSpeed.Z);
|
||||
var matrix = scaleMatrix * rotateMatrix * cameraMatrix * projectMatrix;
|
||||
|
||||
// calculate points
|
||||
var top1 = Vector4.Transform(new Vector3( 1, 1, 1), matrix);
|
||||
var top2 = Vector4.Transform(new Vector3(-1, 1, 1), matrix);
|
||||
var top3 = Vector4.Transform(new Vector3(-1, 1, -1), matrix);
|
||||
var top4 = Vector4.Transform(new Vector3( 1, 1, -1), matrix);
|
||||
|
||||
var bot1 = Vector4.Transform(new Vector3( 1, -1, 1), matrix);
|
||||
var bot2 = Vector4.Transform(new Vector3(-1, -1, 1), matrix);
|
||||
var bot3 = Vector4.Transform(new Vector3(-1, -1, -1), matrix);
|
||||
var bot4 = Vector4.Transform(new Vector3( 1, -1, -1), matrix);
|
||||
|
||||
// draw
|
||||
canvas.Fill(new(0, 0, 0));
|
||||
DrawLine(top1, top2);
|
||||
DrawLine(top2, top3);
|
||||
DrawLine(top3, top4);
|
||||
DrawLine(top4, top1);
|
||||
|
||||
DrawLine(bot1, bot2);
|
||||
DrawLine(bot2, bot3);
|
||||
DrawLine(bot3, bot4);
|
||||
DrawLine(bot4, bot1);
|
||||
|
||||
DrawLine(top1, bot1);
|
||||
DrawLine(top2, bot2);
|
||||
DrawLine(top3, bot3);
|
||||
DrawLine(top4, bot4);
|
||||
|
||||
leds.SwapOnVsync(canvas);
|
||||
// force 30 FPS
|
||||
var elapsed = Environment.TickCount64 - frameStart;
|
||||
if (elapsed < 33) Thread.Sleep(33 - (int)elapsed);
|
||||
}
|
||||
|
||||
void DrawLine(Vector4 a, Vector4 b) => canvas.DrawLine(
|
||||
(int)(a.X * a.W + centerX), (int)(a.Y * a.W + centerY),
|
||||
(int)(b.X * b.W + centerX), (int)(b.Y * b.W + centerY),
|
||||
new(255, 255, 255));
|
||||
@@ -0,0 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\RPiRgbLEDMatrix.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
1
depends/rpi-rgb-led-matrix/bindings/python/.gitignore
vendored
Normal file
1
depends/rpi-rgb-led-matrix/bindings/python/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
build/*
|
||||
92
depends/rpi-rgb-led-matrix/bindings/python/Makefile
Normal file
92
depends/rpi-rgb-led-matrix/bindings/python/Makefile
Normal file
@@ -0,0 +1,92 @@
|
||||
# TODO: This contains a lot of {c|p}ython build boilerplate, this needs cleanup.
|
||||
PYTHON ?= python
|
||||
SETUP := setup.py
|
||||
BUILD_ARGS := build --build-lib .
|
||||
INST_ARGS := install
|
||||
ifdef DESTDIR
|
||||
INST_ARGS += --root=$(DESTDIR)
|
||||
endif
|
||||
CLEAN_ARGS := clean --all
|
||||
|
||||
MANPAGES := $(patsubst %.txt,%,$(wildcard *.txt))
|
||||
TXTTOMAN := a2x -f manpage
|
||||
|
||||
# Where our library resides. It is split between includes and the binary
|
||||
# library in lib
|
||||
RGB_LIBDIR=../../lib
|
||||
RGB_LIBRARY_NAME=rgbmatrix
|
||||
RGB_LIBRARY=$(RGB_LIBDIR)/lib$(RGB_LIBRARY_NAME).a
|
||||
|
||||
ifneq "$(wildcard debian/changelog)" ""
|
||||
PKGNAME := $(shell dpkg-parsechangelog | sed -n 's/^Source: //p')
|
||||
VERSION := $(shell dpkg-parsechangelog | sed -n 's/^Version: \([^-]*\).*/\1/p')
|
||||
UPSDIST := $(PKGNAME)-$(VERSION).tar.gz
|
||||
DEBDIST := $(PKGNAME)_$(VERSION).orig.tar.gz
|
||||
endif
|
||||
|
||||
all: build
|
||||
build: build-python
|
||||
install: install-python
|
||||
clean: clean-python
|
||||
find ./rgbmatrix -type f -name \*.so -delete
|
||||
find . -type f -name \*.pyc -delete
|
||||
$(RM) build-* install-* test-*
|
||||
|
||||
$(RGB_LIBRARY): FORCE
|
||||
$(MAKE) -C $(RGB_LIBDIR)
|
||||
|
||||
test: test-python
|
||||
test-python:
|
||||
ifneq "$(wildcard tests/*.py)" ""
|
||||
nosetests -v -w tests
|
||||
else
|
||||
$(info Test suite is not implemented...)
|
||||
endif
|
||||
|
||||
ifneq "$(wildcard debian/control)" ""
|
||||
PYVERS := $(shell pyversions -r -v debian/control)
|
||||
PYEXEC := $(shell pyversions -d)
|
||||
BUILD_ARGS += --executable=/usr/bin/$(PYEXEC)
|
||||
INST_ARGS += --no-compile -O0
|
||||
|
||||
build-python: $(PYVERS:%=build-python-%)
|
||||
build-python-%: $(RGB_LIBRARY)
|
||||
$(info * Doing build for $(PYTHON)$* ...)
|
||||
$(PYTHON)$* $(SETUP) $(BUILD_ARGS)
|
||||
|
||||
install-python: $(PYVERS:%=install-python-%)
|
||||
install-python-%:
|
||||
$(info * Doing install for $(PYTHON)$* ...)
|
||||
$(PYTHON)$* $(SETUP) $(INST_ARGS)
|
||||
|
||||
clean-python: $(PYVERS:%=clean-python-%)
|
||||
clean-python-%:
|
||||
$(PYTHON)$* $(SETUP) $(CLEAN_ARGS)
|
||||
else
|
||||
build-python: $(RGB_LIBRARY)
|
||||
$(PYTHON) $(SETUP) $(BUILD_ARGS)
|
||||
|
||||
install-python:
|
||||
$(PYTHON) $(SETUP) $(INST_ARGS)
|
||||
|
||||
clean-python:
|
||||
$(PYTHON) $(SETUP) $(CLEAN_ARGS)
|
||||
endif
|
||||
|
||||
distclean: clean
|
||||
dist: distclean
|
||||
$(info * Creating ../$(UPSDIST) and ../$(DEBDIST))
|
||||
@tar --exclude='.svn' \
|
||||
--exclude='*.swp' \
|
||||
--exclude='debian' \
|
||||
-czvf ../$(UPSDIST) \
|
||||
-C ../ $(notdir $(CURDIR))
|
||||
@cp ../$(UPSDIST) ../$(DEBDIST)
|
||||
@if test -d ../tarballs; then \
|
||||
mv -v ../$(DEBDIST) ../tarballs; \
|
||||
fi
|
||||
|
||||
FORCE:
|
||||
.PHONY: FORCE
|
||||
.PHONY: build install test clean dist distclean
|
||||
.PHONY: build-python install-python clean-python
|
||||
147
depends/rpi-rgb-led-matrix/bindings/python/README.md
Executable file
147
depends/rpi-rgb-led-matrix/bindings/python/README.md
Executable file
@@ -0,0 +1,147 @@
|
||||
Python bindings for RGB Matrix library
|
||||
======================================
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
If you have a different than the standard wiring (for instance if you have an
|
||||
Adafruit HAT), you can edit the [../../lib/Makefile](../../lib/Makefile#L26) first to choose
|
||||
the hardware in question (see below for setting it via command line argument).
|
||||
|
||||
Then, in the root directory for the matrix library simply type:
|
||||
|
||||
### Python 2
|
||||
|
||||
```shell
|
||||
sudo apt-get update && sudo apt-get install python2.7-dev python-pillow -y
|
||||
make build-python
|
||||
sudo make install-python
|
||||
```
|
||||
|
||||
### Python 3
|
||||
You can also build for Python 3:
|
||||
|
||||
```shell
|
||||
sudo apt-get update && sudo apt-get install python3-dev python3-pillow -y
|
||||
make build-python PYTHON=$(command -v python3)
|
||||
sudo make install-python PYTHON=$(command -v python3)
|
||||
```
|
||||
|
||||
### PyPy
|
||||
The cython binding to PyPy seems to be somewhat working but extremely slow (20x
|
||||
slower even than the regular Python binding, 160x slower than C++), so this is
|
||||
not recommended.
|
||||
|
||||
So Cython is not good together with PyPy which works best with a
|
||||
[CFFI](https://cffi.readthedocs.io/) binding. @Duality4Y did an experiment here
|
||||
https://github.com/Duality4Y/rgb-matrix-cffi which works well with PyPy and is
|
||||
about twice as fast as running Python3+cython (but Python3+cffi is slower than
|
||||
Python3+cython, so we can't just replace everything with cffi).
|
||||
|
||||
Of course, it would be nice to have the fastest possible binding to all kinds
|
||||
of Python interpreters. If anyone wants to work on that, this would certainly
|
||||
be a welcome pull request.
|
||||
|
||||
Performance
|
||||
-----------
|
||||
The simplicity of scripting comes at a price: Python is slower than C++ of
|
||||
course.
|
||||
If you have to do a lot of pixel updates in your demo, this can be too slow
|
||||
depending on what you do. Here are some rough numbers for calling `SetPixel()`
|
||||
in a tight loop:
|
||||
|
||||
* On a Pi-2 and Pi-3, a Python script will be about 1/8 of the speed compared
|
||||
to the corresponding C++ program (pushing ~0.43 Megapixels/s Python
|
||||
vs. ~3.5 Megapixels/s C++ on a Pi-3 for instance)
|
||||
* On a Pi-1/Pi Zero, the difference is even worse: 1/24 of the speed to the
|
||||
corresponding C++ program. Given that this Pi is already about 1/10 the
|
||||
speed of a Pi-3, this almost makes Python unusable on a Pi-1
|
||||
(~0.015 Megapixels/s Python vs. ~0.36 Megapixels/s C++)
|
||||
* Also interesting: Python3 is a little bit slower than Python2.7.
|
||||
So if you can, stick with Python2.7 for now.
|
||||
* The good news is, that this is due to overhead per function call. If you
|
||||
can do more per function call, then this is less problematic. For instance
|
||||
if you have an image to be displayed with `SetImage()`, that will much
|
||||
faster per pixel (internally this then copies the pixels natively).
|
||||
|
||||
The ~0.015 Megapixels/s on a Pi-1 means that you can update a 32x32 matrix
|
||||
at most with ~15fps. If you have chained 5, then you barely reach 3fps.
|
||||
In a Pi-3, you get about 400fps update rate (85fps for 5-chain) with a Python
|
||||
program (while with C++, you can do the same thing with a comfortable 3500fps
|
||||
(700fps for 5)). Keep in mind that this is if all you do is just calling
|
||||
`SetPixel()`, it does not include any time of what you actually want to do in
|
||||
your demo - so anything in addition to that will drop your update rate.
|
||||
|
||||
If you can prepare the animation you want to show, then you can either prepare
|
||||
images and then use the much faster call to `SetImage()`, or can fill
|
||||
entire offscreen-frames (create with `CreateFrameCanvas()`) and then
|
||||
swap with `SwapOnVSync()` (this is the fastest method).
|
||||
|
||||
Using the library
|
||||
-----------------
|
||||
|
||||
Be aware of the fact that using the full performance of the RGBMatrix requires root privileges.
|
||||
Therefore you should run all you python scripts as using `sudo`.
|
||||
|
||||
You may find examples in the [samples/](./samples) subdirectory.
|
||||
The examples all use the [samplebase.py](./samples/samplebase.py) that provides
|
||||
some basic capabilities to all example programs, such as command-line parsing: all
|
||||
sample-programs accept `--led-rows`, `--led-chain` and `--led-parallel` as
|
||||
command line options to adapt to your configuration
|
||||
|
||||
```bash
|
||||
cd samples
|
||||
sudo ./runtext.py --led-chain=4
|
||||
```
|
||||
|
||||
To use different wiring without recompiling the library to change the default,
|
||||
you can use `--led-gpio-mapping` (or `-m`). For example, to use Adafruit HAT:
|
||||
```bash
|
||||
sudo ./runtext.py --led-gpio-mapping=adafruit-hat
|
||||
```
|
||||
|
||||
Here is a complete example showing how to write an image viewer:
|
||||
```python
|
||||
#!/usr/bin/env python
|
||||
import time
|
||||
import sys
|
||||
|
||||
from rgbmatrix import RGBMatrix, RGBMatrixOptions
|
||||
from PIL import Image
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
sys.exit("Require an image argument")
|
||||
else:
|
||||
image_file = sys.argv[1]
|
||||
|
||||
image = Image.open(image_file)
|
||||
|
||||
# Configuration for the matrix
|
||||
options = RGBMatrixOptions()
|
||||
options.rows = 32
|
||||
options.chain_length = 1
|
||||
options.parallel = 1
|
||||
options.hardware_mapping = 'regular' # If you have an Adafruit HAT: 'adafruit-hat'
|
||||
|
||||
matrix = RGBMatrix(options = options)
|
||||
|
||||
# Make image fit our screen.
|
||||
image.thumbnail((matrix.width, matrix.height), Image.ANTIALIAS)
|
||||
|
||||
matrix.SetImage(image.convert('RGB'))
|
||||
|
||||
try:
|
||||
print("Press CTRL-C to stop.")
|
||||
while True:
|
||||
time.sleep(100)
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(0)
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
The source of truth for what is available in the Python bindings may be found [here](rgbmatrix/core.pyx) (RGBMatrix, FrameCanvas, RGBMatrixOptions) and [here](rgbmatrix/graphics.pyx) (graphics). The underlying implementation's ground truth documentation may be found [here](../../include), specifically for [RGBMatrix, RGBMatrixOptions, and FrameCanvas](../../include/led-matrix.h), [Canvas](../../include/canvas.h) (base class of RGBMatrix), and [graphics methods and Font](../../include/graphics.h).
|
||||
|
||||
### User
|
||||
|
||||
As noted in the Performance section above, Python programs not run as `root` will not be as high-performance as those run as `root`. When running as `root`, be aware of a potentially-unexpected behavior: to reduce the security attack surface, initializing an RGBMatrix as `root` changes the user from `root` to `daemon` (see [#1170](https://github.com/hzeller/rpi-rgb-led-matrix/issues/1170) for more information) by default. This means, for instance, that some file operations possible before initializing the RGBMatrix will not be possible after initialization. To disable this behavior, set `drop_privileges=False` in RGBMatrixOptions, but be aware that doing so will reduce security.
|
||||
@@ -0,0 +1,15 @@
|
||||
# The *.cpp files are included in the distribution; this is only needed when
|
||||
# working on the pyx files.
|
||||
#
|
||||
# Please check in modified *.cpp files with distribution to not require cython
|
||||
# to be installed on the users' machine.
|
||||
# for python3: make PYTHON=$(which python3) CYTHON=$(which cython3)
|
||||
CYTHON ?= cython
|
||||
|
||||
all : core.cpp graphics.cpp
|
||||
|
||||
%.cpp : %.pyx
|
||||
$(CYTHON) --cplus -o $@ $^
|
||||
|
||||
clean:
|
||||
rm -rf core.cpp graphics.cpp
|
||||
7
depends/rpi-rgb-led-matrix/bindings/python/rgbmatrix/__init__.py
Executable file
7
depends/rpi-rgb-led-matrix/bindings/python/rgbmatrix/__init__.py
Executable file
@@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
|
||||
__version__ = "0.0.1"
|
||||
__author__ = "Christoph Friedrich <christoph.friedrich@vonaffenfels.de>"
|
||||
|
||||
from .core import RGBMatrix, FrameCanvas, RGBMatrixOptions
|
||||
13196
depends/rpi-rgb-led-matrix/bindings/python/rgbmatrix/core.cpp
Normal file
13196
depends/rpi-rgb-led-matrix/bindings/python/rgbmatrix/core.cpp
Normal file
File diff suppressed because it is too large
Load Diff
24
depends/rpi-rgb-led-matrix/bindings/python/rgbmatrix/core.pxd
Executable file
24
depends/rpi-rgb-led-matrix/bindings/python/rgbmatrix/core.pxd
Executable file
@@ -0,0 +1,24 @@
|
||||
cimport cppinc
|
||||
|
||||
cdef class Canvas:
|
||||
cdef cppinc.Canvas *__getCanvas(self) except +
|
||||
|
||||
cdef class FrameCanvas(Canvas):
|
||||
cdef cppinc.FrameCanvas *__canvas
|
||||
|
||||
cdef class RGBMatrix(Canvas):
|
||||
cdef cppinc.RGBMatrix *__matrix
|
||||
|
||||
cdef class RGBMatrixOptions:
|
||||
cdef cppinc.Options __options
|
||||
cdef cppinc.RuntimeOptions __runtime_options
|
||||
# Must keep a reference to the encoded bytes for the strings,
|
||||
# otherwise, when the Options struct is used, it will be garbage collected
|
||||
cdef bytes __py_encoded_hardware_mapping
|
||||
cdef bytes __py_encoded_led_rgb_sequence
|
||||
cdef bytes __py_encoded_pixel_mapper_config
|
||||
cdef bytes __py_encoded_panel_type
|
||||
|
||||
# Local Variables:
|
||||
# mode: python
|
||||
# End:
|
||||
272
depends/rpi-rgb-led-matrix/bindings/python/rgbmatrix/core.pyx
Executable file
272
depends/rpi-rgb-led-matrix/bindings/python/rgbmatrix/core.pyx
Executable file
@@ -0,0 +1,272 @@
|
||||
# distutils: language = c++
|
||||
|
||||
from libcpp cimport bool
|
||||
from libc.stdint cimport uint8_t, uint32_t, uintptr_t
|
||||
from PIL import Image
|
||||
import cython
|
||||
|
||||
cdef class Canvas:
|
||||
cdef cppinc.Canvas* __getCanvas(self) except +:
|
||||
raise Exception("Not implemented")
|
||||
|
||||
def SetImage(self, image, int offset_x = 0, int offset_y = 0, unsafe=True):
|
||||
if (image.mode != "RGB"):
|
||||
raise Exception("Currently, only RGB mode is supported for SetImage(). Please create images with mode 'RGB' or convert first with image = image.convert('RGB'). Pull requests to support more modes natively are also welcome :)")
|
||||
|
||||
if unsafe:
|
||||
#In unsafe mode we directly access the underlying PIL image array
|
||||
#in cython, which is considered unsafe pointer accecss,
|
||||
#however it's super fast and seems to work fine
|
||||
#https://groups.google.com/forum/#!topic/cython-users/Dc1ft5W6KM4
|
||||
img_width, img_height = image.size
|
||||
self.SetPixelsPillow(offset_x, offset_y, img_width, img_height, image)
|
||||
else:
|
||||
# First implementation of a SetImage(). OPTIMIZE_ME: A more native
|
||||
# implementation that directly reads the buffer and calls the underlying
|
||||
# C functions can certainly be faster.
|
||||
img_width, img_height = image.size
|
||||
pixels = image.load()
|
||||
for x in range(max(0, -offset_x), min(img_width, self.width - offset_x)):
|
||||
for y in range(max(0, -offset_y), min(img_height, self.height - offset_y)):
|
||||
(r, g, b) = pixels[x, y]
|
||||
self.SetPixel(x + offset_x, y + offset_y, r, g, b)
|
||||
|
||||
@cython.boundscheck(False)
|
||||
@cython.wraparound(False)
|
||||
def SetPixelsPillow(self, int xstart, int ystart, int width, int height, image):
|
||||
cdef cppinc.FrameCanvas* my_canvas = <cppinc.FrameCanvas*>self.__getCanvas()
|
||||
cdef int frame_width = my_canvas.width()
|
||||
cdef int frame_height = my_canvas.height()
|
||||
cdef int row, col
|
||||
cdef uint8_t r, g, b
|
||||
cdef uint32_t **image_ptr
|
||||
cdef uint32_t pixel
|
||||
image.load()
|
||||
ptr_tmp = dict(image.im.unsafe_ptrs)['image32']
|
||||
image_ptr = (<uint32_t **>(<uintptr_t>ptr_tmp))
|
||||
|
||||
for col in range(max(0, -xstart), min(width, frame_width - xstart)):
|
||||
for row in range(max(0, -ystart), min(height, frame_height - ystart)):
|
||||
pixel = image_ptr[row][col]
|
||||
r = (pixel ) & 0xFF
|
||||
g = (pixel >> 8) & 0xFF
|
||||
b = (pixel >> 16) & 0xFF
|
||||
my_canvas.SetPixel(xstart+col, ystart+row, r, g, b)
|
||||
|
||||
cdef class FrameCanvas(Canvas):
|
||||
def __dealloc__(self):
|
||||
if <void*>self.__canvas != NULL:
|
||||
self.__canvas = NULL
|
||||
|
||||
cdef cppinc.Canvas* __getCanvas(self) except *:
|
||||
if <void*>self.__canvas != NULL:
|
||||
return self.__canvas
|
||||
raise Exception("Canvas was destroyed or not initialized, you cannot use this object anymore")
|
||||
|
||||
def Fill(self, uint8_t red, uint8_t green, uint8_t blue):
|
||||
(<cppinc.FrameCanvas*>self.__getCanvas()).Fill(red, green, blue)
|
||||
|
||||
def Clear(self):
|
||||
(<cppinc.FrameCanvas*>self.__getCanvas()).Clear()
|
||||
|
||||
def SetPixel(self, int x, int y, uint8_t red, uint8_t green, uint8_t blue):
|
||||
(<cppinc.FrameCanvas*>self.__getCanvas()).SetPixel(x, y, red, green, blue)
|
||||
|
||||
|
||||
property width:
|
||||
def __get__(self): return (<cppinc.FrameCanvas*>self.__getCanvas()).width()
|
||||
|
||||
property height:
|
||||
def __get__(self): return (<cppinc.FrameCanvas*>self.__getCanvas()).height()
|
||||
|
||||
property pwmBits:
|
||||
def __get__(self): return (<cppinc.FrameCanvas*>self.__getCanvas()).pwmbits()
|
||||
def __set__(self, pwmBits): (<cppinc.FrameCanvas*>self.__getCanvas()).SetPWMBits(pwmBits)
|
||||
|
||||
property brightness:
|
||||
def __get__(self): return (<cppinc.FrameCanvas*>self.__getCanvas()).brightness()
|
||||
def __set__(self, val): (<cppinc.FrameCanvas*>self.__getCanvas()).SetBrightness(val)
|
||||
|
||||
|
||||
cdef class RGBMatrixOptions:
|
||||
def __cinit__(self):
|
||||
self.__options = cppinc.Options()
|
||||
self.__runtime_options = cppinc.RuntimeOptions()
|
||||
|
||||
# RGBMatrix::Options properties
|
||||
property hardware_mapping:
|
||||
def __get__(self): return self.__options.hardware_mapping
|
||||
def __set__(self, value):
|
||||
self.__py_encoded_hardware_mapping = value.encode('utf-8')
|
||||
self.__options.hardware_mapping = self.__py_encoded_hardware_mapping
|
||||
|
||||
property rows:
|
||||
def __get__(self): return self.__options.rows
|
||||
def __set__(self, uint8_t value): self.__options.rows = value
|
||||
|
||||
property cols:
|
||||
def __get__(self): return self.__options.cols
|
||||
def __set__(self, uint32_t value): self.__options.cols = value
|
||||
|
||||
property chain_length:
|
||||
def __get__(self): return self.__options.chain_length
|
||||
def __set__(self, uint8_t value): self.__options.chain_length = value
|
||||
|
||||
property parallel:
|
||||
def __get__(self): return self.__options.parallel
|
||||
def __set__(self, uint8_t value): self.__options.parallel = value
|
||||
|
||||
property pwm_bits:
|
||||
def __get__(self): return self.__options.pwm_bits
|
||||
def __set__(self, uint8_t value): self.__options.pwm_bits = value
|
||||
|
||||
property pwm_lsb_nanoseconds:
|
||||
def __get__(self): return self.__options.pwm_lsb_nanoseconds
|
||||
def __set__(self, uint32_t value): self.__options.pwm_lsb_nanoseconds = value
|
||||
|
||||
property brightness:
|
||||
def __get__(self): return self.__options.brightness
|
||||
def __set__(self, uint8_t value): self.__options.brightness = value
|
||||
|
||||
property scan_mode:
|
||||
def __get__(self): return self.__options.scan_mode
|
||||
def __set__(self, uint8_t value): self.__options.scan_mode = value
|
||||
|
||||
property multiplexing:
|
||||
def __get__(self): return self.__options.multiplexing
|
||||
def __set__(self, uint8_t value): self.__options.multiplexing = value
|
||||
|
||||
property row_address_type:
|
||||
def __get__(self): return self.__options.row_address_type
|
||||
def __set__(self, uint8_t value): self.__options.row_address_type = value
|
||||
|
||||
property disable_hardware_pulsing:
|
||||
def __get__(self): return self.__options.disable_hardware_pulsing
|
||||
def __set__(self, value): self.__options.disable_hardware_pulsing = value
|
||||
|
||||
property show_refresh_rate:
|
||||
def __get__(self): return self.__options.show_refresh_rate
|
||||
def __set__(self, value): self.__options.show_refresh_rate = value
|
||||
|
||||
property inverse_colors:
|
||||
def __get__(self): return self.__options.inverse_colors
|
||||
def __set__(self, value): self.__options.inverse_colors = value
|
||||
|
||||
property led_rgb_sequence:
|
||||
def __get__(self): return self.__options.led_rgb_sequence
|
||||
def __set__(self, value):
|
||||
self.__py_encoded_led_rgb_sequence = value.encode('utf-8')
|
||||
self.__options.led_rgb_sequence = self.__py_encoded_led_rgb_sequence
|
||||
|
||||
property pixel_mapper_config:
|
||||
def __get__(self): return self.__options.pixel_mapper_config
|
||||
def __set__(self, value):
|
||||
self.__py_encoded_pixel_mapper_config = value.encode('utf-8')
|
||||
self.__options.pixel_mapper_config = self.__py_encoded_pixel_mapper_config
|
||||
|
||||
property panel_type:
|
||||
def __get__(self): return self.__options.panel_type
|
||||
def __set__(self, value):
|
||||
self.__py_encoded_panel_type = value.encode('utf-8')
|
||||
self.__options.panel_type = self.__py_encoded_panel_type
|
||||
|
||||
property pwm_dither_bits:
|
||||
def __get__(self): return self.__options.pwm_dither_bits
|
||||
def __set__(self, uint8_t value): self.__options.pwm_dither_bits = value
|
||||
|
||||
property limit_refresh_rate_hz:
|
||||
def __get__(self): return self.__options.limit_refresh_rate_hz
|
||||
def __set__(self, value): self.__options.limit_refresh_rate_hz = value
|
||||
|
||||
|
||||
# RuntimeOptions properties
|
||||
|
||||
property gpio_slowdown:
|
||||
def __get__(self): return self.__runtime_options.gpio_slowdown
|
||||
def __set__(self, uint8_t value): self.__runtime_options.gpio_slowdown = value
|
||||
|
||||
property daemon:
|
||||
def __get__(self): return self.__runtime_options.daemon
|
||||
def __set__(self, uint8_t value): self.__runtime_options.daemon = value
|
||||
|
||||
property drop_privileges:
|
||||
def __get__(self): return self.__runtime_options.drop_privileges
|
||||
def __set__(self, uint8_t value): self.__runtime_options.drop_privileges = value
|
||||
|
||||
cdef class RGBMatrix(Canvas):
|
||||
def __cinit__(self, int rows = 0, int chains = 0, int parallel = 0,
|
||||
RGBMatrixOptions options = None):
|
||||
|
||||
# If RGBMatrixOptions not provided, create defaults and set any optional
|
||||
# parameters supplied
|
||||
if options == None:
|
||||
options = RGBMatrixOptions()
|
||||
|
||||
if rows > 0:
|
||||
options.rows = rows
|
||||
if chains > 0:
|
||||
options.chain_length = chains
|
||||
if parallel > 0:
|
||||
options.parallel = parallel
|
||||
|
||||
self.__matrix = cppinc.CreateMatrixFromOptions(options.__options,
|
||||
options.__runtime_options)
|
||||
|
||||
def __dealloc__(self):
|
||||
self.__matrix.Clear()
|
||||
del self.__matrix
|
||||
|
||||
cdef cppinc.Canvas* __getCanvas(self) except *:
|
||||
if <void*>self.__matrix != NULL:
|
||||
return self.__matrix
|
||||
raise Exception("Canvas was destroyed or not initialized, you cannot use this object anymore")
|
||||
|
||||
def Fill(self, uint8_t red, uint8_t green, uint8_t blue):
|
||||
self.__matrix.Fill(red, green, blue)
|
||||
|
||||
def SetPixel(self, int x, int y, uint8_t red, uint8_t green, uint8_t blue):
|
||||
self.__matrix.SetPixel(x, y, red, green, blue)
|
||||
|
||||
def Clear(self):
|
||||
self.__matrix.Clear()
|
||||
|
||||
def CreateFrameCanvas(self):
|
||||
return __createFrameCanvas(self.__matrix.CreateFrameCanvas())
|
||||
|
||||
# The optional "framerate_fraction" parameter allows to choose which
|
||||
# multiple of the global frame-count to use. So it slows down your animation
|
||||
# to an exact integer fraction of the refresh rate.
|
||||
# Default is 1, so immediately next available frame.
|
||||
# (Say you have 140Hz refresh rate, then a value of 5 would give you an
|
||||
# 28Hz animation, nicely locked to the refresh-rate).
|
||||
# If you combine this with RGBMatrixOptions.limit_refresh_rate_hz you can create
|
||||
# time-correct animations.
|
||||
def SwapOnVSync(self, FrameCanvas newFrame, uint8_t framerate_fraction = 1):
|
||||
return __createFrameCanvas(self.__matrix.SwapOnVSync(newFrame.__canvas, framerate_fraction))
|
||||
|
||||
property luminanceCorrect:
|
||||
def __get__(self): return self.__matrix.luminance_correct()
|
||||
def __set__(self, luminanceCorrect): self.__matrix.set_luminance_correct(luminanceCorrect)
|
||||
|
||||
property pwmBits:
|
||||
def __get__(self): return self.__matrix.pwmbits()
|
||||
def __set__(self, pwmBits): self.__matrix.SetPWMBits(pwmBits)
|
||||
|
||||
property brightness:
|
||||
def __get__(self): return self.__matrix.brightness()
|
||||
def __set__(self, brightness): self.__matrix.SetBrightness(brightness)
|
||||
|
||||
property height:
|
||||
def __get__(self): return self.__matrix.height()
|
||||
|
||||
property width:
|
||||
def __get__(self): return self.__matrix.width()
|
||||
|
||||
cdef __createFrameCanvas(cppinc.FrameCanvas* newCanvas):
|
||||
canvas = FrameCanvas()
|
||||
canvas.__canvas = newCanvas
|
||||
return canvas
|
||||
|
||||
# Local Variables:
|
||||
# mode: python
|
||||
# End:
|
||||
88
depends/rpi-rgb-led-matrix/bindings/python/rgbmatrix/cppinc.pxd
Executable file
88
depends/rpi-rgb-led-matrix/bindings/python/rgbmatrix/cppinc.pxd
Executable file
@@ -0,0 +1,88 @@
|
||||
from libcpp cimport bool
|
||||
from libc.stdint cimport uint8_t, uint32_t
|
||||
|
||||
########################
|
||||
### External classes ###
|
||||
########################
|
||||
|
||||
cdef extern from "canvas.h" namespace "rgb_matrix":
|
||||
cdef cppclass Canvas:
|
||||
int width()
|
||||
int height()
|
||||
void SetPixel(int, int, uint8_t, uint8_t, uint8_t) nogil
|
||||
void Clear() nogil
|
||||
void Fill(uint8_t, uint8_t, uint8_t) nogil
|
||||
|
||||
cdef extern from "led-matrix.h" namespace "rgb_matrix":
|
||||
cdef cppclass RGBMatrix(Canvas):
|
||||
bool SetPWMBits(uint8_t)
|
||||
uint8_t pwmbits()
|
||||
void set_luminance_correct(bool)
|
||||
bool luminance_correct()
|
||||
void SetBrightness(uint8_t)
|
||||
uint8_t brightness()
|
||||
FrameCanvas *CreateFrameCanvas()
|
||||
FrameCanvas *SwapOnVSync(FrameCanvas*, uint8_t)
|
||||
|
||||
cdef cppclass FrameCanvas(Canvas):
|
||||
bool SetPWMBits(uint8_t)
|
||||
uint8_t pwmbits()
|
||||
void SetBrightness(uint8_t)
|
||||
uint8_t brightness()
|
||||
|
||||
struct RuntimeOptions:
|
||||
RuntimeOptions() except +
|
||||
int gpio_slowdown
|
||||
int daemon
|
||||
int drop_privileges
|
||||
|
||||
|
||||
RGBMatrix *CreateMatrixFromOptions(Options &options, RuntimeOptions runtime_options)
|
||||
|
||||
|
||||
|
||||
cdef extern from "led-matrix.h" namespace "rgb_matrix::RGBMatrix":
|
||||
cdef struct Options:
|
||||
Options() except +
|
||||
|
||||
const char *hardware_mapping
|
||||
|
||||
int rows
|
||||
int cols
|
||||
int chain_length
|
||||
int parallel
|
||||
int pwm_bits
|
||||
int pwm_lsb_nanoseconds
|
||||
int brightness
|
||||
int scan_mode
|
||||
int row_address_type
|
||||
int multiplexing
|
||||
int pwm_dither_bits
|
||||
int limit_refresh_rate_hz
|
||||
|
||||
bool disable_hardware_pulsing
|
||||
bool show_refresh_rate
|
||||
bool inverse_colors
|
||||
|
||||
const char *led_rgb_sequence
|
||||
const char *pixel_mapper_config
|
||||
const char *panel_type
|
||||
|
||||
cdef extern from "graphics.h" namespace "rgb_matrix":
|
||||
cdef struct Color:
|
||||
Color(uint8_t, uint8_t, uint8_t) except +
|
||||
uint8_t r
|
||||
uint8_t g
|
||||
uint8_t b
|
||||
|
||||
cdef cppclass Font:
|
||||
Font() except +
|
||||
bool LoadFont(const char*)
|
||||
int height()
|
||||
int baseline()
|
||||
int CharacterWidth(uint32_t)
|
||||
int DrawGlyph(Canvas*, int, int, const Color, uint32_t);
|
||||
|
||||
cdef int DrawText(Canvas*, const Font, int, int, const Color, const char*)
|
||||
cdef void DrawCircle(Canvas*, int, int, int, const Color)
|
||||
cdef void DrawLine(Canvas*, int, int, int, int, const Color)
|
||||
6528
depends/rpi-rgb-led-matrix/bindings/python/rgbmatrix/graphics.cpp
Normal file
6528
depends/rpi-rgb-led-matrix/bindings/python/rgbmatrix/graphics.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
cimport cppinc
|
||||
|
||||
cdef class Color:
|
||||
cdef cppinc.Color __color
|
||||
|
||||
cdef class Font:
|
||||
cdef cppinc.Font __font
|
||||
|
||||
# Local Variables:
|
||||
# mode: python
|
||||
# End:
|
||||
@@ -0,0 +1,54 @@
|
||||
# distutils: language = c++
|
||||
|
||||
from libcpp cimport bool
|
||||
from libc.stdint cimport uint8_t, uint32_t
|
||||
|
||||
cimport core
|
||||
|
||||
cdef class Color:
|
||||
def __init__(self, uint8_t red = 0, uint8_t green = 0, uint8_t blue = 0):
|
||||
self.__color.r = red
|
||||
self.__color.g = green
|
||||
self.__color.b = blue
|
||||
|
||||
property red:
|
||||
def __get__(self): return self.__color.r
|
||||
def __set__(self, uint8_t value): self.__color.r = value
|
||||
|
||||
property green:
|
||||
def __get__(self): return self.__color.g
|
||||
def __set__(self, uint8_t value): self.__color.g = value
|
||||
|
||||
property blue:
|
||||
def __get__(self): return self.__color.b
|
||||
def __set__(self, uint8_t value): self.__color.b = value
|
||||
|
||||
cdef class Font:
|
||||
def CharacterWidth(self, uint32_t char):
|
||||
return self.__font.CharacterWidth(char)
|
||||
|
||||
def LoadFont(self, file):
|
||||
if (not self.__font.LoadFont(file.encode('utf-8'))):
|
||||
raise Exception("Couldn't load font " + file)
|
||||
|
||||
def DrawGlyph(self, core.Canvas c, int x, int y, Color color, uint32_t char):
|
||||
return self.__font.DrawGlyph(c.__getCanvas(), x, y, color.__color, char)
|
||||
|
||||
property height:
|
||||
def __get__(self): return self.__font.height()
|
||||
|
||||
property baseline:
|
||||
def __get__(self): return self.__font.baseline()
|
||||
|
||||
def DrawText(core.Canvas c, Font f, int x, int y, Color color, text):
|
||||
return cppinc.DrawText(c.__getCanvas(), f.__font, x, y, color.__color, text.encode('utf-8'))
|
||||
|
||||
def DrawCircle(core.Canvas c, int x, int y, int r, Color color):
|
||||
cppinc.DrawCircle(c.__getCanvas(), x, y, r, color.__color)
|
||||
|
||||
def DrawLine(core.Canvas c, int x1, int y1, int x2, int y2, Color color):
|
||||
cppinc.DrawLine(c.__getCanvas(), x1, y1, x2, y2, color.__color)
|
||||
|
||||
# Local Variables:
|
||||
# mode: python
|
||||
# End:
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python
|
||||
import time
|
||||
import sys
|
||||
|
||||
from rgbmatrix import RGBMatrix, RGBMatrixOptions
|
||||
from PIL import Image
|
||||
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
sys.exit("Require a gif argument")
|
||||
else:
|
||||
image_file = sys.argv[1]
|
||||
|
||||
gif = Image.open(image_file)
|
||||
|
||||
try:
|
||||
num_frames = gif.n_frames
|
||||
except Exception:
|
||||
sys.exit("provided image is not a gif")
|
||||
|
||||
|
||||
# Configuration for the matrix
|
||||
options = RGBMatrixOptions()
|
||||
options.rows = 32
|
||||
options.cols = 32
|
||||
options.chain_length = 1
|
||||
options.parallel = 1
|
||||
options.hardware_mapping = 'regular' # If you have an Adafruit HAT: 'adafruit-hat'
|
||||
|
||||
matrix = RGBMatrix(options = options)
|
||||
|
||||
# Preprocess the gifs frames into canvases to improve playback performance
|
||||
canvases = []
|
||||
print("Preprocessing gif, this may take a moment depending on the size of the gif...")
|
||||
for frame_index in range(0, num_frames):
|
||||
gif.seek(frame_index)
|
||||
# must copy the frame out of the gif, since thumbnail() modifies the image in-place
|
||||
frame = gif.copy()
|
||||
frame.thumbnail((matrix.width, matrix.height), Image.ANTIALIAS)
|
||||
canvas = matrix.CreateFrameCanvas()
|
||||
canvas.SetImage(frame.convert("RGB"))
|
||||
canvases.append(canvas)
|
||||
# Close the gif file to save memory now that we have copied out all of the frames
|
||||
gif.close()
|
||||
|
||||
print("Completed Preprocessing, displaying gif")
|
||||
|
||||
try:
|
||||
print("Press CTRL-C to stop.")
|
||||
|
||||
# Infinitely loop through the gif
|
||||
cur_frame = 0
|
||||
while(True):
|
||||
matrix.SwapOnVSync(canvases[cur_frame], framerate_fraction=10)
|
||||
if cur_frame == num_frames - 1:
|
||||
cur_frame = 0
|
||||
else:
|
||||
cur_frame += 1
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(0)
|
||||
32
depends/rpi-rgb-led-matrix/bindings/python/samples/graphics.py
Executable file
32
depends/rpi-rgb-led-matrix/bindings/python/samples/graphics.py
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python
|
||||
from samplebase import SampleBase
|
||||
from rgbmatrix import graphics
|
||||
import time
|
||||
|
||||
|
||||
class GraphicsTest(SampleBase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(GraphicsTest, self).__init__(*args, **kwargs)
|
||||
|
||||
def run(self):
|
||||
canvas = self.matrix
|
||||
font = graphics.Font()
|
||||
font.LoadFont("../../../fonts/7x13.bdf")
|
||||
|
||||
red = graphics.Color(255, 0, 0)
|
||||
graphics.DrawLine(canvas, 5, 5, 22, 13, red)
|
||||
|
||||
green = graphics.Color(0, 255, 0)
|
||||
graphics.DrawCircle(canvas, 15, 15, 10, green)
|
||||
|
||||
blue = graphics.Color(0, 0, 255)
|
||||
graphics.DrawText(canvas, font, 2, 10, blue, "Text")
|
||||
|
||||
time.sleep(10) # show display for 10 seconds before exit
|
||||
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
graphics_test = GraphicsTest()
|
||||
if (not graphics_test.process()):
|
||||
graphics_test.print_help()
|
||||
39
depends/rpi-rgb-led-matrix/bindings/python/samples/grayscale-block.py
Executable file
39
depends/rpi-rgb-led-matrix/bindings/python/samples/grayscale-block.py
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python
|
||||
from samplebase import SampleBase
|
||||
import time
|
||||
|
||||
|
||||
class GrayscaleBlock(SampleBase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(GrayscaleBlock, self).__init__(*args, **kwargs)
|
||||
|
||||
def run(self):
|
||||
sub_blocks = 16
|
||||
width = self.matrix.width
|
||||
height = self.matrix.height
|
||||
x_step = max(1, width / sub_blocks)
|
||||
y_step = max(1, height / sub_blocks)
|
||||
count = 0
|
||||
|
||||
while True:
|
||||
for y in range(0, height):
|
||||
for x in range(0, width):
|
||||
c = sub_blocks * int(y / y_step) + int(x / x_step)
|
||||
if count % 4 == 0:
|
||||
self.matrix.SetPixel(x, y, c, c, c)
|
||||
elif count % 4 == 1:
|
||||
self.matrix.SetPixel(x, y, c, 0, 0)
|
||||
elif count % 4 == 2:
|
||||
self.matrix.SetPixel(x, y, 0, c, 0)
|
||||
elif count % 4 == 3:
|
||||
self.matrix.SetPixel(x, y, 0, 0, c)
|
||||
|
||||
count += 1
|
||||
time.sleep(2)
|
||||
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
grayscale_block = GrayscaleBlock()
|
||||
if (not grayscale_block.process()):
|
||||
grayscale_block.print_help()
|
||||
48
depends/rpi-rgb-led-matrix/bindings/python/samples/image-draw.py
Executable file
48
depends/rpi-rgb-led-matrix/bindings/python/samples/image-draw.py
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# (This is an example similar to an example from the Adafruit fork
|
||||
# to show the similarities. Most important difference currently is, that
|
||||
# this library wants RGB mode.)
|
||||
#
|
||||
# A more complex RGBMatrix example works with the Python Imaging Library,
|
||||
# demonstrating a few graphics primitives and image loading.
|
||||
# Note that PIL graphics do not have an immediate effect on the display --
|
||||
# image is drawn into a separate buffer, which is then copied to the matrix
|
||||
# using the SetImage() function (see examples below).
|
||||
# Requires rgbmatrix.so present in the same directory.
|
||||
|
||||
# PIL Image module (create or load images) is explained here:
|
||||
# http://effbot.org/imagingbook/image.htm
|
||||
# PIL ImageDraw module (draw shapes to images) explained here:
|
||||
# http://effbot.org/imagingbook/imagedraw.htm
|
||||
|
||||
from PIL import Image
|
||||
from PIL import ImageDraw
|
||||
import time
|
||||
from rgbmatrix import RGBMatrix, RGBMatrixOptions
|
||||
|
||||
# Configuration for the matrix
|
||||
options = RGBMatrixOptions()
|
||||
options.rows = 32
|
||||
options.chain_length = 1
|
||||
options.parallel = 1
|
||||
options.hardware_mapping = 'regular' # If you have an Adafruit HAT: 'adafruit-hat'
|
||||
|
||||
matrix = RGBMatrix(options = options)
|
||||
|
||||
# RGB example w/graphics prims.
|
||||
# Note, only "RGB" mode is supported currently.
|
||||
image = Image.new("RGB", (32, 32)) # Can be larger than matrix if wanted!!
|
||||
draw = ImageDraw.Draw(image) # Declare Draw instance before prims
|
||||
# Draw some shapes into image (no immediate effect on matrix)...
|
||||
draw.rectangle((0, 0, 31, 31), fill=(0, 0, 0), outline=(0, 0, 255))
|
||||
draw.line((0, 0, 31, 31), fill=(255, 0, 0))
|
||||
draw.line((0, 31, 31, 0), fill=(0, 255, 0))
|
||||
|
||||
# Then scroll image across matrix...
|
||||
for n in range(-32, 33): # Start off top-left, move off bottom-right
|
||||
matrix.Clear()
|
||||
matrix.SetImage(image, n, n)
|
||||
time.sleep(0.05)
|
||||
|
||||
matrix.Clear()
|
||||
40
depends/rpi-rgb-led-matrix/bindings/python/samples/image-scroller.py
Executable file
40
depends/rpi-rgb-led-matrix/bindings/python/samples/image-scroller.py
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env python
|
||||
import time
|
||||
from samplebase import SampleBase
|
||||
from PIL import Image
|
||||
|
||||
|
||||
class ImageScroller(SampleBase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ImageScroller, self).__init__(*args, **kwargs)
|
||||
self.parser.add_argument("-i", "--image", help="The image to display", default="../../../examples-api-use/runtext.ppm")
|
||||
|
||||
def run(self):
|
||||
if not 'image' in self.__dict__:
|
||||
self.image = Image.open(self.args.image).convert('RGB')
|
||||
self.image.resize((self.matrix.width, self.matrix.height), Image.ANTIALIAS)
|
||||
|
||||
double_buffer = self.matrix.CreateFrameCanvas()
|
||||
img_width, img_height = self.image.size
|
||||
|
||||
# let's scroll
|
||||
xpos = 0
|
||||
while True:
|
||||
xpos += 1
|
||||
if (xpos > img_width):
|
||||
xpos = 0
|
||||
|
||||
double_buffer.SetImage(self.image, -xpos)
|
||||
double_buffer.SetImage(self.image, -xpos + img_width)
|
||||
|
||||
double_buffer = self.matrix.SwapOnVSync(double_buffer)
|
||||
time.sleep(0.01)
|
||||
|
||||
# Main function
|
||||
# e.g. call with
|
||||
# sudo ./image-scroller.py --chain=4
|
||||
# if you have a chain of four
|
||||
if __name__ == "__main__":
|
||||
image_scroller = ImageScroller()
|
||||
if (not image_scroller.process()):
|
||||
image_scroller.print_help()
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python
|
||||
import time
|
||||
import sys
|
||||
|
||||
from rgbmatrix import RGBMatrix, RGBMatrixOptions
|
||||
from PIL import Image
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
sys.exit("Require an image argument")
|
||||
else:
|
||||
image_file = sys.argv[1]
|
||||
|
||||
image = Image.open(image_file)
|
||||
|
||||
# Configuration for the matrix
|
||||
options = RGBMatrixOptions()
|
||||
options.rows = 32
|
||||
options.chain_length = 1
|
||||
options.parallel = 1
|
||||
options.hardware_mapping = 'regular' # If you have an Adafruit HAT: 'adafruit-hat'
|
||||
|
||||
matrix = RGBMatrix(options = options)
|
||||
|
||||
# Make image fit our screen.
|
||||
image.thumbnail((matrix.width, matrix.height), Image.ANTIALIAS)
|
||||
|
||||
matrix.SetImage(image.convert('RGB'))
|
||||
|
||||
try:
|
||||
print("Press CTRL-C to stop.")
|
||||
while True:
|
||||
time.sleep(100)
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(0)
|
||||
36
depends/rpi-rgb-led-matrix/bindings/python/samples/pulsing-brightness.py
Executable file
36
depends/rpi-rgb-led-matrix/bindings/python/samples/pulsing-brightness.py
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python
|
||||
from samplebase import SampleBase
|
||||
|
||||
|
||||
class GrayscaleBlock(SampleBase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(GrayscaleBlock, self).__init__(*args, **kwargs)
|
||||
|
||||
def run(self):
|
||||
max_brightness = self.matrix.brightness
|
||||
count = 0
|
||||
c = 255
|
||||
|
||||
while (True):
|
||||
if self.matrix.brightness < 1:
|
||||
self.matrix.brightness = max_brightness
|
||||
count += 1
|
||||
else:
|
||||
self.matrix.brightness -= 1
|
||||
|
||||
if count % 4 == 0:
|
||||
self.matrix.Fill(c, 0, 0)
|
||||
elif count % 4 == 1:
|
||||
self.matrix.Fill(0, c, 0)
|
||||
elif count % 4 == 2:
|
||||
self.matrix.Fill(0, 0, c)
|
||||
elif count % 4 == 3:
|
||||
self.matrix.Fill(c, c, c)
|
||||
|
||||
self.usleep(20 * 1000)
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
grayscale_block = GrayscaleBlock()
|
||||
if (not grayscale_block.process()):
|
||||
grayscale_block.print_help()
|
||||
42
depends/rpi-rgb-led-matrix/bindings/python/samples/pulsing-colors.py
Executable file
42
depends/rpi-rgb-led-matrix/bindings/python/samples/pulsing-colors.py
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env python
|
||||
from samplebase import SampleBase
|
||||
|
||||
|
||||
class PulsingColors(SampleBase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PulsingColors, self).__init__(*args, **kwargs)
|
||||
|
||||
def run(self):
|
||||
self.offscreen_canvas = self.matrix.CreateFrameCanvas()
|
||||
continuum = 0
|
||||
|
||||
while True:
|
||||
self.usleep(5 * 1000)
|
||||
continuum += 1
|
||||
continuum %= 3 * 255
|
||||
|
||||
red = 0
|
||||
green = 0
|
||||
blue = 0
|
||||
|
||||
if continuum <= 255:
|
||||
c = continuum
|
||||
blue = 255 - c
|
||||
red = c
|
||||
elif continuum > 255 and continuum <= 511:
|
||||
c = continuum - 256
|
||||
red = 255 - c
|
||||
green = c
|
||||
else:
|
||||
c = continuum - 512
|
||||
green = 255 - c
|
||||
blue = c
|
||||
|
||||
self.offscreen_canvas.Fill(red, green, blue)
|
||||
self.offscreen_canvas = self.matrix.SwapOnVSync(self.offscreen_canvas)
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
pulsing_colors = PulsingColors()
|
||||
if (not pulsing_colors.process()):
|
||||
pulsing_colors.print_help()
|
||||
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python
|
||||
from samplebase import SampleBase
|
||||
import math
|
||||
|
||||
|
||||
def scale_col(val, lo, hi):
|
||||
if val < lo:
|
||||
return 0
|
||||
if val > hi:
|
||||
return 255
|
||||
return 255 * (val - lo) / (hi - lo)
|
||||
|
||||
|
||||
def rotate(x, y, sin, cos):
|
||||
return x * cos - y * sin, x * sin + y * cos
|
||||
|
||||
|
||||
class RotatingBlockGenerator(SampleBase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(RotatingBlockGenerator, self).__init__(*args, **kwargs)
|
||||
|
||||
def run(self):
|
||||
cent_x = self.matrix.width / 2
|
||||
cent_y = self.matrix.height / 2
|
||||
|
||||
rotate_square = min(self.matrix.width, self.matrix.height) * 1.41
|
||||
min_rotate = cent_x - rotate_square / 2
|
||||
max_rotate = cent_x + rotate_square / 2
|
||||
|
||||
display_square = min(self.matrix.width, self.matrix.height) * 0.7
|
||||
min_display = cent_x - display_square / 2
|
||||
max_display = cent_x + display_square / 2
|
||||
|
||||
deg_to_rad = 2 * 3.14159265 / 360
|
||||
rotation = 0
|
||||
|
||||
# Pre calculate colors
|
||||
col_table = []
|
||||
for x in range(int(min_rotate), int(max_rotate)):
|
||||
col_table.insert(x, scale_col(x, min_display, max_display))
|
||||
|
||||
offset_canvas = self.matrix.CreateFrameCanvas()
|
||||
|
||||
while True:
|
||||
rotation += 1
|
||||
rotation %= 360
|
||||
|
||||
# calculate sin and cos once for each frame
|
||||
angle = rotation * deg_to_rad
|
||||
sin = math.sin(angle)
|
||||
cos = math.cos(angle)
|
||||
|
||||
for x in range(int(min_rotate), int(max_rotate)):
|
||||
for y in range(int(min_rotate), int(max_rotate)):
|
||||
# Our rotate center is always offset by cent_x
|
||||
rot_x, rot_y = rotate(x - cent_x, y - cent_x, sin, cos)
|
||||
|
||||
if x >= min_display and x < max_display and y >= min_display and y < max_display:
|
||||
x_col = col_table[x]
|
||||
y_col = col_table[y]
|
||||
offset_canvas.SetPixel(rot_x + cent_x, rot_y + cent_y, x_col, 255 - y_col, y_col)
|
||||
else:
|
||||
offset_canvas.SetPixel(rot_x + cent_x, rot_y + cent_y, 0, 0, 0)
|
||||
|
||||
offset_canvas = self.matrix.SwapOnVSync(offset_canvas)
|
||||
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
rotating_block_generator = RotatingBlockGenerator()
|
||||
if (not rotating_block_generator.process()):
|
||||
rotating_block_generator.print_help()
|
||||
36
depends/rpi-rgb-led-matrix/bindings/python/samples/runtext.py
Executable file
36
depends/rpi-rgb-led-matrix/bindings/python/samples/runtext.py
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python
|
||||
# Display a runtext with double-buffering.
|
||||
from samplebase import SampleBase
|
||||
from rgbmatrix import graphics
|
||||
import time
|
||||
|
||||
|
||||
class RunText(SampleBase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(RunText, self).__init__(*args, **kwargs)
|
||||
self.parser.add_argument("-t", "--text", help="The text to scroll on the RGB LED panel", default="Hello world!")
|
||||
|
||||
def run(self):
|
||||
offscreen_canvas = self.matrix.CreateFrameCanvas()
|
||||
font = graphics.Font()
|
||||
font.LoadFont("../../../fonts/7x13.bdf")
|
||||
textColor = graphics.Color(255, 255, 0)
|
||||
pos = offscreen_canvas.width
|
||||
my_text = self.args.text
|
||||
|
||||
while True:
|
||||
offscreen_canvas.Clear()
|
||||
len = graphics.DrawText(offscreen_canvas, font, pos, 10, textColor, my_text)
|
||||
pos -= 1
|
||||
if (pos + len < 0):
|
||||
pos = offscreen_canvas.width
|
||||
|
||||
time.sleep(0.05)
|
||||
offscreen_canvas = self.matrix.SwapOnVSync(offscreen_canvas)
|
||||
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
run_text = RunText()
|
||||
if (not run_text.process()):
|
||||
run_text.print_help()
|
||||
81
depends/rpi-rgb-led-matrix/bindings/python/samples/samplebase.py
Executable file
81
depends/rpi-rgb-led-matrix/bindings/python/samples/samplebase.py
Executable file
@@ -0,0 +1,81 @@
|
||||
import argparse
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/..'))
|
||||
from rgbmatrix import RGBMatrix, RGBMatrixOptions
|
||||
|
||||
|
||||
class SampleBase(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.parser = argparse.ArgumentParser()
|
||||
|
||||
self.parser.add_argument("-r", "--led-rows", action="store", help="Display rows. 16 for 16x32, 32 for 32x32. Default: 32", default=32, type=int)
|
||||
self.parser.add_argument("--led-cols", action="store", help="Panel columns. Typically 32 or 64. (Default: 32)", default=32, type=int)
|
||||
self.parser.add_argument("-c", "--led-chain", action="store", help="Daisy-chained boards. Default: 1.", default=1, type=int)
|
||||
self.parser.add_argument("-P", "--led-parallel", action="store", help="For Plus-models or RPi2: parallel chains. 1..3. Default: 1", default=1, type=int)
|
||||
self.parser.add_argument("-p", "--led-pwm-bits", action="store", help="Bits used for PWM. Something between 1..11. Default: 11", default=11, type=int)
|
||||
self.parser.add_argument("-b", "--led-brightness", action="store", help="Sets brightness level. Default: 100. Range: 1..100", default=100, type=int)
|
||||
self.parser.add_argument("-m", "--led-gpio-mapping", help="Hardware Mapping: regular, adafruit-hat, adafruit-hat-pwm" , choices=['regular', 'regular-pi1', 'adafruit-hat', 'adafruit-hat-pwm'], type=str)
|
||||
self.parser.add_argument("--led-scan-mode", action="store", help="Progressive or interlaced scan. 0 Progressive, 1 Interlaced (default)", default=1, choices=range(2), type=int)
|
||||
self.parser.add_argument("--led-pwm-lsb-nanoseconds", action="store", help="Base time-unit for the on-time in the lowest significant bit in nanoseconds. Default: 130", default=130, type=int)
|
||||
self.parser.add_argument("--led-show-refresh", action="store_true", help="Shows the current refresh rate of the LED panel")
|
||||
self.parser.add_argument("--led-slowdown-gpio", action="store", help="Slow down writing to GPIO. Range: 0..4. Default: 1", default=1, type=int)
|
||||
self.parser.add_argument("--led-no-hardware-pulse", action="store", help="Don't use hardware pin-pulse generation")
|
||||
self.parser.add_argument("--led-rgb-sequence", action="store", help="Switch if your matrix has led colors swapped. Default: RGB", default="RGB", type=str)
|
||||
self.parser.add_argument("--led-pixel-mapper", action="store", help="Apply pixel mappers. e.g \"Rotate:90\"", default="", type=str)
|
||||
self.parser.add_argument("--led-row-addr-type", action="store", help="0 = default; 1=AB-addressed panels; 2=row direct; 3=ABC-addressed panels; 4 = ABC Shift + DE direct", default=0, type=int, choices=[0,1,2,3,4])
|
||||
self.parser.add_argument("--led-multiplexing", action="store", help="Multiplexing type: 0=direct; 1=strip; 2=checker; 3=spiral; 4=ZStripe; 5=ZnMirrorZStripe; 6=coreman; 7=Kaler2Scan; 8=ZStripeUneven... (Default: 0)", default=0, type=int)
|
||||
self.parser.add_argument("--led-panel-type", action="store", help="Needed to initialize special panels. Supported: 'FM6126A'", default="", type=str)
|
||||
self.parser.add_argument("--led-no-drop-privs", dest="drop_privileges", help="Don't drop privileges from 'root' after initializing the hardware.", action='store_false')
|
||||
self.parser.set_defaults(drop_privileges=True)
|
||||
|
||||
def usleep(self, value):
|
||||
time.sleep(value / 1000000.0)
|
||||
|
||||
def run(self):
|
||||
print("Running")
|
||||
|
||||
def process(self):
|
||||
self.args = self.parser.parse_args()
|
||||
|
||||
options = RGBMatrixOptions()
|
||||
|
||||
if self.args.led_gpio_mapping != None:
|
||||
options.hardware_mapping = self.args.led_gpio_mapping
|
||||
options.rows = self.args.led_rows
|
||||
options.cols = self.args.led_cols
|
||||
options.chain_length = self.args.led_chain
|
||||
options.parallel = self.args.led_parallel
|
||||
options.row_address_type = self.args.led_row_addr_type
|
||||
options.multiplexing = self.args.led_multiplexing
|
||||
options.pwm_bits = self.args.led_pwm_bits
|
||||
options.brightness = self.args.led_brightness
|
||||
options.pwm_lsb_nanoseconds = self.args.led_pwm_lsb_nanoseconds
|
||||
options.led_rgb_sequence = self.args.led_rgb_sequence
|
||||
options.pixel_mapper_config = self.args.led_pixel_mapper
|
||||
options.panel_type = self.args.led_panel_type
|
||||
|
||||
|
||||
if self.args.led_show_refresh:
|
||||
options.show_refresh_rate = 1
|
||||
|
||||
if self.args.led_slowdown_gpio != None:
|
||||
options.gpio_slowdown = self.args.led_slowdown_gpio
|
||||
if self.args.led_no_hardware_pulse:
|
||||
options.disable_hardware_pulsing = True
|
||||
if not self.args.drop_privileges:
|
||||
options.drop_privileges=False
|
||||
|
||||
self.matrix = RGBMatrix(options = options)
|
||||
|
||||
try:
|
||||
# Start loop
|
||||
print("Press CTRL-C to stop sample")
|
||||
self.run()
|
||||
except KeyboardInterrupt:
|
||||
print("Exiting\n")
|
||||
sys.exit(0)
|
||||
|
||||
return True
|
||||
30
depends/rpi-rgb-led-matrix/bindings/python/samples/simple-square.py
Executable file
30
depends/rpi-rgb-led-matrix/bindings/python/samples/simple-square.py
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python
|
||||
from samplebase import SampleBase
|
||||
|
||||
|
||||
class SimpleSquare(SampleBase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SimpleSquare, self).__init__(*args, **kwargs)
|
||||
|
||||
def run(self):
|
||||
offset_canvas = self.matrix.CreateFrameCanvas()
|
||||
while True:
|
||||
for x in range(0, self.matrix.width):
|
||||
offset_canvas.SetPixel(x, x, 255, 255, 255)
|
||||
offset_canvas.SetPixel(offset_canvas.height - 1 - x, x, 255, 0, 255)
|
||||
|
||||
for x in range(0, offset_canvas.width):
|
||||
offset_canvas.SetPixel(x, 0, 255, 0, 0)
|
||||
offset_canvas.SetPixel(x, offset_canvas.height - 1, 255, 255, 0)
|
||||
|
||||
for y in range(0, offset_canvas.height):
|
||||
offset_canvas.SetPixel(0, y, 0, 0, 255)
|
||||
offset_canvas.SetPixel(offset_canvas.width - 1, y, 0, 255, 0)
|
||||
offset_canvas = self.matrix.SwapOnVSync(offset_canvas)
|
||||
|
||||
|
||||
# Main function
|
||||
if __name__ == "__main__":
|
||||
simple_square = SimpleSquare()
|
||||
if (not simple_square.process()):
|
||||
simple_square.print_help()
|
||||
33
depends/rpi-rgb-led-matrix/bindings/python/setup.py
Normal file
33
depends/rpi-rgb-led-matrix/bindings/python/setup.py
Normal file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/python
|
||||
from distutils.core import setup, Extension
|
||||
|
||||
core_ext = Extension(
|
||||
name = 'core',
|
||||
sources = ['rgbmatrix/core.cpp'],
|
||||
include_dirs = ['../../include'],
|
||||
library_dirs = ['../../lib'],
|
||||
libraries = ['rgbmatrix'],
|
||||
extra_compile_args = ["-O3", "-Wall"],
|
||||
language = 'c++'
|
||||
)
|
||||
|
||||
graphics_ext = Extension(
|
||||
name = 'graphics',
|
||||
sources = ['rgbmatrix/graphics.cpp'],
|
||||
include_dirs = ['../../include'],
|
||||
library_dirs = ['../../lib'],
|
||||
libraries = ['rgbmatrix'],
|
||||
extra_compile_args = ["-O3", "-Wall"],
|
||||
language = 'c++'
|
||||
)
|
||||
|
||||
setup(
|
||||
name = 'rgbmatrix',
|
||||
version = '0.0.1',
|
||||
author = 'Christoph Friedrich',
|
||||
author_email = 'christoph.friedrich@vonaffenfels.de',
|
||||
classifiers = ['Development Status :: 3 - Alpha'],
|
||||
ext_package = 'rgbmatrix',
|
||||
ext_modules = [core_ext, graphics_ext],
|
||||
packages = ['rgbmatrix']
|
||||
)
|
||||
7
depends/rpi-rgb-led-matrix/examples-api-use/.gitignore
vendored
Normal file
7
depends/rpi-rgb-led-matrix/examples-api-use/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
demo
|
||||
minimal-example
|
||||
text-example
|
||||
c-example
|
||||
clock
|
||||
scrolling-text-example
|
||||
ledcat
|
||||
60
depends/rpi-rgb-led-matrix/examples-api-use/Makefile
Normal file
60
depends/rpi-rgb-led-matrix/examples-api-use/Makefile
Normal file
@@ -0,0 +1,60 @@
|
||||
CFLAGS=-Wall -O3 -g -Wextra -Wno-unused-parameter
|
||||
CXXFLAGS=$(CFLAGS)
|
||||
OBJECTS=demo-main.o minimal-example.o c-example.o text-example.o scrolling-text-example.o clock.o ledcat.o input-example.o pixel-mover.o
|
||||
BINARIES=demo minimal-example c-example text-example scrolling-text-example clock ledcat input-example pixel-mover
|
||||
|
||||
# Where our library resides. You mostly only need to change the
|
||||
# RGB_LIB_DISTRIBUTION, this is where the library is checked out.
|
||||
RGB_LIB_DISTRIBUTION=..
|
||||
RGB_INCDIR=$(RGB_LIB_DISTRIBUTION)/include
|
||||
RGB_LIBDIR=$(RGB_LIB_DISTRIBUTION)/lib
|
||||
RGB_LIBRARY_NAME=rgbmatrix
|
||||
RGB_LIBRARY=$(RGB_LIBDIR)/lib$(RGB_LIBRARY_NAME).a
|
||||
LDFLAGS+=-L$(RGB_LIBDIR) -l$(RGB_LIBRARY_NAME) -lrt -lm -lpthread
|
||||
|
||||
# To compile image-example
|
||||
MAGICK_CXXFLAGS?=$(shell GraphicsMagick++-config --cppflags --cxxflags)
|
||||
MAGICK_LDFLAGS?=$(shell GraphicsMagick++-config --ldflags --libs)
|
||||
|
||||
all : $(BINARIES)
|
||||
|
||||
$(RGB_LIBRARY): FORCE
|
||||
$(MAKE) -C $(RGB_LIBDIR)
|
||||
|
||||
demo : demo-main.o $(RGB_LIBRARY)
|
||||
$(CXX) $< -o $@ $(LDFLAGS)
|
||||
|
||||
minimal-example : minimal-example.o
|
||||
input-example : input-example.o
|
||||
text-example: text-example.o
|
||||
scrolling-text-example : scrolling-text-example.o
|
||||
clock : clock.o
|
||||
ledcat : ledcat.o
|
||||
pixel-mover : pixel-mover.o
|
||||
|
||||
# All the binaries that have the same name as the object file.q
|
||||
% : %.o $(RGB_LIBRARY)
|
||||
$(CXX) $< -o $@ $(LDFLAGS)
|
||||
|
||||
image-example.o : image-example.cc
|
||||
$(CXX) -I$(RGB_INCDIR) $(CXXFLAGS) $(MAGICK_CXXFLAGS) -c -o $@ $<
|
||||
|
||||
image-example: image-example.o $(RGB_LIBRARY)
|
||||
$(CXX) $< -o $@ $(LDFLAGS) $(MAGICK_LDFLAGS)
|
||||
|
||||
# Since the C example uses the C++ library underneath, which depends on C++
|
||||
# runtime stuff, you still have to also link -lstdc++
|
||||
c-example : c-example.o $(RGB_LIBRARY)
|
||||
$(CC) $< -o $@ $(LDFLAGS) -lstdc++
|
||||
|
||||
%.o : %.cc
|
||||
$(CXX) -I$(RGB_INCDIR) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
%.o : %.c
|
||||
$(CC) -I$(RGB_INCDIR) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f $(OBJECTS) $(BINARIES)
|
||||
|
||||
FORCE:
|
||||
.PHONY: FORCE
|
||||
461
depends/rpi-rgb-led-matrix/examples-api-use/README.md
Normal file
461
depends/rpi-rgb-led-matrix/examples-api-use/README.md
Normal file
@@ -0,0 +1,461 @@
|
||||
Running some demos
|
||||
------------------
|
||||
Let's start by running some demos, then we can dive into code. The
|
||||
[demo-main.cc](demo-main.cc) has some testing demos. Via command line flags,
|
||||
you can choose the display type you have (16x32 or 32x32), and how many you
|
||||
have chained and paralleled. For detailed description of these flags see the
|
||||
[main README section](../README.md#changing-parameters-via-command-line-flags)
|
||||
about it.
|
||||
|
||||
```
|
||||
$ make
|
||||
$ sudo ./demo
|
||||
usage: ./demo <options> -D <demo-nr> [optional parameter]
|
||||
Options:
|
||||
-D <demo-nr> : Always needs to be set
|
||||
--led-gpio-mapping=<name> : Name of GPIO mapping used. Default "regular"
|
||||
--led-rows=<rows> : Panel rows. Typically 8, 16, 32 or 64. (Default: 32).
|
||||
--led-cols=<cols> : Panel columns. Typically 32 or 64. (Default: 32).
|
||||
--led-chain=<chained> : Number of daisy-chained panels. (Default: 1).
|
||||
--led-parallel=<parallel> : Parallel chains. range=1..3 (Default: 1).
|
||||
--led-multiplexing=<0..17> : Mux type: 0=direct; 1=Stripe; 2=Checkered; 3=Spiral; 4=ZStripe; 5=ZnMirrorZStripe; 6=coreman; 7=Kaler2Scan; 8=ZStripeUneven; 9=P10-128x4-Z; 10=QiangLiQ8; 11=InversedZStripe; 12=P10Outdoor1R1G1-1; 13=P10Outdoor1R1G1-2; 14=P10Outdoor1R1G1-3; 15=P10CoremanMapper; 16=P8Outdoor1R1G1; 17=FlippedStripe (Default: 0)
|
||||
--led-pixel-mapper : Semicolon-separated list of pixel-mappers to arrange pixels.
|
||||
Optional params after a colon e.g. "U-mapper;Rotate:90"
|
||||
Available: "Mirror", "Rotate", "U-mapper", "V-mapper". Default: ""
|
||||
--led-pwm-bits=<1..11> : PWM bits (Default: 11).
|
||||
--led-brightness=<percent>: Brightness in percent (Default: 100).
|
||||
--led-scan-mode=<0..1> : 0 = progressive; 1 = interlaced (Default: 0).
|
||||
--led-row-addr-type=<0..4>: 0 = default; 1 = AB-addressed panels; 2 = direct row select; 3 = ABC-addressed panels; 4 = ABC Shift + DE direct (Default: 0).
|
||||
--led-show-refresh : Show refresh rate.
|
||||
--led-limit-refresh=<Hz> : Limit refresh rate to this frequency in Hz. Useful to keep a
|
||||
constant refresh rate on loaded system. 0=no limit. Default: 0
|
||||
--led-inverse : Switch if your matrix has inverse colors on.
|
||||
--led-rgb-sequence : Switch if your matrix has led colors swapped (Default: "RGB")
|
||||
--led-pwm-lsb-nanoseconds : PWM Nanoseconds for LSB (Default: 130)
|
||||
--led-pwm-dither-bits=<0..2> : Time dithering of lower bits (Default: 0)
|
||||
--led-no-hardware-pulse : Don't use hardware pin-pulse generation.
|
||||
--led-panel-type=<name> : Needed to initialize special panels. Supported: 'FM6126A', 'FM6127'
|
||||
--led-slowdown-gpio=<0..4>: Slowdown GPIO. Needed for faster Pis/slower panels (Default: 1).
|
||||
--led-daemon : Make the process run in the background as daemon.
|
||||
--led-no-drop-privs : Don't drop privileges from 'root' after initializing the hardware.
|
||||
Demos, choosen with -D
|
||||
0 - some rotating square
|
||||
1 - forward scrolling an image (-m <scroll-ms>)
|
||||
2 - backward scrolling an image (-m <scroll-ms>)
|
||||
3 - test image: a square
|
||||
4 - Pulsing color
|
||||
5 - Grayscale Block
|
||||
6 - Abelian sandpile model (-m <time-step-ms>)
|
||||
7 - Conway's game of life (-m <time-step-ms>)
|
||||
8 - Langton's ant (-m <time-step-ms>)
|
||||
9 - Volume bars (-m <time-step-ms>)
|
||||
10 - Evolution of color (-m <time-step-ms>)
|
||||
11 - Brightness pulse generator
|
||||
Example:
|
||||
./demo -D 1 runtext.ppm
|
||||
Scrolls the runtext until Ctrl-C is pressed
|
||||
```
|
||||
|
||||
To run the actual demos, you need to run this as root so that the
|
||||
GPIO pins can be accessed; as soon as that established, the program will drop
|
||||
the privileges.
|
||||
|
||||
Here is how demo '1' looks. It requires a ppm (type raw) with a height of
|
||||
32 pixel - it is infinitely scrolled over the screen; for
|
||||
convenience, there is a little runtext.ppm example included:
|
||||
|
||||
$ sudo ./demo -D 1 runtext.ppm
|
||||
|
||||
Here is a video of how it looks
|
||||
[![Runtext][run-vid]](http://youtu.be/OJvEWyvO4ro)
|
||||
|
||||
Other Examples
|
||||
--------------
|
||||
|
||||
There are a few other examples that you can use as starting point for your
|
||||
own exploration of the API. If you just type `make` in this directory, the
|
||||
Makefile will build all of these, so they are ready to use. Some examples
|
||||
need BDF fonts, of which there are a few provided in [../fonts](../fonts).
|
||||
|
||||
Some of these example programs are described in more detail further down this
|
||||
page.
|
||||
|
||||
* [minimal-example](./minimal-example.cc) Good to get started with the API
|
||||
* [image-example](./image-example.cc) How to show an image (requires to install the graphics magic library, see in the header of that demo)
|
||||
* [text-example](./text-example.cc) Reads text from stdin and displays it.
|
||||
* [scrolling-text-example](./scrolling-text-example.cc) Scrolls a text
|
||||
given on the command-line.
|
||||
* [clock](./clock.cc) Shows a clock with choosable date format string in
|
||||
one or multiple lines.
|
||||
* [input-example](./input-example.cc) Example how to use the LED-Matrix but
|
||||
also read inputs from free GPIO-pins. Needed if you build some interactive
|
||||
piece.
|
||||
* [ledcat](./ledcat.cc) LED-cat compatible reading of pixels from stdin.
|
||||
* [pixel-mover](./pixel-mover.cc) Displays pixel on the display
|
||||
and it's expected position on the terminal. Helpful for testing panels and
|
||||
figuring out new multiplexing mappings.
|
||||
Shows single dot or leaves a trail with length passed with `-t` option
|
||||
(think of 'snake').
|
||||
Can move around the pixel with W=Up, S=Down, A=Left, D=Right keys.
|
||||
|
||||
Using the API
|
||||
-------------
|
||||
While there is the demo program and the [utilities](../utils), this code can
|
||||
be used independently as a library to be used in your own programs.
|
||||
The includes are in `include/`, the library to link is built
|
||||
in `lib/`. This is a C++ also with C bindings. There is also a
|
||||
[Python](../bindings/python) and [c#](../bindings/c%23) bindings.
|
||||
|
||||
Getting started
|
||||
---------------
|
||||
The relevant part to start with is to look at
|
||||
[led-matrix.h](../include/led-matrix.h).
|
||||
|
||||
You can would typically use the `RGBMatrix::CreateFromFlags()` factory to
|
||||
create an RGBMatrix and then go from there.
|
||||
|
||||
```C++
|
||||
#include "led-matrix.h"
|
||||
|
||||
using rgb_matrix::RGBMatrix;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// Set some defaults
|
||||
RGBMatrix::Options my_defaults;
|
||||
my_defaults.hardware_mapping = "regular"; // or e.g. "adafruit-hat" or "adafruit-hat-pwm"
|
||||
my_defaults.chain_length = 3;
|
||||
my_defaults.show_refresh_rate = true;
|
||||
rgb_matrix::RuntimeOptions runtime_defaults;
|
||||
// If you drop privileges, the root user you start the program with
|
||||
// to be able to initialize the hardware will be switched to an unprivileged
|
||||
// user to minimize a potential security attack surface.
|
||||
runtime_defaults.drop_privileges = 1;
|
||||
RGBMatrix *matrix = RGBMatrix::CreateFromFlags(&argc, &argv,
|
||||
&my_defaults,
|
||||
&runtime_defaults);
|
||||
if (matrix == NULL) {
|
||||
PrintMatrixFlags(stderr, my_defaults, runtime_defaults);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// matrix->ApplyPixelMapper(...); // Optional
|
||||
|
||||
// Do your own command line handling with the remaining options.
|
||||
|
||||
// .. now use matrix
|
||||
|
||||
delete matrix; // Make sure to delete it in the end.
|
||||
}
|
||||
```
|
||||
|
||||
The `RGBMatrix` is essentially a canvas, it provides some basic functionality
|
||||
such as `SetPixel()`, `Fill()` or `Clear()`. If you want to do more, you
|
||||
might be interested in functions provided in the
|
||||
[graphics.h](../include/graphics.h) header.
|
||||
|
||||
If you have animations, you might be interested in double-buffering. There is
|
||||
a way to create new canvases with `CreateFrameCanvas()`, and then use
|
||||
`SwapOnVSync()` to change the content atomically. See API documentation for
|
||||
details.
|
||||
|
||||
Start with the [minimal-example.cc](./minimal-example.cc) to start.
|
||||
|
||||
If you are interested in drawing text and the font drawing functions in
|
||||
graphics.h, have a look at the [text example](./text-example.cc):
|
||||
|
||||
```
|
||||
sudo ./text-example -f ../fonts/8x13.bdf
|
||||
hello
|
||||
```
|
||||
|
||||
<img src="../img/text-no-ghosting.jpg" height="100px">
|
||||
|
||||
How about a clock ?
|
||||
|
||||
```
|
||||
sudo ./clock -f ../fonts/7x13.bdf --led-chain=2 -d "%A" -d "%H:%M:%S"
|
||||
```
|
||||
<img src="../img/time-display.jpg" height="100px">
|
||||
|
||||
Fonts are in a human readable and editbable `*.bdf` format. There are some
|
||||
public domain fonts available in the [`../fonts/`](../fonts) directory. Any
|
||||
other fonts you might want to use or scale to the size you need can be
|
||||
converted to a BDF format (either with a font editor or the [otf2bdf] tool).
|
||||
|
||||
Here is an example how you could create a 30pixel high BDF font from some
|
||||
TrueType font:
|
||||
|
||||
```bash
|
||||
otf2bdf -v -o myfont.bdf -r 72 -p 30 /path/to/font-Bold.ttf
|
||||
```
|
||||
|
||||
Integrating in your own application
|
||||
-----------------------------------
|
||||
Until this library shows up in your favorite Linux distribution, you can just
|
||||
include the library via github; it is pretty easy to be up-to-date.
|
||||
|
||||
I suggest to add this code as a sub-module in your git repository. That way
|
||||
you can use that particular version and easily update it if there are changes:
|
||||
|
||||
git submodule add https://github.com/hzeller/rpi-rgb-led-matrix.git matrix
|
||||
|
||||
(Read more about how to use [submodules in git][git-submodules])
|
||||
|
||||
This will check out the repository in a subdirectory `matrix/`.
|
||||
The library to build would be in directory `matrix/lib`, so let's hook that
|
||||
into your toplevel Makefile.
|
||||
I suggest to set up some variables like this; you only need to change the
|
||||
location `RGB_LIB_DISTRIBUTION` is pointing to; in the sub-module example, this
|
||||
was the `matrix` directory:
|
||||
|
||||
RGB_LIB_DISTRIBUTION=matrix
|
||||
RGB_INCDIR=$(RGB_LIB_DISTRIBUTION)/include
|
||||
RGB_LIBDIR=$(RGB_LIB_DISTRIBUTION)/lib
|
||||
RGB_LIBRARY_NAME=rgbmatrix
|
||||
RGB_LIBRARY=$(RGB_LIBDIR)/lib$(RGB_LIBRARY_NAME).a
|
||||
LDFLAGS+=-L$(RGB_LIBDIR) -l$(RGB_LIBRARY_NAME) -lrt -lm -lpthread
|
||||
|
||||
Also, you want to add a target to build the libary in your sub-module
|
||||
|
||||
# (FYI: Make sure, there is a TAB-character in front of the $(MAKE))
|
||||
$(RGB_LIBRARY):
|
||||
$(MAKE) -C $(RGB_LIBDIR)
|
||||
|
||||
Now, your final binary needs to depend on your objects and also the
|
||||
`$(RGB_LIBRARY)`
|
||||
|
||||
my-binary : $(OBJECTS) $(RGB_LIBRARY)
|
||||
$(CXX) $(CXXFLAGS) $(OBJECTS) -o $@ $(LDFLAGS)
|
||||
|
||||
As an example, see the [PixelPusher implementation][pixelpush] which is using
|
||||
this library in a git sub-module.
|
||||
|
||||
If you are writing your own Makefile, make sure to pass the `-O3` option to
|
||||
the compiler to make sure to generate fast code.
|
||||
|
||||
Note, all the types provided are in the `rgb_matrix` namespace. That way, they
|
||||
won't clash with other types you might use in your code; in particular pretty
|
||||
common names such as `GPIO` or `Canvas` might run into clashing trouble.
|
||||
|
||||
Anyway, for convenience you just might add using-declarations in your
|
||||
code:
|
||||
|
||||
// Types exported by the RGB-Matrix library.
|
||||
using rgb_matrix::Canvas;
|
||||
using rgb_matrix::GPIO;
|
||||
using rgb_matrix::RGBMatrix;
|
||||
|
||||
Or, if you are lazy, just import the whole namespace:
|
||||
|
||||
using namespace rgb_matrix;
|
||||
|
||||
Read the [`minimal-example.cc`](./minimal-example.cc) to get started, then
|
||||
have a look into [`demo-main.cc`](./demo-main.cc).
|
||||
|
||||
## Remapping coordinates ##
|
||||
|
||||
You might choose a different physical layout than the wiring provides.
|
||||
|
||||
There is an option `--led-pixel-mapper` that allows you to choose between
|
||||
some re-mapping options, and also programmatic ways to do so.
|
||||
|
||||
### Standard mappers
|
||||
|
||||
#### U-mapper (U-shape connection)
|
||||
Say you have 4 displays with 32x32 and only a single output
|
||||
like with a Raspberry Pi 1 or the Adafruit HAT -- if we chain
|
||||
them, we get a display 32 pixel high, (4*32)=128 pixel long. If we arrange
|
||||
the boards in a U-shape so that they form a square, we get a logical display
|
||||
of 64x64 pixels:
|
||||
|
||||
<img src="../img/chained-64x64.jpg" width="400px"> In action:
|
||||
[![PixelPusher video][pp-vid]](http://youtu.be/ZglGuMaKvpY)
|
||||
|
||||
```
|
||||
So the following chain (Viewed looking at the LED-side of the panels)
|
||||
[<][<][<][<] }- Raspbery Pi connector
|
||||
|
||||
is arranged in this U-shape (on its side)
|
||||
[<][<] }----- Raspberry Pi connector
|
||||
[>][>]
|
||||
```
|
||||
|
||||
Now we need to internally map pixels the pixels so that the 'folded' 128x32
|
||||
screen behaves like a 64x64 screen.
|
||||
|
||||
There is a pixel-mapper that can help with this "U-Arrangement", you choose
|
||||
it with `--led-pixel-mapper=U-mapper`. So in this particular case,
|
||||
|
||||
```
|
||||
./demo --led-chain=4 --led-pixel-mapper="U-mapper"
|
||||
```
|
||||
|
||||
This works for longer and more than one chain as well. Here an arrangement with
|
||||
two chains with 8 panels each
|
||||
|
||||
```
|
||||
[<][<][<][<] }--- Pi connector #1
|
||||
[>][>][>][>]
|
||||
[<][<][<][<] }--- Pi connector #2
|
||||
[>][>][>][>]
|
||||
```
|
||||
|
||||
(`--led-chain=8 --led-parallel=2 --led-pixel-mapper="U-mapper"`).
|
||||
|
||||
#### V-mapper and Vmapper:Z (Vertical arrangement)
|
||||
|
||||
By default, when you add panels on a chain, they are added horizontally.
|
||||
If you have 2 panels of 64x32, you get 128x32.
|
||||
The V-mapper allows the stacking to be vertical and not horizontal and
|
||||
get the 64x64 you might want.
|
||||
|
||||
By default, all the panels are correct side up, and you need more cable length
|
||||
as you need to cross back to the start of the next panel.
|
||||
If you wish to use shorter cables, you can add use Vmapper:Z which will give
|
||||
you serpentine cabling and every other panel will be upside down (see below
|
||||
for an example).
|
||||
|
||||
It is compatible with parallel chains, so you can have multiple stacks
|
||||
of panels all building a coherent overall display.
|
||||
|
||||
Here an example with 3 chains of 4 panels (128x64) for a total of about
|
||||
98k display pixels.
|
||||
|
||||
```
|
||||
./demo --led-rows=64 --led-cols=128 --led-chain=4 -led-parallel=3 --led-pixel-mapper=V-mapper -D0
|
||||
```
|
||||
|
||||
Viewed looking the LED-side of the panels:
|
||||
|
||||
```
|
||||
Vmapper Vmapper:Z
|
||||
|
||||
[O < I] [O < I] [O < I] [I > O] [I > O] [I > O]
|
||||
,---^ ,---^ ,---^ ^ ^ ^
|
||||
[O < I] [O < I] [O < I] [O < I] [O < I] [O < I]
|
||||
,---^ ,---^ ,---^ ^ ^ ^
|
||||
[O < I] [O < I] [O < I] [I > O] [I > O] [I > O]
|
||||
,---^ ,---^ ,---^ ^ ^ ^
|
||||
[O < I] [O < I] [O < I] [O < I] [O < I] [O < I]
|
||||
^ ^ ^ ^ ^ ^
|
||||
#1 #2 #3 #1 #2 #3
|
||||
Pi connector (three parallel chains of len 4)
|
||||
```
|
||||
|
||||
(This is also a good time to notice that 384x256 with 12 128x64 panels, is probably an
|
||||
upper limit of what you can reasonably output without having an unusable fresh
|
||||
rate (Try these options to help: --led-pwm-bits=7 --led-pwm-dither-bits=1 and get about 100Hz)).
|
||||
|
||||
This shows the wiring of a 3x5 Vmapper:Z array built by Marc MERLIN, using 15x 64x32 panels:
|
||||

|
||||
With --led-pwm-bits=7 --led-pwm-dither-bits=1, it gets a better 300Hz refresh
|
||||
but only offers around 31K pixels instead of 98K pixels in the previous example.
|
||||
|
||||
Please note that Vmapper can also be used to improve the refresh rate of a long
|
||||
display even if it is only one panel high (e.g. for a text running output) by
|
||||
splitting the load into multiple parallel chains.
|
||||
|
||||
```
|
||||
|
||||
[O < I] [O < I] [O < I]
|
||||
^ ^ ^
|
||||
#1 #2 #3 Pi connector (three parallel chains of len 1)
|
||||
```
|
||||
|
||||
#### Rotate
|
||||
|
||||
The "Rotate" mapper allows you to rotate your screen. It takes an angle
|
||||
as parameter after a colon:
|
||||
|
||||
```
|
||||
./demo --led-pixel-mapper="Rotate:90"
|
||||
```
|
||||
|
||||
#### Mirror
|
||||
|
||||
The 'Mirror' mapper allows to mirror the output horizontally or vertically.
|
||||
Without parameter, it mirrors horizontally. The parameter is a single character
|
||||
'H' or 'V' for horizontal or vertical mirroring.
|
||||
|
||||
```
|
||||
./demo --led-pixel-mapper="Mirror:H"
|
||||
```
|
||||
|
||||
#### Combining Mappers
|
||||
|
||||
You can chain multiple mappers in the configuration, by separating them
|
||||
with a semicolon. The mappers are applied in the sequence you give them, so
|
||||
if you want to arrange a couple of panels with the U-arrangement, and then
|
||||
rotate the resulting screen, use
|
||||
|
||||
```
|
||||
./demo --led-chain=8 --led-parallel=3 --led-pixel-mapper="U-mapper;Rotate:90"
|
||||
```
|
||||
|
||||
Here, we first create a 128x192 screen (4 panels wide (`4*32=128`),
|
||||
with three folded chains (`6*32=192`)) and then rotate it by 90 degrees to
|
||||
get a 192x128 screen.
|
||||
|
||||
#### Programmatic access
|
||||
|
||||
If you want to choose these mappers programmatically from your program and
|
||||
not via the flags, you can do this by setting the `pixel_mapper_config` option
|
||||
in the options struct in C++ or Python.
|
||||
|
||||
```
|
||||
options.pixel_mapper_config = "Rotate:90";
|
||||
```
|
||||
|
||||
### Writing your own mappers
|
||||
|
||||
If you want to write your own mappers, e.g. if you have a fancy panel
|
||||
arrangement, you can do so using the API provided.
|
||||
|
||||
In the API, there is an interface to implement,
|
||||
a [`PixelMapper`](../include/pixel-mapper.h) that allows to program
|
||||
re-arrangements of pixels in any way. You can plug such an implementation of
|
||||
a `PixelMapper` into the RGBMatrix to use it:
|
||||
|
||||
```
|
||||
bool RGBMatrix::ApplyPixelMapper(const PixelMapper *mapper);
|
||||
```
|
||||
|
||||
If you want, you can also register your PixelMapper globally before you
|
||||
parse the command line options; then this pixel-mapper is automatically
|
||||
provided in the `--led-pixel-mapper` command line option:
|
||||
|
||||
```
|
||||
RegisterPixelMapper(new MyOwnPixelMapper());
|
||||
RGBMatrix *matrix = RGBMatrix::CreateFromFlags(...);
|
||||
```
|
||||
|
||||
Now your mapper can be used alongside (and combined with) the standard
|
||||
mappers already there (e.g. "U-mapper" or "Rotate"). Your mapper can have
|
||||
parameters: In the command-line flag, parameters provided after `:` are passed
|
||||
as-is to your `SetParameters()` implementation
|
||||
(e.g. using `--led-pixel-mapper="Rotate:90"`, the `Rotate` mapper
|
||||
gets a parameter string `"90"` as parameter).
|
||||
|
||||
#### Multiplex Mappers
|
||||
|
||||
Sometimes you even need this for the panel itself: In some panels
|
||||
(typically the 'outdoor panels', often with 1:4 multiplexing) the pixels
|
||||
are not mapped in a straight-forward way, but in a snake arrangement for
|
||||
instance.
|
||||
|
||||
There are simplified pixel mappers for this purpose, the
|
||||
[multiplex mappers](../lib/multiplex-mappers.cc). These are defined there
|
||||
and then can be accessed via the command line flag `--led-multiplexing=...`.
|
||||
|
||||
If you find that whatever parameter you give to `--led-multiplexing=` doesn't
|
||||
work, you might need to write your own mapper (extend `MultiplexMapperBase`
|
||||
and implement the one method `MapSinglePanel()`). Then register them with
|
||||
the `CreateMultiplexMapperList()` function in that file. When you do this,
|
||||
this will automatically become available in the `--led-multiplexing=` command
|
||||
line option in C++ and Python.
|
||||
|
||||
[run-vid]: ../img/running-vid.jpg
|
||||
[git-submodules]: http://git-scm.com/book/en/Git-Tools-Submodules
|
||||
[pixelpush]: https://github.com/hzeller/rpi-matrix-pixelpusher
|
||||
[pp-vid]: ../img/pixelpusher-vid.jpg
|
||||
[otf2bdf]: https://github.com/jirutka/otf2bdf
|
||||
61
depends/rpi-rgb-led-matrix/examples-api-use/c-example.c
Normal file
61
depends/rpi-rgb-led-matrix/examples-api-use/c-example.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Using the C-API of this library.
|
||||
*
|
||||
*/
|
||||
#include "led-matrix-c.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
struct RGBLedMatrixOptions options;
|
||||
struct RGBLedMatrix *matrix;
|
||||
struct LedCanvas *offscreen_canvas;
|
||||
int width, height;
|
||||
int x, y, i;
|
||||
|
||||
memset(&options, 0, sizeof(options));
|
||||
options.rows = 32;
|
||||
options.chain_length = 1;
|
||||
|
||||
/* This supports all the led commandline options. Try --led-help */
|
||||
matrix = led_matrix_create_from_options(&options, &argc, &argv);
|
||||
if (matrix == NULL)
|
||||
return 1;
|
||||
|
||||
/* Let's do an example with double-buffering. We create one extra
|
||||
* buffer onto which we draw, which is then swapped on each refresh.
|
||||
* This is typically a good aproach for animations and such.
|
||||
*/
|
||||
offscreen_canvas = led_matrix_create_offscreen_canvas(matrix);
|
||||
|
||||
led_canvas_get_size(offscreen_canvas, &width, &height);
|
||||
|
||||
fprintf(stderr, "Size: %dx%d. Hardware gpio mapping: %s\n",
|
||||
width, height, options.hardware_mapping);
|
||||
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
for (y = 0; y < height; ++y) {
|
||||
for (x = 0; x < width; ++x) {
|
||||
led_canvas_set_pixel(offscreen_canvas, x, y, i & 0xff, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now, we swap the canvas. We give swap_on_vsync the buffer we
|
||||
* just have drawn into, and wait until the next vsync happens.
|
||||
* we get back the unused buffer to which we'll draw in the next
|
||||
* iteration.
|
||||
*/
|
||||
offscreen_canvas = led_matrix_swap_on_vsync(matrix, offscreen_canvas);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure to always call led_matrix_delete() in the end to reset the
|
||||
* display. Installing signal handlers for defined exit is a good idea.
|
||||
*/
|
||||
led_matrix_delete(matrix);
|
||||
|
||||
return 0;
|
||||
}
|
||||
198
depends/rpi-rgb-led-matrix/examples-api-use/clock.cc
Normal file
198
depends/rpi-rgb-led-matrix/examples-api-use/clock.cc
Normal file
@@ -0,0 +1,198 @@
|
||||
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
// Example of a clock. This is very similar to the text-example,
|
||||
// except that it shows the time :)
|
||||
//
|
||||
// This code is public domain
|
||||
// (but note, that the led-matrix library this depends on is GPL v2)
|
||||
|
||||
#include "led-matrix.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
using namespace rgb_matrix;
|
||||
|
||||
volatile bool interrupt_received = false;
|
||||
static void InterruptHandler(int signo) {
|
||||
interrupt_received = true;
|
||||
}
|
||||
|
||||
static int usage(const char *progname) {
|
||||
fprintf(stderr, "usage: %s [options]\n", progname);
|
||||
fprintf(stderr, "Reads text from stdin and displays it. "
|
||||
"Empty string: clear screen\n");
|
||||
fprintf(stderr, "Options:\n");
|
||||
fprintf(stderr,
|
||||
"\t-d <time-format> : Default '%%H:%%M'. See strftime()\n"
|
||||
"\t Can be provided multiple times for multiple "
|
||||
"lines\n"
|
||||
"\t-f <font-file> : Use given font.\n"
|
||||
"\t-x <x-origin> : X-Origin of displaying text (Default: 0)\n"
|
||||
"\t-y <y-origin> : Y-Origin of displaying text (Default: 0)\n"
|
||||
"\t-s <line-spacing> : Extra spacing between lines when multiple -d given\n"
|
||||
"\t-S <spacing> : Extra spacing between letters (Default: 0)\n"
|
||||
"\t-C <r,g,b> : Color. Default 255,255,0\n"
|
||||
"\t-B <r,g,b> : Background-Color. Default 0,0,0\n"
|
||||
"\t-O <r,g,b> : Outline-Color, e.g. to increase contrast.\n"
|
||||
"\n"
|
||||
);
|
||||
rgb_matrix::PrintMatrixFlags(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool parseColor(Color *c, const char *str) {
|
||||
return sscanf(str, "%hhu,%hhu,%hhu", &c->r, &c->g, &c->b) == 3;
|
||||
}
|
||||
|
||||
static bool FullSaturation(const Color &c) {
|
||||
return (c.r == 0 || c.r == 255)
|
||||
&& (c.g == 0 || c.g == 255)
|
||||
&& (c.b == 0 || c.b == 255);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
RGBMatrix::Options matrix_options;
|
||||
rgb_matrix::RuntimeOptions runtime_opt;
|
||||
if (!rgb_matrix::ParseOptionsFromFlags(&argc, &argv,
|
||||
&matrix_options, &runtime_opt)) {
|
||||
return usage(argv[0]);
|
||||
}
|
||||
|
||||
// We accept multiple format lines
|
||||
|
||||
std::vector<std::string> format_lines;
|
||||
Color color(255, 255, 0);
|
||||
Color bg_color(0, 0, 0);
|
||||
Color outline_color(0,0,0);
|
||||
bool with_outline = false;
|
||||
|
||||
const char *bdf_font_file = NULL;
|
||||
int x_orig = 0;
|
||||
int y_orig = 0;
|
||||
int letter_spacing = 0;
|
||||
int line_spacing = 0;
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "x:y:f:C:B:O:s:S:d:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'd': format_lines.push_back(optarg); break;
|
||||
case 'x': x_orig = atoi(optarg); break;
|
||||
case 'y': y_orig = atoi(optarg); break;
|
||||
case 'f': bdf_font_file = strdup(optarg); break;
|
||||
case 's': line_spacing = atoi(optarg); break;
|
||||
case 'S': letter_spacing = atoi(optarg); break;
|
||||
case 'C':
|
||||
if (!parseColor(&color, optarg)) {
|
||||
fprintf(stderr, "Invalid color spec: %s\n", optarg);
|
||||
return usage(argv[0]);
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
if (!parseColor(&bg_color, optarg)) {
|
||||
fprintf(stderr, "Invalid background color spec: %s\n", optarg);
|
||||
return usage(argv[0]);
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
if (!parseColor(&outline_color, optarg)) {
|
||||
fprintf(stderr, "Invalid outline color spec: %s\n", optarg);
|
||||
return usage(argv[0]);
|
||||
}
|
||||
with_outline = true;
|
||||
break;
|
||||
default:
|
||||
return usage(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (format_lines.empty()) {
|
||||
format_lines.push_back("%H:%M");
|
||||
}
|
||||
|
||||
if (bdf_font_file == NULL) {
|
||||
fprintf(stderr, "Need to specify BDF font-file with -f\n");
|
||||
return usage(argv[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Load font. This needs to be a filename with a bdf bitmap font.
|
||||
*/
|
||||
rgb_matrix::Font font;
|
||||
if (!font.LoadFont(bdf_font_file)) {
|
||||
fprintf(stderr, "Couldn't load font '%s'\n", bdf_font_file);
|
||||
return 1;
|
||||
}
|
||||
rgb_matrix::Font *outline_font = NULL;
|
||||
if (with_outline) {
|
||||
outline_font = font.CreateOutlineFont();
|
||||
}
|
||||
|
||||
RGBMatrix *matrix = RGBMatrix::CreateFromOptions(matrix_options, runtime_opt);
|
||||
if (matrix == NULL)
|
||||
return 1;
|
||||
|
||||
const bool all_extreme_colors = (matrix_options.brightness == 100)
|
||||
&& FullSaturation(color)
|
||||
&& FullSaturation(bg_color)
|
||||
&& FullSaturation(outline_color);
|
||||
if (all_extreme_colors)
|
||||
matrix->SetPWMBits(1);
|
||||
|
||||
const int x = x_orig;
|
||||
int y = y_orig;
|
||||
|
||||
FrameCanvas *offscreen = matrix->CreateFrameCanvas();
|
||||
|
||||
char text_buffer[256];
|
||||
struct timespec next_time;
|
||||
next_time.tv_sec = time(NULL);
|
||||
next_time.tv_nsec = 0;
|
||||
struct tm tm;
|
||||
|
||||
signal(SIGTERM, InterruptHandler);
|
||||
signal(SIGINT, InterruptHandler);
|
||||
|
||||
while (!interrupt_received) {
|
||||
offscreen->Fill(bg_color.r, bg_color.g, bg_color.b);
|
||||
localtime_r(&next_time.tv_sec, &tm);
|
||||
|
||||
int line_offset = 0;
|
||||
for (const std::string &line : format_lines) {
|
||||
strftime(text_buffer, sizeof(text_buffer), line.c_str(), &tm);
|
||||
if (outline_font) {
|
||||
rgb_matrix::DrawText(offscreen, *outline_font,
|
||||
x - 1, y + font.baseline() + line_offset,
|
||||
outline_color, NULL, text_buffer,
|
||||
letter_spacing - 2);
|
||||
}
|
||||
rgb_matrix::DrawText(offscreen, font,
|
||||
x, y + font.baseline() + line_offset,
|
||||
color, NULL, text_buffer,
|
||||
letter_spacing);
|
||||
line_offset += font.height() + line_spacing;
|
||||
}
|
||||
|
||||
// Wait until we're ready to show it.
|
||||
clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &next_time, NULL);
|
||||
|
||||
// Atomic swap with double buffer
|
||||
offscreen = matrix->SwapOnVSync(offscreen);
|
||||
|
||||
next_time.tv_sec += 1;
|
||||
}
|
||||
|
||||
// Finished. Shut down the RGB matrix.
|
||||
delete matrix;
|
||||
|
||||
write(STDOUT_FILENO, "\n", 1); // Create a fresh new line after ^C on screen
|
||||
return 0;
|
||||
}
|
||||
1190
depends/rpi-rgb-led-matrix/examples-api-use/demo-main.cc
Normal file
1190
depends/rpi-rgb-led-matrix/examples-api-use/demo-main.cc
Normal file
File diff suppressed because it is too large
Load Diff
160
depends/rpi-rgb-led-matrix/examples-api-use/image-example.cc
Normal file
160
depends/rpi-rgb-led-matrix/examples-api-use/image-example.cc
Normal file
@@ -0,0 +1,160 @@
|
||||
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
//
|
||||
// Example how to display an image, including animated images using
|
||||
// ImageMagick. For a full utility that does a few more things, have a look
|
||||
// at the led-image-viewer in ../utils
|
||||
//
|
||||
// Showing an image is not so complicated, essentially just copy all the
|
||||
// pixels to the canvas. How to get the pixels ? In this example we're using
|
||||
// the graphicsmagick library as universal image loader library that
|
||||
// can also deal with animated images.
|
||||
// You can of course do your own image loading or use some other library.
|
||||
//
|
||||
// This requires an external dependency, so install these first before you
|
||||
// can call `make image-example`
|
||||
// sudo apt-get update
|
||||
// sudo apt-get install libgraphicsmagick++-dev libwebp-dev -y
|
||||
// make image-example
|
||||
|
||||
#include "led-matrix.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <exception>
|
||||
#include <Magick++.h>
|
||||
#include <magick/image.h>
|
||||
|
||||
using rgb_matrix::Canvas;
|
||||
using rgb_matrix::RGBMatrix;
|
||||
using rgb_matrix::FrameCanvas;
|
||||
|
||||
// Make sure we can exit gracefully when Ctrl-C is pressed.
|
||||
volatile bool interrupt_received = false;
|
||||
static void InterruptHandler(int signo) {
|
||||
interrupt_received = true;
|
||||
}
|
||||
|
||||
using ImageVector = std::vector<Magick::Image>;
|
||||
|
||||
// Given the filename, load the image and scale to the size of the
|
||||
// matrix.
|
||||
// // If this is an animated image, the resutlting vector will contain multiple.
|
||||
static ImageVector LoadImageAndScaleImage(const char *filename,
|
||||
int target_width,
|
||||
int target_height) {
|
||||
ImageVector result;
|
||||
|
||||
ImageVector frames;
|
||||
try {
|
||||
readImages(&frames, filename);
|
||||
} catch (std::exception &e) {
|
||||
if (e.what())
|
||||
fprintf(stderr, "%s\n", e.what());
|
||||
return result;
|
||||
}
|
||||
|
||||
if (frames.empty()) {
|
||||
fprintf(stderr, "No image found.");
|
||||
return result;
|
||||
}
|
||||
|
||||
// Animated images have partial frames that need to be put together
|
||||
if (frames.size() > 1) {
|
||||
Magick::coalesceImages(&result, frames.begin(), frames.end());
|
||||
} else {
|
||||
result.push_back(frames[0]); // just a single still image.
|
||||
}
|
||||
|
||||
for (Magick::Image &image : result) {
|
||||
image.scale(Magick::Geometry(target_width, target_height));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Copy an image to a Canvas. Note, the RGBMatrix is implementing the Canvas
|
||||
// interface as well as the FrameCanvas we use in the double-buffering of the
|
||||
// animted image.
|
||||
void CopyImageToCanvas(const Magick::Image &image, Canvas *canvas) {
|
||||
const int offset_x = 0, offset_y = 0; // If you want to move the image.
|
||||
// Copy all the pixels to the canvas.
|
||||
for (size_t y = 0; y < image.rows(); ++y) {
|
||||
for (size_t x = 0; x < image.columns(); ++x) {
|
||||
const Magick::Color &c = image.pixelColor(x, y);
|
||||
if (c.alphaQuantum() < 256) {
|
||||
canvas->SetPixel(x + offset_x, y + offset_y,
|
||||
ScaleQuantumToChar(c.redQuantum()),
|
||||
ScaleQuantumToChar(c.greenQuantum()),
|
||||
ScaleQuantumToChar(c.blueQuantum()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// An animated image has to constantly swap to the next frame.
|
||||
// We're using double-buffering and fill an offscreen buffer first, then show.
|
||||
void ShowAnimatedImage(const ImageVector &images, RGBMatrix *matrix) {
|
||||
FrameCanvas *offscreen_canvas = matrix->CreateFrameCanvas();
|
||||
while (!interrupt_received) {
|
||||
for (const auto &image : images) {
|
||||
if (interrupt_received) break;
|
||||
CopyImageToCanvas(image, offscreen_canvas);
|
||||
offscreen_canvas = matrix->SwapOnVSync(offscreen_canvas);
|
||||
usleep(image.animationDelay() * 10000); // 1/100s converted to usec
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int usage(const char *progname) {
|
||||
fprintf(stderr, "Usage: %s [led-matrix-options] <image-filename>\n",
|
||||
progname);
|
||||
rgb_matrix::PrintMatrixFlags(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
Magick::InitializeMagick(*argv);
|
||||
|
||||
// Initialize the RGB matrix with
|
||||
RGBMatrix::Options matrix_options;
|
||||
rgb_matrix::RuntimeOptions runtime_opt;
|
||||
if (!rgb_matrix::ParseOptionsFromFlags(&argc, &argv,
|
||||
&matrix_options, &runtime_opt)) {
|
||||
return usage(argv[0]);
|
||||
}
|
||||
|
||||
if (argc != 2)
|
||||
return usage(argv[0]);
|
||||
const char *filename = argv[1];
|
||||
|
||||
signal(SIGTERM, InterruptHandler);
|
||||
signal(SIGINT, InterruptHandler);
|
||||
|
||||
RGBMatrix *matrix = RGBMatrix::CreateFromOptions(matrix_options, runtime_opt);
|
||||
if (matrix == NULL)
|
||||
return 1;
|
||||
|
||||
ImageVector images = LoadImageAndScaleImage(filename,
|
||||
matrix->width(),
|
||||
matrix->height());
|
||||
switch (images.size()) {
|
||||
case 0: // failed to load image.
|
||||
break;
|
||||
case 1: // Simple example: one image to show
|
||||
CopyImageToCanvas(images[0], matrix);
|
||||
while (!interrupt_received) sleep(1000); // Until Ctrl-C is pressed
|
||||
break;
|
||||
default: // More than one image: this is an animation.
|
||||
ShowAnimatedImage(images, matrix);
|
||||
break;
|
||||
}
|
||||
|
||||
matrix->Clear();
|
||||
delete matrix;
|
||||
|
||||
return 0;
|
||||
}
|
||||
64
depends/rpi-rgb-led-matrix/examples-api-use/input-example.cc
Normal file
64
depends/rpi-rgb-led-matrix/examples-api-use/input-example.cc
Normal file
@@ -0,0 +1,64 @@
|
||||
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
// Small example how to use the input bits
|
||||
//
|
||||
// This code is public domain
|
||||
// (but note, that the led-matrix library this depends on is GPL v2)
|
||||
|
||||
#include "led-matrix.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
using rgb_matrix::RGBMatrix;
|
||||
using rgb_matrix::Canvas;
|
||||
|
||||
volatile bool interrupt_received = false;
|
||||
static void InterruptHandler(int signo) {
|
||||
interrupt_received = true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
RGBMatrix::Options defaults;
|
||||
defaults.hardware_mapping = "regular"; // or e.g. "adafruit-hat"
|
||||
defaults.rows = 32;
|
||||
defaults.chain_length = 1;
|
||||
defaults.parallel = 1;
|
||||
RGBMatrix *matrix = RGBMatrix::CreateFromFlags(&argc, &argv, &defaults);
|
||||
if (matrix == NULL)
|
||||
return 1;
|
||||
|
||||
// It is always good to set up a signal handler to cleanly exit when we
|
||||
// receive a CTRL-C for instance.
|
||||
signal(SIGTERM, InterruptHandler);
|
||||
signal(SIGINT, InterruptHandler);
|
||||
|
||||
// Let's request all input bits and see which are actually available.
|
||||
// This will differ depending on which hardware mapping you use and how
|
||||
// many parallel chains you have.
|
||||
const uint64_t available_inputs = matrix->RequestInputs(0xffffffff);
|
||||
fprintf(stderr, "Available GPIO-bits: ");
|
||||
for (int b = 0; b < 32; ++b) {
|
||||
if (available_inputs & (1<<b))
|
||||
fprintf(stderr, "%d ", b);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
while (!interrupt_received) {
|
||||
// Block and wait until any input bit changed or 100ms passed
|
||||
uint32_t inputs = matrix->AwaitInputChange(100);
|
||||
|
||||
// Minimal output: let's show the bits with LEDs in the first row
|
||||
for (int b = 0; b < 32; ++b) {
|
||||
uint8_t col = (inputs & (1<<b)) ? 255 : 0;
|
||||
matrix->SetPixel(32-b, 0, col, col, col);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Exiting.\n");
|
||||
matrix->Clear();
|
||||
delete matrix;
|
||||
|
||||
return 0;
|
||||
}
|
||||
82
depends/rpi-rgb-led-matrix/examples-api-use/ledcat.cc
Normal file
82
depends/rpi-rgb-led-matrix/examples-api-use/ledcat.cc
Normal file
@@ -0,0 +1,82 @@
|
||||
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
// A program that reads frames form STDIN as RGB24, much like
|
||||
// https://github.com/polyfloyd/ledcat does.
|
||||
//
|
||||
// This code is public domain
|
||||
// (but note, that the led-matrix library this depends on is GPL v2)
|
||||
|
||||
#include "led-matrix.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define FPS 60
|
||||
|
||||
using rgb_matrix::RGBMatrix;
|
||||
using rgb_matrix::Canvas;
|
||||
|
||||
volatile bool interrupt_received = false;
|
||||
static void InterruptHandler(int signo) {
|
||||
interrupt_received = true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
RGBMatrix::Options defaults;
|
||||
defaults.hardware_mapping = "regular"; // or e.g. "adafruit-hat"
|
||||
defaults.rows = 32;
|
||||
defaults.chain_length = 1;
|
||||
defaults.parallel = 1;
|
||||
Canvas *canvas = RGBMatrix::CreateFromFlags(&argc, &argv, &defaults);
|
||||
if (canvas == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// It is always good to set up a signal handler to cleanly exit when we
|
||||
// receive a CTRL-C for instance. The DrawOnCanvas() routine is looking
|
||||
// for that.
|
||||
signal(SIGTERM, InterruptHandler);
|
||||
signal(SIGINT, InterruptHandler);
|
||||
|
||||
ssize_t frame_size = canvas->width() * canvas->height() * 3;
|
||||
uint8_t buf[frame_size];
|
||||
|
||||
while (1) {
|
||||
struct timespec start;
|
||||
timespec_get(&start, TIME_UTC);
|
||||
|
||||
ssize_t nread;
|
||||
ssize_t total_nread = 0;
|
||||
while ((nread = read(STDIN_FILENO, &buf[total_nread], frame_size - total_nread)) > 0) {
|
||||
if (interrupt_received) {
|
||||
return 1;
|
||||
}
|
||||
total_nread += nread;
|
||||
}
|
||||
if (total_nread < frame_size){
|
||||
break;
|
||||
}
|
||||
|
||||
for (int y = 0; y < canvas->height(); y++) {
|
||||
for (int x = 0; x < canvas->width(); x++) {
|
||||
uint8_t *p = &buf[(y * canvas->width() + x) * 3];
|
||||
uint8_t r = *(p+0), g = *(p+1), b = *(p+2);
|
||||
canvas->SetPixel(x, y, r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
struct timespec end;
|
||||
timespec_get(&end, TIME_UTC);
|
||||
long tudiff = (end.tv_nsec / 1000 + end.tv_sec * 1000000) - (start.tv_nsec / 1000 + start.tv_sec * 1000000);
|
||||
if (tudiff < 1000000l / FPS) {
|
||||
usleep(1000000l / FPS - tudiff);
|
||||
}
|
||||
}
|
||||
|
||||
// Animation finished. Shut down the RGB matrix.
|
||||
canvas->Clear();
|
||||
delete canvas;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
// Small example how to use the library.
|
||||
// For more examples, look at demo-main.cc
|
||||
//
|
||||
// This code is public domain
|
||||
// (but note, that the led-matrix library this depends on is GPL v2)
|
||||
|
||||
#include "led-matrix.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
using rgb_matrix::RGBMatrix;
|
||||
using rgb_matrix::Canvas;
|
||||
|
||||
volatile bool interrupt_received = false;
|
||||
static void InterruptHandler(int signo) {
|
||||
interrupt_received = true;
|
||||
}
|
||||
|
||||
static void DrawOnCanvas(Canvas *canvas) {
|
||||
/*
|
||||
* Let's create a simple animation. We use the canvas to draw
|
||||
* pixels. We wait between each step to have a slower animation.
|
||||
*/
|
||||
canvas->Fill(0, 0, 255);
|
||||
|
||||
int center_x = canvas->width() / 2;
|
||||
int center_y = canvas->height() / 2;
|
||||
float radius_max = canvas->width() / 2;
|
||||
float angle_step = 1.0 / 360;
|
||||
for (float a = 0, r = 0; r < radius_max; a += angle_step, r += angle_step) {
|
||||
if (interrupt_received)
|
||||
return;
|
||||
float dot_x = cos(a * 2 * M_PI) * r;
|
||||
float dot_y = sin(a * 2 * M_PI) * r;
|
||||
canvas->SetPixel(center_x + dot_x, center_y + dot_y,
|
||||
255, 0, 0);
|
||||
usleep(1 * 1000); // wait a little to slow down things.
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
RGBMatrix::Options defaults;
|
||||
defaults.hardware_mapping = "regular"; // or e.g. "adafruit-hat"
|
||||
defaults.rows = 32;
|
||||
defaults.chain_length = 1;
|
||||
defaults.parallel = 1;
|
||||
defaults.show_refresh_rate = true;
|
||||
Canvas *canvas = RGBMatrix::CreateFromFlags(&argc, &argv, &defaults);
|
||||
if (canvas == NULL)
|
||||
return 1;
|
||||
|
||||
// It is always good to set up a signal handler to cleanly exit when we
|
||||
// receive a CTRL-C for instance. The DrawOnCanvas() routine is looking
|
||||
// for that.
|
||||
signal(SIGTERM, InterruptHandler);
|
||||
signal(SIGINT, InterruptHandler);
|
||||
|
||||
DrawOnCanvas(canvas); // Using the canvas.
|
||||
|
||||
// Animation finished. Shut down the RGB matrix.
|
||||
canvas->Clear();
|
||||
delete canvas;
|
||||
|
||||
return 0;
|
||||
}
|
||||
210
depends/rpi-rgb-led-matrix/examples-api-use/pixel-mover.cc
Normal file
210
depends/rpi-rgb-led-matrix/examples-api-use/pixel-mover.cc
Normal file
@@ -0,0 +1,210 @@
|
||||
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
// Small example how to use the input bits
|
||||
//
|
||||
// This code is public domain
|
||||
// (but note, that the led-matrix library this depends on is GPL v2)
|
||||
|
||||
#include "led-matrix.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <deque>
|
||||
|
||||
using namespace rgb_matrix;
|
||||
|
||||
volatile bool interrupt_received = false;
|
||||
static void InterruptHandler(int signo) {
|
||||
interrupt_received = true;
|
||||
}
|
||||
|
||||
static void InteractiveUseMessage() {
|
||||
fprintf(stderr,
|
||||
"Move around with common movement keysets \n"
|
||||
" W,A,S,D (gaming move style) or\n"
|
||||
" H,J,K,L (vi console move style)\n"
|
||||
" Quit with 'q' or <ESC>\n"
|
||||
"The pixel position cannot be less than 0 or greater than the "
|
||||
"display height and width.\n");
|
||||
}
|
||||
|
||||
static int usage(const char *progname) {
|
||||
fprintf(stderr, "usage: %s [options]\n", progname);
|
||||
fprintf(stderr, "Display single pixel with any colour.\n");
|
||||
InteractiveUseMessage();
|
||||
fprintf(stderr, "Options:\n\n");
|
||||
fprintf(stderr,
|
||||
"\t-C <r,g,b> : Color at front of trail. Default 255,255,0\n"
|
||||
"\t-t <trail-len> : Length of trail behind dot (default:0)\n"
|
||||
"\t-c <r,g,b> : Color at end of trail. Default 0,0,255\n\n"
|
||||
);
|
||||
rgb_matrix::PrintMatrixFlags(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool parseColor(Color *c, const char *str) {
|
||||
return sscanf(str, "%hhu,%hhu,%hhu", &c->r, &c->g, &c->b) == 3;
|
||||
}
|
||||
|
||||
static char getch() {
|
||||
static bool is_terminal = isatty(STDIN_FILENO);
|
||||
|
||||
struct termios old;
|
||||
if (is_terminal) {
|
||||
if (tcgetattr(0, &old) < 0)
|
||||
perror("tcsetattr()");
|
||||
|
||||
// Set to unbuffered mode
|
||||
struct termios no_echo = old;
|
||||
no_echo.c_lflag &= ~ICANON;
|
||||
no_echo.c_lflag &= ~ECHO;
|
||||
no_echo.c_cc[VMIN] = 1;
|
||||
no_echo.c_cc[VTIME] = 0;
|
||||
if (tcsetattr(0, TCSANOW, &no_echo) < 0)
|
||||
perror("tcsetattr ICANON");
|
||||
}
|
||||
|
||||
char buf = 0;
|
||||
if (read(STDIN_FILENO, &buf, 1) < 0)
|
||||
perror ("read()");
|
||||
|
||||
if (is_terminal) {
|
||||
// Back to original terminal settings.
|
||||
if (tcsetattr(0, TCSADRAIN, &old) < 0)
|
||||
perror ("tcsetattr ~ICANON");
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
// Interpolation of color between head and tail of trail.
|
||||
static uint8_t quantize(float c) {
|
||||
return c < 0 ? 0 : c > 255 ? 255 : roundf(c);
|
||||
}
|
||||
static Color interpolate(const Color &c1, const Color &c2, float fraction) {
|
||||
float c2_fraction = 1 - fraction;
|
||||
return { quantize(c1.r * fraction + c2.r * c2_fraction),
|
||||
quantize(c1.g * fraction + c2.g * c2_fraction),
|
||||
quantize(c1.b * fraction + c2.b * c2_fraction)};
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
RGBMatrix::Options matrix_options;
|
||||
rgb_matrix::RuntimeOptions runtime_opt;
|
||||
if (!rgb_matrix::ParseOptionsFromFlags(&argc, &argv,
|
||||
&matrix_options, &runtime_opt)) {
|
||||
return usage(argv[0]);
|
||||
}
|
||||
|
||||
Color front_color(255, 255, 0);
|
||||
Color back_color(0, 0, 255);
|
||||
|
||||
int trail_len = 0;
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "C:c:t:")) != -1) {
|
||||
switch (opt) {
|
||||
case 't':
|
||||
trail_len = std::max(0, atoi(optarg));
|
||||
break;
|
||||
case 'C':
|
||||
if (!parseColor(&front_color, optarg)) {
|
||||
fprintf(stderr, "Invalid color spec: %s\n", optarg);
|
||||
return usage(argv[0]);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
if (!parseColor(&back_color, optarg)) {
|
||||
fprintf(stderr, "Invalid color spec: %s\n", optarg);
|
||||
return usage(argv[0]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return usage(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
RGBMatrix *matrix = RGBMatrix::CreateFromOptions(matrix_options, runtime_opt);
|
||||
if (matrix == NULL)
|
||||
return usage(argv[0]);
|
||||
|
||||
rgb_matrix::FrameCanvas *canvas = matrix->CreateFrameCanvas();
|
||||
signal(SIGTERM, InterruptHandler);
|
||||
signal(SIGINT, InterruptHandler);
|
||||
|
||||
std::deque<std::pair<int, int>> trail;
|
||||
int x_pos = 0;
|
||||
int y_pos = 0;
|
||||
trail.push_back({x_pos, y_pos});
|
||||
|
||||
InteractiveUseMessage();
|
||||
const bool output_is_terminal = isatty(STDOUT_FILENO);
|
||||
|
||||
bool running = true;
|
||||
while (!interrupt_received && running) {
|
||||
canvas->Clear();
|
||||
int distance_from_head = trail.size();
|
||||
for (const auto &pos : trail) { // Draw from tail -> head
|
||||
distance_from_head--;
|
||||
Color c = interpolate(front_color, back_color,
|
||||
1.0 - 1.0f * distance_from_head / trail.size());
|
||||
canvas->SetPixel(pos.first, pos.second, c.r, c.g, c.b);
|
||||
}
|
||||
canvas = matrix->SwapOnVSync(canvas);
|
||||
|
||||
printf("%sX,Y = %d,%d%s",
|
||||
output_is_terminal ? "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" : "",
|
||||
x_pos, y_pos,
|
||||
output_is_terminal ? " " : "\n");
|
||||
fflush(stdout);
|
||||
|
||||
const char c = tolower(getch());
|
||||
switch (c) {
|
||||
case 'w': case 'k': // Up
|
||||
if (y_pos > 0) {
|
||||
y_pos--;
|
||||
trail.push_back({x_pos, y_pos});
|
||||
}
|
||||
break;
|
||||
case 's': case 'j': // Down
|
||||
if (y_pos < canvas->height() - 1) {
|
||||
y_pos++;
|
||||
trail.push_back({x_pos, y_pos});
|
||||
}
|
||||
break;
|
||||
case 'a': case 'h': // Left
|
||||
if (x_pos > 0) {
|
||||
x_pos--;
|
||||
trail.push_back({x_pos, y_pos});
|
||||
}
|
||||
break;
|
||||
case 'd': case 'l': // Right
|
||||
if (x_pos < canvas->width() - 1) {
|
||||
x_pos++;
|
||||
trail.push_back({x_pos, y_pos});
|
||||
}
|
||||
break;
|
||||
// All kinds of conditions which we use to exit
|
||||
case 0x1B: // Escape
|
||||
case 'q': // 'Q'uit
|
||||
case 0x04: // End of file
|
||||
case 0x00: // Other issue from getch()
|
||||
running = false;
|
||||
break;
|
||||
}
|
||||
|
||||
while ((int)trail.size() > trail_len + 1)
|
||||
trail.pop_front(); // items on front are the oldest dots
|
||||
}
|
||||
|
||||
// Finished. Shut down the RGB matrix.
|
||||
delete matrix;
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
BIN
depends/rpi-rgb-led-matrix/examples-api-use/runtext.ppm
Normal file
BIN
depends/rpi-rgb-led-matrix/examples-api-use/runtext.ppm
Normal file
Binary file not shown.
BIN
depends/rpi-rgb-led-matrix/examples-api-use/runtext16.ppm
Normal file
BIN
depends/rpi-rgb-led-matrix/examples-api-use/runtext16.ppm
Normal file
Binary file not shown.
@@ -0,0 +1,184 @@
|
||||
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
// Small example how to scroll text.
|
||||
//
|
||||
// This code is public domain
|
||||
// (but note, that the led-matrix library this depends on is GPL v2)
|
||||
|
||||
// For a utility with a few more features see
|
||||
// ../utils/text-scroller.cc
|
||||
|
||||
#include "led-matrix.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace rgb_matrix;
|
||||
|
||||
volatile bool interrupt_received = false;
|
||||
static void InterruptHandler(int signo) {
|
||||
interrupt_received = true;
|
||||
}
|
||||
|
||||
static int usage(const char *progname) {
|
||||
fprintf(stderr, "usage: %s [options] <text>\n", progname);
|
||||
fprintf(stderr, "Takes text and scrolls it with speed -s\n");
|
||||
fprintf(stderr, "Options:\n");
|
||||
fprintf(stderr,
|
||||
"\t-s <speed> : Approximate letters per second. "
|
||||
"(Zero for no scrolling)\n"
|
||||
"\t-l <loop-count> : Number of loops through the text. "
|
||||
"-1 for endless (default)\n"
|
||||
"\t-f <font-file> : Use given font.\n"
|
||||
"\t-x <x-origin> : X-Origin of displaying text (Default: 0)\n"
|
||||
"\t-y <y-origin> : Y-Origin of displaying text (Default: 0)\n"
|
||||
"\t-t <track=spacing>: Spacing pixels between letters (Default: 0)\n"
|
||||
"\n"
|
||||
"\t-C <r,g,b> : Text-Color. Default 255,255,0\n"
|
||||
"\t-B <r,g,b> : Background-Color. Default 0,0,0\n"
|
||||
"\n"
|
||||
);
|
||||
rgb_matrix::PrintMatrixFlags(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool parseColor(Color *c, const char *str) {
|
||||
return sscanf(str, "%hhu,%hhu,%hhu", &c->r, &c->g, &c->b) == 3;
|
||||
}
|
||||
|
||||
static bool FullSaturation(const Color &c) {
|
||||
return (c.r == 0 || c.r == 255)
|
||||
&& (c.g == 0 || c.g == 255)
|
||||
&& (c.b == 0 || c.b == 255);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
RGBMatrix::Options matrix_options;
|
||||
rgb_matrix::RuntimeOptions runtime_opt;
|
||||
if (!rgb_matrix::ParseOptionsFromFlags(&argc, &argv,
|
||||
&matrix_options, &runtime_opt)) {
|
||||
return usage(argv[0]);
|
||||
}
|
||||
|
||||
Color color(255, 255, 0);
|
||||
Color bg_color(0, 0, 0);
|
||||
|
||||
const char *bdf_font_file = NULL;
|
||||
std::string line;
|
||||
/* x_origin is set by default just right of the screen */
|
||||
const int x_default_start = (matrix_options.chain_length
|
||||
* matrix_options.cols) + 5;
|
||||
int x_orig = x_default_start;
|
||||
int y_orig = 0;
|
||||
int letter_spacing = 0;
|
||||
float speed = 7.0f;
|
||||
int loops = -1;
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "x:y:f:C:B:t:s:l:")) != -1) {
|
||||
switch (opt) {
|
||||
case 's': speed = atof(optarg); break;
|
||||
case 'l': loops = atoi(optarg); break;
|
||||
case 'x': x_orig = atoi(optarg); break;
|
||||
case 'y': y_orig = atoi(optarg); break;
|
||||
case 'f': bdf_font_file = strdup(optarg); break;
|
||||
case 't': letter_spacing = atoi(optarg); break;
|
||||
case 'C':
|
||||
if (!parseColor(&color, optarg)) {
|
||||
fprintf(stderr, "Invalid color spec: %s\n", optarg);
|
||||
return usage(argv[0]);
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
if (!parseColor(&bg_color, optarg)) {
|
||||
fprintf(stderr, "Invalid background color spec: %s\n", optarg);
|
||||
return usage(argv[0]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return usage(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = optind; i < argc; ++i) {
|
||||
line.append(argv[i]).append(" ");
|
||||
}
|
||||
|
||||
if (line.empty()) {
|
||||
fprintf(stderr, "Add the text you want to print on the command-line.\n");
|
||||
return usage(argv[0]);
|
||||
}
|
||||
|
||||
if (bdf_font_file == NULL) {
|
||||
fprintf(stderr, "Need to specify BDF font-file with -f\n");
|
||||
return usage(argv[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Load font. This needs to be a filename with a bdf bitmap font.
|
||||
*/
|
||||
rgb_matrix::Font font;
|
||||
if (!font.LoadFont(bdf_font_file)) {
|
||||
fprintf(stderr, "Couldn't load font '%s'\n", bdf_font_file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
RGBMatrix *canvas = RGBMatrix::CreateFromOptions(matrix_options, runtime_opt);
|
||||
if (canvas == NULL)
|
||||
return 1;
|
||||
|
||||
const bool all_extreme_colors = (matrix_options.brightness == 100)
|
||||
&& FullSaturation(color)
|
||||
&& FullSaturation(bg_color);
|
||||
if (all_extreme_colors)
|
||||
canvas->SetPWMBits(1);
|
||||
|
||||
signal(SIGTERM, InterruptHandler);
|
||||
signal(SIGINT, InterruptHandler);
|
||||
|
||||
printf("CTRL-C for exit.\n");
|
||||
|
||||
// Create a new canvas to be used with led_matrix_swap_on_vsync
|
||||
FrameCanvas *offscreen_canvas = canvas->CreateFrameCanvas();
|
||||
|
||||
int delay_speed_usec = 1000000;
|
||||
if (speed > 0) {
|
||||
delay_speed_usec = 1000000 / speed / font.CharacterWidth('W');
|
||||
} else if (x_orig == x_default_start) {
|
||||
// There would be no scrolling, so text would never appear. Move to front.
|
||||
x_orig = 0;
|
||||
}
|
||||
|
||||
int x = x_orig;
|
||||
int y = y_orig;
|
||||
int length = 0;
|
||||
|
||||
while (!interrupt_received && loops != 0) {
|
||||
offscreen_canvas->Fill(bg_color.r, bg_color.g, bg_color.b);
|
||||
// length = holds how many pixels our text takes up
|
||||
length = rgb_matrix::DrawText(offscreen_canvas, font,
|
||||
x, y + font.baseline(),
|
||||
color, nullptr,
|
||||
line.c_str(), letter_spacing);
|
||||
|
||||
if (speed > 0 && --x + length < 0) {
|
||||
x = x_orig;
|
||||
if (loops > 0) --loops;
|
||||
}
|
||||
|
||||
// Swap the offscreen_canvas with canvas on vsync, avoids flickering
|
||||
offscreen_canvas = canvas->SwapOnVSync(offscreen_canvas);
|
||||
usleep(delay_speed_usec);
|
||||
}
|
||||
|
||||
// Finished. Shut down the RGB matrix.
|
||||
delete canvas;
|
||||
|
||||
return 0;
|
||||
}
|
||||
179
depends/rpi-rgb-led-matrix/examples-api-use/text-example.cc
Normal file
179
depends/rpi-rgb-led-matrix/examples-api-use/text-example.cc
Normal file
@@ -0,0 +1,179 @@
|
||||
// -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
||||
// Small example how write text.
|
||||
//
|
||||
// This code is public domain
|
||||
// (but note, that the led-matrix library this depends on is GPL v2)
|
||||
|
||||
#include "led-matrix.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace rgb_matrix;
|
||||
|
||||
static int usage(const char *progname) {
|
||||
fprintf(stderr, "usage: %s [options]\n", progname);
|
||||
fprintf(stderr, "Reads text from stdin and displays it. "
|
||||
"Empty string: clear screen\n");
|
||||
fprintf(stderr, "Options:\n");
|
||||
fprintf(stderr,
|
||||
"\t-f <font-file> : Use given font.\n"
|
||||
"\t-x <x-origin> : X-Origin of displaying text (Default: 0)\n"
|
||||
"\t-y <y-origin> : Y-Origin of displaying text (Default: 0)\n"
|
||||
"\t-S <spacing> : Spacing pixels between letters (Default: 0)\n"
|
||||
"\t-C <r,g,b> : Color. Default 255,255,0\n"
|
||||
"\t-B <r,g,b> : Font Background-Color. Default 0,0,0\n"
|
||||
"\t-O <r,g,b> : Outline-Color, e.g. to increase contrast.\n"
|
||||
"\t-F <r,g,b> : Panel flooding-background color. Default 0,0,0\n"
|
||||
"\n"
|
||||
);
|
||||
rgb_matrix::PrintMatrixFlags(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool parseColor(Color *c, const char *str) {
|
||||
return sscanf(str, "%hhu,%hhu,%hhu", &c->r, &c->g, &c->b) == 3;
|
||||
}
|
||||
|
||||
static bool FullSaturation(const Color &c) {
|
||||
return (c.r == 0 || c.r == 255)
|
||||
&& (c.g == 0 || c.g == 255)
|
||||
&& (c.b == 0 || c.b == 255);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
RGBMatrix::Options matrix_options;
|
||||
rgb_matrix::RuntimeOptions runtime_opt;
|
||||
if (!rgb_matrix::ParseOptionsFromFlags(&argc, &argv,
|
||||
&matrix_options, &runtime_opt)) {
|
||||
return usage(argv[0]);
|
||||
}
|
||||
|
||||
Color color(255, 255, 0);
|
||||
Color bg_color(0, 0, 0);
|
||||
Color flood_color(0, 0, 0);
|
||||
Color outline_color(0,0,0);
|
||||
bool with_outline = false;
|
||||
|
||||
const char *bdf_font_file = NULL;
|
||||
int x_orig = 0;
|
||||
int y_orig = 0;
|
||||
int letter_spacing = 0;
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "x:y:f:C:B:O:S:F:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'x': x_orig = atoi(optarg); break;
|
||||
case 'y': y_orig = atoi(optarg); break;
|
||||
case 'f': bdf_font_file = strdup(optarg); break;
|
||||
case 'S': letter_spacing = atoi(optarg); break;
|
||||
case 'C':
|
||||
if (!parseColor(&color, optarg)) {
|
||||
fprintf(stderr, "Invalid color spec: %s\n", optarg);
|
||||
return usage(argv[0]);
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
if (!parseColor(&bg_color, optarg)) {
|
||||
fprintf(stderr, "Invalid background color spec: %s\n", optarg);
|
||||
return usage(argv[0]);
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
if (!parseColor(&outline_color, optarg)) {
|
||||
fprintf(stderr, "Invalid outline color spec: %s\n", optarg);
|
||||
return usage(argv[0]);
|
||||
}
|
||||
with_outline = true;
|
||||
break;
|
||||
case 'F':
|
||||
if (!parseColor(&flood_color, optarg)) {
|
||||
fprintf(stderr, "Invalid background color spec: %s\n", optarg);
|
||||
return usage(argv[0]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return usage(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (bdf_font_file == NULL) {
|
||||
fprintf(stderr, "Need to specify BDF font-file with -f\n");
|
||||
return usage(argv[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Load font. This needs to be a filename with a bdf bitmap font.
|
||||
*/
|
||||
rgb_matrix::Font font;
|
||||
if (!font.LoadFont(bdf_font_file)) {
|
||||
fprintf(stderr, "Couldn't load font '%s'\n", bdf_font_file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we want an outline around the font, we create a new font with
|
||||
* the original font as a template that is just an outline font.
|
||||
*/
|
||||
rgb_matrix::Font *outline_font = NULL;
|
||||
if (with_outline) {
|
||||
outline_font = font.CreateOutlineFont();
|
||||
}
|
||||
|
||||
RGBMatrix *canvas = RGBMatrix::CreateFromOptions(matrix_options, runtime_opt);
|
||||
if (canvas == NULL)
|
||||
return 1;
|
||||
|
||||
const bool all_extreme_colors = (matrix_options.brightness == 100)
|
||||
&& FullSaturation(color)
|
||||
&& FullSaturation(bg_color)
|
||||
&& FullSaturation(outline_color);
|
||||
if (all_extreme_colors)
|
||||
canvas->SetPWMBits(1);
|
||||
|
||||
const int x = x_orig;
|
||||
int y = y_orig;
|
||||
|
||||
if (isatty(STDIN_FILENO)) {
|
||||
// Only give a message if we are interactive. If connected via pipe, be quiet
|
||||
printf("Enter lines. Full screen or empty line clears screen.\n"
|
||||
"Supports UTF-8. CTRL-D for exit.\n");
|
||||
}
|
||||
|
||||
canvas->Fill(flood_color.r, flood_color.g, flood_color.b);
|
||||
char line[1024];
|
||||
while (fgets(line, sizeof(line), stdin)) {
|
||||
const size_t last = strlen(line);
|
||||
if (last > 0) line[last - 1] = '\0'; // remove newline.
|
||||
bool line_empty = strlen(line) == 0;
|
||||
if ((y + font.height() > canvas->height()) || line_empty) {
|
||||
canvas->Fill(flood_color.r, flood_color.g, flood_color.b);
|
||||
y = y_orig;
|
||||
}
|
||||
if (line_empty)
|
||||
continue;
|
||||
if (outline_font) {
|
||||
// The outline font, we need to write with a negative (-2) text-spacing,
|
||||
// as we want to have the same letter pitch as the regular text that
|
||||
// we then write on top.
|
||||
rgb_matrix::DrawText(canvas, *outline_font,
|
||||
x - 1, y + font.baseline(),
|
||||
outline_color, &bg_color, line, letter_spacing - 2);
|
||||
}
|
||||
// The regular text. Unless we already have filled the background with
|
||||
// the outline font, we also fill the background here.
|
||||
rgb_matrix::DrawText(canvas, font, x, y + font.baseline(),
|
||||
color, outline_font ? NULL : &bg_color, line,
|
||||
letter_spacing);
|
||||
y += font.height();
|
||||
}
|
||||
|
||||
// Finished. Shut down the RGB matrix.
|
||||
delete canvas;
|
||||
|
||||
return 0;
|
||||
}
|
||||
140567
depends/rpi-rgb-led-matrix/fonts/10x20.bdf
Normal file
140567
depends/rpi-rgb-led-matrix/fonts/10x20.bdf
Normal file
File diff suppressed because it is too large
Load Diff
11981
depends/rpi-rgb-led-matrix/fonts/4x6.bdf
Normal file
11981
depends/rpi-rgb-led-matrix/fonts/4x6.bdf
Normal file
File diff suppressed because it is too large
Load Diff
25905
depends/rpi-rgb-led-matrix/fonts/5x7.bdf
Normal file
25905
depends/rpi-rgb-led-matrix/fonts/5x7.bdf
Normal file
File diff suppressed because it is too large
Load Diff
21422
depends/rpi-rgb-led-matrix/fonts/5x8.bdf
Normal file
21422
depends/rpi-rgb-led-matrix/fonts/5x8.bdf
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user