396 lines
13 KiB
OpenSCAD
396 lines
13 KiB
OpenSCAD
/* Copyright Brian Stephan 2023
|
|
*
|
|
* This file is part of the Buildable Stick System.
|
|
*
|
|
* The Buildable Stick System is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation, either version 3 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
* The Buildable Stick System is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* the Buildable Stick System. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
include <roundedcube.scad>
|
|
|
|
/* QUASI-CONSTANTS */
|
|
|
|
// adjustments
|
|
hole_tolerance = 0.15;
|
|
|
|
// M3
|
|
m3_screw_selftap_radius = 1.3;
|
|
|
|
// M4
|
|
m4_bolt_radius = 2 + hole_tolerance;
|
|
m4_bolt_countersink_radius = 6.1 + hole_tolerance;
|
|
m4_bolt_hex_exterior_radius = 3.6 + hole_tolerance;
|
|
|
|
// 24mm button
|
|
small_button_radius = 12 + hole_tolerance;
|
|
|
|
// 30mm button
|
|
big_button_radius = 15 + hole_tolerance;
|
|
|
|
// JLF mount dimensions
|
|
lever_mount_x = 53;
|
|
lever_mount_y = 95;
|
|
lever_mount_z = 2;
|
|
|
|
// case dimensions
|
|
// base frame box. reminder: top of inside (including mounts) is chopped by top_plate_z for plates
|
|
frame_x = 183;
|
|
frame_y = 208;
|
|
frame_z = 50;
|
|
|
|
// depth of the "lip" of the frame that the top plate sets into/supports the overhang
|
|
frame_wall = 8;
|
|
|
|
// per neutrik (mm)
|
|
neutrik_panel_thickness = 3;
|
|
|
|
// top plate, which can either be the whole plate ("inset") or the mounting frame for a plate that overhangs
|
|
top_plate_x = frame_x - frame_wall;
|
|
top_plate_y = frame_y - frame_wall;
|
|
top_plate_z = 5;
|
|
|
|
// how much the top plate x/y is expanded to overhang the frame
|
|
// note that this is relative to the top plate (so the wall is added back)
|
|
top_plate_overhang_amount = frame_wall + 17;
|
|
overhang_top_plate_x = top_plate_x + top_plate_overhang_amount;
|
|
overhang_top_plate_y = top_plate_y + top_plate_overhang_amount;
|
|
|
|
plate_to_frame_point_x = (top_plate_x/2)-10;
|
|
plate_to_frame_point_y = (top_plate_y/2)-10;
|
|
|
|
// frame interior that supports the top plates
|
|
panel_support_width = 5;
|
|
|
|
// neutrik D screw holes
|
|
neutrik_d_screw_radius = 1.6 + hole_tolerance;
|
|
neutrik_d_radius = 12 + hole_tolerance;
|
|
|
|
// additional button radius for decorative panels, etc.
|
|
decorative_radius = 12;
|
|
jumbo_decorative_radius = 15;
|
|
|
|
/* PARTS */
|
|
|
|
module m4_hole() {
|
|
cylinder(r=m4_bolt_radius, h=100, $fn=50, center=true);
|
|
}
|
|
|
|
module m4_hole_countersink() {
|
|
cylinder(r1=m4_bolt_radius, r2=m4_bolt_countersink_radius, h=3.2, $fn=50, center=true);
|
|
}
|
|
|
|
module top_plate_holes() {
|
|
// holes for mount bolts
|
|
translate([plate_to_frame_point_x, plate_to_frame_point_y, 0]) m4_hole();
|
|
translate([plate_to_frame_point_x, -plate_to_frame_point_y, 0]) m4_hole();
|
|
translate([-plate_to_frame_point_x, plate_to_frame_point_y, 0]) m4_hole();
|
|
translate([-plate_to_frame_point_x, -plate_to_frame_point_y, 0]) m4_hole();
|
|
// holes for mount bolt countersinks
|
|
translate([plate_to_frame_point_x, plate_to_frame_point_y, 2]) m4_hole_countersink();
|
|
translate([plate_to_frame_point_x, -plate_to_frame_point_y, 2]) m4_hole_countersink();
|
|
translate([-plate_to_frame_point_x, plate_to_frame_point_y, 2]) m4_hole_countersink();
|
|
translate([-plate_to_frame_point_x, -plate_to_frame_point_y, 2]) m4_hole_countersink();
|
|
}
|
|
|
|
// button hole, with extra wide bits for various uses (cutting out space
|
|
// for snap-ins, etc.
|
|
module button_24mm_hole() {
|
|
cylinder(r=small_button_radius, h=100, $fn=50, center=true);
|
|
// carve out space for snap-ins, leave 3mm
|
|
// slagcoin has screw-in nut diameter at 29.5mm, so radius+6 to leave some space
|
|
// translation is to leave 3mm thickness in the plate without recentering anything
|
|
translate([0, 0, -25]) cylinder(r=small_button_radius+6, h=49, $fn=50, center=true);
|
|
// space for decorative button surround stuff
|
|
translate([0, 0, 50]) cylinder(r=small_button_radius+decorative_radius, h=20, $fn=50, center=true);
|
|
translate([0, 0, 70]) cylinder(r=small_button_radius+jumbo_decorative_radius, h=20, $fn=50, center=true);
|
|
}
|
|
|
|
// button hole, with extra wide bits for various uses (cutting out space
|
|
// for snap-ins, etc.
|
|
module button_30mm_hole() {
|
|
cylinder(r=big_button_radius, h=100, $fn=50, center=true);
|
|
// carve out space for snap-ins, leave 3mm
|
|
// slagcoin has screw-in nut diameter at 36mm, so radius+6 to leave some space
|
|
// translation is to leave 3mm thickness in the plate without recentering anything
|
|
translate([0, 0, -25]) cylinder(r=big_button_radius+6, h=49, $fn=50, center=true);
|
|
// space for decorative button surround stuff
|
|
translate([0, 0, 50]) cylinder(r=big_button_radius+decorative_radius, h=20, $fn=50, center=true);
|
|
translate([0, 0, 70]) cylinder(r=big_button_radius+jumbo_decorative_radius, h=20, $fn=50, center=true);
|
|
}
|
|
|
|
module frame_hex_bolt_hole() {
|
|
scale([1, 1, 2]) cylinder(r=m4_bolt_hex_exterior_radius, h=frame_z, $fn=6, center=true);
|
|
}
|
|
|
|
module frame_interchange_hole() {
|
|
cylinder(r=15, h=50, $fn=50, center=true);
|
|
}
|
|
|
|
module neutrik_d_hole() {
|
|
cylinder(r=neutrik_d_radius, h=100, $fn=50, center=true);
|
|
}
|
|
|
|
module neutrik_d_screw_hole() {
|
|
cylinder(r=neutrik_d_screw_radius, h=100, $fn=50, center=true);
|
|
}
|
|
|
|
module neutrik_d_mount() {
|
|
neutrik_d_hole();
|
|
translate([9.5, 12, 0]) neutrik_d_screw_hole();
|
|
translate([-9.5, -12, 0]) neutrik_d_screw_hole();
|
|
// clearance for cutting space out of e.g. frame wall
|
|
translate([0, 0, 25]) cube([32, 37, 50], center=true);
|
|
}
|
|
|
|
module m3_mount_post() {
|
|
difference() {
|
|
cylinder(r=m3_screw_selftap_radius*4, h=8, $fn=6, center=true);
|
|
cylinder(r=m3_screw_selftap_radius, h=8*2, $fn=50, center=true);
|
|
}
|
|
}
|
|
|
|
module pcb_mount() {
|
|
translate([44, 18.5, 0]) m3_mount_post();
|
|
translate([44, -18.5, 0]) m3_mount_post();
|
|
translate([-44, 18.5, 0]) m3_mount_post();
|
|
translate([-44, -18.5, 0]) m3_mount_post();
|
|
}
|
|
|
|
/* PIECES */
|
|
|
|
module levermountbase() {
|
|
difference() {
|
|
// base plate
|
|
cube([lever_mount_x, lever_mount_y, lever_mount_z], center=true);
|
|
// joystick hole
|
|
cylinder(r=21, h=3.1, $fn=50, center=true);
|
|
}
|
|
}
|
|
|
|
// see https://www.slagcoin.com/joystick/mounting_layering.html
|
|
// should work with JLF, JLW, LS-32, LS-33, LS-40, LS-55, LS-56
|
|
module levermountholes() {
|
|
// joystick hole
|
|
cylinder(r=12, h=5.1, $fn=50, center=true);
|
|
// holes for joystick bolts
|
|
translate([20, 42.5, 0])
|
|
m4_hole();
|
|
translate([20, -42.5, 0])
|
|
m4_hole();
|
|
translate([-20, 42.5, 0])
|
|
m4_hole();
|
|
translate([-20, -42.5, 0])
|
|
m4_hole();
|
|
// holes for joystick bolt countersinks
|
|
translate([20, 42.5, 2])
|
|
m4_hole_countersink();
|
|
translate([20, -42.5, 2])
|
|
m4_hole_countersink();
|
|
translate([-20, 42.5, 2])
|
|
m4_hole_countersink();
|
|
translate([-20, -42.5, 2])
|
|
m4_hole_countersink();
|
|
}
|
|
|
|
module base_topplate() {
|
|
cube([top_plate_x, top_plate_y, top_plate_z], center=true);
|
|
}
|
|
|
|
module overhang_plate() {
|
|
roundedcube([overhang_top_plate_x, overhang_top_plate_y, top_plate_z], center=true, radius=1);
|
|
}
|
|
|
|
// this takes the base_topplate and makes it a small frame, putting a larger top plate
|
|
module base_top_plate_with_raised_overhang() {
|
|
// make a frame out of the top plate (and keep the main plate on the center plane)
|
|
translate([0, 0, -5]) difference() {
|
|
base_topplate();
|
|
cube([top_plate_x-(panel_support_width*2), top_plate_y-(panel_support_width*2), top_plate_z*2], center=true);
|
|
}
|
|
translate([plate_to_frame_point_x, plate_to_frame_point_y, -2.5]) resize([0, 0, 10]) frame_mount_column();
|
|
translate([-(plate_to_frame_point_x), plate_to_frame_point_y, -2.5]) resize([0, 0, 10]) frame_mount_column();
|
|
translate([plate_to_frame_point_x, -(plate_to_frame_point_y), -2.5]) resize([0, 0, 10]) frame_mount_column();
|
|
translate([-(plate_to_frame_point_x), -(plate_to_frame_point_y), -2.5]) resize([0, 0, 10]) frame_mount_column();
|
|
overhang_plate();
|
|
}
|
|
|
|
module topplate() {
|
|
difference() {
|
|
base_topplate();
|
|
top_plate_holes();
|
|
}
|
|
}
|
|
|
|
module bottom_plate_with_overhang() {
|
|
difference() {
|
|
overhang_plate();
|
|
rotate([180, 0, 0]) top_plate_holes();
|
|
}
|
|
}
|
|
|
|
module top_plate_with_raised_overhang() {
|
|
difference() {
|
|
base_top_plate_with_raised_overhang();
|
|
top_plate_holes();
|
|
}
|
|
}
|
|
|
|
module top_plate_with_raised_overhang_long() {
|
|
rotate([0, 0, -90]) top_plate_with_raised_overhang();
|
|
}
|
|
|
|
module frame_box() {
|
|
difference() {
|
|
roundedcube([frame_x, frame_y, frame_z], center=true, radius=3);
|
|
cube([top_plate_x-(panel_support_width*2), top_plate_y-(panel_support_width*2), frame_z+5], center=true);
|
|
}
|
|
}
|
|
|
|
module frame_mount_column() {
|
|
cube([20, 20, frame_z], center=true);
|
|
}
|
|
|
|
module side_chopper() {
|
|
translate([frame_x/2+4, 0, 0]) cube([16, 2*(frame_y+top_plate_y), 2*(frame_z+top_plate_z)], center=true);
|
|
}
|
|
|
|
module frame_connection_holes() {
|
|
translate([frame_x/2, (frame_y/4)+10, (frame_z/4)]) rotate([0, 90, 0]) m4_hole();
|
|
translate([frame_x/2, (frame_y/4)+10, -(frame_z/4)]) rotate([0, 90, 0]) m4_hole();
|
|
translate([frame_x/2, (frame_y/4)-10, (frame_z/4)]) rotate([0, 90, 0]) m4_hole();
|
|
translate([frame_x/2, (frame_y/4)-10, -(frame_z/4)]) rotate([0, 90, 0]) m4_hole();
|
|
|
|
translate([frame_x/2, -((frame_y/4)+10), (frame_z/4)]) rotate([0, 90, 0]) m4_hole();
|
|
translate([frame_x/2, -((frame_y/4)+10), -(frame_z/4)]) rotate([0, 90, 0]) m4_hole();
|
|
translate([frame_x/2, -((frame_y/4)-10), (frame_z/4)]) rotate([0, 90, 0]) m4_hole();
|
|
translate([frame_x/2, -((frame_y/4)-10), -(frame_z/4)]) rotate([0, 90, 0]) m4_hole();
|
|
}
|
|
|
|
module frame_cable_routing_hole() {
|
|
translate([frame_x/2, 0, 0]) rotate([0, 90, 0]) frame_interchange_hole();
|
|
}
|
|
|
|
module base_frame() {
|
|
frame_box();
|
|
translate([plate_to_frame_point_x, plate_to_frame_point_y, 0]) frame_mount_column();
|
|
translate([-plate_to_frame_point_x, plate_to_frame_point_y, 0]) frame_mount_column();
|
|
translate([plate_to_frame_point_x, -(plate_to_frame_point_y), 0]) frame_mount_column();
|
|
translate([-plate_to_frame_point_x, -(plate_to_frame_point_y), 0]) frame_mount_column();
|
|
}
|
|
|
|
module frame() {
|
|
difference() {
|
|
base_frame();
|
|
translate([0, 0, frame_z/2]) scale([1, 1, 2]) base_topplate();
|
|
translate([plate_to_frame_point_x, plate_to_frame_point_y, 0]) frame_hex_bolt_hole();
|
|
translate([-plate_to_frame_point_x, plate_to_frame_point_y, 0]) frame_hex_bolt_hole();
|
|
translate([plate_to_frame_point_x, -plate_to_frame_point_y, 0]) frame_hex_bolt_hole();
|
|
translate([-plate_to_frame_point_x, -plate_to_frame_point_y, 0]) frame_hex_bolt_hole();
|
|
}
|
|
}
|
|
|
|
/* LAYOUTS */
|
|
|
|
// Directional Arc (both hands)
|
|
|
|
module dir_arc_24mm_6_button() {
|
|
button_24mm_hole();
|
|
translate([29.5, 0, 0]) button_24mm_hole();
|
|
translate([29.5+26.3, -12.9, 0]) button_24mm_hole();
|
|
|
|
translate([29.5+26.3+15.5+9.7+2.6, 0, 0]) button_24mm_hole();
|
|
translate([29.5+26.3+15.5+9.7+2.6+26.9, 10.9, 0]) button_24mm_hole();
|
|
translate([29.5+26.3+15.5+9.7+2.6+26.9+29.6, 10.9, 0]) button_24mm_hole();
|
|
translate([29.5+26.3+15.5+9.7, -29.4, 0]) button_24mm_hole();
|
|
translate([29.5+26.3+15.5+9.7+2.6+26.9-1.7, 10.9-30.1, 0]) button_24mm_hole();
|
|
translate([29.5+26.3+15.5+9.7+2.6+26.9+29.6, 10.9-30.1, 0]) button_24mm_hole();
|
|
|
|
translate([29.5+26.3+15.5, -65.2, 0]) button_30mm_hole();
|
|
}
|
|
|
|
// 6 button plus the normal fourth column for 8 button actually on a third row
|
|
module dir_arc_24mm_8_button_compressed() {
|
|
dir_arc_24mm_6_button();
|
|
translate([29.5+26.3+15.5+9.7+2.6+2.6, 29.4, 0]) button_24mm_hole();
|
|
translate([29.5+26.3+15.5+9.7+2.6+26.9+2.6, 40.3, 0]) button_24mm_hole();
|
|
}
|
|
|
|
// Directional Arc (left hand)
|
|
|
|
module dir_arc_30mm_button_l() {
|
|
translate([-top_plate_x/2, -top_plate_y/2, 0]) translate([73, 132, 0]) button_30mm_hole();
|
|
}
|
|
|
|
module dir_arc_w_30mm() {
|
|
dir_arc_30mm_button_l();
|
|
translate([35, 0, 0]) dir_arc_30mm_button_l();
|
|
translate([35+33.5, -12.9, 0]) dir_arc_30mm_button_l();
|
|
translate([35+7, 34.5, 0]) dir_arc_30mm_button_l();
|
|
// just my guesstimate on this one, but note that this is the same position as sega 2p (just mirrored)
|
|
translate([-top_plate_x/2, -top_plate_y/2, 0]) translate([top_plate_x-28.06, 145-19-9-11-19-9-11, 0]) button_30mm_hole();
|
|
}
|
|
|
|
module dir_arc_w_30mm_plus_one() {
|
|
dir_arc_w_30mm();
|
|
translate([-33.5, -12.9, 0]) dir_arc_30mm_button_l();
|
|
}
|
|
|
|
// Namco Noir (right hand)
|
|
|
|
module noir_button_p1() {
|
|
translate([-top_plate_x/2, -top_plate_y/2, 0]) translate([35, 145, 0]) button_30mm_hole();
|
|
}
|
|
|
|
module noir_plus_one() {
|
|
// standard 8 (all relative to the first button) (via r/fightsticks)
|
|
noir_button_p1();
|
|
translate([32.94, 7.37+4.49, 0]) noir_button_p1();
|
|
translate([32.94+34.54, 7.37, 0]) noir_button_p1();
|
|
translate([32.94+34.54+33.02, -6.86, 0]) noir_button_p1();
|
|
translate([-3.47, -6.86-19.64-4.32-7.62, 0]) noir_button_p1();
|
|
translate([29.38, -6.86-19.64, 0]) noir_button_p1();
|
|
translate([29.38+3.56+31.24, -6.86-19.64-4.32, 0]) noir_button_p1();
|
|
translate([29.38+3.56+31.24+3.3+29.04, -6.86-19.64-4.32-7.62-6.93, 0]) noir_button_p1();
|
|
|
|
// just my guesstimate on this one, but note that this is the same position as sega 2p
|
|
translate([-3.47-3.47, -78, 0]) noir_button_p1();
|
|
}
|
|
|
|
// Sega Astro City 2P (right hand)
|
|
|
|
module sega_2p_p1() {
|
|
translate([-top_plate_x/2, -top_plate_y/2, 0]) translate([28.06, 145, 0]) button_30mm_hole();
|
|
}
|
|
|
|
module sega_2p_6_button() {
|
|
// via slagcoin
|
|
sega_2p_p1();
|
|
translate([30.5, 11+9, 0]) sega_2p_p1();
|
|
translate([30.5+36, 11+9, 0]) sega_2p_p1();
|
|
translate([0, -19-9-11, 0]) sega_2p_p1();
|
|
translate([30.5, -19, 0]) sega_2p_p1();
|
|
translate([30.5+36, -19, 0]) sega_2p_p1();
|
|
}
|
|
|
|
module sega_2p() {
|
|
sega_2p_6_button();
|
|
translate([30.5+36+36, 11, 0]) sega_2p_p1();
|
|
translate([30.5+36+36, -19-9, 0]) sega_2p_p1();
|
|
}
|
|
|
|
module sega_2p_plus_one() {
|
|
sega_2p();
|
|
// just my guesstimate on this one
|
|
translate([0, -19-9-11-19-9-11, 0]) sega_2p_p1();
|
|
}
|