// Fire TV Cube under-TV clamp shelf — parametric
// Units: mm.  Axes: X = left/right, Y = front(-) to back(+), Z = up.
// The TV's bottom edge sits at Z = 0; the TV's front face is at Y = 0.
//
// Parts:  2 x clamp hook   (print lying flat, profile on the bed)
//         1 x cradle       (print upright, floor on the bed)
//         2 x knob screw   (print knob-down, threads vertical)
//         2 x jaw nut      (print flat; press into the hex pocket from the TV side of each rear jaw)
// The clamp is all printed: big knurled knob screw + printed nut, no metal.
// Hardware left: 4x M5x20 button-head bolt + 4x M5 hex nut (cradle -> hooks, slotted fore/aft)
//                felt / rubber pads on every surface touching the TV (incl. screw tips)

/* [Measure your TV] */
tv_depth      = 26;   // UN65D8000 measured ~1" at the clamp height (spec 1.2"); screw covers ~15-36 mm
front_lip_h   = 50;   // front lip height on the bezel. UN65D8000 has ~2.25" (57 mm) of frame below the picture
lip_t         = 10;   // front lip thickness
gusset        = 15;   // brace where the lip meets the arm (front side)
rear_gap      = 10;   // space between TV back and rear jaw (knob screw closes it; ~0-20 mm range)

/* [Fire TV Cube] */
cube_w        = 86;   // 86.1 x 86.1 x 76.9 (all gens)
cube_h        = 77;
cube_clear    = 2;    // per side
top_clear     = 8;    // air + mic/button clearance above the Cube

/* [Clamp hook] */
T             = 7;    // bar / lip thickness
jaw_t         = 14;   // rear jaw thickness (holds the printed nut)
jaw_h         = 75;   // rear jaw height above TV bottom (tall: TV back is stepped, clamp must sit 2"+ up)
hook_w        = 16;   // width of each hook (X)
leg_len       = 36;   // hanger leg length below the bar
leg_d         = 40;   // hanger leg depth (Y)

/* [Printed clamp screw] */
thr_r0        = 7;    // eccentric-circle thread: major dia = 2*(r0+e) = 16, minor = 12
thr_e         = 1;
thr_p         = 3;    // pitch
thr_clr       = 0.35; // radial clearance nut vs screw (raise to 0.45 if tight)
thr_len       = 36;   // threaded length
knob_d        = 45;   // big knurled knob
knob_h        = 18;
knurls        = 24;
nut_af        = 23.6; // printed nut across flats
nut_len       = 10;
pocket_af     = 24.0; // hex pocket in the jaw
boss_w        = 32;   // jaw boss width (X) that houses the nut
bolt_d        = 5.5;  // M5 clearance
nut_af_m5     = 8.3;  // M5 hex nut is 8.0 across flats, 4.0 thick
nut_pocket_d  = 4.5;  // pocket depth from the leg's outer face (bolt: 3 mm wall under head + 16 mm leg; tip ends ~1 mm proud)

/* [Cradle] */
wall          = 6;    // side walls thick enough to recess the bolt heads
head_d        = 10.5; // M5 button head is 9.5 dia, 2.75 tall
head_recess   = 3.0;
floor_t       = 3;
front_lip     = 8;
back_lip      = 5;
cable_notch_w = 60;
stick_out     = 100;  // how far the cradle's front sits in front of the TV screen (98 = Cube fully in front)

$fn = 48;

// ---------- derived ----------
inner      = cube_w + 2*cube_clear;
outer_w    = inner + 2*wall;
outer_d    = inner + 2*wall;
floor_top  = -T - top_clear - cube_h;
wall_top   = -T - 1;
c          = outer_d/2 - stick_out;   // cradle center (Y); slots give +/-8 more
bar_y0     = min(-T, c - leg_d/2);   // bar becomes a forward arm when the cradle sticks out
bar_y1     = tv_depth + rear_gap + jaw_t;
jaw_y0     = tv_depth + rear_gap;
screw_z    = 55;      // knob screw contact ~2.2" above the TV bottom edge (user: min 2")
screw_x    = boss_w/2;
leg_z0     = -T - leg_len;
bolt_z     = -T - leg_len/2 - 2;
bolt_dy    = 12;

