├── .gitignore ├── Makefile ├── README.md ├── TODO ├── boards.scad ├── boards ├── Makefile ├── bbb.scad ├── cubieboard.scad ├── gif │ ├── bbb.gif │ ├── cubieboard.gif │ ├── hikey.gif │ ├── nanopi_neo2.gif │ ├── orangepi_zero.gif │ └── rpi3.gif ├── hikey.scad ├── nanopi_neo2.scad ├── orangepi_zero.scad ├── rpi3.scad └── wemos_esp8266.scad ├── case.scad ├── cases ├── Makefile ├── bbb.scad ├── cubieboard.scad ├── gif │ ├── bbb.gif │ ├── cubieboard.gif │ ├── hikey.gif │ ├── nanopi_neo2.gif │ ├── orangepi_zero.gif │ └── rpi3.gif ├── hikey.scad ├── nanopi_neo2.scad ├── orangepi_zero.scad ├── rpi3.scad └── wemos_esp8266.scad ├── common.mk ├── electronics ├── Makefile ├── README.md ├── _internal.scad ├── button.scad ├── cpu.scad ├── gif │ ├── button.gif │ ├── cpu.gif │ ├── hdmi.gif │ ├── header.gif │ ├── jack.gif │ ├── misc.gif │ ├── network.gif │ ├── power.gif │ ├── sata.gif │ ├── sd.gif │ └── usb.gif ├── hdmi.scad ├── header.scad ├── jack.scad ├── misc.scad ├── network.scad ├── power.scad ├── sata.scad ├── sd.scad └── usb.scad ├── globals.scad ├── pics ├── bbb.jpg ├── cubieboard.jpg ├── hikey.jpg ├── nanopi_neo2.jpg ├── orangepi_zero.jpg ├── rpi3.jpg └── small │ ├── bbb.jpg │ ├── cubieboard.jpg │ ├── hikey.jpg │ ├── nanopi_neo2.jpg │ ├── orangepi_zero.jpg │ └── rpi3.jpg └── utils.scad /.gitignore: -------------------------------------------------------------------------------- 1 | *.png 2 | *.stl 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Clément Bœsch 2 | # 3 | # Permission to use, copy, modify, and distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | stl: 16 | $(MAKE) -C cases $@ 17 | 18 | GIF_MAKE = boards cases electronics 19 | GIF_RULES = $(addprefix gif-,$(GIF_MAKE)) 20 | gif: $(GIF_RULES) 21 | $(GIF_RULES): 22 | $(MAKE) -C $(word 2,$(subst -, ,$@)) gif 23 | 24 | clean: 25 | $(RM) cases/*.stl 26 | 27 | .PHONY: stl gif clean $(GIF_RULES) 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ShimonBox 2 | ========= 3 | 4 | ShimonBox is an [OpenSCAD][openscad] project aiming at providing 5 | semi-automatically generated 3D printable cases for development boards. 6 | 7 | See [pkh.me introduction blog post][blog-post] for more information. 8 | 9 | [openscad]: http://www.openscad.org 10 | [blog-post]: http://blog.pkh.me/p/24-making-development-board-cases-with-shimonbox.html 11 | 12 | 13 | Supported boards 14 | ---------------- 15 | 16 | | Board name | Preview | 17 | | -------------------------------------------- | ------------------------------------------------ | 18 | | [BeagleBone Black](boards/bbb.scad) | ![BeagleBone Black](boards/gif/bbb.gif) | 19 | | [Cubieboard](boards/cubieboard.scad) | ![Cubieboard](boards/gif/cubieboard.gif) | 20 | | [Hikey (LeMaker)](boards/hikey.scad) | ![Hikey](boards/gif/hikey.gif) | 21 | | [NanoPi Neo 2](boards/nanopi_neo2.scad) | ![NanoPi Neo 2](boards/gif/nanopi_neo2.gif) | 22 | | [Orange Pi Zero](boards/orangepi_zero.scad) | ![Orange Pi Zero](boards/gif/orangepi_zero.gif) | 23 | | [Raspberry Pi 3](boards/rpi3.scad) | ![Raspberry Pi 3](boards/gif/rpi3.gif) | 24 | 25 | 26 | Corresponding cases 27 | ------------------- 28 | 29 | | Board name | Preview | Status | 30 | | -------------------------------------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------- | 31 | | [BeagleBone Black](cases/bbb.scad) | ![BeagleBone Black](cases/gif/bbb.gif) | [VERIFIED](pics/bbb.jpg):
![BeagleBone Black](pics/small/bbb.jpg) | 32 | | [Cubieboard](cases/cubieboard.scad) | ![Cubieboard](cases/gif/cubieboard.gif) | [VERIFIED](pics/cubieboard.jpg):
![Cubieboard](pics/small/cubieboard.jpg) | 33 | | [Hikey (LeMaker)](cases/hikey.scad) | ![Hikey](cases/gif/hikey.gif) | [VERIFIED](pics/hikey.jpg):
![Hikey](pics/small/hikey.jpg) | 34 | | [NanoPi Neo 2](cases/nanopi_neo2.scad) | ![NanoPi Neo 2](cases/gif/nanopi_neo2.gif) | [VERIFIED](pics/nanopi_neo2.jpg):
![NanoPi Neo 2](pics/small/nanopi_neo2.jpg) | 35 | | [Orange Pi Zero](cases/orangepi_zero.scad) | ![Orange Pi Zero](cases/gif/orangepi_zero.gif) | [VERIFIED](pics/orangepi_zero.jpg):
![Orange Pi Zero](pics/small/orangepi_zero.jpg) | 36 | | [Raspberry Pi 3](cases/rpi3.scad) | ![Raspberry Pi 3](cases/gif/rpi3.gif) | [VERIFIED](pics/rpi3.jpg):
![Raspberry Pi 3](pics/small/rpi3.jpg) | 37 | 38 | 39 | Usage 40 | ----- 41 | 42 | To make all the `.stl` files, run `make`. The resulting files will be found in 43 | the [cases/](cases) directory. 44 | 45 | If you're looking at building individual parts, you can use `make 46 | cases/-.stl` where `` is the board name and `` is the 47 | part you want to build (`bottom`, `top`, or `button`). 48 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - case.scad: add the possibility to use custom pattern as vents 2 | - cases: make bounding boxes of some components optional holes (typically: GPIO) 3 | - cases: test them and update reports 4 | - doc: document how to write board + case + component 5 | - electronics: be more respectful of the standards for the shape dimensions inside the bounding box 6 | - electronics: natively center them instead of using a translate 7 | 8 | 9 | boards to add: 10 | 11 | - raspberry pi 1 12 | - raspberry pi 2 13 | - odroid c2 14 | 15 | 16 | ideas: 17 | 18 | - integrate hexago as a way to stack them, or simply sliding slices 19 | -------------------------------------------------------------------------------- /boards.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include 16 | 17 | use 18 | 19 | use 20 | use 21 | use 22 | use 23 | use 24 | use 25 | use 26 | 27 | boards = [ 28 | ["bbb", beaglebone_black_info()], 29 | ["cubieboard", cubieboard_info()], 30 | ["hikey", hikey_info()], 31 | ["nanopi_neo2", nanopi_neo2_info()], 32 | ["orangepi_zero", orangepi_zero_info()], 33 | ["rpi3", raspberry_pi_3_info()], 34 | ["wemos_esp8266", wemos_esp8266_info()], 35 | ]; 36 | 37 | module boards_get_plate_2d(id) { 38 | filter(id) { 39 | beaglebone_black_plate_2d(); 40 | cubieboard_plate_2d(); 41 | hikey_plate_2d(); 42 | nanopi_neo2_plate_2d(); 43 | orangepi_zero_plate_2d(); 44 | raspberry_pi_3_plate_2d(); 45 | wemos_esp8266_plate_2d(); 46 | } 47 | } 48 | 49 | module boards_get_board(id) { 50 | filter(id) { 51 | beaglebone_black(); 52 | cubieboard(); 53 | hikey(); 54 | nanopi_neo2(); 55 | orangepi_zero(); 56 | raspberry_pi_3(); 57 | wemos_esp8266(); 58 | } 59 | } 60 | 61 | function boards_get_id(name) = search([name], boards)[0]; 62 | function boards_get_info(id) = boards[id][1]; 63 | -------------------------------------------------------------------------------- /boards/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Clément Bœsch 2 | # 3 | # Permission to use, copy, modify, and distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | OPENSCAD_EXTRA_SETTINGS = --camera=0,0,0,45,0,45,300 16 | include ../common.mk 17 | -------------------------------------------------------------------------------- /boards/bbb.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <../globals.scad> 16 | 17 | use <../case.scad> 18 | use <../utils.scad> 19 | use <../electronics/button.scad> 20 | use <../electronics/hdmi.scad> 21 | use <../electronics/header.scad> 22 | use <../electronics/misc.scad> 23 | use <../electronics/network.scad> 24 | use <../electronics/power.scad> 25 | use <../electronics/sd.scad> 26 | use <../electronics/usb.scad> 27 | 28 | 29 | board_dim = [in2mm(3400), in2mm(2150), 1.75]; 30 | 31 | 32 | /* Plate holes */ 33 | hole_d = in2mm(125); 34 | hole_orig = [board_dim[0], board_dim[1]] * -.5; 35 | ring_off = 1; 36 | holes_pos = [ 37 | hole_orig + [in2mm( 575), in2mm(2025)], 38 | hole_orig + [in2mm( 575), in2mm( 125)], 39 | hole_orig + [in2mm(3175), in2mm( 250)], 40 | hole_orig + [in2mm(3175), in2mm(1900)], 41 | ]; 42 | 43 | 44 | /* Components bounding box dimensions */ 45 | button_dim = [ 4, 3, 2]; 46 | ethernet_dim = [ 21, 16, 13.5]; 47 | gpio_dim = [ 59, 5, 8.5]; 48 | microhdmi_dim = [7.5, in2mm(1110- 850), 3]; 49 | microsdcard_dim = [ 15, 11, 1]; 50 | microsdslot_dim = [ 15, in2mm(1755-1205), 2]; 51 | miniusb_dim = [7.1, in2mm(1880-1575), 4]; 52 | power_dim = [ 14, 9, 11]; 53 | rt1_dim = [3.5, 8, 10.5]; 54 | serial_dim = [ 15, 2.5, 8.5]; 55 | usb_dim = [ 14, 14.5, 8]; 56 | 57 | 58 | module beaglebone_black_plate_2d() { 59 | /* This is a custom 2D plate module because the corner radius are not even 60 | * and thus we can not use a simple minkowski() */ 61 | l = board_dim[0]; 62 | w = board_dim[1]; 63 | ledgesz = in2mm(250); 64 | redgesz = in2mm(500); 65 | difference() { 66 | square([l, w], center=true); 67 | difference() { 68 | union() { 69 | translate([-l/2, -w/2 ]) square(ledgesz); 70 | translate([-l/2, w/2-ledgesz]) square(ledgesz); 71 | translate([ l/2 - redgesz, w/2-redgesz]) square(redgesz); 72 | translate([ l/2 - redgesz, -w/2 ]) square(redgesz); 73 | } 74 | translate([-l/2 + ledgesz, -w/2 + ledgesz]) circle(ledgesz); 75 | translate([-l/2 + ledgesz, w/2 - ledgesz]) circle(ledgesz); 76 | translate([ l/2 - redgesz, w/2 - redgesz]) circle(redgesz); 77 | translate([ l/2 - redgesz, -w/2 + redgesz]) circle(redgesz); 78 | } 79 | } 80 | } 81 | 82 | comp_info = [ 83 | /* info function box dimensions comp-corner rotate board-corner position */ 84 | [button_info(), button_dim, [-1,-1,-1], [0,0,0], [-1,-1, 1], [ 74, 41.5, 0]], 85 | [button_info(), button_dim, [-1,-1,-1], [0,0,0], [-1,-1, 1], [5.5, 40, 0]], 86 | [button_info(), button_dim, [-1,-1,-1], [0,0,0], [-1,-1, 1], [5.5, 49.5, 0]], 87 | [ethernet_info(), ethernet_dim, [ 1, 1,-1], [0,0,2], [-1,-1, 1], [-in2mm(100), in2mm(855), 0]], 88 | [female_header_info(), gpio_dim, [-1, 1,-1], [0,0,0], [-1, 1, 1], [18, -0.5, 0]], 89 | [female_header_info(), gpio_dim, [-1,-1,-1], [0,0,0], [-1,-1, 1], [18, 0.5, 0]], 90 | [microhdmi_info(), microhdmi_dim, [ 1,-1, 1], [0,0,0], [ 1,-1,-1], [ in2mm(25), in2mm(850), 0]], 91 | [microsdcard_info(), microsdcard_dim, [ 1,-1, 1], [0,0,0], [ 1,-1,-1], [in2mm(110), in2mm(1205)+.5, 0]], 92 | [microsdslot_info(), microsdslot_dim, [ 1,-1, 1], [0,0,0], [ 1,-1,-1], [0, in2mm(1205), 0]], 93 | [miniusb_info(), miniusb_dim, [ 1, 1, 1], [0,0,2], [-1,-1,-1], [-in2mm(25), in2mm(1575), 0]], 94 | [pin_header_info(), serial_dim, [-1,-1,-1], [0,0,0], [-1,-1, 1], [41, 6, 0]], 95 | [power_bbb_info(), power_dim, [ 1, 1,-1], [0,0,2], [-1,-1, 1], [-in2mm(100), in2mm(215), 0]], 96 | [rt_bbb_info(), rt1_dim, [-1,-1,-1], [0,0,0], [-1,-1, 1], [68, 6.5, 0]], 97 | [usb_info(), usb_dim, [ 1,-1,-1], [0,0,0], [ 1,-1, 1], [0, in2mm(405) - .6, 0]], 98 | ]; 99 | 100 | module beaglebone_black() { 101 | extrude_plate(board_dim[2], holes_pos, hole_d, ring_off) 102 | beaglebone_black_plate_2d(); 103 | 104 | set_components(board_dim, comp_info) { 105 | button(dim=button_dim, pusher_type="square"); 106 | button(dim=button_dim, pusher_type="square"); 107 | button(dim=button_dim, pusher_type="square"); 108 | ethernet(dim=ethernet_dim); 109 | female_header_pitch254(dim=gpio_dim, n=23, m=2); 110 | female_header_pitch254(dim=gpio_dim, n=23, m=2); 111 | microhdmi(dim=microhdmi_dim); 112 | microsdcard(dim=microsdcard_dim); 113 | microsdslot(dim=microsdslot_dim); 114 | miniusb(dim=miniusb_dim); 115 | pin_header_pitch254(dim=serial_dim, n=6, m=1); 116 | power_bbb(dim=power_dim); 117 | rt_bbb(dim=rt1_dim); 118 | usb(dim=usb_dim); 119 | } 120 | } 121 | 122 | function beaglebone_black_info() = [ 123 | ["board_dim", board_dim], 124 | ["components", comp_info], 125 | ["holes_d", hole_d], 126 | ["holes_pos", holes_pos], 127 | ]; 128 | 129 | demo_board(board_dim) { 130 | beaglebone_black(); 131 | *#bounding_box(board_dim, comp_info); 132 | } 133 | -------------------------------------------------------------------------------- /boards/cubieboard.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <../globals.scad> 16 | 17 | use <../case.scad> 18 | use <../utils.scad> 19 | use <../electronics/button.scad> 20 | use <../electronics/cpu.scad> 21 | use <../electronics/hdmi.scad> 22 | use <../electronics/header.scad> 23 | use <../electronics/jack.scad> 24 | use <../electronics/misc.scad> 25 | use <../electronics/network.scad> 26 | use <../electronics/power.scad> 27 | use <../electronics/sata.scad> 28 | use <../electronics/sd.scad> 29 | use <../electronics/usb.scad> 30 | 31 | 32 | board_dim = [100, 60, 1.25]; 33 | 34 | 35 | /* Plate holes */ 36 | hole_d = 3; 37 | hole_orig = [board_dim[0], board_dim[1]] * -.5; 38 | ring_off = 1.5; 39 | hole_pad = 3.5; 40 | hole_pad_t = [1,-1]*hole_pad; 41 | holes_pos = [for (y=hole_pad_t+[ 0, board_dim[1]], 42 | x=hole_pad_t+[19.5, board_dim[0]]) hole_orig + [x, y]]; 43 | 44 | 45 | /* Components bounding box dimensions */ 46 | cpu_dim = [ 19, 19, 1.25]; 47 | cpurad_dim = [ 19, 19, 5]; 48 | ethernet_dim = [ 21, 16, 13.5]; 49 | fel_dim = [ 3.5, 7, 3.5]; 50 | gpio_dim = [ 50, 6, 6]; 51 | hdmi_dim = [11.25, 15, 6]; 52 | ir_dim = [ 3.5, 5, 7]; 53 | jack_dim = [ 14, 6.5, 5]; 54 | microsdcard_dim = [ 15, 11, 1]; 55 | microsdslot_dim = [14.75, 15, 2]; 56 | otg_dim = [ 9, 7, 4]; 57 | power_dim = [ 12, 7.5, 6]; 58 | powerbtn_dim = [ 3.5, 7, 3.5]; 59 | sata_5v_dim = [ 7.5, 6, 7.5]; 60 | sata_data_dim = [ 17, 6.5, 9]; 61 | serial_dim = [10.25, 2.5, 8.5]; 62 | usbx2_dim = [ 17.5, 14.5, 16]; 63 | 64 | pwrhdmi_dim = [3.5, 2, 3.5]; // cleanup box 65 | 66 | module cubieboard_plate_2d() { 67 | plate_2d(board_dim[0], board_dim[1]); 68 | } 69 | 70 | comp_info = [ 71 | /* info function box dimensions comp-corner rotate board-corner position */ 72 | [button_drill_info(), fel_dim, [-1,-1, 1], [0,1,0], [ 1,-1,-1], [ 0,26.5, 0]], 73 | [button_drill_info(), powerbtn_dim, [-1, 1, 1], [0,3,0], [-1, 1, 1], [ -.5, -16, 0]], 74 | [cpu_info(), cpu_dim, [-1,-1,-1], [0,0,0], [-1,-1, 1], [47.5, 28, 0]], 75 | [cpurad_info(), cpurad_dim, [-1,-1,-1], [0,0,0], [-1,-1, 1], [47.5, 28,1.25]], 76 | [ethernet_info(), ethernet_dim, [ 1,-1,-1], [0,0,0], [ 1,-1, 1], [ 4, 8, 0]], 77 | [hdmi_info(), hdmi_dim, [ 1, 1,-1], [0,0,2], [-1,-1, 1], [ -.5, 20, 0]], 78 | [ir_info(), ir_dim, [-1,-1,-1], [0,0,3], [-1, 1, 1], [13.5, .5, 0]], 79 | [jack_info(), jack_dim, [ 1,-1, 1], [0,0,0], [ 1,-1,-1], [ 2, 39, 0]], // bottom 80 | [jack_info(), jack_dim, [ 1,-1,-1], [0,0,0], [ 1,-1, 1], [ 2, 39, 0]], // top 81 | [microsdcard_info(), microsdcard_dim, [ 1,-1,-1], [0,0,3], [-1,-1, 1], [ 5, -.5, 1]], 82 | [microsdslot_info(), microsdslot_dim, [ 1,-1,-1], [0,0,3], [-1,-1, 1], [ 4,1.75, 0]], 83 | [miniusb_info(), otg_dim, [ 1,-1,-1], [0,0,0], [ 1,-1, 1], [ 1,26.5, 0]], 84 | [pin_header_info(), gpio_dim, [ 1, 1,-1], [2,0,0], [ 1,-1,-1], [ -6, .5, 0]], 85 | [pin_header_info(), gpio_dim, [ 1,-1,-1], [2,0,0], [ 1, 1,-1], [ -6, -.5, 0]], 86 | [pin_header_info(), serial_dim, [-1, 1,-1], [0,0,1], [-1,-1, 1], [44.5, 17, 0]], 87 | [power_cubie_info(), power_dim, [ 1,-1,-1], [0,0,2], [-1, 1, 1], [ 0,-2.5, 0]], 88 | [sata_5v_info(), sata_5v_dim, [-1,-1,-1], [0,0,0], [-1,-1, 1], [ 18, 47, 0]], 89 | [sata_data_info(), sata_data_dim, [ 1,-1,-1], [0,0,2], [-1, 1, 1], [ 27, 0, 0]], 90 | [usbx2_info(), usbx2_dim, [ 1,-1,-1], [0,0,3], [-1,-1, 1], [ 29, -.5, 0]], 91 | 92 | [unknown_drill_info(), pwrhdmi_dim, [ 1, 1,-1], [0,0,2], [-1,-1, 1], [ -.5, 35, 0]], 93 | ]; 94 | 95 | module cubieboard() { 96 | // TODO: ring $fn=8 97 | extrude_plate(board_dim[2], holes_pos, hole_d, ring_off) 98 | cubieboard_plate_2d(); 99 | 100 | set_components(board_dim, comp_info) { 101 | button(dim=fel_dim); 102 | button(dim=powerbtn_dim); 103 | cpu(dim=cpu_dim); 104 | cpurad(dim=cpurad_dim); 105 | ethernet(dim=ethernet_dim); 106 | hdmi(dim=hdmi_dim); 107 | ir(dim=ir_dim); 108 | jack(dim=jack_dim); 109 | jack(dim=jack_dim); 110 | microsdcard(dim=microsdcard_dim); 111 | microsdslot(dim=microsdslot_dim); 112 | miniusb(dim=otg_dim); 113 | pin_header_pitch200(dim=gpio_dim, n=24, m=2); 114 | pin_header_pitch200(dim=gpio_dim, n=24, m=2); 115 | pin_header_pitch254(dim=serial_dim, n=4, m=1); 116 | power_cubie(dim=power_dim); 117 | sata_5v(dim=sata_5v_dim); 118 | sata_data(dim=sata_data_dim); 119 | usbx2(dim=usbx2_dim); 120 | 121 | %cube(pwrhdmi_dim, center=true); 122 | } 123 | } 124 | 125 | function cubieboard_info() = [ 126 | ["board_dim", board_dim], 127 | ["components", comp_info], 128 | ["holes_d", hole_d], 129 | ["holes_pos", holes_pos], 130 | ]; 131 | 132 | demo_board(board_dim) { 133 | cubieboard(); 134 | *#bounding_box(board_dim, comp_info); 135 | } 136 | -------------------------------------------------------------------------------- /boards/gif/bbb.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/boards/gif/bbb.gif -------------------------------------------------------------------------------- /boards/gif/cubieboard.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/boards/gif/cubieboard.gif -------------------------------------------------------------------------------- /boards/gif/hikey.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/boards/gif/hikey.gif -------------------------------------------------------------------------------- /boards/gif/nanopi_neo2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/boards/gif/nanopi_neo2.gif -------------------------------------------------------------------------------- /boards/gif/orangepi_zero.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/boards/gif/orangepi_zero.gif -------------------------------------------------------------------------------- /boards/gif/rpi3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/boards/gif/rpi3.gif -------------------------------------------------------------------------------- /boards/hikey.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <../globals.scad> 16 | 17 | use <../case.scad> 18 | use <../utils.scad> 19 | use <../electronics/button.scad> 20 | use <../electronics/hdmi.scad> 21 | use <../electronics/header.scad> 22 | use <../electronics/misc.scad> 23 | use <../electronics/power.scad> 24 | use <../electronics/sd.scad> 25 | use <../electronics/usb.scad> 26 | 27 | 28 | board_dim = [85.25, 54, 1.25]; 29 | 30 | 31 | /* Plate holes */ 32 | hole_d = 2.5; 33 | hole_orig = [board_dim[0], board_dim[1]] * -.5; 34 | ring_off = 2.5; 35 | hole_pad = 4; 36 | hole_pad_t = [1,-1]*hole_pad; 37 | holes_pos = [for (y=hole_pad_t+[14.5, board_dim[1]], 38 | x=hole_pad_t+[ 0, board_dim[0]]) hole_orig + [x, y]]; 39 | 40 | 41 | /* Components bounding box dimensions */ 42 | capacitor_dim = [ 6, 6, 5]; 43 | cfgpins_dim = [ 6, 4, 5]; 44 | extio_dim = [ 6, 30, 4]; 45 | gpio_dim = [40.5, 4, 4.5]; 46 | hdmi_dim = [9.25, 15, 6]; 47 | microsdcard_dim = [ 15, 11, 1]; 48 | microsdslot_dim = [15.5, 14,1.25]; 49 | microusb_dim = [ 6, 8, 3]; 50 | power_box_dim = [ 13, 9, 9]; // The box is larger to allow fitting a large round power cable 51 | power_dim = [ 13, 9, 6]; 52 | powerbtn_dim = [ 3.5, 3, 2]; 53 | uart0_dim = [ 4, 4, 5]; 54 | usb_dim = [ 14,14.5, 7]; 55 | 56 | 57 | module hikey_plate_2d() { 58 | plate_2d(board_dim[0], board_dim[1]); 59 | } 60 | 61 | comp_info = [ 62 | /* info function box dimensions comp-corner rotate board-corner position */ 63 | [button_info(), powerbtn_dim, [-1, 1,-1], [0,0,0], [-1, 1, 1], [ 52.5, -1, 0]], 64 | [capacitor_info(), capacitor_dim, [ 1, 1,-1], [0,0,0], [ 1, 1, 1], [ -19,-1.75, 0]], 65 | [extio_hikey_info(), extio_dim, [-1, 1,-1], [0,0,1], [-1,-1, 1], [ 18, 12, 0]], 66 | [female_header_info(), gpio_dim, [-1, 1,-1], [0,0,0], [-1, 1, 1], [ 9.5, -2, 0]], 67 | [hdmi_info(), hdmi_dim, [ 1,-1,-1], [0,0,3], [-1,-1, 1], [ 17.5, -2, 0]], 68 | [microsdcard_info(), microsdcard_dim, [ 1,-1,-1], [0,0,3], [-1,-1, 1], [ 1.5, -2, 0]], 69 | [microsdslot_info(), microsdslot_dim, [ 1,-1,-1], [0,0,3], [-1,-1, 1], [ 1.25, 0, 0]], 70 | [microusb_info(), microusb_dim, [ 1,-1,-1], [0,0,3], [-1,-1, 1], [37.75, -1, 0]], 71 | [pin_header_info(), cfgpins_dim, [-1, 1,-1], [0,0,1], [-1,-1, 1], [ 1, 40.5, 0]], 72 | [pin_header_info(), uart0_dim, [-1, 1,-1], [0,0,1], [-1,-1, 1], [ 1, 36, 0]], 73 | [power_hikey_info(), power_box_dim, [ 1,-1,-1], [0,0,1], [ 1, 1, 1], [ -8.5, 0,-1.5]], 74 | [usb_info(), usb_dim, [ 1,-1,-1], [0,0,3], [-1,-1, 1], [ 49, 0, 0]], 75 | [usb_info(), usb_dim, [ 1,-1,-1], [0,0,3], [-1,-1, 1], [ 69, 0, 0]], 76 | ]; 77 | 78 | module hikey() { 79 | extrude_plate(board_dim[2], holes_pos, hole_d, ring_off) 80 | hikey_plate_2d(); 81 | 82 | set_components(board_dim, comp_info) { 83 | button(dim=powerbtn_dim, pusher_type="circle"); 84 | capacitor(dim=capacitor_dim); 85 | extio_hikey(dim=extio_dim); 86 | female_header_pitch200(dim=gpio_dim, n=20, m=2); 87 | hdmi(dim=hdmi_dim); 88 | microsdcard(dim=microsdcard_dim); 89 | microsdslot(dim=microsdslot_dim); 90 | microusb(dim=microusb_dim); 91 | pin_header_pitch200(dim=cfgpins_dim, n=3, m=2); 92 | pin_header_pitch200(dim=uart0_dim, n=2, m=2); 93 | power_hikey(dim=power_dim); 94 | usb(dim=usb_dim); 95 | usb(dim=usb_dim); 96 | } 97 | } 98 | 99 | function hikey_info() = [ 100 | ["board_dim", board_dim], 101 | ["components", comp_info], 102 | ["holes_d", hole_d], 103 | ["holes_pos", holes_pos], 104 | ]; 105 | 106 | demo_board(board_dim) { 107 | hikey(); 108 | *#bounding_box(board_dim, comp_info); 109 | } 110 | -------------------------------------------------------------------------------- /boards/nanopi_neo2.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <../globals.scad> 16 | 17 | use <../case.scad> 18 | use <../utils.scad> 19 | use <../electronics/header.scad> 20 | use <../electronics/network.scad> 21 | use <../electronics/sd.scad> 22 | use <../electronics/usb.scad> 23 | 24 | 25 | board_dim = [40, 40, 1.25]; 26 | 27 | 28 | /* Plate holes */ 29 | hole_d = 3; 30 | hole_orig = [board_dim[0], board_dim[1]] * -.5; 31 | ring_off = 1.6; 32 | hole_pad = 2.3; 33 | hole_pad_t = [1,-1]*hole_pad; 34 | holes_pos = [for (y=hole_pad_t+[0, board_dim[1]], 35 | x=hole_pad_t+[0, board_dim[0]]) hole_orig + [x, y]]; 36 | 37 | 38 | /* Components bounding box dimensions */ 39 | ethernet_dim = [21.5, 15.5, 11.5]; 40 | microsdcard_dim = [ 15, 11, 1]; 41 | microsdslot_dim = [11.5, 12, 1.25]; 42 | microusb_dim = [ 6, 8, 3]; 43 | serial_dim = [10.5, 2.5, 8.5]; 44 | usb_dim = [ 14, 14, 6]; 45 | 46 | ethusb_dim = [ 14, 8.75, 3]; // cleanup box 47 | 48 | 49 | module nanopi_neo2_plate_2d(cut=false) { 50 | difference() { 51 | plate_2d(board_dim[0], board_dim[1], corner_radius=3); 52 | 53 | // The plate is actually cut such that the ethernet slot is stuck in 54 | // the middle. We prevent displaying it in the board here, will still 55 | // keeping the plate shape untouched by default for the case 56 | if (cut) 57 | translate([(board_dim[0]-ethernet_dim[0])/2 + 4, 58 | (board_dim[1]-ethernet_dim[1])/2 - 7]) 59 | square([ethernet_dim[0], ethernet_dim[1]], center=true); 60 | } 61 | } 62 | 63 | comp_info = [ 64 | /* info function box dimensions comp-corner rotate board-corner position */ 65 | [ethernet_info(), ethernet_dim, [ 1,-1, 1], [2,0,0], [ 1, 1,-1], [ 4, -7,-1.5]], 66 | [microsdcard_info(), microsdcard_dim, [ 1, 1,-1], [0,0,2], [-1,-1, 1], [ -2, 7,0.25]], 67 | [microsdslot_info(), microsdslot_dim, [ 1, 1,-1], [0,0,2], [-1,-1, 1], [ 2,6.50, 0]], 68 | [microusb_info(), microusb_dim, [ 1,-1,-1], [0,0,2], [-1, 1, 1], [-.5, -6, 0]], 69 | [pin_header_info(), serial_dim, [ 1,-1,-1], [0,0,0], [ 1,-1, 1], [ -5,2.25, 0]], 70 | [usb_info(), usb_dim, [ 1,-1, 1], [1,0,0], [ 1,-1, 1], [3.5, 8.5, 0]], 71 | 72 | [unknown_info(), ethusb_dim, [ 1,-1, 1], [1,0,0], [ 1,-1, 1], [3.5,14.5,0]], 73 | ]; 74 | 75 | module nanopi_neo2() { 76 | extrude_plate(board_dim[2], holes_pos, hole_d, ring_off, clr=c_darkblue) 77 | nanopi_neo2_plate_2d(cut=true); 78 | 79 | set_components(board_dim, comp_info) { 80 | ethernet(dim=ethernet_dim, swap_led=true); 81 | microsdcard(dim=microsdcard_dim); 82 | microsdslot(dim=microsdslot_dim); 83 | microusb(dim=microusb_dim); 84 | pin_header_pitch254(dim=serial_dim, n=4, m=1); 85 | usb(dim=usb_dim, has_folding=false); 86 | 87 | %cube(ethusb_dim, center=true); 88 | } 89 | } 90 | 91 | function nanopi_neo2_info() = [ 92 | ["board_dim", board_dim], 93 | ["components", comp_info], 94 | ["holes_d", hole_d], 95 | ["holes_pos", holes_pos], 96 | ]; 97 | 98 | demo_board(board_dim) { 99 | nanopi_neo2(); 100 | *#bounding_box(board_dim, comp_info); 101 | } 102 | -------------------------------------------------------------------------------- /boards/orangepi_zero.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <../globals.scad> 16 | 17 | use <../case.scad> 18 | use <../utils.scad> 19 | use <../electronics/header.scad> 20 | use <../electronics/misc.scad> 21 | use <../electronics/network.scad> 22 | use <../electronics/sd.scad> 23 | use <../electronics/usb.scad> 24 | 25 | 26 | board_dim = [48, 46, 1.5]; 27 | 28 | 29 | /* Plate holes */ 30 | hole_d = 3; 31 | hole_orig = [board_dim[0], board_dim[1]] * -.5; 32 | ring_off = 2; 33 | hole_pad = hole_d/2 + 1.5; 34 | hole_pad_t = [1,-1]*hole_pad; 35 | holes_pos = [for (y=hole_pad_t+[0, board_dim[1]], 36 | x=hole_pad_t+[0, board_dim[0]]) hole_orig + [x, y]]; 37 | 38 | 39 | /* Components bounding box dimensions */ 40 | antenna_dim = [ 5, 5, 60]; 41 | ethernet_dim = [16.15, 16.15, 13]; 42 | gpio_dim = [ 32.6, 2.5, 8.65]; 43 | microsdcard_dim = [ 15, 11, 1]; 44 | microsdslot_dim = [14.75, 15, 2]; 45 | microusb_dim = [ 6, 8, 3]; 46 | pulse_dim = [ 13, 7, 6]; 47 | serial_dim = [ 7.25, 2.5, 8.5]; 48 | usb_dim = [14.25, 13, 7]; 49 | 50 | ethusb_dim = [14.25, 2.35, 13]; // cleanup box 51 | 52 | 53 | module orangepi_zero_plate_2d() { 54 | plate_2d(board_dim[0], board_dim[1], corner_radius=2); 55 | } 56 | 57 | comp_info = [ 58 | /* info function box dimensions comp-corner rotate board-corner position */ 59 | [antenna_info(), antenna_dim, [ 0, 0,-1], [0,0,0], [ 1, 1, 0], [ -8, -8, 0]], // arbitrary position 60 | [chip_info(), pulse_dim, [ 1,-1,-1], [0,0,1], [ 1, 1, 1], [ -26, -15, 0]], 61 | [ethernet_info(), ethernet_dim, [ 1, 1, 1], [0,2,0], [-1, 1, 1], [ -3, -14.5, 0]], 62 | [microsdcard_info(), microsdcard_dim, [ 1,-1,-1], [2,0,0], [ 1, 1,-1], [ 2.5,-12.75,-0.75]], 63 | [microsdslot_info(), microsdslot_dim, [ 1,-1,-1], [2,0,0], [ 1, 1,-1], [ 0, -12, 0]], 64 | [microusb_info(), microusb_dim, [ 1,-1,-1], [0,0,0], [ 1,-1, 1], [ 0.75, 6, 0]], 65 | [pin_header_info(), gpio_dim, [-1,-1,-1], [0,0,0], [-1,-1, 1], [ 7.5, 0, 0]], 66 | [pin_header_info(), serial_dim, [-1, 1,-1], [0,0,0], [-1, 1, 1], [ 0.2, -8.3, 0]], 67 | [usb_info(), usb_dim, [ 1,-1,-1], [1,0,2], [-1,-1, 1], [ -3, 6, 0]], 68 | 69 | [unknown_info(), ethusb_dim, [-1,-1,-1], [0,0,0], [-1,-1, 1], [ -3, 13, 0]], 70 | ]; 71 | 72 | module orangepi_zero() { 73 | extrude_plate(board_dim[2], holes_pos, hole_d, ring_off, clr=c_darkblue) 74 | orangepi_zero_plate_2d(cut=true); 75 | 76 | set_components(board_dim, comp_info) { 77 | antenna(dim=antenna_dim); 78 | chip(dim=pulse_dim); 79 | ethernet(dim=ethernet_dim); 80 | microsdcard(dim=microsdcard_dim); 81 | microsdslot(dim=microsdslot_dim); 82 | microusb(dim=microusb_dim); 83 | pin_header_pitch254(dim=gpio_dim, n=13, m=1); 84 | pin_header_pitch254(dim=serial_dim, n=3, m=1); 85 | usb(dim=usb_dim, has_folding=false); 86 | 87 | %cube(ethusb_dim, center=true); 88 | } 89 | } 90 | 91 | function orangepi_zero_info() = [ 92 | ["board_dim", board_dim], 93 | ["components", comp_info], 94 | ["holes_d", hole_d], 95 | ["holes_pos", holes_pos], 96 | ]; 97 | 98 | demo_board(board_dim) { 99 | orangepi_zero(); 100 | *#bounding_box(board_dim, comp_info); 101 | } 102 | -------------------------------------------------------------------------------- /boards/rpi3.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <../globals.scad> 16 | 17 | use <../case.scad> 18 | use <../utils.scad> 19 | use <../electronics/hdmi.scad> 20 | use <../electronics/header.scad> 21 | use <../electronics/jack.scad> 22 | use <../electronics/misc.scad> 23 | use <../electronics/network.scad> 24 | use <../electronics/sd.scad> 25 | use <../electronics/usb.scad> 26 | 27 | 28 | board_dim = [85, 56, 1.25]; 29 | 30 | 31 | /* Plate holes */ 32 | hole_d = 2.75; 33 | hole_orig = [board_dim[0], board_dim[1]] * -.5; 34 | ring_off = 6.2 - hole_d; 35 | hole_pad = 3.5; 36 | holes_pos = [for (y=[0, 49], x=[0, 58]) hole_orig + [x, y] + hole_pad*[1,1]]; 37 | 38 | 39 | /* Components bounding box dimensions */ 40 | ethernet_dim = [ 21, 16, 13.5]; 41 | gpio_dim = [ 51, 5, 8.5]; 42 | hdmi_dim = [ 11.5, 15, 6.5]; 43 | jack_dim = [ 14.5, 7, 6]; 44 | microsdcard_dim = [ 15, 11, 1]; 45 | microsdslot_dim = [ 11.5, 12, 1.25]; 46 | microusb_dim = [ 6, 8, 3]; 47 | serialcon_dim = [ 2.5, 22, 5.5]; 48 | usbx2_dim = [17.25, 15, 16.5]; 49 | 50 | ethusb_dim = [17.25, 3.25, 13.5]; // cleanup box 51 | usbusb_dim = [17.25, 3, 16.5]; // cleanup box 52 | 53 | 54 | module raspberry_pi_3_plate_2d() { 55 | plate_2d(board_dim[0], board_dim[1], 3); 56 | } 57 | 58 | comp_info = [ 59 | /* info function box dimensions comp-corner rotate board-corner position */ 60 | [ethernet_info(), ethernet_dim, [ 1, 0,-1], [0,0,0], [ 1,-1, 1], [ 2,10.25,0]], 61 | [hdmi_info(), hdmi_dim, [ 1, 0,-1], [0,0,3], [-1,-1, 1], [ 32, -1,0]], 62 | [jack_info(), jack_dim, [ 1, 0,-1], [0,0,3], [-1,-1, 1], [53.5, -2,0]], 63 | [microsdcard_info(), microsdcard_dim, [ 1, 0,-1], [2,0,2], [-1, 0,-1], [-2.25, 0,0]], 64 | [microsdslot_info(), microsdslot_dim, [ 1, 0,-1], [2,0,2], [-1, 0,-1], [ 1.75, 0,0]], 65 | [microusb_info(), microusb_dim, [ 1, 0,-1], [0,0,3], [-1,-1, 1], [10.6, -1,0]], 66 | [pin_header_info(), gpio_dim, [ 0, 0,-1], [0,0,0], [-1, 1, 1], [32.5, -3.5,0]], 67 | [serialcon_rpi_info(), serialcon_dim, [ 0,-1,-1], [0,0,0], [-1,-1, 1], [ 45, .25,0]], // camera 68 | [serialcon_rpi_info(), serialcon_dim, [ 1, 0,-1], [0,0,2], [-1,-1, 1], [ 3, 28,0]], // display 69 | [usbx2_info(), usbx2_dim, [ 1, 0,-1], [0,0,0], [ 1,-1, 1], [ 2, 29,0]], 70 | [usbx2_info(), usbx2_dim, [ 1, 0,-1], [0,0,0], [ 1,-1, 1], [ 2, 47,0]], 71 | 72 | [unknown_info(), ethusb_dim, [ 1, 0,-1], [0,0,0], [ 1,-1, 1], [ 2,19.875,0]], 73 | [unknown_info(), usbusb_dim, [ 1, 0,-1], [0,0,0], [ 1,-1, 1], [ 2, 38,0]], 74 | ]; 75 | 76 | module raspberry_pi_3() { 77 | extrude_plate(board_dim[2], holes_pos, hole_d, ring_off, clr=c_green_pcb, clr_ring=c_yellow) 78 | raspberry_pi_3_plate_2d(); 79 | 80 | set_components(board_dim, comp_info) { 81 | ethernet(dim=ethernet_dim, swap_led=true); 82 | hdmi(dim=hdmi_dim); 83 | jack(dim=jack_dim); 84 | microsdcard(dim=microsdcard_dim); 85 | microsdslot(dim=microsdslot_dim); 86 | microusb(dim=microusb_dim); 87 | pin_header_pitch254(dim=gpio_dim, n=20, m=2); 88 | serialcon_rpi(dim=serialcon_dim); 89 | serialcon_rpi(dim=serialcon_dim); 90 | usbx2(dim=usbx2_dim); 91 | usbx2(dim=usbx2_dim); 92 | 93 | %cube(ethusb_dim, center=true); 94 | %cube(usbusb_dim, center=true); 95 | } 96 | } 97 | 98 | function raspberry_pi_3_info() = [ 99 | ["board_dim", board_dim], 100 | ["components", comp_info], 101 | ["holes_d", hole_d], 102 | ["holes_pos", holes_pos], 103 | ]; 104 | 105 | 106 | demo_board(board_dim) { 107 | raspberry_pi_3(); 108 | *#bounding_box(board_dim, comp_info); 109 | } 110 | -------------------------------------------------------------------------------- /boards/wemos_esp8266.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Dan Kortschak 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <../globals.scad> 16 | 17 | use <../case.scad> 18 | use <../utils.scad> 19 | use <../electronics/button.scad> 20 | use <../electronics/cpu.scad> 21 | use <../electronics/usb.scad> 22 | use <../electronics/misc.scad> 23 | 24 | 25 | board_dim = [34.5, 25.75, 1]; 26 | 27 | 28 | /* Plate holes */ 29 | hole_d = 1; 30 | hole_orig = [board_dim[0], board_dim[1]] * -.5; 31 | hole_off = 8; 32 | pitch = 2.54; 33 | ring_off = 0.5; 34 | hole_pad = 1; 35 | hole_pad_t = [1,1]*hole_pad; 36 | holes_pos = [for (y=hole_pad_t+[0, board_dim[1]-2], x=hole_pad_t+[hole_off, hole_off+7*pitch]) 37 | hole_orig + [x, y]]; 38 | 39 | 40 | /* Components bounding box dimensions */ 41 | controller_dim = [15, 12, 3 ]; 42 | power_dim = [10, 4, 1.5 ]; 43 | antenna_dim = [7.5, 16, 1 ]; 44 | antenna_led_dim = [1, 1, 0.2 ]; 45 | microusb_dim = [ 6, 9.5, 5.5 ]; 46 | reset_dim = [ 4.5, 2, 3 ]; 47 | reset_recess_dim = [ 7, 2 ]; 48 | pusher_dim = 1; 49 | 50 | 51 | module wemos_esp8266_plate_2d(cut=false) { 52 | if (cut) { 53 | difference() { 54 | plate_2d(board_dim[0], board_dim[1], corner_radius=3); 55 | 56 | translate([-board_dim[0]/2, -board_dim[1]/2]) 57 | square(reset_recess_dim); 58 | } 59 | } else { 60 | union() { 61 | plate_2d(board_dim[0], board_dim[1], corner_radius=3); 62 | 63 | translate([-board_dim[0]/2, -board_dim[1]/2]) 64 | square(reset_recess_dim+[0, 2]); 65 | } 66 | } 67 | translate([-board_dim[0]/2, board_dim[1]/2-3]) 68 | square([3,3]); 69 | } 70 | 71 | comp_info = [ 72 | /* info function box dimensions comp-corner rotate board-corner position */ 73 | [cpu_info(), controller_dim, [ 1,-1,-1], [0,0,2], [-1, 1, -1], [12, -7, -controller_dim[2]]], 74 | [chip_info(), power_dim, [ 1,-1,-1], [0,0,3], [-1, 1, 1], [10, -19, 0]], 75 | [antenna_info(), antenna_dim, [ 1,-1,-1], [0,0,2], [1, 1, -1], [-antenna_dim[0], -5, -antenna_dim[2]]], 76 | [led_info(), antenna_led_dim, [ 1,-1,-1], [0,2,0], [1, 1, -1], [-antenna_dim[0], -7.5, -antenna_dim[2]]], 77 | [microusb_info(), microusb_dim, [ 1,-1,-1], [0,0,2], [-1, 1, 1], [0, -8.5, -1.25]], 78 | [button_drill_info(), reset_dim, [ 1,-1,-1], [3,0,2], [-1, -1, 1], [1, reset_dim[2]+reset_recess_dim[1]-pusher_dim, 2]], 79 | ]; 80 | 81 | module wemos_esp8266() { 82 | extrude_plate(board_dim[2], holes_pos, hole_d, ring_off, clr=c_darkblue) 83 | wemos_esp8266_plate_2d(true); 84 | 85 | set_components(board_dim, comp_info) { 86 | cpu(dim=controller_dim, clr=c_metal); 87 | chip(dim=power_dim); 88 | antenna(dim=antenna_dim); 89 | led(dim=antenna_led_dim); 90 | microusb(dim=microusb_dim); 91 | button(dim=reset_dim, pusher_h=pusher_dim); 92 | } 93 | } 94 | 95 | function wemos_esp8266_info() = [ 96 | ["board_dim", board_dim], 97 | ["components", comp_info], 98 | ["holes_d", hole_d], 99 | ["holes_pos", holes_pos], 100 | ]; 101 | 102 | demo_board(board_dim) { 103 | wemos_esp8266(); 104 | *#bounding_box(board_dim, comp_info); 105 | } 106 | -------------------------------------------------------------------------------- /case.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include 16 | include 17 | use 18 | 19 | case_thickness = 1.2; 20 | breath_padding = 1; 21 | contact_padding = .2; 22 | 23 | /* Centered top of the buttons looking at the sky, and their dimensions */ 24 | function _get_buttons_pushers_pos_dim(board_dim, cfg, info) = [ 25 | let(comp_info_list = map_get(info, "components")) 26 | 27 | for (comp_info = comp_info_list) 28 | let(meta = comp_info[0], 29 | dim = comp_info[1], 30 | corner_comp = comp_info[2], 31 | rot = comp_info[3], 32 | corner_board = comp_info[4], 33 | position = comp_info[5], 34 | category = map_get(meta, "category")) 35 | 36 | if (category == "button" && [rot[0], rot[1]] == [0, 0]) 37 | let(rz = comp_info[3][2] * 90, 38 | rotm = [[cos(rz),sin(rz),0], [-sin(rz),cos(rz),0], [0,0,1]], 39 | corner_pos = pmul(corner_comp, dim) * -.5, 40 | postrotate_pos = corner_pos * rotm, 41 | board_pos = pmul(corner_board, board_dim) * .5, 42 | centered_pos = postrotate_pos + position + board_pos, 43 | pos = centered_pos + [0, 0, dim[2]/2]) 44 | 45 | [pos, dim] 46 | ]; 47 | 48 | module _vents(vents, w=2.1) { 49 | if (vents != []) { 50 | dim = map_get(vents, "dim"); 51 | pos = map_get(vents, "pos"); 52 | 53 | length = dim[1]; 54 | n_segments = floor(length / w); 55 | n_vents = ceil(n_segments / 2); 56 | n_segwalls = n_segments - n_vents; 57 | n_walls = n_segwalls - (n_segwalls == n_vents ? 1 : 0); 58 | off = (length - (n_vents+n_walls)*w) / 2; 59 | start = -length/2 + off + w/2; 60 | translate(pos) { 61 | intersection() { 62 | circle(d=max(dim), center=true); 63 | for (i = [0:n_vents-1]) 64 | translate([0, start + i*w*2]) 65 | square([dim[0], w], center=true); 66 | } 67 | } 68 | } 69 | } 70 | 71 | module _case_plate_2d(case_id) { 72 | offset(r=case_thickness + breath_padding + _delta) 73 | boards_get_plate_2d(case_id); 74 | } 75 | 76 | module _case_top(case_id, cfg, info, z_offset, buttons_pos_dim) { 77 | top_border_height = 3; // XXX: maybe auto to (max_z+bp)/2 or /3? 78 | 79 | board_dim = map_get(info, "board_dim"); 80 | comp_info = map_get(info, "components"); 81 | holes_d = map_get(info, "holes_d"); 82 | holes_pos = map_get(info, "holes_pos"); 83 | 84 | vents = map_get(map_get(cfg, "vents"), "top"); 85 | 86 | difference() { 87 | union() { 88 | // plate 89 | linear_extrude(height=case_thickness, center=true, convexity=2) { 90 | difference() { 91 | _case_plate_2d(case_id); 92 | _vents(vents); 93 | } 94 | } 95 | 96 | // borders 97 | translate([0, 0, -case_thickness/2 - top_border_height]) { 98 | linear_extrude(height=top_border_height, convexity=2) { 99 | difference() { 100 | offset(r=breath_padding - contact_padding) 101 | boards_get_plate_2d(case_id); 102 | offset(r=breath_padding - contact_padding - case_thickness) 103 | boards_get_plate_2d(case_id); 104 | } 105 | } 106 | } 107 | 108 | // board carriers clippers 109 | h = map_get(cfg, "max_z") + breath_padding - contact_padding; 110 | for(pos = holes_pos) { 111 | translate([pos[0], pos[1], -(h+case_thickness)/2]) { 112 | difference() { 113 | cylinder(h=h, d=holes_d+2, center=true); 114 | cylinder(h=h+_delta, d=holes_d, center=true); 115 | } 116 | } 117 | } 118 | 119 | // button pushers borders 120 | for (button_pos_dim = buttons_pos_dim) { 121 | button_pos = button_pos_dim[0]; 122 | button_dim = button_pos_dim[1]; 123 | h = top_border_height; 124 | d = _get_button_pusher_d(button_dim) + case_thickness*2; 125 | translate([button_pos[0], button_pos[1], -case_thickness/2-h]) 126 | cylinder(h=h, d=d); 127 | } 128 | } 129 | 130 | translate([0, 0, -z_offset]) 131 | bounding_box(board_dim, comp_info, breath_padding); 132 | 133 | for (button_pos_dim = buttons_pos_dim) { 134 | button_pos = button_pos_dim[0]; 135 | button_dim = button_pos_dim[1]; 136 | h = top_border_height + case_thickness + _delta; 137 | d = _get_button_pusher_d(button_dim) + contact_padding; 138 | translate([button_pos[0], button_pos[1], case_thickness/2-h+_delta/2]) 139 | cylinder(h=h, d=d); 140 | } 141 | } 142 | } 143 | 144 | module _case_bottom(case_id, cfg, info, z_offset, bottom_border_h) { 145 | board_dim = map_get(info, "board_dim"); 146 | comp_info = map_get(info, "components"); 147 | holes_d = map_get(info, "holes_d"); 148 | holes_pos = map_get(info, "holes_pos"); 149 | 150 | vents = map_get(map_get(cfg, "vents"), "bottom"); 151 | 152 | difference() { 153 | union() { 154 | // plate 155 | linear_extrude(height=case_thickness, center=true) { 156 | difference() { 157 | _case_plate_2d(case_id); 158 | _vents(vents); 159 | } 160 | } 161 | 162 | // borders 163 | translate([0, 0, case_thickness/2]) { 164 | linear_extrude(height=bottom_border_h, convexity=2) { 165 | difference() { 166 | _case_plate_2d(case_id); 167 | offset(r=breath_padding + _delta) 168 | boards_get_plate_2d(case_id); 169 | } 170 | } 171 | } 172 | 173 | // board carriers 174 | carriers_base_h = -z_offset - board_dim[2]/2 - case_thickness/2; 175 | for(pos = holes_pos) { 176 | translate([pos[0], pos[1], case_thickness/2]) { 177 | l1 = carriers_base_h; 178 | l = carriers_base_h + board_dim[2] + 1; 179 | w0 = holes_d/2 - contact_padding; 180 | w1 = w0 + 1; 181 | w2 = w0 + 2.5; 182 | rotate_extrude() 183 | polygon([[0, 0], [w2, 0], [w1, l1], [w0, l1], [w0, l], [0, l]]); 184 | } 185 | } 186 | } 187 | translate([0, 0, -z_offset]) 188 | bounding_box(board_dim, comp_info, breath_padding); 189 | } 190 | 191 | } 192 | 193 | module _button_pushers(board_dim, cfg, info, buttons_pos_dim) { 194 | for (button_pos_dim = buttons_pos_dim) { 195 | button_pos = button_pos_dim[0]; 196 | button_dim = button_pos_dim[1]; 197 | translate(button_pos) { 198 | h = _get_button_pusher_base_h(cfg) - button_dim[2]; 199 | d = _get_button_pusher_d(button_dim); 200 | cylinder(d=d, h=d/2); 201 | cylinder(d=2*d/3, h=h); 202 | } 203 | } 204 | } 205 | 206 | function _get_button_pusher_base_h(info) = 207 | map_get(info, "max_z") + breath_padding + case_thickness + 1; 208 | 209 | function _get_button_pusher_d(button_dim) = 210 | max(min(button_dim[0], button_dim[1]), 3.5); 211 | 212 | module case(name, cfg, mode="demo") { 213 | case_id = boards_get_id(name); 214 | info = boards_get_info(case_id); 215 | comp_info = map_get(info, "components"); 216 | 217 | // TODO: find min_z and max_z based on the comp list when not provided 218 | min_z = map_get(cfg, "min_z"); 219 | max_z = map_get(cfg, "max_z"); 220 | 221 | board_dim = map_get(info, "board_dim"); 222 | board_h = board_dim[2]; 223 | 224 | bottom_border_h = min_z + max_z + breath_padding*2 + board_h; 225 | 226 | z_offset_base = board_h/2 + breath_padding + case_thickness/2; 227 | z_offset_bottom = -z_offset_base - min_z; 228 | z_offset_top = z_offset_base + max_z; 229 | 230 | case_pos_bottom = [0, 0, z_offset_bottom]; 231 | case_pos_top = [0, 0, z_offset_top]; 232 | 233 | buttons_pos_dim = _get_buttons_pushers_pos_dim(board_dim, cfg, info); 234 | 235 | if (mode == "bottom") { 236 | _case_bottom(case_id, cfg, info, z_offset_bottom, bottom_border_h); 237 | } else if (mode == "top") { 238 | rotate([180, 0, 0]) // flip it to be printable friendly 239 | _case_top(case_id, cfg, info, z_offset_top, buttons_pos_dim); 240 | } else if (mode == "button") { 241 | _button_pushers(board_dim, cfg, info, buttons_pos_dim); 242 | } else if (mode == "check_intersections") { 243 | intersection() { 244 | translate(case_pos_bottom) 245 | _case_bottom(case_id, cfg, info, z_offset_bottom, bottom_border_h); 246 | boards_get_board(case_id); 247 | translate(case_pos_top) 248 | _case_top(case_id, cfg, info, z_offset_top, buttons_pos_dim); 249 | } 250 | } else if (mode == "demo") { 251 | rotate([0, 0, $t*360]) { 252 | 253 | translate(case_pos_bottom) 254 | _case_bottom(case_id, cfg, info, z_offset_bottom, bottom_border_h); 255 | 256 | if (len(buttons_pos_dim)) { 257 | stack_animate(time=$t) { 258 | boards_get_board(case_id); 259 | _button_pushers(board_dim, cfg, info, buttons_pos_dim); 260 | translate(case_pos_top) 261 | _case_top(case_id, cfg, info, z_offset_top, buttons_pos_dim); 262 | } 263 | } else { 264 | stack_animate(time=$t) { 265 | boards_get_board(case_id); 266 | translate(case_pos_top) 267 | _case_top(case_id, cfg, info, z_offset_top, buttons_pos_dim); 268 | } 269 | } 270 | 271 | } 272 | } else { 273 | echo(str("Unknown mode ", mode)); 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /cases/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Clément Bœsch 2 | # 3 | # Permission to use, copy, modify, and distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | OPENSCAD_EXTRA_SETTINGS = --camera=0,0,0,45,0,45,300 16 | GIF_FINAL_DELAY ?= 250 17 | 18 | BOARDS_WITH_BUTTON_PUSHERS = bbb hikey 19 | STLS_EXTRA = $(addsuffix -button.stl,$(BOARDS_WITH_BUTTON_PUSHERS)) 20 | 21 | include ../common.mk 22 | -------------------------------------------------------------------------------- /cases/bbb.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use <../boards/bbb.scad> 16 | use <../case.scad> 17 | use <../utils.scad> 18 | 19 | board_dim = map_get(beaglebone_black_info(), "board_dim"); 20 | 21 | cfg = [ 22 | ["min_z", 4], 23 | ["max_z", 7.5], 24 | ["vents", default_vents(board_dim)], 25 | ]; 26 | 27 | mode = "demo"; 28 | case("bbb", cfg, mode); 29 | -------------------------------------------------------------------------------- /cases/cubieboard.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use <../boards/cubieboard.scad> 16 | use <../case.scad> 17 | use <../utils.scad> 18 | 19 | board_dim = map_get(cubieboard_info(), "board_dim"); 20 | 21 | vents = [ 22 | [ 23 | "bottom", default_bottom_vents(board_dim, s=.5), 24 | ],[ 25 | "top", [ 26 | ["dim", [board_dim[0] * .6, board_dim[1] * .35]], 27 | ["pos", [15, 10]], 28 | ] 29 | ] 30 | ]; 31 | 32 | cfg = [ 33 | ["min_z", 7], 34 | ["max_z", 7.5], 35 | ["vents", vents], 36 | ]; 37 | 38 | mode = "demo"; 39 | case("cubieboard", cfg, mode); 40 | -------------------------------------------------------------------------------- /cases/gif/bbb.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/cases/gif/bbb.gif -------------------------------------------------------------------------------- /cases/gif/cubieboard.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/cases/gif/cubieboard.gif -------------------------------------------------------------------------------- /cases/gif/hikey.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/cases/gif/hikey.gif -------------------------------------------------------------------------------- /cases/gif/nanopi_neo2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/cases/gif/nanopi_neo2.gif -------------------------------------------------------------------------------- /cases/gif/orangepi_zero.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/cases/gif/orangepi_zero.gif -------------------------------------------------------------------------------- /cases/gif/rpi3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/cases/gif/rpi3.gif -------------------------------------------------------------------------------- /cases/hikey.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use <../boards/hikey.scad> 16 | use <../case.scad> 17 | use <../utils.scad> 18 | 19 | board_dim = map_get(hikey_info(), "board_dim"); 20 | 21 | vents = [ 22 | [ 23 | "top", [ 24 | ["dim", [board_dim[0] * .75, board_dim[1] * .4]], 25 | ["pos", [0, board_dim[1]*1/10]], 26 | ], 27 | ],[ 28 | "bottom", default_bottom_vents(board_dim), 29 | ], 30 | ]; 31 | 32 | cfg = [ 33 | ["min_z", 3], 34 | ["max_z", 9], 35 | ["vents", vents], 36 | ]; 37 | 38 | mode = "demo"; 39 | case("hikey", cfg, mode); 40 | -------------------------------------------------------------------------------- /cases/nanopi_neo2.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use <../boards/nanopi_neo2.scad> 16 | use <../case.scad> 17 | use <../utils.scad> 18 | 19 | board_dim = map_get(nanopi_neo2_info(), "board_dim"); 20 | 21 | vents = [ 22 | [ 23 | "bottom", default_bottom_vents(board_dim, s=.5), 24 | ], 25 | ]; 26 | 27 | cfg = [ 28 | ["min_z", 3], 29 | ["max_z", 4], 30 | ["vents", vents], 31 | ]; 32 | 33 | mode = "demo"; 34 | case("nanopi_neo2", cfg, mode); 35 | -------------------------------------------------------------------------------- /cases/orangepi_zero.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use <../boards/orangepi_zero.scad> 16 | use <../case.scad> 17 | use <../utils.scad> 18 | 19 | board_dim = map_get(orangepi_zero_info(), "board_dim"); 20 | 21 | vents = [ 22 | [ 23 | "bottom", default_bottom_vents(board_dim), 24 | ],[ 25 | "top", [ 26 | ["dim", board_dim * .5], 27 | ["pos", [1/3*board_dim[0]/2, 0]], 28 | ], 29 | ] 30 | ]; 31 | 32 | cfg = [ 33 | ["min_z", 3], 34 | ["max_z", 6], 35 | ["vents", vents], 36 | ]; 37 | 38 | mode = "demo"; 39 | case("orangepi_zero", cfg, mode); 40 | -------------------------------------------------------------------------------- /cases/rpi3.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use <../boards/rpi3.scad> 16 | use <../case.scad> 17 | use <../utils.scad> 18 | 19 | board_dim = map_get(raspberry_pi_3_info(), "board_dim"); 20 | 21 | vents = [ 22 | [ 23 | "bottom", default_bottom_vents(board_dim), 24 | ],[ 25 | "top", [ 26 | ["dim", [board_dim[0] * .3, board_dim[1] * .7]], 27 | ["pos", [-18, -4.5]], 28 | ] 29 | ] 30 | ]; 31 | 32 | cfg = [ 33 | ["min_z", 3], 34 | ["max_z", 9], 35 | ["vents", vents], 36 | ]; 37 | 38 | mode = "demo"; 39 | case("rpi3", cfg, mode); 40 | -------------------------------------------------------------------------------- /cases/wemos_esp8266.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Dan Kortschak 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | use <../boards/wemos_esp8266.scad> 16 | use <../case.scad> 17 | use <../utils.scad> 18 | 19 | board_dim = map_get(wemos_esp8266_info(), "board_dim"); 20 | 21 | vents = [ 22 | [ 23 | "bottom", [ 24 | ["dim", [board_dim[0] * .4, board_dim[1] * .3]], 25 | ["pos", [board_dim[0]/15, 0]], 26 | ], 27 | ] 28 | ]; 29 | 30 | cfg = [ 31 | ["min_z", 2.75], 32 | ["max_z", 3.75], 33 | ["vents", vents], 34 | ]; 35 | 36 | mode = "demo"; 37 | case("wemos_esp8266", cfg, mode); 38 | -------------------------------------------------------------------------------- /common.mk: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Clément Bœsch 2 | # 3 | # Permission to use, copy, modify, and distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | OPENSCAD ?= openscad --colorscheme="Tomorrow Night" --imgsize=1024,1024 $(OPENSCAD_EXTRA_SETTINGS) 16 | DSCALE ?= scale=iw/4:ih/4:flags=lanczos 17 | FFMPEG ?= ffmpeg -v warning 18 | STEPS ?= 200 19 | FPS ?= 30 20 | GIF_FINAL_DELAY ?= -1 21 | 22 | define anim_pattern 23 | %$(shell printf $(1) | wc -c)d 24 | endef 25 | 26 | define anim_pictures 27 | $(addsuffix .png,$(addprefix anim-$(1)-,$(shell seq -w $(2)))) 28 | endef 29 | 30 | define dashsplit 31 | $(word $(1),$(subst -, ,$(2))) 32 | endef 33 | 34 | define get_openscad_var 35 | $(if $(shell grep ^\$$$(1) $(2)),$(shell sed -nE 's#^\$$$(1)\s*=\s*([0-9]+)\s*;#\1#p' $(2)),$(3)) 36 | endef 37 | 38 | ANIM_PATTERN := $(call anim_pattern,$(STEPS)) 39 | TARGETS = $(sort $(filter-out _internal,$(subst .scad,,$(wildcard *.scad)))) 40 | GIFS = $(addsuffix .gif,$(addprefix gif/,$(TARGETS))) 41 | STLS = $(addsuffix -bottom.stl,$(TARGETS)) $(addsuffix -top.stl,$(TARGETS)) 42 | 43 | gif: $(GIFS) 44 | 45 | stl: $(STLS) $(STLS_EXTRA) 46 | 47 | .PHONY: gif stl 48 | 49 | .SECONDEXPANSION: # XXX: wtf make... 50 | palette-%.png: $$(call anim_pictures,%,$(STEPS)) 51 | $(FFMPEG) -i anim-$*-$(ANIM_PATTERN).png -vf $(DSCALE),palettegen -y $@ 52 | 53 | gif/%.gif: palette-%.png $$(call anim_pictures,%,$(STEPS)) 54 | $(FFMPEG) -framerate $(FPS) -i anim-$*-$(ANIM_PATTERN).png \ 55 | -i $< -lavfi "$(DSCALE)[x];[x][1:v]paletteuse" \ 56 | -y -frames:v $(STEPS) -loop 0 -final_delay $(GIF_FINAL_DELAY) $@ 57 | 58 | anim-%.png: NUM = $(shell echo $(call dashsplit,2,$*) | sed 's/^0*//') 59 | anim-%.png: VPD = $(call get_openscad_var,vpd,$<,140) 60 | anim-%.png: $$(call dashsplit,1,%).scad 61 | $(OPENSCAD) $< -D'$$t=$(NUM)/$(STEPS)' -o $@ 62 | 63 | %.stl: $$(call dashsplit,1,%).scad 64 | openscad $< -D'mode="$(call dashsplit,2,$*)"' -o $@ 65 | -------------------------------------------------------------------------------- /electronics/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2017 Clément Bœsch 2 | # 3 | # Permission to use, copy, modify, and distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | OPENSCAD_EXTRA_SETTINGS = --camera=0,0,0,55,0,90,$(VPD) 16 | include ../common.mk 17 | -------------------------------------------------------------------------------- /electronics/README.md: -------------------------------------------------------------------------------- 1 | | Category | Preview | 2 | | ----------------------- | ---------------------------- | 3 | | Buttons | ![Buttons](gif/button.gif) | 4 | | CPU | ![CPU](gif/cpu.gif) | 5 | | HDMI | ![HDMI](gif/hdmi.gif) | 6 | | Pin and Female Headers | ![headers](gif/header.gif) | 7 | | Jack | ![jack](gif/jack.gif) | 8 | | Miscleanous stuff | ![Misc](gif/misc.gif) | 9 | | Network | ![Network](gif/network.gif) | 10 | | Power | ![Power](gif/power.gif) | 11 | | SATA | ![SATA](gif/sata.gif) | 12 | | SD | ![SATA](gif/sd.gif) | 13 | | USB | ![USB](gif/usb.gif) | 14 | -------------------------------------------------------------------------------- /electronics/_internal.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <../globals.scad> 16 | 17 | $vpr = [50, 0, 90]; 18 | 19 | module components_demo(pad=30) { 20 | n = $children; 21 | cols = ceil(sqrt(n)); 22 | rows = ceil(n / cols); 23 | offx = pad * (rows - 1) / 2; 24 | offy = pad * (cols - 1) / 2; 25 | for (i = [0:n-1]) { 26 | x = floor(i / cols); 27 | y = i % cols; 28 | translate([x*pad - offx, y*pad - offy]) 29 | rotate(360 * $t) 30 | children(i); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /electronics/button.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <_internal.scad> 16 | 17 | $vpd = 50; 18 | 19 | module button(dim=[4, 3, 2], pusher_h=.5, pusher_type="square", clr=c_metal) { 20 | base_dim = [dim[0], dim[1], dim[2]-pusher_h]; 21 | pusher_dim = [base_dim[0]/2, base_dim[1]/2, pusher_h]; 22 | 23 | color(clr) 24 | translate([0, 0, -pusher_h/2]) 25 | cube(base_dim, center=true); 26 | color(c_black) 27 | translate([0, 0, base_dim[2]/2]) 28 | if (pusher_type == "circle") 29 | cylinder(d=min(base_dim[0], base_dim[1]) / 2, h=pusher_h, center=true); 30 | else 31 | cube(pusher_dim, center=true); 32 | } 33 | 34 | function button_info() = [ 35 | ["category", "button"], 36 | ["watch", "nowhere"], 37 | ]; 38 | 39 | function button_drill_info() = [ 40 | ["category", "button"], 41 | ["watch", "sky"], 42 | ]; 43 | 44 | components_demo(pad=10) { 45 | button(pusher_type="square"); 46 | button(pusher_type="circle"); 47 | } 48 | -------------------------------------------------------------------------------- /electronics/cpu.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <_internal.scad> 16 | 17 | $vpd = 180; 18 | 19 | module cpu(dim=[20, 20, 1.25], clr=c_black) { 20 | color(clr) 21 | cube(dim, center=true); 22 | } 23 | 24 | module cpurad(dim=[20, 20, 5], stick_dim=[3, 1]) { 25 | translate(dim * -.5) // XXX 26 | color(c_black_redish) { 27 | difference() { 28 | cube(dim); 29 | 30 | // horizontal 31 | hh = 3.5; 32 | nb_hcut = 6; 33 | hpad = (dim[1] - (nb_hcut + 1) * stick_dim[1]) / nb_hcut; 34 | translate([0, 0, dim[2]-hh]) 35 | linear_extrude(height=hh + _delta, convexity=4) 36 | for (y = [0:nb_hcut-1]) 37 | translate([-_delta/2, (y + 1) * stick_dim[1] + y * hpad]) 38 | square([dim[0]+_delta, hpad]); 39 | 40 | // vertical 41 | nb_vcut = 4; 42 | vpad = (dim[0] - (nb_vcut + 1) * stick_dim[0]) / nb_vcut; 43 | hv = 4.5; 44 | translate([0, 0, dim[2]-hv]) 45 | linear_extrude(height=hv + _delta, convexity=4) 46 | for (x = [0:nb_vcut-1]) 47 | translate([(x + 1) * stick_dim[0] + x * vpad, -_delta/2]) 48 | square([vpad, dim[1]+_delta]); 49 | } 50 | } 51 | } 52 | 53 | function cpu_info() = [ 54 | ["category", "cpu"], 55 | ["watch", "nowhere"], 56 | ]; 57 | function cpurad_info() = cpu_info(); 58 | 59 | components_demo(pad=40) { 60 | cpu(); 61 | cpurad(); 62 | } 63 | -------------------------------------------------------------------------------- /electronics/gif/button.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/electronics/gif/button.gif -------------------------------------------------------------------------------- /electronics/gif/cpu.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/electronics/gif/cpu.gif -------------------------------------------------------------------------------- /electronics/gif/hdmi.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/electronics/gif/hdmi.gif -------------------------------------------------------------------------------- /electronics/gif/header.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/electronics/gif/header.gif -------------------------------------------------------------------------------- /electronics/gif/jack.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/electronics/gif/jack.gif -------------------------------------------------------------------------------- /electronics/gif/misc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/electronics/gif/misc.gif -------------------------------------------------------------------------------- /electronics/gif/network.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/electronics/gif/network.gif -------------------------------------------------------------------------------- /electronics/gif/power.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/electronics/gif/power.gif -------------------------------------------------------------------------------- /electronics/gif/sata.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/electronics/gif/sata.gif -------------------------------------------------------------------------------- /electronics/gif/sd.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/electronics/gif/sd.gif -------------------------------------------------------------------------------- /electronics/gif/usb.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/electronics/gif/usb.gif -------------------------------------------------------------------------------- /electronics/hdmi.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <_internal.scad> 16 | 17 | $vpd = 150; 18 | 19 | module hdmi(dim=[12, 15, 6]) { 20 | l = dim[0]; 21 | w = dim[1]; 22 | h = dim[2]; 23 | lowest = h - 5.25; 24 | hdmi_polygon_pos = [[0, h], [w, h], [w, h-3.25], 25 | [w-2, lowest], [2, lowest], [0, h-3.25]]; 26 | 27 | rotate([0, 0, 180]) // XXX 28 | translate(dim * -.5) { // XXX 29 | color(c_metal) { 30 | translate([7, 0, 0]) 31 | cube([l-7, w, h]); 32 | rotate([90, 0, 90]) { 33 | linear_extrude(height=7) { 34 | difference() { 35 | polygon(hdmi_polygon_pos); 36 | offset(r=-.5) 37 | polygon(hdmi_polygon_pos); 38 | } 39 | } 40 | } 41 | } 42 | color(c_black) 43 | translate([2, 2, 3]) 44 | cube([7, w-2*2, 1]); 45 | } 46 | } 47 | 48 | module microhdmi(dim=[7.5, 6.5, 3]) { 49 | // TODO 50 | l = dim[0]; 51 | w = dim[1]; 52 | h = dim[2]; 53 | t = .25; 54 | rotate([0, 0, 180]) // XXX 55 | color(c_metal) { 56 | difference() { 57 | cube(dim, center=true); 58 | translate([-t/2,0,0]) 59 | cube([l,w-t,h-t], center=true); 60 | } 61 | } 62 | 63 | 64 | // cube(dim, center=true); 65 | } 66 | 67 | function hdmi_info() = [ 68 | ["category", "hdmi"], 69 | ["watch", "horizon"], 70 | ]; 71 | function microhdmi_info() = hdmi_info(); 72 | 73 | components_demo() { 74 | hdmi(); 75 | microhdmi(); 76 | } 77 | -------------------------------------------------------------------------------- /electronics/header.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <_internal.scad> 16 | 17 | $vpd = 200; 18 | 19 | module _pins_pos(dim, n, m, pins_dist) { // centered position for the pins 20 | l = dim[0]; 21 | w = dim[1]; 22 | pl = (n - 1) * pins_dist; 23 | pw = (m - 1) * pins_dist; 24 | if (l <= pl) echo("WARN: female header length looks too small"); 25 | if (w <= pw) echo("WARN: female header width looks too small"); 26 | translate([(l-pl)/2, (w-pw)/2]) 27 | for (y = [0:m-1]) 28 | for (x = [0:n-1]) 29 | translate([x * pins_dist, y * pins_dist]) 30 | children(); 31 | } 32 | 33 | module _female_header(dim, n, m, pins_sz, pins_dist) { 34 | h = dim[2]; 35 | translate(dim * -.5) { // XXX 36 | color(c_black) { 37 | difference() { 38 | cube(dim); 39 | translate([0, 0, _delta]) 40 | linear_extrude(height=h-.25) 41 | _pins_pos(dim, n, m, pins_dist) 42 | square(pins_sz, center=true); 43 | translate([0, 0, h-.25]) 44 | _pins_pos(dim, n, m, pins_dist) 45 | rotate(45) 46 | cylinder(d1=pins_sz*sqrt(2), d2=1.25+pins_sz, h=.25+_delta, $fn=4); 47 | } 48 | } 49 | } 50 | } 51 | 52 | module _pins_slot(n, u) { 53 | x = u/4; 54 | z = u/2; 55 | h = u*n; 56 | slot_polygons = [ 57 | [-z/2, h/2], [ z/2, h/2], [ u/2, h/2-x], [ u/2,-h/2+x], 58 | [ z/2,-h/2], [-z/2,-h/2], [-u/2,-h/2+x], [-u/2, h/2-x], 59 | ]; 60 | polygon(slot_polygons); 61 | } 62 | 63 | module _pin_header(dim, n, m, pins_sz, pins_dist) { 64 | l = dim[0]; 65 | w = dim[1]; 66 | h = dim[2]; 67 | translate(dim * -.5) { // XXX 68 | color(c_metal) 69 | linear_extrude(height=h) 70 | _pins_pos(dim, n, m, pins_dist) 71 | square(pins_sz, center=true); 72 | pl = (n - 1) * pins_dist; 73 | color(c_black) 74 | linear_extrude(height=h/4) 75 | translate([(l-pl)/2, w/2]) 76 | for (x = [0:n-1]) 77 | translate([x * pins_dist, 0]) 78 | _pins_slot(m, pins_dist); 79 | } 80 | } 81 | 82 | module female_header_pitch200(dim, n, m) { 83 | _female_header(dim, n, m, pins_sz=.50, pins_dist=2); 84 | } 85 | 86 | module female_header_pitch254(dim, n, m) { 87 | _female_header(dim, n, m, pins_sz=.64, pins_dist=2.54); 88 | } 89 | 90 | module pin_header_pitch200(dim, n, m) { 91 | _pin_header(dim, n, m, pins_sz=.50, pins_dist=2); 92 | } 93 | 94 | module pin_header_pitch254(dim, n, m) { 95 | _pin_header(dim, n, m, pins_sz=.64, pins_dist=2.54); 96 | } 97 | 98 | function header_info() = [ 99 | ["category", "header"], 100 | ["watch", "sky"], 101 | ]; 102 | function female_header_info() = header_info(); 103 | function pin_header_info() = header_info(); 104 | function female_header_pitch200_info() = header_info(); 105 | function female_header_pitch254_info() = header_info(); 106 | function pin_header_pitch200_info() = header_info(); 107 | function pin_header_pitch254_info() = header_info(); 108 | 109 | components_demo(pad=50) { 110 | female_header_pitch254(dim=2.54*[10,2,3], n=10, m=2); 111 | pin_header_pitch254(dim=2.54*[10,2,3], n=10, m=2); 112 | female_header_pitch200(dim=2.00*[10,2,2], n=10, m=2); 113 | pin_header_pitch200(dim=2.00*[10,2,2], n=10, m=2); 114 | } 115 | -------------------------------------------------------------------------------- /electronics/jack.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <_internal.scad> 16 | 17 | $vpd = 100; 18 | 19 | module jack(dim=[14.5, 7, 6]) { 20 | l = dim[0]; 21 | w = dim[1]; 22 | h = dim[2]; 23 | 24 | lcyl = 2; 25 | rotate([0, 0, 180]) 26 | translate(dim * -.5) { // XXX 27 | color(c_black) { 28 | difference() { 29 | union() { 30 | translate([lcyl, 0, 0]) 31 | cube([l-lcyl, w, h]); 32 | translate([0, w/2, h/2]) 33 | rotate([90, 0, 90]) 34 | cylinder(d=h, h=lcyl); 35 | } 36 | translate([-_delta/2, w/2, h/2]) 37 | rotate([90, 0, 90]) 38 | cylinder(d=3.5, h=l+_delta); 39 | } 40 | } 41 | } 42 | } 43 | 44 | function jack_info() = [ 45 | ["category", "jack"], 46 | ["watch", "horizon"], 47 | ]; 48 | 49 | components_demo() { 50 | jack(); 51 | } 52 | -------------------------------------------------------------------------------- /electronics/misc.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <_internal.scad> 16 | 17 | $vpd = 200; 18 | 19 | module antenna(dim=[7.5, 16, 1]) { // TODO 20 | color(c_black) 21 | cube(dim, center=true); 22 | } 23 | 24 | module capacitor(dim=[6, 6, 5]) { 25 | l = dim[0]; 26 | w = dim[1]; 27 | h = dim[2]; 28 | translate(dim * -.5) { 29 | color(c_black) 30 | cube([l, w, 1.5]); 31 | color(c_metal) 32 | translate([l/2, w/2, 1.5]) 33 | cylinder(d=l, h=h-1.5); 34 | } 35 | } 36 | 37 | module chip(dim=[10, 5, 2]) { // TODO 38 | color(c_black) 39 | cube(dim, center=true); 40 | } 41 | 42 | module extio_hikey(dim=[6, 30, 4]) { 43 | l = dim[1]; 44 | w = dim[0]; 45 | h = dim[2]; 46 | rotate([0, 0, 90]) translate([dim[1], dim[0], dim[2]] * -.5) // XXX 47 | color([.9,.85,.75]) { 48 | linear_extrude(height=1) { 49 | square([2.5, w]); 50 | translate([l-2.5, 0]) 51 | square([2.5, w]); 52 | translate([0, (w-4)/2]) 53 | square([l, 4]); 54 | } 55 | translate([0, 0, 1]) { 56 | linear_extrude(height=h-1) { 57 | difference() { 58 | translate([1, (w-4)/2]) 59 | square([l-2, 4]); 60 | translate([1.5, (w-4/3)/2]) 61 | square([l-3, 4/3]); 62 | } 63 | } 64 | } 65 | } 66 | } 67 | 68 | module ir(dim=[3.5, 5, 7]) { 69 | l = dim[1]; 70 | w = dim[0]; 71 | h = dim[2]; 72 | rotate([0, 0, 90]) translate([dim[1], dim[0], dim[2]] * -.5) { // XXX 73 | color(c_black) { 74 | translate([0, 0, 1]) 75 | cube([l, w-1, h-1]); 76 | translate([l/2, w-1.5, 1]) 77 | cylinder(r=1.5, h=h-3); 78 | translate([l/2, w-1.5, h-2]) 79 | sphere(r=1.5); 80 | } 81 | color(c_metal) 82 | linear_extrude(height=h/2) 83 | for (i = [0:2]) 84 | translate([i*(l-.5-_delta)/2 + _delta/2, (w-1)/2]) 85 | square(.5); 86 | } 87 | } 88 | 89 | module led(dim=[2, 1, 0.5], clr=c_yellow) { // TODO 90 | color(clr) 91 | cube(dim, center=true); 92 | } 93 | 94 | module rt_bbb(dim=[3.5, 8, 10.5]) { 95 | rt1_l = dim[0]; 96 | rt1_w = dim[1]; 97 | rt1_h = dim[2]; 98 | 99 | head_l = dim[0]; 100 | head_w = dim[1]; 101 | head_h = dim[2] / 3; 102 | 103 | translate(dim * -.5) { // XXX 104 | color(c_metal) 105 | for (y = [1, rt1_w-1]) 106 | translate([rt1_l/2, y]) 107 | cylinder(d=1, h=rt1_h-head_h); 108 | 109 | color(c_gold) 110 | translate([0, 0, rt1_h-head_h]) 111 | cube([head_l, head_w, head_h]); 112 | } 113 | } 114 | 115 | module serialcon_rpi(dim=[2.5, 22, 5.5]) { 116 | l = dim[0]; 117 | w = dim[1]; 118 | h = dim[2]; 119 | translate(dim * -.5) { // XXX 120 | color([.9,.85,.75]) { 121 | translate([0, 1]) 122 | cube([.5+_delta, w-2, h-1.5]); 123 | translate([l-.5, 1]) 124 | cube([.5, w-2, h-1.5]); 125 | translate([_delta, 3, h-1.5]) 126 | cube([0.5, w-3*2, 1.5-_delta]); 127 | } 128 | color(c_black) { 129 | difference() { 130 | union() { 131 | translate([.5, 0.5, 0]) 132 | cube([l-1, w-1, h-1.5+_delta]); 133 | translate([0, 0, h-1.5]) 134 | cube([l, w, 1.5]); 135 | } 136 | translate([-_delta, 3, _delta]) 137 | cube([l-1+_delta, w-3*2, h]); 138 | } 139 | } 140 | } 141 | } 142 | 143 | function antenna_info() = [ 144 | ["category", "misc"], 145 | ["watch", "nowhere"], 146 | ]; 147 | 148 | function capacitor_info() = [ 149 | ["category", "misc"], 150 | ["watch", "nowhere"], 151 | ]; 152 | 153 | function chip_info() = [ 154 | ["category", "misc"], 155 | ["watch", "nowhere"], 156 | ]; 157 | 158 | function extio_hikey_info() = [ 159 | ["category", "misc"], 160 | ["watch", "sky"], 161 | ]; 162 | 163 | function ir_info() = [ 164 | ["category", "misc"], 165 | ["watch", "nowhere"], 166 | ]; 167 | 168 | function led_info() = [ 169 | ["category", "misc"], 170 | ["watch", "sky"], 171 | ]; 172 | 173 | function rt_bbb_info() = [ 174 | ["category", "misc"], 175 | ["watch", "nowhere"], 176 | ]; 177 | 178 | function serialcon_rpi_info() = [ 179 | ["category", "misc"], 180 | ["watch", "sky"], 181 | ]; 182 | 183 | components_demo(pad=40) { 184 | antenna(); 185 | capacitor(); 186 | chip(); 187 | extio_hikey(); 188 | ir(); 189 | led(); 190 | serialcon_rpi(); 191 | rt_bbb(); 192 | } 193 | -------------------------------------------------------------------------------- /electronics/network.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <_internal.scad> 16 | 17 | $vpd = 180; 18 | 19 | module antenna(dim=[5, 5, 60]) { 20 | color(c_black) { 21 | h_base = dim[2]/3; 22 | translate([0, 0, (h_base-dim[2])/2+2]) 23 | cylinder(d=dim[0], h=dim[2]/3, center=true); 24 | difference() { 25 | cylinder(d=3, h=dim[2], center=true); 26 | translate([0, 0, _delta]) 27 | cylinder(d=2.5, h=dim[2], center=true); 28 | } 29 | } 30 | } 31 | 32 | module ethernet(dim=[21, 16, 13.5], swap_led=false) { 33 | l = dim[0]; 34 | w = dim[1]; 35 | h = dim[2]; 36 | 37 | c_green = [.3, .9, .3]; 38 | c_yellow = [.9, .9, .3]; 39 | c1 = swap_led ? c_yellow : c_green; 40 | c2 = swap_led ? c_green : c_yellow; 41 | 42 | rotate([0, 0, 180]) translate(dim * -.5) { // XXX 43 | difference() { 44 | color(c_metal) 45 | cube(dim); 46 | translate([-_delta, 2, 0.5]) 47 | color(c_black) 48 | cube([l-5, w-4, h-3]); 49 | } 50 | 51 | color(c_black) 52 | for (y = [2, w-4]) 53 | translate([0, y, 0.5]) 54 | cube([l-1, 2, 3]); 55 | 56 | color(c1) 57 | translate([-_delta, w-4+_delta, .5]) 58 | cube([1, 2.5, 2]); 59 | 60 | color(c2) 61 | translate([-_delta, 1.5-_delta, .5]) 62 | cube([1, 2.5, 2]); 63 | } 64 | } 65 | 66 | function ethernet_info() = [ 67 | ["category", "network"], 68 | ["watch", "horizon"], 69 | ]; 70 | 71 | function antenna_info() = [ 72 | ["category", "network"], 73 | ["watch", "nowhere"], 74 | ]; 75 | 76 | components_demo() { 77 | ethernet(); 78 | antenna(); 79 | } 80 | -------------------------------------------------------------------------------- /electronics/power.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <_internal.scad> 16 | 17 | $vpd = 150; 18 | 19 | module power_bbb(dim=[14, 9, 11]) { 20 | l = dim[0]; 21 | w = dim[1]; 22 | h = dim[2]; 23 | 24 | l1 = 3.5; 25 | l0 = l - l1; 26 | h0 = 6.5; 27 | 28 | rotate([0, 0, 180]) translate(dim * -.5) { // XXX 29 | color(c_black) { 30 | difference() { 31 | union() { 32 | translate([l1, 0]) { 33 | cube([l0, w, h0]); 34 | translate([0, w/2, h0]) 35 | rotate([0, 90]) 36 | cylinder(d=w-1, h=l0); 37 | } 38 | cube([l1, w, h]); 39 | } 40 | translate([-_delta, w/2, h0]) 41 | rotate([0, 90]) 42 | cylinder(d=6.5, h=l0); 43 | } 44 | } 45 | color(c_metal) 46 | translate([0, w/2, h0]) 47 | rotate([0, 90]) 48 | cylinder(d=2, h=l0); 49 | } 50 | } 51 | 52 | module power_cubie(dim=[12, 7.5, 6]) { 53 | l = dim[0]; 54 | w = dim[1]; 55 | h = dim[2]; 56 | depth = 8; // actual depth 57 | power_hole_d = 4.5; 58 | rotate([0, 0, 180]) translate(dim * -.5) { // XXX 59 | color(c_black) { 60 | difference() { 61 | cube(dim); 62 | translate([-_delta, 1+power_hole_d/2, h/2]) // yes it's misaligned 63 | rotate([0, 90, 0]) 64 | cylinder(d=power_hole_d, h=depth); 65 | } 66 | } 67 | color(c_metal) 68 | translate([0, 1+power_hole_d/2, h/2]) 69 | rotate([0, 90, 0]) 70 | cylinder(d=1.5, h=depth); 71 | } 72 | } 73 | 74 | module power_hikey(dim=[13, 9, 6]) { 75 | l = dim[1]; 76 | w = dim[0]; 77 | h = dim[2]; 78 | 79 | rotate([0, 0, 180]) { // XXX 80 | translate([w/2, -l/2, -h/2]) // XXX 81 | rotate([0, 0, 90]) { // XXX 82 | color(c_black) { 83 | difference() { 84 | union() { 85 | translate([0, w-1]) cube([l, 1, h]); 86 | translate([0, w-3]) cube([l, 1, h]); 87 | translate([1.5/2, w-9]) cube([l-1.5, 8, h]); 88 | translate([3/2, 0]) cube([l-3, w-9, h]); 89 | } 90 | translate([l/2, w+_delta, h/2]) 91 | rotate([90, 0, 0]) 92 | cylinder(d=5, h=9); 93 | } 94 | } 95 | color(c_metal) 96 | translate([l/2, w-.5, h/2]) 97 | rotate([90, 0, 0]) 98 | cylinder(d=2, h=9); 99 | } 100 | } 101 | } 102 | 103 | function power_bbb_info() = [ 104 | ["category", "power"], 105 | ["watch", "horizon"], 106 | ]; 107 | 108 | function power_cubie_info() = [ 109 | ["category", "power"], 110 | ["watch", "horizon"], 111 | ]; 112 | 113 | function power_hikey_info() = [ 114 | ["category", "power"], 115 | ["watch", "horizon"], 116 | ]; 117 | 118 | components_demo() { 119 | power_bbb(); 120 | power_cubie(); 121 | power_hikey(); 122 | } 123 | -------------------------------------------------------------------------------- /electronics/sata.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <_internal.scad> 16 | 17 | $vpd = 150; 18 | 19 | module sata_data(dim=[17, 6.5, 9]) { 20 | rotate([0,0,180]) translate(dim * -.5) 21 | color(c_black) { 22 | difference() { 23 | cube(dim); 24 | translate([1, 1, 2+_delta]) 25 | cube([dim[0]-2, dim[1]-2, dim[2]-2]); 26 | } 27 | translate([3, (dim[1]-1)/2]) 28 | cube([dim[0]-3*2, 1, dim[2]]); 29 | translate([dim[0]-4, (dim[1]-1)/2+1]) 30 | cube([1, 1, dim[2]]); 31 | 32 | } 33 | } 34 | 35 | module sata_5v(dim=[7.5, 6, 7.5]) { 36 | translate(dim * -.5) { // XXX 37 | color("white") { 38 | difference() { 39 | cube(dim); 40 | translate([1, 1, dim[2] - 6 + _delta]) 41 | cube([dim[0]-2, dim[1]-2, 6]); 42 | translate([-_delta/2, 1, dim[2]-3]) 43 | cube([dim[0]+_delta, 1, 3+_delta]); 44 | translate([2, -_delta/2, dim[2]-4]) 45 | cube([dim[0]-4, 1+_delta, 4+_delta]); 46 | } 47 | } 48 | color(c_metal) 49 | linear_extrude(height=dim[2]-1) 50 | for (i = [1:2]) 51 | translate([i*dim[0]/3, dim[1]/3]) 52 | square(.5); 53 | } 54 | } 55 | 56 | function sata_data_info() = [ 57 | ["category", "sata"], 58 | ["watch", "sky"], 59 | ]; 60 | 61 | function sata_5v_info() = [ 62 | ["category", "sata"], 63 | ["watch", "sky"], 64 | ]; 65 | 66 | components_demo() { 67 | sata_data(); 68 | sata_5v(); 69 | } 70 | -------------------------------------------------------------------------------- /electronics/sd.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <_internal.scad> 16 | 17 | $vpd = 100; 18 | 19 | module microsdslot(dim=[13, 12, 1.25]) { 20 | t = .25; 21 | rotate([0, 0, 180]) // XXX 22 | color(c_metal) { 23 | difference() { 24 | cube(dim, center=true); 25 | translate([-t, 0, 0]) 26 | cube([dim[0], dim[1]-2*t, dim[2]-2*t], center=true); 27 | } 28 | } 29 | } 30 | 31 | module microsdcard(dim=[15, 11, 1]) { 32 | l = dim[0]; 33 | w = dim[1]; 34 | h = dim[2]; 35 | tip_dim = [2, w, .25]; 36 | tl = tip_dim[0]; 37 | th = tip_dim[2]; 38 | rotate([0, 0, 180]) // XXX 39 | color(c_black) { 40 | translate([0, 0, -tip_dim[2]/2]) 41 | cube([l, w, h-.25], center=true); 42 | translate([(tl-l)/2, 0, (h-th)/2]) 43 | cube(tip_dim, center=true); 44 | } 45 | } 46 | 47 | function microsdslot_info() = [ 48 | ["category", "sd"], 49 | ["watch", "nowhere"], 50 | ]; 51 | function microsdcard_info() = [ 52 | ["category", "sd"], 53 | ["watch", "horizon"], 54 | ]; 55 | 56 | components_demo() { 57 | microsdslot(); 58 | microsdcard(); 59 | } 60 | -------------------------------------------------------------------------------- /electronics/usb.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include <_internal.scad> 16 | 17 | $vpd = 150; 18 | 19 | module usb(dim=[18, 14.5, 8], n=1, clr="white", has_folding=true) { 20 | pin_l = has_folding ? .6 : 0; 21 | 22 | l = dim[0] - pin_l; 23 | w = dim[1] - pin_l*2; 24 | h = dim[2] - pin_l*2; 25 | 26 | t = 0.25; 27 | p = 0.75; 28 | z = pin_l * sqrt(2); 29 | 30 | rotate([0, 0, 180]) translate(dim * -.5) { // XXX 31 | translate([pin_l, pin_l, pin_l]) { 32 | color(c_metal) { 33 | difference() { 34 | cube([l, w, h]); 35 | translate([-_delta, t, t]) 36 | cube([l-t+_delta, w-t*2, h-t*2]); 37 | } 38 | if (has_folding) { 39 | translate([0, p, h-t]) rotate(a= 45, v=[0,1,0]) translate([-z, 0, 0]) cube([z, w - 2*p, t]); 40 | translate([0, p, t]) rotate(a=-45, v=[0,1,0]) translate([-z, 0, -t]) cube([z, w - 2*p, t]); 41 | translate([0, t, p]) rotate(a= 45, v=[0,0,1]) translate([-z, -t, 0]) cube([z, t, h - 2*p]); 42 | translate([0, w-t, p]) rotate(a=-45, v=[0,0,1]) translate([-z, 0, 0]) cube([z, t, h - 2*p]); 43 | } 44 | } 45 | color(clr) 46 | for (y = [0:n-1]) 47 | translate([0, 1, h-(3.5+9*y)]) // XXX: random shit 48 | cube([l-t, w-2, 2]); 49 | } 50 | color(c_metal) 51 | translate([pin_l+l-l/3, pin_l]) 52 | cube([l/3, w, pin_l]); 53 | } 54 | } 55 | 56 | module usbx2(dim=[18, 14.5, 16], clr=c_black, has_folding=true) { 57 | usb(dim, n=2, clr=clr, has_folding=has_folding); 58 | 59 | // separator (XXX: random shit) 60 | pin_l = has_folding ? .6 : 0; 61 | t = 0.25; 62 | l = dim[0] - pin_l - t; 63 | w = dim[1] - pin_l*2 - t*2; 64 | rotate([0, 0, 180]) translate(dim * -.5) // XXX 65 | color(c_metal) 66 | translate([0, (dim[1]-w)/2, (dim[2]-3.5)/2]) 67 | cube([l, w, 3.5]); 68 | } 69 | 70 | module microusb(dim=[6, 10, 6]) { 71 | jack_dim = [6, 8, 3]; 72 | l = jack_dim[0]; 73 | w = jack_dim[1]; 74 | h = jack_dim[2]; 75 | microusb_polygon_pos = [[1, h], [w-1, h], [w, h-1], 76 | [w-2, 0], [2, 0], [0, h-1]]; 77 | p_w = dim[1]; 78 | p_h = dim[2]; 79 | rotate([0, 0, 180]) translate(jack_dim * -.5) { // XXX 80 | color(c_metal) { 81 | translate([l-1, (w-p_w)/2, (h-p_h)/2]) 82 | cube([1, p_w, p_h]); 83 | rotate([90, 0, 90]) { 84 | linear_extrude(height=l-1) { 85 | difference() { 86 | polygon(microusb_polygon_pos); 87 | offset(r=-.5) 88 | polygon(microusb_polygon_pos); 89 | } 90 | } 91 | } 92 | } 93 | color(c_black) 94 | translate([1.5, (w-4)/2, h-1.5]) 95 | cube([l-2.5, 4, .5]); 96 | } 97 | } 98 | 99 | module miniusb(dim=[7.1, 8, 4]) { 100 | // TODO: merge with microusb (XXX: HDMI?) 101 | l = dim[0]; 102 | w = dim[1]; 103 | h = dim[2]; 104 | lowest = h - 4; 105 | depth = 7; 106 | otg_polygon_pos = [[0, h], [w, h], [w, h-1.5], [w-.5, h-2], 107 | [w-.5, lowest], [.5, lowest], [.5, h-2], 108 | [0, h-1.5]]; 109 | translate(dim * -.5) { // XXX 110 | color(c_metal) { 111 | cube([l-depth, w, h]); 112 | translate([l-depth, 0, 0]) { 113 | rotate([90, 0, 90]) { 114 | linear_extrude(height=depth) { 115 | difference() { 116 | polygon(otg_polygon_pos); 117 | offset(r=-.5) 118 | polygon(otg_polygon_pos); 119 | } 120 | } 121 | } 122 | } 123 | } 124 | color(c_black) 125 | translate([l-depth, 1.5, 2]) 126 | cube([6, w-3, 1]); 127 | } 128 | } 129 | 130 | function usb_info() = [ 131 | ["category", "usb"], 132 | ["watch", "horizon"], 133 | ]; 134 | function usbx2_info() = usb_info(); 135 | function microusb_info() = usb_info(); 136 | function miniusb_info() = usb_info(); 137 | 138 | components_demo(pad=40) { 139 | usb(); 140 | usbx2(); 141 | microusb(); 142 | miniusb(); 143 | } 144 | -------------------------------------------------------------------------------- /globals.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | $fn = 30; 16 | 17 | _delta = 0.005; 18 | 19 | c_black = [.17,.17,.17]; 20 | c_black_redish = [.35,.30,.30]; 21 | c_gold = [.75,.55,.00]; 22 | c_gray = [.40,.40,.40]; 23 | c_darkgray = [.25,.25,.25]; 24 | c_green_pcb = [.00,.50,.25]; 25 | c_metal = [.70,.70,.70]; 26 | c_yellow = [.70,.70,.30]; 27 | c_darkblue = [.20,.30,.40]; 28 | -------------------------------------------------------------------------------- /pics/bbb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/pics/bbb.jpg -------------------------------------------------------------------------------- /pics/cubieboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/pics/cubieboard.jpg -------------------------------------------------------------------------------- /pics/hikey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/pics/hikey.jpg -------------------------------------------------------------------------------- /pics/nanopi_neo2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/pics/nanopi_neo2.jpg -------------------------------------------------------------------------------- /pics/orangepi_zero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/pics/orangepi_zero.jpg -------------------------------------------------------------------------------- /pics/rpi3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/pics/rpi3.jpg -------------------------------------------------------------------------------- /pics/small/bbb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/pics/small/bbb.jpg -------------------------------------------------------------------------------- /pics/small/cubieboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/pics/small/cubieboard.jpg -------------------------------------------------------------------------------- /pics/small/hikey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/pics/small/hikey.jpg -------------------------------------------------------------------------------- /pics/small/nanopi_neo2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/pics/small/nanopi_neo2.jpg -------------------------------------------------------------------------------- /pics/small/orangepi_zero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/pics/small/orangepi_zero.jpg -------------------------------------------------------------------------------- /pics/small/rpi3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ubitux/shimonbox/c644a592915707d5ffe802d9e1c7bbe409d99753/pics/small/rpi3.jpg -------------------------------------------------------------------------------- /utils.scad: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Clément Bœsch 2 | // 3 | // Permission to use, copy, modify, and distribute this software for any 4 | // purpose with or without fee is hereby granted, provided that the above 5 | // copyright notice and this permission notice appear in all copies. 6 | // 7 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | include 16 | 17 | function unknown_info() = [ 18 | ["category", "unknown"], 19 | ["watch", "nowhere"], 20 | ]; 21 | 22 | function unknown_drill_info() = [ 23 | ["category", "unknown"], 24 | ["watch", "horizon"], 25 | ]; 26 | 27 | function in2mm(v) = 2.54 * v / 100; 28 | 29 | function pmul(v,m) = [for (i=[0:len(v)-1]) v[i] * m[i]]; 30 | 31 | function map_get(data, key) = 32 | let(s = search([key], data)[0]) 33 | s == [] ? s : data[s][1]; 34 | 35 | function default_top_vents(board_dim, s=.3) = [ 36 | ["dim", board_dim * s], 37 | ["pos", [0, 0]], 38 | ]; 39 | 40 | function default_bottom_vents(board_dim, s=.7) = default_top_vents(board_dim, s); 41 | 42 | function default_vents(board_dim, bottom_s=.7, top_s=.3) = [ 43 | ["top", default_top_vents(board_dim, top_s)], 44 | ["bottom", default_bottom_vents(board_dim, bottom_s)], 45 | ]; 46 | 47 | module set_component(board_dim, comp_info, debug=false) { 48 | dim = comp_info[1]; 49 | corner_comp = comp_info[2]; 50 | rot = comp_info[3]; 51 | corner_board = comp_info[4]; 52 | position = comp_info[5]; 53 | 54 | corner_pos = pmul(corner_comp, dim) * -.5; 55 | board_corner_pos = pmul(corner_board, board_dim) * .5; 56 | tr = position + board_corner_pos; 57 | 58 | if (debug) { 59 | translate(tr) { 60 | color("blue") cylinder(h=20, d=.25, center=true); 61 | color("green") rotate([90, 0, 0]) cylinder(h=20, d=.25, center=true); 62 | color("red") rotate([0, 90, 0]) cylinder(h=20, d=.25, center=true); 63 | color("pink") sphere(.5); 64 | } 65 | } 66 | 67 | translate(tr) 68 | rotate(rot * 90) 69 | translate(corner_pos) 70 | children(0); 71 | } 72 | 73 | module set_components(board_dim, comp_info_list, debug=false) { 74 | for (i = [0:len(comp_info_list)-1]) 75 | set_component(board_dim, comp_info_list[i], debug) 76 | children(i); 77 | } 78 | 79 | module bounding_box(board_dim, comp_info_list, padding, extruded_dim=50) { 80 | for (comp_info = comp_info_list) { 81 | info = comp_info[0]; 82 | dim = comp_info[1]; 83 | watch = map_get(info, "watch"); 84 | category = map_get(info, "category"); 85 | 86 | /* extrude mask and its inverse */ 87 | ex_mask = [watch == "horizon" ? 1 : 0, 0, watch == "sky" ? 1 : 0]; 88 | ex_mask_inv = [for (i=[0:len(ex_mask)-1]) 1-ex_mask[i]]; 89 | 90 | set_component(board_dim, comp_info) { 91 | box_dim = pmul(ex_mask_inv, dim) + ex_mask*extruded_dim; 92 | all_tr = [extruded_dim-dim[0], 0, extruded_dim-dim[2]] * .5; 93 | box_tr = pmul(all_tr, ex_mask); 94 | translate(box_tr) { 95 | minkowski() { 96 | cube(box_dim, center=true); 97 | sphere(d=2*padding, center=true); 98 | } 99 | } 100 | } 101 | } 102 | } 103 | 104 | module demo_board(board_dim) { 105 | rotate([0, 0, $t*360]) 106 | children(); 107 | } 108 | 109 | module plate_2d(l, w, corner_radius=0) { 110 | if (!corner_radius) { 111 | square([l, w], center=true); 112 | } else { 113 | translate([corner_radius - l/2, corner_radius - w/2]) { 114 | minkowski() { 115 | square([l - corner_radius*2, w - corner_radius*2]); 116 | circle(r=corner_radius); 117 | } 118 | } 119 | } 120 | } 121 | 122 | module _hole_positions(holes_pos) { 123 | for (pos = holes_pos) 124 | translate(pos) 125 | children(); 126 | } 127 | 128 | module extrude_plate(height, holes_pos=[], hole_d=1, ring_off=0, clr=c_darkgray, clr_ring=c_gold) { 129 | translate([0, 0, -height/2]) { 130 | color(clr) { 131 | linear_extrude(height) { 132 | difference() { 133 | children(0); 134 | _hole_positions(holes_pos) 135 | circle(d=hole_d + ring_off); 136 | } 137 | } 138 | } 139 | if (ring_off) { 140 | color(clr_ring) { 141 | linear_extrude(height) { 142 | _hole_positions(holes_pos) { 143 | difference() { 144 | circle(d=hole_d + ring_off); 145 | circle(d=hole_d); 146 | } 147 | } 148 | } 149 | } 150 | } 151 | } 152 | } 153 | 154 | module stack_animate(time, pad=40, axis=[0,0,1]) { 155 | function slope_a(x1, y1, x2, y2) = (y1 - y2) / (x1 - x2); 156 | function slope_b(x1, y1, x2, y2) = (x1*y2 - x2*y1) / (x1 - x2); 157 | function clip_time(t, mint, maxt) = min(max(t, mint), maxt); 158 | 159 | for (i = [0:$children-1]) { 160 | start_pos = (i + 1) * pad; 161 | end_pos = 0; 162 | start_time = i / $children; 163 | end_time = (i + 1) / $children; 164 | a = slope_a(start_time, start_pos, end_time, end_pos); 165 | b = slope_b(start_time, start_pos, end_time, end_pos); 166 | t = clip_time(time, start_time, end_time); 167 | translate(axis * (a*t + b)) 168 | children(i); 169 | } 170 | } 171 | 172 | module filter(id) { 173 | children(id); 174 | } 175 | --------------------------------------------------------------------------------