Design raspicam 'feet' and add some improvements.

// Raspicam

// Copyright (c) 2014, Jérémie Decock (jd.jdhp@gmail.com)

// BODY /////////////////////////////////////

module body(board_width, board_height, board_depth, board_corner_radius, screw_hole_radius, screw_hole_spacing, screw_hole_depth, num_screw_holes, camera_screw_holes_radius, camera_screw_holes_spacing_x, camera_screw_holes_spacing_y, camera_holes_width, hinge_radius_in, hinge_radius_out, hinge_slot_length) {
    difference() {
        union() {
            difference() {
                translate([0, board_width/2, 0]){  // TODO: REMOVE THIS LINE!
                    rotate(a=[0,0,90]){            // TODO: REMOVE THIS LINE!
                        body_main_board(board_width, board_height, board_depth, board_corner_radius);
                    }
                }

                union() {
                    translate([0, board_width - num_screw_holes * screw_hole_spacing - 12.5, 0]){
                        body_screw_holes(screw_hole_radius, screw_hole_spacing, screw_hole_depth, num_screw_holes);
                    }

                    translate([0, camera_screw_holes_spacing_y/2 + 10, 0]){
                        body_camera_screw_holes(camera_screw_holes_radius, camera_screw_holes_spacing_x, camera_screw_holes_spacing_y, screw_hole_depth);
                        translate([0, camera_screw_holes_spacing_y/2, 0]){
                            body_camera_holes(camera_holes_width, screw_hole_depth);
                        }
                    }
                }
            }
            translate([0, board_width, hinge_radius_out - board_depth/2]) {
                rotate(a=[0,90,0]) {
                    body_hinge(hinge_radius_in, hinge_radius_out, board_height);
                }
            }
        }
        translate([0, board_width, hinge_radius_out - board_depth/2]) {
            cube([hinge_slot_length, hinge_radius_out * 2 + 2, hinge_radius_out * 2 + 2], center=true);
        }
    }
}

module body_main_board(width, height, depth, radius) {
	$fn=50;
	//minkowski()
	//{
		cube([width, height, depth], center=true);
    //	cylinder(r=radius, h=depth, center=true);
    //}
}

module body_screw_holes(radius, spacing, depth, num) {
	$fn=50;

	for (i = [1:num]) {
		translate([0, i*spacing, 0]) {
			cylinder(r=radius, h=depth, center=true);
		}
	}
}

module body_camera_screw_holes(radius, spacing_x, spacing_y, depth) {
	$fn=50;

	for (i = [-1, 1]) {
        for (j = [-1, 1]) {
            translate([i*spacing_x/2, j*spacing_y/2, 0]) {
                cylinder(r=radius, h=depth, center=true);
            }
        }
	}
}

module body_camera_holes(width, depth) {
    cube([width, width, depth], center=true);
}

module body_hinge(radius_in, radius_out, length) {
    difference() {
        cylinder(r=radius_out, h=length, center=true, $fn=50);
        translate([0, 0, 0]) {
            cylinder(r=radius_in, h=length+10, center=true, $fn=50);
        }
    }
}

// HINGE SCREW //////////////////////////////

module hinge_screw(radius, head_radius, length, head_length) {
    cylinder(r=head_radius, h=head_length, $fn=8);
    translate([0, 0, head_length/2]) cylinder(r=radius, h=length, $fn=50);

    translate([15, 0, 0]) {
        difference() {
            cylinder(r=head_radius, h=head_length, $fn=8);
            translate([0, 0, head_length/2]) cylinder(r=radius, h=length, $fn=50);
        }
    }
}

// FEET /////////////////////////////////////

module feet(board_width, board_height, board_depth, board_corner_radius, screw_holes_radius, screw_holes_spacing_x, screw_holes_spacing_y, screw_hole_depth, hinge_length, hinge_radius_in, hinge_radius_out, hinge_shelf_width, ventilation_holes_radius) {
    difference() {
        feet_main_board(board_width, board_height, board_depth, board_corner_radius);
        feet_screw_holes(screw_holes_radius, screw_holes_spacing_x, screw_holes_spacing_y, screw_hole_depth);
        feet_ventilation_holes(ventilation_holes_radius, screw_hole_depth);
    }

    translate([board_width/2 + hinge_shelf_width/2, 0, 0]) {
        cube([hinge_shelf_width, hinge_length, board_depth], center=true);
    }

