<commit_before>// preview[view:northeast, tilt:topdiagonal]

/* [Options] */
// Pit probe type
Control_Probe = "Thermocouple"; // [Thermocouple,Thermistor,None]
// Raspberry Pi Model
Pi_Model = "3B/2B/1B+"; // [3B/2B/1B+,Connectorless,1A+,Zero,3A+]
// Which case halves
Pieces = "Both"; // [Both,Top,Bottom]
// Include cutouts and mounts for LCD/Buttons
LCD = 1; // [0:None,1:2-line]
// Thickness of side walls (mm) - Set to trace width multiple
wall = 2.0;
/* [Advanced] */
// Thickness of top and bottom faces (mm)
wall_t = 1.45;
// Height of the body edge bead chamfer (mm)
body_chamfer_height = 1.5;
// Corner ear height (mm) - 0 to disable
MouseEarHeight = 0;
// Corner leg height (mm) - 0 to disable
MouseLegHeight = 0; //body_chamfer_height/2;
// Screw hardware
NutHardware = 2; // [0:Captive Nut,1:5mm Injection Threaded Insert,2:Threaded Insert]

/* [Hidden] */
// External corner radius on the body (mm)
body_corner_radius = wall*2-1/2;
w_off = 0.5; // offset the heatermeter origin from the left edge
d_off = 2.0; // offset the heatermeter origin from the front edge
w = inch(3.725)+0.7+w_off; // overall interior case width
d = inch(3.75)+1.0+d_off; // overall interior case depth
// 19.1+ headless Zero
// 22.4 headless Pi3 (limited by nuttrapps interfering with PCB to -6.7)
// 32 standard
h_b = [32.5-6.7, 32.5][LCD];  // overall interior case height

probe_centerline = 9.3; // case is split along probe centerline on the probe side
case_split = 12.4;  // and the case split on the other 3 sides

pic_ex = 1.7;
lcd_mount_t = 8.2 - (wall_t - 0.8);
pi_screw_t = 2.3;

body_chamfer_height_t = body_chamfer_height;
body_chamfer_height_b = body_chamfer_height;

led_dia = 2.9;
led_h = 4.6 - 1;
led_fudge = 0.3; // total extra diameter to expand the hole and head sphere
led_inset = 0.5; // amount to extend LED through case

e = 0.01;
is_jig = 0; // generate a jig for soldering LEDs

function inch(x) = x*25.4;

echo(str("Case dimensions (mm): ", w+2*wall, "x", d+2*wall, "x", h_b+2*wall_t));
main();

module main()
{
  if (is_jig) {
    intersection() {
      hm43_split();
      translate([wall+6,-d-wall+3,-e]) cube([w-12,d-8,15]);
    }

    difference() {
      cube([w-12,d-8,8 - wall_t]);
      translate([wall,wall,-e]) cube([w-12-2*wall, d-8-2*wall, 8 - wall_t +2*e]);
    }
  } /* is_jig */
  else
    hm43_split();
}

module cube_fillet_chamfer(size,f,c,$fn=32) {
  hull() {
    translate([f,f,c]) linear_extrude(height=size[2]-2*c) minkowski() {
      square([size[0]-2*f, size[1]-2*f]);
      circle(r=f, $fn=$fn);
    }
    translate([f+c,f+c,0]) linear_extrude(height=size[2]) minkowski() {
      square([size[0]-2*(f+c), size[1]-2*(f+c)]);
      circle(r=f, $fn=$fn);
    }
  }
}

module jhole(d, h) {
  translate([0,0,h/2]) cube([2*(wall+pic_ex),d,h], center=true);
}

module phole() {
  dia=4.5;
  // Hole for thermistor probe jack
  rotate([0,90,0]) cylinder(2*wall, d=dia, $fn=16);
  // because 3d print tends to curl up slightly between the probe holes,
  // do not go right to the edge on the final layer (stop 0.25mm short on each side)
  translate([0,-(dia+0.5)/2, -0.3]) cube([2*wall, dia+0.5, 0.6]);
}

module screwhole() {
  rotate(90) translate([0,0,-e]) cylinder(3.5, d=6, $fn=18);
}

module pic_ex_cube(interior) {
  translate([0,33.75+interior*(pic_ex+1.3),2])
    cube_fillet([pic_ex+e, 59.8-interior*(pic_ex*2+1.3+1.5), 20.8], 
      vertical=[0, (1-interior)*pic_ex, (1-interior)*pic_ex, 0],
      top=[0,pic_ex,0,0],
      bottom=[0,pic_ex,0,0]);
}