module hex(af, h) { cylinder(d = af / cos(30), h = h, $fn = 6); }

// ---------- clamp hook (one side; profile in the YZ plane, extruded in X) ----------
module hook() {
  difference() {
    union() {
      translate([0, bar_y0, -T])        cube([boss_w, bar_y1 - bar_y0, T]);         // bar/arm under TV, full 32 mm wide
      translate([0, -lip_t, -T])        cube([boss_w, lip_t, T + front_lip_h]);     // tall front lip (on the bezel)
      translate([0, -lip_t, 0]) rotate([90,0,90]) linear_extrude(boss_w)            // gusset in front of the lip
        polygon([[0,0], [-gusset,0], [0,gusset]]);
      translate([0, jaw_y0, -T])        cube([boss_w, jaw_t, T + jaw_h]);           // rear jaw, full boss width for stiffness
      translate([0, jaw_y0, screw_z - 17]) cube([boss_w, jaw_t, 34]);                 // nut boss
      translate([0, c - leg_d/2, leg_z0]) cube([hook_w, leg_d, leg_len + T - 1]);  // hanger leg
    }
    // clearance hole for the screw + hex pocket for the printed nut. The pocket opens toward the TV;
    // a 3.6 mm wall on the knob side takes the clamping load (the TV pushes the screw + nut backward)
    translate([screw_x, jaw_y0 - 1, screw_z]) rotate([-90,0,0]) cylinder(d = 2*(thr_r0 + thr_e) + 0.8, h = jaw_t + 2);
    translate([screw_x, jaw_y0 - 1, screw_z]) rotate([-90,0,0]) rotate([0,0,30]) hex(pocket_af, nut_len + 1.4);  // flat on top when printed = clean bridge, no support
    // two M5 holes through the leg (X direction) + hex nut pockets on the outer face
    for (dy = [-bolt_dy, bolt_dy]) {
      translate([-1, c + dy, bolt_z]) rotate([0,90,0]) cylinder(d = bolt_d, h = hook_w + 2);
      translate([hook_w - nut_pocket_d, c + dy, bolt_z]) rotate([0,90,0]) hex(nut_af_m5, nut_pocket_d + 1);
    }
  }
}

// ---------- printed thread (single-start eccentric-circle thread: smooth, prints well) ----------
module thread(r0, L) {
  linear_extrude(height = L, twist = -360 * L / thr_p, slices = ceil(L / thr_p * 36))
    translate([thr_e, 0]) circle(r = r0, $fn = 64);
}

// knob screw: knob on the bed, threads up; flat chamfered tip (stick a felt dot on it)
module knob_screw() {
  R = knob_d / 2;
  difference() {
    intersection() {
      cylinder(r = R, h = knob_h, $fn = 96);
      union() {                                                        // 2 mm chamfers top and bottom
        cylinder(r1 = R - 2, r2 = R + knob_h/2 - 2, h = knob_h/2 + 0.01, $fn = 96);
        translate([0,0,knob_h/2]) cylinder(r1 = R + knob_h/2 - 2, r2 = R - 2, h = knob_h/2, $fn = 96);
      }
    }
    for (i = [0 : knurls - 1]) rotate([0, 0, i * 360 / knurls]) translate([R, 0, -1]) cylinder(r = 2.5, h = knob_h + 2, $fn = 24);
  }
  translate([0, 0, knob_h]) intersection() {
    thread(thr_r0, thr_len);
    cylinder(r1 = thr_r0 + thr_e + thr_len - 1, r2 = thr_r0 + thr_e - 1, h = thr_len, $fn = 64);  // tip lead-in
  }
}

