aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2019-10-05 11:33:37 +0000
committers-ol <s-ol@users.noreply.github.com>2020-02-02 15:38:06 +0000
commit8bab30cc658f0b0ab1c3de3c47b97b5e156ca6ba (patch)
tree2ca5f63767994e53720ef1cdbfce4e369aec8ead
downloadjanko-keystep-rgb-master.tar.gz
janko-keystep-rgb-master.zip
initial commitHEADmaster
Diffstat (limited to '')
-rw-r--r--.gitignore1
-rw-r--r--LICENSE339
-rw-r--r--README.md20
-rwxr-xr-xbuild.sh9
-rw-r--r--doc/bridge.pngbin0 -> 7977 bytes
-rw-r--r--doc/side.pngbin0 -> 6174 bytes
-rw-r--r--doc/underside.pngbin0 -> 9079 bytes
-rw-r--r--doc/wiring.pngbin0 -> 34265 bytes
-rw-r--r--doc/wiring.svg351
-rw-r--r--keycap.scad50
-rw-r--r--source/Key A.stlbin0 -> 151884 bytes
-rw-r--r--source/Key As.stlbin0 -> 151584 bytes
-rw-r--r--source/Key B.stlbin0 -> 207684 bytes
-rw-r--r--source/Key C End.stlbin0 -> 150784 bytes
-rw-r--r--source/Key C.stlbin0 -> 179784 bytes
-rw-r--r--source/Key Cs.stlbin0 -> 190984 bytes
-rw-r--r--source/Key D.stlbin0 -> 180284 bytes
-rw-r--r--source/Key Ds.stlbin0 -> 185084 bytes
-rw-r--r--source/Key E.stlbin0 -> 147284 bytes
-rw-r--r--source/Key F.stlbin0 -> 146484 bytes
-rw-r--r--source/Key Fs.stlbin0 -> 143784 bytes
-rw-r--r--source/Key G.stlbin0 -> 187884 bytes
-rw-r--r--source/Key Gs.stlbin0 -> 189584 bytes
-rw-r--r--source/Keycap.stlbin0 -> 472384 bytes
-rw-r--r--source/original_link.url1
25 files changed, 771 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..567609b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+build/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d159169
--- /dev/null
+++ b/LICENSE
@@ -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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8cab9e4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,20 @@
+janko-keystep-rgb
+=================
+This is a modified version of [Tom Jensen's Arturia Keystep Janko Mod](https://www.thingiverse.com/thing:3564049),
+which replaces the piano claviature with a hexagonal Janko grid.
+
+This modification adds mouting holes and wiring channels to add 3535 RGB LEDs like the WS2812B-Mini under each key,
+allowing to change the key coloring on-the-fly to reflect different scales and other information.
+
+Status
+------
+The files and print are currently untested and may undergo some more revisions to work reliably.
+
+Wiring
+------
+This picture shows the wiring for each individual key:
+
+![](doc/wiring.png)
+
+All keys should be daisy-chained together via Din/Dout, and share power.
+Small-gauge, flexible wire (enamel copper) is recommended since the LED packages and pins are small.
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..5eafa3b
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+mkdir -p build
+
+for i in $(seq 0 11); do
+ openscad keycap.scad -o "build/key_${i}.stl" -D "range = [${i}]"
+done
+
+cp source/Keycap.stl build/keycap.stl
+openscad keycap.scad -o "build/all.stl" -D "range = [0 : 11]"
diff --git a/doc/bridge.png b/doc/bridge.png
new file mode 100644
index 0000000..7c08541
--- /dev/null
+++ b/doc/bridge.png
Binary files differ
diff --git a/doc/side.png b/doc/side.png
new file mode 100644
index 0000000..a40fcb6
--- /dev/null
+++ b/doc/side.png
Binary files differ
diff --git a/doc/underside.png b/doc/underside.png
new file mode 100644
index 0000000..b1a6be6
--- /dev/null
+++ b/doc/underside.png
Binary files differ
diff --git a/doc/wiring.png b/doc/wiring.png
new file mode 100644
index 0000000..ccc8ea7
--- /dev/null
+++ b/doc/wiring.png
Binary files differ
diff --git a/doc/wiring.svg b/doc/wiring.svg
new file mode 100644
index 0000000..f69fc6d
--- /dev/null
+++ b/doc/wiring.svg
@@ -0,0 +1,351 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="203.2mm"
+ height="133.35001mm"
+ viewBox="0 0 203.2 133.35001"
+ version="1.1"
+ id="svg8"
+ inkscape:version="0.92.4 5da689c313, 2019-01-14"
+ sodipodi:docname="wiring.svg">
+ <defs
+ id="defs2">
+ <marker
+ inkscape:stockid="DotS"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="marker6647"
+ style="overflow:visible"
+ inkscape:isstock="true">
+ <path
+ id="path6645"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
+ transform="scale(0.2) translate(7.4, 1)" />
+ </marker>
+ <marker
+ inkscape:stockid="DotS"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="DotS"
+ style="overflow:visible"
+ inkscape:isstock="true">
+ <path
+ id="path6315"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1;fill:#ff0000;fill-opacity:1"
+ transform="scale(0.2) translate(7.4, 1)" />
+ </marker>
+ <marker
+ inkscape:stockid="DotL"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="DotL"
+ style="overflow:visible"
+ inkscape:isstock="true">
+ <path
+ id="path6309"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1;fill:#ff0000;fill-opacity:1"
+ transform="scale(0.8) translate(7.4, 1)" />
+ </marker>
+ <pattern
+ inkscape:collect="always"
+ xlink:href="#Strips1_1"
+ id="pattern6047"
+ patternTransform="matrix(0.31480558,0.26088256,-6.5616958,7.917963,13.363476,107.97689)" />
+ <pattern
+ inkscape:isstock="true"
+ inkscape:stockid="Stripes 1:1"
+ id="Strips1_1"
+ patternTransform="translate(0,0) scale(10,10)"
+ height="1"
+ width="2"
+ patternUnits="userSpaceOnUse"
+ inkscape:collect="always">
+ <rect
+ id="rect5317"
+ height="2"
+ width="1"
+ y="-0.5"
+ x="0"
+ style="fill:black;stroke:none" />
+ </pattern>
+ <pattern
+ inkscape:collect="always"
+ xlink:href="#Strips1_1-6"
+ id="pattern6047-3"
+ patternTransform="matrix(0.31480559,0.26088256,-6.5616957,7.9179631,86.356095,107.95417)" />
+ <pattern
+ inkscape:isstock="true"
+ inkscape:stockid="Stripes 1:1"
+ id="Strips1_1-6"
+ patternTransform="translate(0,0) scale(10,10)"
+ height="1"
+ width="2"
+ patternUnits="userSpaceOnUse"
+ inkscape:collect="always">
+ <rect
+ id="rect5317-7"
+ height="2"
+ width="1"
+ y="-0.5"
+ x="0"
+ style="fill:black;stroke:none" />
+ </pattern>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4"
+ inkscape:cx="420.60928"
+ inkscape:cy="239.90081"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:snap-nodes="true"
+ inkscape:snap-bbox="false"
+ inkscape:window-width="1872"
+ inkscape:window-height="1016"
+ inkscape:window-x="1940"
+ inkscape:window-y="36"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-3.4773853,-87.450005)">
+ <image
+ xlink:href="side.png"
+ sodipodi:insensitive="true"
+ style="fill:#000000;fill-opacity:1"
+ width="203.2"
+ height="133.35001"
+ preserveAspectRatio="none"
+ id="image4580"
+ x="3.4773853"
+ y="87.450005" />
+ <rect
+ style="opacity:1;vector-effect:none;fill:url(#pattern6047-3);fill-opacity:1;stroke:none;stroke-width:6.73234129;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect4585-5"
+ width="8.6538363"
+ height="3.9699061"
+ x="85.423531"
+ y="130.84111"
+ ry="0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.66500002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.66500005, 1.99500015;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker6647)"
+ d="m 87.346425,145.77173 3.821435,-0.3071 c 0,0 2.244233,0.33072 2.267858,3.33091"
+ id="path6643"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.66500002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
+ d="m 20.636104,152.57775 66.710321,-6.80602"
+ id="path6244-7"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <rect
+ style="opacity:1;vector-effect:none;fill:url(#pattern6047);fill-opacity:1;stroke:none;stroke-width:6.73234129;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect4585"
+ width="8.6538363"
+ height="3.9699061"
+ x="12.430914"
+ y="130.86382"
+ ry="0" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777778px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332;"
+ x="85.403725"
+ y="129.89674"
+ id="text6075"><tspan
+ sodipodi:role="line"
+ id="tspan6073"
+ x="85.403725"
+ y="129.89674"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777778px;font-family:monospace;-inkscape-font-specification:monospace;stroke-width:0.26458332;">LED1</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ x="12.771268"
+ y="130.14319"
+ id="text6075-4"><tspan
+ sodipodi:role="line"
+ id="tspan6073-3"
+ x="12.771268"
+ y="130.14319"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777767px;font-family:monospace;-inkscape-font-specification:monospace;stroke-width:0.26458332">LED2</tspan></text>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.66500002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 187.84808,161.91741 c 0,0 -1.37352,-8.73734 -7.23215,-7.88689 -4.91369,0.75595 -80.15192,12.2174 -80.15192,12.2174"
+ id="path6095"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.66500002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.66500005, 1.99500015;stroke-dashoffset:1.66250014;stroke-opacity:1"
+ d="m 100.44694,166.246 c 0,0 -6.482291,2.04107 -6.765771,-3.72306 -0.315937,-6.42409 -0.472471,-27.68675 -0.472471,-27.68675"
+ id="path6095-4"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csc" />
+ <path
+ style="fill:none;stroke:#ff0000;stroke-width:0.66500002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.66500005, 1.99500015;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 12.965453,135.20695 0.133635,18.30796 c 0,0 1.202713,4.14268 6.347651,3.34088"
+ id="path6129"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#04ff00;stroke-width:0.66500002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.66500006, 1.99500017;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 15.161574,135.20658 0.133635,16.57072 c 0,0 -0.7684,4.72732 3.842,3.8587"
+ id="path6129-3"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#ff8300;stroke-width:0.66500002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.66500006, 1.99500017;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 17.232914,135.07294 10e-7,14.63302 c 0,0 -0.835218,4.51017 2.037929,4.44335"
+ id="path6129-7"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.66500002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.66500007, 1.99500019;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 19.516918,135.10498 0.0167,14.31565 c 0,0 -0.634767,3.22393 1.102486,3.15712"
+ id="path6129-7-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#00df00;stroke-width:0.66500002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 185.13004,165.52675 c 0,0 -0.77216,-9.17166 -6.63079,-8.32121 -4.91369,0.75595 -78.09065,12.39829 -78.09065,12.39829"
+ id="path6095-0"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#ffff00;stroke-width:0.66500002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 186.62269,163.8056 c 0,0 -1.20647,-9.03802 -7.0651,-8.18757 -4.91369,0.75595 -79.12811,12.13912 -79.12811,12.13912"
+ id="path6095-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#fff500;stroke-width:0.66500002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.66500005, 1.99500015;stroke-dashoffset:1.52950013;stroke-opacity:1"
+ d="m 100.50561,167.79943 c 0,0 -9.130099,1.75455 -9.216485,-5.67943 -0.07474,-6.43142 -0.197095,-26.95508 -0.197095,-26.95508"
+ id="path6095-4-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csc" />
+ <path
+ style="fill:none;stroke:#ff0000;stroke-width:0.66500002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 183.28063,167.54319 c 0,0 -0.63853,-9.10484 -6.49716,-8.25439 -4.91369,0.75595 -76.4606,12.01503 -76.4606,12.01503"
+ id="path6095-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#fe0000;stroke-width:0.66500002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.66500005, 1.99500015;stroke-dashoffset:1.72900009;stroke-opacity:1"
+ d="m 100.32287,171.30383 c 0,0 -12.562765,1.25027 -12.562763,-6.9359 2e-6,-6.43187 -0.700959,-29.35419 -0.700959,-29.35419"
+ id="path6095-4-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="csc" />
+ <path
+ style="fill:none;stroke:#ff0000;stroke-width:0.66500002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#DotS)"
+ d="m 19.446739,156.85579 65.681485,-7.28311 c 0,0 2.605878,-0.13363 2.472245,1.80408"
+ id="path6246"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#00df00;stroke-width:0.66500002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.66500005, 1.99500015;stroke-dashoffset:0.59850001;stroke-opacity:1"
+ d="m 100.4086,169.60383 c 0,0 -10.893951,0.94331 -10.941195,-6.28546 -0.02102,-3.21586 -0.110987,-9.96625 -0.0044,-13.04023 0.06311,-1.82027 -2.334577,-1.95629 -2.334577,-1.95629"
+ id="path6095-4-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cssc" />
+ <path
+ style="fill:none;stroke:#00ff00;stroke-width:0.66500002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 87.128411,148.32185 19.137209,155.636"
+ id="path6240"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#ff8300;stroke-width:0.66500002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:0.66500005, 1.99500015;stroke-dashoffset:2.52700019;stroke-opacity:1"
+ d="m 89.137267,135.07331 0.133636,10.81367 c 0,0 0.0081,1.13925 -2.051772,1.27289"
+ id="path6242"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#ff8300;stroke-width:0.66500002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 19.270844,154.14931 67.948287,-6.98944"
+ id="path6244"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777767px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
+ x="188.58011"
+ y="162.11674"
+ id="text6855"><tspan
+ sodipodi:role="line"
+ id="tspan6853"
+ x="188.58011"
+ y="162.11674"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777767px;font-family:monospace;-inkscape-font-specification:monospace;stroke-width:0.26458332">GND</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777767px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.065;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+ x="182.95425"
+ y="171.89507"
+ id="text6859"><tspan
+ sodipodi:role="line"
+ id="tspan6857"
+ x="182.95425"
+ y="171.89507"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777767px;font-family:monospace;-inkscape-font-specification:monospace;stroke-width:0.065;stroke:#000000;stroke-opacity:1;fill:#ff0000;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none">3V3</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777767px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:0.065;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+ x="187.76511"
+ y="165.74248"
+ id="text6863"><tspan
+ sodipodi:role="line"
+ id="tspan6861"
+ x="187.76511"
+ y="165.74248"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777767px;font-family:monospace;-inkscape-font-specification:monospace;stroke-width:0.065;fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none">D-IN</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777767px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;fill:#00ff00;fill-opacity:1;stroke:#000000;stroke-width:0.065;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+ x="185.48793"
+ y="168.68784"
+ id="text6867"><tspan
+ sodipodi:role="line"
+ id="tspan6865"
+ x="185.48793"
+ y="168.68784"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52777767px;font-family:monospace;-inkscape-font-specification:monospace;stroke-width:0.065;fill:#00ff00;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none">D-OUT</tspan></text>
+ </g>
+</svg>
diff --git a/keycap.scad b/keycap.scad
new file mode 100644
index 0000000..7e280c6
--- /dev/null
+++ b/keycap.scad
@@ -0,0 +1,50 @@
+range = [ 0 : 11 ];
+
+base_pos = [-66.68750, -28.00167 - 3.5, 6];
+key_names = ["C", "Cs", "D", "Ds", "E", "F", "Fs", "G", "Gs", "A", "As", "B"];
+
+* translate([0, 0, 10])
+import("source/Keycap.stl", convexity=3);
+
+for (i = range)
+ key(i);
+
+step_x = 24.245 / 2;
+step_y = 42.00223 / 2;
+function mountpos(i, row) =
+ base_pos +
+ [
+ step_x * i,
+ step_y * (row + i % 2),
+ 0
+ ];
+
+module ledspace(upper, depth) {
+ rotate([0,0,45]) {
+ // cut a 2mm hole for the LED to rest in
+ cube([3.75, 3.55, 4], center=true);
+
+ difference() {
+ // 3.3x3.x3mm shaft for cables
+ cube([3.3, 3.3, upper ? 42 : 32], center=true);
+
+ // little bridge to hold LED
+ translate([0, 0, -2.01 - 1.5/2])
+ cube([1.5, 4, 1.5], center=true);
+ }
+ };
+
+ translate([0, upper ? -2 : 2, -13.5 + depth * 2])
+ cube([3.1, 5, 3], center=true);
+}
+
+module key(i) {
+ difference() {
+ import(str("source/Key ", key_names[i], ".stl"), convexity=3);
+
+ translate(mountpos(i, 0))
+ ledspace(false, i % 2);
+ translate(mountpos(i, 2))
+ ledspace(true, 2 + i % 2);
+ }
+}
diff --git a/source/Key A.stl b/source/Key A.stl
new file mode 100644
index 0000000..2e188bb
--- /dev/null
+++ b/source/Key A.stl
Binary files differ
diff --git a/source/Key As.stl b/source/Key As.stl
new file mode 100644
index 0000000..6a08c7a
--- /dev/null
+++ b/source/Key As.stl
Binary files differ
diff --git a/source/Key B.stl b/source/Key B.stl
new file mode 100644
index 0000000..6a1b63f
--- /dev/null
+++ b/source/Key B.stl
Binary files differ
diff --git a/source/Key C End.stl b/source/Key C End.stl
new file mode 100644
index 0000000..43ee652
--- /dev/null
+++ b/source/Key C End.stl
Binary files differ
diff --git a/source/Key C.stl b/source/Key C.stl
new file mode 100644
index 0000000..4030df6
--- /dev/null
+++ b/source/Key C.stl
Binary files differ
diff --git a/source/Key Cs.stl b/source/Key Cs.stl
new file mode 100644
index 0000000..22881ee
--- /dev/null
+++ b/source/Key Cs.stl
Binary files differ
diff --git a/source/Key D.stl b/source/Key D.stl
new file mode 100644
index 0000000..c34334a
--- /dev/null
+++ b/source/Key D.stl
Binary files differ
diff --git a/source/Key Ds.stl b/source/Key Ds.stl
new file mode 100644
index 0000000..196e91d
--- /dev/null
+++ b/source/Key Ds.stl
Binary files differ
diff --git a/source/Key E.stl b/source/Key E.stl
new file mode 100644
index 0000000..419877b
--- /dev/null
+++ b/source/Key E.stl
Binary files differ
diff --git a/source/Key F.stl b/source/Key F.stl
new file mode 100644
index 0000000..7f6bd58
--- /dev/null
+++ b/source/Key F.stl
Binary files differ
diff --git a/source/Key Fs.stl b/source/Key Fs.stl
new file mode 100644
index 0000000..3aef67a
--- /dev/null
+++ b/source/Key Fs.stl
Binary files differ
diff --git a/source/Key G.stl b/source/Key G.stl
new file mode 100644
index 0000000..8437b0e
--- /dev/null
+++ b/source/Key G.stl
Binary files differ
diff --git a/source/Key Gs.stl b/source/Key Gs.stl
new file mode 100644
index 0000000..6d2ffce
--- /dev/null
+++ b/source/Key Gs.stl
Binary files differ
diff --git a/source/Keycap.stl b/source/Keycap.stl
new file mode 100644
index 0000000..32370a1
--- /dev/null
+++ b/source/Keycap.stl
Binary files differ
diff --git a/source/original_link.url b/source/original_link.url
new file mode 100644
index 0000000..7f3f32a
--- /dev/null
+++ b/source/original_link.url
@@ -0,0 +1 @@
+https://www.thingiverse.com/thing:3564049