@@ -0,0 +1,14 @@ | |||||
// animation | |||||
function get_anim_keys() = [ | |||||
0, // initial | |||||
0.1, // resting | |||||
0.3, // holodisk inserted | |||||
0.4, // laser raised | |||||
0.5, // start playing | |||||
0.7, // stop playing | |||||
0.8, // laser lowered, holodisk removing | |||||
1 // final | |||||
]; | |||||
function anim(key_from, key_to, KEYS=get_anim_keys()) | |||||
= max(0, min(($t - KEYS[key_from]) / (KEYS[key_to] - KEYS[key_from]), 1)); |
@@ -6,48 +6,10 @@ | |||||
* Related: http://cedmagic.com/history/holotape.html | * Related: http://cedmagic.com/history/holotape.html | ||||
*/ | */ | ||||
width=55; | |||||
depth=100; | |||||
height=16; | |||||
wall=3; | |||||
plate=3; | |||||
top_rim=2; | |||||
bolt_headtype="hex"; | |||||
front_body_depth=12; | |||||
front_body_bolt_offset=8; | |||||
back_bumpers_radius=5; | |||||
back_bumpers_bolt_size=3; | |||||
tape_height=5; | |||||
tape_thickness=0.2; | |||||
spool_tape_tolerance=1; | |||||
spool_inner_height=tape_height+spool_tape_tolerance; | |||||
spool_inner_radius=4; | |||||
spool_outer_radius=18; | |||||
spool_plate_height=2; | |||||
spool_plate_holes=3; | |||||
spool_plate_hole_angle=360/spool_plate_holes * 0.5; | |||||
spool_plate_hole_inner_rim=1; | |||||
spool_plate_hole_outer_rim=4; | |||||
spool_slit_depth=0.8; | |||||
spool1_depth=depth*0.77; | |||||
spool2_depth=depth*0.40; | |||||
spool3_depth=(spool1_depth+spool2_depth)/2; | |||||
spool4_depth=depth*0.16; | |||||
main_spools_x=width * 0.45; | |||||
aux_spools_right_x=main_spools_x + spool_outer_radius + 1; | |||||
aux_spools_left_x=main_spools_x - 13; | |||||
middle_spool_in_r=2; | |||||
middle_spool_out_r=7; | |||||
aux_spool_plate_hole_inner_rim=2; | |||||
aux_spool_plate_hole_outer_rim=2; | |||||
spindle_diam=2; | |||||
spindle_diam_tolerance=0.2; | |||||
tape_z=plate+spool_plate_height; | |||||
// dependency: https://github.com/revarbat/BOSL | // dependency: https://github.com/revarbat/BOSL | ||||
use <BOSL/transforms.scad> | |||||
use <BOSL/metric_screws.scad> | |||||
use <BOSL/masks.scad> | |||||
use <holodisk_spec.scad> | |||||
use <anim.scad> | |||||
include <holodisk.scad> | include <holodisk.scad> | ||||
include <reader.scad> | include <reader.scad> |
@@ -1,11 +1,55 @@ | |||||
// dependency: https://github.com/revarbat/BOSL | // dependency: https://github.com/revarbat/BOSL | ||||
use <BOSL/transforms.scad> | use <BOSL/transforms.scad> | ||||
use <BOSL/metric_screws.scad> | |||||
//use <BOSL/metric_screws.scad> | |||||
use <BOSL/masks.scad> | use <BOSL/masks.scad> | ||||
use <holodisk_spec.scad> | |||||
use <anim.scad> | |||||
include <tape.scad> | include <tape.scad> | ||||
module frame() { | |||||
disk_size = get_holodisk_size(); | |||||
holodisk_size = get_holodisk_size(); | |||||
wall=3; | |||||
plate=3; | |||||
top_rim=2; | |||||
bolt_headtype="hex"; | |||||
front_body_depth=12; | |||||
front_body_bolt_offset=8; | |||||
back_bumpers_radius=5; | |||||
back_bumpers_bolt_size=3; | |||||
tape_height=5; | |||||
tape_thickness=0.2; | |||||
spool_tape_tolerance=1; | |||||
spool_inner_height=tape_height+spool_tape_tolerance; | |||||
spool_inner_radius=4; | |||||
spool_outer_radius=18; | |||||
spool_plate_height=2; | |||||
spool_plate_holes=3; | |||||
spool_plate_hole_angle=360/spool_plate_holes * 0.5; | |||||
spool_plate_hole_inner_rim=1; | |||||
spool_plate_hole_outer_rim=4; | |||||
spool_slit_depth=0.8; | |||||
spool1_depth=disk_size.y*0.77; | |||||
spool2_depth=disk_size.y*0.40; | |||||
spool3_depth=(spool1_depth+spool2_depth)/2; | |||||
spool4_depth=disk_size.y*0.16; | |||||
main_spools_x=disk_size.x*0.45; | |||||
aux_spools_right_x=main_spools_x + spool_outer_radius + 1; | |||||
aux_spools_left_x=main_spools_x - 13; | |||||
middle_spool_in_r=2; | |||||
middle_spool_out_r=7; | |||||
aux_spool_plate_hole_inner_rim=2; | |||||
aux_spool_plate_hole_outer_rim=2; | |||||
spindle_diam=2; | |||||
spindle_diam_tolerance=0.2; | |||||
tape_z=plate+spool_plate_height; | |||||
module frame(size) { | |||||
width=size.x; | |||||
depth=size.y; | |||||
height=size.z; | |||||
tr=top_rim; | tr=top_rim; | ||||
tc=tr*1.5; | tc=tr*1.5; | ||||
fbd=front_body_depth; | fbd=front_body_depth; | ||||
@@ -76,21 +120,64 @@ module frame() { | |||||
} | } | ||||
} | } | ||||
module slides() { | |||||
slide_size = get_holodisk_slide_size(); | |||||
slide_pos = get_holodisk_slide_pos(); | |||||
slide_plate_size = [0.1, slide_size.y, slide_size.z]; | |||||
sliding_size = get_holodisk_slide_sliding_size(); | |||||
sliding_pos = get_holodisk_slide_sliding_pos(); | |||||
module slide() { | |||||
hull() { | |||||
translate(sliding_pos) cube(sliding_size); | |||||
translate(slide_pos) cube(slide_plate_size); | |||||
} | |||||
} | |||||
module slider() { | |||||
slider_size = get_holodisk_slide_slider_size(); | |||||
slider_pos = get_holodisk_slide_slider_pos(); | |||||
slider_plate_size = [0.1, slider_size.y, slider_size.z]; | |||||
slider_top_size = [slider_size.x, slider_size.y, sliding_size.z]; | |||||
hull() { | |||||
up((slider_size.z-sliding_size.z)/2) translate(slider_pos) cube(slider_top_size); | |||||
translate(slider_pos) cube(slider_plate_size); | |||||
} | |||||
} | |||||
right(get_holodisk_size().x) { | |||||
slide(); | |||||
slider(); | |||||
} | |||||
scale([-1,1,1]) { | |||||
slide(); | |||||
slider(); | |||||
} | |||||
} | |||||
module bottom_cover() { | module bottom_cover() { | ||||
linear_extrude(height=plate) { | |||||
back_bumpers(); | |||||
square([width, depth]); | |||||
difference() { | |||||
linear_extrude(height=plate) { | |||||
back_bumpers(); | |||||
square([width, depth]); | |||||
} | |||||
down(0.1) translate(get_holodisk_laser_cutout_pos()) cube(get_holodisk_laser_cutout_size()); | |||||
} | } | ||||
} | } | ||||
color("SaddleBrown") top_cover(); | color("SaddleBrown") top_cover(); | ||||
color("grey") walls(); | color("grey") walls(); | ||||
color("Silver") slides(); | |||||
color("SaddleBrown") bottom_cover(); | color("SaddleBrown") bottom_cover(); | ||||
color("silver") back_bolts(); | |||||
color("silver") front_bolts(); | |||||
//color("silver") back_bolts(); | |||||
//color("silver") front_bolts(); | |||||
} | } | ||||
module mechanism() { | |||||
module mechanism(size) { | |||||
width=size.x; | |||||
depth=size.y; | |||||
height=size.z; | |||||
module spool(r_in, r_out, in_rim, out_rim) { | module spool(r_in, r_out, in_rim, out_rim) { | ||||
module spindle(d, h) { | module spindle(d, h) { | ||||
color("Sienna") cylinder(h=h, d=d); | color("Sienna") cylinder(h=h, d=d); | ||||
@@ -180,9 +267,12 @@ module mechanism() { | |||||
tapes(); | tapes(); | ||||
} | } | ||||
module holodisk() { | |||||
#frame(); | |||||
mechanism(); | |||||
module holodisk(size) { | |||||
frame(size); | |||||
mechanism(size); | |||||
} | } | ||||
holodisk(); | |||||
retraction=holodisk_size.y+10; | |||||
back((1-anim(1, 2)) * retraction) // anim insert | |||||
back((anim(len(get_anim_keys())-2, len(get_anim_keys())-1)) * retraction) // anim remove | |||||
holodisk(holodisk_size); |
@@ -0,0 +1,61 @@ | |||||
/* | |||||
* Technical Specification for Wattz Electronics Holodisk (AKA Holotape or THT) | |||||
* | |||||
*/ | |||||
// -- core dimensions -- | |||||
function get_holodisk_size() = [55, 100, 16]; | |||||
// -- tape -- | |||||
function get_holodisk_tape_height() = 5; | |||||
// -- slide -- | |||||
spz = 8; | |||||
function get_holodisk_slide_size() = [2, 35, get_holodisk_size().z - spz]; | |||||
function get_holodisk_slide_pos() = [0, 15, spz/2]; | |||||
sy = 2; | |||||
sz = 4; | |||||
function get_holodisk_slide_sliding_size() = [get_holodisk_slide_size().x, get_holodisk_slide_size().y - sy, get_holodisk_slide_size().z - sz]; | |||||
function get_holodisk_slide_sliding_pos() = [get_holodisk_slide_pos().x, get_holodisk_slide_pos().y + sy/2, get_holodisk_slide_pos().z + sz/2]; | |||||
srx = 2; | |||||
srz = 2; | |||||
function get_holodisk_slide_slider_size() = [get_holodisk_slide_size().x + srx, 15, get_holodisk_slide_size().z + srz]; | |||||
function get_holodisk_slide_slider_pos() = [get_holodisk_slide_sliding_pos().x, get_holodisk_slide_sliding_pos().y, get_holodisk_slide_sliding_pos().z - get_holodisk_slide_slider_size().z/2 + srz]; | |||||
// -- laser -- | |||||
function get_holodisk_laser_cutout_size() = [15, 9, 20]; | |||||
function get_holodisk_laser_cutout_pos() = [ | |||||
get_holodisk_size().x/2 - get_holodisk_laser_cutout_size().x/2, | |||||
12, | |||||
0]; | |||||
function get_holodisk_laser_cutout_pos_center() = [ | |||||
get_holodisk_laser_cutout_pos().x + get_holodisk_laser_cutout_size().x/2, | |||||
get_holodisk_laser_cutout_pos().y + get_holodisk_laser_cutout_size().y/2, | |||||
get_holodisk_laser_cutout_pos().z + get_holodisk_laser_cutout_size().z/2]; | |||||
// -- laser-window -- | |||||
function get_holodisk_laserwindow_pos_center() = [ | |||||
get_holodisk_laser_cutout_pos_center().x, | |||||
0, | |||||
6.5 | |||||
]; | |||||
function get_holodisk_laserwindow_size() = [ | |||||
get_holodisk_laser_cutout_size().x, | |||||
30, | |||||
get_holodisk_tape_height() + 2 | |||||
]; | |||||
// -- END -- |
@@ -1,52 +1,53 @@ | |||||
// dependency: https://github.com/revarbat/BOSL | // dependency: https://github.com/revarbat/BOSL | ||||
use <BOSL/transforms.scad> | use <BOSL/transforms.scad> | ||||
use <holodisk_spec.scad> | |||||
include <anim.scad> | |||||
// outside config | // outside config | ||||
width=60; | |||||
height=15; | |||||
depth=100; | |||||
tape_height=5; | tape_height=5; | ||||
tape_z=4; | tape_z=4; | ||||
// local config | |||||
frame=5; | |||||
head_frame=2; | |||||
head_size=[14, 10, tape_height+head_frame*2]; | |||||
head_pos=[width/2, -frame+2, tape_z-head_frame]; | |||||
laser_size=[10, 2, tape_height]; | |||||
laser_pos=[head_pos.x, head_pos.y + 10 + head_size.y, tape_z]; | |||||
laser_tower_size=[laser_size.x+2, laser_size.y+1, 15]; | |||||
module reader() { | |||||
module reader(disk_size) { | |||||
width=disk_size.x; | |||||
depth=disk_size.y; | |||||
height=disk_size.z; | |||||
laser_cutout_size = get_holodisk_laser_cutout_size(); | |||||
laser_cutout_pos = get_holodisk_laser_cutout_pos_center(); | |||||
frame=5; | |||||
head_frame=2; | |||||
head_size=[14, 10, tape_height+head_frame*2]; | |||||
head_pos=[laser_cutout_pos.x, -frame+2, tape_z-head_frame]; | |||||
laser_size=[10, 2, tape_height]; | |||||
laser_offset=3; | |||||
laser_pos=[laser_cutout_pos.x, laser_cutout_pos.y + laser_offset, tape_z]; | |||||
laser_tower_size=[laser_cutout_size.x - 1, laser_cutout_size.y - 1 - laser_offset, 15]; | |||||
module laser(corner=0.1) { | module laser(corner=0.1) { | ||||
up(laser_size.z/2) | up(laser_size.z/2) | ||||
up(corner) | up(corner) | ||||
color("Red") | color("Red") | ||||
minkowski() { | |||||
s=[laser_size.x, laser_size.y, laser_size.z-corner*2]; | |||||
cube(s, center=true); | |||||
sphere(corner); | |||||
} | |||||
fwd(laser_cutout_size.y/3) cube(laser_size, center=true); | |||||
} | } | ||||
module laser_tower(corner=2) { | |||||
module laser_tower(corner=1) { | |||||
color("DarkSlateBlue") | color("DarkSlateBlue") | ||||
back(laser_tower_size.y-laser_size.y) | |||||
difference() { | difference() { | ||||
minkowski() { | |||||
s=[laser_tower_size.x, laser_tower_size.y, laser_tower_size.z-corner*2]; | |||||
up(laser_size.z/2) | |||||
cube(s, center=true); | |||||
sphere(corner); | |||||
} | |||||
fwd(laser_tower_size.y) scale(1.05) laser(); | |||||
up(laser_size.z/2) | |||||
fwd(laser_offset/2) scale(0.99) cube(laser_tower_size, center=true); | |||||
fwd(laser_size.y/3) scale(1.1) laser(); | |||||
} | } | ||||
} | } | ||||
module head_space() { | module head_space() { | ||||
stube=[head_size.x-head_frame*2, head_size.y+head_frame*3, head_size.z-head_frame*2]; | |||||
/*stube=[head_size.x-head_frame*2, head_size.y+head_frame*3, head_size.z-head_frame*2]; | |||||
up(head_size.z/4 + head_frame) | up(head_size.z/4 + head_frame) | ||||
cube(stube, center=true); | |||||
cube(stube, center=true);*/ | |||||
translate(get_holodisk_laserwindow_pos_center()) cube(get_holodisk_laserwindow_size(), center=true); | |||||
} | } | ||||
module head(corner=0.5) { | module head(corner=0.5) { | ||||
@@ -57,14 +58,19 @@ module reader() { | |||||
s=[head_size[0], head_size[1] + frame, head_size[2]-corner*2]; | s=[head_size[0], head_size[1] + frame, head_size[2]-corner*2]; | ||||
difference() { | difference() { | ||||
up(head_size.z/2) cube(s, center=true); | |||||
translate(head_pos) up(head_size.z/2) cube(s, center=true); | |||||
head_space(); | head_space(); | ||||
} | } | ||||
sphere(corner); | sphere(corner); | ||||
} | } | ||||
} | } | ||||
translate(head_pos) head(); | |||||
head(); | |||||
retraction=laser_tower_size.z; | |||||
down(retraction) | |||||
up(anim(2, 3)*retraction) | |||||
down(anim(5, 6)*retraction) | |||||
translate(laser_pos) { | translate(laser_pos) { | ||||
laser(); | laser(); | ||||
laser_tower(); | laser_tower(); | ||||
@@ -73,10 +79,12 @@ module reader() { | |||||
color("DarkSlateBlue") { | color("DarkSlateBlue") { | ||||
difference() { | difference() { | ||||
fwd(frame) cube([width, frame, height]); | fwd(frame) cube([width, frame, height]); | ||||
translate(head_pos) head_space(); | |||||
head_space(); | |||||
} | } | ||||
fwd(frame) down(frame) cube([width, depth + frame, frame]); | fwd(frame) down(frame) cube([width, depth + frame, frame]); | ||||
} | } | ||||
} | } | ||||
reader(); | |||||
holodisk_size = is_undef(disk_size) ? [50, 100, 20] : disk_size; | |||||
reader(holodisk_size); |