arcade-panel: more hinge stuff, misc fixes
[clinton/3d-models.git] / ble arcade controller / arcade-box.scad
1 // arcade controller thing
2 // Copyright (c) 2017 Clinton Ebadi <clinton@unknownlamer.org>
3 // GPLv3 or (at your option) any later version
4 // .. insert license text here ...
5
6 // todo:
7 // - hinge
8 // - screw holes + captive nut to mount
9 // - internal mount for mcu and battery
10 // - hole for usb panel mount
11 // - bevel lid
12
13 // maybe/wishlist:
14 // - wire routing clips on panel?
15 // - buttons on side for pinball?
16 // - vent under mcu/battery?
17 // - slant panel toward player?
18
19 // bugs:
20 // - hinge is not aligned -- either male arm length or connector placement is wrong
21
22 use <obiscad/bcube.scad>
23 use <obiscad/attach.scad>
24 use <joints.scad>
25
26 // PREVIEW
27 preview();
28
29 module preview () {
30 rotate ([-10, 0, 0]) translate ([0, 0, box_h+20]) panel ();
31 case ();
32 for (i = [2 ,4]) translate ([panel_w+hinge_joint_width*i, 0, 0]) hinge_male ();
33
34 }
35
36 // CONFIGURATION
37
38 panel_w = 250;
39 panel_h = 130;
40
41 box_h = 80; // fixme: box_d.
42 box_wall = 2;
43 base_h = 5; //fixme: thickness?
44
45 $button_d = 30; // I think this should be special
46
47 // fixme: names (js -> joystick)
48 js_width = 85;
49 js_height = 40;
50
51 // fixme: these are a bit confused
52 hinge_joint_width = 4;
53 hinge_joint_thickness = 5;
54 hinge_base_height = 10;
55 hinge_joint_height = 10;
56 hinge_arm_length = 50;
57
58
59 // gunk that should be elsewhere...
60 // bcube parameters, clean up
61 cr = box_wall*2;
62 cres = 0;
63
64 // PANEL COMPONENTS
65
66 module button (bezel = $button_d+4) {
67 circle (d=$button_d);
68 %circle(d=bezel);
69 }
70
71 module joystick () {
72 bolt_d = 8;
73 center_hole_d = 24;
74
75 for (x = [-js_width/2, js_width/2], y = [-js_height/2, js_height/2]) {
76 translate ([x, y, 0]) circle (d=bolt_d); // need slot instead
77 }
78 circle (d=center_hole_d);
79 %square ([js_width, js_height], center=true); // not right...
80 }
81
82
83 // CASE
84
85 module case_base (h=base_h) {
86 bcube([panel_w, panel_h, h], cr, cres);
87 }
88
89 module case_walls () {
90 difference () {
91 union () {
92 difference() {
93 bcube([panel_w, panel_h, box_h-base_h], cr, cres);
94 bcube([panel_w-box_wall*2, panel_h-box_wall*2, box_h+1], cr, cres);
95 }
96 attach (case_connector_wall (x=10), hinge_connector_back ()) hinge_female_base ();
97 }
98 attach (case_connector_wall (x=10), hinge_connector_back ()) hinge_female_cut ();
99 }
100 %connector (case_connector_wall (x=10));
101 }
102
103 module case () {
104 case_base ();
105 translate ([0, 0, box_h/2]) case_walls ();
106 }
107
108
109 // todo:
110 // specify which wall (rear, front, left, right). vector addition may help...
111 // offset from center of wall, as vector (and use vector subtraction!)
112 // optional: inside/outside
113 function case_connector_wall (x=0, y=0, z=0) = [ [panel_w/2-x, panel_h/2-y, (box_h-base_h)/2-z], [0,-1, 0], 0 ];
114
115 // HINGE
116
117 // hinge todo:
118 // calculate z offset so that hinge will align when closed
119 // calculate offset into panel surface for length of peg
120 // attach to case, calculating offset from wall as fixed value + width
121
122 // add connector for pin to socket so that can easily be test fit in
123 // software instead of guessing
124
125 // should panel connector be on its side? Limits motion to 90⁰ Or
126 // maybe just walls only + fillet with no base...
127
128 function hinge_connector_back (th=hinge_joint_thickness*2, h=hinge_base_height) = [ [0, th/2, h/2], [0,1, 0], 0 ];
129
130 // todo:
131 // gusset support underneath
132 // split into base and negative so that a hole can be punched into case wall
133
134 module hinge_female_base () {
135 w = hinge_joint_width * 2;
136 th = hinge_joint_thickness * 2;
137
138 %connector (hinge_connector_back ());
139 cube ([w, th, hinge_base_height], center=true);
140 }
141
142 module hinge_female_cut () {
143 w = hinge_joint_width * 2;
144 th = hinge_joint_thickness * 2;
145
146 // cruft from earlier hacking, remove...
147 jt = hinge_joint_thickness;
148 jw = hinge_joint_width;
149
150 joint_male_negative(male_joint_width=jw, male_joint_thickness=jt, forward_rom=90, backward_rom=90, male_joint_height=hinge_joint_height);
151 }
152
153 module hinge_female () {
154 difference () {
155 hinge_female_base ();
156 hinge_female_cut ();
157 }
158 }
159
160 module hinge_male () {
161 for (i=[0,1]) mirror ([0, i, 0]) translate ([0, -hinge_arm_length/4, 0])
162 joint_male(male_joint_width=hinge_joint_width, male_joint_thickness=hinge_joint_thickness, male_joint_height=hinge_arm_length/2, side=true);
163
164 }
165
166
167 // hinge to panel...
168 // mount hinge on panel arm_length back from edge
169
170 // fixme: wall thickness is not taken into account
171
172 // PANEL
173
174
175 // cleanup after general case_connector_wall() is done
176 panel_c = [ [panel_w/2-10, panel_h/2-hinge_arm_length, -base_h/2+0.01], [0,0, 1], 180 ];
177
178 module panel () {
179 difference () {
180 case_base ();
181 linear_extrude (base_h*2,center=true) panel_layout ();
182 }
183 %connector (panel_c);
184 attach (panel_c, hinge_connector_back ()) hinge_female ();
185 }
186
187 module panel_attach (position, angle=0) {
188 x = position[0];
189 y = position[1];
190 c1 = [ [x, y, base_h/2], [0,0,1], angle ];
191 a1 = [ [0,0, 0], [0,0,0], 0 ];
192 // %connector (c1); // fixme: don't use 2d for layout
193 attach (c1, a1) children ();
194 }
195
196 // panel layout inspired by the Neo Geo layout
197 module panel_layout () {
198 translate ([-panel_w/2 + 40, 0, 0]) {
199 panel_attach ([0, 0], 90) joystick ();
200
201 // p1, coin (floating off in the distance...)
202 translate ([140, 0, 0]) {
203 $button_d=16;
204 for (x = [0, $button_d+10]) {
205 panel_attach ([x, 42]) button ();
206 }
207 }
208
209 // a, b, c, d
210 translate ([60, -20, 0]) {
211 panel_attach ([0, 0]) button ();
212 for (i = [ 1 : 3 ]) {
213 panel_attach ([i*($button_d+10)-10, $button_d]) button ();
214 }
215 }
216 }
217 }