--- /dev/null
+wall_thickness = 1.5;
+
+pcb_length = 53;
+pcb_width = 23;
+pcb_thickness = 1.6;
+pcb_depth = 2;
+pcb_rail_width = 1.5;
+pcb_prog_stick_out = 5; // how much does the programming connector stick out
+
+box_height = 12; // FIXME
+box_depth = pcb_thickness + pcb_depth;
+
+lid_rail_width = 1;
+lid_rail_height = 2;
+
+usb_width = 10;
+usb_height = 4;
+
+rs485_width = 16.5;
+rs485_height = 8;
+
+over = 0.1;
+clearance = 0.2;
+
+module bottom() {
+ difference() {
+ // Exterior
+ translate([-wall_thickness, -wall_thickness, -box_depth-wall_thickness])
+ cube([2*wall_thickness + pcb_length + pcb_prog_stick_out, 2*wall_thickness + pcb_width, wall_thickness + box_depth + box_height]);
+
+ // Interior
+ cube([pcb_length + pcb_prog_stick_out, pcb_width, box_height+1]);
+
+ // USB connector hole
+ translate([-wall_thickness-over, (pcb_width-usb_width)/2, -pcb_thickness])
+ cube([wall_thickness+2*over, usb_width, pcb_thickness+box_height+over]);
+
+ // PCB
+ translate([0, 0, -pcb_thickness])
+ cube([pcb_length, pcb_width, pcb_thickness+over]);
+
+ // Sub-PCB hole
+ translate([0, pcb_rail_width, -pcb_thickness-pcb_depth])
+ cube([pcb_length, pcb_width - 2*pcb_rail_width, pcb_thickness + pcb_depth + over]);
+ }
+}
+
+module top() {
+ difference() {
+ union() {
+ // Lid
+ translate([-wall_thickness, -wall_thickness, 0])
+ cube([pcb_length + pcb_prog_stick_out + 2*wall_thickness, pcb_width + 2*wall_thickness, wall_thickness]);
+
+ // Rails
+ translate([0, 0, -lid_rail_height])
+ cube([pcb_length + pcb_prog_stick_out, lid_rail_width, lid_rail_height + over]);
+ translate([0, pcb_width - lid_rail_width, -lid_rail_height])
+ cube([pcb_length + pcb_prog_stick_out, lid_rail_width, lid_rail_height + over]);
+
+ // USB connector roof
+ translate([-wall_thickness, (pcb_width - usb_width)/2 + clearance, usb_height - box_height + clearance])
+ cube([wall_thickness, usb_width - 2*clearance, box_height - usb_height - clearance + over]);
+
+ // RS485 connector roof
+ //translate([-wall_thickness, (pcb_width - rs485_width)/2 + clearance, rs485_height - box_height + clearance])
+ // cube([wall_thickness, rs485_width - 2*clearance, box_height - rs485_height - clearance + over]);
+ }
+ }
+}
+
+//bottom();
+color([1, 0, 0]) translate([0, 0, box_height]) top();