# HG changeset patch # User Paul Boddie # Date 1418344887 -3600 # Node ID bac004ed7f0d393538e10be629cda60dbe95432c # Parent 894194831154504dbefba3d914f819c663c36e78 Added model presets and support for wide PCBs and associated connecting lugs. Made lug generation more general. Moved PCB definitions inside the back piece transformation block. diff -r 894194831154 -r bac004ed7f0d cartridge.scad --- a/cartridge.scad Thu Dec 11 20:03:01 2014 +0100 +++ b/cartridge.scad Fri Dec 12 01:41:27 2014 +0100 @@ -28,7 +28,12 @@ /* Model configurations. */ - ROM_CARTRIDGE = 1; + ROM_CARTRIDGE = 0; + WIDE_CARTRIDGE = 1; + + /* Set this to the desired model type. */ + + MODEL = ROM_CARTRIDGE; /* Options for checking. Some useful combinations... @@ -142,9 +147,19 @@ cube([width, depth, height], center = true); } + /* Model widths. */ + + ROM_CARTRIDGE_int_payload_width = 86.0; + WIDE_CARTRIDGE_int_payload_width = 140.0; + /* Internal dimensions. */ - int_payload_width = 86.0; /* internal width in the payload section */ + /* internal width in the payload section */ + int_payload_width = + MODEL == ROM_CARTRIDGE ? ROM_CARTRIDGE_int_payload_width : + MODEL == WIDE_CARTRIDGE ? WIDE_CARTRIDGE_int_payload_width : + ROM_CARTRIDGE_int_payload_width; + int_connector_width = 86.0; /* limited to the Plus 1 socket dimensions */ int_payload_depth = 12.5; /* maximum depth in the payload section */ int_connector_depth = 11.0; /* maximum depth in the connector section */ @@ -360,6 +375,44 @@ pow(pcb_lug_cross_height / 2, 2), 0.5); + wide_pcb_lug_offset_from_inside = 6.0; + wide_pcb_lug_offset_from_bottom = 6.0; + + /* PCBs for checking. */ + + pcb_width = 84.85; pcb_height = 62.5; pcb_depth = 1; + edge_connector_width = 56.5; edge_connector_height = 11.85; + + /* + The rectangular part of the narrow left and right holes is smaller + than the "bump" in the case, but the circular parts make the overall + hole larger than the "bump". An extra depth is used for holes to avoid + surface definition problems. + */ + + pcb_hole_margin = 0.55; + pcb_hole_width = 2.2; + pcb_hole_extra_depth = 0.1; + pcb_lug_hole_radius = 3.75; + + pcb_left_hole_offset = pcb_back_support_left_bump_offset_from_bottom + pcb_hole_margin; + pcb_left_hole_height = pcb_back_support_left_bump_height - pcb_hole_margin * 2; + pcb_left_hole_offset_from_centre = pcb_support_offset_from_centre + + pcb_back_support_width / 2 - pcb_hole_width / 2; + + pcb_right_hole_offset = pcb_back_support_right_bump_offset_from_bottom + pcb_hole_margin; + pcb_right_hole_height = pcb_back_support_right_bump_height - pcb_hole_margin * 2; + pcb_right_hole_offset_from_centre = -pcb_left_hole_offset_from_centre; + + pcb_hole_depth = pcb_depth + 2 * pcb_hole_extra_depth; + pcb_hole_start_depth = -pcb_hole_extra_depth; + + wide_pcb_width = 138.0; wide_pcb_height = pcb_height; wide_pcb_depth = pcb_depth; + wide_pcb_hole_depth = pcb_hole_depth; + wide_pcb_hole_start_depth = pcb_hole_start_depth; + + wide_pcb_lug_hole_radius = 4.0; + /* Repeated constructs. */ module pcb_support(xdir, bump_height, bump_offset) { @@ -411,13 +464,27 @@ } module pcb_lug(xdir) { - translate([xdir * - (int_connector_width / 2 - pcb_lug_offset_from_inside), + pcb_lug_explicit(xdir, int_connector_width / 2 - pcb_lug_offset_from_inside, + pcb_lug_offset_from_bottom); + } + + module pcb_lug_wide(xdir) { + pcb_lug_explicit(xdir, int_payload_width / 2 - wide_pcb_lug_offset_from_inside, + wide_pcb_lug_offset_from_bottom); + pcb_lug_explicit(xdir, int_payload_width / 2 - wide_pcb_lug_offset_from_inside, + wide_pcb_height - edge_connector_height - wide_pcb_lug_offset_from_bottom); + } + + module pcb_lug_explicit(xdir, pcb_lug_offset_from_centre, pcb_lug_offset_from_bottom) { + translate([payload_centre + xdir * pcb_lug_offset_from_centre, back_depth, int_payload_lower_extent + pcb_lug_offset_from_bottom ]) rotate([90, 0, 0]) difference() { + + /* Cylinder with cross. */ + union() { cylinder(h=pcb_lug_depth, r=pcb_lug_outer_radius); cube_at(pcb_lug_cross_width, @@ -429,15 +496,32 @@ 0, 0, 1, 0, 0, 0); } + + /* Hollowed out by a cylinder. */ + cylinder(h=pcb_lug_depth, r=pcb_lug_inner_radius); + + /* Tapered off for easier connection. */ + translate([0, 0, pcb_lug_depth - pcb_lug_ro]) fillet_torus(pcb_lug_outer_radius, pcb_lug_rr); } } module pcb_front_lug(xdir) { - translate([xdir * - (int_connector_width / 2 - pcb_lug_offset_from_inside), + pcb_front_lug_explicit(xdir, int_connector_width / 2 - pcb_lug_offset_from_inside, + pcb_lug_offset_from_bottom); + } + + module pcb_front_lug_wide(xdir) { + pcb_front_lug_explicit(xdir, int_payload_width / 2 - wide_pcb_lug_offset_from_inside, + wide_pcb_lug_offset_from_bottom); + pcb_front_lug_explicit(xdir, int_payload_width / 2 - wide_pcb_lug_offset_from_inside, + wide_pcb_height - edge_connector_height - wide_pcb_lug_offset_from_bottom); + } + + module pcb_front_lug_explicit(xdir, pcb_lug_offset_from_centre, pcb_lug_offset_from_bottom) { + translate([payload_centre + xdir * pcb_lug_offset_from_centre, -int_front_depth + pcb_front_lug_depth, int_payload_lower_extent + pcb_lug_offset_from_bottom ]) @@ -541,7 +625,7 @@ /* PCB supports. */ - if (ROM_CARTRIDGE) { + if (MODEL == ROM_CARTRIDGE) { cube_at(pcb_front_support_width, pcb_front_support_depth, pcb_front_support_height, @@ -563,6 +647,12 @@ pcb_front_lug(-1); pcb_front_lug(1); } + + if (MODEL == WIDE_CARTRIDGE) { + + pcb_front_lug_wide(-1); + pcb_front_lug_wide(1); + } } /* Label insets. */ @@ -682,460 +772,487 @@ if (BACK) translate([back_displacement, 0, 0]) - rotate([0, 0, back_rotation]) - difference() { + rotate([0, 0, back_rotation]) { + difference() { + + /* The cartridge surfaces. */ - /* The cartridge surfaces. */ + union() { + + /* Back portion. */ + + if (BACK_SURFACE) { + + /* Surfaces surrounding the payload. */ - union() { + /* Payload section of back surface. */ - /* Back portion. */ + cube_at(payload_width, payload_back, payload_height, + 0, 1, 1, + payload_centre, int_payload_back_depth, int_payload_lower_extent); - if (BACK_SURFACE) { + cube_at(back_left, back_depth, payload_height, + -1, 1, 1, + int_payload_left_extent, 0, int_payload_lower_extent); - /* Surfaces surrounding the payload. */ + cube_at(back_right, back_depth, payload_height, + 1, 1, 1, + int_payload_right_extent, 0, int_payload_lower_extent); + + /* Surfaces surrounding the connector. */ - /* Payload section of back surface. */ + /* Connector section of back surface overlapping the floor. */ + + cube_at(connector_width, connector_back, connector_height, + 0, 1, -1, + 0, int_connector_back_depth, int_payload_lower_extent); - cube_at(payload_width, payload_back, payload_height, - 0, 1, 1, - payload_centre, int_payload_back_depth, int_payload_lower_extent); + cube_at(back_left, back_depth, connector_height, + -1, 1, -1, + -int_connector_width / 2, 0, int_payload_lower_extent); + + cube_at(back_right, back_depth, connector_height, + 1, 1, -1, + int_connector_width / 2, 0, int_payload_lower_extent); - cube_at(back_left, back_depth, payload_height, - -1, 1, 1, - int_payload_left_extent, 0, int_payload_lower_extent); + /* Top of back piece. */ + + cube_at(payload_width, back_depth, top, + 0, 1, 1, + payload_centre, 0, int_payload_upper_extent); - cube_at(back_right, back_depth, payload_height, - 1, 1, 1, - int_payload_right_extent, 0, int_payload_lower_extent); + /* + The extension of the back to connect with the front. Here, the inside + edges are rounded. The outside edges are rounded later. - /* Surfaces surrounding the connector. */ + An extra overlapping measure is employed so that the filleting is + continuous between the payload and connector portions. On the inside + edges, the connector filleting is extended upwards. + */ + + /* Left side of payload. */ - /* Connector section of back surface overlapping the floor. */ + difference() { + cube_at(back_left - groove_depth, groove_width_extra, inner_payload_front_cutout_height, + -1, 1, 1, + int_payload_left_extent, -groove_width_extra, int_payload_lower_extent); + translate([int_payload_left_extent - groove_ro, -groove_width_extra + groove_ro, + int_payload_lower_extent]) + rotate([0, 0, -90]) + fillet_justified(groove_rr, inner_payload_front_cutout_height); + } - cube_at(connector_width, connector_back, connector_height, - 0, 1, -1, - 0, int_connector_back_depth, int_payload_lower_extent); + /* Right side of payload. */ - cube_at(back_left, back_depth, connector_height, - -1, 1, -1, - -int_connector_width / 2, 0, int_payload_lower_extent); + difference() { + cube_at(back_right - groove_depth, groove_width_extra, inner_payload_front_cutout_height, + 1, 1, 1, + int_payload_right_extent, -groove_width_extra, int_payload_lower_extent); + translate([int_payload_right_extent + groove_ro, -groove_width_extra + groove_ro, + int_payload_lower_extent]) + rotate([0, 0, 180]) + fillet_justified(groove_rr, inner_payload_front_cutout_height); + } - cube_at(back_right, back_depth, connector_height, - 1, 1, -1, - int_connector_width / 2, 0, int_payload_lower_extent); + /* Left side of connector. */ - /* Top of back piece. */ + difference() { + cube_at(back_left - groove_depth, groove_width_extra, inner_connector_front_cutout_height, + -1, 1, -1, + -int_connector_width / 2, -groove_width_extra, int_payload_lower_extent); + translate([-int_connector_width / 2 - groove_ro, -groove_width_extra + groove_ro, + lower_extent]) + rotate([0, 0, -90]) + fillet_partitioned(groove_rr, inner_connector_front_cutout_height + extra); + } - cube_at(payload_width, back_depth, top, - 0, 1, 1, - payload_centre, 0, int_payload_upper_extent); + /* Right side of connector. */ - /* - The extension of the back to connect with the front. Here, the inside - edges are rounded. The outside edges are rounded later. + difference() { + cube_at(back_right - groove_depth, groove_width_extra, inner_connector_front_cutout_height, + 1, 1, -1, + int_connector_width / 2, -groove_width_extra, int_payload_lower_extent); + translate([int_connector_width / 2 + groove_ro, -groove_width_extra + groove_ro, + lower_extent]) + rotate([0, 0, 180]) + fillet_partitioned(groove_rr, inner_connector_front_cutout_height + extra); + } + + /* Top side. */ - An extra overlapping measure is employed so that the filleting is - continuous between the payload and connector portions. On the inside - edges, the connector filleting is extended upwards. - */ - - /* Left side of payload. */ + difference() { + cube_at(payload_width - groove_depth * 2, groove_width_extra, top - top_groove_depth, + 0, 1, 1, + payload_centre, -groove_width_extra, int_payload_upper_extent); + translate([payload_centre, -groove_width_extra + groove_ro, + int_payload_upper_extent + groove_ro]) + rotate([0, 0, 180]) + rotate([0, 90, 0]) + fillet(groove_rr, payload_width - groove_depth * 2); + } + } difference() { - cube_at(back_left - groove_depth, groove_width_extra, inner_payload_front_cutout_height, - -1, 1, 1, - int_payload_left_extent, -groove_width_extra, int_payload_lower_extent); - translate([int_payload_left_extent - groove_ro, -groove_width_extra + groove_ro, - int_payload_lower_extent]) - rotate([0, 0, -90]) - fillet_justified(groove_rr, inner_payload_front_cutout_height); - } + + /* Floor of cartridge. */ + + cube_at(int_connector_width, int_connector_back_depth, bottom, + 0, 1, 1, + 0, 0, lower_extent + int_connector_height); - /* Right side of payload. */ + /* Edge connector cutout. */ - difference() { - cube_at(back_right - groove_depth, groove_width_extra, inner_payload_front_cutout_height, - 1, 1, 1, - int_payload_right_extent, -groove_width_extra, int_payload_lower_extent); - translate([int_payload_right_extent + groove_ro, -groove_width_extra + groove_ro, - int_payload_lower_extent]) - rotate([0, 0, 180]) - fillet_justified(groove_rr, inner_payload_front_cutout_height); + cube_at(edge_connector_cutout_back_width, + edge_connector_cutout_back_depth, + bottom, + 0, 1, 1, + 0, 0, lower_extent + int_connector_height); } - /* Left side of connector. */ + /* Extended floor. */ + + if (payload_width > connector_width) { + + difference() { - difference() { - cube_at(back_left - groove_depth, groove_width_extra, inner_connector_front_cutout_height, - -1, 1, -1, - -int_connector_width / 2, -groove_width_extra, int_payload_lower_extent); - translate([-int_connector_width / 2 - groove_ro, -groove_width_extra + groove_ro, - lower_extent]) - rotate([0, 0, -90]) - fillet_partitioned(groove_rr, inner_connector_front_cutout_height + extra); + cube_at(payload_width - connector_width, back_depth, bottom, + 1, 1, 1, + payload_left_extent, 0, lower_extent + int_connector_height); + + cube_at(payload_width - connector_width, edge_connector_cutout_front_depth, bottom, + 1, 1, 1, + payload_left_extent, 0, lower_extent + int_connector_height); + } } - /* Right side of connector. */ + /* PCB supports. */ - difference() { - cube_at(back_right - groove_depth, groove_width_extra, inner_connector_front_cutout_height, - 1, 1, -1, - int_connector_width / 2, -groove_width_extra, int_payload_lower_extent); - translate([int_connector_width / 2 + groove_ro, -groove_width_extra + groove_ro, - lower_extent]) - rotate([0, 0, 180]) - fillet_partitioned(groove_rr, inner_connector_front_cutout_height + extra); + if (MODEL == ROM_CARTRIDGE) { + pcb_support(-1, pcb_back_support_left_bump_height, + pcb_back_support_left_bump_offset_from_bottom); + pcb_support(1, pcb_back_support_right_bump_height, + pcb_back_support_right_bump_offset_from_bottom); + + /* Circular "lugs" to hold PCBs in place. */ + + pcb_lug(-1); + pcb_lug(1); } - /* Top side. */ + if (MODEL == WIDE_CARTRIDGE) { - difference() { - cube_at(payload_width - groove_depth * 2, groove_width_extra, top - top_groove_depth, - 0, 1, 1, - payload_centre, -groove_width_extra, int_payload_upper_extent); - translate([payload_centre, -groove_width_extra + groove_ro, - int_payload_upper_extent + groove_ro]) - rotate([0, 0, 180]) - rotate([0, 90, 0]) - fillet(groove_rr, payload_width - groove_depth * 2); + pcb_lug_wide(1); + pcb_lug_wide(-1); } } - difference() { + /* Label insets. */ - /* Floor of cartridge. */ + union() { + + /* Top label. See also the front piece. */ - cube_at(int_connector_width, int_connector_back_depth, bottom, - 0, 1, 1, - 0, 0, lower_extent + int_connector_height); + if (TOP_LABEL_INSET) + translate([top_label_left_extent, + -front_depth + top_label_offset_from_front, + upper_extent - top_label_depth]) + cube([top_label_width, top_label_height, + top_label_depth]); + } + + /* Top and side grooves, positioned in the back portion. */ + + union() { + + /* Left groove. */ - /* Edge connector cutout. */ + cube_at(groove_depth, groove_width_normal, height, + 1, 1, 0, + payload_left_extent, 0, 0); + + /* Right groove. */ + + cube_at(groove_depth, groove_width_normal, height, + -1, 1, 0, + payload_right_extent, 0, 0); - cube_at(edge_connector_cutout_back_width, - edge_connector_cutout_back_depth, - bottom, - 0, 1, 1, - 0, 0, lower_extent + int_connector_height); + /* Top grooves. */ + + cube_at(payload_width, groove_width_normal, groove_depth, + 0, 1, -1, + payload_centre, 0, upper_extent); + + cube_at(payload_width, top_groove_width, top_groove_depth, + 0, 1, -1, + payload_centre, -groove_width_extra, upper_extent); } - /* Extended floor. */ + /* Back cavity. */ - if (payload_width > connector_width) { + if (BACK_CAVITY) + intersection() { - difference() { + /* From the bottom upwards. */ - cube_at(payload_width - connector_width, back_depth, bottom, - 1, 1, 1, - payload_left_extent, 0, lower_extent + int_connector_height); + translate([0, back_depth, lower_extent]) + linear_extrude(height = back_cavity_height) + translate([-int_connector_width / 2, 0, 0]) + polygon([ + [back_cavity_offset_from_inner_left, 0], + [back_cavity_inner_offset_from_inner_left, + -back_cavity_depth], + [back_cavity_inner_offset_from_inner_left + + back_cavity_inner_width, + -back_cavity_depth], + [back_cavity_offset_from_inner_left + + back_cavity_width, 0] + ]); - cube_at(payload_width - connector_width, edge_connector_cutout_front_depth, bottom, - 1, 1, 1, - payload_left_extent, 0, lower_extent + int_connector_height); + /* From left to right. */ + + translate([back_cavity_width / 2, back_depth, lower_extent]) + rotate([0, -90, 0]) + linear_extrude(height = back_cavity_width) + polygon([ + [-extra, -back_cavity_depth], + [back_cavity_inner_height, + -back_cavity_depth], + [back_cavity_height, 0], + [-extra, 0] + ]); } - } + + /* Inner back cavities. */ + + translate([0, int_connector_back_depth, lower_extent]) + linear_extrude(height = int_connector_height) + translate([-int_connector_width / 2, 0, 0]) + polygon([ + [0, 0], + [inner_back_slope_max_offset, 0], + [inner_back_slope_min_offset, + inner_back_slope_depth], + [0, inner_back_slope_depth] + ]); - /* PCB supports. */ + translate([0, int_connector_back_depth, lower_extent]) + linear_extrude(height = int_connector_height) + translate([int_connector_width / 2, 0, 0]) + polygon([ + [0, 0], + [-inner_back_slope_max_offset, 0], + [-inner_back_slope_min_offset, + inner_back_slope_depth], + [0, inner_back_slope_depth] + ]); + + /* Inner back edge cavity. */ + + translate([inner_back_edge_width / 2, + int_connector_back_depth + inner_back_edge_depth, lower_extent]) + rotate([0, -90, 0]) + linear_extrude(height = inner_back_edge_width) + polygon([ + [-extra, -inner_back_edge_depth], + [inner_back_edge_height, -inner_back_edge_depth], + [0, 0], + [-extra, 0] + ]); + + /* Fillets to round off the edges. */ + + union() { - if (ROM_CARTRIDGE) { - pcb_support(-1, pcb_back_support_left_bump_height, - pcb_back_support_left_bump_offset_from_bottom); - pcb_support(1, pcb_back_support_right_bump_height, - pcb_back_support_right_bump_offset_from_bottom); + /* Top left and right rounding. */ + + translate([payload_left_extent + ro, back_depth / 2, upper_extent - ro]) + rotate([0, 0, 180]) + rotate([90, 0, 0]) + fillet(rr, back_depth); + translate([payload_right_extent - ro, back_depth / 2, upper_extent - ro]) + rotate([90, 0, 0]) + fillet(rr, back_depth); + + /* Top back rounding. */ + + translate([payload_centre, back_depth - ro, upper_extent - ro]) + rotate([0, -90, 0]) + fillet(rr, payload_width); + + /* Outer edge rounding. */ + + translate([payload_right_extent - ro, back_depth - ro, int_payload_lower_extent - bottom - extra]) + fillet_justified(rr, payload_height + bottom + extra); + + translate([payload_left_extent + ro, back_depth - ro, int_payload_lower_extent - bottom - extra]) + rotate([0, 0, 90]) + fillet_justified(rr, payload_height + bottom + extra); + + translate([connector_width / 2 - ro, back_depth - ro, lower_extent]) + fillet_partitioned(rr, connector_height - bottom); + + translate([-connector_width / 2 + ro, back_depth - ro, lower_extent]) + rotate([0, 0, 90]) + fillet_partitioned(rr, connector_height - bottom); - /* Circular "lugs" to hold PCBs in place. */ + /* + Outer edge rounding of the back extension. This is done as a + separate removal operation rather than occurring when creating the + extension in order to ensure that the edges are actually rounded. + + An extra overlapping measure is employed so that the filleting is + continuous between the payload and connector portions. On the outside + edges, the payload filleting is extended downwards. + */ + + translate([payload_left_extent + groove_depth + groove_ro, -groove_width_extra + groove_ro, + int_payload_lower_extent - extra]) + rotate([0, 0, 180]) + fillet_justified(groove_rr, inner_payload_front_cutout_height + extra); + + translate([payload_right_extent - groove_depth - groove_ro, -groove_width_extra + groove_ro, + int_payload_lower_extent - extra]) + rotate([0, 0, -90]) + fillet_justified(groove_rr, inner_payload_front_cutout_height + extra); - pcb_lug(-1); - pcb_lug(1); + /* Sides of connector. */ + + translate([-connector_width / 2 + groove_depth + groove_ro, -groove_width_extra + groove_ro, + lower_extent]) + rotate([0, 0, 180]) + fillet_partitioned(groove_rr, inner_connector_front_cutout_height); + + translate([connector_width / 2 - groove_depth - groove_ro, -groove_width_extra + groove_ro, + lower_extent]) + rotate([0, 0, -90]) + fillet_partitioned(groove_rr, inner_connector_front_cutout_height); + + /* Top of payload. */ + + translate([payload_centre, -groove_width_extra + groove_ro, + int_payload_upper_extent + inner_top_front_cutout_height - groove_ro]) + rotate([0, 0, 180]) + rotate([0, -90, 0]) + fillet(groove_rr, payload_width - groove_depth * 2); } } - /* Label insets. */ + /* PCBs for checking. */ + + if (PCB) if (MODEL == ROM_CARTRIDGE) { + translate([0, 0, int_payload_lower_extent]) + difference() { - union() { - - /* Top label. See also the front piece. */ + /* Mock PCB. */ - if (TOP_LABEL_INSET) - translate([top_label_left_extent, - -front_depth + top_label_offset_from_front, - upper_extent - top_label_depth]) - cube([top_label_width, top_label_height, - top_label_depth]); - } + union() { + cube_at(pcb_width, pcb_depth, + pcb_height - edge_connector_height, + 0, 1, 1, + 0, 0, 0); + cube_at(edge_connector_width, pcb_depth, + edge_connector_height, + 0, 1, -1, + 0, 0, 0); + } - /* Top and side grooves, positioned in the back portion. */ - - union() { - - /* Left groove. */ + /* Holes for mounting. */ - cube_at(groove_depth, groove_width_normal, height, - 1, 1, 0, - payload_left_extent, 0, 0); - - /* Right groove. */ - - cube_at(groove_depth, groove_width_normal, height, - -1, 1, 0, - payload_right_extent, 0, 0); + union() { + cube_at(pcb_hole_width, 1, pcb_left_hole_height, + 1, 1, 1, + pcb_left_hole_offset_from_centre, 0, pcb_left_hole_offset); + translate([pcb_left_hole_offset_from_centre + + pcb_hole_width / 2, pcb_hole_start_depth, pcb_left_hole_offset]) + rotate([-90, 0, 0]) + cylinder(h=pcb_hole_depth, r=pcb_hole_width / 2); + translate([pcb_left_hole_offset_from_centre + + pcb_hole_width / 2, pcb_hole_start_depth, + pcb_left_hole_offset + pcb_left_hole_height]) + rotate([-90, 0, 0]) + cylinder(h=pcb_hole_depth, r=pcb_hole_width / 2); + } - /* Top grooves. */ + union() { + cube_at(pcb_hole_width, 1, pcb_right_hole_height, + -1, 1, 1, + pcb_right_hole_offset_from_centre, 0, pcb_right_hole_offset); + translate([pcb_right_hole_offset_from_centre - + pcb_hole_width / 2, pcb_hole_start_depth, pcb_right_hole_offset]) + rotate([-90, 0, 0]) + cylinder(h=pcb_hole_depth, r=pcb_hole_width / 2); + translate([pcb_right_hole_offset_from_centre - + pcb_hole_width / 2, pcb_hole_start_depth, + pcb_right_hole_offset + pcb_right_hole_height]) + rotate([-90, 0, 0]) + cylinder(h=pcb_hole_depth, r=pcb_hole_width / 2); + } - cube_at(payload_width, groove_width_normal, groove_depth, - 0, 1, -1, - payload_centre, 0, upper_extent); + /* Holes for lugs. */ - cube_at(payload_width, top_groove_width, top_groove_depth, - 0, 1, -1, - payload_centre, -groove_width_extra, upper_extent); + translate([ + -int_connector_width / 2 + pcb_lug_offset_from_inside, + pcb_hole_start_depth, pcb_lug_offset_from_bottom]) + rotate([-90, 0, 0]) + cylinder(h=pcb_hole_depth, r=pcb_lug_hole_radius); + + translate([ + int_connector_width / 2 - pcb_lug_offset_from_inside, + pcb_hole_start_depth, pcb_lug_offset_from_bottom]) + rotate([-90, 0, 0]) + cylinder(h=pcb_hole_depth, r=pcb_lug_hole_radius); + } } - /* Back cavity. */ - - if (BACK_CAVITY) - intersection() { - - /* From the bottom upwards. */ + if (PCB) if (MODEL == WIDE_CARTRIDGE) { + translate([0, 0, int_payload_lower_extent]) + difference() { - translate([0, back_depth, lower_extent]) - linear_extrude(height = back_cavity_height) - translate([-int_connector_width / 2, 0, 0]) - polygon([ - [back_cavity_offset_from_inner_left, 0], - [back_cavity_inner_offset_from_inner_left, - -back_cavity_depth], - [back_cavity_inner_offset_from_inner_left + - back_cavity_inner_width, - -back_cavity_depth], - [back_cavity_offset_from_inner_left + - back_cavity_width, 0] - ]); - - /* From left to right. */ - - translate([back_cavity_width / 2, back_depth, lower_extent]) - rotate([0, -90, 0]) - linear_extrude(height = back_cavity_width) - polygon([ - [-extra, -back_cavity_depth], - [back_cavity_inner_height, - -back_cavity_depth], - [back_cavity_height, 0], - [-extra, 0] - ]); - } - - /* Inner back cavities. */ + /* Mock PCB. */ - translate([0, int_connector_back_depth, lower_extent]) - linear_extrude(height = int_connector_height) - translate([-int_connector_width / 2, 0, 0]) - polygon([ - [0, 0], - [inner_back_slope_max_offset, 0], - [inner_back_slope_min_offset, - inner_back_slope_depth], - [0, inner_back_slope_depth] - ]); + union() { + cube_at(wide_pcb_width, wide_pcb_depth, + wide_pcb_height - edge_connector_height, + 0, 1, 1, + payload_centre, 0, 0); + cube_at(edge_connector_width, wide_pcb_depth, + edge_connector_height, + 0, 1, -1, + 0, 0, 0); + } - translate([0, int_connector_back_depth, lower_extent]) - linear_extrude(height = int_connector_height) - translate([int_connector_width / 2, 0, 0]) - polygon([ - [0, 0], - [-inner_back_slope_max_offset, 0], - [-inner_back_slope_min_offset, - inner_back_slope_depth], - [0, inner_back_slope_depth] - ]); - - /* Inner back edge cavity. */ - - translate([inner_back_edge_width / 2, - int_connector_back_depth + inner_back_edge_depth, lower_extent]) - rotate([0, -90, 0]) - linear_extrude(height = inner_back_edge_width) - polygon([ - [-extra, -inner_back_edge_depth], - [inner_back_edge_height, -inner_back_edge_depth], - [0, 0], - [-extra, 0] - ]); - - /* Fillets to round off the edges. */ + /* Holes for lugs. */ - union() { + translate([ + payload_centre + int_payload_width / 2 - wide_pcb_lug_offset_from_inside , + wide_pcb_hole_start_depth, + wide_pcb_height - edge_connector_height - wide_pcb_lug_offset_from_bottom]) + rotate([-90, 0, 0]) + cylinder(h=wide_pcb_hole_depth, r=wide_pcb_lug_hole_radius); - /* Top left and right rounding. */ - - translate([payload_left_extent + ro, back_depth / 2, upper_extent - ro]) - rotate([0, 0, 180]) - rotate([90, 0, 0]) - fillet(rr, back_depth); - translate([payload_right_extent - ro, back_depth / 2, upper_extent - ro]) - rotate([90, 0, 0]) - fillet(rr, back_depth); - - /* Top back rounding. */ - - translate([payload_centre, back_depth - ro, upper_extent - ro]) - rotate([0, -90, 0]) - fillet(rr, payload_width); - - /* Outer edge rounding. */ - - translate([payload_right_extent - ro, back_depth - ro, int_payload_lower_extent - bottom - extra]) - fillet_justified(rr, payload_height + bottom + extra); - - translate([payload_left_extent + ro, back_depth - ro, int_payload_lower_extent - bottom - extra]) - rotate([0, 0, 90]) - fillet_justified(rr, payload_height + bottom + extra); - - translate([connector_width / 2 - ro, back_depth - ro, lower_extent]) - fillet_partitioned(rr, connector_height - bottom); - - translate([-connector_width / 2 + ro, back_depth - ro, lower_extent]) - rotate([0, 0, 90]) - fillet_partitioned(rr, connector_height - bottom); + translate([ + payload_centre - int_payload_width / 2 + wide_pcb_lug_offset_from_inside , + wide_pcb_hole_start_depth, + wide_pcb_height - edge_connector_height - wide_pcb_lug_offset_from_bottom]) + rotate([-90, 0, 0]) + cylinder(h=wide_pcb_hole_depth, r=wide_pcb_lug_hole_radius); - /* - Outer edge rounding of the back extension. This is done as a - separate removal operation rather than occurring when creating the - extension in order to ensure that the edges are actually rounded. - - An extra overlapping measure is employed so that the filleting is - continuous between the payload and connector portions. On the outside - edges, the payload filleting is extended downwards. - */ - - translate([payload_left_extent + groove_depth + groove_ro, -groove_width_extra + groove_ro, - int_payload_lower_extent - extra]) - rotate([0, 0, 180]) - fillet_justified(groove_rr, inner_payload_front_cutout_height + extra); - - translate([payload_right_extent - groove_depth - groove_ro, -groove_width_extra + groove_ro, - int_payload_lower_extent - extra]) - rotate([0, 0, -90]) - fillet_justified(groove_rr, inner_payload_front_cutout_height + extra); + translate([ + payload_centre + int_payload_width / 2 - wide_pcb_lug_offset_from_inside , + wide_pcb_hole_start_depth, + wide_pcb_lug_offset_from_bottom]) + rotate([-90, 0, 0]) + cylinder(h=wide_pcb_hole_depth, r=wide_pcb_lug_hole_radius); - /* Sides of connector. */ - - translate([-connector_width / 2 + groove_depth + groove_ro, -groove_width_extra + groove_ro, - lower_extent]) - rotate([0, 0, 180]) - fillet_partitioned(groove_rr, inner_connector_front_cutout_height); - - translate([connector_width / 2 - groove_depth - groove_ro, -groove_width_extra + groove_ro, - lower_extent]) - rotate([0, 0, -90]) - fillet_partitioned(groove_rr, inner_connector_front_cutout_height); - - /* Top of payload. */ - - translate([payload_centre, -groove_width_extra + groove_ro, - int_payload_upper_extent + inner_top_front_cutout_height - groove_ro]) - rotate([0, 0, 180]) - rotate([0, -90, 0]) - fillet(groove_rr, payload_width - groove_depth * 2); + translate([ + payload_centre - int_payload_width / 2 + wide_pcb_lug_offset_from_inside , + wide_pcb_hole_start_depth, + wide_pcb_lug_offset_from_bottom]) + rotate([-90, 0, 0]) + cylinder(h=wide_pcb_hole_depth, r=wide_pcb_lug_hole_radius); + } } } - - /* PCB for checking. */ - - pcb_width = 84.85; pcb_height = 62.5; pcb_depth = 1; - edge_connector_width = 56.5; edge_connector_height = 11.85; - pcb_position_y = int_payload_lower_extent; - - /* - The rectangular part of the narrow left and right holes is smaller - than the "bump" in the case, but the circular parts make the overall - hole larger than the "bump". An extra depth is used for holes to avoid - surface definition problems. - */ - - pcb_hole_margin = 0.55; - pcb_hole_width = 2.2; - pcb_hole_extra_depth = 0.1; - pcb_lug_hole_radius = 3.75; - - pcb_left_hole_offset = pcb_back_support_left_bump_offset_from_bottom + pcb_hole_margin; - pcb_left_hole_height = pcb_back_support_left_bump_height - pcb_hole_margin * 2; - pcb_left_hole_offset_from_centre = pcb_support_offset_from_centre + - pcb_back_support_width / 2 - pcb_hole_width / 2; - - pcb_right_hole_offset = pcb_back_support_right_bump_offset_from_bottom + pcb_hole_margin; - pcb_right_hole_height = pcb_back_support_right_bump_height - pcb_hole_margin * 2; - pcb_right_hole_offset_from_centre = -pcb_left_hole_offset_from_centre; - - pcb_hole_depth = pcb_depth + 2 * pcb_hole_extra_depth; - pcb_hole_start_depth = -pcb_hole_extra_depth; - - if (PCB) if (ROM_CARTRIDGE) { - translate([back_displacement, 0, 0]) - translate([0, 0, pcb_position_y]) - difference() { - - /* Mock PCB. */ - - union() { - cube_at(pcb_width, pcb_depth, - pcb_height - edge_connector_height, - 0, 1, 1, - 0, 0, 0); - cube_at(edge_connector_width, pcb_depth, - edge_connector_height, - 0, 1, -1, - 0, 0, 0); - } - - /* Holes for mounting. */ - - union() { - cube_at(pcb_hole_width, 1, pcb_left_hole_height, - 1, 1, 1, - pcb_left_hole_offset_from_centre, 0, pcb_left_hole_offset); - translate([pcb_left_hole_offset_from_centre + - pcb_hole_width / 2, pcb_hole_start_depth, pcb_left_hole_offset]) - rotate([-90, 0, 0]) - cylinder(h=pcb_hole_depth, r=pcb_hole_width / 2); - translate([pcb_left_hole_offset_from_centre + - pcb_hole_width / 2, pcb_hole_start_depth, - pcb_left_hole_offset + pcb_left_hole_height]) - rotate([-90, 0, 0]) - cylinder(h=pcb_hole_depth, r=pcb_hole_width / 2); - } - - union() { - cube_at(pcb_hole_width, 1, pcb_right_hole_height, - -1, 1, 1, - pcb_right_hole_offset_from_centre, 0, pcb_right_hole_offset); - translate([pcb_right_hole_offset_from_centre - - pcb_hole_width / 2, pcb_hole_start_depth, pcb_right_hole_offset]) - rotate([-90, 0, 0]) - cylinder(h=pcb_hole_depth, r=pcb_hole_width / 2); - translate([pcb_right_hole_offset_from_centre - - pcb_hole_width / 2, pcb_hole_start_depth, - pcb_right_hole_offset + pcb_right_hole_height]) - rotate([-90, 0, 0]) - cylinder(h=pcb_hole_depth, r=pcb_hole_width / 2); - } - - /* Holes for lugs. */ - - translate([ - -int_connector_width / 2 + pcb_lug_offset_from_inside, - pcb_hole_start_depth, pcb_lug_offset_from_bottom]) - rotate([-90, 0, 0]) - cylinder(h=pcb_hole_depth, r=pcb_lug_hole_radius); - - translate([ - int_connector_width / 2 - pcb_lug_offset_from_inside, - pcb_hole_start_depth, pcb_lug_offset_from_bottom]) - rotate([-90, 0, 0]) - cylinder(h=pcb_hole_depth, r=pcb_lug_hole_radius); - } - } } cartridge();