// Config ///////////////////////
///////////////////////////////////

battery = true;

// No battery
//battery_z = 3.3+0.5;

// 700mAh battery
//battery_z = 5+0.5;

// 1000mAh battery
battery_z = 11.3+0.5;

// Render
render_case_top = false;
render_case_bottom = true;
render_battery_door = false;
render_powerswitch = false;
render_led_window = false;
render_led_guide = false;
render_sma = false;

render_device_model = false;
render_debug_model = false;

flat_sma = false;

// Constants ///////////////////
///////////////////////////////////

battery_door = battery;
pcb_w = 27.4;
pcb_h = 64.8;
pcb_t = 1.47;
trx_module_h = 2.7;

// Battery size
battery_x = 25.5;
battery_y = 51;

battery_depth = pcb_t+trx_module_h+0.65;
b_offset = 6.5;
b_shelf_l = 37.81;

//bc_z = 3.85;
bc_z = 4.15;
highest_component = bc_z;

sidewall_extend = 2.2;
case_wt = 1.6 + 1.5 + sidewall_extend;
case_bt = 2.1;

top_case_t = 4.5;

hull_x = pcb_w+2*case_wt;
hull_y = pcb_h+2*case_wt;
hull_z = pcb_t+(highest_component-0.2)+case_bt;

bat_end = battery_depth+battery_z;
bottom_thickness = 0.2+0.15*14;
bat_extra = bat_end - hull_z + bottom_thickness;

use_bat_door_screws = false;

e_mrg = 0.1;

n1_d = 5.65;
n1_h = 2.2;
n2_h = 2.1;
n2_h_extra_backspacing = 0.5;
n2_h_extra_frontspacing = 1.0;
n2_d = 9.24;
// Added 2.75 to original to allow for ring and nut
sma_slide_adjust = 2.75*1;
sma_spacing = 13.75;
sma_pos_x = pcb_w/2 - n2_d/2 - 0.75;
sma_pos_y = pcb_h/2 + sma_spacing+0;
//sma_pos_z = -hull_z+(8/2)-0.5;
sma_pos_z = -2.5;

neopixel_offset_x = 0;
neopixel_offset_y = 2.8+2.55+0;
neopixel_depth = 2+0.45;

// Switch and button params
reset_v_adjust = 0.0;
power_v_adjust = -0.15;
power_pl_t = 0.9;
    
sw_py = 5.7;
sw_x = 4.6;
sw_y = 9.2;
sw_z = 3.75;

rb_py = 21.0;
rb_x = 4.6;
rb_y = 2.5;
rb_fy = 8;
rb_z = 2.5;

// Used in calculating hull boundaries
pd=1;
sma_shorten_thr = 3.3;
sma_align = pcb_h+sma_spacing+n1_h+n2_h-pd+case_wt+sma_shorten_thr;
sma_center = pcb_w/2+sma_pos_x;
hull_end = -case_wt+hull_x;
delta_x = hull_end-sma_center;

module prism(l, w, h){polyhedron(points=[[0,0,0], [l,0,0], [l,w,0], [0,w,0], [0,w,h], [l,w,h]],faces=[[0,1,2,3],[5,4,3,2],[0,4,5,1],[0,3,4],[5,2,1]]);}
module rcube(x=0, y=0, z=0, r=0, n=4, x_axis=false, y_axis=false) {
    cn = n*4;
    module pcx() {rotate([0,90,0]) cylinder(r=r, h=x, $fn=cn);}
    module pcy() {rotate([90,0,0]) cylinder(r=r, h=y, $fn=cn);}
    module pc() {rotate([0,0,0]) cylinder(r=r, h=z, $fn=cn);}
    if (!y_axis && x_axis) {
        hull() {
            translate([0,r,r]) pcx();
            translate([0,r,z-r]) pcx();
            translate([0,y-r,r]) pcx();
            translate([0,y-r,z-r]) pcx();
        }
    }
    if (y_axis && ! x_axis) {
        hull() {
            translate([r,y,r]) pcy();
            translate([r,y,z-r]) pcy();
            translate([x-r,y,r]) pcy();
            translate([x-r,y,z-r]) pcy();
        }
    }
    if (!y_axis && ! x_axis) {
        
        hull() {
            translate([r,r,0]) pc();
            translate([x-r,r,0]) pc();
            translate([r,y-r,0]) pc();
            translate([x-r,y-r,0]) pc();
        }
    }
}


 // Actual measured height of bolts + 0.2mm
scr_h = 10;
scr_d = 1.9;
module screw() {
    h1_d = 4.1;
    h2_d = 4.1;
    h3_d = 1.9;
    hs_h = 1;
    h_h = 1.65;
    h_sink = 0.1;
    sfn = 16;
    
    translate([0,0,h_sink]) cylinder(d=scr_d, h=scr_h, $fn=sfn);
    translate([0,0,0]) cylinder(d1=h1_d, d2=h2_d, h=h_h+h_sink, $fn=sfn);
    
    translate([0,0,h_h+h_sink]) cylinder(d1=h2_d, d2=h3_d, h=hs_h, $fn=sfn);
}
module mounting_holes() {
    mh_d = top_case_t+0.05;
    //scr_h = highest_component+mh_d;
   
    //translate([pcb_w-2.25, 2.25, -mh_d]) screw();
    
    ant_m_ofs = 6;
    ant_y_ofs = 10.5;
    // Antenna left
    translate([pcb_w-sma_center+ant_m_ofs, sma_align-ant_y_ofs, -mh_d]) screw();
    
    // Antenna right
    translate([pcb_w-sma_center-ant_m_ofs, sma_align-ant_y_ofs, -mh_d]) screw();
    
    // Body top left
    translate([pcb_w-2.25+1, pcb_h-2.25-0.5, -mh_d]) screw();
    
    // Body top right
    translate([2.32+1, pcb_h-2.25-0.5, -mh_d]) screw();
    
    m_ofs = 3.25;
    scr_xofs=m_ofs;
    scr_yofs = m_ofs;
    // Near SD
    translate([-case_wt+scr_d/2+scr_xofs, -(case_wt-sidewall_extend)+scr_d/2+scr_yofs, -mh_d]) screw();
    
    // Near USB
    translate([pcb_w+case_wt-scr_d/2-scr_xofs, -(case_wt-sidewall_extend)+scr_d/2+scr_yofs, -mh_d]) screw();
}

module fixpoints() {
    fp_spacing = 2;
    fp_zm = 1.3;
    fp_ym = 1.5;
    fp_w = 3.5;
    fp_h = 3.5;
    fp_s = sqrt((fp_h*fp_h)/2);
    cut_margin = 0.01;
    // Extra width
    //ew = 0.0;
    
    translate([pcb_w+case_wt+cut_margin, pcb_h-fp_ym, fp_zm]) {
        translate([0,-fp_w,0]) rotate([45,0,90]) prism(fp_w, fp_s, fp_s);
        translate([0,-fp_w*2-fp_spacing,0]) rotate([45,0,90]) prism(fp_w, fp_s, fp_s);
    }
    
    rotate([0,180,0]) translate([case_wt+cut_margin, pcb_h-fp_ym, -fp_h-fp_zm]) {
        translate([0,-fp_w,0]) rotate([45,0,90]) prism(fp_w, fp_s, fp_s);
        translate([0,-fp_w*2-fp_spacing,0]) rotate([45,0,90]) prism(fp_w, fp_s, fp_s);
    }
}

module positioned_board_bounds() {
    bounds = 100;
    translate([-pcb_w/2, -pcb_h/2, -bounds/2]) cube([pcb_w, pcb_h, bounds]);
}
module device() {
    union() {
        pcb(); //done
        sd(); //done
        antennas(); // done
        usb_conn(); // done
        led_guide();
        switches(); // done
        //batcon();
        mcu(); //done
        keepout(); //done
        disp_pm();
        disp();
        mounting_holes();
        if (battery) {
            bat();
        }
    }
}

module bat() {
    b_x = battery_x;
    b_y = battery_y;
    b_z = battery_z;
    b_depth = battery_depth;

    if (battery) {
        if (false) {
            // Version with internal overhang shelf
            color("red") translate([pcb_w/2-b_x/2, b_offset, b_depth]) cube([b_x, b_y, b_z]);
        } else {
            color("red") translate([pcb_w/2-b_x/2, b_offset]) cube([b_x, b_shelf_l, b_z+b_depth]);
            color("red") translate([pcb_w/2-b_x/2, b_offset, 0]) cube([b_x, b_y, b_z+b_depth]);
        }
    }
}

module pcb() {
    color("darkgreen") cube([pcb_w, pcb_h, pcb_t]);
}

module led_guide(g_h = 1.0) {
    catch_t = 0.4;
    g_w = case_wt+0.05+0.25;
    g_l = 6;
    g_o = 1.5;
    translate([0*-5, 1.5, 0]) color("cyan") difference() {
        translate([-g_w,2,-1]) cube([g_w+g_o, g_l, g_h]);
        translate([0,2,-1+catch_t]) cube([g_o, g_l, g_h-catch_t]);
    }
}
module usb_conn() {
    su_x = 10.0;
    su_y = 26;
    su_z = 3.1;
    
    usb_y = 8.6;
    usb_sink = 0.6;
    
    sw_x = su_x;
    sw_y = 5;
    sw_z = 2;
    
    pm_x = 14.5;
    pm_y = 13;
    pm_z = 2.65;
    
    // Port cavity
    color("silver") translate([1.8,0,-su_z-0.2]) cube([su_y-2.75, su_x, su_z+usb_sink]);
    
    // IC gap
    color("silver") translate([9.2,6,-su_z]) cube([6.2, 20, su_z+usb_sink]);
    
    // Board LED
    color("silver") translate([pcb_w-4,14,-0.75]) cube([4, 6, 0.75]);
    
    // Power LEDs
    color("silver") translate([0,2,-1]) cube([4, 9, 1]);
    
    // USB
    color("silver") translate([15.8+0.35,-2*case_wt,-su_z]) rcube(usb_y, su_x+2*case_wt, su_z+usb_sink, 1, y_axis=true);
    
    // PMU ICs
    //color("silver") translate([su_x,0,-pm_z]) cube([pm_x, pm_y, pm_z]);
}

module reset_button(movement_margin=false) {
    plt_extra = 0.45;
    
    rbb_w = 3.5;
    rbb_h = 1.6;
    pl_w = rb_y+0.5;
    pl_h = rb_z+0.5;
    pl_t = 0.3;
    translate([0, 0,0]) {
        difference() {
            union() {
                color("orange") translate([pcb_w,rb_py,pcb_t]) rcube(case_wt-0.5, rb_y, rb_z, 1, x_axis=true);
                if (movement_margin == true) {
                    color("orange") translate([pcb_w,rb_py-0.25,pcb_t-0.25]) cube([pl_t+plt_extra, pl_w, pl_h]);
                } else {
                    color("orange") translate([pcb_w,rb_py-0.25,pcb_t-0.25]) cube([pl_t, pl_w, pl_h]);
                }
            }
            translate([-0.1+pcb_w,rb_py+rb_y/2-rbb_w/2,pcb_t+rb_z/2-rbb_h/2]) cube([0.6, rbb_w, rbb_h]);
        }
    }
}

module power_switch(slide_cutout=false, ridges=true) {
    stick_out = 1-0.35;
    slide_l = 2.5;
    slide_m = 0.5;
    peg_d = 1.77;
    peg_ofx = 2.5;
    pl_t = power_pl_t;
    
    peg_l = 5;
    insert_d = 2.3;
    
    slide_fit_margin = 0.1;
    fit_margin = 0.3;
    
    slide_t = slide_l+slide_m;
    translate([0,0,power_v_adjust]) {
        difference() {
            union() {
                if (slide_cutout == true) {
                    color("orange") translate([pcb_w-pl_t,sw_py-slide_t+slide_m/2,pcb_t]) cube([pl_t, sw_y+slide_t, sw_z]);
                } else {
                    color("orange") translate([pcb_w-pl_t+0.1,sw_py-slide_t+slide_m/2,pcb_t+slide_fit_margin/2]) cube([pl_t, sw_y+slide_t, sw_z-slide_fit_margin]);
                }
                
                color("orange") translate([pcb_w,sw_py,pcb_t+fit_margin/2]) rcube(case_wt+stick_out, sw_y-slide_l, sw_z-fit_margin, 1, x_axis=true);
            }
            
            color("silver") translate([pcb_w-(pl_t+peg_l)+insert_d,sw_py+peg_ofx,pcb_t+sw_z/2-peg_d/2]) cube([peg_l, peg_d, peg_d]);
            rdg_ofs = -0.14;
            rdg_spc = 3.4;
            rdg_snk = 1.25;
            cube_s= 4;
            
            if (ridges) {
                translate([pcb_w-pl_t+0.1+case_wt+stick_out+cube_s-rdg_snk,sw_py-slide_t+slide_m/2+rdg_ofs+rdg_spc*0,pcb_t+slide_fit_margin/2-1]) rotate([0,0,45]) cube([cube_s,cube_s,6]);
                translate([pcb_w-pl_t+0.1+case_wt+stick_out+cube_s-rdg_snk,sw_py-slide_t+slide_m/2+rdg_ofs+rdg_spc*1,pcb_t+slide_fit_margin/2-1]) rotate([0,0,45]) cube([cube_s,cube_s,6]);
                translate([pcb_w-pl_t+0.1+case_wt+stick_out+cube_s-rdg_snk,sw_py-slide_t+slide_m/2+rdg_ofs+rdg_spc*2,pcb_t+slide_fit_margin/2-1]) rotate([0,0,45]) cube([cube_s,cube_s,6]);
                translate([3.3,0, (sw_z-slide_fit_margin)/2]) {
                translate([pcb_w-pl_t+0.1+case_wt+stick_out,sw_py-slide_t+slide_m/2,pcb_t+slide_fit_margin/2]) rotate([0,45*5,0]) cube([pl_t, sw_y+slide_t, sw_z-slide_fit_margin]);
                translate([pcb_w-pl_t+0.1+case_wt+stick_out,sw_py-slide_t+slide_m/2,pcb_t+slide_fit_margin/2]) rotate([0,45*5,0]) cube([sw_z-slide_fit_margin, sw_y+slide_t, pl_t]);
                }
            }
            
        }
    }
}

module switches() {
    // Power Switch
    sl_ext = 6.8;
    color("orange") translate([pcb_w-sw_x+power_pl_t+0.05,sw_py-sl_ext/2,pcb_t+power_v_adjust-0.2]) cube([sw_x+0.15, sw_y+sl_ext, sw_z+0.40]);
    color("silver") translate([pcb_w-sw_x,sw_py,pcb_t+power_v_adjust]) rcube(sw_x+2*case_wt, sw_y, sw_z, 1, x_axis=true);
    
    // Reset button
    color("silver") translate([pcb_w-sw_x,rb_py+rb_y/2-rb_fy/2,pcb_t-0.25]) cube([rb_x, rb_fy+0.5, rb_z+0.5]);
    color("silver") translate([pcb_w-sw_x,rb_py,pcb_t+reset_v_adjust]) rcube(rb_x+2*case_wt, rb_y, rb_z, 1, x_axis=true);
}

module disp() {
    disp_x = 16.75;
    disp_y = 25;
    disp_z = 3.4;
    inactive_margin = 3.4;
    
    f_height = 3.1-disp_z;
    offset_x = 3.3-2+0.5;
    pos_y = 20.85+4.3;
    
    module disp_cutout_boundaries() {
        cutout = 1.25;
        ch = 2;
        rd_d = 1;
        cfn = 12;
        i = inactive_margin;
        c = cutout;
        a_x = disp_x - i;
        translate([c,c,-ch]) cylinder(d=rd_d, h=ch, $fn=cfn);
        translate([a_x-c,c,-ch]) cylinder(d=rd_d, h=ch, $fn=cfn);
        translate([a_x-c,disp_y-c,-ch]) cylinder(d=rd_d, h=ch, $fn=cfn);
        translate([c,disp_y-c,-ch]) cylinder(d=rd_d, h=ch, $fn=cfn);
    }
    module disp_cutout() {
        hull() {
            disp_cutout_boundaries();
        }
    }
    
    union() {
        color("gray") translate([offset_x,pos_y,-disp_z-f_height]) cube([disp_x, disp_y, disp_z]);
        color("gray") translate([pcb_w-disp_x/2-3,pos_y+((disp_y/4)*1),-disp_z-f_height]) cube([disp_x/2+3, disp_y/2, disp_z]);
        color("gray") translate([offset_x,pos_y,-disp_z-f_height]) disp_cutout();
    }
}

module disp_pm() {
    dsp_x = 16;
    dsp_y = 24;
    dsp_z = 1.65;
    
    dspb_x = 5;
    dspb_y = 9;
    
    py_offset = 4.3;
    
    color("silver") translate([pcb_w-dsp_x,20.85+py_offset,-dsp_z]) cube([dsp_x, dsp_y, dsp_z]);
    color("silver") translate([pcb_w-dsp_x-dspb_x,25.5+py_offset,-dsp_z]) cube([dspb_x, dspb_y, dsp_z]);
}

module mcu() {
    mcu_x = 21;
    mcu_y = 20.11;
    mcu_z = 1.50;
     translate([pcb_w/2-mcu_x/2, 38.6, pcb_t-0.01]) union() {
        color("white") cube([mcu_x, mcu_y, mcu_z]);
        //color("white") translate([-4,0,0]) cube([4,4,mcu_z]);
        //color("white") translate([mcu_x,0,0]) cube([6.2,7,mcu_z]); 
    }
}

module sd() {
    sd_x = 5.85+2*case_wt;
    bl_x =  5.85;
    sd_y = 11.85+0;
    sd_z = 2.85;
    
    //color("silver") translate([-2*case_wt,6.4-0.37,pcb_t]) rcube(sd_y, sd_x, sd_z, 1, y_axis=true);
    color("silver") translate([2-0.6,-2*case_wt,-sd_z]) rcube(sd_y, sd_x, sd_z, 1, y_axis=true);
}

module batcon() {
    bc_x = 8.9;
    bc_y = 6.7;
    color("white") translate([5.25, 0.8, pcb_t]) cube([bc_x, bc_y, bc_z]);

}

module keepout() {
    trx_x = 21;
    trx_y = 37+5;
    //trx_z = 2.85;
    trx_z = bc_z;
    
    cbl_gd_h = trx_z-2.85-0.2 + (e_mrg);
    cbl_gd_d = 3.75;
    
    trx_xpos = pcb_w/2-trx_x/2;
    trx_ypos = 2.3;
    
    difference() {
        color("silver") translate([trx_xpos,trx_ypos,pcb_t]) cube([trx_x, trx_y, trx_z]);
        if (!battery) {
            //color("grey") translate([4.5+trx_xpos+0, 22.75+cbl_gd_d/2+trx_ypos+0, pcb_t+trx_z-cbl_gd_h+e_mrg]) cylinder(d=cbl_gd_d, h=cbl_gd_h, $fn=12);
            //color("grey") translate([11.5+cbl_gd_d/2+trx_xpos, 33.5+trx_ypos+0, pcb_t+trx_z-cbl_gd_h+e_mrg]) cylinder(d=cbl_gd_d, h=cbl_gd_h, $fn=12);
        }
    }
}

module antennas() {
    ant_x = 16.9;
    ant_y = 6.1;
    ant_z = 3.8;
    color("silver") translate([pcb_w/2-ant_x/2,pcb_h-ant_y, pcb_t]) cube([ant_x, ant_y, ant_z]);
    
    ufl_sx = 5;
    ufl_sy = 6;
    ufl_sz = bc_z;
    color("silver") translate([0,18.5, pcb_t]) cube([ufl_sx, ufl_sy, ufl_sz]);
}

module new_hull_boundaries_1(hz=hull_z) {
    hz_trnslt = hull_z-hz;
    translate([-case_wt+hull_x-pd, -case_wt, hz_trnslt]) cube([pd,pd,hz]);
    
    translate([-case_wt+hull_x-pd, sma_align, hz_trnslt]) cube([pd,pd,hz]);
    translate([pcb_w/2+sma_pos_x-delta_x, sma_align, hz_trnslt]) cube([pd,pd,hz]);
    
    ant_conn_angled_offset = 1.8;
    translate([pcb_w/2+sma_pos_x-delta_x-ant_conn_angled_offset, -case_wt+hull_y-pd, hz_trnslt]) cube([pd,pd,hz]);
    
    translate([pcb_w/2+sma_pos_x-delta_x-ant_conn_angled_offset,  -case_wt, hz_trnslt]) cube([pd,pd,hz]);
}

module new_hull_boundaries_2(hz=hull_z) {
    pd=1;
    sma_shorten_thr = 4.3;
    sma_align = pcb_h+sma_spacing+n1_h+n2_h-pd+case_wt+sma_shorten_thr;
    
    hz_trnslt = hull_z-hz;
    translate([-case_wt, -case_wt+hull_y-pd, hz_trnslt]) cube([pd,pd,hz]);
    translate([-case_wt, -case_wt, hz_trnslt]) cube([pd,pd,hz]);
    
    sma_center = pcb_w/2+sma_pos_x;
    hull_end = -case_wt+hull_x;
    delta_x = hull_end-sma_center;
    
    ant_conn_angled_offset = 1.8;
    translate([pcb_w/2+sma_pos_x-delta_x-ant_conn_angled_offset-pd, -case_wt+hull_y-pd, hz_trnslt]) cube([pd,pd,hz]);
    
    translate([pcb_w/2+sma_pos_x-delta_x-ant_conn_angled_offset-pd,  -case_wt, hz_trnslt]) cube([pd,pd,hz]);
}

module hull_shape(hz=hull_z) {
    translate([pcb_w,0,hull_z]) rotate([0,180,0]) union() {
        hull() {
            new_hull_boundaries_1(hz);
        }
        hull() {
            new_hull_boundaries_2(hz);
        }
    }
}

module bottom_hull() {
    //translate([-case_wt, -case_wt, 0]) cube([hull_x, hull_y, hull_z]);
    if (battery) {
        
        if (sidewall_extend > 0) {
            difference() {
                hull_shape(hull_z+bat_extra);
                tb_de_extends();
            }
        } else {
            hull_shape(hull_z+bat_extra);
        }
    } else {
        if (sidewall_extend > 0) {
            difference() {
                hull_shape();
                tb_de_extends();
            }
        } else {
            hull_shape();
        }
    }
}

module top_hull() {
    //translate([-case_wt, -case_wt, 0]) cube([hull_x, hull_y, hull_z]);
    if (sidewall_extend > 0) {
        difference() {
            mirror([0,0,1]) hull_shape(hz=top_case_t);
            tb_de_extends();
        }
    } else {
        mirror([0,0,1]) hull_shape(hz=top_case_t);
    }
}


module sma_pt(cutout=false) {
    thr_h = 13.1;
    thr_d = 6.3;
    cut_d = 0.5;
    
    cbl_d = 2.45;
    cbl_h = 60;
    
    cylinder(d=n1_d, h=n1_h, $fn=6);
    translate([0,0,n1_h-n2_h_extra_backspacing]) cylinder(d=n2_d, h=n2_h+n2_h_extra_backspacing+n2_h_extra_frontspacing, $fn=6);
    difference() {
        translate([0,0,n1_h]) cylinder(d=thr_d, h=thr_h, $fn=24);
        if (flat_sma) {
            translate([0,thr_d-cut_d,n1_h+n2_h+thr_h/2]) cube([6.3,6.3,13.1], center=true);
        }
    }
    translate([0,0,-cbl_h]) cylinder(d=cbl_d, h=cbl_h, $fn=24);
    
    module extra_cutout() {
        translate([0, -n1_d/2, n1_h/2]) cube([n1_d,n1_d,n1_h], center=true);
        translate([0, -n2_d/2, n2_h/2+n1_h]) cube([n2_d,n2_d,n2_h], center=true);
        translate([0, -thr_d/2, thr_h/2+n1_h]) cube([thr_d,thr_d,thr_h], center=true);
        translate([0, -cbl_d/2-1, -cbl_h+cbl_h/2]) cube([cbl_d,cbl_d+2,cbl_h], center=true);
    }
    
    if (cutout) extra_cutout();
}

module positioned_sma(cutout=false) {
    translate([sma_pos_x, sma_pos_y+sma_slide_adjust, sma_pos_z]) rotate([-90,0,0]) sma_pt(cutout);
}

module tb_de_extend() {
    deh = 55;
    translate([0,-sidewall_extend*4,-deh/2]) cube([pcb_w*2, sidewall_extend*6, deh]);
}
module tb_de_extends() {
    // Bottom
    translate([-case_wt*2,-sidewall_extend*1-case_wt,0]) tb_de_extend();
    // Top
    //translate([-case_wt*2, sma_align+1-sidewall_extend, -25]) tb_de_extend();
}
module bottom_shell() {
    difference() {
        bottom_hull();
        device();
        //if (sidewall_extend > 0) {
        //    tb_de_extends();
        //}
        //translate([power_pl_t-0.1,0,0]) power_switch(slide_cutout=true);
        //translate([-0.05,0,0]) reset_button(movement_margin=true);
        //stress_release();
    }
}

module top_shell() {
    difference() {
        top_hull();
        device();
    }
}

module mold_top() {
    difference() {
        rotate([0,180,0] )translate([-pcb_w/2, -pcb_h/2, 0]) top_shell();
    }
}

door_t = bottom_thickness;
door_margin_x = 0.0;
door_margin_y = 4.5;
door_y_offset = 4.5;
module case_bottom() {
    difference() {
        rotate([0,180,0] )translate([-pcb_w/2, -pcb_h/2, 0]) bottom_shell();
        positioned_sma(true);
        neopixel();
        difference() {
            neopixel_cables();
            translate([0,-0.2,0]) positioned_board_bounds();
        }
        rotate([0,180,0]) translate([-pcb_w/2, -pcb_h/2, 0]) fixpoints();
        //if (battery_door) { rotate([0,180,0] ) translate([-pcb_w/2, -pcb_h/2-door_y_offset, hull_z+bat_extra-door_t]) case_door(); }
        //if (battery_door) { translate([0,0,-2.5])  rotate([0,180,0] )translate([-pcb_w/2, -pcb_h/2, 0]) bat(); }
    }
}

module case_door(zm=true, so=false, shrink_z=false) {
    use_screws = use_bat_door_screws;
    use_jigs = !use_screws;
    use_notches = false;
    // Change this to tune bottom shell flushness
    d_z_support_m = 2*0.15;
    z_m = 0.2;
    b_x = battery_x+2*door_margin_x;
    b_y = battery_y+2*door_margin_y;
    b_z = battery_z;
    b_depth = battery_depth;
    
    sym = 3;
    sox = pcb_w/2-b_x/2+b_x/2;
    soy = b_offset;
    soz = 0.6;
    module d_screws() {
        translate([sox, soy+sym,bottom_thickness+soz]) rotate([0,180,0]) screw();
        translate([sox, soy+b_y-sym,bottom_thickness+soz]) rotate([0,180,0]) screw();
    }
    
    module flange(y_o=0) {
        fl_s = 4;
        fl_bh = door_t-d_z_support_m;
        c_s = sqrt(2*pow(fl_s,2));
        difference() {
            translate([sox+b_x/2, soy+b_y/2-c_s/2+y_o, 0]) rotate([-45, -90, 0]) prism(fl_bh,  fl_s, fl_s);
            translate([sox+b_x/2, b_y/2+soy-c_s/2+y_o, 0]) rotate([0, 45, 0]) cube([c_s,  c_s, fl_bh*3]);
        }
        if (zm) difference() {
            translate([sox+b_x/2, soy+b_y/2-c_s/2+y_o, fl_bh]) rotate([-45, -90, 0]) prism(fl_bh,  fl_s, fl_s);
            translate([sox+b_x/2+fl_bh, b_y/2+soy-c_s/2+y_o, 0]) rotate([0, 0, 0]) cube([c_s,  c_s, fl_bh*3]);
        }
        
        difference() {
            translate([sox-b_x/2, soy+b_y/2+c_s/2+y_o, 0]) rotate([-45, -90, 180]) prism(fl_bh,  fl_s, fl_s);
            translate([sox-b_x/2, b_y/2+soy-c_s/2+y_o, 0]) rotate([0, 225, 0]) cube([c_s,  c_s, fl_bh*3]);
        }
        if (zm) difference() {
            translate([sox-b_x/2, soy+b_y/2+c_s/2+y_o, fl_bh]) rotate([-45, -90, 180]) prism(fl_bh,  fl_s, fl_s);
            translate([sox-b_x/2-fl_bh-c_s, b_y/2+soy-c_s/2+y_o, 0]) rotate([0, 0, 0]) cube([c_s,  c_s, fl_bh*3]);
        }
    }
    
