Compare commits
11 Commits
Author | SHA1 | Date |
---|---|---|
Nathan Wagner | 3d3b3fbf7b | 10 months ago |
Nathan Wagner | 6e27fc641b | 1 year ago |
Nathan Wagner | 66d55c15de | 1 year ago |
Nathan Wagner | 7df4020194 | 1 year ago |
nathan | c413a2302d | 1 year ago |
nathan | ed18dd911a | 1 year ago |
nathan | d539dc9119 | 1 year ago |
nathan | c7028fb8ed | 1 year ago |
nathan | 9a9d5ecf47 | 1 year ago |
nathan | 2da123a095 | 1 year ago |
nathan | 83505d780c | 1 year ago |
@ -0,0 +1,25 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||
// README at: https://github.com/devcontainers/templates/tree/main/src/go
|
||||
{
|
||||
"name": "Go",
|
||||
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1-1.21-bullseye",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
|
||||
}
|
||||
|
||||
// Features to add to the dev container. More info: https://containers.dev/features.
|
||||
// "features": {},
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
// "postCreateCommand": "go version",
|
||||
|
||||
// Configure tool-specific properties.
|
||||
// "customizations": {},
|
||||
|
||||
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
||||
// "remoteUser": "root"
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
name: build lightwatch
|
||||
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- ".gitea/workflows/**"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: registry.local/catthehacker:act-latest-wagnerca
|
||||
volumes:
|
||||
- /var/run/user/1000/docker.sock:/var/run/docker.sock
|
||||
- /var/run/secrets/kubernetes.io/serviceaccount:/var/run/secrets/kubernetes.io/serviceaccount
|
||||
env:
|
||||
KUBERNETES_PORT: "tcp://10.43.0.1:443"
|
||||
KUBERNETES_PORT_443_TCP: "tcp://10.43.0.1:443"
|
||||
KUBERNETES_PORT_443_TCP_ADDR: "10.43.0.1"
|
||||
KUBERNETES_PORT_443_TCP_PORT: "443"
|
||||
KUBERNETES_PORT_443_TCP_PROTO: "tcp"
|
||||
KUBERNETES_SERVICE_HOST: "10.43.0.1"
|
||||
KUBERNETES_SERVICE_PORT: "443"
|
||||
KUBERNETES_SERVICE_PORT_HTTPS: "443"
|
||||
BUILDKIT_HOST: "docker-container://wagner-buildkitd"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: docker buildx create --use --name=wagner-buildkitd --driver=remote
|
||||
- run: docker buildx ls
|
||||
- name: short-sha
|
||||
id: short-sha
|
||||
run: echo "short-sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
- run: |
|
||||
docker buildx build . \
|
||||
-t registry.local/rgbarm64lib:${{ steps.short-sha.outputs.short-sha }} \
|
||||
-t registry.local/rgbarm64lib:latest \
|
||||
--platform=linux/arm64,linux/amd64 \
|
||||
--push
|
@ -1,25 +0,0 @@
|
||||
pipeline {
|
||||
agent any
|
||||
stages {
|
||||
/*stage('GitCheckOut') {
|
||||
steps{
|
||||
checkout([$class: 'GitSCM', branches: [[name: "${env.CHECKOUT}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'gitea', url: "$GIT_URL"]]])
|
||||
}
|
||||
|
||||
}*/
|
||||
stage('buildPush') {
|
||||
steps{
|
||||
sh 'docker buildx rm jenkins-agent || echo "none there"'
|
||||
sh '''#!/bin/bash
|
||||
docker buildx create --bootstrap --name=jenkins-agent --driver=kubernetes --driver-opt=namespace=jenkinsagent --driver-opt=qemu.install=true --driver-opt=\\"nodeselector=kubernetes.io/arch=amd64\\" --driver-opt=\\"image=registry.local/buildkit-wagnerca:stable-3-rootless\\" --use
|
||||
'''
|
||||
sh 'docker buildx build . -t registry.local/rgbarm64lib:v0.0.$BUILD_NUMBER --push --platform=linux/arm64,linux/amd64'
|
||||
sh 'docker buildx build . -t registry.local/rgbarm64lib:latest --push --platform=linux/arm64,linux/amd64'
|
||||
sh 'docker buildx rm jenkins-agent'
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue