// 13 potentiometers:
//    10 steps
//    1 to set clock rate (if onboard clock is used) (rv11)
//    1 for manual glide (rv16)
//    1 for cv glide atten (rv15)

// 13 SPDT switches:
//    10 steps  (sw1-sw10)
//    1 for 5v / 2.5v output mode (sw12)
//    1 for run/stop (sw14)
//    1 for once/cont (sw15)

// 2 NO Moment switches:
//    1 for manual step (sw13)
//    1 for manual reset (sw16)

// 8 Sockets:
// clock in  (j2/j11)
// casc out  (j14/j15)
// reset/casc in  (j1/j13)
// gate out  (j4/j10)
// clock out (j5/j12)
// glide in  (j16/j17)
// cv out    (j7/j6)
// pause cv in (j18/j19)

// 10 LEDs - one per step
// 1 rotary switch - number of steps (sw11)



/* [Default values] */
// Line segments for circles
FN = 60; // [1:1:360]
// Unit size (mm)
U = 44.45;
// Horizontal pitch size (mm)
HP = 5.075; // 5.07 for a little bit of margin
// Futura Light typeface for labels
default_label_font = "Futura Md BT:style=Medium";
font_for_title = "QuentinEF:style=Medium";
title_font_size = 12;
label_font_size = 5;

$fn=FN;
footprint_depth = 1;  //non-printing, barely-visible outline of component footprints


/* [Panel] */
// Height of module (mm) - Would not change this if you are using Eurorack
height = 128.5; // A little less then 3U
// Thickness of module (mm) - Would not change this if you are using Eurorack
thickness = 2;  // Website specifies a thickness of 2mm - but adjust to fit printer specs - often the first layer will be thinner than this
printer_z_fix = 0.5;  // this gets added to the base panel's thickness to account for squishing
tolerance = 0.25;

// for inset labels, translating to this height controls label depth
label_inset_height =  thickness-1;

// Width of module (HP)
width = 38; // [1:1:84]

/* [Holes] */
// Four hole threshold (HP)
four_hole_threshold = 10;
// Center two holes
two_holes_type = "opposite"; // [center, opposite, mirror]
// Hole radius (mm)
hole_r = 1.7;
// Hole distance from the side (HP)
hole_dist_side = hp_mm(1.5);
// Hole distance from the top (mm)
hole_dist_top = 2.5;

rail_clearance = 8;  // mm from very top/bottom edge and where it is safe to put reinforcing walls; i.e. the thickness of the rail + a safety margin

// margins from edges
h_margin = thickness*2;
v_margin = hole_dist_top*2 + thickness;

width_mm = hp_mm(width); // where to put the output jacks

working_height = height - v_margin;
working_increment = working_height / (8+tolerance/5);  // generally-useful spacing amount for vertical columns of stuff

col_left = thickness + 6 + tolerance;  // rib + half a jack
col_right = width_mm - thickness*2.5 - tolerance*6;

out_row_1 = v_margin+12;
out_row_2 = working_increment*1 + out_row_1;
out_row_3 = working_increment*2 + out_row_1;
out_row_4 = working_increment*3 + out_row_1;
out_row_5 = working_increment*4 + out_row_1;
out_row_6 = working_increment*5 + out_row_1;
out_row_7 = working_increment*6 + out_row_1;
out_row_8 = working_increment*7 + out_row_1;
out_row_9 = working_increment*8 + out_row_1;


//special-case the knob spacing on the left sub-panel
top_row = height - rail_clearance - thickness*2 - 16.5/2; // 16.5 is the diameter of the round part of a pot

working_width = width_mm - h_margin;

left_rib_x = 0;
right_rib_x = width_mm - thickness;

// How much horizontal space needed for left-hand and right-hand sub-panels
left_panel_width = 12*3 + tolerance*2;  //three knobs plus space between them
right_panel_width = width_mm - col_right;  // column from edge plus hole radius

slider_spacing = 12.5;  // space between centers of each sliding pot; these are actually 8.8mm but require more on the circuit board for a single through-hole on one side

//calculated x value of exact middle of slider panel (between steps 5 and 6); middle of panel after deducting left/right sub-panels
slider_center = (width_mm - left_panel_width - right_panel_width)/2 + left_panel_width;
slider_bottom = v_margin+8;

// elevated sockets to fit two mounting posts into
hole_top = out_row_1 + 94;  // this should be height of the step LED + 23mm
hole_left = slider_center - 13; // this one is easy
hole_bottom = hole_top - 89.75; // these two come directly from kicad
hole_right = hole_left + 78.5;