    if (use_jigs) {
        jig_w = 4.5;
        jig_h = 4.5;
        jig_topcut = 0;

        intersection() {
            union() {
                translate([sox-b_x/2, soy+b_y, 0]) rotate([180,0,0]) prism(b_x,  jig_w, jig_h);
                translate([sox-b_x/2+b_x, soy, 0]) rotate([180,0,180]) prism(b_x,  jig_w, jig_h);
                
                if (zm) translate([sox-b_x/2+b_x, soy+jig_w, 0]) rotate([180,0,180]) cube([b_x, b_y-2*jig_w, jig_h]);
                //translate([sox-b_x/2, soy+jig_w, 0]) rotate([180,0,0]) prism(b_x,  jig_w, jig_h);
                //translate([sox-b_x/2+b_x, soy-jig_w+b_y, 0]) rotate([180,0,180]) prism(b_x,  jig_w, jig_h);
            }
            if (zm) {
                translate([pcb_w/2-b_x/2, b_offset,-jig_h+jig_topcut]) rcube(x=b_x, y=b_y, z=door_t+z_m+jig_h-jig_topcut, r=2, n=4);
            } else {
                jig_topcut = 2.0;
                translate([pcb_w/2-b_x/2, b_offset,-jig_h+jig_topcut]) rcube(x=b_x, y=b_y, z=door_t+z_m+jig_h-jig_topcut, r=2, n=4);
            }
        }
    }

    if (so && use_screws) {
        translate([sox, soy+sym,bottom_thickness+soz+0.0]) rotate([0,180,0]) screw();
        translate([sox, soy+b_y-sym,bottom_thickness+soz+2.3]) rotate([0,180,0]) screw();
        
    } else {
        difference() {
            
            if (zm) {
                //union() {
                    translate([pcb_w/2-b_x/2, b_offset]) rcube(x=b_x, y=b_y, z=door_t+z_m, r=2, n=4);
                    //translate([0,0,3.3]) d_screws();
                //}
            } else {
                difference() {
                    translate([pcb_w/2-b_x/2, b_offset]) rcube(x=b_x, y=b_y, z=door_t-d_z_support_m, r=2, n=4);
                    if (use_screws) {
                        translate([0,0,-d_z_support_m]) d_screws();
                    }
                    if (use_jigs) {
                        tap_w = 3.2;
                        tap_d = 2;
                        tap_h = 2.5;
                        tap_oz = 0.15;
                        translate([pcb_w/2-0, b_offset,tap_h/2+tap_oz]) cube([tap_w,tap_d,tap_h], center=true);
                        translate([pcb_w/2-0, b_offset+tap_d-0.05,tap_h/2+tap_oz-(tap_h/3)]) cube([tap_w,tap_d,tap_h/3], center=true);
                    }
                }
            }
            
            if (use_notches) {
                notch_m = 1;
                notch_w = 3.25;
                notch_d = 1.25;
                notch_i = 1.25;
                notch_a = 3;
                
                if (zm) {
                    translate([sox+b_x/2-notch_i, soy+b_y/2+notch_w/2+notch_a, 0]) rotate([0,0,-90]) prism(notch_w,  notch_i, notch_d);
                    translate([sox-b_x/2+notch_i, soy+b_y/2-notch_w/2-notch_a, 0]) rotate([0,0,90]) prism(notch_w, notch_i, notch_d);
                } else {
                    notch_w = notch_w+1;
                    translate([sox+b_x/2-notch_i, soy+b_y/2+notch_w/2+notch_a, 0]) rotate([0,0,-90]) prism(notch_w,  notch_i, notch_d);
                    translate([sox-b_x/2+notch_i, soy+b_y/2-notch_w/2-notch_a, 0]) rotate([0,0,90]) prism(notch_w, notch_i, notch_d);
                }
            }
        }

        flange(-b_y/8);
        flange(3*(-b_y/8));
        flange(b_y/8);
        flange(3*(b_y/8));
    }
}

module case_top() {
    difference() {
        rotate([0,180,0] )translate([-pcb_w/2, -pcb_h/2, 0]) top_shell();
        positioned_sma();
        window();
        neopixel();
        neopixel_cables();
    }
}

module positioned_device() {
    rotate([0,180,0] )translate([-pcb_w/2, -pcb_h/2, 0]) device();
}

module positioned_bat() {
    rotate([0,180,0] )translate([-pcb_w/2, -pcb_h/2, 0]) bat();
}

module neopixel(margin=0) {
    pixel_w = 5.1+margin;
    pixel_h = 3.35;
    pcb_d = 9.6;
    cutout_d = 2;
    pcb_t = 2.25;
    
    depth = neopixel_depth;
    
    translate([sma_pos_x-neopixel_offset_x,sma_pos_y-neopixel_offset_y,depth]) union() {
        color("white") translate([0,0,(pixel_h-pcb_t)/2]) cube([pixel_w, pixel_w, pixel_h-pcb_t], center=true);
        color("green") translate([0,0,-pcb_t-cutout_d]) cylinder(d=pcb_d, h=pcb_t+cutout_d, $fn=24);
    }
}