    translate([board_width/2 + hinge_shelf_width, 0, hinge_radius_out - board_depth/2]) {
        rotate(a=[90,0,0]) {
            feet_hinge(radius_in=hinge_radius_in, radius_out=hinge_radius_out, length=hinge_length);
        }
    }
}

module feet_screw_holes(radius, spacing_x, spacing_y, depth) {
	$fn=50;

	for (i = [-1, 1]) {
        for (j = [-1, 1]) {
            translate([i*spacing_x/2, j*spacing_y/2, 0]) {
                cylinder(r=radius, h=depth, center=true);
            }
        }
	}
}

module feet_ventilation_holes(radius, depth) {
	$fn=50;

    translate([0, 0, 0]) {
        cylinder(r=radius, h=depth, center=true);
    }
}

module feet_main_board(width, height, depth, radius) {
	$fn=50;
	//minkowski()
	//{
		cube([width, height, depth], center=true);
	//	cylinder(r=radius, h=depth, center=true);
	//}
}

module feet_hinge(radius_in, radius_out, length) {
    difference() {
        cylinder(r=radius_out, h=length, center=true, $fn=50);
        translate([0, 0, 0]) {
            cylinder(r=radius_in, h=length+10, center=true, $fn=50);
        }
    }
}

/////////////////////////////////////////////

assign(feet_board_width=98,
       feet_board_height=65,
       feet_board_depth=3,
       feet_board_corner_radius=3,
       feet_screw_holes_radius=1.5,
       feet_screw_holes_spacing_x=70,
       feet_screw_holes_spacing_y=30,
       feet_screw_hole_depth=10,
       feet_hinge_shelf_width=20,
       feet_ventilation_holes_radius=3,
       body_board_width=100,
       body_board_height=40,
       body_board_depth=3,
       body_board_corner_radius=3,
       body_screw_hole_radius=1.5,
       body_screw_hole_spacing=5,
       body_screw_hole_depth=10,
       body_num_screw_holes=9,
       body_camera_screw_holes_radius=1,
       body_camera_screw_holes_spacing_x=20,
       body_camera_screw_holes_spacing_y=12,
       body_camera_holes_width=8,
       body_hinge_radius_out=4.6,
       hinge_radius=1.5,
       hinge_head_radius=4.6,
       hinge_head_length=5) {

    color([1,0,0]) {
        translate([0, -50, feet_board_depth/2]) {
            feet(board_width=feet_board_width, board_height=feet_board_height, board_depth=feet_board_depth, board_corner_radius=feet_board_corner_radius, screw_holes_radius=feet_screw_holes_radius, screw_holes_spacing_x=feet_screw_holes_spacing_x, screw_holes_spacing_y=feet_screw_holes_spacing_y, screw_hole_depth=feet_screw_hole_depth, hinge_length=body_board_height/3, hinge_radius_in=hinge_radius + 0.5, hinge_radius_out=body_hinge_radius_out, hinge_shelf_width=feet_hinge_shelf_width, ventilation_holes_radius=feet_ventilation_holes_radius);
        }
    }

    color([0,0,1]) {
        translate([0, 0, body_board_depth/2]) {
            body(board_width=body_board_width, board_height=body_board_height, board_depth=body_board_depth, board_corner_radius=body_board_corner_radius, screw_hole_radius=body_screw_hole_radius, screw_hole_spacing=body_screw_hole_spacing, screw_hole_depth=body_screw_hole_depth, num_screw_holes=body_num_screw_holes, camera_screw_holes_radius=body_camera_screw_holes_radius, camera_screw_holes_spacing_x=body_camera_screw_holes_spacing_x, camera_screw_holes_spacing_y=body_camera_screw_holes_spacing_y, camera_holes_width=body_camera_holes_width, hinge_radius_in=hinge_radius + 0.5, hinge_radius_out=body_hinge_radius_out, hinge_slot_length=body_board_height / 3 + 1);
        }
    }

    color([0,1,0]) {
        translate([-50, 0, 0]) {
            hinge_screw(radius=hinge_radius, head_radius=hinge_head_radius, length=body_board_height + 1 + hinge_head_length, head_length=hinge_head_length);
        }
    }
}

// Raspicam

// Copyright (c) 2014, Jérémie Decock (jd.jdhp@gmail.com)

// BODY /////////////////////////////////////

module body(board_width, board_height, board_depth, board_corner_radius, screw_hole_radius, screw_hole_spacing, screw_hole_depth, num_screw_holes, camera_screw_holes_radius, camera_screw_holes_spacing_x, camera_screw_holes_spacing_y, camera_holes_width, hinge_radius_in, hinge_radius_out) {
    difference() {
        union() {
            difference() {
                translate([0, board_width/2, 0]){
                    rotate(a=[0,0,90]){
                        body_main_board(board_width, board_height, board_depth, board_corner_radius);
                    }
                }

                union() {
                    translate([0, board_width - num_screw_holes * screw_hole_spacing - 12.5, 0]){
                    //translate([0, 0, 0]){
                        body_screw_holes(screw_hole_radius, screw_hole_spacing, screw_hole_depth, num_screw_holes);
                    }

                    translate([-camera_screw_holes_spacing_x/2, 10, 0]){
                        body_camera_screw_holes(camera_screw_holes_radius, camera_screw_holes_spacing_x, camera_screw_holes_spacing_y, screw_hole_depth);
                    }

                    translate([0, camera_screw_holes_spacing_y + 10, 0]){
                        body_camera_holes(camera_holes_width, screw_hole_depth);
                    }
                }
            }
            translate([0, board_width, hinge_radius_out - board_depth/2]) {
                rotate(a=[0,90,0]) {
                    body_hinge(hinge_radius_in, hinge_radius_out, board_height);
                }
            }
        }
        translate([0, board_width, hinge_radius_out - board_depth/2]) {
            cube([board_height / 3 + 1, hinge_radius_out * 2 + 2, hinge_radius_out * 2 + 2], center=true);
        }
    }
}

module body_main_board(width, height, depth, radius) {
	$fn=50;
	//minkowski()
	//{
		cube([width, height, depth], center=true);
    //	cylinder(r=radius, h=depth, center=true);
    //}
}

module body_screw_holes(radius, spacing, depth, num) {
	$fn=50;

	for (i = [1:num]) {
		translate([0, i*spacing, 0]) {
			cylinder(r=radius, h=depth, center=true);
		}
	}
}

module body_camera_screw_holes(radius, spacing_x, spacing_y, depth) {
	$fn=50;

	for (i = [0:1]) {
        for (j = [0:1]) {
            translate([i*spacing_x, j*spacing_y, 0]) {
                cylinder(r=radius, h=depth, center=true);
            }
        }
	}
}

module body_camera_holes(width, depth) {
    cube([width, width, depth], center=true);
}

module body_hinge(radius_in, radius_out, length) {
    difference() {
        cylinder(r=radius_out, h=length, center=true, $fn=50);
        translate([0, 0, 0]) {
            cylinder(r=radius_in, h=length+10, center=true, $fn=50);
        }
    }
}

// HINGE SCREW //////////////////////////////

module hinge_screw(radius, head_radius, length, head_length) {
    cylinder(r=head_radius, h=head_length, $fn=8);
    translate([0, 0, 0]) {
        cylinder(r=radius, h=length, $fn=50);
    }
}

// FEET /////////////////////////////////////
module feet(width, height, depth, radius) {
	$fn=50;
	//minkowski()
	//{
		cube([width, height, depth]);
	//	cylinder(r=radius, h=depth, center=true);
	//}
}

color([1,0,0]) translate([0, -100, 0]) feet(98, 65, 3, 3);

color([0,0,1]) translate([0, 0, 0]) body(board_width=100, board_height=40, board_depth=3, board_corner_radius=3, screw_hole_radius=1.5, screw_hole_spacing=5, screw_hole_depth=10, num_screw_holes=9, camera_screw_holes_radius=1, camera_screw_holes_spacing_x=20, camera_screw_holes_spacing_y=12, camera_holes_width=8, hinge_radius_in=1.6, hinge_radius_out=4.6);

color([0,1,0]) translate([-50, 0, 0]) hinge_screw(radius=1.5, head_radius=3, length=65, head_length=5);


added features to anker hub

added features to anker hub

$fn = 64;

use <raspberrypi.scad>

// interference fit adjustment for 3D printer
iFitAdjust = .4;
iFitAdjust_d = .25;

// waveshare 5" knock off
displayScreenWidth = 119;
displayScreenHeight = 72;
displayScreenThickness = 3;
displayScreenYOffset = 3.5;
displayBoardWidth = 122;
displayBoardHeight = 79;
displayBoardThickness = 7;
displayDepth = 22;
displayScrewDiameter = 3;
module display() {
    // screen
    translate([-displayScreenWidth / 2, -displayScreenHeight / 2, 0])
        cube([displayScreenWidth, displayScreenHeight, displayScreenThickness], center=false);
    // board
    translate([-displayBoardWidth / 2, -displayBoardHeight / 2 + displayScreenYOffset, -displayBoardThickness])
        cube([displayBoardWidth, displayBoardHeight, displayBoardThickness], center=false);
}

displayMountThickness = displayBoardThickness;
displayMountScrewOffset = 2;
module display_mount() {
    // corner tabs
    for (i = [-1,1])
        for (j = [-1,1]) {
            translate([i * displayBoardWidth/2 + i * displayMountScrewOffset, j * displayBoardHeight/2 + j * displayMountScrewOffset, -displayMountThickness / 2])
                difference() {
                    cube([displayMountTabWidth, displayMountTabHeight, displayMountThickness], center=true);
                    translate([i * 2, j * 2, -displayBoardThickness])
                        cylinder(h=2 * displayBoardThickness + 2, d = displayScrewDiameter + iFitAdjust_d);
                }
        }
}

displayMountTabThickness = 3;
displayMountTabWidth = 15;
displayMountTabHeight = 20;
module display_mount_tabs() {
    // corner tabs
    for (i = [-1,1])
        for (j = [-1,1]) {
            translate([i * displayBoardWidth/2 + i * displayMountScrewOffset, j * displayBoardHeight/2 + j * displayMountScrewOffset, -displayBoardThickness - displayMountTabThickness / 2])
                difference() {
                    cube([displayMountTabWidth, displayMountTabHeight, displayMountTabThickness], center=true);
                    translate([i * 2, j * 2, -displayBoardThickness / 2])
                        cylinder(h=displayBoardThickness + 2, d = displayScrewDiameter + iFitAdjust_d * 2);
                }
        }
}

// encoders
encoderShaftDiameter = 7;
encoderShaftHeight = 18;
encoderWidth = 18;
encoderLength = 31;
encoderDepth = 8.2;
module encoder() {
    // encoder shaft
    cylinder(h = encoderShaftHeight, d = encoderShaftDiameter, center=false);
    // encoder base
    translate([-encoderWidth/2, -encoderLength/2, -encoderDepth/2])
        cube([encoderWidth, encoderLength, encoderDepth]);
}

// lid with screen and encoders
lidThickness = displayScreenThickness - .5;
lidScrewDiameter = 3.5;
lidScrewBoundaryOffset = 10;
module lid() {
  //display_mount_tabs();

  difference() {
    // face plate
    union() {
        translate([-(displayBoardWidth * 1.5 + encoderWidth * 1.1)/2, -(displayBoardHeight * 1.25 + encoderLength)/2, 0])
            cube([displayBoardWidth * 1.5 + encoderWidth * 1.1, displayBoardHeight * 1.25 +            encoderLength, lidThickness]);
        display_mount();
    }
    // screen cutout
    display();
    // encoder cutout
    for (i = [-1,1])
        for (j = [-1,1]) {
            translate([i * displayBoardWidth/2 + i * (encoderWidth * 1.1), j * displayBoardHeight/2, - encoderShaftHeight / 2 + 2])
                encoder();
        }
    // screw holes
    #for (i = [-1,1])
        for (j = [-1,1]) {
            translate([i * (displayBoardWidth * 1.5 + encoderWidth * 1.1 - lidScrewBoundaryOffset) / 2, j * (displayBoardHeight * 1.25 +            encoderLength - lidScrewBoundaryOffset) / 2, - encoderShaftHeight / 2 + 2])
                cylinder(h=20, d=lidScrewDiameter + iFitAdjust_d);
        }
  }
}

mcp23017BoardWidth = 40;
mcp23017BoardLength = 60;
mcp23017BoardHeight = 1.4;
mcp23017BoardScrewDiameter = 2;
mcp23017BoardScrewInset = 1.7;
header40PinWidth = 4.8;
header40PinLength = 51;
header40PinHeight = 11;
header40pinInsetL = 4.5;
header40pinInsetW = 4.5;
mcpToHifiOffset = 10.2;
hifiBoardWidth = 56;
hifiBoardLength = 65.3;
hifiBoardHeight = 1.4;
hifiBoardCutoutWidth = lidThickness * 3;
hifiBoardCutoutLength = 46;
hifiBoardCutoutHeight = 14.5;
hifiBoardScrewDiameter = 4;
hifiBoardScrewInset = 3.7;
hifiMcpWidth = mcp23017BoardWidth - mcpToHifiOffset + hifiBoardWidth;
module hifi_mcp23017_boards() {
    // mcp23017 protoboard
    color("limegreen")
    difference() {
        // board
        cube([mcp23017BoardWidth, mcp23017BoardLength, mcp23017BoardHeight]);
        // screw holes
        translate([mcp23017BoardScrewInset, mcp23017BoardScrewInset, -.1])
            cylinder(d=mcp23017BoardScrewDiameter, h=mcp23017BoardHeight + .2);
        translate([mcp23017BoardWidth - mcp23017BoardScrewInset, mcp23017BoardScrewInset, -.1])
            cylinder(d=mcp23017BoardScrewDiameter, h=mcp23017BoardHeight + .2);
        translate([mcp23017BoardScrewInset, mcp23017BoardLength - mcp23017BoardScrewInset, -.1])
            cylinder(d=mcp23017BoardScrewDiameter, h=mcp23017BoardHeight + .2);
        translate([mcp23017BoardWidth - mcp23017BoardScrewInset, mcp23017BoardLength - mcp23017BoardScrewInset, -.1])
            cylinder(d=mcp23017BoardScrewDiameter, h=mcp23017BoardHeight + .2);
    }
    // 40 pin header
    color("black")
    translate([header40pinInsetL, header40pinInsetW, mcp23017BoardHeight])
        cube([header40PinWidth, header40PinLength, header40PinHeight]);
    // sainsmart pifi dac board
    color("darkgrey")
    translate([-hifiBoardWidth + mcpToHifiOffset, 0, mcp23017BoardHeight + header40PinHeight])
    difference() {
        // board
        cube([hifiBoardWidth, hifiBoardLength, hifiBoardHeight]);
        // screw holes
        translate([hifiBoardScrewInset, hifiBoardScrewInset, -.1])
            cylinder(d=hifiBoardScrewDiameter, h=hifiBoardHeight + .2);
        translate([hifiBoardWidth - hifiBoardScrewInset, hifiBoardScrewInset, -.1])
            cylinder(d=hifiBoardScrewDiameter, h=hifiBoardHeight + .2);
        translate([hifiBoardScrewInset, hifiBoardLength - hifiBoardScrewInset, -.1])
            cylinder(d=hifiBoardScrewDiameter, h=hifiBoardHeight + .2);
        translate([hifiBoardWidth - hifiBoardScrewInset, hifiBoardLength - hifiBoardScrewInset, -.1])
            cylinder(d=hifiBoardScrewDiameter, h=hifiBoardHeight + .2);
    }
    color("darkgrey")
    translate([-hifiBoardWidth + mcpToHifiOffset - hifiBoardCutoutWidth / 2, hifiBoardLength / 2 - hifiBoardCutoutLength / 2, mcp23017BoardHeight + header40PinHeight])
        cube([hifiBoardCutoutWidth, hifiBoardCutoutLength, hifiBoardCutoutHeight]);
}

anker7PortHubHeight = 44.5;
anker7PortHubLength = 110;
anker7PortHubWidth = 23;
anker7PortHubPowerDiameter = 10.5;
anker7PortHubPowerHeight = 31;
anker7PortHubPowerLength = 5;
anker7PortHubPowerWidth = 10.4;
anker7PortHubUSBH = 9;
anker7PortHubUSBW = 11;
anker7PortHubUSBHeight = 14.5;
anker7PortHubUSBLength = 5;
anker7PortHubUSBWidth = 9;
module anker_7port_usb_hub() {
    difference() {
        color("black")
        translate([0, 0, boxThickness])
            cube([anker7PortHubWidth, anker7PortHubLength, anker7PortHubHeight]);
        translate([anker7PortHubPowerWidth, anker7PortHubPowerLength, anker7PortHubPowerHeight])
            rotate([90, 0, 0])
                cylinder(h=20, d=anker7PortHubPowerDiameter);
        translate([anker7PortHubUSBWidth - anker7PortHubUSBW / 2, anker7PortHubUSBLength, anker7PortHubUSBHeight - anker7PortHubUSBH/2])
            rotate([90, 0, 0])
                cube([anker7PortHubUSBW, anker7PortHubUSBH, 20]);
    }
}

// box with pi mounts and holes
rPi3BottomSpacer = 4;
rPi3Length = 85;
rpi3Width = 56;
boxHeight = 80;
boxThickness = lidThickness;
hifiMcpSpacer = 4;
module box() {

    // bottom
    translate([-(displayBoardWidth * 1.5 + encoderWidth * 1.1)/2, -(displayBoardHeight * 1.25 + encoderLength)/2, 0])
            cube([displayBoardWidth * 1.5 + encoderWidth * 1.1, displayBoardHeight * 1.25 +            encoderLength, boxThickness]);
    // pi mount holes
    translate([(displayBoardWidth * 1.5 + encoderWidth * 1.1)/2 - rPi3Length / 2, (displayBoardHeight * 1.25 + encoderLength)/2 - 29, boxThickness + rPi3BottomSpacer])
        pi3();
    // sides
    for (i = [-1, 1])
        translate([-(displayBoardWidth * 1.5 + encoderWidth * 1.1)/2, -i * (displayBoardHeight * 1.25 + encoderLength)/2 - (i == -1 ? boxThickness : 0), 0])
            cube([displayBoardWidth * 1.5 + encoderWidth * 1.1, boxThickness, boxHeight]);
    for (i = [-1, 1])
        translate([-i * (displayBoardWidth * 1.5 + encoderWidth * 1.1)/2 - (i == -1 ? boxThickness : 0), -(displayBoardHeight * 1.25 + encoderLength)/2, 0])
            cube([boxThickness, displayBoardHeight * 1.25 + encoderLength, boxHeight]);
    // pi usb / ethernet cutou

    // hifi audio out board with mcp23017 board
    rotate([0, 0, 90])
    translate([-(displayBoardWidth * 1.5 + encoderWidth * 1.1)/2 + hifiMcpWidth, 0, boxThickness + hifiMcpSpacer])
        hifi_mcp23017_boards();
    // anker usb power hub
    anker_7port_usb_hub();
 //   translate([0,0,boxHeight + 2])
 //       lid();
}

//display();
//encoder();
//lid();
//display_mount_tabs();
box();

$fn = 64;

use <raspberrypi.scad>

// interference fit adjustment for 3D printer
iFitAdjust = .4;
iFitAdjust_d = .25;

// waveshare 5" knock off
displayScreenWidth = 119;
displayScreenHeight = 72;
displayScreenThickness = 3;
displayScreenYOffset = 3.5;
displayBoardWidth = 122;
displayBoardHeight = 79;
displayBoardThickness = 7;
displayDepth = 22;
displayScrewDiameter = 3;
module display() {
    // screen
    translate([-displayScreenWidth / 2, -displayScreenHeight / 2, 0])
        cube([displayScreenWidth, displayScreenHeight, displayScreenThickness], center=false);
    // board
    translate([-displayBoardWidth / 2, -displayBoardHeight / 2 + displayScreenYOffset, -displayBoardThickness])
        cube([displayBoardWidth, displayBoardHeight, displayBoardThickness], center=false);
}

displayMountThickness = displayBoardThickness;
displayMountScrewOffset = 2;
module display_mount() {
    // corner tabs
    for (i = [-1,1])
        for (j = [-1,1]) {
            translate([i * displayBoardWidth/2 + i * displayMountScrewOffset, j * displayBoardHeight/2 + j * displayMountScrewOffset, -displayMountThickness / 2])
                difference() {
                    cube([displayMountTabWidth, displayMountTabHeight, displayMountThickness], center=true);
                    translate([i * 2, j * 2, -displayBoardThickness])
                        cylinder(h=2 * displayBoardThickness + 2, d = displayScrewDiameter + iFitAdjust_d);
                }
        }
}

displayMountTabThickness = 3;
displayMountTabWidth = 15;
displayMountTabHeight = 20;
module display_mount_tabs() {
    // corner tabs
    for (i = [-1,1])
        for (j = [-1,1]) {
            translate([i * displayBoardWidth/2 + i * displayMountScrewOffset, j * displayBoardHeight/2 + j * displayMountScrewOffset, -displayBoardThickness - displayMountTabThickness / 2])
                difference() {
                    cube([displayMountTabWidth, displayMountTabHeight, displayMountTabThickness], center=true);
                    translate([i * 2, j * 2, -displayBoardThickness / 2])
                        cylinder(h=displayBoardThickness + 2, d = displayScrewDiameter + iFitAdjust_d * 2);
                }
        }
}

// encoders
encoderShaftDiameter = 7;
encoderShaftHeight = 18;
encoderWidth = 18;
encoderLength = 31;
encoderDepth = 8.2;
module encoder() {
    // encoder shaft
    cylinder(h = encoderShaftHeight, d = encoderShaftDiameter, center=false);
    // encoder base
    translate([-encoderWidth/2, -encoderLength/2, -encoderDepth/2])
        cube([encoderWidth, encoderLength, encoderDepth]);
}

// lid with screen and encoders
lidThickness = displayScreenThickness - .5;
lidScrewDiameter = 3.5;
lidScrewBoundaryOffset = 10;
module lid() {
  //display_mount_tabs();

  difference() {
    // face plate
    union() {
        translate([-(displayBoardWidth * 1.5 + encoderWidth * 1.1)/2, -(displayBoardHeight * 1.25 + encoderLength)/2, 0])
            cube([displayBoardWidth * 1.5 + encoderWidth * 1.1, displayBoardHeight * 1.25 +            encoderLength, lidThickness]);
        display_mount();
    }
    // screen cutout
    display();
    // encoder cutout
    for (i = [-1,1])
        for (j = [-1,1]) {
            translate([i * displayBoardWidth/2 + i * (encoderWidth * 1.1), j * displayBoardHeight/2, - encoderShaftHeight / 2 + 2])
                encoder();
        }
    // screw holes
    #for (i = [-1,1])
        for (j = [-1,1]) {
            translate([i * (displayBoardWidth * 1.5 + encoderWidth * 1.1 - lidScrewBoundaryOffset) / 2, j * (displayBoardHeight * 1.25 +            encoderLength - lidScrewBoundaryOffset) / 2, - encoderShaftHeight / 2 + 2])
                cylinder(h=20, d=lidScrewDiameter + iFitAdjust_d);
        }
  }
}