module screw_pimount() {
  cylinder(wall_t+pi_screw_t, d=6.4, $fn=18);
  // alignment nubbies
  //cylinder(wall_t+pi_screw_t+1.4, d=2.4, $fn=12);
}

module screw_keyhole() {
  d=6.2;
  d2=3.5;
  off=4.15; // ideally would be D but runs into edge of case
  h=3;
  
  cylinder(wall_t+2*e, d=d, $fn=18);
  translate([-d2/2,0,0]) cube([d2,off,wall_t+2*e]);
  translate([0,off,0]) {
    cylinder(wall_t+2*e, d=d2, $fn=18);
    translate([0,0,wall_t+e]) cylinder(h+e, d=d, $fn=18);
  }
}

module screw_keyhole_p() {
  d=6.2+wall;
  h=2.3;
  
  difference() {
    cylinder(wall_t+h, d=d, $fn=18);
    translate([0,0,-e]) cylinder(wall_t+h+2*e, d=d-wall, $fn=18);
    translate([-d,0,-e]) cube([d*2, d/2, wall_t+h+2*e]);
  }
}

module btn_rnd() {
  dia = is_jig ? 6.0 : 7.2; // TPU button covers was 8.0
  cylinder(wall_t+2*e, d1=dia, d2=dia+1.5*wall_t, $fn=24);
  translate([-6.5,-6.5,0]) cube([13,13,0.5+e]);
}

module tc_plusminus() {
  T=0.75+e;
  H=2;
  W=6;
  // Minus
  translate([0,2,0]) 
    cube_fillet([T, W, H], top=[0,0,0,T]);
  translate([0,-(2+W),0]) {
    cube_fillet([T, W, H], top=[0,0,0,T]);
    translate([0,(W-H)/2,(H-W)/2])
      cube_fillet([T, H, W], top=[0,0,0,T]);
  }
}

module led() {
  translate([0, 0, -(led_h+1)]) {
    cylinder(1, d=led_dia+0.3+led_fudge, $fn=24);
    translate([0, 0, 1-e]) cylinder(led_h-led_dia/2+e, d=led_dia+led_fudge, $fn=24);
    translate([0, 0, 1+led_h-led_dia/2]) sphere(d=led_dia+led_fudge, $fn=24);
  }
}

module led_pillar() {
  translate([0,0,-led_h-e])
    cylinder(led_h-led_inset, d=led_dia+led_fudge+2*wall, $fn=24);
}

module nuttrap() {
  ww_w=3;
  ww_d=wall;
  nut_h=3.2;
  nut_ingress = 5.7;
  nut_d = nut_ingress / sin(60);
  nut_ingress_off = nut_ingress/sqrt(3)/2;
  oa_h=wall_t+0.4+nut_h+wall_t+[0,6.7][LCD];
  screw_l=[20,25][LCD];

  // bottom half for M3 socket cap screw (flush)
  difference() {
    translate([-5.5/2-ww_w, -nut_ingress/2-d_off-e, 0])
      cube_fillet([5.5+2*ww_w, nut_ingress+d_off+ww_d, 6], vertical=[3.4,3.4], $fn=20);
    // socket cap
    rotate(90) translate([0,0,-e]) cylinder(3.5, d=6, $fn=18);
    // screw shaft
    translate([0,0,3.5+0.3]) cylinder(oa_h-3, d=3.4, $fn=16);
    // rectangular hole to remove some of the solid layer material
    translate([-5.7/2, -(6*PI/18)/2, 0]) cube([5.7, 6*PI/18, 3.5+0.3+e]);
  }
  
  // top half M3 nut trap
  if (NutHardware == 0) { // Captive Nut Slots
    translate([0,0,h_b+wall_t-oa_h])
    difference() {
      translate([-(nut_d/2+ww_w), -nut_ingress/2-d_off, 0])
        cube_fillet([nut_d+2*ww_w, nut_ingress+d_off+ww_d, oa_h+e],
          vertical=[ww_d/2,3.4], $fn=20);
      // M3 screw
      translate([0,0,-e]) cylinder(wall_t, d1=4, d2=3.4, $fn=16);
      // nut hole / M3 extra
      translate([0,0,wall_t+0.3]) {
        // nut 2x for an elongated trap
        translate([-0.2,0,0]) cylinder(nut_h*1.5+e, d=nut_d, $fn=6);
        translate([+0.2,0,0]) cylinder(nut_h*1.5+e, d=nut_d, $fn=6);
        cylinder(oa_h-wall_t-0.3, d=4, $fn=16);  // M3 with plenty of clearance
        //translate([-50,-50,-100]) cube([100,100,100+e]); // cutaway top
      }
      // nut ingress (sideways trapezoid with wider side at ingress)
      translate([nut_ingress_off,-nut_ingress/2,wall_t+0.3])
         linear_extrude(nut_h+e) polygon([[0,0],
           [nut_d/2+ww_w-nut_ingress_off+0.4+e, -0.8],       
           [nut_d/2+ww_w-nut_ingress_off+0.4+e, nut_ingress+0.8],
           [0,nut_ingress]]);
    }
  } else if (NutHardware == 1 || NutHardware == 2) { // Threaded inserts
    // 5mm injected molding threaded insert (M3 x 5.4 x 5.2 tall)
    // 5.0mm dia 5mm tall, with 5.6mm alignment area at top 1.2mm tall
    // Threaded insert (M3 x 4.6 x 5.7 tall)
    // 4.3mm dia 5.5mm tall, with 4.8mm alignment area at top 1.2mm tall
    nhd = [[5.0, 5.0, 5.6], [4.3, 5.5, 4.8]][NutHardware-1];
    translate([0,0,h_b+wall_t-(h_b-screw_l+2)])
    difference() {
      union() {
        cylinder((h_b-screw_l)+2, d=nhd[0]+2*wall, $fn=24);
        cylinder(1.2-e, d1=nhd[2]+2*wall, d2=nhd[0]+2*wall, $fn=24);
        translate([(nhd[0]+2*wall)/-2, -nut_ingress/2-d_off, 0])
          cube([nhd[0]+2*wall, nut_ingress/2+d_off, (h_b-screw_l)+2]);
      }
      cylinder(nhd[1]+1.2, d=nhd[0], $fn=24);
      translate([0,0,-e]) cylinder(1.2, d1=nhd[2], d2=nhd[0], $fn=24); // alignment helper
    }
  }
}

module locklip_p(l, l_offset=0,
  lip_insert_depth=2.0, // how deep V to insert
  lip_v_off=0.2, // extra height before starting insert
  lip_h_off=0.4, // back connector away from mating area
  lip_w=2.5,  // thickness of attachment beam
  insert_inset=[0,0] // inset the insert inside mating area
  ) {
  translate([l_offset,0,0]) rotate([90,0,90])
    difference() {
      linear_extrude(l-2*l_offset, convexity=11) polygon(points=[
        [0.1, -lip_w-lip_insert_depth-lip_h_off],  // 0.1 to add depth to keep extrusion manifold
        [-lip_w-lip_insert_depth-lip_h_off, 0],
        [-lip_w-lip_insert_depth-lip_h_off, lip_v_off+2*lip_insert_depth],
        [-lip_insert_depth-lip_h_off, lip_v_off+2*lip_insert_depth,],
        [-lip_h_off, lip_v_off+lip_insert_depth],
        [-lip_insert_depth-lip_h_off, lip_v_off],
        [-lip_insert_depth-lip_h_off, 0],
        [0.1, 0]
      ]);
      translate([-lip_w-lip_insert_depth-lip_h_off-e, 0, 0]) {
        if (insert_inset[0] > 0)
          translate([0,0,-e])
            cube([lip_w+lip_insert_depth+lip_h_off+0.1+2*e,
              lip_v_off+2*lip_insert_depth+e, insert_inset[0]+e]);
        if (insert_inset[1] > 0)
          translate([0, 0, l-2*l_offset-insert_inset[1]])
            cube([lip_w+lip_insert_depth+lip_h_off+0.1+2*e,
              lip_v_off+2*lip_insert_depth+e, insert_inset[1]+e]);
      }
    }
}

module locklip_n(l, l_offset=0,
  lip_insert_depth=2.2, // how deep V to insert
  lip_tip_clip=0.3, // how much to shave off the top tip
  ) {
  translate([l-l_offset,0,0]) rotate([90,0,0]) rotate([0,-90,0]) 
    linear_extrude(height=l-2*l_offset) polygon(points=[
      [0.1, -3*lip_insert_depth],  // 0.1 to add depth to keep extrusion manifold
      [0.1, -lip_tip_clip],
      [-lip_insert_depth+lip_tip_clip, -lip_tip_clip],
      [-e, -lip_insert_depth],
      [-lip_insert_depth, -2*lip_insert_depth]
    ]);
}

module lcd_screw() {
  rotate([180]) difference() {
    //cylinder(lcd_mount_t, d=2.5+3.2, $fn=16);
    cylinder(lcd_mount_t+e, d=2.5, $fn=16);
  }
}

module lcd_mount() {
  // Assuming starting at bottom left screw hole
  //lcd_screw(); 
  //translate([75,0,0]) lcd_screw(); // bottom right hole obscured by PCB
  translate([0,31,0]) lcd_screw();
  translate([75,31,0]) lcd_screw();
}

module lcd_neg() {
  // Assuming starting at bottom left screw hole
  // (Note LCD is not centered vertically on PCB, top is 5.15, bottom is 4.55mm)
  translate([1.0, 1.55, 0])
    cube([73.0, 27.3, lcd_mount_t+wall_t-0.8]); // black bezel inset
  translate([5.5, 7.5, 0])
    cube([64.0, 15.4, lcd_mount_t+wall_t+2*e]); // LCD active area
  //translate([4.23, -2.5, 0])
  //  cube([16*2.54, 5, lcd_mount_t+wall_t-0.8]); // pins cutout
}

module locklip_top_n(split) {
  translate([wall, d+wall, split+wall_t+e])
    rotate([180]) {
      locklip_n(28);
      translate([w-34,0,0]) locklip_n(34);
    }
}

module hm_base() {
  cube_bchamfer([w+2*wall, d+2*wall, h_b+2*wall_t], 
    r=body_corner_radius, top=body_chamfer_height_t, 
    bottom=body_chamfer_height_b, $fn=36);
  // extra thick by Pi connectors
  if (Pi_Model != "Zero" && Pi_Model != "1A+" && Pi_Model != "3A+")
    translate([-pic_ex,wall+d_off,wall_t])
      pic_ex_cube(0);
  // TC +/-
  if (Control_Probe == "Thermocouple")
    translate([w+wall*2-e,wall+d_off+10,wall_t+19]) tc_plusminus();

  // Eliminate the chamfer where the screws are
  translate([wall+inch(0.825)+0.5,wall+d_off+inch(0.1),0]) {
    cylinder(body_chamfer_height_b, d=6+2*wall, $fn=24);
    translate([inch(2.0),0,0]) cylinder(body_chamfer_height_b, d=6+2*wall, $fn=24);
  }
}

module hm43() {
difference() {
  union() {
    difference() {
      hm_base();

      // Main cutout
      translate([wall, wall, wall_t])
        cube_fillet([w, d, h_b],
          bottom=[pi_screw_t,pi_screw_t,pi_screw_t,pi_screw_t],
          top=[pi_screw_t,pi_screw_t,pi_screw_t,pi_screw_t],
          vertical=[body_corner_radius/2,body_corner_radius/2,body_corner_radius/2,body_corner_radius/2],
          $fn=[36,4,4]);
      if (Pi_Model != "Zero" && Pi_Model != "1A+" && Pi_Model != "3A+")
        translate([wall-pic_ex+e,wall+d_off,wall_t]) pic_ex_cube(1);
    } // main diff

    if (LCD) translate([wall+inch(1.925)+w_off, wall+d_off+inch(1.15), h_b+2*wall_t])
      translate([inch(1.3), inch(-0.05), led_inset]) {
        led_pillar();  //red
        translate([0, inch(0.35), 0]) led_pillar(); //yellow
        translate([0, inch(0.70), 0]) led_pillar(); //green
      }
  } // main union

  // Probe jack side
  translate([w+wall*0.5, wall+d_off, wall_t+probe_centerline]) {
    // Probe jacks
    if (Control_Probe == "Thermocouple")
      // TC jack
      translate([0,inch(0.4)-16.5/2,-1.1]) cube([2*wall, 16.5, 6.5]);
    else if (Control_Probe == "Thermistor")
      translate([0,inch(0.28),0]) phole();
    if (Control_Probe != "None") {
      translate([0,inch(0.95)+inch(0.37)*0,0]) phole();
      translate([0,inch(0.95)+inch(0.37)*1,0]) phole();
      translate([0,inch(0.95)+inch(0.37)*2,0]) phole();
    }
  }
  // Pi connector side  
  translate([0,wall+d_off,wall_t]) {
    // Pi connectors
    translate([0,0,5]) {
      if (Pi_Model == "3B/2B/1B+") {
        // ethernet
        translate([0,81.5,-0.8]) jhole(15,13);
        translate([0,81.5,-1.8]) jhole(5,5);
        // USB 0+1
        translate([0,62.75,0]) jhole(13,14.8);<commit_msg>[3d] Add ThermistorJack option for 4.3.6 PCB<commit_after>// preview[view:northeast, tilt:topdiagonal]

/* [Options] */
// Pit probe type
Control_Probe = "Thermocouple"; // [Thermocouple,Thermistor,None]
// Raspberry Pi Model
Pi_Model = "3B/2B/1B+"; // [3B/2B/1B+,Connectorless,1A+,Zero,3A+]
// Which case halves
Pieces = "Both"; // [Both,Top,Bottom]
// Probe mono jack type (MJ1 is the smaller new one for 4.3.6)
ThermistorJack = 1; // [0:MJ-2508N,1:MJ1-2503A]
// Include cutouts and mounts for LCD/Buttons
LCD = 1; // [0:None,1:2-line]
// Thickness of side walls (mm) - Set to trace width multiple
wall = 2.0;
/* [Advanced] */
// Thickness of top and bottom faces (mm)
wall_t = 1.45;
// Height of the body edge bead chamfer (mm)
body_chamfer_height = 1.5;
// Corner ear height (mm) - 0 to disable
MouseEarHeight = 0;
// Corner leg height (mm) - 0 to disable
MouseLegHeight = 0; //body_chamfer_height/2;
// Screw hardware
NutHardware = 2; // [0:Captive Nut,1:5mm Injection Threaded Insert,2:Threaded Insert]

/* [Hidden] */
// External corner radius on the body (mm)
body_corner_radius = wall*2-1/2;
w_off = 0.5; // offset the heatermeter origin from the left edge
d_off = 2.0; // offset the heatermeter origin from the front edge
w = inch(3.725)+0.7+w_off; // overall interior case width
d = inch(3.75)+1.0+d_off; // overall interior case depth
// 19.1+ headless Zero
// 22.4 headless Pi3 (limited by nuttrapps interfering with PCB to -6.7)
// 32 standard
h_b = [32.5-6.7, 32.5][LCD];  // overall interior case height

probe_centerline = 9.3+([0, 3.0][ThermistorJack]); // case is split along probe centerline on the probe side
case_split = 12.3;  // and the case split on the other 3 sides (12.4 ideal?)

pic_ex = 1.7;
lcd_mount_t = 8.2 - (wall_t - 0.8);
pi_screw_t = 2.3;

body_chamfer_height_t = body_chamfer_height;
body_chamfer_height_b = body_chamfer_height;

led_dia = 2.9;
led_h = 4.6 - 1;
led_fudge = 0.3; // total extra diameter to expand the hole and head sphere
led_inset = 0.5; // amount to extend LED through case

e = 0.01;
is_jig = 0; // generate a jig for soldering LEDs

function inch(x) = x*25.4;

echo(str("Case dimensions (mm): ", w+2*wall, "x", d+2*wall, "x", h_b+2*wall_t));
main();

module main()
{
  if (is_jig) {
    intersection() {
      hm43_split();
      translate([wall+6,-d-wall+3,-e]) cube([w-12,d-8,15]);
    }

    difference() {
      cube([w-12,d-8,8 - wall_t]);
      translate([wall,wall,-e]) cube([w-12-2*wall, d-8-2*wall, 8 - wall_t +2*e]);
    }
  } /* is_jig */
  else
    hm43_split();
}

module cube_fillet_chamfer(size,f,c,$fn=32) {
  hull() {
    translate([f,f,c]) linear_extrude(height=size[2]-2*c) minkowski() {
      square([size[0]-2*f, size[1]-2*f]);
      circle(r=f, $fn=$fn);
    }
    translate([f+c,f+c,0]) linear_extrude(height=size[2]) minkowski() {
      square([size[0]-2*(f+c), size[1]-2*(f+c)]);
      circle(r=f, $fn=$fn);
    }
  }
}

module jhole(d, h) {
  translate([0,0,h/2]) cube([2*(wall+pic_ex),d,h], center=true);
}

module phole() {
  dia=4.5;
  // Hole for thermistor probe jack
  rotate([0,90,0]) cylinder(2*wall, d=dia, $fn=16);
  // because 3d print tends to curl up slightly between the probe holes,
  // do not go right to the edge on the final layer (stop 0.25mm short on each side)
  translate([0,-(dia+0.5)/2, -0.3]) cube([2*wall, dia+0.5, 0.6]);
}

module screwhole() {
  rotate(90) translate([0,0,-e]) cylinder(3.5, d=6, $fn=18);
}

module pic_ex_cube(interior) {
  translate([0,33.75+interior*(pic_ex+1.3),2])
    cube_fillet([pic_ex+e, 59.8-interior*(pic_ex*2+1.3+1.5), 20.8], 
      vertical=[0, (1-interior)*pic_ex, (1-interior)*pic_ex, 0],
      top=[0,pic_ex,0,0],
      bottom=[0,pic_ex,0,0]);
}

module screw_pimount() {
  cylinder(wall_t+pi_screw_t, d=6.4, $fn=18);
  // alignment nubbies
  //cylinder(wall_t+pi_screw_t+1.4, d=2.4, $fn=12);
}

module screw_keyhole() {
  d=6.2;
  d2=3.5;
  off=4.15; // ideally would be D but runs into edge of case
  h=3;
  
  cylinder(wall_t+2*e, d=d, $fn=18);
  translate([-d2/2,0,0]) cube([d2,off,wall_t+2*e]);
  translate([0,off,0]) {
    cylinder(wall_t+2*e, d=d2, $fn=18);
    translate([0,0,wall_t+e]) cylinder(h+e, d=d, $fn=18);
  }
}

module screw_keyhole_p() {
  d=6.2+wall;
  h=2.3;
  
  difference() {
    cylinder(wall_t+h, d=d, $fn=18);
    translate([0,0,-e]) cylinder(wall_t+h+2*e, d=d-wall, $fn=18);
    translate([-d,0,-e]) cube([d*2, d/2, wall_t+h+2*e]);
  }
}

module btn_rnd() {
  dia = is_jig ? 6.0 : 7.2; // TPU button covers was 8.0
  cylinder(wall_t+2*e, d1=dia, d2=dia+1.5*wall_t, $fn=24);
  translate([-6.5,-6.5,0]) cube([13,13,0.5+e]);
}

module tc_plusminus() {
  T=0.75+e;
  H=2;
  W=6;
  // Minus
  translate([0,2,0]) 
    cube_fillet([T, W, H], top=[0,0,0,T]);
  translate([0,-(2+W),0]) {
    cube_fillet([T, W, H], top=[0,0,0,T]);
    translate([0,(W-H)/2,(H-W)/2])
      cube_fillet([T, H, W], top=[0,0,0,T]);
  }
}

module led() {
  translate([0, 0, -(led_h+1)]) {
    cylinder(1, d=led_dia+0.3+led_fudge, $fn=24);
    translate([0, 0, 1-e]) cylinder(led_h-led_dia/2+e, d=led_dia+led_fudge, $fn=24);
    translate([0, 0, 1+led_h-led_dia/2]) sphere(d=led_dia+led_fudge, $fn=24);
  }
}

module led_pillar() {
  translate([0,0,-led_h-e])
    cylinder(led_h-led_inset, d=led_dia+led_fudge+2*wall, $fn=24);
}

module nuttrap() {
  ww_w=3;
  ww_d=wall;
  nut_h=3.2;
  nut_ingress = 5.7;
  nut_d = nut_ingress / sin(60);
  nut_ingress_off = nut_ingress/sqrt(3)/2;
  oa_h=wall_t+0.4+nut_h+wall_t+[0,6.7][LCD];
  screw_l=[20,25][LCD];

  // bottom half for M3 socket cap screw (flush)
  difference() {
    translate([-5.5/2-ww_w, -nut_ingress/2-d_off-e, 0])
      cube_fillet([5.5+2*ww_w, nut_ingress+d_off+ww_d, 6], vertical=[3.4,3.4], $fn=20);
    // socket cap
    rotate(90) translate([0,0,-e]) cylinder(3.5, d=6, $fn=18);
    // screw shaft
    translate([0,0,3.5+0.3]) cylinder(oa_h-3, d=3.4, $fn=16);
    // rectangular hole to remove some of the solid layer material
    translate([-5.7/2, -(6*PI/18)/2, 0]) cube([5.7, 6*PI/18, 3.5+0.3+e]);
  }
  
  // top half M3 nut trap
  if (NutHardware == 0) { // Captive Nut Slots
    translate([0,0,h_b+wall_t-oa_h])
    difference() {
      translate([-(nut_d/2+ww_w), -nut_ingress/2-d_off, 0])
        cube_fillet([nut_d+2*ww_w, nut_ingress+d_off+ww_d, oa_h+e],
          vertical=[ww_d/2,3.4], $fn=20);
      // M3 screw
      translate([0,0,-e]) cylinder(wall_t, d1=4, d2=3.4, $fn=16);
      // nut hole / M3 extra
      translate([0,0,wall_t+0.3]) {
        // nut 2x for an elongated trap
        translate([-0.2,0,0]) cylinder(nut_h*1.5+e, d=nut_d, $fn=6);
        translate([+0.2,0,0]) cylinder(nut_h*1.5+e, d=nut_d, $fn=6);
        cylinder(oa_h-wall_t-0.3, d=4, $fn=16);  // M3 with plenty of clearance
        //translate([-50,-50,-100]) cube([100,100,100+e]); // cutaway top
      }
      // nut ingress (sideways trapezoid with wider side at ingress)
      translate([nut_ingress_off,-nut_ingress/2,wall_t+0.3])
         linear_extrude(nut_h+e) polygon([[0,0],
           [nut_d/2+ww_w-nut_ingress_off+0.4+e, -0.8],       
           [nut_d/2+ww_w-nut_ingress_off+0.4+e, nut_ingress+0.8],
           [0,nut_ingress]]);
    }
  } else if (NutHardware == 1 || NutHardware == 2) { // Threaded inserts
    // 5mm injected molding threaded insert (M3 x 5.4 x 5.2 tall)
    // 5.0mm dia 5mm tall, with 5.6mm alignment area at top 1.2mm tall
    // Threaded insert (M3 x 4.6 x 5.7 tall)
    // 4.3mm dia 5.5mm tall, with 4.8mm alignment area at top 1.2mm tall
    nhd = [[5.0, 5.0, 5.6], [4.3, 5.5, 4.8]][NutHardware-1];
    translate([0,0,h_b+wall_t-(h_b-screw_l+2)])
    difference() {
      union() {
        cylinder((h_b-screw_l)+2, d=nhd[0]+2*wall, $fn=24);
        cylinder(1.2-e, d1=nhd[2]+2*wall, d2=nhd[0]+2*wall, $fn=24);
        translate([(nhd[0]+2*wall)/-2, -nut_ingress/2-d_off, 0])
          cube([nhd[0]+2*wall, nut_ingress/2+d_off, (h_b-screw_l)+2]);
      }
      cylinder(nhd[1]+1.2, d=nhd[0], $fn=24);
      translate([0,0,-e]) cylinder(1.2, d1=nhd[2], d2=nhd[0], $fn=24); // alignment helper
    }
  }
}

module locklip_p(l, l_offset=0,
  lip_insert_depth=2.0, // how deep V to insert
  lip_v_off=0.2, // extra height before starting insert
  lip_h_off=0.4, // back connector away from mating area
  lip_w=2.5,  // thickness of attachment beam
  insert_inset=[0,0] // inset the insert inside mating area
  ) {
  translate([l_offset,0,0]) rotate([90,0,90])
    difference() {
      linear_extrude(l-2*l_offset, convexity=11) polygon(points=[
        [0.1, -lip_w-lip_insert_depth-lip_h_off],  // 0.1 to add depth to keep extrusion manifold
        [-lip_w-lip_insert_depth-lip_h_off, 0],
        [-lip_w-lip_insert_depth-lip_h_off, lip_v_off+2*lip_insert_depth],
        [-lip_insert_depth-lip_h_off, lip_v_off+2*lip_insert_depth,],
        [-lip_h_off, lip_v_off+lip_insert_depth],
        [-lip_insert_depth-lip_h_off, lip_v_off],
        [-lip_insert_depth-lip_h_off, 0],
        [0.1, 0]
      ]);
      translate([-lip_w-lip_insert_depth-lip_h_off-e, 0, 0]) {
        if (insert_inset[0] > 0)
          translate([0,0,-e])
            cube([lip_w+lip_insert_depth+lip_h_off+0.1+2*e,
              lip_v_off+2*lip_insert_depth+e, insert_inset[0]+e]);
        if (insert_inset[1] > 0)
          translate([0, 0, l-2*l_offset-insert_inset[1]])
            cube([lip_w+lip_insert_depth+lip_h_off+0.1+2*e,
              lip_v_off+2*lip_insert_depth+e, insert_inset[1]+e]);
      }
    }
}

module locklip_n(l, l_offset=0,
  lip_insert_depth=2.2, // how deep V to insert
  lip_tip_clip=0.3, // how much to shave off the top tip
  ) {
  translate([l-l_offset,0,0]) rotate([90,0,0]) rotate([0,-90,0]) 
    linear_extrude(height=l-2*l_offset) polygon(points=[
      [0.1, -3*lip_insert_depth],  // 0.1 to add depth to keep extrusion manifold
      [0.1, -lip_tip_clip],
      [-lip_insert_depth+lip_tip_clip, -lip_tip_clip],
      [-e, -lip_insert_depth],
      [-lip_insert_depth, -2*lip_insert_depth]
    ]);
}

module lcd_screw() {
  rotate([180]) difference() {
    //cylinder(lcd_mount_t, d=2.5+3.2, $fn=16);
    cylinder(lcd_mount_t+e, d=2.5, $fn=16);
  }
}

module lcd_mount() {
  // Assuming starting at bottom left screw hole
  //lcd_screw(); 
  //translate([75,0,0]) lcd_screw(); // bottom right hole obscured by PCB
  translate([0,31,0]) lcd_screw();
  translate([75,31,0]) lcd_screw();
}

module lcd_neg() {
  // Assuming starting at bottom left screw hole
  // (Note LCD is not centered vertically on PCB, top is 5.15, bottom is 4.55mm)
  translate([1.0, 1.55, 0])
    cube([73.0, 27.3, lcd_mount_t+wall_t-0.8]); // black bezel inset
  translate([5.5, 7.5, 0])
    cube([64.0, 15.4, lcd_mount_t+wall_t+2*e]); // LCD active area
  //translate([4.23, -2.5, 0])
  //  cube([16*2.54, 5, lcd_mount_t+wall_t-0.8]); // pins cutout
}

module locklip_top_n(split) {
  translate([wall, d+wall, split+wall_t+e])
    rotate([180]) {
      locklip_n(28);
      translate([w-34,0,0]) locklip_n(34);
    }
}

module hm_base() {
  cube_bchamfer([w+2*wall, d+2*wall, h_b+2*wall_t], 
    r=body_corner_radius, top=body_chamfer_height_t, 
    bottom=body_chamfer_height_b, $fn=36);
  // extra thick by Pi connectors
  if (Pi_Model != "Zero" && Pi_Model != "1A+" && Pi_Model != "3A+")
    translate([-pic_ex,wall+d_off,wall_t])
      pic_ex_cube(0);
  // TC +/-
  if (Control_Probe == "Thermocouple")
    translate([w+wall*2-e,wall+d_off+10,wall_t+19]) tc_plusminus();

  // Eliminate the chamfer where the screws are
  translate([wall+inch(0.825)+0.5,wall+d_off+inch(0.1),0]) {
    cylinder(body_chamfer_height_b, d=6+2*wall, $fn=24);
    translate([inch(2.0),0,0]) cylinder(body_chamfer_height_b, d=6+2*wall, $fn=24);
  }
}

module hm43() {
difference() {
  union() {
    difference() {
      hm_base();

      // Main cutout
      translate([wall, wall, wall_t])
        cube_fillet([w, d, h_b],
          bottom=[pi_screw_t,pi_screw_t,pi_screw_t,pi_screw_t],
          top=[pi_screw_t,pi_screw_t,pi_screw_t,pi_screw_t],
          vertical=[body_corner_radius/2,body_corner_radius/2,body_corner_radius/2,body_corner_radius/2],
          $fn=[36,4,4]);
      if (Pi_Model != "Zero" && Pi_Model != "1A+" && Pi_Model != "3A+")
        translate([wall-pic_ex+e,wall+d_off,wall_t]) pic_ex_cube(1);
    } // main diff

    if (LCD) translate([wall+inch(1.925)+w_off, wall+d_off+inch(1.15), h_b+2*wall_t])
      translate([inch(1.3), inch(-0.05), led_inset]) {
        led_pillar();  //red
        translate([0, inch(0.35), 0]) led_pillar(); //yellow
        translate([0, inch(0.70), 0]) led_pillar(); //green
      }
  } // main union

  // Probe jack side
  translate([w+wall*0.5, wall+d_off, wall_t+probe_centerline]) {
    // Probe jacks
    if (Control_Probe == "Thermocouple")
      // TC jack
      translate([0,inch(0.4)-16.5/2,-1.1-([0, 3.0][ThermistorJack])]) cube([2*wall, 16.5, 6.5]);
    else if (Control_Probe == "Thermistor")
      translate([0,inch(0.28),0]) phole();
    if (Control_Probe != "None") {
      translate([0,inch(0.95)+inch(0.37)*0,0]) phole();
      translate([0,inch(0.95)+inch(0.37)*1,0]) phole();
      translate([0,inch(0.95)+inch(0.37)*2,0]) phole();
    }
  }
  // Pi connector side  
  translate([0,wall+d_off,wall_t]) {
    // Pi connectors
    translate([0,0,5]) {
      if (Pi_Model == "3B/2B/1B+") {
        // ethernet
        translate([0,81.5,-0.8]) jhole(15,13);
        translate([0,81.5,-1.8]) jhole(5,5);
        // USB 0+1
        translate([0,62.75,0]) jhole(13,14.8);
{'fraction_non_alphanumeric': 0.1943673591839796, 'fraction_numerical': 0.06708917722943074, 'mean_word_length': 3.292129406084017, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4694134', 'n_tokens_mistral': 12485, 'n_tokens_neox': 11642, 'n_words': 2114}