removing submodule
build lightwatch / build (push) Failing after 5m6s
Details
build lightwatch / build (push) Failing after 5m6s
Details
parent
d539dc9119
commit
ed18dd911a
@ -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
|
@ -0,0 +1,6 @@
|
||||
*.o
|
||||
*.a
|
||||
*~
|
||||
*.so
|
||||
.envrc
|
||||
.direnv
|
@ -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.
|
@ -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
|
@ -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
|
@ -0,0 +1,3 @@
|
||||
include ../kicad-scripts/makefile.inc
|
||||
|
||||
active3-rpi-hub75-adapter-fab.zip:
|
@ -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
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`/" < $^ > $@
|
@ -0,0 +1,3 @@
|
||||
include ../kicad-scripts/makefile.inc
|
||||
|
||||
passive3-rpi-hub75-adapter-fab.zip:
|
@ -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
|
@ -0,0 +1,3 @@
|
||||
include ../kicad-scripts/makefile.inc
|
||||
|
||||
passive-rpi-hub75-adapter-fab.zip:
|
@ -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
|
@ -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
|
@ -0,0 +1,5 @@
|
||||
**/.vs
|
||||
**/bin
|
||||
**/obj
|
||||
**/*.sln
|
||||
**/*.csproj.user
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
};
|
@ -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)
|
@ -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`
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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>
|
@ -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>
|
@ -0,0 +1 @@
|
||||
build/*
|
@ -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
|
@ -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
|
@ -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
|
File diff suppressed because it is too large
Load Diff
@ -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:
|
@ -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:
|
@ -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)
|
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)
|
@ -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()
|
@ -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()
|
@ -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()
|
@ -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)
|
@ -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()
|
@ -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()
|
@ -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()
|
@ -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
|
@ -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()
|
@ -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']
|
||||
)
|
@ -0,0 +1,7 @@
|
||||
demo
|
||||
minimal-example
|
||||
text-example
|
||||
c-example
|
||||
clock
|
||||
scrolling-text-example
|
||||
ledcat
|
@ -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
|
@ -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:
|
||||
![Vmapper_Z_192x160_3x5.jpg](../img/Vmapper_Z_192x160_3x5.jpg)
|
||||
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
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
Binary file not shown.
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;
|
||||
}
|
@ -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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
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
Loading…
Reference in New Issue