mcp23017BoardWidth = 40;
mcp23017BoardLength = 60;
mcp23017BoardHeight = 1.4;
mcp23017BoardScrewDiameter = 2;
mcp23017BoardScrewInset = 1.7;
header40PinWidth = 4.8;
header40PinLength = 51;
header40PinHeight = 11;
header40pinInsetL = 4.5;
header40pinInsetW = 4.5;
mcpToHifiOffset = 10.2;
hifiBoardWidth = 56;
hifiBoardLength = 65.3;
hifiBoardHeight = 1.4;
hifiBoardCutoutWidth = lidThickness * 3;
hifiBoardCutoutLength = 46;
hifiBoardCutoutHeight = 14.5;
hifiBoardScrewDiameter = 4;
hifiBoardScrewInset = 3.7;
hifiMcpWidth = mcp23017BoardWidth - mcpToHifiOffset + hifiBoardWidth;
module hifi_mcp23017_boards() {
    // mcp23017 protoboard
    color("limegreen")
    difference() {
        // board
        cube([mcp23017BoardWidth, mcp23017BoardLength, mcp23017BoardHeight]);
        // screw holes
        translate([mcp23017BoardScrewInset, mcp23017BoardScrewInset, -.1])
            cylinder(d=mcp23017BoardScrewDiameter, h=mcp23017BoardHeight + .2);
        translate([mcp23017BoardWidth - mcp23017BoardScrewInset, mcp23017BoardScrewInset, -.1])
            cylinder(d=mcp23017BoardScrewDiameter, h=mcp23017BoardHeight + .2);
        translate([mcp23017BoardScrewInset, mcp23017BoardLength - mcp23017BoardScrewInset, -.1])
            cylinder(d=mcp23017BoardScrewDiameter, h=mcp23017BoardHeight + .2);
        translate([mcp23017BoardWidth - mcp23017BoardScrewInset, mcp23017BoardLength - mcp23017BoardScrewInset, -.1])
            cylinder(d=mcp23017BoardScrewDiameter, h=mcp23017BoardHeight + .2);
    }
    // 40 pin header
    color("black")
    translate([header40pinInsetL, header40pinInsetW, mcp23017BoardHeight])
        cube([header40PinWidth, header40PinLength, header40PinHeight]);
    // sainsmart pifi dac board
    color("darkgrey")
    translate([-hifiBoardWidth + mcpToHifiOffset, 0, mcp23017BoardHeight + header40PinHeight])
    difference() {
        // board
        cube([hifiBoardWidth, hifiBoardLength, hifiBoardHeight]);
        // screw holes
        translate([hifiBoardScrewInset, hifiBoardScrewInset, -.1])
            cylinder(d=hifiBoardScrewDiameter, h=hifiBoardHeight + .2);
        translate([hifiBoardWidth - hifiBoardScrewInset, hifiBoardScrewInset, -.1])
            cylinder(d=hifiBoardScrewDiameter, h=hifiBoardHeight + .2);
        translate([hifiBoardScrewInset, hifiBoardLength - hifiBoardScrewInset, -.1])
            cylinder(d=hifiBoardScrewDiameter, h=hifiBoardHeight + .2);
        translate([hifiBoardWidth - hifiBoardScrewInset, hifiBoardLength - hifiBoardScrewInset, -.1])
            cylinder(d=hifiBoardScrewDiameter, h=hifiBoardHeight + .2);
    }
    color("darkgrey")
    translate([-hifiBoardWidth + mcpToHifiOffset - hifiBoardCutoutWidth / 2, hifiBoardLength / 2 - hifiBoardCutoutLength / 2, mcp23017BoardHeight + header40PinHeight])
        cube([hifiBoardCutoutWidth, hifiBoardCutoutLength, hifiBoardCutoutHeight]);
}

anker7PortHubHeight = 44.5;
anker7PortHubLength = 110;
anker7PortHubWidth = 23;
module anker_7port_usb_hub() {
    color("black")
    translate([0, 0, boxThickness])
        cube([anker7PortHubWidth, anker7PortHubLength, anker7PortHubHeight]);
}

// box with pi mounts and holes
rPi3BottomSpacer = 4;
rPi3Length = 85;
rpi3Width = 56;
boxHeight = 80;
boxThickness = lidThickness;
hifiMcpSpacer = 4;
module box() {

    // bottom
    translate([-(displayBoardWidth * 1.5 + encoderWidth * 1.1)/2, -(displayBoardHeight * 1.25 + encoderLength)/2, 0])
            cube([displayBoardWidth * 1.5 + encoderWidth * 1.1, displayBoardHeight * 1.25 +            encoderLength, boxThickness]);
    // pi mount holes
    translate([(displayBoardWidth * 1.5 + encoderWidth * 1.1)/2 - rPi3Length / 2, (displayBoardHeight * 1.25 + encoderLength)/2 - 29, boxThickness + rPi3BottomSpacer])
        pi3();
    // sides
    for (i = [-1, 1])
        translate([-(displayBoardWidth * 1.5 + encoderWidth * 1.1)/2, -i * (displayBoardHeight * 1.25 + encoderLength)/2 - (i == -1 ? boxThickness : 0), 0])
            cube([displayBoardWidth * 1.5 + encoderWidth * 1.1, boxThickness, boxHeight]);
    for (i = [-1, 1])
        translate([-i * (displayBoardWidth * 1.5 + encoderWidth * 1.1)/2 - (i == -1 ? boxThickness : 0), -(displayBoardHeight * 1.25 + encoderLength)/2, 0])
            cube([boxThickness, displayBoardHeight * 1.25 + encoderLength, boxHeight]);
    // pi usb / ethernet cutou

    // hifi audio out board with mcp23017 board
    rotate([0, 0, 90])
    translate([-(displayBoardWidth * 1.5 + encoderWidth * 1.1)/2 + hifiMcpWidth, 0, boxThickness + hifiMcpSpacer])
        hifi_mcp23017_boards();
    // anker usb power hub
    anker_7port_usb_hub();
 //   translate([0,0,boxHeight + 2])
 //       lid();
}

//display();
//encoder();
//lid();
//display_mount_tabs();
box();