// projection: make a 2d version
//projection(){
translate([0, 50, 0])
// draw panel, subtract holes
union() {
    difference(){
        color([.1,.1,.1])
        panel(width);

        // Top left:  clock in, speed
        // clock in (j2/j11)
        translate([col_left, out_row_7, 0]) audio_jack_3_5mm();
        //clock rate (rv11)
        translate([col_left+27, out_row_7, 0]) rotate([0, 0, 90]) pot_p160(anchor_hole="both");

        // Left side: meta-step controls
        // Step count (sw11)
        // step rotary switch - this needs a _big_ knob, these are not easy to actuate
        // so put it between rows 5 and 6
        translate([col_left + 27/2, (out_row_6 + out_row_5)/2, 0]) rotary_switch();

        // manual step (sw13) - pushbutton
        translate([col_left, out_row_4, 0]) pushbutton_switch_6mm();

        // manual reset (sw16) - pushbutton
        translate([col_left+27, out_row_4, 0]) pushbutton_switch_6mm();

        // run/stop (sw14)
        translate([col_left, out_row_3, 0]) toggle_switch_6mm();

        // once/continuous (sw15)
        translate([col_left+27, out_row_3, 0]) toggle_switch_6mm();

        // reset/casc in (j1/j13)
        translate([col_left, out_row_2, 0]) audio_jack_3_5mm();

        // pause (j18/j19)
        translate([col_left+27, out_row_2, 0]) audio_jack_3_5mm();

        // glide in (j16/j17)
        translate([col_left-.5, out_row_1, 0]) audio_jack_3_5mm();
        // glide atten (rv15)
        translate([col_left+12.25, out_row_1, 0]) rotate([0,0,180]) pot_p160(anchor_hole="both");
        // glide manual (rv16)
        translate([col_left+27, out_row_1, 0]) rotate([0,0,180]) pot_p160(anchor_hole="both");
        
        
        // Everything OUT goes on the right
        // cv out (j7/j6)
        translate([col_right, out_row_1, 0]) audio_jack_3_5mm();

        // cv range (sw12)
        translate([col_right, out_row_2, 0]) toggle_switch_6mm();

        // gate out (j4/j10)
        translate([col_right, out_row_3, 0]) audio_jack_3_5mm();

        // clock out (j5/j12)
        translate([col_right, out_row_5, 0]) audio_jack_3_5mm();

        // casc out (j14/j15)
        translate([col_right, out_row_4, 0]) audio_jack_3_5mm();

        // steps: slider, led, switch (sw1-sw10, rv1-rv10)
        // Note: don't mess with the multipliers here, tweak the variables themselves
        translate([slider_center-slider_spacing*.5, slider_bottom, 0]) make_step();
        translate([slider_center-slider_spacing*1.5, slider_bottom, 0]) make_step();
        translate([slider_center-slider_spacing*2.5, slider_bottom, 0]) make_step();
        translate([slider_center-slider_spacing*3.5, slider_bottom, 0]) make_step();
        translate([slider_center-slider_spacing*4.5, slider_bottom, 0]) make_step();
        translate([slider_center+slider_spacing*.5, slider_bottom, 0]) make_step();
        translate([slider_center+slider_spacing*1.5, slider_bottom, 0]) make_step();
        translate([slider_center+slider_spacing*2.5, slider_bottom, 0]) make_step();
        translate([slider_center+slider_spacing*3.5, slider_bottom, 0]) make_step();
        translate([slider_center+slider_spacing*4.5, slider_bottom, 0]) make_step();

    // mounting holes - for projection() only
    //    color([1,0,0])
    //    translate([hole_left, hole_top, -thickness+1]) mounting_hole_m3();
    //    translate([hole_right, hole_bottom, -thickness+1]) mounting_hole_m3();


    }



    // ribs - reinforcements and barriers against shorts on the rails
    translate([left_rib_x, rail_clearance, 0])
        v_wall(h=4, l=height-rail_clearance*2-thickness, th=thickness*1.25);
    translate([right_rib_x, rail_clearance, 0])
        v_wall(h=4, l=height-rail_clearance*2-thickness, th=thickness);

    // top horizontal rib
    translate([left_rib_x, height-rail_clearance-thickness, 0])
        h_wall(h=4, l=right_rib_x+thickness);
    // bottom horizontal rib
    translate([left_rib_x, rail_clearance, 0])
        h_wall(h=4, l=right_rib_x);
    
    //another rib to balance the switches along the bottom
    translate([slider_center-slider_spacing*5, rail_clearance+12, 0])
        h_wall(h=4, l=slider_spacing*10-1, th=1);
    //connect that to the bottom
    translate([slider_center-slider_spacing*5-2, rail_clearance, 0])
        v_wall(h=4, l=height-rail_clearance*2-thickness, th=2);
    //connect that to the bottom
    translate([slider_center+slider_spacing*5-1.5, rail_clearance, 0])
        v_wall(h=4, l=height-rail_clearance*2-thickness, th=2);
    
    //another rib to reinforce along the LEDs
    translate([slider_center-slider_spacing*5, rail_clearance+22+56, 0])
        h_wall(h=4, l=slider_spacing*10+right_panel_width*3-thickness, th=1.5);
    
    // mounting holes
    translate([hole_left, hole_top, thickness]) mounting_hole_m3(h=5, flange=12);
    translate([hole_right, hole_bottom, thickness]) mounting_hole_m3(h=5, flange=9);
    
    //outline of whole PCB?
//    translate([slider_center, height/2+4, 0])
//    cube([137.5, 97, 1], center=true);

}

//end: projection
//}

module make_surface(filename, h) {
    for (a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
        linear_extrude(height=a/h, convexity=10)
            projection(cut = true)
                surface(filename, center=true);
}


// h[p]
module panel(h) {
    width_mm = hp_mm(h);
    difference() {
//        translate([0, 0, -printer_z_fix])
        cube(size = [width_mm, height, thickness+printer_z_fix]);
        
        if (h < four_hole_threshold) {
            if (two_holes_type == "center") {
                translate([width_mm/2, hole_dist_top, -1])
                cylinder(r=hole_r, h=thickness*2);
           
                translate([width_mm/2, height-hole_dist_top, -1])
                cylinder(r=hole_r, h=thickness*2); 
            } else if (two_holes_type == "opposite") {
                translate([hole_dist_side, hole_dist_top, -1])
                cylinder(r=hole_r, h=thickness*2);
           
                translate([width_mm - hole_dist_side, height-hole_dist_top, -1])
                cylinder(r=hole_r, h=thickness*2); 
            } else if (two_holes_type == "mirror") {
                translate([hole_dist_side, hole_dist_top, -1])
                cylinder(r=hole_r, h=thickness*2);
           
                translate([hole_dist_side, height-hole_dist_top, -1])
                cylinder(r=hole_r, h=thickness*2); 
            }
        } else {
            translate([hole_dist_side, hole_dist_top, -1])
            cylinder(r=hole_r, h=thickness*2);
           
            translate([hole_dist_side, height - hole_dist_top, -1])
            cylinder(r=hole_r, h=thickness*2);
            
            translate([width_mm - hole_dist_side, hole_dist_top, -1])
            cylinder(r=hole_r, h=thickness*2);
           
            translate([width_mm - hole_dist_side, height - hole_dist_top, -1])
            cylinder(r=hole_r, h=thickness*2); 
        }
    }
}



// http://www.rean-connectors.com/en/products/din-chassis-connectors/nys325
module nys325_midi_socket() {
    cylinder(r=7.55, h=thickness*2+1);
    translate([0, 11.3, -1])
    cylinder(r=1.6, h=thickness*2+1);
    translate([0, -11.3, -1])
    cylinder(r=1.6, h=thickness*2+1);
}

module audio_jack_3_5mm(vertical=true) {
    translate([0, 0, -1]) cylinder(r=3+tolerance/2, h=thickness*2+1);
    if (vertical) {
        translate([-9/2, -10.5/2, -footprint_depth/2]) cube([9, 10.5, footprint_depth]);
    } else {
        translate([-10.5/2, -9/2, -footprint_depth/2]) cube([10.5, 9, footprint_depth]);
    }
}

module mounting_hole_m3(h=thickness, flange=8){
    difference() {
        translate([0,0,-h+thickness])
        cube([flange, flange, h], center=true);
        translate([0,0,-h-2])
        cylinder(r=2.25, h=h+3, $fn=6);
    };

}


module toggle_switch_6mm() {
    translate([0, 0, -1]) cylinder(r=3+tolerance/2, h=thickness*2+1);
    translate([-8/2, -13/2, -footprint_depth/2]) cube([8, 13.15, footprint_depth]);
}

module pushbutton_switch_6mm() {
    translate([0, 0, -1]) cylinder(r=3+tolerance/2, h=thickness*2+1);
    translate([0, 0, -footprint_depth/2]) cylinder(d=9.75, h=footprint_depth);
}

module toggle_switch_6_8mm() {
    translate([0, 0, -1]) cylinder(r=3.4, h=thickness*2+1);
}

module rotary_switch(){
    translate([0, 0, -1]) cylinder(r=5, h=thickness*2);
    //hole(s) for anchor
    translate([17/2 + 3/2, 0, -1]) cylinder(r=1.5+tolerance, h=thickness);
    translate([9.6, 0, -1]) cylinder(r=1.5+tolerance, h=thickness);
    // visual indicator of space switch takes up
    translate([0, 0, -footprint_depth/2]) cylinder(r=14, h=footprint_depth);
}
// 
module pot_p160(anchor_hole="left") {
    translate([0, 0, -1]) cylinder(r=3.75, h=thickness*2);
    // hole for anchor; with translate() ends up being h-1 deep
    if (anchor_hole=="left" || anchor_hole=="both") {
        translate([7.8, 0, -1]) cylinder(r=1.5, h=thickness);
        translate([0, 13/2, -footprint_depth/2]) cube([17, 13, footprint_depth], center=true);
    }
    if (anchor_hole=="right" || anchor_hole=="both") {
        translate([-7.8, 0, -1]) cylinder(r=1.5, h=thickness);
        translate([0, 0, -footprint_depth/2]) cube([17, 13, footprint_depth], center=true);
    }
    // visual indicator of space pot body takes up
    translate([0, 0, -footprint_depth/2]) cylinder(r=16.5/2, h=footprint_depth);

}

module pot_wh148() {
    translate([0, 0, -1]) cylinder(r=3.6, h=thickness*2);
    // hole for anchor; with translate() ends up being h-1 deep
    translate([7.8, 0, -1]) cylinder(r=1.3, h=thickness);
}

module pot_0547() {
    // slider pot slit
    translate([-1.25, 0, -1]) cube([2.5, 52, thickness*2]);
    // visual indicator
    translate([-8.8/2, -4, -footprint_depth/2]) cube([8.8, 60.25, footprint_depth]);
    
}


module led_5mm() {
    // make a hole for a 5mm led, with a hair of margin
    translate([0, 0, -1]) cylinder(r=2.575, h=thickness*2+2);
}

module make_step(bottom_element="switch") {
    // generate holes for a pot, an LED, and a switch
    if (bottom_element=="pot"){
        pot_0547();
        translate([0, 55+8, 0]) led_5mm();
        translate([0, 55+24, 0]) toggle_switch_6mm();
    } else if (bottom_element=="switch") {
        toggle_switch_6mm();
//        translate([0, 16, 0]) pot_0547();
//        translate([0, 55+24, 0]) led_5mm();
        translate([0, 13, 0]) pot_0547();
        translate([0, 56+20, 0]) led_5mm();
    }
}



module label(string, size=4, halign="center", height=thickness+1, font=default_label_font) {
    color([1,0,0])
    linear_extrude(height)
    text(string, size, halign=halign, font=font);
}

module title(string, size=12, halign="center", font=font_for_title) {
    color([1,0,0])
    linear_extrude(thickness+1)
    text(string, size, halign=halign, font=font);
}

// draw a "vertical" wall
// h = z height, i.e. how tall the wall is coming out of the panel
// l = length of the wall along the panel
module v_wall(h, l, th=thickness) {
    translate([0, 0, -h]) cube(size = [th, l, h]);
}

// draw a horizontal wall (across the panel)
// h = z height, how far the wall comes out of the panel
// l = length of the wall along the panel
module h_wall(h, l, th=thickness) {
    translate([0, 0, -h]) cube(size = [l, th, h]);
}

// draws two walls in parallel, close together so a PCB can fit between
// h = how deep to make the walls; a little extra is probably good
// l = length of the side of the board that will be seated in the slit, with tolerances
// th = thickness of the PCB, with tolerances
// wall_thickness = how thick to make each wall of the holder
// e.g.: Radio Shaek is 51mm x 70mm and 1.2mm thick
module pcb_holder(h, l, th, wall_thickness=thickness) {
    translate([0-(wall_thickness+th)/2, 0, 0])
    v_wall(h, l, wall_thickness);

    translate([(wall_thickness+th)/2, 0, 0])
    v_wall(h, l, wall_thickness);
}


// https://www.elfa.se/Web/Downloads/_t/ds/els-511sygwa-s530-e1_eng_tds.pdf
module x1_7seg_14_22mm_display() {
    cube([12.25, 19.25, thickness]);
}

module x2_7seg_14_22mm_display() {
    cube([25, 19.25, thickness]);
}

// https://www.elfa.se/Web/Downloads/2e/wa/qmCC56-12EWA.pdf
module x4_7seg_14_22mm_display() {
    cube([50.5, 19.25, thickness]);
}

// https://cdn.sparkfun.com/datasheets/Components/Switches/MX%20Series.pdf
module cherry_mx_button() {
	union(){
		cube([14,14,thickness]);

		translate([-1,1,0])
		cube([14+2*1,thickness,thickness]);

		translate([-1,14-1-3,0])
		cube([14+2*1,3,thickness]);
	}
}


// 1U  = 1.75" = 44.45mm
// 1HP = 1/5"  = 5.08mm

// u[nits]
function units_mm(u) = u * U; 

// h[p]
function hp_mm(h) = h * HP; 