// ============================================================
// sim7600x_mount.scad — Waveshare SIM7600X 4G HAT Bracket
// Rev A  2026-03-01  sl-mechanical
// ============================================================
// Mounts the SIM7600X HAT near the Jetson Orin on the base plate.
//
// PCB: 65 × 56 mm, 4× M2.5 mounting holes (RPi HAT std pattern).
//
// SIM card access without disassembly:
//   The Y− edge of the bracket platform is fully open — a notch
//   in the floor plate is wider than the SIM tray so the card
//   inserts / ejects with the board fully installed.
//
// Base plate attachment: 4× M3 flat-head countersunk holes at
// bracket corners.  Drill M3 clearance holes in base plate and
// use M3 nyloc nuts underneath, or use captured M3 T-nuts.
//
// ⚠  VERIFY WITH CALIPERS BEFORE PRINTING:
//    HAT_L, HAT_W             PCB dimensions
//    HAT_HOLE_X, HAT_HOLE_Y   M2.5 hole spacing
//    HAT_HOLE_OX, HAT_HOLE_OY hole inset from PCB corners
//    SIM_X, SIM_W             SIM slot centre & width on Y− edge
//    USB_X, USB_W, USB_H      USB port on Y− edge
//
// RENDER options:
//   "assembly"     bracket + phantom PCB (default)
//   "bracket"      print-ready bracket
//   "bracket_2d"   floor projection → DXF for base-plate layout
// ============================================================

RENDER = "assembly";

// ── ⚠ Verify before printing ─────────────────────────────────
// Waveshare SIM7600X-H 4G HAT
HAT_L       = 65.0;   // PCB length (X)
HAT_W       = 56.0;   // PCB width  (Y) — SIM slot on Y=0 edge
HAT_H_BELOW =  3.0;   // tallest component on PCB underside (verify)

// RPi HAT standard M2.5 hole pattern
HAT_HOLE_X  = 58.0;   // X span between hole pairs
HAT_HOLE_Y  = 49.0;   // Y span between hole pairs
HAT_HOLE_OX =  3.5;   // hole inset from X− edge of PCB
HAT_HOLE_OY =  3.5;   // hole inset from Y− edge of PCB
M25_D       =  2.7;   // M2.5 clearance (loose, for alignment)
M25_OD      =  5.0;   // standoff post outer diameter

// SIM card slot (Y− edge, verify position from left/X− corner)
SIM_X       = 42.0;   // SIM slot centre from PCB X− edge
SIM_W       = 17.0;   // SIM slot width
SIM_H_NOTCH =  4.5;   // notch height for tray travel + eject pin

// USB Micro-B port (Y− edge, verify — may differ by HAT version)
USB_X       = 11.0;   // USB port centre from PCB X− edge
USB_W       = 10.5;   // USB port width
USB_H       =  7.0;   // USB port height

// u.FL pigtail exit slot (Y+ wall)
UFL_SLOT_W  = 12.0;
UFL_SLOT_H  =  5.0;

// ── Bracket geometry ─────────────────────────────────────────
STNDFF_H    = HAT_H_BELOW + 4.0;   // standoff height (clears underside)
PLAT_T      =  3.5;   // floor plate thickness
WALL_T      =  2.5;   // side wall thickness

PAD_X       =  5.0;   // platform extends PAD_X beyond PCB on X± sides
PAD_Y_PLUS  =  8.0;   // platform extends PAD_Y_PLUS beyond PCB on Y+ side
// Y− side: open (no wall, no floor overhang) — SIM/USB access

PLAT_L      = HAT_L + 2 * PAD_X;
PLAT_W      = HAT_W + PAD_Y_PLUS;   // Y− edge flush with PCB Y=0

// PCB sits with Y=0 edge flush with bracket Y=0 face
PCB_X0      = PAD_X;   // X offset of PCB within bracket

// M3 base-plate mounting holes
M3_D        =  3.4;
M3_CS_D     =  6.2;   // flat-head countersink diameter
M3_CS_H     =  3.0;   // countersink depth (from bottom face)
M3_INSET    =  5.0;   // hole inset from bracket corner