module neopixel_cables() {
    np_x = sma_pos_x-neopixel_offset_x;
    np_y = sma_pos_y-neopixel_offset_y;
    np_z = neopixel_depth;
    
    trn_w = 5;
    trn_d = 2.25+2;
    
    po_x = -pcb_w/2;
    po_y = -pcb_h/2;
    
    tfn = 16;
    lower_offset = (0.125*pcb_w);
    end_offset = 7;
    
    module p1() { translate([np_x, np_y, np_z-trn_d]) cylinder(d=trn_w, h=trn_d, $fn=tfn); }
    module p2() { translate([po_x+(5*(pcb_w/8)), po_y+pcb_h-trn_w/2, np_z-trn_d]) cylinder(d=trn_w, h=trn_d, $fn=tfn); }
    module p3() { translate([po_x+lower_offset, po_y+pcb_h-trn_w/2-6, np_z-trn_d]) cylinder(d=trn_w, h=trn_d, $fn=tfn); }
    module p4() { translate([po_x+lower_offset, po_y+end_offset, np_z-trn_d]) cylinder(d=trn_w, h=trn_d, $fn=tfn); }
    
    hull() { p1(); p2(); }
    hull() { p2(); p3(); }
    hull() { p3(); p4(); }
    
}

module stress_release() {
    sr_d = 3;
    bt = 0.35;
    sr_h = hull_z-pcb_t-bt;
    
    //translate([case_wt, case_wt, hull_z-sr_h-bt]) cylinder(d=sr_d, h=sr_h, $fn=16);
    translate([0, 0, hull_z-sr_h-bt]) cube([sr_d,sr_d+2,sr_h]);
}

module window(cavity=false) {
    w_d = 6;
    w_h = 25;
    
    difference() {
        intersection() {
            translate([sma_pos_x-neopixel_offset_x,sma_pos_y-neopixel_offset_y,0])
            translate([0,0,-w_h/2]) cylinder(d=w_d, h=w_h, $fn=24);
            mold_top();
        }
        neopixel(margin=2);
        if (cavity==true) {
            translate([0,0,-0.35]) intersection() {
                translate([sma_pos_x-neopixel_offset_x,sma_pos_y-neopixel_offset_y,0]) translate([0,0,-w_h/2]) cylinder(d=w_d-1.8, h=w_h, $fn=24);
                mold_top();
            }
        }
    }
}

module positioned_door() {
    rotate([0,180,0] ) translate([-pcb_w/2, -pcb_h/2-door_y_offset, hull_z+bat_extra-door_t]) color("gray") case_door(zm=false, shrink_z=true);
}

// Parts /////////////////////////
///////////////////////////////////

// Powerswitch
if (render_powerswitch) {
    //rotate([0,-90,0]) translate([-pcb_w, -3-6,-1])
    rotate([0,180,0]) translate([-pcb_w/2+1, -pcb_h/2, 0]) power_switch(slide_cutout=false, ridges=true);
}

// LED Window
if (render_led_window) {
    window(cavity=true);
    //window(cavity=false);
}

// LED Guide
if (render_led_guide) {
    rotate([0,180,0] )translate([-pcb_w/2+1, -pcb_h/2, 0])  led_guide(g_h=1.15);
}

// Case bottom
if (render_case_bottom) {
    if (battery_door) {
        difference() {
            difference() {
                color("gray") case_bottom();
                rotate([0,180,0] ) translate([-pcb_w/2, -pcb_h/2-door_y_offset, hull_z+bat_extra-door_t]) color("gray") case_door(zm=true);
            }
            // Disabled since it is no longer used in screwless design
            //rotate([0,180,0] ) translate([-pcb_w/2, -pcb_h/2-door_y_offset, hull_z+bat_extra-door_t]) color("gray") case_door(so=true);
        }
    } else {
        color("gray") case_bottom();
    }
}

// Battery door
if (render_battery_door) {
    positioned_door();
}
// Case top
if (render_case_top) color("gray") case_top();

//rotate([0,180,0]) translate([-pcb_w/2, -pcb_h/2, 0]) fixpoints();

// Tests & Diagnostics //////
///////////////////////////////////
if (render_device_model) {

}

if (render_sma) {
    positioned_sma();
}

if (render_debug_model) {
    positioned_device();
    neopixel();
    neopixel_cables();
    positioned_sma();
    if (battery_door) {
        //translate([0,0,-2.5])  rotate([0,180,0] )translate([-pcb_w/2, -pcb_h/2, 0]) bat(); 
    }
    //color("gold") positioned_sma();
    //positioned_bat();
    //hull_shape();
    //translate([-power_pl_t,0,0]) rotate([0,180,0] )translate([-pcb_w/2, -pcb_h/2, 0]) power_switch(slide_cutout=false);
}