├── .gitignore ├── LICENSE ├── LICENSE-models ├── README.md ├── doc └── intro.md ├── guide ├── README.org ├── application-of-switches-and-caps.jpg ├── circuit-diagram.png ├── diode-diagram-drive-columns.png ├── diode-diagram-drive-rows.png ├── hotglue-left-hand.jpg ├── left-hand-mcp-1.jpg ├── left-hand-mcp-2.jpg ├── left-hand-pcb-pyralux.png ├── madness.jpg ├── right-hand-pcb-1.jpg ├── right-hand-pcb-pyralux.png ├── right-hand-pcb-with-teensy.jpg ├── rows-and-columns-connected-to-chips.jpg ├── teensy-1.jpg ├── teensy-2-fuxor-reziztorrs.jpg ├── thumb-key-wiring.jpg ├── trrs-jack.jpg ├── wiring-create-columns-left.jpg ├── wiring-create-columns-right.jpg ├── wiring-create-rows-both-sides.jpg ├── wiring-create-rows-testing.jpg ├── wiring_create_rows.jpg └── workbench.jpg ├── project.clj ├── qmk-guide ├── README.md ├── dactyl-breadboard.jpg ├── dactyl-circuit-diagram.png ├── dactyl-keymapping.png ├── dactyl-left-wiring.jpg ├── dactyl-pull-up-resistors.jpg ├── dactyl-right-wiring.jpg ├── digikey-shopping-cart.csv ├── massdrop-ergodox-build-guide.pdf └── trrs-diagram.jpg ├── resources ├── Cc-by-nc-sa_icon.svg ├── glamourshot.png ├── pcb-left.svg ├── pcb-right.svg └── prototype.jpg ├── src └── dactyl_keyboard │ ├── dactyl.clj │ ├── lightcycle.clj │ ├── util.clj │ └── wrist.clj ├── target ├── repl-port └── stale │ └── extract-native.dependencies └── test └── dactyl_cave └── core_test.clj /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | \#*\# 3 | 4 | .repl-* 5 | .nrepl-* 6 | 7 | .lein-* 8 | 9 | /target 10 | /things 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published by 637 | the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /LICENSE-models: -------------------------------------------------------------------------------- 1 | Attribution-ShareAlike 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More_considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution-ShareAlike 4.0 International Public 58 | License 59 | 60 | By exercising the Licensed Rights (defined below), You accept and agree 61 | to be bound by the terms and conditions of this Creative Commons 62 | Attribution-ShareAlike 4.0 International Public License ("Public 63 | License"). To the extent this Public License may be interpreted as a 64 | contract, You are granted the Licensed Rights in consideration of Your 65 | acceptance of these terms and conditions, and the Licensor grants You 66 | such rights in consideration of benefits the Licensor receives from 67 | making the Licensed Material available under these terms and 68 | conditions. 69 | 70 | 71 | Section 1 -- Definitions. 72 | 73 | a. Adapted Material means material subject to Copyright and Similar 74 | Rights that is derived from or based upon the Licensed Material 75 | and in which the Licensed Material is translated, altered, 76 | arranged, transformed, or otherwise modified in a manner requiring 77 | permission under the Copyright and Similar Rights held by the 78 | Licensor. For purposes of this Public License, where the Licensed 79 | Material is a musical work, performance, or sound recording, 80 | Adapted Material is always produced where the Licensed Material is 81 | synched in timed relation with a moving image. 82 | 83 | b. Adapter's License means the license You apply to Your Copyright 84 | and Similar Rights in Your contributions to Adapted Material in 85 | accordance with the terms and conditions of this Public License. 86 | 87 | c. BY-SA Compatible License means a license listed at 88 | creativecommons.org/compatiblelicenses, approved by Creative 89 | Commons as essentially the equivalent of this Public License. 90 | 91 | d. Copyright and Similar Rights means copyright and/or similar rights 92 | closely related to copyright including, without limitation, 93 | performance, broadcast, sound recording, and Sui Generis Database 94 | Rights, without regard to how the rights are labeled or 95 | categorized. For purposes of this Public License, the rights 96 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 97 | Rights. 98 | 99 | e. Effective Technological Measures means those measures that, in the 100 | absence of proper authority, may not be circumvented under laws 101 | fulfilling obligations under Article 11 of the WIPO Copyright 102 | Treaty adopted on December 20, 1996, and/or similar international 103 | agreements. 104 | 105 | f. Exceptions and Limitations means fair use, fair dealing, and/or 106 | any other exception or limitation to Copyright and Similar Rights 107 | that applies to Your use of the Licensed Material. 108 | 109 | g. License Elements means the license attributes listed in the name 110 | of a Creative Commons Public License. The License Elements of this 111 | Public License are Attribution and ShareAlike. 112 | 113 | h. Licensed Material means the artistic or literary work, database, 114 | or other material to which the Licensor applied this Public 115 | License. 116 | 117 | i. Licensed Rights means the rights granted to You subject to the 118 | terms and conditions of this Public License, which are limited to 119 | all Copyright and Similar Rights that apply to Your use of the 120 | Licensed Material and that the Licensor has authority to license. 121 | 122 | j. Licensor means the individual(s) or entity(ies) granting rights 123 | under this Public License. 124 | 125 | k. Share means to provide material to the public by any means or 126 | process that requires permission under the Licensed Rights, such 127 | as reproduction, public display, public performance, distribution, 128 | dissemination, communication, or importation, and to make material 129 | available to the public including in ways that members of the 130 | public may access the material from a place and at a time 131 | individually chosen by them. 132 | 133 | l. Sui Generis Database Rights means rights other than copyright 134 | resulting from Directive 96/9/EC of the European Parliament and of 135 | the Council of 11 March 1996 on the legal protection of databases, 136 | as amended and/or succeeded, as well as other essentially 137 | equivalent rights anywhere in the world. 138 | 139 | m. You means the individual or entity exercising the Licensed Rights 140 | under this Public License. Your has a corresponding meaning. 141 | 142 | 143 | Section 2 -- Scope. 144 | 145 | a. License grant. 146 | 147 | 1. Subject to the terms and conditions of this Public License, 148 | the Licensor hereby grants You a worldwide, royalty-free, 149 | non-sublicensable, non-exclusive, irrevocable license to 150 | exercise the Licensed Rights in the Licensed Material to: 151 | 152 | a. reproduce and Share the Licensed Material, in whole or 153 | in part; and 154 | 155 | b. produce, reproduce, and Share Adapted Material. 156 | 157 | 2. Exceptions and Limitations. For the avoidance of doubt, where 158 | Exceptions and Limitations apply to Your use, this Public 159 | License does not apply, and You do not need to comply with 160 | its terms and conditions. 161 | 162 | 3. Term. The term of this Public License is specified in Section 163 | 6(a). 164 | 165 | 4. Media and formats; technical modifications allowed. The 166 | Licensor authorizes You to exercise the Licensed Rights in 167 | all media and formats whether now known or hereafter created, 168 | and to make technical modifications necessary to do so. The 169 | Licensor waives and/or agrees not to assert any right or 170 | authority to forbid You from making technical modifications 171 | necessary to exercise the Licensed Rights, including 172 | technical modifications necessary to circumvent Effective 173 | Technological Measures. For purposes of this Public License, 174 | simply making modifications authorized by this Section 2(a) 175 | (4) never produces Adapted Material. 176 | 177 | 5. Downstream recipients. 178 | 179 | a. Offer from the Licensor -- Licensed Material. Every 180 | recipient of the Licensed Material automatically 181 | receives an offer from the Licensor to exercise the 182 | Licensed Rights under the terms and conditions of this 183 | Public License. 184 | 185 | b. Additional offer from the Licensor -- Adapted Material. 186 | Every recipient of Adapted Material from You 187 | automatically receives an offer from the Licensor to 188 | exercise the Licensed Rights in the Adapted Material 189 | under the conditions of the Adapter's License You apply. 190 | 191 | c. No downstream restrictions. You may not offer or impose 192 | any additional or different terms or conditions on, or 193 | apply any Effective Technological Measures to, the 194 | Licensed Material if doing so restricts exercise of the 195 | Licensed Rights by any recipient of the Licensed 196 | Material. 197 | 198 | 6. No endorsement. Nothing in this Public License constitutes or 199 | may be construed as permission to assert or imply that You 200 | are, or that Your use of the Licensed Material is, connected 201 | with, or sponsored, endorsed, or granted official status by, 202 | the Licensor or others designated to receive attribution as 203 | provided in Section 3(a)(1)(A)(i). 204 | 205 | b. Other rights. 206 | 207 | 1. Moral rights, such as the right of integrity, are not 208 | licensed under this Public License, nor are publicity, 209 | privacy, and/or other similar personality rights; however, to 210 | the extent possible, the Licensor waives and/or agrees not to 211 | assert any such rights held by the Licensor to the limited 212 | extent necessary to allow You to exercise the Licensed 213 | Rights, but not otherwise. 214 | 215 | 2. Patent and trademark rights are not licensed under this 216 | Public License. 217 | 218 | 3. To the extent possible, the Licensor waives any right to 219 | collect royalties from You for the exercise of the Licensed 220 | Rights, whether directly or through a collecting society 221 | under any voluntary or waivable statutory or compulsory 222 | licensing scheme. In all other cases the Licensor expressly 223 | reserves any right to collect such royalties. 224 | 225 | 226 | Section 3 -- License Conditions. 227 | 228 | Your exercise of the Licensed Rights is expressly made subject to the 229 | following conditions. 230 | 231 | a. Attribution. 232 | 233 | 1. If You Share the Licensed Material (including in modified 234 | form), You must: 235 | 236 | a. retain the following if it is supplied by the Licensor 237 | with the Licensed Material: 238 | 239 | i. identification of the creator(s) of the Licensed 240 | Material and any others designated to receive 241 | attribution, in any reasonable manner requested by 242 | the Licensor (including by pseudonym if 243 | designated); 244 | 245 | ii. a copyright notice; 246 | 247 | iii. a notice that refers to this Public License; 248 | 249 | iv. a notice that refers to the disclaimer of 250 | warranties; 251 | 252 | v. a URI or hyperlink to the Licensed Material to the 253 | extent reasonably practicable; 254 | 255 | b. indicate if You modified the Licensed Material and 256 | retain an indication of any previous modifications; and 257 | 258 | c. indicate the Licensed Material is licensed under this 259 | Public License, and include the text of, or the URI or 260 | hyperlink to, this Public License. 261 | 262 | 2. You may satisfy the conditions in Section 3(a)(1) in any 263 | reasonable manner based on the medium, means, and context in 264 | which You Share the Licensed Material. For example, it may be 265 | reasonable to satisfy the conditions by providing a URI or 266 | hyperlink to a resource that includes the required 267 | information. 268 | 269 | 3. If requested by the Licensor, You must remove any of the 270 | information required by Section 3(a)(1)(A) to the extent 271 | reasonably practicable. 272 | 273 | b. ShareAlike. 274 | 275 | In addition to the conditions in Section 3(a), if You Share 276 | Adapted Material You produce, the following conditions also apply. 277 | 278 | 1. The Adapter's License You apply must be a Creative Commons 279 | license with the same License Elements, this version or 280 | later, or a BY-SA Compatible License. 281 | 282 | 2. You must include the text of, or the URI or hyperlink to, the 283 | Adapter's License You apply. You may satisfy this condition 284 | in any reasonable manner based on the medium, means, and 285 | context in which You Share Adapted Material. 286 | 287 | 3. You may not offer or impose any additional or different terms 288 | or conditions on, or apply any Effective Technological 289 | Measures to, Adapted Material that restrict exercise of the 290 | rights granted under the Adapter's License You apply. 291 | 292 | 293 | Section 4 -- Sui Generis Database Rights. 294 | 295 | Where the Licensed Rights include Sui Generis Database Rights that 296 | apply to Your use of the Licensed Material: 297 | 298 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 299 | to extract, reuse, reproduce, and Share all or a substantial 300 | portion of the contents of the database; 301 | 302 | b. if You include all or a substantial portion of the database 303 | contents in a database in which You have Sui Generis Database 304 | Rights, then the database in which You have Sui Generis Database 305 | Rights (but not its individual contents) is Adapted Material, 306 | 307 | including for purposes of Section 3(b); and 308 | c. You must comply with the conditions in Section 3(a) if You Share 309 | all or a substantial portion of the contents of the database. 310 | 311 | For the avoidance of doubt, this Section 4 supplements and does not 312 | replace Your obligations under this Public License where the Licensed 313 | Rights include other Copyright and Similar Rights. 314 | 315 | 316 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 317 | 318 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 319 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 320 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 321 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 322 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 323 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 324 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 325 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 326 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 327 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 328 | 329 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 330 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 331 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 332 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 333 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 334 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 335 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 336 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 337 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 338 | 339 | c. The disclaimer of warranties and limitation of liability provided 340 | above shall be interpreted in a manner that, to the extent 341 | possible, most closely approximates an absolute disclaimer and 342 | waiver of all liability. 343 | 344 | 345 | Section 6 -- Term and Termination. 346 | 347 | a. This Public License applies for the term of the Copyright and 348 | Similar Rights licensed here. However, if You fail to comply with 349 | this Public License, then Your rights under this Public License 350 | terminate automatically. 351 | 352 | b. Where Your right to use the Licensed Material has terminated under 353 | Section 6(a), it reinstates: 354 | 355 | 1. automatically as of the date the violation is cured, provided 356 | it is cured within 30 days of Your discovery of the 357 | violation; or 358 | 359 | 2. upon express reinstatement by the Licensor. 360 | 361 | For the avoidance of doubt, this Section 6(b) does not affect any 362 | right the Licensor may have to seek remedies for Your violations 363 | of this Public License. 364 | 365 | c. For the avoidance of doubt, the Licensor may also offer the 366 | Licensed Material under separate terms or conditions or stop 367 | distributing the Licensed Material at any time; however, doing so 368 | will not terminate this Public License. 369 | 370 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 371 | License. 372 | 373 | 374 | Section 7 -- Other Terms and Conditions. 375 | 376 | a. The Licensor shall not be bound by any additional or different 377 | terms or conditions communicated by You unless expressly agreed. 378 | 379 | b. Any arrangements, understandings, or agreements regarding the 380 | Licensed Material not stated herein are separate from and 381 | independent of the terms and conditions of this Public License. 382 | 383 | 384 | Section 8 -- Interpretation. 385 | 386 | a. For the avoidance of doubt, this Public License does not, and 387 | shall not be interpreted to, reduce, limit, restrict, or impose 388 | conditions on any use of the Licensed Material that could lawfully 389 | be made without permission under this Public License. 390 | 391 | b. To the extent possible, if any provision of this Public License is 392 | deemed unenforceable, it shall be automatically reformed to the 393 | minimum extent necessary to make it enforceable. If the provision 394 | cannot be reformed, it shall be severed from this Public License 395 | without affecting the enforceability of the remaining terms and 396 | conditions. 397 | 398 | c. No term or condition of this Public License will be waived and no 399 | failure to comply consented to unless expressly agreed to by the 400 | Licensor. 401 | 402 | d. Nothing in this Public License constitutes or may be interpreted 403 | as a limitation upon, or waiver of, any privileges and immunities 404 | that apply to the Licensor or You, including from the legal 405 | processes of any jurisdiction or authority. 406 | 407 | 408 | ======================================================================= 409 | 410 | Creative Commons is not a party to its public 411 | licenses. Notwithstanding, Creative Commons may elect to apply one of 412 | its public licenses to material it publishes and in those instances 413 | will be considered the “Licensor.” The text of the Creative Commons 414 | public licenses is dedicated to the public domain under the CC0 Public 415 | Domain Dedication. Except for the limited purpose of indicating that 416 | material is shared under a Creative Commons public license or as 417 | otherwise permitted by the Creative Commons policies published at 418 | creativecommons.org/policies, Creative Commons does not authorize the 419 | use of the trademark "Creative Commons" or any other trademark or logo 420 | of Creative Commons without its prior written consent including, 421 | without limitation, in connection with any unauthorized modifications 422 | to any of its public licenses or any other arrangements, 423 | understandings, or agreements concerning use of licensed material. For 424 | the avoidance of doubt, this paragraph does not form part of the 425 | public licenses. 426 | 427 | Creative Commons may be contacted at creativecommons.org. 428 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Ex-Dactyl Keyboard 2 | The Ex-Dactyl is an extended version of Dactyl keyboard, which is a parameterized, split-hand, concave, columnar, ergonomic keyboard. 3 | 4 | ![](https://thingiverse-production-new.s3.amazonaws.com/assets/59/64/c4/50/0d/IMG_5335.JPG) 5 | ![](https://thingiverse-production-new.s3.amazonaws.com/assets/6c/6e/a8/60/f7/IMG_6127.JPG) 6 | 7 | You can download it from [Thingiverse](https://www.thingiverse.com/thing:3815317) 8 | 9 | ## Assembly 10 | 11 | ### Generating a Design 12 | 13 | **Setting up the Clojure environment** 14 | * [Install the Clojure runtime](https://clojure.org) 15 | * [Install the Leiningen project manager](http://leiningen.org/) 16 | * [Install OpenSCAD](http://www.openscad.org/) 17 | 18 | **Generating the design** 19 | * Run `lein repl` 20 | * Load the file `(load-file "src/dactyl_keyboard/dactyl.clj")` 21 | * This will regenerate the `things/*.scad` files 22 | * Use OpenSCAD to open a `.scad` file. 23 | * Make changes to design, repeat `load-file`, OpenSCAD will watch for changes and rerender. 24 | * When done, use OpenSCAD to export STL files 25 | 26 | **Tips** 27 | * [Some other ways to evaluate the clojure design file](http://stackoverflow.com/a/28213489) 28 | * [Example designing with clojure](http://adereth.github.io/blog/2014/04/09/3d-printing-with-clojure/) 29 | 30 | 31 | ### Printing 32 | Pregenerated STL files are available in the [things/](things/) directory after generation. 33 | 34 | ### Wiring 35 | Masks for the flexible PCBs I used are available for the [left](resources/pcb-left.svg) and [right](resources/pcb-right.svg) side. 36 | 37 | A [very rough guide for the brave is here](guide/README.org#wiring) - It will be improved over time (**TODO**)! 38 | 39 | ## License 40 | 41 | Copyright © 2015 Matthew Adereth 42 | 43 | The source code for generating the models (everything excluding the [things/](things/) and [resources/](resources/) directories is distributed under the [GNU AFFERO GENERAL PUBLIC LICENSE Version 3](LICENSE). The generated models and PCB designs are distributed under the [Creative Commons Attribution-ShareAlike License Version 4.0](LICENSE-models). 44 | -------------------------------------------------------------------------------- /doc/intro.md: -------------------------------------------------------------------------------- 1 | # Introduction to dactyl-cave 2 | 3 | TODO: write [great documentation](http://jacobian.org/writing/great-documentation/what-to-write/) 4 | -------------------------------------------------------------------------------- /guide/README.org: -------------------------------------------------------------------------------- 1 | * Preparation and Cost 2 | Get all the parts / raw material: 3 | - For the 3D printing there are two options: 4 | 1. Filament, which is the basis for 3D printing. Luckily I could print at my work-place 5 | which reduced the cost from 210€ to 70€. The kind of filament you need depends on the 3D 6 | printer you have available. 7 | 2. Buy the printout of adareth's model at shapeways for 210€ over here 8 | http://www.shapeways.com/designer/adereth/creations 9 | - Decide on the switches 10 | - If you are going to invest a whole lot of time and money for a custom keyboard instead of 11 | buying one for 10€ I'd recommend to use your favorite switch-type. To make a 12 | well-informed decision I bought a switch-tester for this from massdrop and decided on 13 | Cherry MX Whites. https://www.massdrop.com/buy/varmilo-switch-tester-with-anodized-case 14 | - I ordered 70 Cherry MX Whites from here: 15 | https://mechanicalkeyboards.com/shop/index.php?l=product_detail&p=847 16 | - Decide on the key caps 17 | - On the glamour shot you can see the 1976 keycap set; it used to be sold over here: 18 | http://pimpmykeyboard.com/sa-1976-keycap-set/ but the link is dead right now. You could 19 | try this link: https://www.massdrop.com/buy/nineteenseventysix-sa-keycap-set but it is a 20 | massdrop which is way different from usual online-stores. If you find a site that sells 21 | these, make sure you get the right amount and type of keys according to the layout. 22 | - I got the "TKL Base Set + TKL Modifier" from over here: 23 | http://pimpmykeyboard.com/dsa-pbt-abs-blank-keycap-sets/ but I'm still two long keys 24 | short, I will have to order those specifically and I have a bunch of keys I don't use 25 | left-over. 26 | - The USB-Cable that connects the keyboard to your computer 27 | - It's an USB 2.0 to USB Mini-B cable, make sure you get one that is 2 meters long, it 28 | really makes handling the keyboard so much more comfortable 29 | - https://www.amazon.de/gp/product/B00NH11N5A/ 30 | - The main controller (right half) 31 | - A Teensy 2.0, I got that one from here: https://www.pjrc.com/store/teensy.html 32 | - The chip, connectors and cable to give life to the left half 33 | - TRRS cable and jacks 34 | - Got my TRRS cable from here: http://www.digikey.de/product-search/de?keywords=839-1257-ND 35 | - Got my TRRS jacks from here: http://www.digikey.de/product-search/de?keywords=CP-43514-ND 36 | - MCP23018 16 bit IO Expander 37 | - Got mine from here: http://www.digikey.de/product-search/de?keywords=MCP23018-E%2FSP-ND 38 | 39 | What I spend on my keyboard (should give you a rough estimate for your build): 40 | | item | cost | 41 | |-----------------------------------+------| 42 | | filament | 70 | 43 | | switch-tester | 30 | 44 | | key-caps | 70 | 45 | | teensy 2.0 | 30 | 46 | | switches | 60 | 47 | | usb cable | 10 | 48 | | IO Expander, TRRS jacks and cable | 30 | 49 | |-----------------------------------+------| 50 | | overall cost | 300 | 51 | #+TBLFM: @9$2=vsum(@2$2..@8$2) 52 | 53 | My choices / advantages: 54 | - Using the soldering iron at the uni-workshop for free 55 | - 76 Diodes for free 56 | - Soldering wire and copper for free 57 | - All the resistors used for free (5 resistors are used) 58 | - Several files for working out the rough edges of the 3D-printout 59 | 60 | Depending on what you have available you might spend more or less money than me; however, 300€ 61 | is a good rough estimate. 62 | 63 | After all the parts have arrived it is safe to move on to the next section. 64 | 65 | * Wiring 66 | It is assumed that you have printed the casing successfully. 67 | 68 | 1) Plug the switches into the casing. No glue is needed; the casing provides the perfect fit. 69 | 2) Put the keycaps on the switches 70 | - Note that in the pictures here some of the long keys on the thumb-part are too short; 71 | that's why it doesn't look symmetrical 72 | 73 | [[file:application-of-switches-and-caps.jpg]] 74 | 75 | Now going further on in the guide there are two options 76 | 1. The first option is to print flexible PCBs. The advantage is that you save a lot of wiring 77 | business, everything looks rather clean and you don't have to worry about your cables being too 78 | thick such that the casing doesn't close. However, if you don't have the means to print out such 79 | PCBs there is the second option, wiring everything by hand. 80 | - The guide for this PCB-option is very rough indeed and it doesn't include the firmware 81 | used. Wiring and firmware play extremely close together--wiring before knowing your 82 | firmware is like buying a shoe without measuring your feet before. For this option, 83 | information about the exact firmware is not published, this in addition to the fact that 84 | the pictures in this rough guide are incomplete makes this option extremely 85 | beginner-unfriendly. Going in blind-sided like this may lead to one of these things: 86 | 1. reprogramming huge parts of the firmware to match your wiring, which comes with a ton of 87 | debugging. 88 | 2. rewiring to adapt to what the firmware expects, which may easily double your work here. 89 | - [[Route 1: Dactyl Flexible PCB Rough Guide]] 90 | 2. The second option is to hand-wire everything. For people like me, who had never soldered before, 91 | this was great pain and pleasure. 92 | - Here too firmware and wiring go hand in hand, you pretty much have to have a detailed look 93 | at the firmware you are using before wiring anything. I provide my modification of the 94 | "ergodox-firmware" over here: https://github.com/BubblesToTheLimit/ergodox-firmware 95 | - TODO: Make a successfull pull-request, such that it is available in the official 96 | ergodox-firmware 97 | - Some of the steps of this guide may not be described in much detail, but in contrast to 98 | option one there is a whole lot more information. 99 | - [[Route 2: Dactyl Hand-Wiring Guide]] 100 | 101 | ** Route 1: Dactyl Flexible PCB Rough Guide 102 | [[workbench.jpg]] 103 | 104 | For now, take a look at the images and try to figure things out; I know that's not great (it's 105 | better than nothing!) 106 | 107 | *** Making the PCB 108 | Get two sheets of 6in square Pyralux™. Use the Toner Transfer method to etch the Pyralux sheets as 109 | you would a usual PCB 110 | 111 | #+BEGIN_QUOTE 112 | NOTE: If you only have an Inkjet make photocopies of the print out. Voilà, Toner based copies! 113 | #+END_QUOTE 114 | 115 | [[http://www.instructables.com/id/Toner-transfer-no-soak-high-quality-double-sided/][Here's a handy toner transfer guide ...]] 116 | 117 | Print these PCB designs out... 118 | 119 | Left hand: 120 | 121 | [[left-hand-pcb-pyralux.png]] 122 | 123 | Right hand: 124 | 125 | [[right-hand-pcb-pyralux.png]] 126 | 127 | When you're done etching, you'll need to carefully cut the pcb into pieces... See the images 128 | below. 129 | 130 | *** Applying the PCB to the electronical parts 131 | The thumb cluster pcb for the left hand: 132 | 133 | [[madness.jpg]] 134 | 135 | Solder the MCP like so: 136 | 137 | [[left-hand-mcp-1.jpg]] 138 | [[left-hand-mcp-2.jpg]] 139 | 140 | Solder the Teensy 2.0 like so: 141 | 142 | [[teensy-1.jpg]] 143 | 144 | The two 2.2kΩ (Red Red Red Gold) pull-up resistors ensure a clear signal between the USB controller and the I/O expander. 145 | [[https://learn.sparkfun.com/tutorials/pull-up-resistors][Read more about pull-up resistors here]]. 146 | 147 | [[teensy-2-fuxor-reziztorrs.jpg]] 148 | 149 | Each hand of the keyboard will wire up like so: 150 | 151 | [[right-hand-pcb-1.jpg]] 152 | 153 | Teensy goes here... note the rows soldered to the teensy via the Pyralux: 154 | 155 | [[right-hand-pcb-with-teensy.jpg]] 156 | 157 | Here the left hand: 158 | 159 | [[hotglue-left-hand.jpg]] 160 | 161 | ** Route 2: Dactyl Hand-Wiring Guide 162 | *** Step 1: Creating the rows 163 | Using the copper wire you solder each row together, notice how the thumb-part gets its own 164 | row. If you take a close look you can see how I did do a messy job soldering, I had to redo 165 | some of the parts because they weren't soldered properly. Do this for both sides. It doesn't 166 | matter which of the two available pins of each switch you chose for the row, but for it to 167 | look clean you should decide for either one of them. 168 | 169 | [[file:wiring_create_rows.jpg]] 170 | 171 | [[file:wiring-create-rows-both-sides.jpg]] 172 | 173 | You might want to go ahead and test each one of the 70 switches with a multimeter. 174 | 175 | [[file:wiring-create-rows-testing.jpg]] 176 | 177 | *** Step 2: Create the columns 178 | The next step is to create the columns by soldering the diodes. There are two options for 179 | soldering the diodes, all heading towards the switch or all heading away from the 180 | switch. These two ways are called "row-driven" or "column-driven" and here again it is 181 | cruciual for the firmware and the actual wiring to be on the same page. 182 | 183 | [[file:diode-diagram-drive-columns.png]] 184 | 185 | [[file:diode-diagram-drive-rows.png]] 186 | 187 | If you want to try and use the "tmk_keyboard" firmware which seems to be also interesting you 188 | want to wire the diodes in the according way (check whether the tmk_keyboard firmware expects 189 | a row-driven or a column-driven setup). 190 | 191 | As you can see in these following pictures, I went for the "row-driven" setup (visible by the 192 | direction of the diodes, the black line being towards the key-switches). This first picture 193 | doesn't show how the 6 thumb-keys are actually individually connected to the 6 main columns, 194 | but note the small black line on each diode. 195 | 196 | [[file:wiring-create-columns-left.jpg]] 197 | 198 | This second picture shows how the 6 thumb-keys are actually connected to the 6 main columns. 199 | 200 | [[file:wiring-create-columns-right.jpg]] 201 | 202 | How thumb-keys are wired again depends on the firmware. The following picture shows the wiring 203 | of the thumb keys more clearly and also the part in the code that reflects this wiring 204 | (ergodox-firmware/src/keyboard/dactyl/matrix.h). 205 | 206 | [[file:thumb-key-wiring.jpg]] 207 | 208 | *** Step 3: Put the Teensy and the MCP in place 209 | This next step is to wire the Teensy 2.0 and the MCP 23018 in place. 210 | Everything necessary for that really is the following circuit diagram. 211 | 212 | [[file:circuit-diagram.png]] 213 | 214 | Things to note here: 215 | - The columns for the MCP go from 0 to 6, the columns for the Teensy go from 7 to D (counting 216 | in hexadecimal) which makes great sense, since the MCP is to the left of the Teensy and we 217 | read from left to right. 218 | - When debugging this and using the ergodox-firmware, both sides have to be wired completely 219 | and actually with the TRRS connected. Don't expect the keyboard to work before that. The 220 | reason is that the ergodox-firmware stops completely if either the Teensy or the MCP weren't 221 | initiated properly. 222 | - The LEDs are handy for debugging; definitely go ahead and connect those. When the keyboard 223 | starts successfully two of the LEDs light up shortly. 224 | - From the Teensy over to the MCP go exactly 4 connections. The blue, the red and the two green 225 | ones. This is done using the TRRS jacks and cable. 226 | - Yes, the connection from B4 to VCC doesn't seem to make any sense, but the B4 port actually 227 | gets used directly in the ergodox-firmware, so just connect those connections that make no 228 | sense on first sight and either don't question it or find out why this is necessary by going 229 | through the firmware in great detail. 230 | 231 | This is how the trrs jacks are wired: 232 | 233 | [[file:trrs-jack.jpg]] 234 | 235 | After you are done you might have the following result: 236 | 237 | [[file:rows-and-columns-connected-to-chips.jpg]] 238 | 239 | Good luck! 240 | -------------------------------------------------------------------------------- /guide/application-of-switches-and-caps.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/application-of-switches-and-caps.jpg -------------------------------------------------------------------------------- /guide/circuit-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/circuit-diagram.png -------------------------------------------------------------------------------- /guide/diode-diagram-drive-columns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/diode-diagram-drive-columns.png -------------------------------------------------------------------------------- /guide/diode-diagram-drive-rows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/diode-diagram-drive-rows.png -------------------------------------------------------------------------------- /guide/hotglue-left-hand.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/hotglue-left-hand.jpg -------------------------------------------------------------------------------- /guide/left-hand-mcp-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/left-hand-mcp-1.jpg -------------------------------------------------------------------------------- /guide/left-hand-mcp-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/left-hand-mcp-2.jpg -------------------------------------------------------------------------------- /guide/left-hand-pcb-pyralux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/left-hand-pcb-pyralux.png -------------------------------------------------------------------------------- /guide/madness.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/madness.jpg -------------------------------------------------------------------------------- /guide/right-hand-pcb-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/right-hand-pcb-1.jpg -------------------------------------------------------------------------------- /guide/right-hand-pcb-pyralux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/right-hand-pcb-pyralux.png -------------------------------------------------------------------------------- /guide/right-hand-pcb-with-teensy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/right-hand-pcb-with-teensy.jpg -------------------------------------------------------------------------------- /guide/rows-and-columns-connected-to-chips.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/rows-and-columns-connected-to-chips.jpg -------------------------------------------------------------------------------- /guide/teensy-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/teensy-1.jpg -------------------------------------------------------------------------------- /guide/teensy-2-fuxor-reziztorrs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/teensy-2-fuxor-reziztorrs.jpg -------------------------------------------------------------------------------- /guide/thumb-key-wiring.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/thumb-key-wiring.jpg -------------------------------------------------------------------------------- /guide/trrs-jack.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/trrs-jack.jpg -------------------------------------------------------------------------------- /guide/wiring-create-columns-left.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/wiring-create-columns-left.jpg -------------------------------------------------------------------------------- /guide/wiring-create-columns-right.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/wiring-create-columns-right.jpg -------------------------------------------------------------------------------- /guide/wiring-create-rows-both-sides.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/wiring-create-rows-both-sides.jpg -------------------------------------------------------------------------------- /guide/wiring-create-rows-testing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/wiring-create-rows-testing.jpg -------------------------------------------------------------------------------- /guide/wiring_create_rows.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/wiring_create_rows.jpg -------------------------------------------------------------------------------- /guide/workbench.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/guide/workbench.jpg -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject dactyl-keyboard "0.1.0-SNAPSHOT" 2 | :description "A parametrized, split-hand, concave, columnar, erogonomic keyboard" 3 | :url "http://example.com/FIXME" 4 | :license {:name "Eclipse Public License" 5 | :url "http://www.eclipse.org/legal/epl-v10.html"} 6 | :dependencies [[org.clojure/clojure "1.7.0"] 7 | [unicode-math "0.2.0"] 8 | [scad-clj "0.4.0"]]) 9 | 10 | 11 | -------------------------------------------------------------------------------- /qmk-guide/README.md: -------------------------------------------------------------------------------- 1 | # The EZ Way to QMK 2 | 3 | Do you love your Kinesis Advantage, but also love your Ergodox-EZ? Now you can 4 | have the best of both worlds with your very own QMK running Dactyl! Feels like a 5 | Kinesis, works like an Ergodox-EZ. 6 | 7 | I found this [Massdrop guide](massdrop-ergodox-build-guide.pdf) that shipped with their original 8 | Ergodox to be very helpful. 9 | 10 | ## Shopping List 11 | 12 | ### Things you'll have to find yourself: 13 | 14 | * Case 15 | * 70x Cherry MX compatible Switches 16 | * 6x Cherry ML switches (optional) 17 | 18 | 19 | ### Things you can order from Digikey 20 | 21 | #### An aside on LEDs 22 | 23 | Before you place this order, you'll need to figure out what color you want your 24 | LEDs to be, or if you even want LEDs at all. 25 | 26 | I had a terrible time figuring out how to figure out which resistor to use with 27 | each LED. All I can attest to is that 28 | [These Orange LEDs](http://www.maxkeyboard.com/max-keyboard-orange-3mm-flangeless-replacement-led-for-backlit-mechanical-keyboard-10-pcs.html) 29 | work with 30 | [These 220Ω resistors](http://www.digikey.com/scripts/DkSearch/dksus.dll?Detail&itemSeq=229354283&uq=636318134508631803) 31 | or at least have yet to fail in my Dactyl. 32 | 33 | I was hoping that I could find these LEDs on Digikey for you, but they don't 34 | have ones with the exact specs and I don't know if that breaks the compatibility 35 | with the resistors I found. 36 | 37 | Here's 38 | [the evil mad scientist's guide](http://www.evilmadscientist.com/2012/resistors-for-leds/) 39 | to choosing resistors for LEDs, but every time I did the math, it didn't work 40 | out. 41 | 42 | Seriously, find someone who knows more about this if you're making decisions 43 | here. You're probably already more qualified than me, so open a PR and fix this 44 | session. 45 | 46 | * 70x [1N4148 Diodes](http://www.digikey.com/scripts/DkSearch/dksus.dll?Detail&itemSeq=229354375&uq=636318149504319926) 47 | * 2x [2.2kΩ Pull up Resistors](https://www.digikey.com/product-detail/en/CFR-25JB-52-2K2/2.2KQBK-ND/666) 48 | * 2x [TRRS Jacks](http://www.digikey.com/scripts/DkSearch/dksus.dll?Detail&itemSeq=229354247&uq=636318148338283334) 49 | * 1 [Teensy 2.0](https://www.digikey.com/product-detail/en/adafruit-industries-llc/199/1528-1993-ND/6827126) 50 | * 1 [MCP23018 I/O Expander](https://www.digikey.com/product-detail/en/microchip-technology/MCP23018-E-SP/MCP23018-E-SP-ND/1999505) 51 | * [28 Pin IC Socket](http://www.digikey.com/scripts/DkSearch/dksus.dll?Detail&itemSeq=229356912&uq=636318143621851738) 52 | 53 | If you want everything in this list from [Digikey](https://www.digikey.com), you 54 | can upload [this cart](digikey-shopping-cart.csv). 55 | 56 | ### Things From Amazon 57 | 58 | * 1x [MiniUSB Extender Cable](https://www.amazon.com/gp/product/B00B5HSA3Q) 59 | * Solder/Electrical Tape/Twosided tape 60 | * [30AWG wrapping wire](https://www.amazon.com/gp/product/B00GWFECWO) 61 | * TRRS Cable [this one](https://www.amazon.com/Coiled-3-5mm-Jack-Audio-Cable/dp/B019TRW4HQ) 62 | worked for me, but it's a matter of taste and how much distance you need. 63 | 64 | ## Wiring up the Matrix 65 | 66 | The firmware you choose will determine the wiring of the keyboard. Since the 67 | Ergodox-EZ isn't going anywhere **AND** has first class support in QMK by its 68 | creator, it makes pretty good sense to wire it up the same way. 69 | 70 | Here's what the matrix code for the Ergodox-EZ in QMK looks like: 71 | 72 | ```c 73 | // matrix positions 74 | { // MCP23018 75 | { k00, k10, k20, k30, k40, KC_NO }, \ 76 | { k01, k11, k21, k31, k41, k51 }, \ 77 | { k02, k12, k22, k32, k42, k52 }, \ 78 | { k03, k13, k23, k33, k43, k53 }, \ 79 | { k04, k14, k24, k34, k44, k54 }, \ 80 | { k05, k15, k25, k35, KC_NO, k55 }, \ 81 | { k06, k16, KC_NO, k36, KC_NO, k56 }, \ 82 | // Teensy 83 | { k07, k17, KC_NO, k37, KC_NO, k57 }, \ 84 | { k08, k18, k28, k38, KC_NO, k58 }, \ 85 | { k09, k19, k29, k39, k49, k59 }, \ 86 | { k0A, k1A, k2A, k3A, k4A, k5A }, \ 87 | { k0B, k1B, k2B, k3B, k4B, k5B }, \ 88 | { k0C, k1C, k2C, k3C, k4C, k5C }, \ 89 | { k0D, k1D, k2D, k3D, k4D, KC_NO } \ 90 | } 91 | ``` 92 | 93 | This is a software mapping of 14 rows, even though the physical layout will wind 94 | up with 14 columns. Physically, it looks like this: 95 | 96 | ![](dactyl-keymapping.png) 97 | 98 | Look at those colors, they'll be consistent throughout this documentation, 99 | including the physical wire we wire it up with. 100 | 101 | ### Rows 102 | 103 | You don't have to decide how to connect the rows to the Teensy or MCP yet. Just 104 | worry about getting the matrix right. 105 | 106 | Wiring rows 0-4 is easy. With the 30AWG wire, I had to cut individual wire 107 | segments from switch to switch. The thumb clusters are Row 5 on each side, so 108 | the same approach will work, it just doesn't look like a row. 109 | 110 | Row 5 is the thumb cluster, so just wire them together and imagine they're in a 111 | row instead of it being more like a circle. 112 | 113 | The rows are just wire. Individual segments connecting two switches. I used a 114 | pair of pointy tweezers to put little hooks on the end of each segment. The idea 115 | is to let the Solder do most of the work. If a day ever comes where you have to 116 | desolder one of these, you'll be glad you didn't aggressively wrap it. 117 | 118 | ### Columns 119 | 120 | The columns need to be wired with diodes. You can probably wire the entire 121 | column with the diode stems, but I chose to add some wire segments so it would 122 | look clearer for this guide. 123 | 124 | ![](dactyl-left-wiring.jpg) 125 | 126 | The diodes need the black bar facing away from the key. The other guides 127 | disagree, but they don't use QMK. 128 | 129 | To use wire segments here, I soldered the end of the diode with the black bar to 130 | the wire first, then placed the other stem on the switch, positioned the diode 131 | where I wanted it and then bet the diode stem into a hook around the switch 132 | terminal. 133 | 134 | I also made a habit of keeping the trimmed diode stems to use as bridges if 135 | needed later. 136 | 137 | **Note:** Column 6 only has one key at this point. 138 | 139 | ### Ergodox Compatibility Inner Columns 140 | 141 | **This is an optional step, and can be done as a mod after you're done** so 142 | there's no pressure to make this decision now. 143 | 144 | Ergodoxes have an additional three keys in columns 6 & 7. Do you want them on 145 | your Dactyl? 146 | 147 | I own an Ergodox-EZ as well, and want to use the same keymap for both. So I 148 | added the extra switches below the thumb clusters as Cherry ML switches. If you 149 | don't care about a consistent experience between a Dactyl and Ergodox, or even 150 | if you do, it's a matter of personal preference. 151 | 152 | Wherever you put them, they're wired into rows 0,1 and 3. Either way, you need 153 | to wire columns 6 and 7 to the top inner most key in the thumb cluster, so 154 | columns 6 & 7 are going to be live. 155 | 156 | If you go with MLs, you can put them wherever you want, but be careful measuring 157 | where the holes go, you only get one shot. 158 | 159 | **TODO:** CherryML switch hole specs. 160 | 161 | ## The Matrix Has You 162 | 163 | Actually, you have it! Congratulations on having gotten this far. 164 | 165 | ## Wiring The Right Half 166 | 167 | ### Wiring the Teensy 168 | 169 | We have to start off with the obligatory wiring diagram 170 | 171 | ![](dactyl-circuit-diagram.png) 172 | 173 | Notice the row numbers are different from the other guides to match the QMK 174 | key codes we're using. 175 | 176 | I started off by breadboarding this whole project, but I also burnt out the 177 | teensy's bootloader. 178 | [My misadventures wiring a Dactyl](http://joedevivo.com/2017/05/20/building-a-qmk-dactyl.html) 179 | are a fun read if you feel like this is too hard. I've been there. 180 | 181 | Here's the pinout mappings for the rows and columns: 182 | 183 | | Row | Wire Color | Teensy Pin | 184 | |---------|------------|------------| 185 | | 0 | Yellow | PF0 | 186 | | 1 | Orange | PF1 | 187 | | 2 | Green | PF4 | 188 | | 3 | Brown | PF5 | 189 | | 4 | Blue | PF6 | 190 | | 5 | Purple | PF7 | 191 | 192 | 193 | | Column | Wire Color | Teensy Pin | 194 | |--------|------------|------------| 195 | | 7 | Red | PB0 | 196 | | 8 | Yellow | PB1 | 197 | | 9 | Orange | PB2 | 198 | | A | Green | PB3 | 199 | | B | Brown | PD2 | 200 | | C | Blue | PD3 | 201 | | D | Purple | PC6 | 202 | 203 | Wiring the teensy involves looping the 30AWG wire through the Teensy's pinouts, 204 | I went through twice, and then dabbed a little solder. If you are ok with 205 | possibly wasting a little wire, you can use longer wire to solder up the Teensy 206 | and then breadboard with those wires. There's no room for pins in the case, so 207 | this is the best way to test it out. 208 | 209 | Here's my breadboarded version, almost done. (missing the reset wire to the MCP 210 | in this photo) 211 | 212 | ![](dactyl-breadboard.jpg) 213 | 214 | Yours will look similar, but with the Teensy coming from off board with a bunch 215 | of wires. You don't have to breadboard the columns and rows for the teensy, you 216 | can test them by clipping them to the right spot on the matrix you built. 217 | 218 | Columns and rows run by the MCP (Greetings, program!) will be accessible via the 219 | breadboard. 220 | 221 | Here's what that looks like wired in. 222 | 223 | ![](dactyl-right-wiring.jpg) 224 | 225 | Fortunately, QMK *will* let you just run the right half, so you can check in at 226 | this point and see how that all works, 227 | 228 | ### The TRRS Jack 229 | 230 | In an effort to move some of the bulk away from the Teensy, I put the pull up 231 | resistors as close to the jack as I could. 232 | 233 | ![](dactyl-pull-up-resistors.jpg) 234 | 235 | I wired the two 2.2k resistors to the bottom two terminals on the TRRS jack, 236 | then wired the SCL(PD0) and SDA(PD1) to the resistor leg going into the jack. 237 | Then soldered the outside legs together and ran a wire from Vcc to those outside 238 | legs, and from them to a third terminal on the TRRS jack. Now all you need is to 239 | run GND to the fourth terminal. 240 | 241 | ![](trrs-diagram.jpg) 242 | 243 | ## Wiring The Left Half 244 | 245 | ### Wiring the I/O Expander 246 | -------------------------------------------------------------------------------- /qmk-guide/dactyl-breadboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/qmk-guide/dactyl-breadboard.jpg -------------------------------------------------------------------------------- /qmk-guide/dactyl-circuit-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/qmk-guide/dactyl-circuit-diagram.png -------------------------------------------------------------------------------- /qmk-guide/dactyl-keymapping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/qmk-guide/dactyl-keymapping.png -------------------------------------------------------------------------------- /qmk-guide/dactyl-left-wiring.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/qmk-guide/dactyl-left-wiring.jpg -------------------------------------------------------------------------------- /qmk-guide/dactyl-pull-up-resistors.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/qmk-guide/dactyl-pull-up-resistors.jpg -------------------------------------------------------------------------------- /qmk-guide/dactyl-right-wiring.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/qmk-guide/dactyl-right-wiring.jpg -------------------------------------------------------------------------------- /qmk-guide/digikey-shopping-cart.csv: -------------------------------------------------------------------------------- 1 | Index,Quantity,Part Number,Description,Customer Reference,Available Quantity,Backorder Quantity,Unit Price USD,Extended Price USD, 2 | 1,2,CP-43514-ND,CONN JACK 4COND 3.5MM R/A,,2,0,1.06000,2.12, 3 | 2,2,2.2KQBK-ND,RES 2.2K OHM 1/4W 5% AXIAL,,2,0,0.10000,0.20, 4 | 3,3,220QBK-ND,RES 220 OHM 1/4W 5% AXIAL,,3,0,0.10000,0.30, 5 | 4,1,1528-1993-ND,TEENSY (ATMEGA32U4 USB DEV BOARD,,1,0,19.94000,19.94, 6 | 5,100,1N4148FS-ND,DIODE GEN PURP 100V 200MA DO35,,100,0,0.03080,3.08, 7 | 6,10,ED3050-5-ND,CONN IC DIP SOCKET 28POS TIN,,10,0,0.31500,3.15, 8 | 7,1,MCP23018-E/SP-ND,IC I/O EXPANDER I2C 16B 28SDIP,,1,0,1.56000,1.56, 9 | -------------------------------------------------------------------------------- /qmk-guide/massdrop-ergodox-build-guide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/qmk-guide/massdrop-ergodox-build-guide.pdf -------------------------------------------------------------------------------- /qmk-guide/trrs-diagram.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/qmk-guide/trrs-diagram.jpg -------------------------------------------------------------------------------- /resources/Cc-by-nc-sa_icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /resources/glamourshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/resources/glamourshot.png -------------------------------------------------------------------------------- /resources/prototype.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LSChyi/ex-dactyl-keyboard/1b2f6eb881d64e4b05f281d210fe5cb40e3f27a1/resources/prototype.jpg -------------------------------------------------------------------------------- /src/dactyl_keyboard/lightcycle.clj: -------------------------------------------------------------------------------- 1 | (ns dactyl-keyboard.lightcycle 2 | (:refer-clojure :exclude [use import]) 3 | (:require [scad-clj.scad :refer :all] 4 | [scad-clj.model :refer :all] 5 | [dactyl-keyboard.util :refer :all] 6 | [unicode-math.core :refer :all])) 7 | 8 | ;;;;;;;;;;;;;;;;; 9 | ;; Switch Hole ;; 10 | ;;;;;;;;;;;;;;;;; 11 | 12 | (def keyswitch-height 14.4) ;; Was 14.1, then 14.25 13 | (def keyswitch-width 14.4) 14 | 15 | (def sa-profile-key-height 12.7) 16 | 17 | (def plate-thickness 4) 18 | (def mount-width (+ keyswitch-width 3)) 19 | (def mount-height (+ keyswitch-height 3)) 20 | 21 | #_(def single-plate 22 | (let [top-wall (->> (cube (+ keyswitch-width 3) 1.5 plate-thickness) 23 | (translate [0 24 | (+ (/ 1.5 2) (/ keyswitch-height 2)) 25 | (/ plate-thickness 2)])) 26 | left-wall (->> (cube 1.5 (+ keyswitch-height 3) plate-thickness) 27 | (translate [(+ (/ 1.5 2) (/ keyswitch-width 2)) 28 | 0 29 | (/ plate-thickness 2)])) 30 | side-nub (->> (binding [*fn* 30] (cylinder 1 2.75)) 31 | (rotate (/ π 2) [1 0 0]) 32 | (translate [(+ (/ keyswitch-width 2)) 0 1]) 33 | (hull (->> (cube 1.5 2.75 plate-thickness) 34 | (translate [(+ (/ 1.5 2) (/ keyswitch-width 2)) 35 | 0 36 | (/ plate-thickness 2)])))) 37 | plate-half (union top-wall left-wall (with-fn 100 side-nub))] 38 | (union plate-half 39 | (->> plate-half 40 | (mirror [1 0 0]) 41 | (mirror [0 1 0]))))) 42 | 43 | (def alps-width 15.6) 44 | (def alps-notch-width 15.5) 45 | (def alps-notch-height 1) 46 | (def alps-height 13) 47 | 48 | (def single-plate 49 | (let [top-wall (->> (cube (+ keyswitch-width 3) 2.2 plate-thickness) 50 | (translate [0 51 | (+ (/ 2.2 2) (/ alps-height 2)) 52 | (/ plate-thickness 2)])) 53 | left-wall (union (->> (cube 1.5 (+ keyswitch-height 3) plate-thickness) 54 | (translate [(+ (/ 1.5 2) (/ 15.6 2)) 55 | 0 56 | (/ plate-thickness 2)])) 57 | (->> (cube 1.5 (+ keyswitch-height 3) 1.0) 58 | (translate [(+ (/ 1.5 2) (/ alps-notch-width 2)) 59 | 0 60 | (- plate-thickness 61 | (/ alps-notch-height 2))])) 62 | ) 63 | plate-half (union top-wall left-wall)] 64 | (union plate-half 65 | (->> plate-half 66 | (mirror [1 0 0]) 67 | (mirror [0 1 0]))))) 68 | 69 | 70 | ;;;;;;;;;;;;;;;; 71 | ;; SA Keycaps ;; 72 | ;;;;;;;;;;;;;;;; 73 | 74 | (def sa-length 18.25) 75 | (def sa-double-length 37.5) 76 | (def sa-cap {1 (let [bl2 (/ 18.5 2) 77 | m (/ 17 2) 78 | key-cap (hull (->> (polygon [[bl2 bl2] [bl2 (- bl2)] [(- bl2) (- bl2)] [(- bl2) bl2]]) 79 | (extrude-linear {:height 0.1 :twist 0 :convexity 0}) 80 | (translate [0 0 0.05])) 81 | (->> (polygon [[m m] [m (- m)] [(- m) (- m)] [(- m) m]]) 82 | (extrude-linear {:height 0.1 :twist 0 :convexity 0}) 83 | (translate [0 0 6])) 84 | (->> (polygon [[6 6] [6 -6] [-6 -6] [-6 6]]) 85 | (extrude-linear {:height 0.1 :twist 0 :convexity 0}) 86 | (translate [0 0 12])))] 87 | (->> key-cap 88 | (translate [0 0 (+ 5 plate-thickness)]) 89 | (color [220/255 163/255 163/255 1]))) 90 | 2 (let [bl2 (/ sa-double-length 2) 91 | bw2 (/ 18.25 2) 92 | key-cap (hull (->> (polygon [[bw2 bl2] [bw2 (- bl2)] [(- bw2) (- bl2)] [(- bw2) bl2]]) 93 | (extrude-linear {:height 0.1 :twist 0 :convexity 0}) 94 | (translate [0 0 0.05])) 95 | (->> (polygon [[6 16] [6 -16] [-6 -16] [-6 16]]) 96 | (extrude-linear {:height 0.1 :twist 0 :convexity 0}) 97 | (translate [0 0 12])))] 98 | (->> key-cap 99 | (translate [0 0 (+ 5 plate-thickness)]) 100 | (color [127/255 159/255 127/255 1]))) 101 | 1.5 (let [bl2 (/ 18.25 2) 102 | bw2 (/ 28 2) 103 | key-cap (hull (->> (polygon [[bw2 bl2] [bw2 (- bl2)] [(- bw2) (- bl2)] [(- bw2) bl2]]) 104 | (extrude-linear {:height 0.1 :twist 0 :convexity 0}) 105 | (translate [0 0 0.05])) 106 | (->> (polygon [[11 6] [-11 6] [-11 -6] [11 -6]]) 107 | (extrude-linear {:height 0.1 :twist 0 :convexity 0}) 108 | (translate [0 0 12])))] 109 | (->> key-cap 110 | (translate [0 0 (+ 5 plate-thickness)]) 111 | (color [240/255 223/255 175/255 1])))}) 112 | 113 | ;;;;;;;;;;;;;;;;;;;;;;;;; 114 | ;; Placement Functions ;; 115 | ;;;;;;;;;;;;;;;;;;;;;;;;; 116 | 117 | (def columns (range 0 6)) 118 | (def rows (range 1 5)) 119 | 120 | (def α (/ π 12)) 121 | (def β (/ π 36)) 122 | (def cap-top-height (+ plate-thickness sa-profile-key-height)) 123 | (def row-radius (+ (/ (/ (+ mount-height 1/2) 2) 124 | (Math/sin (/ α 2))) 125 | cap-top-height)) 126 | (def column-radius (+ (/ (/ (+ mount-width 2.0) 2) 127 | (Math/sin (/ β 2))) 128 | cap-top-height)) 129 | 130 | (defn key-place [column row shape] 131 | (let [row-placed-shape (->> shape 132 | (translate [0 0 (- row-radius)]) 133 | (rotate (* α (- 2 row)) [1 0 0]) 134 | (translate [0 0 row-radius])) 135 | column-offset (cond 136 | (= column 2) [0 2.82 -3.0] ;;was moved -4.5 137 | (>= column 4) [0 -5.8 5.64] 138 | :else [0 0 0]) 139 | column-angle (* β (- 2 column)) 140 | placed-shape (->> row-placed-shape 141 | (translate [0 0 (- column-radius)]) 142 | (rotate column-angle [0 1 0]) 143 | (translate [0 0 column-radius]) 144 | (translate column-offset))] 145 | (->> placed-shape 146 | (rotate (/ π 12) [0 1 0]) 147 | (translate [0 0 13])))) 148 | 149 | (defn case-place [column row shape] 150 | (let [row-placed-shape (->> shape 151 | (translate [0 0 (- row-radius)]) 152 | (rotate (* α (- 2 row)) [1 0 0]) 153 | (translate [0 0 row-radius])) 154 | column-offset [0 -4.35 5.64] 155 | column-angle (* β (- 2 column)) 156 | placed-shape (->> row-placed-shape 157 | (translate [0 0 (- column-radius)]) 158 | (rotate column-angle [0 1 0]) 159 | (translate [0 0 column-radius]) 160 | (translate column-offset))] 161 | (->> placed-shape 162 | (rotate (/ π 12) [0 1 0]) 163 | (translate [0 0 13])))) 164 | 165 | (def key-holes 166 | (apply union 167 | (for [column columns 168 | row rows 169 | :when (or (not= column 0) 170 | (not= row 4))] 171 | (->> single-plate 172 | (key-place column row))))) 173 | 174 | (def caps 175 | (apply union 176 | (for [column columns 177 | row rows 178 | :when (or (not= column 0) 179 | (not= row 4))] 180 | (->> (sa-cap (if (= column 5) 1 1)) 181 | (key-place column row))))) 182 | 183 | ;;;;;;;;;;;;;;;;;;;; 184 | ;; Web Connectors ;; 185 | ;;;;;;;;;;;;;;;;;;;; 186 | 187 | (def web-thickness 3.5) 188 | (def post-size 0.1) 189 | (def web-post (->> (cube post-size post-size web-thickness) 190 | (translate [0 0 (+ (/ web-thickness -2) 191 | plate-thickness)]))) 192 | 193 | (def post-adj (/ post-size 2)) 194 | (def web-post-tr (translate [(- (/ mount-width 2) post-adj) (- (/ mount-height 2) post-adj) 0] web-post)) 195 | (def web-post-tl (translate [(+ (/ mount-width -2) post-adj) (- (/ mount-height 2) post-adj) 0] web-post)) 196 | (def web-post-bl (translate [(+ (/ mount-width -2) post-adj) (+ (/ mount-height -2) post-adj) 0] web-post)) 197 | (def web-post-br (translate [(- (/ mount-width 2) post-adj) (+ (/ mount-height -2) post-adj) 0] web-post)) 198 | 199 | (def connectors 200 | (apply union 201 | (concat 202 | ;; Row connections 203 | (for [column (drop-last columns) 204 | row rows 205 | :when (or (not= column 0) 206 | (not= row 4))] 207 | (triangle-hulls 208 | (key-place (inc column) row web-post-tl) 209 | (key-place column row web-post-tr) 210 | (key-place (inc column) row web-post-bl) 211 | (key-place column row web-post-br))) 212 | 213 | ;; Column connections 214 | (for [column columns 215 | row (drop-last rows) 216 | :when (or (not= column 0) 217 | (not= row 3))] 218 | (triangle-hulls 219 | (key-place column row web-post-bl) 220 | (key-place column row web-post-br) 221 | (key-place column (inc row) web-post-tl) 222 | (key-place column (inc row) web-post-tr))) 223 | 224 | ;; Diagonal connections 225 | (for [column (drop-last columns) 226 | row (drop-last rows) 227 | :when (or (not= column 0) 228 | (not= row 3))] 229 | (triangle-hulls 230 | (key-place column row web-post-br) 231 | (key-place column (inc row) web-post-tr) 232 | (key-place (inc column) row web-post-bl) 233 | (key-place (inc column) (inc row) web-post-tl)))))) 234 | 235 | ;;;;;;;;;;;; 236 | ;; Thumbs ;; 237 | ;;;;;;;;;;;; 238 | 239 | (defn thumb-place [column row shape] 240 | (let [cap-top-height (+ plate-thickness sa-profile-key-height) 241 | α (/ π 12) 242 | row-radius (+ (/ (/ (+ mount-height 1) 2) 243 | (Math/sin (/ α 2))) 244 | cap-top-height) 245 | β (/ π 36) 246 | column-radius (+ (/ (/ (+ mount-width 2) 2) 247 | (Math/sin (/ β 2))) 248 | cap-top-height) 249 | #_(+ (/ (/ (+ pillar-width 5) 2) 250 | (Math/sin (/ β 2))) 251 | cap-top-height)] 252 | (->> shape 253 | (translate [0 0 (- row-radius)]) 254 | (rotate (* α row) [1 0 0]) 255 | (translate [0 0 row-radius]) 256 | (translate [0 0 (- column-radius)]) 257 | (rotate (* column β) [0 1 0]) 258 | (translate [0 0 column-radius]) 259 | (translate [mount-width 0 0]) 260 | (rotate (* π (- 1/4 3/16)) [0 0 1]) 261 | (rotate (/ π 12) [1 1 0]) 262 | (translate [-52 -45 40])))) 263 | 264 | (defn thumb-2x-column [shape] 265 | (thumb-place 0 -1/2 (rotate (/ π 2) [0 0 1] shape))) 266 | 267 | (defn thumb-2x+1-column [shape] 268 | (union (thumb-place 1 -1/2 (rotate (/ π 2) [0 0 1] shape)) 269 | (thumb-place 1 1 shape))) 270 | 271 | (defn thumb-1x-column [shape] 272 | (union (thumb-place 2 -1 shape) 273 | (thumb-place 2 0 shape) 274 | (thumb-place 2 1 shape))) 275 | 276 | 277 | 278 | (= (* 2 sa-length) 279 | sa-double-length) 280 | (def double-plates 281 | (let [plate-height (/ (- sa-double-length mount-height) 2) 282 | top-plate (->> (cube mount-width plate-height web-thickness) 283 | (translate [0 (/ (+ plate-height mount-height) 2) 284 | (- plate-thickness (/ web-thickness 2))])) 285 | stabilizer-cutout (union (->> (cube 14.2 3.5 web-thickness) 286 | (translate [0.5 12 (- plate-thickness (/ web-thickness 2))]) 287 | (color [1 0 0 1/2])) 288 | (->> (cube 16 3.5 web-thickness) 289 | (translate [0.5 12 (- plate-thickness (/ web-thickness 2) 1.4)]) 290 | (color [1 0 0 1/2]))) 291 | ;;top-plate (difference top-plate stabilizer-cutout) 292 | ] 293 | (color [1 0 0] (union top-plate (mirror [0 1 0] top-plate))))) 294 | 295 | (defn extended-plate-height [size] (/ (- (* (+ 1 sa-length) size) mount-height) 2)) 296 | 297 | (defn extended-plates [size] 298 | (let [plate-height (extended-plate-height size) 299 | top-plate (->> (cube mount-width plate-height web-thickness) 300 | (translate [0 (/ (+ plate-height mount-height) 2) 301 | (- plate-thickness (/ web-thickness 2))]))] 302 | (color [0 1 1] (union top-plate (mirror [0 1 0] top-plate))) 303 | )) 304 | 305 | (defn thumb-layout [shape] 306 | (union 307 | (thumb-place 0 -1/2 (union shape (extended-plates 2))) 308 | 309 | (thumb-place 1 7/8 (union shape (extended-plates 1.25))) 310 | (thumb-place 1 -5/8 (union shape (extended-plates 1.75))) 311 | 312 | (thumb-place 2 -3/4 (union shape (extended-plates 1.5))) 313 | (thumb-place 2 3/4 (union shape (extended-plates 1.5))) 314 | )) 315 | 316 | (defn thumb-layout-bottom [shape] 317 | (union 318 | (thumb-place 0 -1/2 shape) 319 | 320 | (thumb-place 1 7/8 shape) 321 | (thumb-place 1 -5/8 shape) 322 | 323 | (thumb-place 2 -3/4 shape) 324 | (thumb-place 2 3/4 shape) 325 | )) 326 | 327 | (def thumbcaps 328 | (union 329 | (thumb-2x-column (sa-cap 2)) 330 | (thumb-place 1 -1/2 (sa-cap 2)) 331 | (thumb-place 1 1 (sa-cap 1)) 332 | (thumb-1x-column (sa-cap 1)))) 333 | 334 | (def thumb-connectors 335 | (union 336 | #_(apply union 337 | (concat 338 | (for [column [2] row [1]] 339 | (triangle-hulls (thumb-place column row web-post-br) 340 | (thumb-place column row web-post-tr) 341 | (thumb-place (dec column) row web-post-bl) 342 | (thumb-place (dec column) row web-post-tl))) 343 | (for [column [2] row [0 1]] 344 | (triangle-hulls 345 | (thumb-place column row web-post-bl) 346 | (thumb-place column row web-post-br) 347 | (thumb-place column (dec row) web-post-tl) 348 | (thumb-place column (dec row) web-post-tr))))) 349 | (let [thumb-tl #(->> web-post-tl 350 | (translate [0 (extended-plate-height %) 0])) 351 | thumb-bl #(->> web-post-bl 352 | (translate [0 (- (extended-plate-height %)) 0])) 353 | thumb-tr #(->> web-post-tr 354 | (translate [0 (extended-plate-height %) 0])) 355 | thumb-br #(->> web-post-br 356 | (translate [0 (- (extended-plate-height %)) 0]))] 357 | (union 358 | 359 | ;;Connecting the double to 1.75 360 | (triangle-hulls (thumb-place 0 -1/2 (thumb-tl 2)) 361 | (thumb-place 0 -1/2 (thumb-bl 2)) 362 | (thumb-place 1 -5/8 (thumb-br 1.75)) 363 | (thumb-place 0 -1/2 (thumb-tl 2)) 364 | (thumb-place 1 -5/8 (thumb-tr 1.75)) 365 | (thumb-place 1 7/8 (thumb-br 1.25))) 366 | 367 | (triangle-hulls (thumb-place 1 7/8 (thumb-br 1.25)) 368 | (thumb-place 1 7/8 (thumb-bl 1.25)) 369 | (thumb-place 1 -5/8 (thumb-tr 1.75)) 370 | (thumb-place 1 -5/8 (thumb-tl 1.75))) 371 | 372 | (triangle-hulls (thumb-place 2 3/4 (thumb-br 1.5)) 373 | (thumb-place 2 3/4 (thumb-bl 1.5)) 374 | (thumb-place 2 -3/4 (thumb-tr 1.5)) 375 | (thumb-place 2 -3/4 (thumb-tl 1.5))) 376 | 377 | (triangle-hulls (thumb-place 2 3/4 (thumb-br 1.5)) 378 | (thumb-place 2 3/4 (thumb-bl 1.5)) 379 | (thumb-place 2 -3/4 (thumb-tr 1.5)) 380 | (thumb-place 2 -3/4 (thumb-tl 1.5))) 381 | 382 | (triangle-hulls (thumb-place 2 -3/4 (thumb-br 1.5)) 383 | (thumb-place 1 -5/8 (thumb-bl 1.75)) 384 | (thumb-place 2 -3/4 (thumb-tr 1.5)) 385 | (thumb-place 1 -5/8 (thumb-tl 1.75)) 386 | (thumb-place 2 3/4 (thumb-br 1.5)) 387 | (thumb-place 1 7/8 (thumb-bl 1.25)) 388 | (thumb-place 2 3/4 (thumb-tr 1.5)) 389 | (thumb-place 1 7/8 (thumb-tl 1.25)) 390 | ) 391 | 392 | 393 | ;;Connecting the thumb to everything 394 | (triangle-hulls (thumb-place 0 -1/2 (thumb-br 2)) 395 | (key-place 1 4 web-post-bl) 396 | (thumb-place 0 -1/2 (thumb-tr 2)) 397 | (key-place 1 4 web-post-tl) 398 | (key-place 1 3 web-post-bl) 399 | (thumb-place 0 -1/2 (thumb-tr 2)) 400 | (key-place 0 3 web-post-br) 401 | (key-place 0 3 web-post-bl) 402 | (thumb-place 0 -1/2 (thumb-tr 2)) 403 | (thumb-place 0 -1/2 (thumb-tl 2)) 404 | (key-place 0 3 web-post-bl) 405 | (thumb-place 1 -5/8 (thumb-tr 1.75)) 406 | (thumb-place 1 7/8 (thumb-br 1.25)) 407 | (key-place 0 3 web-post-bl) 408 | (key-place 0 3 web-post-tl) 409 | (thumb-place 1 7/8 (thumb-br 1.25)) 410 | (thumb-place 1 7/8 (thumb-tr 1.25)) 411 | ))))) 412 | 413 | (def thumb 414 | 415 | (union 416 | (thumb-layout (rotate (/ Math/PI 2) [0 0 1] single-plate)) 417 | (color [1 0 0] thumb-connectors) 418 | 419 | #_(thumb-place 0 -1/2 (extended-plates 2)) 420 | #_(thumb-place 1 -1/2 double-plates))) 421 | 422 | ;;;;;;;;;; 423 | ;; Case ;; 424 | ;;;;;;;;;; 425 | 426 | ;; In column units 427 | (def right-wall-column (+ (last columns) 0.55)) 428 | (def left-wall-column (- (first columns) 1/2)) 429 | (def thumb-back-y 0.93) 430 | (def thumb-right-wall (- -1/2 0.05)) 431 | (def thumb-front-row (+ -1 0.07)) 432 | (def thumb-left-wall-column (+ 5/2 0.05)) 433 | (def back-y (+ (first rows) #_0.02 -0.15)) 434 | 435 | (defn range-inclusive [start end step] 436 | (concat (range start end step) [end])) 437 | 438 | (def wall-step 0.2) 439 | (def wall-sphere-n 20) ;;Sphere resolution, lower for faster renders 440 | 441 | (defn wall-sphere-at [coords] 442 | (->> (sphere 1) 443 | (translate coords) 444 | (with-fn wall-sphere-n))) 445 | 446 | (defn scale-to-range [start end x] 447 | (+ start (* (- end start) x))) 448 | 449 | (defn wall-sphere-bottom [front-to-back-scale] 450 | (wall-sphere-at [0 451 | (scale-to-range 452 | (+ (/ mount-height -2) -3.5) 453 | (+ (/ mount-height 2) 5.0) 454 | front-to-back-scale) 455 | -6])) 456 | 457 | (defn wall-sphere-top [front-to-back-scale] 458 | (wall-sphere-at [0 459 | (scale-to-range 460 | (+ (/ mount-height -2) -3.5) 461 | (+ (/ mount-height 2) 3.5) 462 | front-to-back-scale) 463 | 5])) 464 | 465 | (def wall-sphere-top-back (wall-sphere-top 1)) 466 | (def wall-sphere-bottom-back (wall-sphere-bottom 1)) 467 | (def wall-sphere-bottom-front (wall-sphere-bottom 0)) 468 | (def wall-sphere-top-front (wall-sphere-top 0)) 469 | 470 | (defn top-case-cover [place-fn sphere 471 | x-start x-end 472 | y-start y-end 473 | step] 474 | (apply union 475 | (for [x (range-inclusive x-start (- x-end step) step) 476 | y (range-inclusive y-start (- y-end step) step)] 477 | (hull (place-fn x y sphere) 478 | (place-fn (+ x step) y sphere) 479 | (place-fn x (+ y step) sphere) 480 | (place-fn (+ x step) (+ y step) sphere))))) 481 | 482 | (def front-wall 483 | (let [step wall-step ;;0.1 484 | wall-step 0.05 ;;0.05 485 | place case-place 486 | top-cover (fn [x-start x-end y-start y-end] 487 | (top-case-cover place wall-sphere-top-front 488 | x-start x-end y-start y-end 489 | wall-step))] 490 | (union 491 | (apply union 492 | (for [x (range-inclusive 0.7 (- right-wall-column step) step)] 493 | (hull (place x 4 wall-sphere-top-front) 494 | (place (+ x step) 4 wall-sphere-top-front) 495 | (place x 4 wall-sphere-bottom-front) 496 | (place (+ x step) 4 wall-sphere-bottom-front)))) 497 | (apply union 498 | (for [x (range-inclusive 0.5 0.7 0.01)] 499 | (hull (place x 4 wall-sphere-top-front) 500 | (place (+ x step) 4 wall-sphere-top-front) 501 | (place 0.7 4 wall-sphere-bottom-front)))) 502 | (top-cover 0.5 1.7 3.6 4) 503 | (top-cover 1.59 2.41 3.42 4) ;; was 3.32 504 | (top-cover 2.39 3.41 3.6 4) 505 | (apply union 506 | (for [x (range 2 5)] 507 | (union 508 | (hull (place (- x 1/2) 4 (translate [0 1 1] wall-sphere-bottom-front)) 509 | (place (+ x 1/2) 4 (translate [0 1 1] wall-sphere-bottom-front)) 510 | (key-place x 4 web-post-bl) 511 | (key-place x 4 web-post-br)) 512 | (hull (place (- x 1/2) 4 (translate [0 1 1] wall-sphere-bottom-front)) 513 | (key-place x 4 web-post-bl) 514 | (key-place (- x 1) 4 web-post-br))))) 515 | (hull (place right-wall-column 4 (translate [0 1 1] wall-sphere-bottom-front)) 516 | (place (- right-wall-column 1) 4 (translate [0 1 1] wall-sphere-bottom-front)) 517 | (key-place 5 4 web-post-bl) 518 | (key-place 5 4 web-post-br)) 519 | (hull (place (+ 4 1/2) 4 (translate [0 1 1] wall-sphere-bottom-front)) 520 | (place (- right-wall-column 1) 4 (translate [0 1 1] wall-sphere-bottom-front)) 521 | (key-place 4 4 web-post-br) 522 | (key-place 5 4 web-post-bl)) 523 | (hull (place 0.7 4 (translate [0 1 1] wall-sphere-bottom-front)) 524 | (place 1.7 4 (translate [0 1 1] wall-sphere-bottom-front)) 525 | (key-place 1 4 web-post-bl) 526 | (key-place 1 4 web-post-br))))) 527 | 528 | (def back-wall 529 | (let [back-row (first rows) 530 | step wall-step 531 | wall-sphere-top-backtep 0.05 532 | place case-place 533 | front-top-cover (fn [x-start x-end y-start y-end] 534 | (apply union 535 | (for [x (range-inclusive x-start (- x-end wall-sphere-top-backtep) wall-sphere-top-backtep) 536 | y (range-inclusive y-start (- y-end wall-sphere-top-backtep) wall-sphere-top-backtep)] 537 | (hull (place x y wall-sphere-top-back) 538 | (place (+ x wall-sphere-top-backtep) y wall-sphere-top-back) 539 | (place x (+ y wall-sphere-top-backtep) wall-sphere-top-back) 540 | (place (+ x wall-sphere-top-backtep) (+ y wall-sphere-top-backtep) wall-sphere-top-back)))))] 541 | (union 542 | (apply union 543 | (for [x (range-inclusive left-wall-column (- right-wall-column step) step)] 544 | (hull (place x back-y wall-sphere-top-back) 545 | (place (+ x step) back-y wall-sphere-top-back) 546 | (place x back-y wall-sphere-bottom-back) 547 | (place (+ x step) back-y wall-sphere-bottom-back)))) 548 | ;; (front-top-cover left-wall-column 1.56 back-y (+ back-y 0.06)) 549 | #_(front-top-cover left-wall-column right-wall-column back-y (+ back-y 0.06)) 550 | ;; (front-top-cover 1.56 2.44 back-y (+ back-y 0.06)) 551 | (front-top-cover 3.56 4.44 back-y (+ back-y 0.2)) 552 | (front-top-cover 4.3 right-wall-column back-y (+ back-y 0.2)) 553 | 554 | 555 | (hull (place left-wall-column back-y (translate [1 -1 1] wall-sphere-bottom-back)) 556 | (place (+ left-wall-column 1) back-y (translate [0 -1 1] wall-sphere-bottom-back)) 557 | (key-place 0 back-row web-post-tl) 558 | (key-place 0 back-row web-post-tr)) 559 | 560 | (hull (place 5 back-y (translate [0 -1 1] wall-sphere-bottom-back)) 561 | (place right-wall-column back-y (translate [0 -1 1] wall-sphere-bottom-back)) 562 | (key-place 5 back-row web-post-tl) 563 | (key-place 5 back-row web-post-tr)) 564 | 565 | (apply union 566 | (for [x (range 1 5)] 567 | (union 568 | (hull (place (- x 1/2) back-y (translate [0 -1 1] wall-sphere-bottom-back)) 569 | (place (+ x 1/2) back-y (translate [0 -1 1] wall-sphere-bottom-back)) 570 | (key-place x back-row web-post-tl) 571 | (key-place x back-row web-post-tr)) 572 | (hull (place (- x 1/2) back-y (translate [0 -1 1] wall-sphere-bottom-back)) 573 | (key-place x back-row web-post-tl) 574 | (key-place (- x 1) back-row web-post-tr))))) 575 | (hull (place (- 5 1/2) back-y (translate [0 -1 1] wall-sphere-bottom-back)) 576 | (place 5 back-y (translate [0 -1 1] wall-sphere-bottom-back)) 577 | (key-place 4 back-row web-post-tr) 578 | (key-place 5 back-row web-post-tl))))) 579 | 580 | (def right-wall 581 | (let [place case-place] 582 | (union 583 | (apply union 584 | (map (partial apply hull) 585 | (partition 2 1 586 | (for [scale (range-inclusive 0 1 0.01)] 587 | (let [x (scale-to-range 4 back-y scale)] 588 | (hull (place right-wall-column x (wall-sphere-top scale)) 589 | (place right-wall-column x (wall-sphere-bottom scale)))))))) 590 | 591 | (apply union 592 | (concat 593 | (for [x (range 1 5)] 594 | (union 595 | (hull (place right-wall-column x (translate [-1 0 1] (wall-sphere-bottom 1/2))) 596 | (key-place 5 x web-post-br) 597 | (key-place 5 x web-post-tr)))) 598 | (for [x (range 1 4)] 599 | (union 600 | (hull (place right-wall-column x (translate [-1 0 1] (wall-sphere-bottom 1/2))) 601 | (place right-wall-column (inc x) (translate [-1 0 1] (wall-sphere-bottom 1/2))) 602 | (key-place 5 x web-post-br) 603 | (key-place 5 (inc x) web-post-tr)))) 604 | [(union 605 | (hull (place right-wall-column (first rows) (translate [-1 0 1] (wall-sphere-bottom 1/2))) 606 | (place right-wall-column back-y (translate [-1 -1 1] (wall-sphere-bottom 1))) 607 | (key-place 5 (first rows) web-post-tr)) 608 | (hull (place right-wall-column 4 (translate [-1 0 1] (wall-sphere-bottom 1/2))) 609 | (place right-wall-column 4 (translate [-1 1 1] (wall-sphere-bottom 0))) 610 | (key-place 5 4 web-post-br)))]))))) 611 | 612 | (def left-wall 613 | (let [place case-place] 614 | (union 615 | (apply union 616 | (for [x (range-inclusive (dec (first rows)) (- 1.6666 wall-step) wall-step)] 617 | (hull (place left-wall-column x wall-sphere-top-front) 618 | (place left-wall-column (+ x wall-step) wall-sphere-top-front) 619 | (place left-wall-column x wall-sphere-bottom-front) 620 | (place left-wall-column (+ x wall-step) wall-sphere-bottom-front)))) 621 | (hull (place left-wall-column (dec (first rows)) wall-sphere-top-front) 622 | (place left-wall-column (dec (first rows)) wall-sphere-bottom-front) 623 | (place left-wall-column back-y wall-sphere-top-back) 624 | (place left-wall-column back-y wall-sphere-bottom-back)) 625 | #_(color [0 1 0] (hull (place left-wall-column 0 (translate [1 -1 1] wall-sphere-bottom-back)) 626 | (place left-wall-column 1 (translate [1 0 1] wall-sphere-bottom-back)) 627 | (key-place 0 0 web-post-tl) 628 | (key-place 0 0 web-post-bl))) 629 | (color [0 1 0] (hull (place left-wall-column 1 (translate [1 -1 1] wall-sphere-bottom-back)) 630 | (place left-wall-column 2 (translate [1 0 1] wall-sphere-bottom-back)) 631 | (key-place 0 1 web-post-tl) 632 | (key-place 0 1 web-post-bl))) 633 | (color [1 0 0] (hull (place left-wall-column 2 (translate [1 0 1] wall-sphere-bottom-back)) 634 | (place left-wall-column 1.6666 (translate [1 0 1] wall-sphere-bottom-front)) 635 | (key-place 0 1 web-post-bl) 636 | (key-place 0 2 web-post-bl))) 637 | (color [1 1 0] (hull (place left-wall-column 1.6666 (translate [1 0 1] wall-sphere-bottom-front)) 638 | (key-place 0 2 web-post-bl) 639 | (key-place 0 3 web-post-tl))) 640 | (hull (place left-wall-column 1.6666 (translate [1 0 1] wall-sphere-bottom-front)) 641 | (thumb-place 1 1 web-post-tr) 642 | (key-place 0 3 web-post-tl)) 643 | (hull (place left-wall-column 1.6666 (translate [1 0 1] wall-sphere-bottom-front)) 644 | (thumb-place 1 1 web-post-tr) 645 | (thumb-place 1/2 thumb-back-y (translate [0 -1 1] wall-sphere-bottom-back)))))) 646 | 647 | (def thumb-back-wall 648 | (let [step wall-step 649 | top-step 0.05 650 | front-top-cover (fn [x-start x-end y-start y-end] 651 | (apply union 652 | (for [x (range-inclusive x-start (- x-end top-step) top-step) 653 | y (range-inclusive y-start (- y-end top-step) top-step)] 654 | (hull (thumb-place x y wall-sphere-top-back) 655 | (thumb-place (+ x top-step) y wall-sphere-top-back) 656 | (thumb-place x (+ y top-step) wall-sphere-top-back) 657 | (thumb-place (+ x top-step) (+ y top-step) wall-sphere-top-back))))) 658 | back-y thumb-back-y] 659 | (union 660 | (apply union 661 | (for [x (range-inclusive 1/2 (- (+ 5/2 0.05) step) step)] 662 | (hull (thumb-place x back-y wall-sphere-top-back) 663 | (thumb-place (+ x step) back-y wall-sphere-top-back) 664 | (thumb-place x back-y wall-sphere-bottom-back) 665 | (thumb-place (+ x step) back-y wall-sphere-bottom-back)))) 666 | (hull (thumb-place 1/2 back-y wall-sphere-top-back) 667 | (thumb-place 1/2 back-y wall-sphere-bottom-back) 668 | (case-place left-wall-column 1.6666 wall-sphere-top-front)) 669 | (hull (thumb-place 1/2 back-y wall-sphere-bottom-back) 670 | (case-place left-wall-column 1.6666 wall-sphere-top-front) 671 | (case-place left-wall-column 1.6666 wall-sphere-bottom-front)) 672 | (hull 673 | (thumb-place 1/2 thumb-back-y (translate [0 -1 1] wall-sphere-bottom-back)) 674 | (thumb-place 1 1 web-post-tr) 675 | (thumb-place 3/2 thumb-back-y (translate [0 -1 1] wall-sphere-bottom-back)) 676 | (thumb-place 1 1 web-post-tl)) 677 | (hull 678 | (thumb-place (+ 5/2 0.05) thumb-back-y (translate [1 -1 1] wall-sphere-bottom-back)) 679 | (thumb-place 3/2 thumb-back-y (translate [0 -1 1] wall-sphere-bottom-back)) 680 | (thumb-place 1 1 web-post-tl) 681 | (thumb-place 2 1 web-post-tl))))) 682 | 683 | (def thumb-left-wall 684 | (let [step wall-step 685 | place thumb-place] 686 | (union 687 | (apply union 688 | (for [x (range-inclusive (+ -1 0.07) (- 1.95 step) step)] 689 | (hull (place thumb-left-wall-column x wall-sphere-top-front) 690 | (place thumb-left-wall-column (+ x step) wall-sphere-top-front) 691 | (place thumb-left-wall-column x wall-sphere-bottom-front) 692 | (place thumb-left-wall-column (+ x step) wall-sphere-bottom-front)))) 693 | (hull (place thumb-left-wall-column 1.95 wall-sphere-top-front) 694 | (place thumb-left-wall-column 1.95 wall-sphere-bottom-front) 695 | (place thumb-left-wall-column thumb-back-y wall-sphere-top-back) 696 | (place thumb-left-wall-column thumb-back-y wall-sphere-bottom-back)) 697 | 698 | (hull 699 | (thumb-place thumb-left-wall-column thumb-back-y (translate [1 -1 1] wall-sphere-bottom-back)) 700 | (thumb-place thumb-left-wall-column 0 (translate [1 0 1] wall-sphere-bottom-back)) 701 | (thumb-place 2 1 web-post-tl) 702 | (thumb-place 2 1 web-post-bl)) 703 | (hull 704 | (thumb-place thumb-left-wall-column 0 (translate [1 0 1] wall-sphere-bottom-back)) 705 | (thumb-place 2 0 web-post-tl) 706 | (thumb-place 2 1 web-post-bl)) 707 | (hull 708 | (thumb-place thumb-left-wall-column 0 (translate [1 0 1] wall-sphere-bottom-back)) 709 | (thumb-place thumb-left-wall-column -1 (translate [1 0 1] wall-sphere-bottom-back)) 710 | (thumb-place 2 0 web-post-tl) 711 | (thumb-place 2 0 web-post-bl)) 712 | (hull 713 | (thumb-place thumb-left-wall-column -1 (translate [1 0 1] wall-sphere-bottom-back)) 714 | (thumb-place 2 -1 web-post-tl) 715 | (thumb-place 2 0 web-post-bl)) 716 | (hull 717 | (thumb-place thumb-left-wall-column -1 (translate [1 0 1] wall-sphere-bottom-back)) 718 | (thumb-place thumb-left-wall-column (+ -1 0.07) (translate [1 1 1] wall-sphere-bottom-front)) 719 | (thumb-place 2 -1 web-post-tl) 720 | (thumb-place 2 -1 web-post-bl))))) 721 | 722 | (def thumb-front-wall 723 | (let [step wall-step ;;0.1 724 | wall-sphere-top-fronttep 0.05 ;;0.05 725 | place thumb-place 726 | plate-height (/ (- sa-double-length mount-height) 2) 727 | thumb-tl (->> web-post-tl 728 | (translate [0 plate-height 0])) 729 | thumb-bl (->> web-post-bl 730 | (translate [0 (- plate-height) 0])) 731 | thumb-tr (->> web-post-tr 732 | (translate [-0 plate-height 0])) 733 | thumb-br (->> web-post-br 734 | (translate [-0 (- plate-height) 0]))] 735 | (union 736 | (apply union 737 | (for [x (range-inclusive thumb-right-wall (- (+ 5/2 0.05) step) step)] 738 | (hull (place x thumb-front-row wall-sphere-top-front) 739 | (place (+ x step) thumb-front-row wall-sphere-top-front) 740 | (place x thumb-front-row wall-sphere-bottom-front) 741 | (place (+ x step) thumb-front-row wall-sphere-bottom-front)))) 742 | 743 | (hull (place thumb-right-wall thumb-front-row wall-sphere-top-front) 744 | (place thumb-right-wall thumb-front-row wall-sphere-bottom-front) 745 | (case-place 0.5 4 wall-sphere-top-front)) 746 | (hull (place thumb-right-wall thumb-front-row wall-sphere-bottom-front) 747 | (case-place 0.5 4 wall-sphere-top-front) 748 | (case-place 0.7 4 wall-sphere-bottom-front)) 749 | 750 | (hull (place thumb-right-wall thumb-front-row wall-sphere-bottom-front) 751 | (key-place 1 4 web-post-bl) 752 | (place 0 -1/2 thumb-br) 753 | (place 0 -1/2 web-post-br) 754 | (case-place 0.7 4 wall-sphere-bottom-front)) 755 | 756 | (hull (place (+ 5/2 0.05) thumb-front-row (translate [1 1 1] wall-sphere-bottom-front)) 757 | (place (+ 3/2 0.05) thumb-front-row (translate [0 1 1] wall-sphere-bottom-front)) 758 | (place 2 -1 web-post-bl) 759 | (place 2 -1 web-post-br)) 760 | 761 | (hull (place thumb-right-wall thumb-front-row (translate [0 1 1] wall-sphere-bottom-front)) 762 | (place (+ 1/2 0.05) thumb-front-row (translate [0 1 1] wall-sphere-bottom-front)) 763 | (place 0 -1/2 thumb-bl) 764 | (place 0 -1/2 thumb-br)) 765 | (hull (place (+ 1/2 0.05) thumb-front-row (translate [0 1 1] wall-sphere-bottom-front)) 766 | (place (+ 3/2 0.05) thumb-front-row (translate [0 1 1] wall-sphere-bottom-front)) 767 | (place 0 -1/2 thumb-bl) 768 | (place 1 -1/2 thumb-bl) 769 | (place 1 -1/2 thumb-br) 770 | (place 2 -1 web-post-br))))) 771 | 772 | (def new-case 773 | (union front-wall 774 | right-wall 775 | back-wall 776 | left-wall 777 | thumb-back-wall 778 | thumb-left-wall 779 | thumb-front-wall)) 780 | 781 | ;;;;;;;;;;;; 782 | ;; Bottom ;; 783 | ;;;;;;;;;;;; 784 | 785 | 786 | (def bottom-key-guard (->> (cube mount-width mount-height web-thickness) 787 | (translate [0 0 (+ (- (/ web-thickness 2)) -4.5)]))) 788 | (def bottom-front-key-guard (->> (cube mount-width (/ mount-height 2) web-thickness) 789 | (translate [0 (/ mount-height 4) (+ (- (/ web-thickness 2)) -4.5)]))) 790 | 791 | (def bottom-plate 792 | (union 793 | (apply union 794 | (for [column columns 795 | row (drop-last rows) ;; 796 | :when (or (not= column 0) 797 | (not= row 4))] 798 | (->> bottom-key-guard 799 | (key-place column row)))) 800 | (thumb-layout-bottom (rotate (/ π 2) [0 0 1] bottom-key-guard)) 801 | (apply union 802 | (for [column columns 803 | row [(last rows)] ;; 804 | :when (or (not= column 0) 805 | (not= row 4))] 806 | (->> bottom-front-key-guard 807 | (key-place column row)))) 808 | (let [shift #(translate [0 0 (+ (- web-thickness) -5)] %) 809 | web-post-tl (shift web-post-tl) 810 | web-post-tr (shift web-post-tr) 811 | web-post-br (shift web-post-br) 812 | web-post-bl (shift web-post-bl) 813 | half-shift-correction #(translate [0 (/ mount-height 2) 0] %) 814 | half-post-br (half-shift-correction web-post-br) 815 | half-post-bl (half-shift-correction web-post-bl) 816 | row-connections (concat 817 | (for [column (drop-last columns) 818 | row (drop-last rows) 819 | :when (or (not= column 0) 820 | (not= row 4))] 821 | (triangle-hulls 822 | (key-place (inc column) row web-post-tl) 823 | (key-place column row web-post-tr) 824 | (key-place (inc column) row web-post-bl) 825 | (key-place column row web-post-br))) 826 | (for [column (drop-last columns) 827 | row [(last rows)] 828 | :when (or (not= column 0) 829 | (not= row 4))] 830 | (triangle-hulls 831 | (key-place (inc column) row web-post-tl) 832 | (key-place column row web-post-tr) 833 | (key-place (inc column) row half-post-bl) 834 | (key-place column row half-post-br)))) 835 | column-connections (for [column columns 836 | row (drop-last rows) 837 | :when (or (not= column 0) 838 | (not= row 3))] 839 | (triangle-hulls 840 | (key-place column row web-post-bl) 841 | (key-place column row web-post-br) 842 | (key-place column (inc row) web-post-tl) 843 | (key-place column (inc row) web-post-tr))) 844 | diagonal-connections (for [column (drop-last columns) 845 | row (drop-last rows) 846 | :when (or (not= column 0) 847 | (not= row 3))] 848 | (triangle-hulls 849 | (key-place column row web-post-br) 850 | (key-place column (inc row) web-post-tr) 851 | (key-place (inc column) row web-post-bl) 852 | (key-place (inc column) (inc row) web-post-tl))) 853 | main-keys-bottom (concat row-connections 854 | column-connections 855 | diagonal-connections) 856 | front-wall (concat 857 | (for [x (range 2 5)] 858 | (union 859 | (hull (case-place (- x 1/2) 4 (translate [0 1 1] wall-sphere-bottom-front)) 860 | (case-place (+ x 1/2) 4 (translate [0 1 1] wall-sphere-bottom-front)) 861 | (key-place x 4 half-post-bl) 862 | (key-place x 4 half-post-br)) 863 | (hull (case-place (- x 1/2) 4 (translate [0 1 1] wall-sphere-bottom-front)) 864 | (key-place x 4 half-post-bl) 865 | (key-place (- x 1) 4 half-post-br)))) 866 | [(hull (case-place right-wall-column 4 (translate [0 1 1] wall-sphere-bottom-front)) 867 | (case-place (- right-wall-column 1) 4 (translate [0 1 1] wall-sphere-bottom-front)) 868 | (key-place 5 4 half-post-bl) 869 | (key-place 5 4 half-post-br)) 870 | (hull (case-place (+ 4 1/2) 4 (translate [0 1 1] wall-sphere-bottom-front)) 871 | (case-place (- right-wall-column 1) 4 (translate [0 1 1] wall-sphere-bottom-front)) 872 | (key-place 4 4 half-post-br) 873 | (key-place 5 4 half-post-bl))]) 874 | right-wall (concat 875 | (for [x (drop-last rows)] 876 | (hull (case-place right-wall-column x (translate [-1 0 1] (wall-sphere-bottom 1/2))) 877 | (key-place 5 x web-post-br) 878 | (key-place 5 x web-post-tr))) 879 | (for [x (drop-last rows)] 880 | (hull (case-place right-wall-column x (translate [-1 0 1] (wall-sphere-bottom 1/2))) 881 | (case-place right-wall-column (inc x) (translate [-1 0 1] (wall-sphere-bottom 1/2))) 882 | (key-place 5 x web-post-br) 883 | (key-place 5 (inc x) web-post-tr))) 884 | [(union 885 | (hull (case-place right-wall-column (first rows) (translate [-1 0 1] (wall-sphere-bottom 1/2))) 886 | (case-place right-wall-column back-y (translate [-1 -1 1] (wall-sphere-bottom 1))) 887 | (key-place 5 (first rows) web-post-tr) 888 | ) 889 | (hull (case-place right-wall-column 4 (translate [-1 0 1] (wall-sphere-bottom 1/2))) 890 | (case-place right-wall-column 4 (translate [0 1 1] (wall-sphere-bottom 0))) 891 | (key-place 5 4 half-post-br) 892 | ) 893 | (hull (case-place right-wall-column 4 (translate [-1 0 1] (wall-sphere-bottom 1/2))) 894 | (key-place 5 4 half-post-br) 895 | (key-place 5 4 web-post-tr)))]) 896 | back-wall (concat 897 | (for [x (range 1 6)] 898 | (union 899 | (hull (case-place (- x 1/2) back-y (translate [0 -1 1] wall-sphere-bottom-back)) 900 | (case-place (+ x 1/2) back-y (translate [0 -1 1] wall-sphere-bottom-back)) 901 | (key-place x (first rows) web-post-tl) 902 | (key-place x (first rows) web-post-tr)) 903 | (hull (case-place (- x 1/2) back-y (translate [0 -1 1] wall-sphere-bottom-back)) 904 | (key-place x (first rows) web-post-tl) 905 | (key-place (- x 1) (first rows) web-post-tr)))) 906 | [(hull (case-place left-wall-column back-y (translate [1 -1 1] wall-sphere-bottom-back)) 907 | (case-place (+ left-wall-column 1) back-y (translate [0 -1 1] wall-sphere-bottom-back)) 908 | (key-place 0 (first rows) web-post-tl) 909 | (key-place 0 (first rows) web-post-tr))]) 910 | left-wall (let [place case-place] 911 | [(hull (place left-wall-column 1 (translate [1 -1 1] wall-sphere-bottom-back)) 912 | (place left-wall-column 2 (translate [1 0 1] wall-sphere-bottom-back)) 913 | (key-place 0 1 web-post-tl) 914 | (key-place 0 1 web-post-bl)) 915 | #_(hull (place left-wall-column 1 (translate [1 0 1] wall-sphere-bottom-back)) 916 | (place left-wall-column 2 (translate [1 0 1] wall-sphere-bottom-back)) 917 | (key-place 0 0 web-post-bl) 918 | (key-place 0 1 web-post-bl)) 919 | (hull (place left-wall-column 2 (translate [1 0 1] wall-sphere-bottom-back)) 920 | (place left-wall-column 1.6666 (translate [1 0 1] wall-sphere-bottom-front)) 921 | (key-place 0 1 web-post-bl) 922 | (key-place 0 2 web-post-bl)) 923 | (hull (place left-wall-column 1.6666 (translate [1 0 1] wall-sphere-bottom-front)) 924 | (key-place 0 2 web-post-bl) 925 | (key-place 0 3 web-post-tl))]) 926 | 927 | #_(union 928 | (thumb-place 0 -1/2 shape) 929 | 930 | (thumb-place 1 7/8 shape) 931 | (thumb-place 1 -5/8 shape) 932 | 933 | (thumb-place 2 -3/4 shape) 934 | (thumb-place 2 3/4 shape) 935 | ) 936 | 937 | 938 | thumb-tl #(->> web-post-tl 939 | (translate [0 (extended-plate-height %) 0])) 940 | thumb-bl #(->> web-post-bl 941 | (translate [0 (- (extended-plate-height %)) 0])) 942 | thumb-tr #(->> web-post-tr 943 | (translate [0 (extended-plate-height %) 0])) 944 | thumb-br #(->> web-post-br 945 | (translate [0 (- (extended-plate-height %)) 0])) 946 | 947 | thumbs [(triangle-hulls (thumb-place 0 -1/2 web-post-tl) 948 | (thumb-place 0 -1/2 web-post-bl) 949 | (thumb-place 1 -5/8 web-post-tr) 950 | (thumb-place 1 -5/8 web-post-br)) 951 | (hull (thumb-place 1 -5/8 web-post-tr) 952 | (thumb-place 1 -5/8 web-post-tl) 953 | (thumb-place 1 7/8 web-post-bl) 954 | (thumb-place 1 7/8 web-post-br)) 955 | (hull (thumb-place 2 -3/4 web-post-tr) 956 | (thumb-place 2 -3/4 web-post-tl) 957 | (thumb-place 2 3/4 web-post-bl) 958 | (thumb-place 2 3/4 web-post-br)) 959 | (triangle-hulls (thumb-place 2 3/4 web-post-tr) 960 | (thumb-place 1 7/8 web-post-tl) 961 | (thumb-place 2 3/4 web-post-br) 962 | (thumb-place 1 7/8 web-post-bl) 963 | (thumb-place 2 -3/4 web-post-tr) 964 | (thumb-place 1 -5/8 web-post-tl) 965 | (thumb-place 2 -3/4 web-post-br) 966 | (thumb-place 1 -5/8 web-post-bl) 967 | )] 968 | thumb-back-wall [(hull 969 | (thumb-place 1/2 thumb-back-y (translate [0 -1 1] wall-sphere-bottom-back)) 970 | (thumb-place 1 7/8 web-post-tr) 971 | (thumb-place 3/2 thumb-back-y (translate [0 -1 1] wall-sphere-bottom-back)) 972 | (thumb-place 1 7/8 web-post-tl)) 973 | 974 | (hull 975 | (thumb-place (+ 5/2 0.05) thumb-back-y (translate [1 -1 1] wall-sphere-bottom-back)) 976 | (thumb-place 3/2 thumb-back-y (translate [0 -1 1] wall-sphere-bottom-back)) 977 | (thumb-place 1 7/8 web-post-tl) 978 | (thumb-place 2 3/4 web-post-tr)) 979 | 980 | (hull 981 | (thumb-place (+ 5/2 0.05) thumb-back-y (translate [1 -1 1] wall-sphere-bottom-back)) 982 | (thumb-place 2 3/4 web-post-tl) 983 | (thumb-place 2 3/4 web-post-tr)) 984 | 985 | (hull 986 | (thumb-place 1/2 thumb-back-y (translate [0 -1 1] wall-sphere-bottom-back)) 987 | (case-place left-wall-column 1.6666 (translate [1 0 1] wall-sphere-bottom-front)) 988 | (key-place 0 3 web-post-tl) 989 | (thumb-place 1 7/8 web-post-tr)) 990 | ] 991 | thumb-left-wall [(hull 992 | (thumb-place thumb-left-wall-column thumb-back-y (translate [1 -1 1] wall-sphere-bottom-back)) 993 | (thumb-place thumb-left-wall-column 0 (translate [1 0 1] wall-sphere-bottom-back)) 994 | (thumb-place 2 1 web-post-tl) 995 | (thumb-place 2 1 web-post-bl)) 996 | (hull 997 | (thumb-place thumb-left-wall-column 0 (translate [1 0 1] wall-sphere-bottom-back)) 998 | (thumb-place 2 0 web-post-tl) 999 | (thumb-place 2 1 web-post-bl)) 1000 | (hull 1001 | (thumb-place thumb-left-wall-column 0 (translate [1 0 1] wall-sphere-bottom-back)) 1002 | (thumb-place thumb-left-wall-column -1 (translate [1 0 1] wall-sphere-bottom-back)) 1003 | (thumb-place 2 0 web-post-tl) 1004 | (thumb-place 2 0 web-post-bl)) 1005 | (hull 1006 | (thumb-place thumb-left-wall-column -1 (translate [1 0 1] wall-sphere-bottom-back)) 1007 | (thumb-place 2 -1 web-post-tl) 1008 | (thumb-place 2 0 web-post-bl)) 1009 | (hull 1010 | (thumb-place thumb-left-wall-column -1 (translate [1 0 1] wall-sphere-bottom-back)) 1011 | (thumb-place thumb-left-wall-column (+ -1 0.07) (translate [1 1 1] wall-sphere-bottom-front)) 1012 | (thumb-place 2 -1 web-post-tl) 1013 | (thumb-place 2 -1 web-post-bl))] 1014 | thumb-front-wall [(hull (thumb-place (+ 5/2 0.05) thumb-front-row (translate [1 1 1] wall-sphere-bottom-front)) 1015 | (thumb-place (+ 3/2 0.05) thumb-front-row (translate [0 1 1] wall-sphere-bottom-front)) 1016 | (thumb-place 2 -3/4 web-post-bl) 1017 | (thumb-place 2 -3/4 web-post-br)) 1018 | 1019 | (hull (thumb-place (+ 1/2 0.05) thumb-front-row (translate [0 1 1] wall-sphere-bottom-front)) 1020 | (thumb-place (+ 3/2 0.05) thumb-front-row (translate [0 1 1] wall-sphere-bottom-front)) 1021 | (thumb-place 1 -5/8 web-post-bl) 1022 | (thumb-place 1 -5/8 web-post-br) 1023 | (thumb-place 2 -3/4 web-post-br)) 1024 | 1025 | (hull (thumb-place thumb-right-wall thumb-front-row (translate [-1 1 1] wall-sphere-bottom-front)) 1026 | (thumb-place (+ 1/2 0.05) thumb-front-row (translate [0 1 1] wall-sphere-bottom-front)) 1027 | (thumb-place 0 -1/2 web-post-bl) 1028 | (thumb-place 1 -5/8 web-post-br) 1029 | (thumb-place 0 -1/2 web-post-br))] 1030 | thumb-inside [(triangle-hulls 1031 | (thumb-place 1 7/8 web-post-tr) 1032 | (key-place 0 3 web-post-tl) 1033 | (thumb-place 1 7/8 web-post-br) 1034 | (key-place 0 3 web-post-bl) 1035 | (thumb-place 1 -5/8 web-post-tr) 1036 | (thumb-place 0 -1/2 web-post-tl) 1037 | (key-place 0 3 web-post-bl) 1038 | (thumb-place 0 -1/2 web-post-tr) 1039 | (key-place 0 3 web-post-br) 1040 | (key-place 1 3 web-post-bl) 1041 | (thumb-place 0 -1/2 web-post-tr) 1042 | (key-place 1 4 web-post-tl) 1043 | (key-place 1 4 half-post-bl)) 1044 | 1045 | (hull 1046 | (thumb-place 0 -1/2 web-post-tr) 1047 | (thumb-place 0 -1/2 web-post-br) 1048 | (key-place 1 4 half-post-bl)) 1049 | 1050 | (hull 1051 | (key-place 1 4 half-post-bl) 1052 | (key-place 1 4 half-post-br) 1053 | (case-place (- 2 1/2) 4 (translate [0 1 1] wall-sphere-bottom-front)) 1054 | (case-place 0.7 4 (translate [0 1 1] wall-sphere-bottom-front))) 1055 | 1056 | (hull 1057 | (thumb-place 0 -1/2 web-post-br) 1058 | (thumb-place thumb-right-wall thumb-front-row (translate [-1 1 1] wall-sphere-bottom-front)) 1059 | (key-place 1 4 half-post-bl) 1060 | ) 1061 | 1062 | (hull 1063 | (thumb-place thumb-right-wall thumb-front-row (translate [-1 1 1] wall-sphere-bottom-front)) 1064 | (case-place 0.7 4 (translate [0 1 1] wall-sphere-bottom-front)) 1065 | (thumb-place 0 -1/2 web-post-br) 1066 | (thumb-place 0 -1/2 web-post-tr) 1067 | ) 1068 | 1069 | #_ (hull 1070 | (case-place 0.7 4 (translate [0 1 1] wall-sphere-bottom-front)) 1071 | (thumb-place 0 -1/2 web-post-br) 1072 | (thumb-place 0 -1/2 web-post-tr) 1073 | 1074 | ) 1075 | 1076 | 1077 | #_ (hull 1078 | (thumb-place 0 -1 web-post-br) 1079 | (thumb-place 0 -1/2 web-post-br) 1080 | (thumb-place thumb-right-wall thumb-front-row (translate [-1 1 1] wall-sphere-bottom-front)) 1081 | (key-place 1 4 half-post-bl) 1082 | ) 1083 | 1084 | 1085 | 1086 | ] 1087 | stands (let [bumper-diameter 9.6 1088 | bumper-radius (/ bumper-diameter 2) 1089 | stand-diameter (+ bumper-diameter 2) 1090 | stand-radius (/ stand-diameter 2) 1091 | stand-at #(difference (->> (sphere stand-radius) 1092 | (translate [0 0 (+ (/ stand-radius -2) -4.5)]) 1093 | % 1094 | (bottom-hull)) 1095 | (->> (cube stand-diameter stand-diameter stand-radius) 1096 | (translate [0 0 (/ stand-radius -2)]) 1097 | %) 1098 | (->> (sphere bumper-radius) 1099 | (translate [0 0 (+ (/ stand-radius -2) -4.5)]) 1100 | % 1101 | (bottom 1.5)))] 1102 | [(stand-at #(key-place 0 1 %)) 1103 | (stand-at #(thumb-place 1 -1/2 %)) 1104 | (stand-at #(key-place 5 1 %)) 1105 | (stand-at #(key-place 5 3 %))])] 1106 | (apply union 1107 | (concat 1108 | main-keys-bottom 1109 | front-wall 1110 | right-wall 1111 | back-wall 1112 | left-wall 1113 | thumbs 1114 | thumb-back-wall 1115 | thumb-left-wall 1116 | thumb-front-wall 1117 | thumb-inside 1118 | stands))))) 1119 | 1120 | (def screw-hole (->> (cylinder 1.5 60) 1121 | (translate [0 0 3/2]) 1122 | (with-fn wall-sphere-n))) 1123 | 1124 | (def screw-holes 1125 | (union 1126 | (key-place (+ 4 1/2) 3/2 screw-hole) 1127 | (key-place (+ 4 1/2) (+ 3 1/2) screw-hole) 1128 | (thumb-place 2 0 screw-hole))) 1129 | 1130 | (defn circuit-cover [width length height] 1131 | (let [cover-sphere-radius 1 1132 | cover-sphere (->> (sphere cover-sphere-radius) 1133 | (with-fn 20)) 1134 | cover-sphere-z (+ (- height) (- cover-sphere-radius)) 1135 | cover-sphere-x (+ (/ width 2) cover-sphere-radius) 1136 | cover-sphere-y (+ (/ length 2) (+ cover-sphere-radius)) 1137 | cover-sphere-tl (->> cover-sphere 1138 | (translate [(- cover-sphere-x) (- cover-sphere-y) cover-sphere-z]) 1139 | (key-place 1/2 3/2)) 1140 | cover-sphere-tr (->> cover-sphere 1141 | (translate [cover-sphere-x (- cover-sphere-y) cover-sphere-z]) 1142 | (key-place 1/2 3/2)) 1143 | cover-sphere-br (->> cover-sphere 1144 | (translate [cover-sphere-x cover-sphere-y cover-sphere-z]) 1145 | (key-place 1/2 3/2)) 1146 | cover-sphere-bl (->> cover-sphere 1147 | (translate [(- cover-sphere-x) cover-sphere-y cover-sphere-z]) 1148 | (key-place 1/2 3/2)) 1149 | 1150 | lower-to-bottom #(translate [0 0 (+ (- cover-sphere-radius) -5.5)] %) 1151 | bl (->> cover-sphere lower-to-bottom (key-place 0 1/2)) 1152 | br (->> cover-sphere lower-to-bottom (key-place 1 1/2)) 1153 | tl (->> cover-sphere lower-to-bottom (key-place 0 5/2)) 1154 | tr (->> cover-sphere lower-to-bottom (key-place 1 5/2)) 1155 | 1156 | mlb (->> cover-sphere 1157 | (translate [(- cover-sphere-x) 0 (+ (- height) -1)]) 1158 | (key-place 1/2 3/2)) 1159 | mrb (->> cover-sphere 1160 | (translate [cover-sphere-x 0 (+ (- height) -1)]) 1161 | (key-place 1/2 3/2)) 1162 | 1163 | mlt (->> cover-sphere 1164 | (translate [(+ (- cover-sphere-x) -4) 0 -6]) 1165 | (key-place 1/2 3/2)) 1166 | mrt (->> cover-sphere 1167 | (translate [(+ cover-sphere-x 4) 0 -6]) 1168 | (key-place 1/2 3/2))] 1169 | (union 1170 | (hull cover-sphere-bl cover-sphere-br cover-sphere-tl cover-sphere-tr) 1171 | (hull cover-sphere-br cover-sphere-bl bl br) 1172 | (hull cover-sphere-tr cover-sphere-tl tl tr) 1173 | (hull cover-sphere-tl tl mlb mlt) 1174 | (hull cover-sphere-bl bl mlb mlt) 1175 | (hull cover-sphere-tr tr mrb mrt) 1176 | (hull cover-sphere-br br mrb mrt)))) 1177 | 1178 | (def io-exp-width 10) 1179 | (def io-exp-height 8) 1180 | (def io-exp-length 36) 1181 | 1182 | (def teensy-width 20) 1183 | (def teensy-height 12) 1184 | (def teensy-length 33) 1185 | 1186 | (def io-exp-cover (circuit-cover io-exp-width io-exp-length io-exp-height)) 1187 | (def teensy-cover (circuit-cover teensy-width teensy-length teensy-height)) 1188 | 1189 | (def trrs-diameter 6.6) 1190 | (def trrs-radius (/ trrs-diameter 2)) 1191 | (def trrs-hole-depth 10) 1192 | 1193 | (def trrs-hole (->> (union (cylinder trrs-radius trrs-hole-depth) 1194 | (->> (cube trrs-diameter (+ trrs-radius 5) trrs-hole-depth) 1195 | (translate [0 (/ (+ trrs-radius 5) 2) 0]))) 1196 | (rotate (/ π 2) [1 0 0]) 1197 | (translate [0 (+ (/ mount-height 2) 4) (- trrs-radius)]) 1198 | (with-fn 50))) 1199 | 1200 | (def trrs-hole-just-circle 1201 | (->> (cylinder trrs-radius trrs-hole-depth) 1202 | (rotate (/ π 2) [1 0 0]) 1203 | (translate [0 (+ (/ mount-height 2) 4) (- trrs-radius)]) 1204 | (with-fn 50) 1205 | (key-place 1/2 0))) 1206 | 1207 | (def trrs-box-hole (->> (cube 14 14 7 ) 1208 | (translate [0 1 -3.5]))) 1209 | 1210 | 1211 | (def trrs-cutout 1212 | (->> (union trrs-hole 1213 | trrs-box-hole) 1214 | (key-place 1/2 1))) 1215 | 1216 | (def teensy-pcb-thickness 1.6) 1217 | (def teensy-offset-height 5) 1218 | 1219 | (def teensy-pcb (->> (cube 18 30.5 teensy-pcb-thickness) 1220 | (translate [0 0 (+ (/ teensy-pcb-thickness -2) (- teensy-offset-height))]) 1221 | (key-place 1/2 3/2) 1222 | (color [1 0 0]))) 1223 | 1224 | (def teensy-support 1225 | (difference 1226 | (union 1227 | (->> (cube 3 3 9) 1228 | (translate [0 0 -2]) 1229 | (key-place 1/2 3/2) 1230 | (color [0 1 0])) 1231 | (hull (->> (cube 3 6 9) 1232 | (translate [0 0 -2]) 1233 | (key-place 1/2 2) 1234 | (color [0 0 1])) 1235 | (->> (cube 3 3 (+ teensy-pcb-thickness 3)) 1236 | (translate [0 (/ 30.5 -2) (+ (- teensy-offset-height) 1237 | #_(/ (+ teensy-pcb-thickness 3) -2) 1238 | )]) 1239 | (key-place 1/2 3/2) 1240 | (color [0 0 1])))) 1241 | teensy-pcb 1242 | (->> (cube 18 30.5 teensy-pcb-thickness) 1243 | (translate [0 1.5 (+ (/ teensy-pcb-thickness -2) (- teensy-offset-height) -1)]) 1244 | (key-place 1/2 3/2) 1245 | (color [1 0 0])))) 1246 | 1247 | (def usb-cutout 1248 | (let [hole-height 6.2 1249 | side-radius (/ hole-height 2) 1250 | hole-width 10.75 1251 | side-cylinder (->> (cylinder side-radius teensy-length) 1252 | (with-fn 20) 1253 | (translate [(/ (- hole-width hole-height) 2) 0 0]))] 1254 | (->> (hull side-cylinder 1255 | (mirror [-1 0 0] side-cylinder)) 1256 | (rotate (/ π 2) [1 0 0]) 1257 | (translate [0 (/ teensy-length 2) (- side-radius)]) 1258 | (translate [0 0 (- 1)]) 1259 | (translate [0 0 (- teensy-offset-height)]) 1260 | (key-place 1/2 3/2)))) 1261 | 1262 | ;;;;;;;;;;;;;;;;;; 1263 | ;; Final Export ;; 1264 | ;;;;;;;;;;;;;;;;;; 1265 | 1266 | (def dactyl-top-right 1267 | (difference 1268 | (union key-holes 1269 | connectors 1270 | thumb 1271 | new-case 1272 | teensy-support 1273 | #_caps) 1274 | trrs-hole-just-circle 1275 | screw-holes)) 1276 | 1277 | (def dactyl-bottom-right 1278 | (difference 1279 | (union 1280 | teensy-cover 1281 | (difference 1282 | bottom-plate 1283 | (hull teensy-cover) 1284 | new-case 1285 | teensy-cover 1286 | trrs-cutout 1287 | (->> (cube 1000 1000 10) (translate [0 0 -5])) 1288 | screw-holes)) 1289 | usb-cutout 1290 | dactyl-top-right)) 1291 | 1292 | (def dactyl-bottom-left 1293 | (mirror [-1 0 0] 1294 | (union 1295 | io-exp-cover 1296 | (difference 1297 | bottom-plate 1298 | (hull io-exp-cover) 1299 | new-case 1300 | io-exp-cover 1301 | trrs-cutout 1302 | (->> (cube 1000 1000 10) (translate [0 0 -5])) 1303 | screw-holes)))) 1304 | 1305 | 1306 | 1307 | (def dactyl-top-left 1308 | (mirror [-1 0 0] 1309 | (difference 1310 | (union key-holes 1311 | connectors 1312 | thumb 1313 | new-case) 1314 | trrs-hole-just-circle 1315 | screw-holes))) 1316 | 1317 | (comment 1318 | (spit "things/lightcycle-cherry-top-right.scad" 1319 | (write-scad dactyl-top-right)) 1320 | 1321 | (spit "things/lightcycle-cherry-bottom-right.scad" 1322 | (write-scad dactyl-bottom-right)) 1323 | 1324 | (spit "things/lightcycle-cherry-top-left.scad" 1325 | (write-scad dactyl-top-left)) 1326 | 1327 | (spit "things/lightcycle-cherry-bottom-left.scad" 1328 | (write-scad dactyl-bottom-left))) 1329 | 1330 | (spit "things/lightcycle-matias-top-right.scad" 1331 | (write-scad dactyl-top-right)) 1332 | 1333 | (spit "things/lightcycle-matias-bottom-right.scad" 1334 | (write-scad dactyl-bottom-right)) 1335 | 1336 | (spit "things/lightcycle-matias-top-left.scad" 1337 | (write-scad dactyl-top-left)) 1338 | 1339 | (spit "things/lightcycle-matias-bottom-left.scad" 1340 | (write-scad dactyl-bottom-left)) 1341 | -------------------------------------------------------------------------------- /src/dactyl_keyboard/util.clj: -------------------------------------------------------------------------------- 1 | (ns dactyl-keyboard.util 2 | (:refer-clojure :exclude [use import]) 3 | (:require [scad-clj.model :refer :all])) 4 | 5 | (defn triangle-hulls [& shapes] 6 | (apply union 7 | (map (partial apply hull) 8 | (partition 3 1 shapes)))) 9 | 10 | (defn bottom [height p] 11 | (->> (project p) 12 | (extrude-linear {:height height :twist 0 :convexity 0}) 13 | (translate [0 0 (/ height 2)]))) 14 | 15 | (defn bottom-hull [p] 16 | (hull p (bottom 1 p))) 17 | -------------------------------------------------------------------------------- /src/dactyl_keyboard/wrist.clj: -------------------------------------------------------------------------------- 1 | (ns dactyl-keyboard.wrist 2 | (:refer-clojure :exclude [use import]) 3 | (:require [scad-clj.scad :refer :all] 4 | [scad-clj.model :refer :all] 5 | [unicode-math.core :refer :all] 6 | [dactyl-keyboard.util :refer :all])) 7 | 8 | (def pad-corner-r 11) 9 | (def pad-width 95) 10 | (def pad-length 76.5) 11 | 12 | (def stand-height 45) 13 | (def stand-thickness 1.5) 14 | 15 | (def bumper-diameter 9.6) 16 | (def bumper-radius (/ bumper-diameter 2)) 17 | (def bumper-height 2) 18 | 19 | (def corner-circle (->> (cylinder pad-corner-r stand-thickness) 20 | (translate [(- (/ pad-width 2) pad-corner-r) 21 | (- (/ pad-length 2) pad-corner-r) 22 | (+ stand-height (/ stand-thickness 2))]))) 23 | 24 | (def corner {:back-right corner-circle 25 | :back-left (->> corner-circle (mirror [-1 0 0])) 26 | :front-right (->> corner-circle (mirror [0 -1 0])) 27 | :front-left (->> corner-circle (mirror [0 -1 0]) (mirror [-1 0 0])) }) 28 | 29 | (def corner-circle-bottom (->> 30 | (difference 31 | (cylinder pad-corner-r stand-height) 32 | (translate [0 0 (- (/ stand-height 2))] 33 | (cylinder bumper-radius bumper-height) 34 | ) 35 | ) 36 | (translate [(- (/ pad-width 2) pad-corner-r) 37 | (- (/ pad-length 2) pad-corner-r) 38 | (/ stand-height 2)]))) 39 | 40 | (def corner-bottom {:back-right corner-circle-bottom 41 | :back-left (->> corner-circle-bottom (mirror [-1 0 0])) 42 | :front-right (->> corner-circle-bottom (mirror [0 -1 0])) 43 | :front-left (->> corner-circle-bottom (mirror [0 -1 0]) (mirror [-1 0 0])) }) 44 | 45 | (def wrist-rest 46 | (union (hull (corner :back-right) 47 | (corner :back-left) 48 | (corner :front-right) 49 | (corner :front-left)) 50 | (corner-bottom :back-right) 51 | (corner-bottom :back-left) 52 | (corner-bottom :front-right) 53 | (corner-bottom :front-left))) 54 | 55 | (spit "things/wrist.scad" 56 | (write-scad wrist-rest)) 57 | -------------------------------------------------------------------------------- /target/repl-port: -------------------------------------------------------------------------------- 1 | 49375 -------------------------------------------------------------------------------- /target/stale/extract-native.dependencies: -------------------------------------------------------------------------------- 1 | ([:dependencies ([cider/cider-nrepl "0.10.0"] [org.clojure/clojure "1.7.0"] [unicode-math/unicode-math "0.2.0"] [scad-clj/scad-clj "0.4.0"] [org.clojure/tools.nrepl "0.2.12" :exclusions ([org.clojure/clojure]) :scope "test"] [clojure-complete/clojure-complete "0.2.3" :exclusions ([org.clojure/clojure]) :scope "test"])]) -------------------------------------------------------------------------------- /test/dactyl_cave/core_test.clj: -------------------------------------------------------------------------------- 1 | (ns dactyl-cave.core-test 2 | (:require [clojure.test :refer :all] 3 | [dactyl-cave.core :refer :all])) 4 | 5 | (deftest a-test 6 | (testing "FIXME, I fail." 7 | (is (= 0 1)))) 8 | --------------------------------------------------------------------------------