// Side wall height (for cable containment)
WALL_H      = STNDFF_H + 4.0;

$fn = 48;
e   = 0.01;

// ─────────────────────────────────────────────────────────────
module sim7600x_bracket() {
    difference() {
        union() {
            // ── Floor plate ──────────────────────────────────
            cube([PLAT_L, PLAT_W, PLAT_T]);

            // ── Side walls: X−, X+, Y+ only (Y− open) ───────
            translate([0, 0, 0])
                cube([WALL_T, PLAT_W, WALL_H]);
            translate([PLAT_L - WALL_T, 0, 0])
                cube([WALL_T, PLAT_W, WALL_H]);
            translate([0, PLAT_W - WALL_T, 0])
                cube([PLAT_L, WALL_T, WALL_H]);

            // ── M2.5 standoff posts (×4) ─────────────────────
            for (hx=[0, HAT_HOLE_X], hy=[0, HAT_HOLE_Y])
                translate([PCB_X0 + HAT_HOLE_OX + hx,
                           HAT_HOLE_OY + hy,
                           PLAT_T])
                    cylinder(d=M25_OD, h=STNDFF_H);
        }

        // ── M2.5 clearance bores through standoffs ───────────
        for (hx=[0, HAT_HOLE_X], hy=[0, HAT_HOLE_Y])
            translate([PCB_X0 + HAT_HOLE_OX + hx,
                       HAT_HOLE_OY + hy, -e])
                cylinder(d=M25_D, h=PLAT_T + STNDFF_H + e);

        // ── SIM card access notch (Y− face of floor) ─────────
        // Notch 4 mm wider than SIM slot each side
        translate([PCB_X0 + SIM_X - SIM_W/2 - 4, -e, -e])
            cube([SIM_W + 8, WALL_T + e, PLAT_T + SIM_H_NOTCH + e]);

        // ── USB port access notch (Y− face of X− wall) ───────
        translate([PCB_X0 + USB_X - USB_W/2, -e,
                   PLAT_T + STNDFF_H/2 - USB_H/2])
            cube([USB_W, WALL_T + 2*e, USB_H]);

        // ── u.FL pigtail exit slot (Y+ wall, upper zone) ─────
        translate([PLAT_L/2 - UFL_SLOT_W/2,
                   PLAT_W - WALL_T - e,
                   PLAT_T + STNDFF_H - UFL_SLOT_H])
            cube([UFL_SLOT_W, WALL_T + 2*e, UFL_SLOT_H + e]);

        // ── M3 base-plate mounting holes (×4, countersunk) ───
        for (cx=[M3_INSET, PLAT_L - M3_INSET])
            for (cy=[M3_INSET, PLAT_W - M3_INSET]) {
                translate([cx, cy, -e])
                    cylinder(d=M3_D, h=PLAT_T + 2*e);
                // Countersink from bottom face
                translate([cx, cy, -e])
                    cylinder(d1=M3_CS_D, d2=M3_D,
                             h=M3_CS_H + e);
            }

        // ── Cable relief notch in X+ wall ────────────────────
        translate([PLAT_L - WALL_T - e, PLAT_W * 0.35, PLAT_T + 2])
            cube([WALL_T + 2*e, 9, 5]);
    }
}

// ─────────────────────────────────────────────────────────────
if (RENDER == "assembly") {
    color("DimGray", 0.92) sim7600x_bracket();
    // Phantom PCB
    color("ForestGreen", 0.3)
        translate([PCB_X0, 0, PLAT_T + STNDFF_H])
            cube([HAT_L, HAT_W, 1.6]);
    // SIM access marker (yellow arrow zone)
    color("Gold", 0.7)
        translate([PCB_X0 + SIM_X - 10, -8, 0])
            cube([20, 8, 2]);

} else if (RENDER == "bracket") {
    sim7600x_bracket();

} else if (RENDER == "bracket_2d") {
    projection(cut=true)
        translate([0, 0, -PLAT_T/2])
            sim7600x_bracket();
}