// printed nut: hex, pressed into the jaw pocket
module jaw_nut() {
  difference() {
    hex(nut_af, nut_len);
    translate([0, 0, -0.01]) thread(thr_r0 + thr_clr, nut_len + 0.02);
    translate([0, 0, -0.01]) cylinder(r1 = thr_r0 + thr_e + 1, r2 = thr_r0 + thr_e - 1, h = 2);  // entry chamfer
  }
}

// ---------- cradle ----------
module cradle() {
  y0 = c - outer_d/2;
  difference() {
    union() {
      translate([-outer_w/2, y0, floor_top - floor_t]) cube([outer_w, outer_d, floor_t]);                    // floor
      for (sx = [-1, 1]) translate([sx > 0 ? inner/2 : -outer_w/2, y0, floor_top - floor_t])
        cube([wall, outer_d, wall_top - floor_top + floor_t]);                                           // side walls
      translate([-outer_w/2, y0, floor_top - floor_t]) cube([outer_w, wall, floor_t + front_lip]);          // front lip
      translate([-outer_w/2, y0 + outer_d - wall, floor_top - floor_t]) cube([outer_w, wall, floor_t + back_lip]);
    }
    // cable notch in the back lip
    translate([-cable_notch_w/2, y0 + outer_d - wall - 1, floor_top]) cube([cable_notch_w, wall + 2, back_lip + 1]);
    // vent slots in the floor
    for (i = [-3:3]) translate([i*11 - 2.5, c - 30, floor_top - floor_t - 1]) cube([5, 60, floor_t + 2]);
    // side-wall windows (airflow, less plastic)
    // straight sides, then a 45-degree roof to a 16 mm flat top, so no long bridge when printed
    for (sx = [-1, 1]) translate([sx*(inner/2 + wall/2) - wall, 0, 0]) rotate([90,0,90]) linear_extrude(wall*2)
      polygon([[c-30, floor_top+7], [c+30, floor_top+7], [c+30, floor_top+27],
               [c+8, floor_top+49], [c-8, floor_top+49], [c-30, floor_top+27]]);
    // slotted M5 holes (+/- 8 mm fore/aft adjustment)
    for (sx = [-1, 1], dy = [-bolt_dy, bolt_dy])
      hull() for (s = [-8, 8])
        translate([sx*(inner/2 + wall/2) - wall, c + dy + s, bolt_z]) rotate([0,90,0]) cylinder(d = bolt_d, h = wall*2);
    // recess so the button heads sit flush on the inside (clear of the Cube)
    for (sx = [-1, 1], dy = [-bolt_dy, bolt_dy])
      hull() for (s = [-8, 8])
        translate([sx > 0 ? inner/2 - 1 : -inner/2 - head_recess, c + dy + s, bolt_z]) rotate([0,90,0]) cylinder(d = head_d, h = head_recess + 1);
  }
}

// ---------- layout ----------
part = "assembly";   // [assembly, hook, cradle, knob_screw, jaw_nut]

if (part == "hook")   rotate([0,-90,0]) hook();       // profile flat on the bed
if (part == "cradle") translate([0,0,-(floor_top - floor_t)]) cradle();
if (part == "knob_screw") knob_screw();
if (part == "jaw_nut")    jaw_nut();
if (part == "assembly") {
  cradle();
  translate([ outer_w/2, 0, 0]) hook();
  translate([-outer_w/2, 0, 0]) mirror([1,0,0]) hook();
  for (sx = [-1, 1]) {
    xs = sx * (outer_w/2 + screw_x);
    translate([xs, jaw_y0 + 0.2, screw_z]) rotate([-90,0,0]) rotate([0,0,30]) jaw_nut();
    translate([xs, jaw_y0 + jaw_t + 12 + knob_h, screw_z]) rotate([90,0,0]) knob_screw();
  }
  %translate([-300, 0, 0]) cube([600, tv_depth, 120]);                                   // TV ghost
  %translate([-cube_w/2, c - cube_w/2, floor_top]) cube([cube_w, cube_w, cube_h]);       // Cube ghost
}
